1*a6cc1574Ssthen /*
2*a6cc1574Ssthen * testcode/readzone.c - readzone tool reads zonefiles
3*a6cc1574Ssthen *
4*a6cc1574Ssthen * Copyright (c) 2021, NLnet Labs. All rights reserved.
5*a6cc1574Ssthen *
6*a6cc1574Ssthen * This software is open source.
7*a6cc1574Ssthen *
8*a6cc1574Ssthen * Redistribution and use in source and binary forms, with or without
9*a6cc1574Ssthen * modification, are permitted provided that the following conditions
10*a6cc1574Ssthen * are met:
11*a6cc1574Ssthen *
12*a6cc1574Ssthen * Redistributions of source code must retain the above copyright notice,
13*a6cc1574Ssthen * this list of conditions and the following disclaimer.
14*a6cc1574Ssthen *
15*a6cc1574Ssthen * Redistributions in binary form must reproduce the above copyright notice,
16*a6cc1574Ssthen * this list of conditions and the following disclaimer in the documentation
17*a6cc1574Ssthen * and/or other materials provided with the distribution.
18*a6cc1574Ssthen *
19*a6cc1574Ssthen * Neither the name of the NLNET LABS nor the names of its contributors may
20*a6cc1574Ssthen * be used to endorse or promote products derived from this software without
21*a6cc1574Ssthen * specific prior written permission.
22*a6cc1574Ssthen *
23*a6cc1574Ssthen * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24*a6cc1574Ssthen * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25*a6cc1574Ssthen * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
26*a6cc1574Ssthen * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
27*a6cc1574Ssthen * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
28*a6cc1574Ssthen * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
29*a6cc1574Ssthen * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
30*a6cc1574Ssthen * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
31*a6cc1574Ssthen * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
32*a6cc1574Ssthen * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33*a6cc1574Ssthen * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34*a6cc1574Ssthen *
35*a6cc1574Ssthen */
36*a6cc1574Ssthen /**
37*a6cc1574Ssthen * \file
38*a6cc1574Ssthen * Command to read and echo a zonefile.
39*a6cc1574Ssthen */
40*a6cc1574Ssthen
41*a6cc1574Ssthen #include "config.h"
42*a6cc1574Ssthen #include <stdio.h>
43*a6cc1574Ssthen #include <stdlib.h>
44*a6cc1574Ssthen #include <errno.h>
45*a6cc1574Ssthen #include <string.h>
46*a6cc1574Ssthen #include <unistd.h>
47*a6cc1574Ssthen
48*a6cc1574Ssthen #include "sldns/str2wire.h"
49*a6cc1574Ssthen #include "sldns/wire2str.h"
50*a6cc1574Ssthen
print_usage(FILE * out,const char * progname)51*a6cc1574Ssthen int print_usage(FILE *out, const char *progname)
52*a6cc1574Ssthen {
53*a6cc1574Ssthen fprintf(out, "usage: %s [ -u ] <zonefile> [<origin>]\n", progname);
54*a6cc1574Ssthen fprintf(out, "\t-u\tprint in unknown type (RFC3597) format\n");
55*a6cc1574Ssthen return out == stdout ? EXIT_SUCCESS : EXIT_FAILURE;
56*a6cc1574Ssthen }
57*a6cc1574Ssthen
main(int argc,char * const * argv)58*a6cc1574Ssthen int main(int argc, char *const *argv)
59*a6cc1574Ssthen {
60*a6cc1574Ssthen char *progname = argv[0];
61*a6cc1574Ssthen uint8_t rr[LDNS_RR_BUF_SIZE];
62*a6cc1574Ssthen char *str = malloc(1024 * 1024);
63*a6cc1574Ssthen size_t str_len = sizeof(str);
64*a6cc1574Ssthen struct sldns_file_parse_state state;
65*a6cc1574Ssthen FILE *in = NULL;
66*a6cc1574Ssthen int s = -1;
67*a6cc1574Ssthen int opt;
68*a6cc1574Ssthen int print_in_unknown_type_format = 0;
69*a6cc1574Ssthen
70*a6cc1574Ssthen while ((opt = getopt(argc, argv, "hu")) != -1) {
71*a6cc1574Ssthen switch (opt) {
72*a6cc1574Ssthen case 'h':
73*a6cc1574Ssthen free(str);
74*a6cc1574Ssthen return print_usage(stdout, progname);
75*a6cc1574Ssthen case 'u':
76*a6cc1574Ssthen print_in_unknown_type_format = 1;
77*a6cc1574Ssthen break;
78*a6cc1574Ssthen default:
79*a6cc1574Ssthen free(str);
80*a6cc1574Ssthen return print_usage(stderr, progname);
81*a6cc1574Ssthen }
82*a6cc1574Ssthen }
83*a6cc1574Ssthen argc -= optind;
84*a6cc1574Ssthen argv += optind;
85*a6cc1574Ssthen
86*a6cc1574Ssthen memset(&state, 0, sizeof(state));
87*a6cc1574Ssthen state.default_ttl = 3600;
88*a6cc1574Ssthen state.lineno = 1;
89*a6cc1574Ssthen if (argc == 2) {
90*a6cc1574Ssthen state.origin_len = sizeof(state.origin);
91*a6cc1574Ssthen s = sldns_str2wire_dname_buf(argv[1], state.origin
92*a6cc1574Ssthen , &state.origin_len);
93*a6cc1574Ssthen if (s) {
94*a6cc1574Ssthen fprintf(stderr, "Error parsing origin: %s\n"
95*a6cc1574Ssthen , sldns_get_errorstr_parse(s));
96*a6cc1574Ssthen free(str);
97*a6cc1574Ssthen return EXIT_FAILURE;
98*a6cc1574Ssthen }
99*a6cc1574Ssthen s = -1;
100*a6cc1574Ssthen }
101*a6cc1574Ssthen if (!str)
102*a6cc1574Ssthen fprintf(stderr, "Memory allocation error: %s\n"
103*a6cc1574Ssthen , strerror(errno));
104*a6cc1574Ssthen
105*a6cc1574Ssthen else if (argc != 1 && argc != 2) {
106*a6cc1574Ssthen free(str);
107*a6cc1574Ssthen return print_usage(stderr, progname);
108*a6cc1574Ssthen }
109*a6cc1574Ssthen
110*a6cc1574Ssthen else if (!(in = fopen(argv[0], "r")))
111*a6cc1574Ssthen fprintf(stderr, "Error opening \"%s\": %s\n"
112*a6cc1574Ssthen , argv[0], strerror(errno));
113*a6cc1574Ssthen else while (!feof(in)) {
114*a6cc1574Ssthen size_t rr_len = sizeof(rr), dname_len = 0;
115*a6cc1574Ssthen size_t written;
116*a6cc1574Ssthen
117*a6cc1574Ssthen s = sldns_fp2wire_rr_buf(in, rr, &rr_len, &dname_len, &state);
118*a6cc1574Ssthen if (s) {
119*a6cc1574Ssthen fprintf( stderr, "parse error %d:%d: %s\n"
120*a6cc1574Ssthen , state.lineno, LDNS_WIREPARSE_OFFSET(s)
121*a6cc1574Ssthen , sldns_get_errorstr_parse(s));
122*a6cc1574Ssthen break;
123*a6cc1574Ssthen }
124*a6cc1574Ssthen if (rr_len == 0)
125*a6cc1574Ssthen continue;
126*a6cc1574Ssthen
127*a6cc1574Ssthen if (print_in_unknown_type_format)
128*a6cc1574Ssthen written = sldns_wire2str_rr_unknown_buf(
129*a6cc1574Ssthen rr, rr_len, str, str_len);
130*a6cc1574Ssthen else
131*a6cc1574Ssthen written = sldns_wire2str_rr_buf(
132*a6cc1574Ssthen rr, rr_len, str, str_len);
133*a6cc1574Ssthen
134*a6cc1574Ssthen if (written > str_len) {
135*a6cc1574Ssthen while (written > str_len)
136*a6cc1574Ssthen str_len *= 2;
137*a6cc1574Ssthen free(str);
138*a6cc1574Ssthen if (!(str = malloc(str_len))) {
139*a6cc1574Ssthen fprintf(stderr, "Memory allocation error: %s\n"
140*a6cc1574Ssthen , strerror(errno));
141*a6cc1574Ssthen s = -1;
142*a6cc1574Ssthen break;
143*a6cc1574Ssthen }
144*a6cc1574Ssthen if (print_in_unknown_type_format)
145*a6cc1574Ssthen (void) sldns_wire2str_rr_unknown_buf(
146*a6cc1574Ssthen rr, rr_len, str, str_len);
147*a6cc1574Ssthen else
148*a6cc1574Ssthen (void) sldns_wire2str_rr_buf(
149*a6cc1574Ssthen rr, rr_len, str, str_len);
150*a6cc1574Ssthen }
151*a6cc1574Ssthen fprintf(stdout, "%s", str);
152*a6cc1574Ssthen }
153*a6cc1574Ssthen if (in)
154*a6cc1574Ssthen fclose(in);
155*a6cc1574Ssthen free(str);
156*a6cc1574Ssthen return !in || s ? EXIT_FAILURE : EXIT_SUCCESS;
157*a6cc1574Ssthen }
158