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 <stdint.h>
49#include "sldns/str2wire.h"
50#include "sldns/wire2str.h"
51
52int print_usage(FILE *out, const char *progname)
53{
54	fprintf(out, "usage: %s [ -u ] <zonefile> [<origin>]\n", progname);
55	fprintf(out, "\t-u\tprint in unknown type (RFC3597) format\n");
56	return out == stdout ? EXIT_SUCCESS : EXIT_FAILURE;
57}
58
59int main(int argc, char *const *argv)
60{
61	char *progname = argv[0];
62	uint8_t rr[LDNS_RR_BUF_SIZE];
63	char *str = malloc(1024 * 1024);
64	size_t str_len = sizeof(str);
65	struct sldns_file_parse_state state;
66	FILE *in = NULL;
67	int s = -1;
68	int opt;
69	int print_in_unknown_type_format = 0;
70
71	while ((opt = getopt(argc, argv, "hu")) != -1) {
72		switch (opt) {
73		case 'h':
74			free(str);
75			return print_usage(stdout, progname);
76		case 'u':
77			print_in_unknown_type_format = 1;
78			break;
79		default:
80			free(str);
81			return print_usage(stderr, progname);
82		}
83	}
84	argc -= optind;
85	argv += optind;
86
87	memset(&state, 0, sizeof(state));
88	state.default_ttl = 3600;
89	state.lineno = 1;
90	if (argc == 2) {
91		state.origin_len = sizeof(state.origin);
92		s = sldns_str2wire_dname_buf(argv[1], state.origin
93		                                    , &state.origin_len);
94		if (s) {
95			fprintf(stderr, "Error parsing origin: %s\n"
96			              , sldns_get_errorstr_parse(s));
97			free(str);
98			return EXIT_FAILURE;
99		}
100		s = -1;
101	}
102	if (!str)
103		fprintf(stderr, "Memory allocation error: %s\n"
104		              , strerror(errno));
105
106	else if (argc != 1 && argc != 2) {
107		free(str);
108		return print_usage(stderr, progname);
109	}
110
111	else if (!(in = fopen(argv[0], "r")))
112		fprintf(stderr, "Error opening \"%s\": %s\n"
113		              , argv[0], strerror(errno));
114	else while (!feof(in)) {
115		size_t rr_len = sizeof(rr), dname_len = 0;
116		size_t written;
117
118		s = sldns_fp2wire_rr_buf(in, rr, &rr_len, &dname_len, &state);
119		if (s) {
120			fprintf( stderr, "parse error %d:%d: %s\n"
121			               , state.lineno, LDNS_WIREPARSE_OFFSET(s)
122			               , sldns_get_errorstr_parse(s));
123			break;
124		}
125		if (rr_len == 0)
126			continue;
127
128		if (print_in_unknown_type_format)
129			written = sldns_wire2str_rr_unknown_buf(
130				rr, rr_len, str, str_len);
131		else
132			written = sldns_wire2str_rr_buf(
133				rr, rr_len, str, str_len);
134
135		if (written > str_len) {
136			while (written > str_len)
137				str_len *= 2;
138			free(str);
139			if (!(str = malloc(str_len))) {
140				fprintf(stderr, "Memory allocation error: %s\n"
141				              , strerror(errno));
142				s = -1;
143				break;
144			}
145			if (print_in_unknown_type_format)
146				(void) sldns_wire2str_rr_unknown_buf(
147					rr, rr_len, str, str_len);
148			else
149				(void) sldns_wire2str_rr_buf(
150					rr, rr_len, str, str_len);
151		}
152		fprintf(stdout, "%s", str);
153	}
154	if (in)
155		fclose(in);
156	free(str);
157	return !in || s ? EXIT_FAILURE : EXIT_SUCCESS;
158}
159