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