1*00b67f09SDavid van Moolenbroek /* $NetBSD: check-tool.c,v 1.7 2014/12/10 04:37:51 christos Exp $ */
2*00b67f09SDavid van Moolenbroek
3*00b67f09SDavid van Moolenbroek /*
4*00b67f09SDavid van Moolenbroek * Copyright (C) 2004-2014 Internet Systems Consortium, Inc. ("ISC")
5*00b67f09SDavid van Moolenbroek * Copyright (C) 2000-2002 Internet Software Consortium.
6*00b67f09SDavid van Moolenbroek *
7*00b67f09SDavid van Moolenbroek * Permission to use, copy, modify, and/or distribute this software for any
8*00b67f09SDavid van Moolenbroek * purpose with or without fee is hereby granted, provided that the above
9*00b67f09SDavid van Moolenbroek * copyright notice and this permission notice appear in all copies.
10*00b67f09SDavid van Moolenbroek *
11*00b67f09SDavid van Moolenbroek * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
12*00b67f09SDavid van Moolenbroek * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
13*00b67f09SDavid van Moolenbroek * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
14*00b67f09SDavid van Moolenbroek * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
15*00b67f09SDavid van Moolenbroek * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
16*00b67f09SDavid van Moolenbroek * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17*00b67f09SDavid van Moolenbroek * PERFORMANCE OF THIS SOFTWARE.
18*00b67f09SDavid van Moolenbroek */
19*00b67f09SDavid van Moolenbroek
20*00b67f09SDavid van Moolenbroek /* Id: check-tool.c,v 1.44 2011/12/22 07:32:39 each Exp */
21*00b67f09SDavid van Moolenbroek
22*00b67f09SDavid van Moolenbroek /*! \file */
23*00b67f09SDavid van Moolenbroek
24*00b67f09SDavid van Moolenbroek #include <config.h>
25*00b67f09SDavid van Moolenbroek
26*00b67f09SDavid van Moolenbroek #include <stdio.h>
27*00b67f09SDavid van Moolenbroek
28*00b67f09SDavid van Moolenbroek #ifdef _WIN32
29*00b67f09SDavid van Moolenbroek #include <Winsock2.h>
30*00b67f09SDavid van Moolenbroek #endif
31*00b67f09SDavid van Moolenbroek
32*00b67f09SDavid van Moolenbroek #include "check-tool.h"
33*00b67f09SDavid van Moolenbroek #include <isc/buffer.h>
34*00b67f09SDavid van Moolenbroek #include <isc/log.h>
35*00b67f09SDavid van Moolenbroek #include <isc/mem.h>
36*00b67f09SDavid van Moolenbroek #include <isc/netdb.h>
37*00b67f09SDavid van Moolenbroek #include <isc/net.h>
38*00b67f09SDavid van Moolenbroek #include <isc/region.h>
39*00b67f09SDavid van Moolenbroek #include <isc/stdio.h>
40*00b67f09SDavid van Moolenbroek #include <isc/string.h>
41*00b67f09SDavid van Moolenbroek #include <isc/symtab.h>
42*00b67f09SDavid van Moolenbroek #include <isc/types.h>
43*00b67f09SDavid van Moolenbroek #include <isc/util.h>
44*00b67f09SDavid van Moolenbroek
45*00b67f09SDavid van Moolenbroek #include <dns/db.h>
46*00b67f09SDavid van Moolenbroek #include <dns/dbiterator.h>
47*00b67f09SDavid van Moolenbroek #include <dns/fixedname.h>
48*00b67f09SDavid van Moolenbroek #include <dns/log.h>
49*00b67f09SDavid van Moolenbroek #include <dns/name.h>
50*00b67f09SDavid van Moolenbroek #include <dns/rdata.h>
51*00b67f09SDavid van Moolenbroek #include <dns/rdataclass.h>
52*00b67f09SDavid van Moolenbroek #include <dns/rdataset.h>
53*00b67f09SDavid van Moolenbroek #include <dns/rdatasetiter.h>
54*00b67f09SDavid van Moolenbroek #include <dns/rdatatype.h>
55*00b67f09SDavid van Moolenbroek #include <dns/result.h>
56*00b67f09SDavid van Moolenbroek #include <dns/types.h>
57*00b67f09SDavid van Moolenbroek #include <dns/zone.h>
58*00b67f09SDavid van Moolenbroek
59*00b67f09SDavid van Moolenbroek #include <isccfg/log.h>
60*00b67f09SDavid van Moolenbroek
61*00b67f09SDavid van Moolenbroek #ifndef CHECK_SIBLING
62*00b67f09SDavid van Moolenbroek #define CHECK_SIBLING 1
63*00b67f09SDavid van Moolenbroek #endif
64*00b67f09SDavid van Moolenbroek
65*00b67f09SDavid van Moolenbroek #ifndef CHECK_LOCAL
66*00b67f09SDavid van Moolenbroek #define CHECK_LOCAL 1
67*00b67f09SDavid van Moolenbroek #endif
68*00b67f09SDavid van Moolenbroek
69*00b67f09SDavid van Moolenbroek #ifdef HAVE_ADDRINFO
70*00b67f09SDavid van Moolenbroek #ifdef HAVE_GETADDRINFO
71*00b67f09SDavid van Moolenbroek #ifdef HAVE_GAISTRERROR
72*00b67f09SDavid van Moolenbroek #define USE_GETADDRINFO
73*00b67f09SDavid van Moolenbroek #endif
74*00b67f09SDavid van Moolenbroek #endif
75*00b67f09SDavid van Moolenbroek #endif
76*00b67f09SDavid van Moolenbroek
77*00b67f09SDavid van Moolenbroek #define CHECK(r) \
78*00b67f09SDavid van Moolenbroek do { \
79*00b67f09SDavid van Moolenbroek result = (r); \
80*00b67f09SDavid van Moolenbroek if (result != ISC_R_SUCCESS) \
81*00b67f09SDavid van Moolenbroek goto cleanup; \
82*00b67f09SDavid van Moolenbroek } while (/*CONSTCOND*/0)
83*00b67f09SDavid van Moolenbroek
84*00b67f09SDavid van Moolenbroek #define ERR_IS_CNAME 1
85*00b67f09SDavid van Moolenbroek #define ERR_NO_ADDRESSES 2
86*00b67f09SDavid van Moolenbroek #define ERR_LOOKUP_FAILURE 3
87*00b67f09SDavid van Moolenbroek #define ERR_EXTRA_A 4
88*00b67f09SDavid van Moolenbroek #define ERR_EXTRA_AAAA 5
89*00b67f09SDavid van Moolenbroek #define ERR_MISSING_GLUE 5
90*00b67f09SDavid van Moolenbroek #define ERR_IS_MXCNAME 6
91*00b67f09SDavid van Moolenbroek #define ERR_IS_SRVCNAME 7
92*00b67f09SDavid van Moolenbroek
93*00b67f09SDavid van Moolenbroek static const char *dbtype[] = { "rbt" };
94*00b67f09SDavid van Moolenbroek
95*00b67f09SDavid van Moolenbroek int debug = 0;
96*00b67f09SDavid van Moolenbroek const char *journal = NULL;
97*00b67f09SDavid van Moolenbroek isc_boolean_t nomerge = ISC_TRUE;
98*00b67f09SDavid van Moolenbroek #if CHECK_LOCAL
99*00b67f09SDavid van Moolenbroek isc_boolean_t docheckmx = ISC_TRUE;
100*00b67f09SDavid van Moolenbroek isc_boolean_t dochecksrv = ISC_TRUE;
101*00b67f09SDavid van Moolenbroek isc_boolean_t docheckns = ISC_TRUE;
102*00b67f09SDavid van Moolenbroek #else
103*00b67f09SDavid van Moolenbroek isc_boolean_t docheckmx = ISC_FALSE;
104*00b67f09SDavid van Moolenbroek isc_boolean_t dochecksrv = ISC_FALSE;
105*00b67f09SDavid van Moolenbroek isc_boolean_t docheckns = ISC_FALSE;
106*00b67f09SDavid van Moolenbroek #endif
107*00b67f09SDavid van Moolenbroek unsigned int zone_options = DNS_ZONEOPT_CHECKNS |
108*00b67f09SDavid van Moolenbroek DNS_ZONEOPT_CHECKMX |
109*00b67f09SDavid van Moolenbroek DNS_ZONEOPT_MANYERRORS |
110*00b67f09SDavid van Moolenbroek DNS_ZONEOPT_CHECKNAMES |
111*00b67f09SDavid van Moolenbroek DNS_ZONEOPT_CHECKINTEGRITY |
112*00b67f09SDavid van Moolenbroek #if CHECK_SIBLING
113*00b67f09SDavid van Moolenbroek DNS_ZONEOPT_CHECKSIBLING |
114*00b67f09SDavid van Moolenbroek #endif
115*00b67f09SDavid van Moolenbroek DNS_ZONEOPT_CHECKWILDCARD |
116*00b67f09SDavid van Moolenbroek DNS_ZONEOPT_WARNMXCNAME |
117*00b67f09SDavid van Moolenbroek DNS_ZONEOPT_WARNSRVCNAME;
118*00b67f09SDavid van Moolenbroek unsigned int zone_options2 = 0;
119*00b67f09SDavid van Moolenbroek
120*00b67f09SDavid van Moolenbroek /*
121*00b67f09SDavid van Moolenbroek * This needs to match the list in bin/named/log.c.
122*00b67f09SDavid van Moolenbroek */
123*00b67f09SDavid van Moolenbroek static isc_logcategory_t categories[] = {
124*00b67f09SDavid van Moolenbroek { "", 0 },
125*00b67f09SDavid van Moolenbroek { "client", 0 },
126*00b67f09SDavid van Moolenbroek { "network", 0 },
127*00b67f09SDavid van Moolenbroek { "update", 0 },
128*00b67f09SDavid van Moolenbroek { "queries", 0 },
129*00b67f09SDavid van Moolenbroek { "unmatched", 0 },
130*00b67f09SDavid van Moolenbroek { "update-security", 0 },
131*00b67f09SDavid van Moolenbroek { "query-errors", 0 },
132*00b67f09SDavid van Moolenbroek { NULL, 0 }
133*00b67f09SDavid van Moolenbroek };
134*00b67f09SDavid van Moolenbroek
135*00b67f09SDavid van Moolenbroek static isc_symtab_t *symtab = NULL;
136*00b67f09SDavid van Moolenbroek static isc_mem_t *sym_mctx;
137*00b67f09SDavid van Moolenbroek
138*00b67f09SDavid van Moolenbroek static void
freekey(char * key,unsigned int type,isc_symvalue_t value,void * userarg)139*00b67f09SDavid van Moolenbroek freekey(char *key, unsigned int type, isc_symvalue_t value, void *userarg) {
140*00b67f09SDavid van Moolenbroek UNUSED(type);
141*00b67f09SDavid van Moolenbroek UNUSED(value);
142*00b67f09SDavid van Moolenbroek isc_mem_free(userarg, key);
143*00b67f09SDavid van Moolenbroek }
144*00b67f09SDavid van Moolenbroek
145*00b67f09SDavid van Moolenbroek static void
add(char * key,int value)146*00b67f09SDavid van Moolenbroek add(char *key, int value) {
147*00b67f09SDavid van Moolenbroek isc_result_t result;
148*00b67f09SDavid van Moolenbroek isc_symvalue_t symvalue;
149*00b67f09SDavid van Moolenbroek
150*00b67f09SDavid van Moolenbroek if (sym_mctx == NULL) {
151*00b67f09SDavid van Moolenbroek result = isc_mem_create(0, 0, &sym_mctx);
152*00b67f09SDavid van Moolenbroek if (result != ISC_R_SUCCESS)
153*00b67f09SDavid van Moolenbroek return;
154*00b67f09SDavid van Moolenbroek }
155*00b67f09SDavid van Moolenbroek
156*00b67f09SDavid van Moolenbroek if (symtab == NULL) {
157*00b67f09SDavid van Moolenbroek result = isc_symtab_create(sym_mctx, 100, freekey, sym_mctx,
158*00b67f09SDavid van Moolenbroek ISC_FALSE, &symtab);
159*00b67f09SDavid van Moolenbroek if (result != ISC_R_SUCCESS)
160*00b67f09SDavid van Moolenbroek return;
161*00b67f09SDavid van Moolenbroek }
162*00b67f09SDavid van Moolenbroek
163*00b67f09SDavid van Moolenbroek key = isc_mem_strdup(sym_mctx, key);
164*00b67f09SDavid van Moolenbroek if (key == NULL)
165*00b67f09SDavid van Moolenbroek return;
166*00b67f09SDavid van Moolenbroek
167*00b67f09SDavid van Moolenbroek symvalue.as_pointer = NULL;
168*00b67f09SDavid van Moolenbroek result = isc_symtab_define(symtab, key, value, symvalue,
169*00b67f09SDavid van Moolenbroek isc_symexists_reject);
170*00b67f09SDavid van Moolenbroek if (result != ISC_R_SUCCESS)
171*00b67f09SDavid van Moolenbroek isc_mem_free(sym_mctx, key);
172*00b67f09SDavid van Moolenbroek }
173*00b67f09SDavid van Moolenbroek
174*00b67f09SDavid van Moolenbroek static isc_boolean_t
logged(char * key,int value)175*00b67f09SDavid van Moolenbroek logged(char *key, int value) {
176*00b67f09SDavid van Moolenbroek isc_result_t result;
177*00b67f09SDavid van Moolenbroek
178*00b67f09SDavid van Moolenbroek if (symtab == NULL)
179*00b67f09SDavid van Moolenbroek return (ISC_FALSE);
180*00b67f09SDavid van Moolenbroek
181*00b67f09SDavid van Moolenbroek result = isc_symtab_lookup(symtab, key, value, NULL);
182*00b67f09SDavid van Moolenbroek if (result == ISC_R_SUCCESS)
183*00b67f09SDavid van Moolenbroek return (ISC_TRUE);
184*00b67f09SDavid van Moolenbroek return (ISC_FALSE);
185*00b67f09SDavid van Moolenbroek }
186*00b67f09SDavid van Moolenbroek
187*00b67f09SDavid van Moolenbroek static isc_boolean_t
checkns(dns_zone_t * zone,dns_name_t * name,dns_name_t * owner,dns_rdataset_t * a,dns_rdataset_t * aaaa)188*00b67f09SDavid van Moolenbroek checkns(dns_zone_t *zone, dns_name_t *name, dns_name_t *owner,
189*00b67f09SDavid van Moolenbroek dns_rdataset_t *a, dns_rdataset_t *aaaa)
190*00b67f09SDavid van Moolenbroek {
191*00b67f09SDavid van Moolenbroek #ifdef USE_GETADDRINFO
192*00b67f09SDavid van Moolenbroek dns_rdataset_t *rdataset;
193*00b67f09SDavid van Moolenbroek dns_rdata_t rdata = DNS_RDATA_INIT;
194*00b67f09SDavid van Moolenbroek struct addrinfo hints, *ai, *cur;
195*00b67f09SDavid van Moolenbroek char namebuf[DNS_NAME_FORMATSIZE + 1];
196*00b67f09SDavid van Moolenbroek char ownerbuf[DNS_NAME_FORMATSIZE];
197*00b67f09SDavid van Moolenbroek char addrbuf[sizeof("xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:123.123.123.123")];
198*00b67f09SDavid van Moolenbroek isc_boolean_t answer = ISC_TRUE;
199*00b67f09SDavid van Moolenbroek isc_boolean_t match;
200*00b67f09SDavid van Moolenbroek const char *type;
201*00b67f09SDavid van Moolenbroek void *ptr = NULL;
202*00b67f09SDavid van Moolenbroek int result;
203*00b67f09SDavid van Moolenbroek
204*00b67f09SDavid van Moolenbroek REQUIRE(a == NULL || !dns_rdataset_isassociated(a) ||
205*00b67f09SDavid van Moolenbroek a->type == dns_rdatatype_a);
206*00b67f09SDavid van Moolenbroek REQUIRE(aaaa == NULL || !dns_rdataset_isassociated(aaaa) ||
207*00b67f09SDavid van Moolenbroek aaaa->type == dns_rdatatype_aaaa);
208*00b67f09SDavid van Moolenbroek
209*00b67f09SDavid van Moolenbroek if (a == NULL || aaaa == NULL)
210*00b67f09SDavid van Moolenbroek return (answer);
211*00b67f09SDavid van Moolenbroek
212*00b67f09SDavid van Moolenbroek memset(&hints, 0, sizeof(hints));
213*00b67f09SDavid van Moolenbroek hints.ai_flags = AI_CANONNAME;
214*00b67f09SDavid van Moolenbroek hints.ai_family = PF_UNSPEC;
215*00b67f09SDavid van Moolenbroek hints.ai_socktype = SOCK_STREAM;
216*00b67f09SDavid van Moolenbroek hints.ai_protocol = IPPROTO_TCP;
217*00b67f09SDavid van Moolenbroek
218*00b67f09SDavid van Moolenbroek dns_name_format(name, namebuf, sizeof(namebuf) - 1);
219*00b67f09SDavid van Moolenbroek /*
220*00b67f09SDavid van Moolenbroek * Turn off search.
221*00b67f09SDavid van Moolenbroek */
222*00b67f09SDavid van Moolenbroek if (dns_name_countlabels(name) > 1U)
223*00b67f09SDavid van Moolenbroek strcat(namebuf, ".");
224*00b67f09SDavid van Moolenbroek dns_name_format(owner, ownerbuf, sizeof(ownerbuf));
225*00b67f09SDavid van Moolenbroek
226*00b67f09SDavid van Moolenbroek result = getaddrinfo(namebuf, NULL, &hints, &ai);
227*00b67f09SDavid van Moolenbroek dns_name_format(name, namebuf, sizeof(namebuf) - 1);
228*00b67f09SDavid van Moolenbroek switch (result) {
229*00b67f09SDavid van Moolenbroek case 0:
230*00b67f09SDavid van Moolenbroek /*
231*00b67f09SDavid van Moolenbroek * Work around broken getaddrinfo() implementations that
232*00b67f09SDavid van Moolenbroek * fail to set ai_canonname on first entry.
233*00b67f09SDavid van Moolenbroek */
234*00b67f09SDavid van Moolenbroek cur = ai;
235*00b67f09SDavid van Moolenbroek while (cur != NULL && cur->ai_canonname == NULL &&
236*00b67f09SDavid van Moolenbroek cur->ai_next != NULL)
237*00b67f09SDavid van Moolenbroek cur = cur->ai_next;
238*00b67f09SDavid van Moolenbroek if (cur != NULL && cur->ai_canonname != NULL &&
239*00b67f09SDavid van Moolenbroek strcasecmp(cur->ai_canonname, namebuf) != 0 &&
240*00b67f09SDavid van Moolenbroek !logged(namebuf, ERR_IS_CNAME)) {
241*00b67f09SDavid van Moolenbroek dns_zone_log(zone, ISC_LOG_ERROR,
242*00b67f09SDavid van Moolenbroek "%s/NS '%s' (out of zone) "
243*00b67f09SDavid van Moolenbroek "is a CNAME '%s' (illegal)",
244*00b67f09SDavid van Moolenbroek ownerbuf, namebuf,
245*00b67f09SDavid van Moolenbroek cur->ai_canonname);
246*00b67f09SDavid van Moolenbroek /* XXX950 make fatal for 9.5.0 */
247*00b67f09SDavid van Moolenbroek /* answer = ISC_FALSE; */
248*00b67f09SDavid van Moolenbroek add(namebuf, ERR_IS_CNAME);
249*00b67f09SDavid van Moolenbroek }
250*00b67f09SDavid van Moolenbroek break;
251*00b67f09SDavid van Moolenbroek case EAI_NONAME:
252*00b67f09SDavid van Moolenbroek #if defined(EAI_NODATA) && (EAI_NODATA != EAI_NONAME)
253*00b67f09SDavid van Moolenbroek case EAI_NODATA:
254*00b67f09SDavid van Moolenbroek #endif
255*00b67f09SDavid van Moolenbroek if (!logged(namebuf, ERR_NO_ADDRESSES)) {
256*00b67f09SDavid van Moolenbroek dns_zone_log(zone, ISC_LOG_ERROR,
257*00b67f09SDavid van Moolenbroek "%s/NS '%s' (out of zone) "
258*00b67f09SDavid van Moolenbroek "has no addresses records (A or AAAA)",
259*00b67f09SDavid van Moolenbroek ownerbuf, namebuf);
260*00b67f09SDavid van Moolenbroek add(namebuf, ERR_NO_ADDRESSES);
261*00b67f09SDavid van Moolenbroek }
262*00b67f09SDavid van Moolenbroek /* XXX950 make fatal for 9.5.0 */
263*00b67f09SDavid van Moolenbroek return (ISC_TRUE);
264*00b67f09SDavid van Moolenbroek
265*00b67f09SDavid van Moolenbroek default:
266*00b67f09SDavid van Moolenbroek if (!logged(namebuf, ERR_LOOKUP_FAILURE)) {
267*00b67f09SDavid van Moolenbroek dns_zone_log(zone, ISC_LOG_WARNING,
268*00b67f09SDavid van Moolenbroek "getaddrinfo(%s) failed: %s",
269*00b67f09SDavid van Moolenbroek namebuf, gai_strerror(result));
270*00b67f09SDavid van Moolenbroek add(namebuf, ERR_LOOKUP_FAILURE);
271*00b67f09SDavid van Moolenbroek }
272*00b67f09SDavid van Moolenbroek return (ISC_TRUE);
273*00b67f09SDavid van Moolenbroek }
274*00b67f09SDavid van Moolenbroek
275*00b67f09SDavid van Moolenbroek /*
276*00b67f09SDavid van Moolenbroek * Check that all glue records really exist.
277*00b67f09SDavid van Moolenbroek */
278*00b67f09SDavid van Moolenbroek if (!dns_rdataset_isassociated(a))
279*00b67f09SDavid van Moolenbroek goto checkaaaa;
280*00b67f09SDavid van Moolenbroek result = dns_rdataset_first(a);
281*00b67f09SDavid van Moolenbroek while (result == ISC_R_SUCCESS) {
282*00b67f09SDavid van Moolenbroek dns_rdataset_current(a, &rdata);
283*00b67f09SDavid van Moolenbroek match = ISC_FALSE;
284*00b67f09SDavid van Moolenbroek for (cur = ai; cur != NULL; cur = cur->ai_next) {
285*00b67f09SDavid van Moolenbroek if (cur->ai_family != AF_INET)
286*00b67f09SDavid van Moolenbroek continue;
287*00b67f09SDavid van Moolenbroek ptr = &((struct sockaddr_in *)(cur->ai_addr))->sin_addr;
288*00b67f09SDavid van Moolenbroek if (memcmp(ptr, rdata.data, rdata.length) == 0) {
289*00b67f09SDavid van Moolenbroek match = ISC_TRUE;
290*00b67f09SDavid van Moolenbroek break;
291*00b67f09SDavid van Moolenbroek }
292*00b67f09SDavid van Moolenbroek }
293*00b67f09SDavid van Moolenbroek if (!match && !logged(namebuf, ERR_EXTRA_A)) {
294*00b67f09SDavid van Moolenbroek dns_zone_log(zone, ISC_LOG_ERROR, "%s/NS '%s' "
295*00b67f09SDavid van Moolenbroek "extra GLUE A record (%s)",
296*00b67f09SDavid van Moolenbroek ownerbuf, namebuf,
297*00b67f09SDavid van Moolenbroek inet_ntop(AF_INET, rdata.data,
298*00b67f09SDavid van Moolenbroek addrbuf, sizeof(addrbuf)));
299*00b67f09SDavid van Moolenbroek add(namebuf, ERR_EXTRA_A);
300*00b67f09SDavid van Moolenbroek /* XXX950 make fatal for 9.5.0 */
301*00b67f09SDavid van Moolenbroek /* answer = ISC_FALSE; */
302*00b67f09SDavid van Moolenbroek }
303*00b67f09SDavid van Moolenbroek dns_rdata_reset(&rdata);
304*00b67f09SDavid van Moolenbroek result = dns_rdataset_next(a);
305*00b67f09SDavid van Moolenbroek }
306*00b67f09SDavid van Moolenbroek
307*00b67f09SDavid van Moolenbroek checkaaaa:
308*00b67f09SDavid van Moolenbroek if (!dns_rdataset_isassociated(aaaa))
309*00b67f09SDavid van Moolenbroek goto checkmissing;
310*00b67f09SDavid van Moolenbroek result = dns_rdataset_first(aaaa);
311*00b67f09SDavid van Moolenbroek while (result == ISC_R_SUCCESS) {
312*00b67f09SDavid van Moolenbroek dns_rdataset_current(aaaa, &rdata);
313*00b67f09SDavid van Moolenbroek match = ISC_FALSE;
314*00b67f09SDavid van Moolenbroek for (cur = ai; cur != NULL; cur = cur->ai_next) {
315*00b67f09SDavid van Moolenbroek if (cur->ai_family != AF_INET6)
316*00b67f09SDavid van Moolenbroek continue;
317*00b67f09SDavid van Moolenbroek ptr = &((struct sockaddr_in6 *)(cur->ai_addr))->sin6_addr;
318*00b67f09SDavid van Moolenbroek if (memcmp(ptr, rdata.data, rdata.length) == 0) {
319*00b67f09SDavid van Moolenbroek match = ISC_TRUE;
320*00b67f09SDavid van Moolenbroek break;
321*00b67f09SDavid van Moolenbroek }
322*00b67f09SDavid van Moolenbroek }
323*00b67f09SDavid van Moolenbroek if (!match && !logged(namebuf, ERR_EXTRA_AAAA)) {
324*00b67f09SDavid van Moolenbroek dns_zone_log(zone, ISC_LOG_ERROR, "%s/NS '%s' "
325*00b67f09SDavid van Moolenbroek "extra GLUE AAAA record (%s)",
326*00b67f09SDavid van Moolenbroek ownerbuf, namebuf,
327*00b67f09SDavid van Moolenbroek inet_ntop(AF_INET6, rdata.data,
328*00b67f09SDavid van Moolenbroek addrbuf, sizeof(addrbuf)));
329*00b67f09SDavid van Moolenbroek add(namebuf, ERR_EXTRA_AAAA);
330*00b67f09SDavid van Moolenbroek /* XXX950 make fatal for 9.5.0. */
331*00b67f09SDavid van Moolenbroek /* answer = ISC_FALSE; */
332*00b67f09SDavid van Moolenbroek }
333*00b67f09SDavid van Moolenbroek dns_rdata_reset(&rdata);
334*00b67f09SDavid van Moolenbroek result = dns_rdataset_next(aaaa);
335*00b67f09SDavid van Moolenbroek }
336*00b67f09SDavid van Moolenbroek
337*00b67f09SDavid van Moolenbroek checkmissing:
338*00b67f09SDavid van Moolenbroek /*
339*00b67f09SDavid van Moolenbroek * Check that all addresses appear in the glue.
340*00b67f09SDavid van Moolenbroek */
341*00b67f09SDavid van Moolenbroek if (!logged(namebuf, ERR_MISSING_GLUE)) {
342*00b67f09SDavid van Moolenbroek isc_boolean_t missing_glue = ISC_FALSE;
343*00b67f09SDavid van Moolenbroek for (cur = ai; cur != NULL; cur = cur->ai_next) {
344*00b67f09SDavid van Moolenbroek switch (cur->ai_family) {
345*00b67f09SDavid van Moolenbroek case AF_INET:
346*00b67f09SDavid van Moolenbroek rdataset = a;
347*00b67f09SDavid van Moolenbroek ptr = &((struct sockaddr_in *)(cur->ai_addr))->sin_addr;
348*00b67f09SDavid van Moolenbroek type = "A";
349*00b67f09SDavid van Moolenbroek break;
350*00b67f09SDavid van Moolenbroek case AF_INET6:
351*00b67f09SDavid van Moolenbroek rdataset = aaaa;
352*00b67f09SDavid van Moolenbroek ptr = &((struct sockaddr_in6 *)(cur->ai_addr))->sin6_addr;
353*00b67f09SDavid van Moolenbroek type = "AAAA";
354*00b67f09SDavid van Moolenbroek break;
355*00b67f09SDavid van Moolenbroek default:
356*00b67f09SDavid van Moolenbroek continue;
357*00b67f09SDavid van Moolenbroek }
358*00b67f09SDavid van Moolenbroek match = ISC_FALSE;
359*00b67f09SDavid van Moolenbroek if (dns_rdataset_isassociated(rdataset))
360*00b67f09SDavid van Moolenbroek result = dns_rdataset_first(rdataset);
361*00b67f09SDavid van Moolenbroek else
362*00b67f09SDavid van Moolenbroek result = ISC_R_FAILURE;
363*00b67f09SDavid van Moolenbroek while (result == ISC_R_SUCCESS && !match) {
364*00b67f09SDavid van Moolenbroek dns_rdataset_current(rdataset, &rdata);
365*00b67f09SDavid van Moolenbroek if (memcmp(ptr, rdata.data, rdata.length) == 0)
366*00b67f09SDavid van Moolenbroek match = ISC_TRUE;
367*00b67f09SDavid van Moolenbroek dns_rdata_reset(&rdata);
368*00b67f09SDavid van Moolenbroek result = dns_rdataset_next(rdataset);
369*00b67f09SDavid van Moolenbroek }
370*00b67f09SDavid van Moolenbroek if (!match) {
371*00b67f09SDavid van Moolenbroek dns_zone_log(zone, ISC_LOG_ERROR, "%s/NS '%s' "
372*00b67f09SDavid van Moolenbroek "missing GLUE %s record (%s)",
373*00b67f09SDavid van Moolenbroek ownerbuf, namebuf, type,
374*00b67f09SDavid van Moolenbroek inet_ntop(cur->ai_family, ptr,
375*00b67f09SDavid van Moolenbroek addrbuf, sizeof(addrbuf)));
376*00b67f09SDavid van Moolenbroek /* XXX950 make fatal for 9.5.0. */
377*00b67f09SDavid van Moolenbroek /* answer = ISC_FALSE; */
378*00b67f09SDavid van Moolenbroek missing_glue = ISC_TRUE;
379*00b67f09SDavid van Moolenbroek }
380*00b67f09SDavid van Moolenbroek }
381*00b67f09SDavid van Moolenbroek if (missing_glue)
382*00b67f09SDavid van Moolenbroek add(namebuf, ERR_MISSING_GLUE);
383*00b67f09SDavid van Moolenbroek }
384*00b67f09SDavid van Moolenbroek freeaddrinfo(ai);
385*00b67f09SDavid van Moolenbroek return (answer);
386*00b67f09SDavid van Moolenbroek #else
387*00b67f09SDavid van Moolenbroek return (ISC_TRUE);
388*00b67f09SDavid van Moolenbroek #endif
389*00b67f09SDavid van Moolenbroek }
390*00b67f09SDavid van Moolenbroek
391*00b67f09SDavid van Moolenbroek static isc_boolean_t
checkmx(dns_zone_t * zone,dns_name_t * name,dns_name_t * owner)392*00b67f09SDavid van Moolenbroek checkmx(dns_zone_t *zone, dns_name_t *name, dns_name_t *owner) {
393*00b67f09SDavid van Moolenbroek #ifdef USE_GETADDRINFO
394*00b67f09SDavid van Moolenbroek struct addrinfo hints, *ai, *cur;
395*00b67f09SDavid van Moolenbroek char namebuf[DNS_NAME_FORMATSIZE + 1];
396*00b67f09SDavid van Moolenbroek char ownerbuf[DNS_NAME_FORMATSIZE];
397*00b67f09SDavid van Moolenbroek int result;
398*00b67f09SDavid van Moolenbroek int level = ISC_LOG_ERROR;
399*00b67f09SDavid van Moolenbroek isc_boolean_t answer = ISC_TRUE;
400*00b67f09SDavid van Moolenbroek
401*00b67f09SDavid van Moolenbroek memset(&hints, 0, sizeof(hints));
402*00b67f09SDavid van Moolenbroek hints.ai_flags = AI_CANONNAME;
403*00b67f09SDavid van Moolenbroek hints.ai_family = PF_UNSPEC;
404*00b67f09SDavid van Moolenbroek hints.ai_socktype = SOCK_STREAM;
405*00b67f09SDavid van Moolenbroek hints.ai_protocol = IPPROTO_TCP;
406*00b67f09SDavid van Moolenbroek
407*00b67f09SDavid van Moolenbroek dns_name_format(name, namebuf, sizeof(namebuf) - 1);
408*00b67f09SDavid van Moolenbroek /*
409*00b67f09SDavid van Moolenbroek * Turn off search.
410*00b67f09SDavid van Moolenbroek */
411*00b67f09SDavid van Moolenbroek if (dns_name_countlabels(name) > 1U)
412*00b67f09SDavid van Moolenbroek strcat(namebuf, ".");
413*00b67f09SDavid van Moolenbroek dns_name_format(owner, ownerbuf, sizeof(ownerbuf));
414*00b67f09SDavid van Moolenbroek
415*00b67f09SDavid van Moolenbroek result = getaddrinfo(namebuf, NULL, &hints, &ai);
416*00b67f09SDavid van Moolenbroek dns_name_format(name, namebuf, sizeof(namebuf) - 1);
417*00b67f09SDavid van Moolenbroek switch (result) {
418*00b67f09SDavid van Moolenbroek case 0:
419*00b67f09SDavid van Moolenbroek /*
420*00b67f09SDavid van Moolenbroek * Work around broken getaddrinfo() implementations that
421*00b67f09SDavid van Moolenbroek * fail to set ai_canonname on first entry.
422*00b67f09SDavid van Moolenbroek */
423*00b67f09SDavid van Moolenbroek cur = ai;
424*00b67f09SDavid van Moolenbroek while (cur != NULL && cur->ai_canonname == NULL &&
425*00b67f09SDavid van Moolenbroek cur->ai_next != NULL)
426*00b67f09SDavid van Moolenbroek cur = cur->ai_next;
427*00b67f09SDavid van Moolenbroek if (cur != NULL && cur->ai_canonname != NULL &&
428*00b67f09SDavid van Moolenbroek strcasecmp(cur->ai_canonname, namebuf) != 0) {
429*00b67f09SDavid van Moolenbroek if ((zone_options & DNS_ZONEOPT_WARNMXCNAME) != 0)
430*00b67f09SDavid van Moolenbroek level = ISC_LOG_WARNING;
431*00b67f09SDavid van Moolenbroek if ((zone_options & DNS_ZONEOPT_IGNOREMXCNAME) == 0) {
432*00b67f09SDavid van Moolenbroek if (!logged(namebuf, ERR_IS_MXCNAME)) {
433*00b67f09SDavid van Moolenbroek dns_zone_log(zone, level,
434*00b67f09SDavid van Moolenbroek "%s/MX '%s' (out of zone)"
435*00b67f09SDavid van Moolenbroek " is a CNAME '%s' "
436*00b67f09SDavid van Moolenbroek "(illegal)",
437*00b67f09SDavid van Moolenbroek ownerbuf, namebuf,
438*00b67f09SDavid van Moolenbroek cur->ai_canonname);
439*00b67f09SDavid van Moolenbroek add(namebuf, ERR_IS_MXCNAME);
440*00b67f09SDavid van Moolenbroek }
441*00b67f09SDavid van Moolenbroek if (level == ISC_LOG_ERROR)
442*00b67f09SDavid van Moolenbroek answer = ISC_FALSE;
443*00b67f09SDavid van Moolenbroek }
444*00b67f09SDavid van Moolenbroek }
445*00b67f09SDavid van Moolenbroek freeaddrinfo(ai);
446*00b67f09SDavid van Moolenbroek return (answer);
447*00b67f09SDavid van Moolenbroek
448*00b67f09SDavid van Moolenbroek case EAI_NONAME:
449*00b67f09SDavid van Moolenbroek #if defined(EAI_NODATA) && (EAI_NODATA != EAI_NONAME)
450*00b67f09SDavid van Moolenbroek case EAI_NODATA:
451*00b67f09SDavid van Moolenbroek #endif
452*00b67f09SDavid van Moolenbroek if (!logged(namebuf, ERR_NO_ADDRESSES)) {
453*00b67f09SDavid van Moolenbroek dns_zone_log(zone, ISC_LOG_ERROR,
454*00b67f09SDavid van Moolenbroek "%s/MX '%s' (out of zone) "
455*00b67f09SDavid van Moolenbroek "has no addresses records (A or AAAA)",
456*00b67f09SDavid van Moolenbroek ownerbuf, namebuf);
457*00b67f09SDavid van Moolenbroek add(namebuf, ERR_NO_ADDRESSES);
458*00b67f09SDavid van Moolenbroek }
459*00b67f09SDavid van Moolenbroek /* XXX950 make fatal for 9.5.0. */
460*00b67f09SDavid van Moolenbroek return (ISC_TRUE);
461*00b67f09SDavid van Moolenbroek
462*00b67f09SDavid van Moolenbroek default:
463*00b67f09SDavid van Moolenbroek if (!logged(namebuf, ERR_LOOKUP_FAILURE)) {
464*00b67f09SDavid van Moolenbroek dns_zone_log(zone, ISC_LOG_WARNING,
465*00b67f09SDavid van Moolenbroek "getaddrinfo(%s) failed: %s",
466*00b67f09SDavid van Moolenbroek namebuf, gai_strerror(result));
467*00b67f09SDavid van Moolenbroek add(namebuf, ERR_LOOKUP_FAILURE);
468*00b67f09SDavid van Moolenbroek }
469*00b67f09SDavid van Moolenbroek return (ISC_TRUE);
470*00b67f09SDavid van Moolenbroek }
471*00b67f09SDavid van Moolenbroek #else
472*00b67f09SDavid van Moolenbroek return (ISC_TRUE);
473*00b67f09SDavid van Moolenbroek #endif
474*00b67f09SDavid van Moolenbroek }
475*00b67f09SDavid van Moolenbroek
476*00b67f09SDavid van Moolenbroek static isc_boolean_t
checksrv(dns_zone_t * zone,dns_name_t * name,dns_name_t * owner)477*00b67f09SDavid van Moolenbroek checksrv(dns_zone_t *zone, dns_name_t *name, dns_name_t *owner) {
478*00b67f09SDavid van Moolenbroek #ifdef USE_GETADDRINFO
479*00b67f09SDavid van Moolenbroek struct addrinfo hints, *ai, *cur;
480*00b67f09SDavid van Moolenbroek char namebuf[DNS_NAME_FORMATSIZE + 1];
481*00b67f09SDavid van Moolenbroek char ownerbuf[DNS_NAME_FORMATSIZE];
482*00b67f09SDavid van Moolenbroek int result;
483*00b67f09SDavid van Moolenbroek int level = ISC_LOG_ERROR;
484*00b67f09SDavid van Moolenbroek isc_boolean_t answer = ISC_TRUE;
485*00b67f09SDavid van Moolenbroek
486*00b67f09SDavid van Moolenbroek memset(&hints, 0, sizeof(hints));
487*00b67f09SDavid van Moolenbroek hints.ai_flags = AI_CANONNAME;
488*00b67f09SDavid van Moolenbroek hints.ai_family = PF_UNSPEC;
489*00b67f09SDavid van Moolenbroek hints.ai_socktype = SOCK_STREAM;
490*00b67f09SDavid van Moolenbroek hints.ai_protocol = IPPROTO_TCP;
491*00b67f09SDavid van Moolenbroek
492*00b67f09SDavid van Moolenbroek dns_name_format(name, namebuf, sizeof(namebuf) - 1);
493*00b67f09SDavid van Moolenbroek /*
494*00b67f09SDavid van Moolenbroek * Turn off search.
495*00b67f09SDavid van Moolenbroek */
496*00b67f09SDavid van Moolenbroek if (dns_name_countlabels(name) > 1U)
497*00b67f09SDavid van Moolenbroek strcat(namebuf, ".");
498*00b67f09SDavid van Moolenbroek dns_name_format(owner, ownerbuf, sizeof(ownerbuf));
499*00b67f09SDavid van Moolenbroek
500*00b67f09SDavid van Moolenbroek result = getaddrinfo(namebuf, NULL, &hints, &ai);
501*00b67f09SDavid van Moolenbroek dns_name_format(name, namebuf, sizeof(namebuf) - 1);
502*00b67f09SDavid van Moolenbroek switch (result) {
503*00b67f09SDavid van Moolenbroek case 0:
504*00b67f09SDavid van Moolenbroek /*
505*00b67f09SDavid van Moolenbroek * Work around broken getaddrinfo() implementations that
506*00b67f09SDavid van Moolenbroek * fail to set ai_canonname on first entry.
507*00b67f09SDavid van Moolenbroek */
508*00b67f09SDavid van Moolenbroek cur = ai;
509*00b67f09SDavid van Moolenbroek while (cur != NULL && cur->ai_canonname == NULL &&
510*00b67f09SDavid van Moolenbroek cur->ai_next != NULL)
511*00b67f09SDavid van Moolenbroek cur = cur->ai_next;
512*00b67f09SDavid van Moolenbroek if (cur != NULL && cur->ai_canonname != NULL &&
513*00b67f09SDavid van Moolenbroek strcasecmp(cur->ai_canonname, namebuf) != 0) {
514*00b67f09SDavid van Moolenbroek if ((zone_options & DNS_ZONEOPT_WARNSRVCNAME) != 0)
515*00b67f09SDavid van Moolenbroek level = ISC_LOG_WARNING;
516*00b67f09SDavid van Moolenbroek if ((zone_options & DNS_ZONEOPT_IGNORESRVCNAME) == 0) {
517*00b67f09SDavid van Moolenbroek if (!logged(namebuf, ERR_IS_SRVCNAME)) {
518*00b67f09SDavid van Moolenbroek dns_zone_log(zone, level, "%s/SRV '%s'"
519*00b67f09SDavid van Moolenbroek " (out of zone) is a "
520*00b67f09SDavid van Moolenbroek "CNAME '%s' (illegal)",
521*00b67f09SDavid van Moolenbroek ownerbuf, namebuf,
522*00b67f09SDavid van Moolenbroek cur->ai_canonname);
523*00b67f09SDavid van Moolenbroek add(namebuf, ERR_IS_SRVCNAME);
524*00b67f09SDavid van Moolenbroek }
525*00b67f09SDavid van Moolenbroek if (level == ISC_LOG_ERROR)
526*00b67f09SDavid van Moolenbroek answer = ISC_FALSE;
527*00b67f09SDavid van Moolenbroek }
528*00b67f09SDavid van Moolenbroek }
529*00b67f09SDavid van Moolenbroek freeaddrinfo(ai);
530*00b67f09SDavid van Moolenbroek return (answer);
531*00b67f09SDavid van Moolenbroek
532*00b67f09SDavid van Moolenbroek case EAI_NONAME:
533*00b67f09SDavid van Moolenbroek #if defined(EAI_NODATA) && (EAI_NODATA != EAI_NONAME)
534*00b67f09SDavid van Moolenbroek case EAI_NODATA:
535*00b67f09SDavid van Moolenbroek #endif
536*00b67f09SDavid van Moolenbroek if (!logged(namebuf, ERR_NO_ADDRESSES)) {
537*00b67f09SDavid van Moolenbroek dns_zone_log(zone, ISC_LOG_ERROR,
538*00b67f09SDavid van Moolenbroek "%s/SRV '%s' (out of zone) "
539*00b67f09SDavid van Moolenbroek "has no addresses records (A or AAAA)",
540*00b67f09SDavid van Moolenbroek ownerbuf, namebuf);
541*00b67f09SDavid van Moolenbroek add(namebuf, ERR_NO_ADDRESSES);
542*00b67f09SDavid van Moolenbroek }
543*00b67f09SDavid van Moolenbroek /* XXX950 make fatal for 9.5.0. */
544*00b67f09SDavid van Moolenbroek return (ISC_TRUE);
545*00b67f09SDavid van Moolenbroek
546*00b67f09SDavid van Moolenbroek default:
547*00b67f09SDavid van Moolenbroek if (!logged(namebuf, ERR_LOOKUP_FAILURE)) {
548*00b67f09SDavid van Moolenbroek dns_zone_log(zone, ISC_LOG_WARNING,
549*00b67f09SDavid van Moolenbroek "getaddrinfo(%s) failed: %s",
550*00b67f09SDavid van Moolenbroek namebuf, gai_strerror(result));
551*00b67f09SDavid van Moolenbroek add(namebuf, ERR_LOOKUP_FAILURE);
552*00b67f09SDavid van Moolenbroek }
553*00b67f09SDavid van Moolenbroek return (ISC_TRUE);
554*00b67f09SDavid van Moolenbroek }
555*00b67f09SDavid van Moolenbroek #else
556*00b67f09SDavid van Moolenbroek return (ISC_TRUE);
557*00b67f09SDavid van Moolenbroek #endif
558*00b67f09SDavid van Moolenbroek }
559*00b67f09SDavid van Moolenbroek
560*00b67f09SDavid van Moolenbroek isc_result_t
setup_logging(isc_mem_t * mctx,FILE * errout,isc_log_t ** logp)561*00b67f09SDavid van Moolenbroek setup_logging(isc_mem_t *mctx, FILE *errout, isc_log_t **logp) {
562*00b67f09SDavid van Moolenbroek isc_logdestination_t destination;
563*00b67f09SDavid van Moolenbroek isc_logconfig_t *logconfig = NULL;
564*00b67f09SDavid van Moolenbroek isc_log_t *log = NULL;
565*00b67f09SDavid van Moolenbroek
566*00b67f09SDavid van Moolenbroek RUNTIME_CHECK(isc_log_create(mctx, &log, &logconfig) == ISC_R_SUCCESS);
567*00b67f09SDavid van Moolenbroek isc_log_registercategories(log, categories);
568*00b67f09SDavid van Moolenbroek isc_log_setcontext(log);
569*00b67f09SDavid van Moolenbroek dns_log_init(log);
570*00b67f09SDavid van Moolenbroek dns_log_setcontext(log);
571*00b67f09SDavid van Moolenbroek cfg_log_init(log);
572*00b67f09SDavid van Moolenbroek
573*00b67f09SDavid van Moolenbroek destination.file.stream = errout;
574*00b67f09SDavid van Moolenbroek destination.file.name = NULL;
575*00b67f09SDavid van Moolenbroek destination.file.versions = ISC_LOG_ROLLNEVER;
576*00b67f09SDavid van Moolenbroek destination.file.maximum_size = 0;
577*00b67f09SDavid van Moolenbroek RUNTIME_CHECK(isc_log_createchannel(logconfig, "stderr",
578*00b67f09SDavid van Moolenbroek ISC_LOG_TOFILEDESC,
579*00b67f09SDavid van Moolenbroek ISC_LOG_DYNAMIC,
580*00b67f09SDavid van Moolenbroek &destination, 0) == ISC_R_SUCCESS);
581*00b67f09SDavid van Moolenbroek RUNTIME_CHECK(isc_log_usechannel(logconfig, "stderr",
582*00b67f09SDavid van Moolenbroek NULL, NULL) == ISC_R_SUCCESS);
583*00b67f09SDavid van Moolenbroek
584*00b67f09SDavid van Moolenbroek *logp = log;
585*00b67f09SDavid van Moolenbroek return (ISC_R_SUCCESS);
586*00b67f09SDavid van Moolenbroek }
587*00b67f09SDavid van Moolenbroek
588*00b67f09SDavid van Moolenbroek /*% scan the zone for oversize TTLs */
589*00b67f09SDavid van Moolenbroek static isc_result_t
check_ttls(dns_zone_t * zone,dns_ttl_t maxttl)590*00b67f09SDavid van Moolenbroek check_ttls(dns_zone_t *zone, dns_ttl_t maxttl) {
591*00b67f09SDavid van Moolenbroek isc_result_t result;
592*00b67f09SDavid van Moolenbroek dns_db_t *db = NULL;
593*00b67f09SDavid van Moolenbroek dns_dbversion_t *version = NULL;
594*00b67f09SDavid van Moolenbroek dns_dbnode_t *node = NULL;
595*00b67f09SDavid van Moolenbroek dns_dbiterator_t *dbiter = NULL;
596*00b67f09SDavid van Moolenbroek dns_rdatasetiter_t *rdsiter = NULL;
597*00b67f09SDavid van Moolenbroek dns_rdataset_t rdataset;
598*00b67f09SDavid van Moolenbroek dns_fixedname_t fname;
599*00b67f09SDavid van Moolenbroek dns_name_t *name;
600*00b67f09SDavid van Moolenbroek dns_fixedname_init(&fname);
601*00b67f09SDavid van Moolenbroek name = dns_fixedname_name(&fname);
602*00b67f09SDavid van Moolenbroek dns_rdataset_init(&rdataset);
603*00b67f09SDavid van Moolenbroek
604*00b67f09SDavid van Moolenbroek CHECK(dns_zone_getdb(zone, &db));
605*00b67f09SDavid van Moolenbroek INSIST(db != NULL);
606*00b67f09SDavid van Moolenbroek
607*00b67f09SDavid van Moolenbroek CHECK(dns_db_newversion(db, &version));
608*00b67f09SDavid van Moolenbroek CHECK(dns_db_createiterator(db, 0, &dbiter));
609*00b67f09SDavid van Moolenbroek
610*00b67f09SDavid van Moolenbroek for (result = dns_dbiterator_first(dbiter);
611*00b67f09SDavid van Moolenbroek result == ISC_R_SUCCESS;
612*00b67f09SDavid van Moolenbroek result = dns_dbiterator_next(dbiter)) {
613*00b67f09SDavid van Moolenbroek result = dns_dbiterator_current(dbiter, &node, name);
614*00b67f09SDavid van Moolenbroek if (result == DNS_R_NEWORIGIN)
615*00b67f09SDavid van Moolenbroek result = ISC_R_SUCCESS;
616*00b67f09SDavid van Moolenbroek CHECK(result);
617*00b67f09SDavid van Moolenbroek
618*00b67f09SDavid van Moolenbroek CHECK(dns_db_allrdatasets(db, node, version, 0, &rdsiter));
619*00b67f09SDavid van Moolenbroek for (result = dns_rdatasetiter_first(rdsiter);
620*00b67f09SDavid van Moolenbroek result == ISC_R_SUCCESS;
621*00b67f09SDavid van Moolenbroek result = dns_rdatasetiter_next(rdsiter)) {
622*00b67f09SDavid van Moolenbroek dns_rdatasetiter_current(rdsiter, &rdataset);
623*00b67f09SDavid van Moolenbroek if (rdataset.ttl > maxttl) {
624*00b67f09SDavid van Moolenbroek char nbuf[DNS_NAME_FORMATSIZE];
625*00b67f09SDavid van Moolenbroek char tbuf[255];
626*00b67f09SDavid van Moolenbroek isc_buffer_t b;
627*00b67f09SDavid van Moolenbroek isc_region_t r;
628*00b67f09SDavid van Moolenbroek
629*00b67f09SDavid van Moolenbroek dns_name_format(name, nbuf, sizeof(nbuf));
630*00b67f09SDavid van Moolenbroek isc_buffer_init(&b, tbuf, sizeof(tbuf) - 1);
631*00b67f09SDavid van Moolenbroek CHECK(dns_rdatatype_totext(rdataset.type, &b));
632*00b67f09SDavid van Moolenbroek isc_buffer_usedregion(&b, &r);
633*00b67f09SDavid van Moolenbroek r.base[r.length] = 0;
634*00b67f09SDavid van Moolenbroek
635*00b67f09SDavid van Moolenbroek dns_zone_log(zone, ISC_LOG_ERROR,
636*00b67f09SDavid van Moolenbroek "%s/%s TTL %d exceeds "
637*00b67f09SDavid van Moolenbroek "maximum TTL %d",
638*00b67f09SDavid van Moolenbroek nbuf, tbuf, rdataset.ttl, maxttl);
639*00b67f09SDavid van Moolenbroek dns_rdataset_disassociate(&rdataset);
640*00b67f09SDavid van Moolenbroek CHECK(ISC_R_RANGE);
641*00b67f09SDavid van Moolenbroek }
642*00b67f09SDavid van Moolenbroek dns_rdataset_disassociate(&rdataset);
643*00b67f09SDavid van Moolenbroek }
644*00b67f09SDavid van Moolenbroek if (result == ISC_R_NOMORE)
645*00b67f09SDavid van Moolenbroek result = ISC_R_SUCCESS;
646*00b67f09SDavid van Moolenbroek CHECK(result);
647*00b67f09SDavid van Moolenbroek
648*00b67f09SDavid van Moolenbroek dns_rdatasetiter_destroy(&rdsiter);
649*00b67f09SDavid van Moolenbroek dns_db_detachnode(db, &node);
650*00b67f09SDavid van Moolenbroek }
651*00b67f09SDavid van Moolenbroek
652*00b67f09SDavid van Moolenbroek if (result == ISC_R_NOMORE)
653*00b67f09SDavid van Moolenbroek result = ISC_R_SUCCESS;
654*00b67f09SDavid van Moolenbroek
655*00b67f09SDavid van Moolenbroek cleanup:
656*00b67f09SDavid van Moolenbroek if (node != NULL)
657*00b67f09SDavid van Moolenbroek dns_db_detachnode(db, &node);
658*00b67f09SDavid van Moolenbroek if (rdsiter != NULL)
659*00b67f09SDavid van Moolenbroek dns_rdatasetiter_destroy(&rdsiter);
660*00b67f09SDavid van Moolenbroek if (dbiter != NULL)
661*00b67f09SDavid van Moolenbroek dns_dbiterator_destroy(&dbiter);
662*00b67f09SDavid van Moolenbroek if (version != NULL)
663*00b67f09SDavid van Moolenbroek dns_db_closeversion(db, &version, ISC_FALSE);
664*00b67f09SDavid van Moolenbroek if (db != NULL)
665*00b67f09SDavid van Moolenbroek dns_db_detach(&db);
666*00b67f09SDavid van Moolenbroek
667*00b67f09SDavid van Moolenbroek return (result);
668*00b67f09SDavid van Moolenbroek }
669*00b67f09SDavid van Moolenbroek
670*00b67f09SDavid van Moolenbroek /*% load the zone */
671*00b67f09SDavid van Moolenbroek isc_result_t
load_zone(isc_mem_t * mctx,const char * zonename,const char * filename,dns_masterformat_t fileformat,const char * classname,dns_ttl_t maxttl,dns_zone_t ** zonep)672*00b67f09SDavid van Moolenbroek load_zone(isc_mem_t *mctx, const char *zonename, const char *filename,
673*00b67f09SDavid van Moolenbroek dns_masterformat_t fileformat, const char *classname,
674*00b67f09SDavid van Moolenbroek dns_ttl_t maxttl, dns_zone_t **zonep)
675*00b67f09SDavid van Moolenbroek {
676*00b67f09SDavid van Moolenbroek isc_result_t result;
677*00b67f09SDavid van Moolenbroek dns_rdataclass_t rdclass;
678*00b67f09SDavid van Moolenbroek isc_textregion_t region;
679*00b67f09SDavid van Moolenbroek isc_buffer_t buffer;
680*00b67f09SDavid van Moolenbroek dns_fixedname_t fixorigin;
681*00b67f09SDavid van Moolenbroek dns_name_t *origin;
682*00b67f09SDavid van Moolenbroek dns_zone_t *zone = NULL;
683*00b67f09SDavid van Moolenbroek
684*00b67f09SDavid van Moolenbroek REQUIRE(zonep == NULL || *zonep == NULL);
685*00b67f09SDavid van Moolenbroek
686*00b67f09SDavid van Moolenbroek if (debug)
687*00b67f09SDavid van Moolenbroek fprintf(stderr, "loading \"%s\" from \"%s\" class \"%s\"\n",
688*00b67f09SDavid van Moolenbroek zonename, filename, classname);
689*00b67f09SDavid van Moolenbroek
690*00b67f09SDavid van Moolenbroek CHECK(dns_zone_create(&zone, mctx));
691*00b67f09SDavid van Moolenbroek
692*00b67f09SDavid van Moolenbroek dns_zone_settype(zone, dns_zone_master);
693*00b67f09SDavid van Moolenbroek
694*00b67f09SDavid van Moolenbroek isc_buffer_constinit(&buffer, zonename, strlen(zonename));
695*00b67f09SDavid van Moolenbroek isc_buffer_add(&buffer, strlen(zonename));
696*00b67f09SDavid van Moolenbroek dns_fixedname_init(&fixorigin);
697*00b67f09SDavid van Moolenbroek origin = dns_fixedname_name(&fixorigin);
698*00b67f09SDavid van Moolenbroek CHECK(dns_name_fromtext(origin, &buffer, dns_rootname, 0, NULL));
699*00b67f09SDavid van Moolenbroek CHECK(dns_zone_setorigin(zone, origin));
700*00b67f09SDavid van Moolenbroek CHECK(dns_zone_setdbtype(zone, 1, (const char * const *) dbtype));
701*00b67f09SDavid van Moolenbroek CHECK(dns_zone_setfile2(zone, filename, fileformat));
702*00b67f09SDavid van Moolenbroek if (journal != NULL)
703*00b67f09SDavid van Moolenbroek CHECK(dns_zone_setjournal(zone, journal));
704*00b67f09SDavid van Moolenbroek
705*00b67f09SDavid van Moolenbroek DE_CONST(classname, region.base);
706*00b67f09SDavid van Moolenbroek region.length = strlen(classname);
707*00b67f09SDavid van Moolenbroek CHECK(dns_rdataclass_fromtext(&rdclass, ®ion));
708*00b67f09SDavid van Moolenbroek
709*00b67f09SDavid van Moolenbroek dns_zone_setclass(zone, rdclass);
710*00b67f09SDavid van Moolenbroek dns_zone_setoption(zone, zone_options, ISC_TRUE);
711*00b67f09SDavid van Moolenbroek dns_zone_setoption2(zone, zone_options2, ISC_TRUE);
712*00b67f09SDavid van Moolenbroek dns_zone_setoption(zone, DNS_ZONEOPT_NOMERGE, nomerge);
713*00b67f09SDavid van Moolenbroek
714*00b67f09SDavid van Moolenbroek dns_zone_setmaxttl(zone, maxttl);
715*00b67f09SDavid van Moolenbroek
716*00b67f09SDavid van Moolenbroek if (docheckmx)
717*00b67f09SDavid van Moolenbroek dns_zone_setcheckmx(zone, checkmx);
718*00b67f09SDavid van Moolenbroek if (docheckns)
719*00b67f09SDavid van Moolenbroek dns_zone_setcheckns(zone, checkns);
720*00b67f09SDavid van Moolenbroek if (dochecksrv)
721*00b67f09SDavid van Moolenbroek dns_zone_setchecksrv(zone, checksrv);
722*00b67f09SDavid van Moolenbroek
723*00b67f09SDavid van Moolenbroek CHECK(dns_zone_load(zone));
724*00b67f09SDavid van Moolenbroek
725*00b67f09SDavid van Moolenbroek /*
726*00b67f09SDavid van Moolenbroek * When loading map files we can't catch oversize TTLs during
727*00b67f09SDavid van Moolenbroek * load, so we check for them here.
728*00b67f09SDavid van Moolenbroek */
729*00b67f09SDavid van Moolenbroek if (fileformat == dns_masterformat_map && maxttl != 0) {
730*00b67f09SDavid van Moolenbroek CHECK(check_ttls(zone, maxttl));
731*00b67f09SDavid van Moolenbroek }
732*00b67f09SDavid van Moolenbroek
733*00b67f09SDavid van Moolenbroek if (zonep != NULL) {
734*00b67f09SDavid van Moolenbroek *zonep = zone;
735*00b67f09SDavid van Moolenbroek zone = NULL;
736*00b67f09SDavid van Moolenbroek }
737*00b67f09SDavid van Moolenbroek
738*00b67f09SDavid van Moolenbroek cleanup:
739*00b67f09SDavid van Moolenbroek if (zone != NULL)
740*00b67f09SDavid van Moolenbroek dns_zone_detach(&zone);
741*00b67f09SDavid van Moolenbroek return (result);
742*00b67f09SDavid van Moolenbroek }
743*00b67f09SDavid van Moolenbroek
744*00b67f09SDavid van Moolenbroek /*% dump the zone */
745*00b67f09SDavid van Moolenbroek isc_result_t
dump_zone(const char * zonename,dns_zone_t * zone,const char * filename,dns_masterformat_t fileformat,const dns_master_style_t * style,const isc_uint32_t rawversion)746*00b67f09SDavid van Moolenbroek dump_zone(const char *zonename, dns_zone_t *zone, const char *filename,
747*00b67f09SDavid van Moolenbroek dns_masterformat_t fileformat, const dns_master_style_t *style,
748*00b67f09SDavid van Moolenbroek const isc_uint32_t rawversion)
749*00b67f09SDavid van Moolenbroek {
750*00b67f09SDavid van Moolenbroek isc_result_t result;
751*00b67f09SDavid van Moolenbroek FILE *output = stdout;
752*00b67f09SDavid van Moolenbroek const char *flags;
753*00b67f09SDavid van Moolenbroek
754*00b67f09SDavid van Moolenbroek flags = (fileformat == dns_masterformat_text) ? "w+" : "wb+";
755*00b67f09SDavid van Moolenbroek
756*00b67f09SDavid van Moolenbroek if (debug) {
757*00b67f09SDavid van Moolenbroek if (filename != NULL && strcmp(filename, "-") != 0)
758*00b67f09SDavid van Moolenbroek fprintf(stderr, "dumping \"%s\" to \"%s\"\n",
759*00b67f09SDavid van Moolenbroek zonename, filename);
760*00b67f09SDavid van Moolenbroek else
761*00b67f09SDavid van Moolenbroek fprintf(stderr, "dumping \"%s\"\n", zonename);
762*00b67f09SDavid van Moolenbroek }
763*00b67f09SDavid van Moolenbroek
764*00b67f09SDavid van Moolenbroek if (filename != NULL && strcmp(filename, "-") != 0) {
765*00b67f09SDavid van Moolenbroek result = isc_stdio_open(filename, flags, &output);
766*00b67f09SDavid van Moolenbroek
767*00b67f09SDavid van Moolenbroek if (result != ISC_R_SUCCESS) {
768*00b67f09SDavid van Moolenbroek fprintf(stderr, "could not open output "
769*00b67f09SDavid van Moolenbroek "file \"%s\" for writing\n", filename);
770*00b67f09SDavid van Moolenbroek return (ISC_R_FAILURE);
771*00b67f09SDavid van Moolenbroek }
772*00b67f09SDavid van Moolenbroek }
773*00b67f09SDavid van Moolenbroek
774*00b67f09SDavid van Moolenbroek result = dns_zone_dumptostream3(zone, output, fileformat, style,
775*00b67f09SDavid van Moolenbroek rawversion);
776*00b67f09SDavid van Moolenbroek if (output != stdout)
777*00b67f09SDavid van Moolenbroek (void)isc_stdio_close(output);
778*00b67f09SDavid van Moolenbroek
779*00b67f09SDavid van Moolenbroek return (result);
780*00b67f09SDavid van Moolenbroek }
781*00b67f09SDavid van Moolenbroek
782*00b67f09SDavid van Moolenbroek #ifdef _WIN32
783*00b67f09SDavid van Moolenbroek void
InitSockets(void)784*00b67f09SDavid van Moolenbroek InitSockets(void) {
785*00b67f09SDavid van Moolenbroek WORD wVersionRequested;
786*00b67f09SDavid van Moolenbroek WSADATA wsaData;
787*00b67f09SDavid van Moolenbroek int err;
788*00b67f09SDavid van Moolenbroek
789*00b67f09SDavid van Moolenbroek wVersionRequested = MAKEWORD(2, 0);
790*00b67f09SDavid van Moolenbroek
791*00b67f09SDavid van Moolenbroek err = WSAStartup( wVersionRequested, &wsaData );
792*00b67f09SDavid van Moolenbroek if (err != 0) {
793*00b67f09SDavid van Moolenbroek fprintf(stderr, "WSAStartup() failed: %d\n", err);
794*00b67f09SDavid van Moolenbroek exit(1);
795*00b67f09SDavid van Moolenbroek }
796*00b67f09SDavid van Moolenbroek }
797*00b67f09SDavid van Moolenbroek
798*00b67f09SDavid van Moolenbroek void
DestroySockets(void)799*00b67f09SDavid van Moolenbroek DestroySockets(void) {
800*00b67f09SDavid van Moolenbroek WSACleanup();
801*00b67f09SDavid van Moolenbroek }
802*00b67f09SDavid van Moolenbroek #endif
803*00b67f09SDavid van Moolenbroek
804