1*00b67f09SDavid van Moolenbroek /* $NetBSD: masterdump.c,v 1.11 2015/07/08 17:28:58 christos Exp $ */
2*00b67f09SDavid van Moolenbroek
3*00b67f09SDavid van Moolenbroek /*
4*00b67f09SDavid van Moolenbroek * Copyright (C) 2004-2009, 2011-2015 Internet Systems Consortium, Inc. ("ISC")
5*00b67f09SDavid van Moolenbroek * Copyright (C) 1999-2003 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 */
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 <stdlib.h>
27*00b67f09SDavid van Moolenbroek
28*00b67f09SDavid van Moolenbroek #include <isc/event.h>
29*00b67f09SDavid van Moolenbroek #include <isc/file.h>
30*00b67f09SDavid van Moolenbroek #include <isc/magic.h>
31*00b67f09SDavid van Moolenbroek #include <isc/mem.h>
32*00b67f09SDavid van Moolenbroek #include <isc/print.h>
33*00b67f09SDavid van Moolenbroek #include <isc/stdio.h>
34*00b67f09SDavid van Moolenbroek #include <isc/string.h>
35*00b67f09SDavid van Moolenbroek #include <isc/task.h>
36*00b67f09SDavid van Moolenbroek #include <isc/time.h>
37*00b67f09SDavid van Moolenbroek #include <isc/util.h>
38*00b67f09SDavid van Moolenbroek
39*00b67f09SDavid van Moolenbroek #include <dns/db.h>
40*00b67f09SDavid van Moolenbroek #include <dns/dbiterator.h>
41*00b67f09SDavid van Moolenbroek #include <dns/events.h>
42*00b67f09SDavid van Moolenbroek #include <dns/fixedname.h>
43*00b67f09SDavid van Moolenbroek #include <dns/lib.h>
44*00b67f09SDavid van Moolenbroek #include <dns/log.h>
45*00b67f09SDavid van Moolenbroek #include <dns/master.h>
46*00b67f09SDavid van Moolenbroek #include <dns/masterdump.h>
47*00b67f09SDavid van Moolenbroek #include <dns/ncache.h>
48*00b67f09SDavid van Moolenbroek #include <dns/rdata.h>
49*00b67f09SDavid van Moolenbroek #include <dns/rdataclass.h>
50*00b67f09SDavid van Moolenbroek #include <dns/rdataset.h>
51*00b67f09SDavid van Moolenbroek #include <dns/rdatasetiter.h>
52*00b67f09SDavid van Moolenbroek #include <dns/rdatatype.h>
53*00b67f09SDavid van Moolenbroek #include <dns/result.h>
54*00b67f09SDavid van Moolenbroek #include <dns/time.h>
55*00b67f09SDavid van Moolenbroek #include <dns/ttl.h>
56*00b67f09SDavid van Moolenbroek
57*00b67f09SDavid van Moolenbroek #define DNS_DCTX_MAGIC ISC_MAGIC('D', 'c', 't', 'x')
58*00b67f09SDavid van Moolenbroek #define DNS_DCTX_VALID(d) ISC_MAGIC_VALID(d, DNS_DCTX_MAGIC)
59*00b67f09SDavid van Moolenbroek
60*00b67f09SDavid van Moolenbroek #define RETERR(x) do { \
61*00b67f09SDavid van Moolenbroek isc_result_t _r = (x); \
62*00b67f09SDavid van Moolenbroek if (_r != ISC_R_SUCCESS) \
63*00b67f09SDavid van Moolenbroek return (_r); \
64*00b67f09SDavid van Moolenbroek } while (/*CONSTCOND*/0)
65*00b67f09SDavid van Moolenbroek
66*00b67f09SDavid van Moolenbroek #define CHECK(x) do { \
67*00b67f09SDavid van Moolenbroek if ((x) != ISC_R_SUCCESS) \
68*00b67f09SDavid van Moolenbroek goto cleanup; \
69*00b67f09SDavid van Moolenbroek } while (/*CONSTCOND*/0)
70*00b67f09SDavid van Moolenbroek
71*00b67f09SDavid van Moolenbroek struct dns_master_style {
72*00b67f09SDavid van Moolenbroek unsigned int flags; /* DNS_STYLEFLAG_* */
73*00b67f09SDavid van Moolenbroek unsigned int ttl_column;
74*00b67f09SDavid van Moolenbroek unsigned int class_column;
75*00b67f09SDavid van Moolenbroek unsigned int type_column;
76*00b67f09SDavid van Moolenbroek unsigned int rdata_column;
77*00b67f09SDavid van Moolenbroek unsigned int line_length;
78*00b67f09SDavid van Moolenbroek unsigned int tab_width;
79*00b67f09SDavid van Moolenbroek unsigned int split_width;
80*00b67f09SDavid van Moolenbroek };
81*00b67f09SDavid van Moolenbroek
82*00b67f09SDavid van Moolenbroek /*%
83*00b67f09SDavid van Moolenbroek * The maximum length of the newline+indentation that is output
84*00b67f09SDavid van Moolenbroek * when inserting a line break in an RR. This effectively puts an
85*00b67f09SDavid van Moolenbroek * upper limits on the value of "rdata_column", because if it is
86*00b67f09SDavid van Moolenbroek * very large, the tabs and spaces needed to reach it will not fit.
87*00b67f09SDavid van Moolenbroek */
88*00b67f09SDavid van Moolenbroek #define DNS_TOTEXT_LINEBREAK_MAXLEN 100
89*00b67f09SDavid van Moolenbroek
90*00b67f09SDavid van Moolenbroek /*%
91*00b67f09SDavid van Moolenbroek * Context structure for a masterfile dump in progress.
92*00b67f09SDavid van Moolenbroek */
93*00b67f09SDavid van Moolenbroek typedef struct dns_totext_ctx {
94*00b67f09SDavid van Moolenbroek dns_master_style_t style;
95*00b67f09SDavid van Moolenbroek isc_boolean_t class_printed;
96*00b67f09SDavid van Moolenbroek char * linebreak;
97*00b67f09SDavid van Moolenbroek char linebreak_buf[DNS_TOTEXT_LINEBREAK_MAXLEN];
98*00b67f09SDavid van Moolenbroek dns_name_t * origin;
99*00b67f09SDavid van Moolenbroek dns_name_t * neworigin;
100*00b67f09SDavid van Moolenbroek dns_fixedname_t origin_fixname;
101*00b67f09SDavid van Moolenbroek isc_uint32_t current_ttl;
102*00b67f09SDavid van Moolenbroek isc_boolean_t current_ttl_valid;
103*00b67f09SDavid van Moolenbroek } dns_totext_ctx_t;
104*00b67f09SDavid van Moolenbroek
105*00b67f09SDavid van Moolenbroek LIBDNS_EXTERNAL_DATA const dns_master_style_t
106*00b67f09SDavid van Moolenbroek dns_master_style_keyzone = {
107*00b67f09SDavid van Moolenbroek DNS_STYLEFLAG_OMIT_OWNER |
108*00b67f09SDavid van Moolenbroek DNS_STYLEFLAG_OMIT_CLASS |
109*00b67f09SDavid van Moolenbroek DNS_STYLEFLAG_REL_OWNER |
110*00b67f09SDavid van Moolenbroek DNS_STYLEFLAG_REL_DATA |
111*00b67f09SDavid van Moolenbroek DNS_STYLEFLAG_OMIT_TTL |
112*00b67f09SDavid van Moolenbroek DNS_STYLEFLAG_TTL |
113*00b67f09SDavid van Moolenbroek DNS_STYLEFLAG_COMMENT |
114*00b67f09SDavid van Moolenbroek DNS_STYLEFLAG_RRCOMMENT |
115*00b67f09SDavid van Moolenbroek DNS_STYLEFLAG_MULTILINE |
116*00b67f09SDavid van Moolenbroek DNS_STYLEFLAG_KEYDATA,
117*00b67f09SDavid van Moolenbroek 24, 24, 24, 32, 80, 8, UINT_MAX
118*00b67f09SDavid van Moolenbroek };
119*00b67f09SDavid van Moolenbroek
120*00b67f09SDavid van Moolenbroek LIBDNS_EXTERNAL_DATA const dns_master_style_t
121*00b67f09SDavid van Moolenbroek dns_master_style_default = {
122*00b67f09SDavid van Moolenbroek DNS_STYLEFLAG_OMIT_OWNER |
123*00b67f09SDavid van Moolenbroek DNS_STYLEFLAG_OMIT_CLASS |
124*00b67f09SDavid van Moolenbroek DNS_STYLEFLAG_REL_OWNER |
125*00b67f09SDavid van Moolenbroek DNS_STYLEFLAG_REL_DATA |
126*00b67f09SDavid van Moolenbroek DNS_STYLEFLAG_OMIT_TTL |
127*00b67f09SDavid van Moolenbroek DNS_STYLEFLAG_TTL |
128*00b67f09SDavid van Moolenbroek DNS_STYLEFLAG_COMMENT |
129*00b67f09SDavid van Moolenbroek DNS_STYLEFLAG_RRCOMMENT |
130*00b67f09SDavid van Moolenbroek DNS_STYLEFLAG_MULTILINE,
131*00b67f09SDavid van Moolenbroek 24, 24, 24, 32, 80, 8, UINT_MAX
132*00b67f09SDavid van Moolenbroek };
133*00b67f09SDavid van Moolenbroek
134*00b67f09SDavid van Moolenbroek LIBDNS_EXTERNAL_DATA const dns_master_style_t
135*00b67f09SDavid van Moolenbroek dns_master_style_full = {
136*00b67f09SDavid van Moolenbroek DNS_STYLEFLAG_COMMENT |
137*00b67f09SDavid van Moolenbroek DNS_STYLEFLAG_RESIGN,
138*00b67f09SDavid van Moolenbroek 46, 46, 46, 64, 120, 8, UINT_MAX
139*00b67f09SDavid van Moolenbroek };
140*00b67f09SDavid van Moolenbroek
141*00b67f09SDavid van Moolenbroek LIBDNS_EXTERNAL_DATA const dns_master_style_t
142*00b67f09SDavid van Moolenbroek dns_master_style_explicitttl = {
143*00b67f09SDavid van Moolenbroek DNS_STYLEFLAG_OMIT_OWNER |
144*00b67f09SDavid van Moolenbroek DNS_STYLEFLAG_OMIT_CLASS |
145*00b67f09SDavid van Moolenbroek DNS_STYLEFLAG_REL_OWNER |
146*00b67f09SDavid van Moolenbroek DNS_STYLEFLAG_REL_DATA |
147*00b67f09SDavid van Moolenbroek DNS_STYLEFLAG_COMMENT |
148*00b67f09SDavid van Moolenbroek DNS_STYLEFLAG_RRCOMMENT |
149*00b67f09SDavid van Moolenbroek DNS_STYLEFLAG_MULTILINE,
150*00b67f09SDavid van Moolenbroek 24, 32, 32, 40, 80, 8, UINT_MAX
151*00b67f09SDavid van Moolenbroek };
152*00b67f09SDavid van Moolenbroek
153*00b67f09SDavid van Moolenbroek LIBDNS_EXTERNAL_DATA const dns_master_style_t
154*00b67f09SDavid van Moolenbroek dns_master_style_cache = {
155*00b67f09SDavid van Moolenbroek DNS_STYLEFLAG_OMIT_OWNER |
156*00b67f09SDavid van Moolenbroek DNS_STYLEFLAG_OMIT_CLASS |
157*00b67f09SDavid van Moolenbroek DNS_STYLEFLAG_MULTILINE |
158*00b67f09SDavid van Moolenbroek DNS_STYLEFLAG_RRCOMMENT |
159*00b67f09SDavid van Moolenbroek DNS_STYLEFLAG_TRUST |
160*00b67f09SDavid van Moolenbroek DNS_STYLEFLAG_NCACHE,
161*00b67f09SDavid van Moolenbroek 24, 32, 32, 40, 80, 8, UINT_MAX
162*00b67f09SDavid van Moolenbroek };
163*00b67f09SDavid van Moolenbroek
164*00b67f09SDavid van Moolenbroek LIBDNS_EXTERNAL_DATA const dns_master_style_t
165*00b67f09SDavid van Moolenbroek dns_master_style_simple = {
166*00b67f09SDavid van Moolenbroek 0,
167*00b67f09SDavid van Moolenbroek 24, 32, 32, 40, 80, 8, UINT_MAX
168*00b67f09SDavid van Moolenbroek };
169*00b67f09SDavid van Moolenbroek
170*00b67f09SDavid van Moolenbroek /*%
171*00b67f09SDavid van Moolenbroek * A style suitable for dns_rdataset_totext().
172*00b67f09SDavid van Moolenbroek */
173*00b67f09SDavid van Moolenbroek LIBDNS_EXTERNAL_DATA const dns_master_style_t
174*00b67f09SDavid van Moolenbroek dns_master_style_debug = {
175*00b67f09SDavid van Moolenbroek DNS_STYLEFLAG_REL_OWNER,
176*00b67f09SDavid van Moolenbroek 24, 32, 40, 48, 80, 8, UINT_MAX
177*00b67f09SDavid van Moolenbroek };
178*00b67f09SDavid van Moolenbroek
179*00b67f09SDavid van Moolenbroek /*%
180*00b67f09SDavid van Moolenbroek * Similar, but with each line commented out.
181*00b67f09SDavid van Moolenbroek */
182*00b67f09SDavid van Moolenbroek LIBDNS_EXTERNAL_DATA const dns_master_style_t
183*00b67f09SDavid van Moolenbroek dns_master_style_comment = {
184*00b67f09SDavid van Moolenbroek DNS_STYLEFLAG_REL_OWNER |
185*00b67f09SDavid van Moolenbroek DNS_STYLEFLAG_MULTILINE |
186*00b67f09SDavid van Moolenbroek DNS_STYLEFLAG_RRCOMMENT |
187*00b67f09SDavid van Moolenbroek DNS_STYLEFLAG_COMMENTDATA,
188*00b67f09SDavid van Moolenbroek 24, 32, 40, 48, 80, 8, UINT_MAX
189*00b67f09SDavid van Moolenbroek };
190*00b67f09SDavid van Moolenbroek
191*00b67f09SDavid van Moolenbroek
192*00b67f09SDavid van Moolenbroek #define N_SPACES 10
193*00b67f09SDavid van Moolenbroek static char spaces[N_SPACES+1] = " ";
194*00b67f09SDavid van Moolenbroek
195*00b67f09SDavid van Moolenbroek #define N_TABS 10
196*00b67f09SDavid van Moolenbroek static char tabs[N_TABS+1] = "\t\t\t\t\t\t\t\t\t\t";
197*00b67f09SDavid van Moolenbroek
198*00b67f09SDavid van Moolenbroek struct dns_dumpctx {
199*00b67f09SDavid van Moolenbroek unsigned int magic;
200*00b67f09SDavid van Moolenbroek isc_mem_t *mctx;
201*00b67f09SDavid van Moolenbroek isc_mutex_t lock;
202*00b67f09SDavid van Moolenbroek unsigned int references;
203*00b67f09SDavid van Moolenbroek isc_boolean_t canceled;
204*00b67f09SDavid van Moolenbroek isc_boolean_t first;
205*00b67f09SDavid van Moolenbroek isc_boolean_t do_date;
206*00b67f09SDavid van Moolenbroek isc_stdtime_t now;
207*00b67f09SDavid van Moolenbroek FILE *f;
208*00b67f09SDavid van Moolenbroek dns_db_t *db;
209*00b67f09SDavid van Moolenbroek dns_dbversion_t *version;
210*00b67f09SDavid van Moolenbroek dns_dbiterator_t *dbiter;
211*00b67f09SDavid van Moolenbroek dns_totext_ctx_t tctx;
212*00b67f09SDavid van Moolenbroek isc_task_t *task;
213*00b67f09SDavid van Moolenbroek dns_dumpdonefunc_t done;
214*00b67f09SDavid van Moolenbroek void *done_arg;
215*00b67f09SDavid van Moolenbroek unsigned int nodes;
216*00b67f09SDavid van Moolenbroek /* dns_master_dumpinc() */
217*00b67f09SDavid van Moolenbroek char *file;
218*00b67f09SDavid van Moolenbroek char *tmpfile;
219*00b67f09SDavid van Moolenbroek dns_masterformat_t format;
220*00b67f09SDavid van Moolenbroek dns_masterrawheader_t header;
221*00b67f09SDavid van Moolenbroek isc_result_t (*dumpsets)(isc_mem_t *mctx, dns_name_t *name,
222*00b67f09SDavid van Moolenbroek dns_rdatasetiter_t *rdsiter,
223*00b67f09SDavid van Moolenbroek dns_totext_ctx_t *ctx,
224*00b67f09SDavid van Moolenbroek isc_buffer_t *buffer, FILE *f);
225*00b67f09SDavid van Moolenbroek };
226*00b67f09SDavid van Moolenbroek
227*00b67f09SDavid van Moolenbroek #define NXDOMAIN(x) (((x)->attributes & DNS_RDATASETATTR_NXDOMAIN) != 0)
228*00b67f09SDavid van Moolenbroek
229*00b67f09SDavid van Moolenbroek /*%
230*00b67f09SDavid van Moolenbroek * Output tabs and spaces to go from column '*current' to
231*00b67f09SDavid van Moolenbroek * column 'to', and update '*current' to reflect the new
232*00b67f09SDavid van Moolenbroek * current column.
233*00b67f09SDavid van Moolenbroek */
234*00b67f09SDavid van Moolenbroek static isc_result_t
indent(unsigned int * current,unsigned int to,int tabwidth,isc_buffer_t * target)235*00b67f09SDavid van Moolenbroek indent(unsigned int *current, unsigned int to, int tabwidth,
236*00b67f09SDavid van Moolenbroek isc_buffer_t *target)
237*00b67f09SDavid van Moolenbroek {
238*00b67f09SDavid van Moolenbroek isc_region_t r;
239*00b67f09SDavid van Moolenbroek unsigned char *p;
240*00b67f09SDavid van Moolenbroek unsigned int from;
241*00b67f09SDavid van Moolenbroek int ntabs, nspaces, t;
242*00b67f09SDavid van Moolenbroek
243*00b67f09SDavid van Moolenbroek from = *current;
244*00b67f09SDavid van Moolenbroek
245*00b67f09SDavid van Moolenbroek if (to < from + 1)
246*00b67f09SDavid van Moolenbroek to = from + 1;
247*00b67f09SDavid van Moolenbroek
248*00b67f09SDavid van Moolenbroek ntabs = to / tabwidth - from / tabwidth;
249*00b67f09SDavid van Moolenbroek if (ntabs < 0)
250*00b67f09SDavid van Moolenbroek ntabs = 0;
251*00b67f09SDavid van Moolenbroek
252*00b67f09SDavid van Moolenbroek if (ntabs > 0) {
253*00b67f09SDavid van Moolenbroek isc_buffer_availableregion(target, &r);
254*00b67f09SDavid van Moolenbroek if (r.length < (unsigned) ntabs)
255*00b67f09SDavid van Moolenbroek return (ISC_R_NOSPACE);
256*00b67f09SDavid van Moolenbroek p = r.base;
257*00b67f09SDavid van Moolenbroek
258*00b67f09SDavid van Moolenbroek t = ntabs;
259*00b67f09SDavid van Moolenbroek while (t) {
260*00b67f09SDavid van Moolenbroek int n = t;
261*00b67f09SDavid van Moolenbroek if (n > N_TABS)
262*00b67f09SDavid van Moolenbroek n = N_TABS;
263*00b67f09SDavid van Moolenbroek memmove(p, tabs, n);
264*00b67f09SDavid van Moolenbroek p += n;
265*00b67f09SDavid van Moolenbroek t -= n;
266*00b67f09SDavid van Moolenbroek }
267*00b67f09SDavid van Moolenbroek isc_buffer_add(target, ntabs);
268*00b67f09SDavid van Moolenbroek from = (to / tabwidth) * tabwidth;
269*00b67f09SDavid van Moolenbroek }
270*00b67f09SDavid van Moolenbroek
271*00b67f09SDavid van Moolenbroek nspaces = to - from;
272*00b67f09SDavid van Moolenbroek INSIST(nspaces >= 0);
273*00b67f09SDavid van Moolenbroek
274*00b67f09SDavid van Moolenbroek isc_buffer_availableregion(target, &r);
275*00b67f09SDavid van Moolenbroek if (r.length < (unsigned) nspaces)
276*00b67f09SDavid van Moolenbroek return (ISC_R_NOSPACE);
277*00b67f09SDavid van Moolenbroek p = r.base;
278*00b67f09SDavid van Moolenbroek
279*00b67f09SDavid van Moolenbroek t = nspaces;
280*00b67f09SDavid van Moolenbroek while (t) {
281*00b67f09SDavid van Moolenbroek int n = t;
282*00b67f09SDavid van Moolenbroek if (n > N_SPACES)
283*00b67f09SDavid van Moolenbroek n = N_SPACES;
284*00b67f09SDavid van Moolenbroek memmove(p, spaces, n);
285*00b67f09SDavid van Moolenbroek p += n;
286*00b67f09SDavid van Moolenbroek t -= n;
287*00b67f09SDavid van Moolenbroek }
288*00b67f09SDavid van Moolenbroek isc_buffer_add(target, nspaces);
289*00b67f09SDavid van Moolenbroek
290*00b67f09SDavid van Moolenbroek *current = to;
291*00b67f09SDavid van Moolenbroek return (ISC_R_SUCCESS);
292*00b67f09SDavid van Moolenbroek }
293*00b67f09SDavid van Moolenbroek
294*00b67f09SDavid van Moolenbroek static isc_result_t
totext_ctx_init(const dns_master_style_t * style,dns_totext_ctx_t * ctx)295*00b67f09SDavid van Moolenbroek totext_ctx_init(const dns_master_style_t *style, dns_totext_ctx_t *ctx) {
296*00b67f09SDavid van Moolenbroek isc_result_t result;
297*00b67f09SDavid van Moolenbroek
298*00b67f09SDavid van Moolenbroek REQUIRE(style->tab_width != 0);
299*00b67f09SDavid van Moolenbroek
300*00b67f09SDavid van Moolenbroek ctx->style = *style;
301*00b67f09SDavid van Moolenbroek ctx->class_printed = ISC_FALSE;
302*00b67f09SDavid van Moolenbroek
303*00b67f09SDavid van Moolenbroek dns_fixedname_init(&ctx->origin_fixname);
304*00b67f09SDavid van Moolenbroek
305*00b67f09SDavid van Moolenbroek /*
306*00b67f09SDavid van Moolenbroek * Set up the line break string if needed.
307*00b67f09SDavid van Moolenbroek */
308*00b67f09SDavid van Moolenbroek if ((ctx->style.flags & DNS_STYLEFLAG_MULTILINE) != 0) {
309*00b67f09SDavid van Moolenbroek isc_buffer_t buf;
310*00b67f09SDavid van Moolenbroek isc_region_t r;
311*00b67f09SDavid van Moolenbroek unsigned int col = 0;
312*00b67f09SDavid van Moolenbroek
313*00b67f09SDavid van Moolenbroek isc_buffer_init(&buf, ctx->linebreak_buf,
314*00b67f09SDavid van Moolenbroek sizeof(ctx->linebreak_buf));
315*00b67f09SDavid van Moolenbroek
316*00b67f09SDavid van Moolenbroek isc_buffer_availableregion(&buf, &r);
317*00b67f09SDavid van Moolenbroek if (r.length < 1)
318*00b67f09SDavid van Moolenbroek return (DNS_R_TEXTTOOLONG);
319*00b67f09SDavid van Moolenbroek r.base[0] = '\n';
320*00b67f09SDavid van Moolenbroek isc_buffer_add(&buf, 1);
321*00b67f09SDavid van Moolenbroek
322*00b67f09SDavid van Moolenbroek if ((ctx->style.flags & DNS_STYLEFLAG_COMMENTDATA) != 0) {
323*00b67f09SDavid van Moolenbroek isc_buffer_availableregion(&buf, &r);
324*00b67f09SDavid van Moolenbroek if (r.length < 1)
325*00b67f09SDavid van Moolenbroek return (DNS_R_TEXTTOOLONG);
326*00b67f09SDavid van Moolenbroek r.base[0] = ';';
327*00b67f09SDavid van Moolenbroek isc_buffer_add(&buf, 1);
328*00b67f09SDavid van Moolenbroek }
329*00b67f09SDavid van Moolenbroek
330*00b67f09SDavid van Moolenbroek result = indent(&col, ctx->style.rdata_column,
331*00b67f09SDavid van Moolenbroek ctx->style.tab_width, &buf);
332*00b67f09SDavid van Moolenbroek /*
333*00b67f09SDavid van Moolenbroek * Do not return ISC_R_NOSPACE if the line break string
334*00b67f09SDavid van Moolenbroek * buffer is too small, because that would just make
335*00b67f09SDavid van Moolenbroek * dump_rdataset() retry indefinitely with ever
336*00b67f09SDavid van Moolenbroek * bigger target buffers. That's a different buffer,
337*00b67f09SDavid van Moolenbroek * so it won't help. Use DNS_R_TEXTTOOLONG as a substitute.
338*00b67f09SDavid van Moolenbroek */
339*00b67f09SDavid van Moolenbroek if (result == ISC_R_NOSPACE)
340*00b67f09SDavid van Moolenbroek return (DNS_R_TEXTTOOLONG);
341*00b67f09SDavid van Moolenbroek if (result != ISC_R_SUCCESS)
342*00b67f09SDavid van Moolenbroek return (result);
343*00b67f09SDavid van Moolenbroek
344*00b67f09SDavid van Moolenbroek isc_buffer_availableregion(&buf, &r);
345*00b67f09SDavid van Moolenbroek if (r.length < 1)
346*00b67f09SDavid van Moolenbroek return (DNS_R_TEXTTOOLONG);
347*00b67f09SDavid van Moolenbroek r.base[0] = '\0';
348*00b67f09SDavid van Moolenbroek isc_buffer_add(&buf, 1);
349*00b67f09SDavid van Moolenbroek ctx->linebreak = ctx->linebreak_buf;
350*00b67f09SDavid van Moolenbroek } else {
351*00b67f09SDavid van Moolenbroek ctx->linebreak = NULL;
352*00b67f09SDavid van Moolenbroek }
353*00b67f09SDavid van Moolenbroek
354*00b67f09SDavid van Moolenbroek ctx->origin = NULL;
355*00b67f09SDavid van Moolenbroek ctx->neworigin = NULL;
356*00b67f09SDavid van Moolenbroek ctx->current_ttl = 0;
357*00b67f09SDavid van Moolenbroek ctx->current_ttl_valid = ISC_FALSE;
358*00b67f09SDavid van Moolenbroek
359*00b67f09SDavid van Moolenbroek return (ISC_R_SUCCESS);
360*00b67f09SDavid van Moolenbroek }
361*00b67f09SDavid van Moolenbroek
362*00b67f09SDavid van Moolenbroek #define INDENT_TO(col) \
363*00b67f09SDavid van Moolenbroek do { \
364*00b67f09SDavid van Moolenbroek if ((result = indent(&column, ctx->style.col, \
365*00b67f09SDavid van Moolenbroek ctx->style.tab_width, target)) \
366*00b67f09SDavid van Moolenbroek != ISC_R_SUCCESS) \
367*00b67f09SDavid van Moolenbroek return (result); \
368*00b67f09SDavid van Moolenbroek } while (/*CONSTCOND*/0)
369*00b67f09SDavid van Moolenbroek
370*00b67f09SDavid van Moolenbroek
371*00b67f09SDavid van Moolenbroek static isc_result_t
str_totext(const char * source,isc_buffer_t * target)372*00b67f09SDavid van Moolenbroek str_totext(const char *source, isc_buffer_t *target) {
373*00b67f09SDavid van Moolenbroek unsigned int l;
374*00b67f09SDavid van Moolenbroek isc_region_t region;
375*00b67f09SDavid van Moolenbroek
376*00b67f09SDavid van Moolenbroek isc_buffer_availableregion(target, ®ion);
377*00b67f09SDavid van Moolenbroek l = strlen(source);
378*00b67f09SDavid van Moolenbroek
379*00b67f09SDavid van Moolenbroek if (l > region.length)
380*00b67f09SDavid van Moolenbroek return (ISC_R_NOSPACE);
381*00b67f09SDavid van Moolenbroek
382*00b67f09SDavid van Moolenbroek memmove(region.base, source, l);
383*00b67f09SDavid van Moolenbroek isc_buffer_add(target, l);
384*00b67f09SDavid van Moolenbroek return (ISC_R_SUCCESS);
385*00b67f09SDavid van Moolenbroek }
386*00b67f09SDavid van Moolenbroek
387*00b67f09SDavid van Moolenbroek static isc_result_t
ncache_summary(dns_rdataset_t * rdataset,isc_boolean_t omit_final_dot,isc_buffer_t * target)388*00b67f09SDavid van Moolenbroek ncache_summary(dns_rdataset_t *rdataset, isc_boolean_t omit_final_dot,
389*00b67f09SDavid van Moolenbroek isc_buffer_t *target)
390*00b67f09SDavid van Moolenbroek {
391*00b67f09SDavid van Moolenbroek isc_result_t result = ISC_R_SUCCESS;
392*00b67f09SDavid van Moolenbroek dns_rdataset_t rds;
393*00b67f09SDavid van Moolenbroek dns_name_t name;
394*00b67f09SDavid van Moolenbroek
395*00b67f09SDavid van Moolenbroek dns_rdataset_init(&rds);
396*00b67f09SDavid van Moolenbroek dns_name_init(&name, NULL);
397*00b67f09SDavid van Moolenbroek
398*00b67f09SDavid van Moolenbroek do {
399*00b67f09SDavid van Moolenbroek dns_ncache_current(rdataset, &name, &rds);
400*00b67f09SDavid van Moolenbroek for (result = dns_rdataset_first(&rds);
401*00b67f09SDavid van Moolenbroek result == ISC_R_SUCCESS;
402*00b67f09SDavid van Moolenbroek result = dns_rdataset_next(&rds)) {
403*00b67f09SDavid van Moolenbroek CHECK(str_totext("; ", target));
404*00b67f09SDavid van Moolenbroek CHECK(dns_name_totext(&name, omit_final_dot, target));
405*00b67f09SDavid van Moolenbroek CHECK(str_totext(" ", target));
406*00b67f09SDavid van Moolenbroek CHECK(dns_rdatatype_totext(rds.type, target));
407*00b67f09SDavid van Moolenbroek if (rds.type == dns_rdatatype_rrsig) {
408*00b67f09SDavid van Moolenbroek CHECK(str_totext(" ", target));
409*00b67f09SDavid van Moolenbroek CHECK(dns_rdatatype_totext(rds.covers, target));
410*00b67f09SDavid van Moolenbroek CHECK(str_totext(" ...\n", target));
411*00b67f09SDavid van Moolenbroek } else {
412*00b67f09SDavid van Moolenbroek dns_rdata_t rdata = DNS_RDATA_INIT;
413*00b67f09SDavid van Moolenbroek dns_rdataset_current(&rds, &rdata);
414*00b67f09SDavid van Moolenbroek CHECK(str_totext(" ", target));
415*00b67f09SDavid van Moolenbroek CHECK(dns_rdata_tofmttext(&rdata, dns_rootname,
416*00b67f09SDavid van Moolenbroek 0, 0, 0, " ", target));
417*00b67f09SDavid van Moolenbroek CHECK(str_totext("\n", target));
418*00b67f09SDavid van Moolenbroek }
419*00b67f09SDavid van Moolenbroek }
420*00b67f09SDavid van Moolenbroek dns_rdataset_disassociate(&rds);
421*00b67f09SDavid van Moolenbroek result = dns_rdataset_next(rdataset);
422*00b67f09SDavid van Moolenbroek } while (result == ISC_R_SUCCESS);
423*00b67f09SDavid van Moolenbroek
424*00b67f09SDavid van Moolenbroek if (result == ISC_R_NOMORE)
425*00b67f09SDavid van Moolenbroek result = ISC_R_SUCCESS;
426*00b67f09SDavid van Moolenbroek cleanup:
427*00b67f09SDavid van Moolenbroek if (dns_rdataset_isassociated(&rds))
428*00b67f09SDavid van Moolenbroek dns_rdataset_disassociate(&rds);
429*00b67f09SDavid van Moolenbroek
430*00b67f09SDavid van Moolenbroek return (result);
431*00b67f09SDavid van Moolenbroek }
432*00b67f09SDavid van Moolenbroek
433*00b67f09SDavid van Moolenbroek /*
434*00b67f09SDavid van Moolenbroek * Convert 'rdataset' to master file text format according to 'ctx',
435*00b67f09SDavid van Moolenbroek * storing the result in 'target'. If 'owner_name' is NULL, it
436*00b67f09SDavid van Moolenbroek * is omitted; otherwise 'owner_name' must be valid and have at least
437*00b67f09SDavid van Moolenbroek * one label.
438*00b67f09SDavid van Moolenbroek */
439*00b67f09SDavid van Moolenbroek
440*00b67f09SDavid van Moolenbroek static isc_result_t
rdataset_totext(dns_rdataset_t * rdataset,dns_name_t * owner_name,dns_totext_ctx_t * ctx,isc_boolean_t omit_final_dot,isc_buffer_t * target)441*00b67f09SDavid van Moolenbroek rdataset_totext(dns_rdataset_t *rdataset,
442*00b67f09SDavid van Moolenbroek dns_name_t *owner_name,
443*00b67f09SDavid van Moolenbroek dns_totext_ctx_t *ctx,
444*00b67f09SDavid van Moolenbroek isc_boolean_t omit_final_dot,
445*00b67f09SDavid van Moolenbroek isc_buffer_t *target)
446*00b67f09SDavid van Moolenbroek {
447*00b67f09SDavid van Moolenbroek isc_result_t result;
448*00b67f09SDavid van Moolenbroek unsigned int column;
449*00b67f09SDavid van Moolenbroek isc_boolean_t first = ISC_TRUE;
450*00b67f09SDavid van Moolenbroek isc_uint32_t current_ttl;
451*00b67f09SDavid van Moolenbroek isc_boolean_t current_ttl_valid;
452*00b67f09SDavid van Moolenbroek dns_rdatatype_t type;
453*00b67f09SDavid van Moolenbroek unsigned int type_start;
454*00b67f09SDavid van Moolenbroek
455*00b67f09SDavid van Moolenbroek REQUIRE(DNS_RDATASET_VALID(rdataset));
456*00b67f09SDavid van Moolenbroek
457*00b67f09SDavid van Moolenbroek rdataset->attributes |= DNS_RDATASETATTR_LOADORDER;
458*00b67f09SDavid van Moolenbroek result = dns_rdataset_first(rdataset);
459*00b67f09SDavid van Moolenbroek
460*00b67f09SDavid van Moolenbroek current_ttl = ctx->current_ttl;
461*00b67f09SDavid van Moolenbroek current_ttl_valid = ctx->current_ttl_valid;
462*00b67f09SDavid van Moolenbroek
463*00b67f09SDavid van Moolenbroek while (result == ISC_R_SUCCESS) {
464*00b67f09SDavid van Moolenbroek column = 0;
465*00b67f09SDavid van Moolenbroek
466*00b67f09SDavid van Moolenbroek /*
467*00b67f09SDavid van Moolenbroek * Comment?
468*00b67f09SDavid van Moolenbroek */
469*00b67f09SDavid van Moolenbroek if ((ctx->style.flags & DNS_STYLEFLAG_COMMENTDATA) != 0)
470*00b67f09SDavid van Moolenbroek RETERR(str_totext(";", target));
471*00b67f09SDavid van Moolenbroek
472*00b67f09SDavid van Moolenbroek /*
473*00b67f09SDavid van Moolenbroek * Owner name.
474*00b67f09SDavid van Moolenbroek */
475*00b67f09SDavid van Moolenbroek if (owner_name != NULL &&
476*00b67f09SDavid van Moolenbroek ! ((ctx->style.flags & DNS_STYLEFLAG_OMIT_OWNER) != 0 &&
477*00b67f09SDavid van Moolenbroek !first))
478*00b67f09SDavid van Moolenbroek {
479*00b67f09SDavid van Moolenbroek unsigned int name_start = target->used;
480*00b67f09SDavid van Moolenbroek RETERR(dns_name_totext(owner_name,
481*00b67f09SDavid van Moolenbroek omit_final_dot,
482*00b67f09SDavid van Moolenbroek target));
483*00b67f09SDavid van Moolenbroek column += target->used - name_start;
484*00b67f09SDavid van Moolenbroek }
485*00b67f09SDavid van Moolenbroek
486*00b67f09SDavid van Moolenbroek /*
487*00b67f09SDavid van Moolenbroek * TTL.
488*00b67f09SDavid van Moolenbroek */
489*00b67f09SDavid van Moolenbroek if ((ctx->style.flags & DNS_STYLEFLAG_NO_TTL) == 0 &&
490*00b67f09SDavid van Moolenbroek !((ctx->style.flags & DNS_STYLEFLAG_OMIT_TTL) != 0 &&
491*00b67f09SDavid van Moolenbroek current_ttl_valid &&
492*00b67f09SDavid van Moolenbroek rdataset->ttl == current_ttl))
493*00b67f09SDavid van Moolenbroek {
494*00b67f09SDavid van Moolenbroek char ttlbuf[64];
495*00b67f09SDavid van Moolenbroek isc_region_t r;
496*00b67f09SDavid van Moolenbroek unsigned int length;
497*00b67f09SDavid van Moolenbroek
498*00b67f09SDavid van Moolenbroek INDENT_TO(ttl_column);
499*00b67f09SDavid van Moolenbroek length = snprintf(ttlbuf, sizeof(ttlbuf), "%u",
500*00b67f09SDavid van Moolenbroek rdataset->ttl);
501*00b67f09SDavid van Moolenbroek INSIST(length <= sizeof(ttlbuf));
502*00b67f09SDavid van Moolenbroek isc_buffer_availableregion(target, &r);
503*00b67f09SDavid van Moolenbroek if (r.length < length)
504*00b67f09SDavid van Moolenbroek return (ISC_R_NOSPACE);
505*00b67f09SDavid van Moolenbroek memmove(r.base, ttlbuf, length);
506*00b67f09SDavid van Moolenbroek isc_buffer_add(target, length);
507*00b67f09SDavid van Moolenbroek column += length;
508*00b67f09SDavid van Moolenbroek
509*00b67f09SDavid van Moolenbroek /*
510*00b67f09SDavid van Moolenbroek * If the $TTL directive is not in use, the TTL we
511*00b67f09SDavid van Moolenbroek * just printed becomes the default for subsequent RRs.
512*00b67f09SDavid van Moolenbroek */
513*00b67f09SDavid van Moolenbroek if ((ctx->style.flags & DNS_STYLEFLAG_TTL) == 0) {
514*00b67f09SDavid van Moolenbroek current_ttl = rdataset->ttl;
515*00b67f09SDavid van Moolenbroek current_ttl_valid = ISC_TRUE;
516*00b67f09SDavid van Moolenbroek }
517*00b67f09SDavid van Moolenbroek }
518*00b67f09SDavid van Moolenbroek
519*00b67f09SDavid van Moolenbroek /*
520*00b67f09SDavid van Moolenbroek * Class.
521*00b67f09SDavid van Moolenbroek */
522*00b67f09SDavid van Moolenbroek if ((ctx->style.flags & DNS_STYLEFLAG_NO_CLASS) == 0 &&
523*00b67f09SDavid van Moolenbroek ((ctx->style.flags & DNS_STYLEFLAG_OMIT_CLASS) == 0 ||
524*00b67f09SDavid van Moolenbroek ctx->class_printed == ISC_FALSE))
525*00b67f09SDavid van Moolenbroek {
526*00b67f09SDavid van Moolenbroek unsigned int class_start;
527*00b67f09SDavid van Moolenbroek INDENT_TO(class_column);
528*00b67f09SDavid van Moolenbroek class_start = target->used;
529*00b67f09SDavid van Moolenbroek result = dns_rdataclass_totext(rdataset->rdclass,
530*00b67f09SDavid van Moolenbroek target);
531*00b67f09SDavid van Moolenbroek if (result != ISC_R_SUCCESS)
532*00b67f09SDavid van Moolenbroek return (result);
533*00b67f09SDavid van Moolenbroek column += (target->used - class_start);
534*00b67f09SDavid van Moolenbroek }
535*00b67f09SDavid van Moolenbroek
536*00b67f09SDavid van Moolenbroek /*
537*00b67f09SDavid van Moolenbroek * Type.
538*00b67f09SDavid van Moolenbroek */
539*00b67f09SDavid van Moolenbroek
540*00b67f09SDavid van Moolenbroek if ((rdataset->attributes & DNS_RDATASETATTR_NEGATIVE) != 0) {
541*00b67f09SDavid van Moolenbroek type = rdataset->covers;
542*00b67f09SDavid van Moolenbroek } else {
543*00b67f09SDavid van Moolenbroek type = rdataset->type;
544*00b67f09SDavid van Moolenbroek }
545*00b67f09SDavid van Moolenbroek
546*00b67f09SDavid van Moolenbroek INDENT_TO(type_column);
547*00b67f09SDavid van Moolenbroek type_start = target->used;
548*00b67f09SDavid van Moolenbroek if ((rdataset->attributes & DNS_RDATASETATTR_NEGATIVE) != 0)
549*00b67f09SDavid van Moolenbroek RETERR(str_totext("\\-", target));
550*00b67f09SDavid van Moolenbroek switch (type) {
551*00b67f09SDavid van Moolenbroek case dns_rdatatype_keydata:
552*00b67f09SDavid van Moolenbroek #define KEYDATA "KEYDATA"
553*00b67f09SDavid van Moolenbroek if ((ctx->style.flags & DNS_STYLEFLAG_KEYDATA) != 0) {
554*00b67f09SDavid van Moolenbroek if (isc_buffer_availablelength(target) <
555*00b67f09SDavid van Moolenbroek (sizeof(KEYDATA) - 1))
556*00b67f09SDavid van Moolenbroek return (ISC_R_NOSPACE);
557*00b67f09SDavid van Moolenbroek isc_buffer_putstr(target, KEYDATA);
558*00b67f09SDavid van Moolenbroek break;
559*00b67f09SDavid van Moolenbroek }
560*00b67f09SDavid van Moolenbroek /* FALLTHROUGH */
561*00b67f09SDavid van Moolenbroek default:
562*00b67f09SDavid van Moolenbroek result = dns_rdatatype_totext(type, target);
563*00b67f09SDavid van Moolenbroek if (result != ISC_R_SUCCESS)
564*00b67f09SDavid van Moolenbroek return (result);
565*00b67f09SDavid van Moolenbroek }
566*00b67f09SDavid van Moolenbroek column += (target->used - type_start);
567*00b67f09SDavid van Moolenbroek
568*00b67f09SDavid van Moolenbroek /*
569*00b67f09SDavid van Moolenbroek * Rdata.
570*00b67f09SDavid van Moolenbroek */
571*00b67f09SDavid van Moolenbroek INDENT_TO(rdata_column);
572*00b67f09SDavid van Moolenbroek if ((rdataset->attributes & DNS_RDATASETATTR_NEGATIVE) != 0) {
573*00b67f09SDavid van Moolenbroek if (NXDOMAIN(rdataset))
574*00b67f09SDavid van Moolenbroek RETERR(str_totext(";-$NXDOMAIN\n", target));
575*00b67f09SDavid van Moolenbroek else
576*00b67f09SDavid van Moolenbroek RETERR(str_totext(";-$NXRRSET\n", target));
577*00b67f09SDavid van Moolenbroek /*
578*00b67f09SDavid van Moolenbroek * Print a summary of the cached records which make
579*00b67f09SDavid van Moolenbroek * up the negative response.
580*00b67f09SDavid van Moolenbroek */
581*00b67f09SDavid van Moolenbroek RETERR(ncache_summary(rdataset, omit_final_dot,
582*00b67f09SDavid van Moolenbroek target));
583*00b67f09SDavid van Moolenbroek break;
584*00b67f09SDavid van Moolenbroek } else {
585*00b67f09SDavid van Moolenbroek dns_rdata_t rdata = DNS_RDATA_INIT;
586*00b67f09SDavid van Moolenbroek isc_region_t r;
587*00b67f09SDavid van Moolenbroek
588*00b67f09SDavid van Moolenbroek dns_rdataset_current(rdataset, &rdata);
589*00b67f09SDavid van Moolenbroek
590*00b67f09SDavid van Moolenbroek RETERR(dns_rdata_tofmttext(&rdata,
591*00b67f09SDavid van Moolenbroek ctx->origin,
592*00b67f09SDavid van Moolenbroek ctx->style.flags,
593*00b67f09SDavid van Moolenbroek ctx->style.line_length -
594*00b67f09SDavid van Moolenbroek ctx->style.rdata_column,
595*00b67f09SDavid van Moolenbroek ctx->style.split_width,
596*00b67f09SDavid van Moolenbroek ctx->linebreak,
597*00b67f09SDavid van Moolenbroek target));
598*00b67f09SDavid van Moolenbroek
599*00b67f09SDavid van Moolenbroek isc_buffer_availableregion(target, &r);
600*00b67f09SDavid van Moolenbroek if (r.length < 1)
601*00b67f09SDavid van Moolenbroek return (ISC_R_NOSPACE);
602*00b67f09SDavid van Moolenbroek r.base[0] = '\n';
603*00b67f09SDavid van Moolenbroek isc_buffer_add(target, 1);
604*00b67f09SDavid van Moolenbroek }
605*00b67f09SDavid van Moolenbroek
606*00b67f09SDavid van Moolenbroek first = ISC_FALSE;
607*00b67f09SDavid van Moolenbroek result = dns_rdataset_next(rdataset);
608*00b67f09SDavid van Moolenbroek }
609*00b67f09SDavid van Moolenbroek
610*00b67f09SDavid van Moolenbroek if (result != ISC_R_NOMORE)
611*00b67f09SDavid van Moolenbroek return (result);
612*00b67f09SDavid van Moolenbroek
613*00b67f09SDavid van Moolenbroek /*
614*00b67f09SDavid van Moolenbroek * Update the ctx state to reflect what we just printed.
615*00b67f09SDavid van Moolenbroek * This is done last, only when we are sure we will return
616*00b67f09SDavid van Moolenbroek * success, because this function may be called multiple
617*00b67f09SDavid van Moolenbroek * times with increasing buffer sizes until it succeeds,
618*00b67f09SDavid van Moolenbroek * and failed attempts must not update the state prematurely.
619*00b67f09SDavid van Moolenbroek */
620*00b67f09SDavid van Moolenbroek ctx->class_printed = ISC_TRUE;
621*00b67f09SDavid van Moolenbroek ctx->current_ttl= current_ttl;
622*00b67f09SDavid van Moolenbroek ctx->current_ttl_valid = current_ttl_valid;
623*00b67f09SDavid van Moolenbroek
624*00b67f09SDavid van Moolenbroek return (ISC_R_SUCCESS);
625*00b67f09SDavid van Moolenbroek }
626*00b67f09SDavid van Moolenbroek
627*00b67f09SDavid van Moolenbroek /*
628*00b67f09SDavid van Moolenbroek * Print the name, type, and class of an empty rdataset,
629*00b67f09SDavid van Moolenbroek * such as those used to represent the question section
630*00b67f09SDavid van Moolenbroek * of a DNS message.
631*00b67f09SDavid van Moolenbroek */
632*00b67f09SDavid van Moolenbroek static isc_result_t
question_totext(dns_rdataset_t * rdataset,dns_name_t * owner_name,dns_totext_ctx_t * ctx,isc_boolean_t omit_final_dot,isc_buffer_t * target)633*00b67f09SDavid van Moolenbroek question_totext(dns_rdataset_t *rdataset,
634*00b67f09SDavid van Moolenbroek dns_name_t *owner_name,
635*00b67f09SDavid van Moolenbroek dns_totext_ctx_t *ctx,
636*00b67f09SDavid van Moolenbroek isc_boolean_t omit_final_dot,
637*00b67f09SDavid van Moolenbroek isc_buffer_t *target)
638*00b67f09SDavid van Moolenbroek {
639*00b67f09SDavid van Moolenbroek unsigned int column;
640*00b67f09SDavid van Moolenbroek isc_result_t result;
641*00b67f09SDavid van Moolenbroek isc_region_t r;
642*00b67f09SDavid van Moolenbroek
643*00b67f09SDavid van Moolenbroek REQUIRE(DNS_RDATASET_VALID(rdataset));
644*00b67f09SDavid van Moolenbroek result = dns_rdataset_first(rdataset);
645*00b67f09SDavid van Moolenbroek REQUIRE(result == ISC_R_NOMORE);
646*00b67f09SDavid van Moolenbroek
647*00b67f09SDavid van Moolenbroek column = 0;
648*00b67f09SDavid van Moolenbroek
649*00b67f09SDavid van Moolenbroek /* Owner name */
650*00b67f09SDavid van Moolenbroek {
651*00b67f09SDavid van Moolenbroek unsigned int name_start = target->used;
652*00b67f09SDavid van Moolenbroek RETERR(dns_name_totext(owner_name,
653*00b67f09SDavid van Moolenbroek omit_final_dot,
654*00b67f09SDavid van Moolenbroek target));
655*00b67f09SDavid van Moolenbroek column += target->used - name_start;
656*00b67f09SDavid van Moolenbroek }
657*00b67f09SDavid van Moolenbroek
658*00b67f09SDavid van Moolenbroek /* Class */
659*00b67f09SDavid van Moolenbroek {
660*00b67f09SDavid van Moolenbroek unsigned int class_start;
661*00b67f09SDavid van Moolenbroek INDENT_TO(class_column);
662*00b67f09SDavid van Moolenbroek class_start = target->used;
663*00b67f09SDavid van Moolenbroek result = dns_rdataclass_totext(rdataset->rdclass, target);
664*00b67f09SDavid van Moolenbroek if (result != ISC_R_SUCCESS)
665*00b67f09SDavid van Moolenbroek return (result);
666*00b67f09SDavid van Moolenbroek column += (target->used - class_start);
667*00b67f09SDavid van Moolenbroek }
668*00b67f09SDavid van Moolenbroek
669*00b67f09SDavid van Moolenbroek /* Type */
670*00b67f09SDavid van Moolenbroek {
671*00b67f09SDavid van Moolenbroek unsigned int type_start;
672*00b67f09SDavid van Moolenbroek INDENT_TO(type_column);
673*00b67f09SDavid van Moolenbroek type_start = target->used;
674*00b67f09SDavid van Moolenbroek result = dns_rdatatype_totext(rdataset->type, target);
675*00b67f09SDavid van Moolenbroek if (result != ISC_R_SUCCESS)
676*00b67f09SDavid van Moolenbroek return (result);
677*00b67f09SDavid van Moolenbroek column += (target->used - type_start);
678*00b67f09SDavid van Moolenbroek }
679*00b67f09SDavid van Moolenbroek
680*00b67f09SDavid van Moolenbroek isc_buffer_availableregion(target, &r);
681*00b67f09SDavid van Moolenbroek if (r.length < 1)
682*00b67f09SDavid van Moolenbroek return (ISC_R_NOSPACE);
683*00b67f09SDavid van Moolenbroek r.base[0] = '\n';
684*00b67f09SDavid van Moolenbroek isc_buffer_add(target, 1);
685*00b67f09SDavid van Moolenbroek
686*00b67f09SDavid van Moolenbroek return (ISC_R_SUCCESS);
687*00b67f09SDavid van Moolenbroek }
688*00b67f09SDavid van Moolenbroek
689*00b67f09SDavid van Moolenbroek isc_result_t
dns_rdataset_totext(dns_rdataset_t * rdataset,dns_name_t * owner_name,isc_boolean_t omit_final_dot,isc_boolean_t question,isc_buffer_t * target)690*00b67f09SDavid van Moolenbroek dns_rdataset_totext(dns_rdataset_t *rdataset,
691*00b67f09SDavid van Moolenbroek dns_name_t *owner_name,
692*00b67f09SDavid van Moolenbroek isc_boolean_t omit_final_dot,
693*00b67f09SDavid van Moolenbroek isc_boolean_t question,
694*00b67f09SDavid van Moolenbroek isc_buffer_t *target)
695*00b67f09SDavid van Moolenbroek {
696*00b67f09SDavid van Moolenbroek dns_totext_ctx_t ctx;
697*00b67f09SDavid van Moolenbroek isc_result_t result;
698*00b67f09SDavid van Moolenbroek result = totext_ctx_init(&dns_master_style_debug, &ctx);
699*00b67f09SDavid van Moolenbroek if (result != ISC_R_SUCCESS) {
700*00b67f09SDavid van Moolenbroek UNEXPECTED_ERROR(__FILE__, __LINE__,
701*00b67f09SDavid van Moolenbroek "could not set master file style");
702*00b67f09SDavid van Moolenbroek return (ISC_R_UNEXPECTED);
703*00b67f09SDavid van Moolenbroek }
704*00b67f09SDavid van Moolenbroek
705*00b67f09SDavid van Moolenbroek /*
706*00b67f09SDavid van Moolenbroek * The caller might want to give us an empty owner
707*00b67f09SDavid van Moolenbroek * name (e.g. if they are outputting into a master
708*00b67f09SDavid van Moolenbroek * file and this rdataset has the same name as the
709*00b67f09SDavid van Moolenbroek * previous one.)
710*00b67f09SDavid van Moolenbroek */
711*00b67f09SDavid van Moolenbroek if (dns_name_countlabels(owner_name) == 0)
712*00b67f09SDavid van Moolenbroek owner_name = NULL;
713*00b67f09SDavid van Moolenbroek
714*00b67f09SDavid van Moolenbroek if (question)
715*00b67f09SDavid van Moolenbroek return (question_totext(rdataset, owner_name, &ctx,
716*00b67f09SDavid van Moolenbroek omit_final_dot, target));
717*00b67f09SDavid van Moolenbroek else
718*00b67f09SDavid van Moolenbroek return (rdataset_totext(rdataset, owner_name, &ctx,
719*00b67f09SDavid van Moolenbroek omit_final_dot, target));
720*00b67f09SDavid van Moolenbroek }
721*00b67f09SDavid van Moolenbroek
722*00b67f09SDavid van Moolenbroek isc_result_t
dns_master_rdatasettotext(dns_name_t * owner_name,dns_rdataset_t * rdataset,const dns_master_style_t * style,isc_buffer_t * target)723*00b67f09SDavid van Moolenbroek dns_master_rdatasettotext(dns_name_t *owner_name,
724*00b67f09SDavid van Moolenbroek dns_rdataset_t *rdataset,
725*00b67f09SDavid van Moolenbroek const dns_master_style_t *style,
726*00b67f09SDavid van Moolenbroek isc_buffer_t *target)
727*00b67f09SDavid van Moolenbroek {
728*00b67f09SDavid van Moolenbroek dns_totext_ctx_t ctx;
729*00b67f09SDavid van Moolenbroek isc_result_t result;
730*00b67f09SDavid van Moolenbroek result = totext_ctx_init(style, &ctx);
731*00b67f09SDavid van Moolenbroek if (result != ISC_R_SUCCESS) {
732*00b67f09SDavid van Moolenbroek UNEXPECTED_ERROR(__FILE__, __LINE__,
733*00b67f09SDavid van Moolenbroek "could not set master file style");
734*00b67f09SDavid van Moolenbroek return (ISC_R_UNEXPECTED);
735*00b67f09SDavid van Moolenbroek }
736*00b67f09SDavid van Moolenbroek
737*00b67f09SDavid van Moolenbroek return (rdataset_totext(rdataset, owner_name, &ctx,
738*00b67f09SDavid van Moolenbroek ISC_FALSE, target));
739*00b67f09SDavid van Moolenbroek }
740*00b67f09SDavid van Moolenbroek
741*00b67f09SDavid van Moolenbroek isc_result_t
dns_master_questiontotext(dns_name_t * owner_name,dns_rdataset_t * rdataset,const dns_master_style_t * style,isc_buffer_t * target)742*00b67f09SDavid van Moolenbroek dns_master_questiontotext(dns_name_t *owner_name,
743*00b67f09SDavid van Moolenbroek dns_rdataset_t *rdataset,
744*00b67f09SDavid van Moolenbroek const dns_master_style_t *style,
745*00b67f09SDavid van Moolenbroek isc_buffer_t *target)
746*00b67f09SDavid van Moolenbroek {
747*00b67f09SDavid van Moolenbroek dns_totext_ctx_t ctx;
748*00b67f09SDavid van Moolenbroek isc_result_t result;
749*00b67f09SDavid van Moolenbroek result = totext_ctx_init(style, &ctx);
750*00b67f09SDavid van Moolenbroek if (result != ISC_R_SUCCESS) {
751*00b67f09SDavid van Moolenbroek UNEXPECTED_ERROR(__FILE__, __LINE__,
752*00b67f09SDavid van Moolenbroek "could not set master file style");
753*00b67f09SDavid van Moolenbroek return (ISC_R_UNEXPECTED);
754*00b67f09SDavid van Moolenbroek }
755*00b67f09SDavid van Moolenbroek
756*00b67f09SDavid van Moolenbroek return (question_totext(rdataset, owner_name, &ctx,
757*00b67f09SDavid van Moolenbroek ISC_FALSE, target));
758*00b67f09SDavid van Moolenbroek }
759*00b67f09SDavid van Moolenbroek
760*00b67f09SDavid van Moolenbroek /*
761*00b67f09SDavid van Moolenbroek * Print an rdataset. 'buffer' is a scratch buffer, which must have been
762*00b67f09SDavid van Moolenbroek * dynamically allocated by the caller. It must be large enough to
763*00b67f09SDavid van Moolenbroek * hold the result from dns_ttl_totext(). If more than that is needed,
764*00b67f09SDavid van Moolenbroek * the buffer will be grown automatically.
765*00b67f09SDavid van Moolenbroek */
766*00b67f09SDavid van Moolenbroek
767*00b67f09SDavid van Moolenbroek static isc_result_t
dump_rdataset(isc_mem_t * mctx,dns_name_t * name,dns_rdataset_t * rdataset,dns_totext_ctx_t * ctx,isc_buffer_t * buffer,FILE * f)768*00b67f09SDavid van Moolenbroek dump_rdataset(isc_mem_t *mctx, dns_name_t *name, dns_rdataset_t *rdataset,
769*00b67f09SDavid van Moolenbroek dns_totext_ctx_t *ctx,
770*00b67f09SDavid van Moolenbroek isc_buffer_t *buffer, FILE *f)
771*00b67f09SDavid van Moolenbroek {
772*00b67f09SDavid van Moolenbroek isc_region_t r;
773*00b67f09SDavid van Moolenbroek isc_result_t result;
774*00b67f09SDavid van Moolenbroek
775*00b67f09SDavid van Moolenbroek REQUIRE(buffer->length > 0);
776*00b67f09SDavid van Moolenbroek
777*00b67f09SDavid van Moolenbroek /*
778*00b67f09SDavid van Moolenbroek * Output a $TTL directive if needed.
779*00b67f09SDavid van Moolenbroek */
780*00b67f09SDavid van Moolenbroek
781*00b67f09SDavid van Moolenbroek if ((ctx->style.flags & DNS_STYLEFLAG_TTL) != 0) {
782*00b67f09SDavid van Moolenbroek if (ctx->current_ttl_valid == ISC_FALSE ||
783*00b67f09SDavid van Moolenbroek ctx->current_ttl != rdataset->ttl)
784*00b67f09SDavid van Moolenbroek {
785*00b67f09SDavid van Moolenbroek if ((ctx->style.flags & DNS_STYLEFLAG_COMMENT) != 0)
786*00b67f09SDavid van Moolenbroek {
787*00b67f09SDavid van Moolenbroek isc_buffer_clear(buffer);
788*00b67f09SDavid van Moolenbroek result = dns_ttl_totext(rdataset->ttl,
789*00b67f09SDavid van Moolenbroek ISC_TRUE, buffer);
790*00b67f09SDavid van Moolenbroek INSIST(result == ISC_R_SUCCESS);
791*00b67f09SDavid van Moolenbroek isc_buffer_usedregion(buffer, &r);
792*00b67f09SDavid van Moolenbroek fprintf(f, "$TTL %u\t; %.*s\n", rdataset->ttl,
793*00b67f09SDavid van Moolenbroek (int) r.length, (char *) r.base);
794*00b67f09SDavid van Moolenbroek } else {
795*00b67f09SDavid van Moolenbroek fprintf(f, "$TTL %u\n", rdataset->ttl);
796*00b67f09SDavid van Moolenbroek }
797*00b67f09SDavid van Moolenbroek ctx->current_ttl = rdataset->ttl;
798*00b67f09SDavid van Moolenbroek ctx->current_ttl_valid = ISC_TRUE;
799*00b67f09SDavid van Moolenbroek }
800*00b67f09SDavid van Moolenbroek }
801*00b67f09SDavid van Moolenbroek
802*00b67f09SDavid van Moolenbroek isc_buffer_clear(buffer);
803*00b67f09SDavid van Moolenbroek
804*00b67f09SDavid van Moolenbroek /*
805*00b67f09SDavid van Moolenbroek * Generate the text representation of the rdataset into
806*00b67f09SDavid van Moolenbroek * the buffer. If the buffer is too small, grow it.
807*00b67f09SDavid van Moolenbroek */
808*00b67f09SDavid van Moolenbroek for (;;) {
809*00b67f09SDavid van Moolenbroek int newlength;
810*00b67f09SDavid van Moolenbroek void *newmem;
811*00b67f09SDavid van Moolenbroek result = rdataset_totext(rdataset, name, ctx,
812*00b67f09SDavid van Moolenbroek ISC_FALSE, buffer);
813*00b67f09SDavid van Moolenbroek if (result != ISC_R_NOSPACE)
814*00b67f09SDavid van Moolenbroek break;
815*00b67f09SDavid van Moolenbroek
816*00b67f09SDavid van Moolenbroek newlength = buffer->length * 2;
817*00b67f09SDavid van Moolenbroek newmem = isc_mem_get(mctx, newlength);
818*00b67f09SDavid van Moolenbroek if (newmem == NULL)
819*00b67f09SDavid van Moolenbroek return (ISC_R_NOMEMORY);
820*00b67f09SDavid van Moolenbroek isc_mem_put(mctx, buffer->base, buffer->length);
821*00b67f09SDavid van Moolenbroek isc_buffer_init(buffer, newmem, newlength);
822*00b67f09SDavid van Moolenbroek }
823*00b67f09SDavid van Moolenbroek if (result != ISC_R_SUCCESS)
824*00b67f09SDavid van Moolenbroek return (result);
825*00b67f09SDavid van Moolenbroek
826*00b67f09SDavid van Moolenbroek /*
827*00b67f09SDavid van Moolenbroek * Write the buffer contents to the master file.
828*00b67f09SDavid van Moolenbroek */
829*00b67f09SDavid van Moolenbroek isc_buffer_usedregion(buffer, &r);
830*00b67f09SDavid van Moolenbroek result = isc_stdio_write(r.base, 1, (size_t)r.length, f, NULL);
831*00b67f09SDavid van Moolenbroek
832*00b67f09SDavid van Moolenbroek if (result != ISC_R_SUCCESS) {
833*00b67f09SDavid van Moolenbroek UNEXPECTED_ERROR(__FILE__, __LINE__,
834*00b67f09SDavid van Moolenbroek "master file write failed: %s",
835*00b67f09SDavid van Moolenbroek isc_result_totext(result));
836*00b67f09SDavid van Moolenbroek return (result);
837*00b67f09SDavid van Moolenbroek }
838*00b67f09SDavid van Moolenbroek
839*00b67f09SDavid van Moolenbroek return (ISC_R_SUCCESS);
840*00b67f09SDavid van Moolenbroek }
841*00b67f09SDavid van Moolenbroek
842*00b67f09SDavid van Moolenbroek /*
843*00b67f09SDavid van Moolenbroek * Define the order in which rdatasets should be printed in zone
844*00b67f09SDavid van Moolenbroek * files. We will print SOA and NS records before others, SIGs
845*00b67f09SDavid van Moolenbroek * immediately following the things they sign, and order everything
846*00b67f09SDavid van Moolenbroek * else by RR number. This is all just for aesthetics and
847*00b67f09SDavid van Moolenbroek * compatibility with buggy software that expects the SOA to be first;
848*00b67f09SDavid van Moolenbroek * the DNS specifications allow any order.
849*00b67f09SDavid van Moolenbroek */
850*00b67f09SDavid van Moolenbroek
851*00b67f09SDavid van Moolenbroek static int
dump_order(const dns_rdataset_t * rds)852*00b67f09SDavid van Moolenbroek dump_order(const dns_rdataset_t *rds) {
853*00b67f09SDavid van Moolenbroek int t;
854*00b67f09SDavid van Moolenbroek int sig;
855*00b67f09SDavid van Moolenbroek if (rds->type == dns_rdatatype_rrsig) {
856*00b67f09SDavid van Moolenbroek t = rds->covers;
857*00b67f09SDavid van Moolenbroek sig = 1;
858*00b67f09SDavid van Moolenbroek } else {
859*00b67f09SDavid van Moolenbroek t = rds->type;
860*00b67f09SDavid van Moolenbroek sig = 0;
861*00b67f09SDavid van Moolenbroek }
862*00b67f09SDavid van Moolenbroek switch (t) {
863*00b67f09SDavid van Moolenbroek case dns_rdatatype_soa:
864*00b67f09SDavid van Moolenbroek t = 0;
865*00b67f09SDavid van Moolenbroek break;
866*00b67f09SDavid van Moolenbroek case dns_rdatatype_ns:
867*00b67f09SDavid van Moolenbroek t = 1;
868*00b67f09SDavid van Moolenbroek break;
869*00b67f09SDavid van Moolenbroek default:
870*00b67f09SDavid van Moolenbroek t += 2;
871*00b67f09SDavid van Moolenbroek break;
872*00b67f09SDavid van Moolenbroek }
873*00b67f09SDavid van Moolenbroek return (t << 1) + sig;
874*00b67f09SDavid van Moolenbroek }
875*00b67f09SDavid van Moolenbroek
876*00b67f09SDavid van Moolenbroek static int
dump_order_compare(const void * a,const void * b)877*00b67f09SDavid van Moolenbroek dump_order_compare(const void *a, const void *b) {
878*00b67f09SDavid van Moolenbroek return (dump_order(*((const dns_rdataset_t * const *) a)) -
879*00b67f09SDavid van Moolenbroek dump_order(*((const dns_rdataset_t * const *) b)));
880*00b67f09SDavid van Moolenbroek }
881*00b67f09SDavid van Moolenbroek
882*00b67f09SDavid van Moolenbroek /*
883*00b67f09SDavid van Moolenbroek * Dump all the rdatasets of a domain name to a master file. We make
884*00b67f09SDavid van Moolenbroek * a "best effort" attempt to sort the RRsets in a nice order, but if
885*00b67f09SDavid van Moolenbroek * there are more than MAXSORT RRsets, we punt and only sort them in
886*00b67f09SDavid van Moolenbroek * groups of MAXSORT. This is not expected to ever happen in practice
887*00b67f09SDavid van Moolenbroek * since much less than 64 RR types have been registered with the
888*00b67f09SDavid van Moolenbroek * IANA, so far, and the output will be correct (though not
889*00b67f09SDavid van Moolenbroek * aesthetically pleasing) even if it does happen.
890*00b67f09SDavid van Moolenbroek */
891*00b67f09SDavid van Moolenbroek
892*00b67f09SDavid van Moolenbroek #define MAXSORT 64
893*00b67f09SDavid van Moolenbroek
894*00b67f09SDavid van Moolenbroek static isc_result_t
dump_rdatasets_text(isc_mem_t * mctx,dns_name_t * name,dns_rdatasetiter_t * rdsiter,dns_totext_ctx_t * ctx,isc_buffer_t * buffer,FILE * f)895*00b67f09SDavid van Moolenbroek dump_rdatasets_text(isc_mem_t *mctx, dns_name_t *name,
896*00b67f09SDavid van Moolenbroek dns_rdatasetiter_t *rdsiter, dns_totext_ctx_t *ctx,
897*00b67f09SDavid van Moolenbroek isc_buffer_t *buffer, FILE *f)
898*00b67f09SDavid van Moolenbroek {
899*00b67f09SDavid van Moolenbroek isc_result_t itresult, dumpresult;
900*00b67f09SDavid van Moolenbroek isc_region_t r;
901*00b67f09SDavid van Moolenbroek dns_rdataset_t rdatasets[MAXSORT];
902*00b67f09SDavid van Moolenbroek dns_rdataset_t *sorted[MAXSORT];
903*00b67f09SDavid van Moolenbroek int i, n;
904*00b67f09SDavid van Moolenbroek
905*00b67f09SDavid van Moolenbroek itresult = dns_rdatasetiter_first(rdsiter);
906*00b67f09SDavid van Moolenbroek dumpresult = ISC_R_SUCCESS;
907*00b67f09SDavid van Moolenbroek
908*00b67f09SDavid van Moolenbroek if (itresult == ISC_R_SUCCESS && ctx->neworigin != NULL) {
909*00b67f09SDavid van Moolenbroek isc_buffer_clear(buffer);
910*00b67f09SDavid van Moolenbroek itresult = dns_name_totext(ctx->neworigin, ISC_FALSE, buffer);
911*00b67f09SDavid van Moolenbroek RUNTIME_CHECK(itresult == ISC_R_SUCCESS);
912*00b67f09SDavid van Moolenbroek isc_buffer_usedregion(buffer, &r);
913*00b67f09SDavid van Moolenbroek fprintf(f, "$ORIGIN %.*s\n", (int) r.length, (char *) r.base);
914*00b67f09SDavid van Moolenbroek ctx->neworigin = NULL;
915*00b67f09SDavid van Moolenbroek }
916*00b67f09SDavid van Moolenbroek
917*00b67f09SDavid van Moolenbroek again:
918*00b67f09SDavid van Moolenbroek for (i = 0;
919*00b67f09SDavid van Moolenbroek itresult == ISC_R_SUCCESS && i < MAXSORT;
920*00b67f09SDavid van Moolenbroek itresult = dns_rdatasetiter_next(rdsiter), i++) {
921*00b67f09SDavid van Moolenbroek dns_rdataset_init(&rdatasets[i]);
922*00b67f09SDavid van Moolenbroek dns_rdatasetiter_current(rdsiter, &rdatasets[i]);
923*00b67f09SDavid van Moolenbroek sorted[i] = &rdatasets[i];
924*00b67f09SDavid van Moolenbroek }
925*00b67f09SDavid van Moolenbroek n = i;
926*00b67f09SDavid van Moolenbroek INSIST(n <= MAXSORT);
927*00b67f09SDavid van Moolenbroek
928*00b67f09SDavid van Moolenbroek qsort(sorted, n, sizeof(sorted[0]), dump_order_compare);
929*00b67f09SDavid van Moolenbroek
930*00b67f09SDavid van Moolenbroek for (i = 0; i < n; i++) {
931*00b67f09SDavid van Moolenbroek dns_rdataset_t *rds = sorted[i];
932*00b67f09SDavid van Moolenbroek if (ctx->style.flags & DNS_STYLEFLAG_TRUST)
933*00b67f09SDavid van Moolenbroek fprintf(f, "; %s\n", dns_trust_totext(rds->trust));
934*00b67f09SDavid van Moolenbroek if (((rds->attributes & DNS_RDATASETATTR_NEGATIVE) != 0) &&
935*00b67f09SDavid van Moolenbroek (ctx->style.flags & DNS_STYLEFLAG_NCACHE) == 0) {
936*00b67f09SDavid van Moolenbroek /* Omit negative cache entries */
937*00b67f09SDavid van Moolenbroek } else {
938*00b67f09SDavid van Moolenbroek isc_result_t result =
939*00b67f09SDavid van Moolenbroek dump_rdataset(mctx, name, rds, ctx,
940*00b67f09SDavid van Moolenbroek buffer, f);
941*00b67f09SDavid van Moolenbroek if (result != ISC_R_SUCCESS)
942*00b67f09SDavid van Moolenbroek dumpresult = result;
943*00b67f09SDavid van Moolenbroek if ((ctx->style.flags & DNS_STYLEFLAG_OMIT_OWNER) != 0)
944*00b67f09SDavid van Moolenbroek name = NULL;
945*00b67f09SDavid van Moolenbroek }
946*00b67f09SDavid van Moolenbroek if (ctx->style.flags & DNS_STYLEFLAG_RESIGN &&
947*00b67f09SDavid van Moolenbroek rds->attributes & DNS_RDATASETATTR_RESIGN) {
948*00b67f09SDavid van Moolenbroek isc_buffer_t b;
949*00b67f09SDavid van Moolenbroek char buf[sizeof("YYYYMMDDHHMMSS")];
950*00b67f09SDavid van Moolenbroek memset(buf, 0, sizeof(buf));
951*00b67f09SDavid van Moolenbroek isc_buffer_init(&b, buf, sizeof(buf) - 1);
952*00b67f09SDavid van Moolenbroek dns_time64_totext((isc_uint64_t)rds->resign, &b);
953*00b67f09SDavid van Moolenbroek fprintf(f, "; resign=%s\n", buf);
954*00b67f09SDavid van Moolenbroek }
955*00b67f09SDavid van Moolenbroek dns_rdataset_disassociate(rds);
956*00b67f09SDavid van Moolenbroek }
957*00b67f09SDavid van Moolenbroek
958*00b67f09SDavid van Moolenbroek if (dumpresult != ISC_R_SUCCESS)
959*00b67f09SDavid van Moolenbroek return (dumpresult);
960*00b67f09SDavid van Moolenbroek
961*00b67f09SDavid van Moolenbroek /*
962*00b67f09SDavid van Moolenbroek * If we got more data than could be sorted at once,
963*00b67f09SDavid van Moolenbroek * go handle the rest.
964*00b67f09SDavid van Moolenbroek */
965*00b67f09SDavid van Moolenbroek if (itresult == ISC_R_SUCCESS)
966*00b67f09SDavid van Moolenbroek goto again;
967*00b67f09SDavid van Moolenbroek
968*00b67f09SDavid van Moolenbroek if (itresult == ISC_R_NOMORE)
969*00b67f09SDavid van Moolenbroek itresult = ISC_R_SUCCESS;
970*00b67f09SDavid van Moolenbroek
971*00b67f09SDavid van Moolenbroek return (itresult);
972*00b67f09SDavid van Moolenbroek }
973*00b67f09SDavid van Moolenbroek
974*00b67f09SDavid van Moolenbroek /*
975*00b67f09SDavid van Moolenbroek * Dump given RRsets in the "raw" format.
976*00b67f09SDavid van Moolenbroek */
977*00b67f09SDavid van Moolenbroek static isc_result_t
dump_rdataset_raw(isc_mem_t * mctx,dns_name_t * name,dns_rdataset_t * rdataset,isc_buffer_t * buffer,FILE * f)978*00b67f09SDavid van Moolenbroek dump_rdataset_raw(isc_mem_t *mctx, dns_name_t *name, dns_rdataset_t *rdataset,
979*00b67f09SDavid van Moolenbroek isc_buffer_t *buffer, FILE *f)
980*00b67f09SDavid van Moolenbroek {
981*00b67f09SDavid van Moolenbroek isc_result_t result;
982*00b67f09SDavid van Moolenbroek isc_uint32_t totallen;
983*00b67f09SDavid van Moolenbroek isc_uint16_t dlen;
984*00b67f09SDavid van Moolenbroek isc_region_t r, r_hdr;
985*00b67f09SDavid van Moolenbroek
986*00b67f09SDavid van Moolenbroek REQUIRE(buffer->length > 0);
987*00b67f09SDavid van Moolenbroek REQUIRE(DNS_RDATASET_VALID(rdataset));
988*00b67f09SDavid van Moolenbroek
989*00b67f09SDavid van Moolenbroek rdataset->attributes |= DNS_RDATASETATTR_LOADORDER;
990*00b67f09SDavid van Moolenbroek restart:
991*00b67f09SDavid van Moolenbroek totallen = 0;
992*00b67f09SDavid van Moolenbroek result = dns_rdataset_first(rdataset);
993*00b67f09SDavid van Moolenbroek REQUIRE(result == ISC_R_SUCCESS);
994*00b67f09SDavid van Moolenbroek
995*00b67f09SDavid van Moolenbroek isc_buffer_clear(buffer);
996*00b67f09SDavid van Moolenbroek
997*00b67f09SDavid van Moolenbroek /*
998*00b67f09SDavid van Moolenbroek * Common header and owner name (length followed by name)
999*00b67f09SDavid van Moolenbroek * These fields should be in a moderate length, so we assume we
1000*00b67f09SDavid van Moolenbroek * can store all of them in the initial buffer.
1001*00b67f09SDavid van Moolenbroek */
1002*00b67f09SDavid van Moolenbroek isc_buffer_availableregion(buffer, &r_hdr);
1003*00b67f09SDavid van Moolenbroek INSIST(r_hdr.length >= sizeof(dns_masterrawrdataset_t));
1004*00b67f09SDavid van Moolenbroek isc_buffer_putuint32(buffer, totallen); /* XXX: leave space */
1005*00b67f09SDavid van Moolenbroek isc_buffer_putuint16(buffer, rdataset->rdclass); /* 16-bit class */
1006*00b67f09SDavid van Moolenbroek isc_buffer_putuint16(buffer, rdataset->type); /* 16-bit type */
1007*00b67f09SDavid van Moolenbroek isc_buffer_putuint16(buffer, rdataset->covers); /* same as type */
1008*00b67f09SDavid van Moolenbroek isc_buffer_putuint32(buffer, rdataset->ttl); /* 32-bit TTL */
1009*00b67f09SDavid van Moolenbroek isc_buffer_putuint32(buffer, dns_rdataset_count(rdataset));
1010*00b67f09SDavid van Moolenbroek totallen = isc_buffer_usedlength(buffer);
1011*00b67f09SDavid van Moolenbroek INSIST(totallen <= sizeof(dns_masterrawrdataset_t));
1012*00b67f09SDavid van Moolenbroek
1013*00b67f09SDavid van Moolenbroek dns_name_toregion(name, &r);
1014*00b67f09SDavid van Moolenbroek INSIST(isc_buffer_availablelength(buffer) >=
1015*00b67f09SDavid van Moolenbroek (sizeof(dlen) + r.length));
1016*00b67f09SDavid van Moolenbroek dlen = (isc_uint16_t)r.length;
1017*00b67f09SDavid van Moolenbroek isc_buffer_putuint16(buffer, dlen);
1018*00b67f09SDavid van Moolenbroek isc_buffer_copyregion(buffer, &r);
1019*00b67f09SDavid van Moolenbroek totallen += sizeof(dlen) + r.length;
1020*00b67f09SDavid van Moolenbroek
1021*00b67f09SDavid van Moolenbroek do {
1022*00b67f09SDavid van Moolenbroek dns_rdata_t rdata = DNS_RDATA_INIT;
1023*00b67f09SDavid van Moolenbroek
1024*00b67f09SDavid van Moolenbroek dns_rdataset_current(rdataset, &rdata);
1025*00b67f09SDavid van Moolenbroek dns_rdata_toregion(&rdata, &r);
1026*00b67f09SDavid van Moolenbroek INSIST(r.length <= 0xffffU);
1027*00b67f09SDavid van Moolenbroek dlen = (isc_uint16_t)r.length;
1028*00b67f09SDavid van Moolenbroek
1029*00b67f09SDavid van Moolenbroek /*
1030*00b67f09SDavid van Moolenbroek * Copy the rdata into the buffer. If the buffer is too small,
1031*00b67f09SDavid van Moolenbroek * grow it. This should be rare, so we'll simply restart the
1032*00b67f09SDavid van Moolenbroek * entire procedure (or should we copy the old data and
1033*00b67f09SDavid van Moolenbroek * continue?).
1034*00b67f09SDavid van Moolenbroek */
1035*00b67f09SDavid van Moolenbroek if (isc_buffer_availablelength(buffer) <
1036*00b67f09SDavid van Moolenbroek sizeof(dlen) + r.length) {
1037*00b67f09SDavid van Moolenbroek int newlength;
1038*00b67f09SDavid van Moolenbroek void *newmem;
1039*00b67f09SDavid van Moolenbroek
1040*00b67f09SDavid van Moolenbroek newlength = buffer->length * 2;
1041*00b67f09SDavid van Moolenbroek newmem = isc_mem_get(mctx, newlength);
1042*00b67f09SDavid van Moolenbroek if (newmem == NULL)
1043*00b67f09SDavid van Moolenbroek return (ISC_R_NOMEMORY);
1044*00b67f09SDavid van Moolenbroek isc_mem_put(mctx, buffer->base, buffer->length);
1045*00b67f09SDavid van Moolenbroek isc_buffer_init(buffer, newmem, newlength);
1046*00b67f09SDavid van Moolenbroek goto restart;
1047*00b67f09SDavid van Moolenbroek }
1048*00b67f09SDavid van Moolenbroek isc_buffer_putuint16(buffer, dlen);
1049*00b67f09SDavid van Moolenbroek isc_buffer_copyregion(buffer, &r);
1050*00b67f09SDavid van Moolenbroek totallen += sizeof(dlen) + r.length;
1051*00b67f09SDavid van Moolenbroek
1052*00b67f09SDavid van Moolenbroek result = dns_rdataset_next(rdataset);
1053*00b67f09SDavid van Moolenbroek } while (result == ISC_R_SUCCESS);
1054*00b67f09SDavid van Moolenbroek
1055*00b67f09SDavid van Moolenbroek if (result != ISC_R_NOMORE)
1056*00b67f09SDavid van Moolenbroek return (result);
1057*00b67f09SDavid van Moolenbroek
1058*00b67f09SDavid van Moolenbroek /*
1059*00b67f09SDavid van Moolenbroek * Fill in the total length field.
1060*00b67f09SDavid van Moolenbroek * XXX: this is a bit tricky. Since we have already "used" the space
1061*00b67f09SDavid van Moolenbroek * for the total length in the buffer, we first remember the entire
1062*00b67f09SDavid van Moolenbroek * buffer length in the region, "rewind", and then write the value.
1063*00b67f09SDavid van Moolenbroek */
1064*00b67f09SDavid van Moolenbroek isc_buffer_usedregion(buffer, &r);
1065*00b67f09SDavid van Moolenbroek isc_buffer_clear(buffer);
1066*00b67f09SDavid van Moolenbroek isc_buffer_putuint32(buffer, totallen);
1067*00b67f09SDavid van Moolenbroek INSIST(isc_buffer_usedlength(buffer) < totallen);
1068*00b67f09SDavid van Moolenbroek
1069*00b67f09SDavid van Moolenbroek /*
1070*00b67f09SDavid van Moolenbroek * Write the buffer contents to the raw master file.
1071*00b67f09SDavid van Moolenbroek */
1072*00b67f09SDavid van Moolenbroek result = isc_stdio_write(r.base, 1, (size_t)r.length, f, NULL);
1073*00b67f09SDavid van Moolenbroek
1074*00b67f09SDavid van Moolenbroek if (result != ISC_R_SUCCESS) {
1075*00b67f09SDavid van Moolenbroek UNEXPECTED_ERROR(__FILE__, __LINE__,
1076*00b67f09SDavid van Moolenbroek "raw master file write failed: %s",
1077*00b67f09SDavid van Moolenbroek isc_result_totext(result));
1078*00b67f09SDavid van Moolenbroek return (result);
1079*00b67f09SDavid van Moolenbroek }
1080*00b67f09SDavid van Moolenbroek
1081*00b67f09SDavid van Moolenbroek return (result);
1082*00b67f09SDavid van Moolenbroek }
1083*00b67f09SDavid van Moolenbroek
1084*00b67f09SDavid van Moolenbroek static isc_result_t
dump_rdatasets_raw(isc_mem_t * mctx,dns_name_t * name,dns_rdatasetiter_t * rdsiter,dns_totext_ctx_t * ctx,isc_buffer_t * buffer,FILE * f)1085*00b67f09SDavid van Moolenbroek dump_rdatasets_raw(isc_mem_t *mctx, dns_name_t *name,
1086*00b67f09SDavid van Moolenbroek dns_rdatasetiter_t *rdsiter, dns_totext_ctx_t *ctx,
1087*00b67f09SDavid van Moolenbroek isc_buffer_t *buffer, FILE *f)
1088*00b67f09SDavid van Moolenbroek {
1089*00b67f09SDavid van Moolenbroek isc_result_t result;
1090*00b67f09SDavid van Moolenbroek dns_rdataset_t rdataset;
1091*00b67f09SDavid van Moolenbroek
1092*00b67f09SDavid van Moolenbroek for (result = dns_rdatasetiter_first(rdsiter);
1093*00b67f09SDavid van Moolenbroek result == ISC_R_SUCCESS;
1094*00b67f09SDavid van Moolenbroek result = dns_rdatasetiter_next(rdsiter)) {
1095*00b67f09SDavid van Moolenbroek
1096*00b67f09SDavid van Moolenbroek dns_rdataset_init(&rdataset);
1097*00b67f09SDavid van Moolenbroek dns_rdatasetiter_current(rdsiter, &rdataset);
1098*00b67f09SDavid van Moolenbroek
1099*00b67f09SDavid van Moolenbroek if (((rdataset.attributes & DNS_RDATASETATTR_NEGATIVE) != 0) &&
1100*00b67f09SDavid van Moolenbroek (ctx->style.flags & DNS_STYLEFLAG_NCACHE) == 0) {
1101*00b67f09SDavid van Moolenbroek /* Omit negative cache entries */
1102*00b67f09SDavid van Moolenbroek } else {
1103*00b67f09SDavid van Moolenbroek result = dump_rdataset_raw(mctx, name, &rdataset,
1104*00b67f09SDavid van Moolenbroek buffer, f);
1105*00b67f09SDavid van Moolenbroek }
1106*00b67f09SDavid van Moolenbroek dns_rdataset_disassociate(&rdataset);
1107*00b67f09SDavid van Moolenbroek if (result != ISC_R_SUCCESS)
1108*00b67f09SDavid van Moolenbroek return (result);
1109*00b67f09SDavid van Moolenbroek }
1110*00b67f09SDavid van Moolenbroek
1111*00b67f09SDavid van Moolenbroek if (result == ISC_R_NOMORE)
1112*00b67f09SDavid van Moolenbroek result = ISC_R_SUCCESS;
1113*00b67f09SDavid van Moolenbroek
1114*00b67f09SDavid van Moolenbroek return (result);
1115*00b67f09SDavid van Moolenbroek }
1116*00b67f09SDavid van Moolenbroek
1117*00b67f09SDavid van Moolenbroek static isc_result_t
dump_rdatasets_map(isc_mem_t * mctx,dns_name_t * name,dns_rdatasetiter_t * rdsiter,dns_totext_ctx_t * ctx,isc_buffer_t * buffer,FILE * f)1118*00b67f09SDavid van Moolenbroek dump_rdatasets_map(isc_mem_t *mctx, dns_name_t *name,
1119*00b67f09SDavid van Moolenbroek dns_rdatasetiter_t *rdsiter, dns_totext_ctx_t *ctx,
1120*00b67f09SDavid van Moolenbroek isc_buffer_t *buffer, FILE *f)
1121*00b67f09SDavid van Moolenbroek {
1122*00b67f09SDavid van Moolenbroek UNUSED(mctx);
1123*00b67f09SDavid van Moolenbroek UNUSED(name);
1124*00b67f09SDavid van Moolenbroek UNUSED(rdsiter);
1125*00b67f09SDavid van Moolenbroek UNUSED(ctx);
1126*00b67f09SDavid van Moolenbroek UNUSED(buffer);
1127*00b67f09SDavid van Moolenbroek UNUSED(f);
1128*00b67f09SDavid van Moolenbroek
1129*00b67f09SDavid van Moolenbroek return (ISC_R_NOTIMPLEMENTED);
1130*00b67f09SDavid van Moolenbroek }
1131*00b67f09SDavid van Moolenbroek
1132*00b67f09SDavid van Moolenbroek /*
1133*00b67f09SDavid van Moolenbroek * Initial size of text conversion buffer. The buffer is used
1134*00b67f09SDavid van Moolenbroek * for several purposes: converting origin names, rdatasets,
1135*00b67f09SDavid van Moolenbroek * $DATE timestamps, and comment strings for $TTL directives.
1136*00b67f09SDavid van Moolenbroek *
1137*00b67f09SDavid van Moolenbroek * When converting rdatasets, it is dynamically resized, but
1138*00b67f09SDavid van Moolenbroek * when converting origins, timestamps, etc it is not. Therefore,
1139*00b67f09SDavid van Moolenbroek * the initial size must large enough to hold the longest possible
1140*00b67f09SDavid van Moolenbroek * text representation of any domain name (for $ORIGIN).
1141*00b67f09SDavid van Moolenbroek */
1142*00b67f09SDavid van Moolenbroek static const int initial_buffer_length = 1200;
1143*00b67f09SDavid van Moolenbroek
1144*00b67f09SDavid van Moolenbroek static isc_result_t
1145*00b67f09SDavid van Moolenbroek dumptostreaminc(dns_dumpctx_t *dctx);
1146*00b67f09SDavid van Moolenbroek
1147*00b67f09SDavid van Moolenbroek static void
dumpctx_destroy(dns_dumpctx_t * dctx)1148*00b67f09SDavid van Moolenbroek dumpctx_destroy(dns_dumpctx_t *dctx) {
1149*00b67f09SDavid van Moolenbroek
1150*00b67f09SDavid van Moolenbroek dctx->magic = 0;
1151*00b67f09SDavid van Moolenbroek DESTROYLOCK(&dctx->lock);
1152*00b67f09SDavid van Moolenbroek dns_dbiterator_destroy(&dctx->dbiter);
1153*00b67f09SDavid van Moolenbroek if (dctx->version != NULL)
1154*00b67f09SDavid van Moolenbroek dns_db_closeversion(dctx->db, &dctx->version, ISC_FALSE);
1155*00b67f09SDavid van Moolenbroek dns_db_detach(&dctx->db);
1156*00b67f09SDavid van Moolenbroek if (dctx->task != NULL)
1157*00b67f09SDavid van Moolenbroek isc_task_detach(&dctx->task);
1158*00b67f09SDavid van Moolenbroek if (dctx->file != NULL)
1159*00b67f09SDavid van Moolenbroek isc_mem_free(dctx->mctx, dctx->file);
1160*00b67f09SDavid van Moolenbroek if (dctx->tmpfile != NULL)
1161*00b67f09SDavid van Moolenbroek isc_mem_free(dctx->mctx, dctx->tmpfile);
1162*00b67f09SDavid van Moolenbroek isc_mem_putanddetach(&dctx->mctx, dctx, sizeof(*dctx));
1163*00b67f09SDavid van Moolenbroek }
1164*00b67f09SDavid van Moolenbroek
1165*00b67f09SDavid van Moolenbroek void
dns_dumpctx_attach(dns_dumpctx_t * source,dns_dumpctx_t ** target)1166*00b67f09SDavid van Moolenbroek dns_dumpctx_attach(dns_dumpctx_t *source, dns_dumpctx_t **target) {
1167*00b67f09SDavid van Moolenbroek
1168*00b67f09SDavid van Moolenbroek REQUIRE(DNS_DCTX_VALID(source));
1169*00b67f09SDavid van Moolenbroek REQUIRE(target != NULL && *target == NULL);
1170*00b67f09SDavid van Moolenbroek
1171*00b67f09SDavid van Moolenbroek LOCK(&source->lock);
1172*00b67f09SDavid van Moolenbroek INSIST(source->references > 0);
1173*00b67f09SDavid van Moolenbroek source->references++;
1174*00b67f09SDavid van Moolenbroek INSIST(source->references != 0); /* Overflow? */
1175*00b67f09SDavid van Moolenbroek UNLOCK(&source->lock);
1176*00b67f09SDavid van Moolenbroek
1177*00b67f09SDavid van Moolenbroek *target = source;
1178*00b67f09SDavid van Moolenbroek }
1179*00b67f09SDavid van Moolenbroek
1180*00b67f09SDavid van Moolenbroek void
dns_dumpctx_detach(dns_dumpctx_t ** dctxp)1181*00b67f09SDavid van Moolenbroek dns_dumpctx_detach(dns_dumpctx_t **dctxp) {
1182*00b67f09SDavid van Moolenbroek dns_dumpctx_t *dctx;
1183*00b67f09SDavid van Moolenbroek isc_boolean_t need_destroy = ISC_FALSE;
1184*00b67f09SDavid van Moolenbroek
1185*00b67f09SDavid van Moolenbroek REQUIRE(dctxp != NULL);
1186*00b67f09SDavid van Moolenbroek dctx = *dctxp;
1187*00b67f09SDavid van Moolenbroek REQUIRE(DNS_DCTX_VALID(dctx));
1188*00b67f09SDavid van Moolenbroek
1189*00b67f09SDavid van Moolenbroek *dctxp = NULL;
1190*00b67f09SDavid van Moolenbroek
1191*00b67f09SDavid van Moolenbroek LOCK(&dctx->lock);
1192*00b67f09SDavid van Moolenbroek INSIST(dctx->references != 0);
1193*00b67f09SDavid van Moolenbroek dctx->references--;
1194*00b67f09SDavid van Moolenbroek if (dctx->references == 0)
1195*00b67f09SDavid van Moolenbroek need_destroy = ISC_TRUE;
1196*00b67f09SDavid van Moolenbroek UNLOCK(&dctx->lock);
1197*00b67f09SDavid van Moolenbroek if (need_destroy)
1198*00b67f09SDavid van Moolenbroek dumpctx_destroy(dctx);
1199*00b67f09SDavid van Moolenbroek }
1200*00b67f09SDavid van Moolenbroek
1201*00b67f09SDavid van Moolenbroek dns_dbversion_t *
dns_dumpctx_version(dns_dumpctx_t * dctx)1202*00b67f09SDavid van Moolenbroek dns_dumpctx_version(dns_dumpctx_t *dctx) {
1203*00b67f09SDavid van Moolenbroek REQUIRE(DNS_DCTX_VALID(dctx));
1204*00b67f09SDavid van Moolenbroek return (dctx->version);
1205*00b67f09SDavid van Moolenbroek }
1206*00b67f09SDavid van Moolenbroek
1207*00b67f09SDavid van Moolenbroek dns_db_t *
dns_dumpctx_db(dns_dumpctx_t * dctx)1208*00b67f09SDavid van Moolenbroek dns_dumpctx_db(dns_dumpctx_t *dctx) {
1209*00b67f09SDavid van Moolenbroek REQUIRE(DNS_DCTX_VALID(dctx));
1210*00b67f09SDavid van Moolenbroek return (dctx->db);
1211*00b67f09SDavid van Moolenbroek }
1212*00b67f09SDavid van Moolenbroek
1213*00b67f09SDavid van Moolenbroek void
dns_dumpctx_cancel(dns_dumpctx_t * dctx)1214*00b67f09SDavid van Moolenbroek dns_dumpctx_cancel(dns_dumpctx_t *dctx) {
1215*00b67f09SDavid van Moolenbroek REQUIRE(DNS_DCTX_VALID(dctx));
1216*00b67f09SDavid van Moolenbroek
1217*00b67f09SDavid van Moolenbroek LOCK(&dctx->lock);
1218*00b67f09SDavid van Moolenbroek dctx->canceled = ISC_TRUE;
1219*00b67f09SDavid van Moolenbroek UNLOCK(&dctx->lock);
1220*00b67f09SDavid van Moolenbroek }
1221*00b67f09SDavid van Moolenbroek
1222*00b67f09SDavid van Moolenbroek static isc_result_t
flushandsync(FILE * f,isc_result_t result,const char * temp)1223*00b67f09SDavid van Moolenbroek flushandsync(FILE *f, isc_result_t result, const char *temp) {
1224*00b67f09SDavid van Moolenbroek isc_boolean_t logit = ISC_TF(result == ISC_R_SUCCESS);
1225*00b67f09SDavid van Moolenbroek
1226*00b67f09SDavid van Moolenbroek if (result == ISC_R_SUCCESS)
1227*00b67f09SDavid van Moolenbroek result = isc_stdio_flush(f);
1228*00b67f09SDavid van Moolenbroek if (result != ISC_R_SUCCESS && logit) {
1229*00b67f09SDavid van Moolenbroek if (temp != NULL)
1230*00b67f09SDavid van Moolenbroek isc_log_write(dns_lctx, ISC_LOGCATEGORY_GENERAL,
1231*00b67f09SDavid van Moolenbroek DNS_LOGMODULE_MASTERDUMP, ISC_LOG_ERROR,
1232*00b67f09SDavid van Moolenbroek "dumping to master file: %s: flush: %s",
1233*00b67f09SDavid van Moolenbroek temp, isc_result_totext(result));
1234*00b67f09SDavid van Moolenbroek else
1235*00b67f09SDavid van Moolenbroek isc_log_write(dns_lctx, ISC_LOGCATEGORY_GENERAL,
1236*00b67f09SDavid van Moolenbroek DNS_LOGMODULE_MASTERDUMP, ISC_LOG_ERROR,
1237*00b67f09SDavid van Moolenbroek "dumping to stream: flush: %s",
1238*00b67f09SDavid van Moolenbroek isc_result_totext(result));
1239*00b67f09SDavid van Moolenbroek logit = ISC_FALSE;
1240*00b67f09SDavid van Moolenbroek }
1241*00b67f09SDavid van Moolenbroek
1242*00b67f09SDavid van Moolenbroek if (result == ISC_R_SUCCESS)
1243*00b67f09SDavid van Moolenbroek result = isc_stdio_sync(f);
1244*00b67f09SDavid van Moolenbroek if (result != ISC_R_SUCCESS && logit) {
1245*00b67f09SDavid van Moolenbroek if (temp != NULL)
1246*00b67f09SDavid van Moolenbroek isc_log_write(dns_lctx, ISC_LOGCATEGORY_GENERAL,
1247*00b67f09SDavid van Moolenbroek DNS_LOGMODULE_MASTERDUMP, ISC_LOG_ERROR,
1248*00b67f09SDavid van Moolenbroek "dumping to master file: %s: fsync: %s",
1249*00b67f09SDavid van Moolenbroek temp, isc_result_totext(result));
1250*00b67f09SDavid van Moolenbroek else
1251*00b67f09SDavid van Moolenbroek isc_log_write(dns_lctx, ISC_LOGCATEGORY_GENERAL,
1252*00b67f09SDavid van Moolenbroek DNS_LOGMODULE_MASTERDUMP, ISC_LOG_ERROR,
1253*00b67f09SDavid van Moolenbroek "dumping to stream: fsync: %s",
1254*00b67f09SDavid van Moolenbroek isc_result_totext(result));
1255*00b67f09SDavid van Moolenbroek }
1256*00b67f09SDavid van Moolenbroek return (result);
1257*00b67f09SDavid van Moolenbroek }
1258*00b67f09SDavid van Moolenbroek
1259*00b67f09SDavid van Moolenbroek static isc_result_t
closeandrename(FILE * f,isc_result_t result,const char * temp,const char * file)1260*00b67f09SDavid van Moolenbroek closeandrename(FILE *f, isc_result_t result, const char *temp, const char *file)
1261*00b67f09SDavid van Moolenbroek {
1262*00b67f09SDavid van Moolenbroek isc_result_t tresult;
1263*00b67f09SDavid van Moolenbroek isc_boolean_t logit = ISC_TF(result == ISC_R_SUCCESS);
1264*00b67f09SDavid van Moolenbroek
1265*00b67f09SDavid van Moolenbroek result = flushandsync(f, result, temp);
1266*00b67f09SDavid van Moolenbroek if (result != ISC_R_SUCCESS)
1267*00b67f09SDavid van Moolenbroek logit = ISC_FALSE;
1268*00b67f09SDavid van Moolenbroek
1269*00b67f09SDavid van Moolenbroek tresult = isc_stdio_close(f);
1270*00b67f09SDavid van Moolenbroek if (result == ISC_R_SUCCESS)
1271*00b67f09SDavid van Moolenbroek result = tresult;
1272*00b67f09SDavid van Moolenbroek if (result != ISC_R_SUCCESS && logit) {
1273*00b67f09SDavid van Moolenbroek isc_log_write(dns_lctx, ISC_LOGCATEGORY_GENERAL,
1274*00b67f09SDavid van Moolenbroek DNS_LOGMODULE_MASTERDUMP, ISC_LOG_ERROR,
1275*00b67f09SDavid van Moolenbroek "dumping master file: %s: fclose: %s",
1276*00b67f09SDavid van Moolenbroek temp, isc_result_totext(result));
1277*00b67f09SDavid van Moolenbroek logit = ISC_FALSE;
1278*00b67f09SDavid van Moolenbroek }
1279*00b67f09SDavid van Moolenbroek if (result == ISC_R_SUCCESS)
1280*00b67f09SDavid van Moolenbroek result = isc_file_rename(temp, file);
1281*00b67f09SDavid van Moolenbroek else
1282*00b67f09SDavid van Moolenbroek (void)isc_file_remove(temp);
1283*00b67f09SDavid van Moolenbroek if (result != ISC_R_SUCCESS && logit) {
1284*00b67f09SDavid van Moolenbroek isc_log_write(dns_lctx, ISC_LOGCATEGORY_GENERAL,
1285*00b67f09SDavid van Moolenbroek DNS_LOGMODULE_MASTERDUMP, ISC_LOG_ERROR,
1286*00b67f09SDavid van Moolenbroek "dumping master file: rename: %s: %s",
1287*00b67f09SDavid van Moolenbroek file, isc_result_totext(result));
1288*00b67f09SDavid van Moolenbroek }
1289*00b67f09SDavid van Moolenbroek return (result);
1290*00b67f09SDavid van Moolenbroek }
1291*00b67f09SDavid van Moolenbroek
1292*00b67f09SDavid van Moolenbroek static void
dump_quantum(isc_task_t * task,isc_event_t * event)1293*00b67f09SDavid van Moolenbroek dump_quantum(isc_task_t *task, isc_event_t *event) {
1294*00b67f09SDavid van Moolenbroek isc_result_t result;
1295*00b67f09SDavid van Moolenbroek isc_result_t tresult;
1296*00b67f09SDavid van Moolenbroek dns_dumpctx_t *dctx;
1297*00b67f09SDavid van Moolenbroek
1298*00b67f09SDavid van Moolenbroek REQUIRE(event != NULL);
1299*00b67f09SDavid van Moolenbroek dctx = event->ev_arg;
1300*00b67f09SDavid van Moolenbroek REQUIRE(DNS_DCTX_VALID(dctx));
1301*00b67f09SDavid van Moolenbroek if (dctx->canceled)
1302*00b67f09SDavid van Moolenbroek result = ISC_R_CANCELED;
1303*00b67f09SDavid van Moolenbroek else
1304*00b67f09SDavid van Moolenbroek result = dumptostreaminc(dctx);
1305*00b67f09SDavid van Moolenbroek if (result == DNS_R_CONTINUE) {
1306*00b67f09SDavid van Moolenbroek event->ev_arg = dctx;
1307*00b67f09SDavid van Moolenbroek isc_task_send(task, &event);
1308*00b67f09SDavid van Moolenbroek return;
1309*00b67f09SDavid van Moolenbroek }
1310*00b67f09SDavid van Moolenbroek
1311*00b67f09SDavid van Moolenbroek if (dctx->file != NULL) {
1312*00b67f09SDavid van Moolenbroek tresult = closeandrename(dctx->f, result,
1313*00b67f09SDavid van Moolenbroek dctx->tmpfile, dctx->file);
1314*00b67f09SDavid van Moolenbroek if (tresult != ISC_R_SUCCESS && result == ISC_R_SUCCESS)
1315*00b67f09SDavid van Moolenbroek result = tresult;
1316*00b67f09SDavid van Moolenbroek } else
1317*00b67f09SDavid van Moolenbroek result = flushandsync(dctx->f, result, NULL);
1318*00b67f09SDavid van Moolenbroek (dctx->done)(dctx->done_arg, result);
1319*00b67f09SDavid van Moolenbroek isc_event_free(&event);
1320*00b67f09SDavid van Moolenbroek dns_dumpctx_detach(&dctx);
1321*00b67f09SDavid van Moolenbroek }
1322*00b67f09SDavid van Moolenbroek
1323*00b67f09SDavid van Moolenbroek static isc_result_t
task_send(dns_dumpctx_t * dctx)1324*00b67f09SDavid van Moolenbroek task_send(dns_dumpctx_t *dctx) {
1325*00b67f09SDavid van Moolenbroek isc_event_t *event;
1326*00b67f09SDavid van Moolenbroek
1327*00b67f09SDavid van Moolenbroek event = isc_event_allocate(dctx->mctx, NULL, DNS_EVENT_DUMPQUANTUM,
1328*00b67f09SDavid van Moolenbroek dump_quantum, dctx, sizeof(*event));
1329*00b67f09SDavid van Moolenbroek if (event == NULL)
1330*00b67f09SDavid van Moolenbroek return (ISC_R_NOMEMORY);
1331*00b67f09SDavid van Moolenbroek isc_task_send(dctx->task, &event);
1332*00b67f09SDavid van Moolenbroek return (ISC_R_SUCCESS);
1333*00b67f09SDavid van Moolenbroek }
1334*00b67f09SDavid van Moolenbroek
1335*00b67f09SDavid van Moolenbroek static isc_result_t
dumpctx_create(isc_mem_t * mctx,dns_db_t * db,dns_dbversion_t * version,const dns_master_style_t * style,FILE * f,dns_dumpctx_t ** dctxp,dns_masterformat_t format,dns_masterrawheader_t * header)1336*00b67f09SDavid van Moolenbroek dumpctx_create(isc_mem_t *mctx, dns_db_t *db, dns_dbversion_t *version,
1337*00b67f09SDavid van Moolenbroek const dns_master_style_t *style, FILE *f, dns_dumpctx_t **dctxp,
1338*00b67f09SDavid van Moolenbroek dns_masterformat_t format, dns_masterrawheader_t *header)
1339*00b67f09SDavid van Moolenbroek {
1340*00b67f09SDavid van Moolenbroek dns_dumpctx_t *dctx;
1341*00b67f09SDavid van Moolenbroek isc_result_t result;
1342*00b67f09SDavid van Moolenbroek unsigned int options;
1343*00b67f09SDavid van Moolenbroek
1344*00b67f09SDavid van Moolenbroek dctx = isc_mem_get(mctx, sizeof(*dctx));
1345*00b67f09SDavid van Moolenbroek if (dctx == NULL)
1346*00b67f09SDavid van Moolenbroek return (ISC_R_NOMEMORY);
1347*00b67f09SDavid van Moolenbroek
1348*00b67f09SDavid van Moolenbroek dctx->mctx = NULL;
1349*00b67f09SDavid van Moolenbroek dctx->f = f;
1350*00b67f09SDavid van Moolenbroek dctx->dbiter = NULL;
1351*00b67f09SDavid van Moolenbroek dctx->db = NULL;
1352*00b67f09SDavid van Moolenbroek dctx->version = NULL;
1353*00b67f09SDavid van Moolenbroek dctx->done = NULL;
1354*00b67f09SDavid van Moolenbroek dctx->done_arg = NULL;
1355*00b67f09SDavid van Moolenbroek dctx->task = NULL;
1356*00b67f09SDavid van Moolenbroek dctx->nodes = 0;
1357*00b67f09SDavid van Moolenbroek dctx->first = ISC_TRUE;
1358*00b67f09SDavid van Moolenbroek dctx->canceled = ISC_FALSE;
1359*00b67f09SDavid van Moolenbroek dctx->file = NULL;
1360*00b67f09SDavid van Moolenbroek dctx->tmpfile = NULL;
1361*00b67f09SDavid van Moolenbroek dctx->format = format;
1362*00b67f09SDavid van Moolenbroek if (header == NULL)
1363*00b67f09SDavid van Moolenbroek dns_master_initrawheader(&dctx->header);
1364*00b67f09SDavid van Moolenbroek else
1365*00b67f09SDavid van Moolenbroek dctx->header = *header;
1366*00b67f09SDavid van Moolenbroek
1367*00b67f09SDavid van Moolenbroek switch (format) {
1368*00b67f09SDavid van Moolenbroek case dns_masterformat_text:
1369*00b67f09SDavid van Moolenbroek dctx->dumpsets = dump_rdatasets_text;
1370*00b67f09SDavid van Moolenbroek break;
1371*00b67f09SDavid van Moolenbroek case dns_masterformat_raw:
1372*00b67f09SDavid van Moolenbroek dctx->dumpsets = dump_rdatasets_raw;
1373*00b67f09SDavid van Moolenbroek break;
1374*00b67f09SDavid van Moolenbroek case dns_masterformat_map:
1375*00b67f09SDavid van Moolenbroek dctx->dumpsets = dump_rdatasets_map;
1376*00b67f09SDavid van Moolenbroek break;
1377*00b67f09SDavid van Moolenbroek default:
1378*00b67f09SDavid van Moolenbroek INSIST(0);
1379*00b67f09SDavid van Moolenbroek break;
1380*00b67f09SDavid van Moolenbroek }
1381*00b67f09SDavid van Moolenbroek
1382*00b67f09SDavid van Moolenbroek result = totext_ctx_init(style, &dctx->tctx);
1383*00b67f09SDavid van Moolenbroek if (result != ISC_R_SUCCESS) {
1384*00b67f09SDavid van Moolenbroek UNEXPECTED_ERROR(__FILE__, __LINE__,
1385*00b67f09SDavid van Moolenbroek "could not set master file style");
1386*00b67f09SDavid van Moolenbroek goto cleanup;
1387*00b67f09SDavid van Moolenbroek }
1388*00b67f09SDavid van Moolenbroek
1389*00b67f09SDavid van Moolenbroek isc_stdtime_get(&dctx->now);
1390*00b67f09SDavid van Moolenbroek dns_db_attach(db, &dctx->db);
1391*00b67f09SDavid van Moolenbroek
1392*00b67f09SDavid van Moolenbroek dctx->do_date = dns_db_iscache(dctx->db);
1393*00b67f09SDavid van Moolenbroek
1394*00b67f09SDavid van Moolenbroek if (dctx->format == dns_masterformat_text &&
1395*00b67f09SDavid van Moolenbroek (dctx->tctx.style.flags & DNS_STYLEFLAG_REL_OWNER) != 0) {
1396*00b67f09SDavid van Moolenbroek options = DNS_DB_RELATIVENAMES;
1397*00b67f09SDavid van Moolenbroek } else
1398*00b67f09SDavid van Moolenbroek options = 0;
1399*00b67f09SDavid van Moolenbroek result = dns_db_createiterator(dctx->db, options, &dctx->dbiter);
1400*00b67f09SDavid van Moolenbroek if (result != ISC_R_SUCCESS)
1401*00b67f09SDavid van Moolenbroek goto cleanup;
1402*00b67f09SDavid van Moolenbroek
1403*00b67f09SDavid van Moolenbroek result = isc_mutex_init(&dctx->lock);
1404*00b67f09SDavid van Moolenbroek if (result != ISC_R_SUCCESS)
1405*00b67f09SDavid van Moolenbroek goto cleanup;
1406*00b67f09SDavid van Moolenbroek if (version != NULL)
1407*00b67f09SDavid van Moolenbroek dns_db_attachversion(dctx->db, version, &dctx->version);
1408*00b67f09SDavid van Moolenbroek else if (!dns_db_iscache(db))
1409*00b67f09SDavid van Moolenbroek dns_db_currentversion(dctx->db, &dctx->version);
1410*00b67f09SDavid van Moolenbroek isc_mem_attach(mctx, &dctx->mctx);
1411*00b67f09SDavid van Moolenbroek dctx->references = 1;
1412*00b67f09SDavid van Moolenbroek dctx->magic = DNS_DCTX_MAGIC;
1413*00b67f09SDavid van Moolenbroek *dctxp = dctx;
1414*00b67f09SDavid van Moolenbroek return (ISC_R_SUCCESS);
1415*00b67f09SDavid van Moolenbroek
1416*00b67f09SDavid van Moolenbroek cleanup:
1417*00b67f09SDavid van Moolenbroek if (dctx->dbiter != NULL)
1418*00b67f09SDavid van Moolenbroek dns_dbiterator_destroy(&dctx->dbiter);
1419*00b67f09SDavid van Moolenbroek if (dctx->db != NULL)
1420*00b67f09SDavid van Moolenbroek dns_db_detach(&dctx->db);
1421*00b67f09SDavid van Moolenbroek if (dctx != NULL)
1422*00b67f09SDavid van Moolenbroek isc_mem_put(mctx, dctx, sizeof(*dctx));
1423*00b67f09SDavid van Moolenbroek return (result);
1424*00b67f09SDavid van Moolenbroek }
1425*00b67f09SDavid van Moolenbroek
1426*00b67f09SDavid van Moolenbroek static isc_result_t
writeheader(dns_dumpctx_t * dctx)1427*00b67f09SDavid van Moolenbroek writeheader(dns_dumpctx_t *dctx) {
1428*00b67f09SDavid van Moolenbroek isc_result_t result = ISC_R_SUCCESS;
1429*00b67f09SDavid van Moolenbroek isc_buffer_t buffer;
1430*00b67f09SDavid van Moolenbroek char *bufmem;
1431*00b67f09SDavid van Moolenbroek isc_region_t r;
1432*00b67f09SDavid van Moolenbroek dns_masterrawheader_t rawheader;
1433*00b67f09SDavid van Moolenbroek isc_uint32_t rawversion, now32;
1434*00b67f09SDavid van Moolenbroek
1435*00b67f09SDavid van Moolenbroek bufmem = isc_mem_get(dctx->mctx, initial_buffer_length);
1436*00b67f09SDavid van Moolenbroek if (bufmem == NULL)
1437*00b67f09SDavid van Moolenbroek return (ISC_R_NOMEMORY);
1438*00b67f09SDavid van Moolenbroek
1439*00b67f09SDavid van Moolenbroek isc_buffer_init(&buffer, bufmem, initial_buffer_length);
1440*00b67f09SDavid van Moolenbroek
1441*00b67f09SDavid van Moolenbroek switch (dctx->format) {
1442*00b67f09SDavid van Moolenbroek case dns_masterformat_text:
1443*00b67f09SDavid van Moolenbroek /*
1444*00b67f09SDavid van Moolenbroek * If the database has cache semantics, output an
1445*00b67f09SDavid van Moolenbroek * RFC2540 $DATE directive so that the TTLs can be
1446*00b67f09SDavid van Moolenbroek * adjusted when it is reloaded. For zones it is not
1447*00b67f09SDavid van Moolenbroek * really needed, and it would make the file
1448*00b67f09SDavid van Moolenbroek * incompatible with pre-RFC2540 software, so we omit
1449*00b67f09SDavid van Moolenbroek * it in the zone case.
1450*00b67f09SDavid van Moolenbroek */
1451*00b67f09SDavid van Moolenbroek if (dctx->do_date) {
1452*00b67f09SDavid van Moolenbroek result = dns_time32_totext(dctx->now, &buffer);
1453*00b67f09SDavid van Moolenbroek RUNTIME_CHECK(result == ISC_R_SUCCESS);
1454*00b67f09SDavid van Moolenbroek isc_buffer_usedregion(&buffer, &r);
1455*00b67f09SDavid van Moolenbroek fprintf(dctx->f, "$DATE %.*s\n",
1456*00b67f09SDavid van Moolenbroek (int) r.length, (char *) r.base);
1457*00b67f09SDavid van Moolenbroek }
1458*00b67f09SDavid van Moolenbroek break;
1459*00b67f09SDavid van Moolenbroek case dns_masterformat_raw:
1460*00b67f09SDavid van Moolenbroek case dns_masterformat_map:
1461*00b67f09SDavid van Moolenbroek r.base = (unsigned char *)&rawheader;
1462*00b67f09SDavid van Moolenbroek r.length = sizeof(rawheader);
1463*00b67f09SDavid van Moolenbroek isc_buffer_region(&buffer, &r);
1464*00b67f09SDavid van Moolenbroek #if !defined(STDTIME_ON_32BITS) || (STDTIME_ON_32BITS + 0) != 1
1465*00b67f09SDavid van Moolenbroek /*
1466*00b67f09SDavid van Moolenbroek * We assume isc_stdtime_t is a 32-bit integer,
1467*00b67f09SDavid van Moolenbroek * which should be the case on most platforms.
1468*00b67f09SDavid van Moolenbroek * If it turns out to be uncommon, we'll need
1469*00b67f09SDavid van Moolenbroek * to bump the version number and revise the
1470*00b67f09SDavid van Moolenbroek * header format.
1471*00b67f09SDavid van Moolenbroek */
1472*00b67f09SDavid van Moolenbroek isc_log_write(dns_lctx,
1473*00b67f09SDavid van Moolenbroek ISC_LOGCATEGORY_GENERAL,
1474*00b67f09SDavid van Moolenbroek DNS_LOGMODULE_MASTERDUMP,
1475*00b67f09SDavid van Moolenbroek ISC_LOG_INFO,
1476*00b67f09SDavid van Moolenbroek "dumping master file in raw "
1477*00b67f09SDavid van Moolenbroek "format: stdtime is not 32bits");
1478*00b67f09SDavid van Moolenbroek now32 = 0;
1479*00b67f09SDavid van Moolenbroek #else
1480*00b67f09SDavid van Moolenbroek now32 = dctx->now;
1481*00b67f09SDavid van Moolenbroek #endif
1482*00b67f09SDavid van Moolenbroek rawversion = 1;
1483*00b67f09SDavid van Moolenbroek if ((dctx->header.flags & DNS_MASTERRAW_COMPAT) != 0)
1484*00b67f09SDavid van Moolenbroek rawversion = 0;
1485*00b67f09SDavid van Moolenbroek
1486*00b67f09SDavid van Moolenbroek isc_buffer_putuint32(&buffer, dctx->format);
1487*00b67f09SDavid van Moolenbroek isc_buffer_putuint32(&buffer, rawversion);
1488*00b67f09SDavid van Moolenbroek isc_buffer_putuint32(&buffer, now32);
1489*00b67f09SDavid van Moolenbroek
1490*00b67f09SDavid van Moolenbroek if (rawversion == 1) {
1491*00b67f09SDavid van Moolenbroek isc_buffer_putuint32(&buffer, dctx->header.flags);
1492*00b67f09SDavid van Moolenbroek isc_buffer_putuint32(&buffer,
1493*00b67f09SDavid van Moolenbroek dctx->header.sourceserial);
1494*00b67f09SDavid van Moolenbroek isc_buffer_putuint32(&buffer, dctx->header.lastxfrin);
1495*00b67f09SDavid van Moolenbroek }
1496*00b67f09SDavid van Moolenbroek
1497*00b67f09SDavid van Moolenbroek INSIST(isc_buffer_usedlength(&buffer) <= sizeof(rawheader));
1498*00b67f09SDavid van Moolenbroek result = isc_stdio_write(buffer.base, 1,
1499*00b67f09SDavid van Moolenbroek isc_buffer_usedlength(&buffer),
1500*00b67f09SDavid van Moolenbroek dctx->f, NULL);
1501*00b67f09SDavid van Moolenbroek if (result != ISC_R_SUCCESS)
1502*00b67f09SDavid van Moolenbroek break;
1503*00b67f09SDavid van Moolenbroek
1504*00b67f09SDavid van Moolenbroek break;
1505*00b67f09SDavid van Moolenbroek default:
1506*00b67f09SDavid van Moolenbroek INSIST(0);
1507*00b67f09SDavid van Moolenbroek }
1508*00b67f09SDavid van Moolenbroek
1509*00b67f09SDavid van Moolenbroek isc_mem_put(dctx->mctx, buffer.base, buffer.length);
1510*00b67f09SDavid van Moolenbroek return (result);
1511*00b67f09SDavid van Moolenbroek }
1512*00b67f09SDavid van Moolenbroek
1513*00b67f09SDavid van Moolenbroek static isc_result_t
dumptostreaminc(dns_dumpctx_t * dctx)1514*00b67f09SDavid van Moolenbroek dumptostreaminc(dns_dumpctx_t *dctx) {
1515*00b67f09SDavid van Moolenbroek isc_result_t result = ISC_R_SUCCESS;
1516*00b67f09SDavid van Moolenbroek isc_buffer_t buffer;
1517*00b67f09SDavid van Moolenbroek char *bufmem;
1518*00b67f09SDavid van Moolenbroek dns_name_t *name;
1519*00b67f09SDavid van Moolenbroek dns_fixedname_t fixname;
1520*00b67f09SDavid van Moolenbroek unsigned int nodes;
1521*00b67f09SDavid van Moolenbroek isc_time_t start;
1522*00b67f09SDavid van Moolenbroek
1523*00b67f09SDavid van Moolenbroek bufmem = isc_mem_get(dctx->mctx, initial_buffer_length);
1524*00b67f09SDavid van Moolenbroek if (bufmem == NULL)
1525*00b67f09SDavid van Moolenbroek return (ISC_R_NOMEMORY);
1526*00b67f09SDavid van Moolenbroek
1527*00b67f09SDavid van Moolenbroek isc_buffer_init(&buffer, bufmem, initial_buffer_length);
1528*00b67f09SDavid van Moolenbroek
1529*00b67f09SDavid van Moolenbroek dns_fixedname_init(&fixname);
1530*00b67f09SDavid van Moolenbroek name = dns_fixedname_name(&fixname);
1531*00b67f09SDavid van Moolenbroek
1532*00b67f09SDavid van Moolenbroek if (dctx->first) {
1533*00b67f09SDavid van Moolenbroek CHECK(writeheader(dctx));
1534*00b67f09SDavid van Moolenbroek
1535*00b67f09SDavid van Moolenbroek /*
1536*00b67f09SDavid van Moolenbroek * Fast format is not currently written incrementally,
1537*00b67f09SDavid van Moolenbroek * so we make the call to dns_db_serialize() here.
1538*00b67f09SDavid van Moolenbroek * If the database is anything other than an rbtdb,
1539*00b67f09SDavid van Moolenbroek * this should result in not implemented
1540*00b67f09SDavid van Moolenbroek */
1541*00b67f09SDavid van Moolenbroek if (dctx->format == dns_masterformat_map) {
1542*00b67f09SDavid van Moolenbroek result = dns_db_serialize(dctx->db, dctx->version,
1543*00b67f09SDavid van Moolenbroek dctx->f);
1544*00b67f09SDavid van Moolenbroek goto cleanup;
1545*00b67f09SDavid van Moolenbroek }
1546*00b67f09SDavid van Moolenbroek
1547*00b67f09SDavid van Moolenbroek result = dns_dbiterator_first(dctx->dbiter);
1548*00b67f09SDavid van Moolenbroek if (result != ISC_R_SUCCESS && result != ISC_R_NOMORE)
1549*00b67f09SDavid van Moolenbroek goto cleanup;
1550*00b67f09SDavid van Moolenbroek
1551*00b67f09SDavid van Moolenbroek dctx->first = ISC_FALSE;
1552*00b67f09SDavid van Moolenbroek } else
1553*00b67f09SDavid van Moolenbroek result = ISC_R_SUCCESS;
1554*00b67f09SDavid van Moolenbroek
1555*00b67f09SDavid van Moolenbroek nodes = dctx->nodes;
1556*00b67f09SDavid van Moolenbroek isc_time_now(&start);
1557*00b67f09SDavid van Moolenbroek while (result == ISC_R_SUCCESS && (dctx->nodes == 0 || nodes--)) {
1558*00b67f09SDavid van Moolenbroek dns_rdatasetiter_t *rdsiter = NULL;
1559*00b67f09SDavid van Moolenbroek dns_dbnode_t *node = NULL;
1560*00b67f09SDavid van Moolenbroek
1561*00b67f09SDavid van Moolenbroek result = dns_dbiterator_current(dctx->dbiter, &node, name);
1562*00b67f09SDavid van Moolenbroek if (result != ISC_R_SUCCESS && result != DNS_R_NEWORIGIN)
1563*00b67f09SDavid van Moolenbroek break;
1564*00b67f09SDavid van Moolenbroek if (result == DNS_R_NEWORIGIN) {
1565*00b67f09SDavid van Moolenbroek dns_name_t *origin =
1566*00b67f09SDavid van Moolenbroek dns_fixedname_name(&dctx->tctx.origin_fixname);
1567*00b67f09SDavid van Moolenbroek result = dns_dbiterator_origin(dctx->dbiter, origin);
1568*00b67f09SDavid van Moolenbroek RUNTIME_CHECK(result == ISC_R_SUCCESS);
1569*00b67f09SDavid van Moolenbroek if ((dctx->tctx.style.flags &
1570*00b67f09SDavid van Moolenbroek DNS_STYLEFLAG_REL_DATA) != 0)
1571*00b67f09SDavid van Moolenbroek dctx->tctx.origin = origin;
1572*00b67f09SDavid van Moolenbroek dctx->tctx.neworigin = origin;
1573*00b67f09SDavid van Moolenbroek }
1574*00b67f09SDavid van Moolenbroek result = dns_db_allrdatasets(dctx->db, node, dctx->version,
1575*00b67f09SDavid van Moolenbroek dctx->now, &rdsiter);
1576*00b67f09SDavid van Moolenbroek if (result != ISC_R_SUCCESS) {
1577*00b67f09SDavid van Moolenbroek dns_db_detachnode(dctx->db, &node);
1578*00b67f09SDavid van Moolenbroek goto cleanup;
1579*00b67f09SDavid van Moolenbroek }
1580*00b67f09SDavid van Moolenbroek result = (dctx->dumpsets)(dctx->mctx, name, rdsiter,
1581*00b67f09SDavid van Moolenbroek &dctx->tctx, &buffer, dctx->f);
1582*00b67f09SDavid van Moolenbroek dns_rdatasetiter_destroy(&rdsiter);
1583*00b67f09SDavid van Moolenbroek if (result != ISC_R_SUCCESS) {
1584*00b67f09SDavid van Moolenbroek dns_db_detachnode(dctx->db, &node);
1585*00b67f09SDavid van Moolenbroek goto cleanup;
1586*00b67f09SDavid van Moolenbroek }
1587*00b67f09SDavid van Moolenbroek dns_db_detachnode(dctx->db, &node);
1588*00b67f09SDavid van Moolenbroek result = dns_dbiterator_next(dctx->dbiter);
1589*00b67f09SDavid van Moolenbroek }
1590*00b67f09SDavid van Moolenbroek
1591*00b67f09SDavid van Moolenbroek /*
1592*00b67f09SDavid van Moolenbroek * Work out how many nodes can be written in the time between
1593*00b67f09SDavid van Moolenbroek * two requests to the nameserver. Smooth the resulting number and
1594*00b67f09SDavid van Moolenbroek * use it as a estimate for the number of nodes to be written in the
1595*00b67f09SDavid van Moolenbroek * next iteration.
1596*00b67f09SDavid van Moolenbroek */
1597*00b67f09SDavid van Moolenbroek if (dctx->nodes != 0 && result == ISC_R_SUCCESS) {
1598*00b67f09SDavid van Moolenbroek unsigned int pps = dns_pps; /* packets per second */
1599*00b67f09SDavid van Moolenbroek unsigned int interval;
1600*00b67f09SDavid van Moolenbroek isc_uint64_t usecs;
1601*00b67f09SDavid van Moolenbroek isc_time_t end;
1602*00b67f09SDavid van Moolenbroek
1603*00b67f09SDavid van Moolenbroek isc_time_now(&end);
1604*00b67f09SDavid van Moolenbroek if (pps < 100)
1605*00b67f09SDavid van Moolenbroek pps = 100;
1606*00b67f09SDavid van Moolenbroek interval = 1000000 / pps; /* interval in usecs */
1607*00b67f09SDavid van Moolenbroek if (interval == 0)
1608*00b67f09SDavid van Moolenbroek interval = 1;
1609*00b67f09SDavid van Moolenbroek usecs = isc_time_microdiff(&end, &start);
1610*00b67f09SDavid van Moolenbroek if (usecs == 0) {
1611*00b67f09SDavid van Moolenbroek dctx->nodes = dctx->nodes * 2;
1612*00b67f09SDavid van Moolenbroek if (dctx->nodes > 1000)
1613*00b67f09SDavid van Moolenbroek dctx->nodes = 1000;
1614*00b67f09SDavid van Moolenbroek } else {
1615*00b67f09SDavid van Moolenbroek nodes = dctx->nodes * interval;
1616*00b67f09SDavid van Moolenbroek nodes /= (unsigned int)usecs;
1617*00b67f09SDavid van Moolenbroek if (nodes == 0)
1618*00b67f09SDavid van Moolenbroek nodes = 1;
1619*00b67f09SDavid van Moolenbroek else if (nodes > 1000)
1620*00b67f09SDavid van Moolenbroek nodes = 1000;
1621*00b67f09SDavid van Moolenbroek
1622*00b67f09SDavid van Moolenbroek /* Smooth and assign. */
1623*00b67f09SDavid van Moolenbroek dctx->nodes = (nodes + dctx->nodes * 7) / 8;
1624*00b67f09SDavid van Moolenbroek
1625*00b67f09SDavid van Moolenbroek isc_log_write(dns_lctx, ISC_LOGCATEGORY_GENERAL,
1626*00b67f09SDavid van Moolenbroek DNS_LOGMODULE_MASTERDUMP,
1627*00b67f09SDavid van Moolenbroek ISC_LOG_DEBUG(1),
1628*00b67f09SDavid van Moolenbroek "dumptostreaminc(%p) new nodes -> %d\n",
1629*00b67f09SDavid van Moolenbroek dctx, dctx->nodes);
1630*00b67f09SDavid van Moolenbroek }
1631*00b67f09SDavid van Moolenbroek result = DNS_R_CONTINUE;
1632*00b67f09SDavid van Moolenbroek } else if (result == ISC_R_NOMORE)
1633*00b67f09SDavid van Moolenbroek result = ISC_R_SUCCESS;
1634*00b67f09SDavid van Moolenbroek cleanup:
1635*00b67f09SDavid van Moolenbroek RUNTIME_CHECK(dns_dbiterator_pause(dctx->dbiter) == ISC_R_SUCCESS);
1636*00b67f09SDavid van Moolenbroek isc_mem_put(dctx->mctx, buffer.base, buffer.length);
1637*00b67f09SDavid van Moolenbroek return (result);
1638*00b67f09SDavid van Moolenbroek }
1639*00b67f09SDavid van Moolenbroek
1640*00b67f09SDavid van Moolenbroek isc_result_t
dns_master_dumptostreaminc(isc_mem_t * mctx,dns_db_t * db,dns_dbversion_t * version,const dns_master_style_t * style,FILE * f,isc_task_t * task,dns_dumpdonefunc_t done,void * done_arg,dns_dumpctx_t ** dctxp)1641*00b67f09SDavid van Moolenbroek dns_master_dumptostreaminc(isc_mem_t *mctx, dns_db_t *db,
1642*00b67f09SDavid van Moolenbroek dns_dbversion_t *version,
1643*00b67f09SDavid van Moolenbroek const dns_master_style_t *style,
1644*00b67f09SDavid van Moolenbroek FILE *f, isc_task_t *task,
1645*00b67f09SDavid van Moolenbroek dns_dumpdonefunc_t done, void *done_arg,
1646*00b67f09SDavid van Moolenbroek dns_dumpctx_t **dctxp)
1647*00b67f09SDavid van Moolenbroek {
1648*00b67f09SDavid van Moolenbroek dns_dumpctx_t *dctx = NULL;
1649*00b67f09SDavid van Moolenbroek isc_result_t result;
1650*00b67f09SDavid van Moolenbroek
1651*00b67f09SDavid van Moolenbroek REQUIRE(task != NULL);
1652*00b67f09SDavid van Moolenbroek REQUIRE(f != NULL);
1653*00b67f09SDavid van Moolenbroek REQUIRE(done != NULL);
1654*00b67f09SDavid van Moolenbroek
1655*00b67f09SDavid van Moolenbroek result = dumpctx_create(mctx, db, version, style, f, &dctx,
1656*00b67f09SDavid van Moolenbroek dns_masterformat_text, NULL);
1657*00b67f09SDavid van Moolenbroek if (result != ISC_R_SUCCESS)
1658*00b67f09SDavid van Moolenbroek return (result);
1659*00b67f09SDavid van Moolenbroek isc_task_attach(task, &dctx->task);
1660*00b67f09SDavid van Moolenbroek dctx->done = done;
1661*00b67f09SDavid van Moolenbroek dctx->done_arg = done_arg;
1662*00b67f09SDavid van Moolenbroek dctx->nodes = 100;
1663*00b67f09SDavid van Moolenbroek
1664*00b67f09SDavid van Moolenbroek result = task_send(dctx);
1665*00b67f09SDavid van Moolenbroek if (result == ISC_R_SUCCESS) {
1666*00b67f09SDavid van Moolenbroek dns_dumpctx_attach(dctx, dctxp);
1667*00b67f09SDavid van Moolenbroek return (DNS_R_CONTINUE);
1668*00b67f09SDavid van Moolenbroek }
1669*00b67f09SDavid van Moolenbroek
1670*00b67f09SDavid van Moolenbroek dns_dumpctx_detach(&dctx);
1671*00b67f09SDavid van Moolenbroek return (result);
1672*00b67f09SDavid van Moolenbroek }
1673*00b67f09SDavid van Moolenbroek
1674*00b67f09SDavid van Moolenbroek /*
1675*00b67f09SDavid van Moolenbroek * Dump an entire database into a master file.
1676*00b67f09SDavid van Moolenbroek */
1677*00b67f09SDavid van Moolenbroek isc_result_t
dns_master_dumptostream(isc_mem_t * mctx,dns_db_t * db,dns_dbversion_t * version,const dns_master_style_t * style,FILE * f)1678*00b67f09SDavid van Moolenbroek dns_master_dumptostream(isc_mem_t *mctx, dns_db_t *db,
1679*00b67f09SDavid van Moolenbroek dns_dbversion_t *version,
1680*00b67f09SDavid van Moolenbroek const dns_master_style_t *style,
1681*00b67f09SDavid van Moolenbroek FILE *f)
1682*00b67f09SDavid van Moolenbroek {
1683*00b67f09SDavid van Moolenbroek return (dns_master_dumptostream3(mctx, db, version, style,
1684*00b67f09SDavid van Moolenbroek dns_masterformat_text, NULL, f));
1685*00b67f09SDavid van Moolenbroek }
1686*00b67f09SDavid van Moolenbroek
1687*00b67f09SDavid van Moolenbroek isc_result_t
dns_master_dumptostream2(isc_mem_t * mctx,dns_db_t * db,dns_dbversion_t * version,const dns_master_style_t * style,dns_masterformat_t format,FILE * f)1688*00b67f09SDavid van Moolenbroek dns_master_dumptostream2(isc_mem_t *mctx, dns_db_t *db,
1689*00b67f09SDavid van Moolenbroek dns_dbversion_t *version,
1690*00b67f09SDavid van Moolenbroek const dns_master_style_t *style,
1691*00b67f09SDavid van Moolenbroek dns_masterformat_t format, FILE *f)
1692*00b67f09SDavid van Moolenbroek {
1693*00b67f09SDavid van Moolenbroek return (dns_master_dumptostream3(mctx, db, version, style,
1694*00b67f09SDavid van Moolenbroek format, NULL, f));
1695*00b67f09SDavid van Moolenbroek }
1696*00b67f09SDavid van Moolenbroek
1697*00b67f09SDavid van Moolenbroek isc_result_t
dns_master_dumptostream3(isc_mem_t * mctx,dns_db_t * db,dns_dbversion_t * version,const dns_master_style_t * style,dns_masterformat_t format,dns_masterrawheader_t * header,FILE * f)1698*00b67f09SDavid van Moolenbroek dns_master_dumptostream3(isc_mem_t *mctx, dns_db_t *db,
1699*00b67f09SDavid van Moolenbroek dns_dbversion_t *version,
1700*00b67f09SDavid van Moolenbroek const dns_master_style_t *style,
1701*00b67f09SDavid van Moolenbroek dns_masterformat_t format,
1702*00b67f09SDavid van Moolenbroek dns_masterrawheader_t *header, FILE *f)
1703*00b67f09SDavid van Moolenbroek {
1704*00b67f09SDavid van Moolenbroek dns_dumpctx_t *dctx = NULL;
1705*00b67f09SDavid van Moolenbroek isc_result_t result;
1706*00b67f09SDavid van Moolenbroek
1707*00b67f09SDavid van Moolenbroek result = dumpctx_create(mctx, db, version, style, f, &dctx,
1708*00b67f09SDavid van Moolenbroek format, header);
1709*00b67f09SDavid van Moolenbroek if (result != ISC_R_SUCCESS)
1710*00b67f09SDavid van Moolenbroek return (result);
1711*00b67f09SDavid van Moolenbroek
1712*00b67f09SDavid van Moolenbroek result = dumptostreaminc(dctx);
1713*00b67f09SDavid van Moolenbroek INSIST(result != DNS_R_CONTINUE);
1714*00b67f09SDavid van Moolenbroek dns_dumpctx_detach(&dctx);
1715*00b67f09SDavid van Moolenbroek
1716*00b67f09SDavid van Moolenbroek result = flushandsync(f, result, NULL);
1717*00b67f09SDavid van Moolenbroek return (result);
1718*00b67f09SDavid van Moolenbroek }
1719*00b67f09SDavid van Moolenbroek
1720*00b67f09SDavid van Moolenbroek static isc_result_t
opentmp(isc_mem_t * mctx,dns_masterformat_t format,const char * file,char ** tempp,FILE ** fp)1721*00b67f09SDavid van Moolenbroek opentmp(isc_mem_t *mctx, dns_masterformat_t format, const char *file,
1722*00b67f09SDavid van Moolenbroek char **tempp, FILE **fp) {
1723*00b67f09SDavid van Moolenbroek FILE *f = NULL;
1724*00b67f09SDavid van Moolenbroek isc_result_t result;
1725*00b67f09SDavid van Moolenbroek char *tempname = NULL;
1726*00b67f09SDavid van Moolenbroek int tempnamelen;
1727*00b67f09SDavid van Moolenbroek
1728*00b67f09SDavid van Moolenbroek tempnamelen = strlen(file) + 20;
1729*00b67f09SDavid van Moolenbroek tempname = isc_mem_allocate(mctx, tempnamelen);
1730*00b67f09SDavid van Moolenbroek if (tempname == NULL)
1731*00b67f09SDavid van Moolenbroek return (ISC_R_NOMEMORY);
1732*00b67f09SDavid van Moolenbroek
1733*00b67f09SDavid van Moolenbroek result = isc_file_mktemplate(file, tempname, tempnamelen);
1734*00b67f09SDavid van Moolenbroek if (result != ISC_R_SUCCESS)
1735*00b67f09SDavid van Moolenbroek goto cleanup;
1736*00b67f09SDavid van Moolenbroek
1737*00b67f09SDavid van Moolenbroek if (format == dns_masterformat_text)
1738*00b67f09SDavid van Moolenbroek result = isc_file_openunique(tempname, &f);
1739*00b67f09SDavid van Moolenbroek else
1740*00b67f09SDavid van Moolenbroek result = isc_file_bopenunique(tempname, &f);
1741*00b67f09SDavid van Moolenbroek if (result != ISC_R_SUCCESS) {
1742*00b67f09SDavid van Moolenbroek isc_log_write(dns_lctx, ISC_LOGCATEGORY_GENERAL,
1743*00b67f09SDavid van Moolenbroek DNS_LOGMODULE_MASTERDUMP, ISC_LOG_ERROR,
1744*00b67f09SDavid van Moolenbroek "dumping master file: %s: open: %s",
1745*00b67f09SDavid van Moolenbroek tempname, isc_result_totext(result));
1746*00b67f09SDavid van Moolenbroek goto cleanup;
1747*00b67f09SDavid van Moolenbroek }
1748*00b67f09SDavid van Moolenbroek *tempp = tempname;
1749*00b67f09SDavid van Moolenbroek *fp = f;
1750*00b67f09SDavid van Moolenbroek return (ISC_R_SUCCESS);
1751*00b67f09SDavid van Moolenbroek
1752*00b67f09SDavid van Moolenbroek cleanup:
1753*00b67f09SDavid van Moolenbroek isc_mem_free(mctx, tempname);
1754*00b67f09SDavid van Moolenbroek return (result);
1755*00b67f09SDavid van Moolenbroek }
1756*00b67f09SDavid van Moolenbroek
1757*00b67f09SDavid van Moolenbroek isc_result_t
dns_master_dumpinc(isc_mem_t * mctx,dns_db_t * db,dns_dbversion_t * version,const dns_master_style_t * style,const char * filename,isc_task_t * task,dns_dumpdonefunc_t done,void * done_arg,dns_dumpctx_t ** dctxp)1758*00b67f09SDavid van Moolenbroek dns_master_dumpinc(isc_mem_t *mctx, dns_db_t *db, dns_dbversion_t *version,
1759*00b67f09SDavid van Moolenbroek const dns_master_style_t *style, const char *filename,
1760*00b67f09SDavid van Moolenbroek isc_task_t *task, dns_dumpdonefunc_t done, void *done_arg,
1761*00b67f09SDavid van Moolenbroek dns_dumpctx_t **dctxp)
1762*00b67f09SDavid van Moolenbroek {
1763*00b67f09SDavid van Moolenbroek return (dns_master_dumpinc3(mctx, db, version, style, filename, task,
1764*00b67f09SDavid van Moolenbroek done, done_arg, dctxp,
1765*00b67f09SDavid van Moolenbroek dns_masterformat_text, NULL));
1766*00b67f09SDavid van Moolenbroek }
1767*00b67f09SDavid van Moolenbroek
1768*00b67f09SDavid van Moolenbroek isc_result_t
dns_master_dumpinc2(isc_mem_t * mctx,dns_db_t * db,dns_dbversion_t * version,const dns_master_style_t * style,const char * filename,isc_task_t * task,dns_dumpdonefunc_t done,void * done_arg,dns_dumpctx_t ** dctxp,dns_masterformat_t format)1769*00b67f09SDavid van Moolenbroek dns_master_dumpinc2(isc_mem_t *mctx, dns_db_t *db, dns_dbversion_t *version,
1770*00b67f09SDavid van Moolenbroek const dns_master_style_t *style, const char *filename,
1771*00b67f09SDavid van Moolenbroek isc_task_t *task, dns_dumpdonefunc_t done, void *done_arg,
1772*00b67f09SDavid van Moolenbroek dns_dumpctx_t **dctxp, dns_masterformat_t format)
1773*00b67f09SDavid van Moolenbroek {
1774*00b67f09SDavid van Moolenbroek return (dns_master_dumpinc3(mctx, db, version, style, filename, task,
1775*00b67f09SDavid van Moolenbroek done, done_arg, dctxp, format, NULL));
1776*00b67f09SDavid van Moolenbroek }
1777*00b67f09SDavid van Moolenbroek
1778*00b67f09SDavid van Moolenbroek isc_result_t
dns_master_dumpinc3(isc_mem_t * mctx,dns_db_t * db,dns_dbversion_t * version,const dns_master_style_t * style,const char * filename,isc_task_t * task,dns_dumpdonefunc_t done,void * done_arg,dns_dumpctx_t ** dctxp,dns_masterformat_t format,dns_masterrawheader_t * header)1779*00b67f09SDavid van Moolenbroek dns_master_dumpinc3(isc_mem_t *mctx, dns_db_t *db, dns_dbversion_t *version,
1780*00b67f09SDavid van Moolenbroek const dns_master_style_t *style, const char *filename,
1781*00b67f09SDavid van Moolenbroek isc_task_t *task, dns_dumpdonefunc_t done, void *done_arg,
1782*00b67f09SDavid van Moolenbroek dns_dumpctx_t **dctxp, dns_masterformat_t format,
1783*00b67f09SDavid van Moolenbroek dns_masterrawheader_t *header)
1784*00b67f09SDavid van Moolenbroek {
1785*00b67f09SDavid van Moolenbroek FILE *f = NULL;
1786*00b67f09SDavid van Moolenbroek isc_result_t result;
1787*00b67f09SDavid van Moolenbroek char *tempname = NULL;
1788*00b67f09SDavid van Moolenbroek char *file = NULL;
1789*00b67f09SDavid van Moolenbroek dns_dumpctx_t *dctx = NULL;
1790*00b67f09SDavid van Moolenbroek
1791*00b67f09SDavid van Moolenbroek file = isc_mem_strdup(mctx, filename);
1792*00b67f09SDavid van Moolenbroek if (file == NULL)
1793*00b67f09SDavid van Moolenbroek return (ISC_R_NOMEMORY);
1794*00b67f09SDavid van Moolenbroek
1795*00b67f09SDavid van Moolenbroek result = opentmp(mctx, format, filename, &tempname, &f);
1796*00b67f09SDavid van Moolenbroek if (result != ISC_R_SUCCESS)
1797*00b67f09SDavid van Moolenbroek goto cleanup;
1798*00b67f09SDavid van Moolenbroek
1799*00b67f09SDavid van Moolenbroek result = dumpctx_create(mctx, db, version, style, f, &dctx,
1800*00b67f09SDavid van Moolenbroek format, header);
1801*00b67f09SDavid van Moolenbroek if (result != ISC_R_SUCCESS) {
1802*00b67f09SDavid van Moolenbroek (void)isc_stdio_close(f);
1803*00b67f09SDavid van Moolenbroek (void)isc_file_remove(tempname);
1804*00b67f09SDavid van Moolenbroek goto cleanup;
1805*00b67f09SDavid van Moolenbroek }
1806*00b67f09SDavid van Moolenbroek
1807*00b67f09SDavid van Moolenbroek isc_task_attach(task, &dctx->task);
1808*00b67f09SDavid van Moolenbroek dctx->done = done;
1809*00b67f09SDavid van Moolenbroek dctx->done_arg = done_arg;
1810*00b67f09SDavid van Moolenbroek dctx->nodes = 100;
1811*00b67f09SDavid van Moolenbroek dctx->file = file;
1812*00b67f09SDavid van Moolenbroek file = NULL;
1813*00b67f09SDavid van Moolenbroek dctx->tmpfile = tempname;
1814*00b67f09SDavid van Moolenbroek tempname = NULL;
1815*00b67f09SDavid van Moolenbroek
1816*00b67f09SDavid van Moolenbroek result = task_send(dctx);
1817*00b67f09SDavid van Moolenbroek if (result == ISC_R_SUCCESS) {
1818*00b67f09SDavid van Moolenbroek dns_dumpctx_attach(dctx, dctxp);
1819*00b67f09SDavid van Moolenbroek return (DNS_R_CONTINUE);
1820*00b67f09SDavid van Moolenbroek }
1821*00b67f09SDavid van Moolenbroek
1822*00b67f09SDavid van Moolenbroek cleanup:
1823*00b67f09SDavid van Moolenbroek if (dctx != NULL)
1824*00b67f09SDavid van Moolenbroek dns_dumpctx_detach(&dctx);
1825*00b67f09SDavid van Moolenbroek if (file != NULL)
1826*00b67f09SDavid van Moolenbroek isc_mem_free(mctx, file);
1827*00b67f09SDavid van Moolenbroek if (tempname != NULL)
1828*00b67f09SDavid van Moolenbroek isc_mem_free(mctx, tempname);
1829*00b67f09SDavid van Moolenbroek return (result);
1830*00b67f09SDavid van Moolenbroek }
1831*00b67f09SDavid van Moolenbroek
1832*00b67f09SDavid van Moolenbroek isc_result_t
dns_master_dump(isc_mem_t * mctx,dns_db_t * db,dns_dbversion_t * version,const dns_master_style_t * style,const char * filename)1833*00b67f09SDavid van Moolenbroek dns_master_dump(isc_mem_t *mctx, dns_db_t *db, dns_dbversion_t *version,
1834*00b67f09SDavid van Moolenbroek const dns_master_style_t *style, const char *filename)
1835*00b67f09SDavid van Moolenbroek {
1836*00b67f09SDavid van Moolenbroek return (dns_master_dump3(mctx, db, version, style, filename,
1837*00b67f09SDavid van Moolenbroek dns_masterformat_text, NULL));
1838*00b67f09SDavid van Moolenbroek }
1839*00b67f09SDavid van Moolenbroek
1840*00b67f09SDavid van Moolenbroek isc_result_t
dns_master_dump2(isc_mem_t * mctx,dns_db_t * db,dns_dbversion_t * version,const dns_master_style_t * style,const char * filename,dns_masterformat_t format)1841*00b67f09SDavid van Moolenbroek dns_master_dump2(isc_mem_t *mctx, dns_db_t *db, dns_dbversion_t *version,
1842*00b67f09SDavid van Moolenbroek const dns_master_style_t *style, const char *filename,
1843*00b67f09SDavid van Moolenbroek dns_masterformat_t format)
1844*00b67f09SDavid van Moolenbroek {
1845*00b67f09SDavid van Moolenbroek return (dns_master_dump3(mctx, db, version, style, filename,
1846*00b67f09SDavid van Moolenbroek format, NULL));
1847*00b67f09SDavid van Moolenbroek }
1848*00b67f09SDavid van Moolenbroek
1849*00b67f09SDavid van Moolenbroek isc_result_t
dns_master_dump3(isc_mem_t * mctx,dns_db_t * db,dns_dbversion_t * version,const dns_master_style_t * style,const char * filename,dns_masterformat_t format,dns_masterrawheader_t * header)1850*00b67f09SDavid van Moolenbroek dns_master_dump3(isc_mem_t *mctx, dns_db_t *db, dns_dbversion_t *version,
1851*00b67f09SDavid van Moolenbroek const dns_master_style_t *style, const char *filename,
1852*00b67f09SDavid van Moolenbroek dns_masterformat_t format, dns_masterrawheader_t *header)
1853*00b67f09SDavid van Moolenbroek {
1854*00b67f09SDavid van Moolenbroek FILE *f = NULL;
1855*00b67f09SDavid van Moolenbroek isc_result_t result;
1856*00b67f09SDavid van Moolenbroek char *tempname;
1857*00b67f09SDavid van Moolenbroek dns_dumpctx_t *dctx = NULL;
1858*00b67f09SDavid van Moolenbroek
1859*00b67f09SDavid van Moolenbroek result = opentmp(mctx, format, filename, &tempname, &f);
1860*00b67f09SDavid van Moolenbroek if (result != ISC_R_SUCCESS)
1861*00b67f09SDavid van Moolenbroek return (result);
1862*00b67f09SDavid van Moolenbroek
1863*00b67f09SDavid van Moolenbroek result = dumpctx_create(mctx, db, version, style, f, &dctx,
1864*00b67f09SDavid van Moolenbroek format, header);
1865*00b67f09SDavid van Moolenbroek if (result != ISC_R_SUCCESS)
1866*00b67f09SDavid van Moolenbroek goto cleanup;
1867*00b67f09SDavid van Moolenbroek
1868*00b67f09SDavid van Moolenbroek result = dumptostreaminc(dctx);
1869*00b67f09SDavid van Moolenbroek INSIST(result != DNS_R_CONTINUE);
1870*00b67f09SDavid van Moolenbroek dns_dumpctx_detach(&dctx);
1871*00b67f09SDavid van Moolenbroek
1872*00b67f09SDavid van Moolenbroek result = closeandrename(f, result, tempname, filename);
1873*00b67f09SDavid van Moolenbroek
1874*00b67f09SDavid van Moolenbroek cleanup:
1875*00b67f09SDavid van Moolenbroek isc_mem_free(mctx, tempname);
1876*00b67f09SDavid van Moolenbroek return (result);
1877*00b67f09SDavid van Moolenbroek }
1878*00b67f09SDavid van Moolenbroek
1879*00b67f09SDavid van Moolenbroek /*
1880*00b67f09SDavid van Moolenbroek * Dump a database node into a master file.
1881*00b67f09SDavid van Moolenbroek * XXX: this function assumes the text format.
1882*00b67f09SDavid van Moolenbroek */
1883*00b67f09SDavid van Moolenbroek isc_result_t
dns_master_dumpnodetostream(isc_mem_t * mctx,dns_db_t * db,dns_dbversion_t * version,dns_dbnode_t * node,dns_name_t * name,const dns_master_style_t * style,FILE * f)1884*00b67f09SDavid van Moolenbroek dns_master_dumpnodetostream(isc_mem_t *mctx, dns_db_t *db,
1885*00b67f09SDavid van Moolenbroek dns_dbversion_t *version,
1886*00b67f09SDavid van Moolenbroek dns_dbnode_t *node, dns_name_t *name,
1887*00b67f09SDavid van Moolenbroek const dns_master_style_t *style,
1888*00b67f09SDavid van Moolenbroek FILE *f)
1889*00b67f09SDavid van Moolenbroek {
1890*00b67f09SDavid van Moolenbroek isc_result_t result;
1891*00b67f09SDavid van Moolenbroek isc_buffer_t buffer;
1892*00b67f09SDavid van Moolenbroek char *bufmem;
1893*00b67f09SDavid van Moolenbroek isc_stdtime_t now;
1894*00b67f09SDavid van Moolenbroek dns_totext_ctx_t ctx;
1895*00b67f09SDavid van Moolenbroek dns_rdatasetiter_t *rdsiter = NULL;
1896*00b67f09SDavid van Moolenbroek
1897*00b67f09SDavid van Moolenbroek result = totext_ctx_init(style, &ctx);
1898*00b67f09SDavid van Moolenbroek if (result != ISC_R_SUCCESS) {
1899*00b67f09SDavid van Moolenbroek UNEXPECTED_ERROR(__FILE__, __LINE__,
1900*00b67f09SDavid van Moolenbroek "could not set master file style");
1901*00b67f09SDavid van Moolenbroek return (ISC_R_UNEXPECTED);
1902*00b67f09SDavid van Moolenbroek }
1903*00b67f09SDavid van Moolenbroek
1904*00b67f09SDavid van Moolenbroek isc_stdtime_get(&now);
1905*00b67f09SDavid van Moolenbroek
1906*00b67f09SDavid van Moolenbroek bufmem = isc_mem_get(mctx, initial_buffer_length);
1907*00b67f09SDavid van Moolenbroek if (bufmem == NULL)
1908*00b67f09SDavid van Moolenbroek return (ISC_R_NOMEMORY);
1909*00b67f09SDavid van Moolenbroek
1910*00b67f09SDavid van Moolenbroek isc_buffer_init(&buffer, bufmem, initial_buffer_length);
1911*00b67f09SDavid van Moolenbroek
1912*00b67f09SDavid van Moolenbroek result = dns_db_allrdatasets(db, node, version, now, &rdsiter);
1913*00b67f09SDavid van Moolenbroek if (result != ISC_R_SUCCESS)
1914*00b67f09SDavid van Moolenbroek goto failure;
1915*00b67f09SDavid van Moolenbroek result = dump_rdatasets_text(mctx, name, rdsiter, &ctx, &buffer, f);
1916*00b67f09SDavid van Moolenbroek if (result != ISC_R_SUCCESS)
1917*00b67f09SDavid van Moolenbroek goto failure;
1918*00b67f09SDavid van Moolenbroek dns_rdatasetiter_destroy(&rdsiter);
1919*00b67f09SDavid van Moolenbroek
1920*00b67f09SDavid van Moolenbroek result = ISC_R_SUCCESS;
1921*00b67f09SDavid van Moolenbroek
1922*00b67f09SDavid van Moolenbroek failure:
1923*00b67f09SDavid van Moolenbroek isc_mem_put(mctx, buffer.base, buffer.length);
1924*00b67f09SDavid van Moolenbroek return (result);
1925*00b67f09SDavid van Moolenbroek }
1926*00b67f09SDavid van Moolenbroek
1927*00b67f09SDavid van Moolenbroek isc_result_t
dns_master_dumpnode(isc_mem_t * mctx,dns_db_t * db,dns_dbversion_t * version,dns_dbnode_t * node,dns_name_t * name,const dns_master_style_t * style,const char * filename)1928*00b67f09SDavid van Moolenbroek dns_master_dumpnode(isc_mem_t *mctx, dns_db_t *db, dns_dbversion_t *version,
1929*00b67f09SDavid van Moolenbroek dns_dbnode_t *node, dns_name_t *name,
1930*00b67f09SDavid van Moolenbroek const dns_master_style_t *style, const char *filename)
1931*00b67f09SDavid van Moolenbroek {
1932*00b67f09SDavid van Moolenbroek FILE *f = NULL;
1933*00b67f09SDavid van Moolenbroek isc_result_t result;
1934*00b67f09SDavid van Moolenbroek
1935*00b67f09SDavid van Moolenbroek result = isc_stdio_open(filename, "w", &f);
1936*00b67f09SDavid van Moolenbroek if (result != ISC_R_SUCCESS) {
1937*00b67f09SDavid van Moolenbroek isc_log_write(dns_lctx, ISC_LOGCATEGORY_GENERAL,
1938*00b67f09SDavid van Moolenbroek DNS_LOGMODULE_MASTERDUMP, ISC_LOG_ERROR,
1939*00b67f09SDavid van Moolenbroek "dumping node to file: %s: open: %s", filename,
1940*00b67f09SDavid van Moolenbroek isc_result_totext(result));
1941*00b67f09SDavid van Moolenbroek return (ISC_R_UNEXPECTED);
1942*00b67f09SDavid van Moolenbroek }
1943*00b67f09SDavid van Moolenbroek
1944*00b67f09SDavid van Moolenbroek result = dns_master_dumpnodetostream(mctx, db, version, node, name,
1945*00b67f09SDavid van Moolenbroek style, f);
1946*00b67f09SDavid van Moolenbroek if (result != ISC_R_SUCCESS) {
1947*00b67f09SDavid van Moolenbroek isc_log_write(dns_lctx, ISC_LOGCATEGORY_GENERAL,
1948*00b67f09SDavid van Moolenbroek DNS_LOGMODULE_MASTERDUMP, ISC_LOG_ERROR,
1949*00b67f09SDavid van Moolenbroek "dumping master file: %s: dump: %s", filename,
1950*00b67f09SDavid van Moolenbroek isc_result_totext(result));
1951*00b67f09SDavid van Moolenbroek (void)isc_stdio_close(f);
1952*00b67f09SDavid van Moolenbroek return (ISC_R_UNEXPECTED);
1953*00b67f09SDavid van Moolenbroek }
1954*00b67f09SDavid van Moolenbroek
1955*00b67f09SDavid van Moolenbroek result = isc_stdio_close(f);
1956*00b67f09SDavid van Moolenbroek if (result != ISC_R_SUCCESS) {
1957*00b67f09SDavid van Moolenbroek isc_log_write(dns_lctx, ISC_LOGCATEGORY_GENERAL,
1958*00b67f09SDavid van Moolenbroek DNS_LOGMODULE_MASTERDUMP, ISC_LOG_ERROR,
1959*00b67f09SDavid van Moolenbroek "dumping master file: %s: close: %s", filename,
1960*00b67f09SDavid van Moolenbroek isc_result_totext(result));
1961*00b67f09SDavid van Moolenbroek return (ISC_R_UNEXPECTED);
1962*00b67f09SDavid van Moolenbroek }
1963*00b67f09SDavid van Moolenbroek
1964*00b67f09SDavid van Moolenbroek return (result);
1965*00b67f09SDavid van Moolenbroek }
1966*00b67f09SDavid van Moolenbroek
1967*00b67f09SDavid van Moolenbroek isc_result_t
dns_master_stylecreate(dns_master_style_t ** stylep,unsigned int flags,unsigned int ttl_column,unsigned int class_column,unsigned int type_column,unsigned int rdata_column,unsigned int line_length,unsigned int tab_width,isc_mem_t * mctx)1968*00b67f09SDavid van Moolenbroek dns_master_stylecreate(dns_master_style_t **stylep, unsigned int flags,
1969*00b67f09SDavid van Moolenbroek unsigned int ttl_column, unsigned int class_column,
1970*00b67f09SDavid van Moolenbroek unsigned int type_column, unsigned int rdata_column,
1971*00b67f09SDavid van Moolenbroek unsigned int line_length, unsigned int tab_width,
1972*00b67f09SDavid van Moolenbroek isc_mem_t *mctx)
1973*00b67f09SDavid van Moolenbroek {
1974*00b67f09SDavid van Moolenbroek return (dns_master_stylecreate2(stylep, flags, ttl_column,
1975*00b67f09SDavid van Moolenbroek class_column, type_column,
1976*00b67f09SDavid van Moolenbroek rdata_column, line_length,
1977*00b67f09SDavid van Moolenbroek tab_width, 0xffffffff, mctx));
1978*00b67f09SDavid van Moolenbroek }
1979*00b67f09SDavid van Moolenbroek
1980*00b67f09SDavid van Moolenbroek isc_result_t
dns_master_stylecreate2(dns_master_style_t ** stylep,unsigned int flags,unsigned int ttl_column,unsigned int class_column,unsigned int type_column,unsigned int rdata_column,unsigned int line_length,unsigned int tab_width,unsigned int split_width,isc_mem_t * mctx)1981*00b67f09SDavid van Moolenbroek dns_master_stylecreate2(dns_master_style_t **stylep, unsigned int flags,
1982*00b67f09SDavid van Moolenbroek unsigned int ttl_column, unsigned int class_column,
1983*00b67f09SDavid van Moolenbroek unsigned int type_column, unsigned int rdata_column,
1984*00b67f09SDavid van Moolenbroek unsigned int line_length, unsigned int tab_width,
1985*00b67f09SDavid van Moolenbroek unsigned int split_width, isc_mem_t *mctx)
1986*00b67f09SDavid van Moolenbroek {
1987*00b67f09SDavid van Moolenbroek dns_master_style_t *style;
1988*00b67f09SDavid van Moolenbroek
1989*00b67f09SDavid van Moolenbroek REQUIRE(stylep != NULL && *stylep == NULL);
1990*00b67f09SDavid van Moolenbroek style = isc_mem_get(mctx, sizeof(*style));
1991*00b67f09SDavid van Moolenbroek if (style == NULL)
1992*00b67f09SDavid van Moolenbroek return (ISC_R_NOMEMORY);
1993*00b67f09SDavid van Moolenbroek
1994*00b67f09SDavid van Moolenbroek style->flags = flags;
1995*00b67f09SDavid van Moolenbroek style->ttl_column = ttl_column;
1996*00b67f09SDavid van Moolenbroek style->class_column = class_column;
1997*00b67f09SDavid van Moolenbroek style->type_column = type_column;
1998*00b67f09SDavid van Moolenbroek style->rdata_column = rdata_column;
1999*00b67f09SDavid van Moolenbroek style->line_length = line_length;
2000*00b67f09SDavid van Moolenbroek style->tab_width = tab_width;
2001*00b67f09SDavid van Moolenbroek style->split_width = split_width;
2002*00b67f09SDavid van Moolenbroek
2003*00b67f09SDavid van Moolenbroek *stylep = style;
2004*00b67f09SDavid van Moolenbroek return (ISC_R_SUCCESS);
2005*00b67f09SDavid van Moolenbroek }
2006*00b67f09SDavid van Moolenbroek
2007*00b67f09SDavid van Moolenbroek void
dns_master_styledestroy(dns_master_style_t ** stylep,isc_mem_t * mctx)2008*00b67f09SDavid van Moolenbroek dns_master_styledestroy(dns_master_style_t **stylep, isc_mem_t *mctx) {
2009*00b67f09SDavid van Moolenbroek dns_master_style_t *style;
2010*00b67f09SDavid van Moolenbroek
2011*00b67f09SDavid van Moolenbroek REQUIRE(stylep != NULL && *stylep != NULL);
2012*00b67f09SDavid van Moolenbroek style = *stylep;
2013*00b67f09SDavid van Moolenbroek *stylep = NULL;
2014*00b67f09SDavid van Moolenbroek isc_mem_put(mctx, style, sizeof(*style));
2015*00b67f09SDavid van Moolenbroek }
2016