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 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 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