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