/* * read a zone file from disk and prints it, one RR per line * * (c) NLnetLabs 2005-2008 * * See the file LICENSE for the license */ #include "config.h" #include #include #include #include #include static void print_usage(const char* progname) { printf("Usage: %s [OPTIONS] \n", progname); printf("\tReads the zonefile and prints it.\n"); printf("\tThe RR count of the zone is printed to stderr.\n"); printf("\t-0 zeroize timestamps and signature in RRSIG records.\n"); printf("\t-b include Bubble Babble encoding of DS's.\n"); printf("\t-c canonicalize all rrs in the zone.\n"); printf("\t-d only show DNSSEC data from the zone\n"); printf("\t-e \n"); printf("\t\tDo not print RRs of the given .\n"); printf("\t\tThis option may be given multiple times.\n"); printf("\t\t-e is not meant to be used together with -E.\n"); printf("\t-E \n"); printf("\t\tPrint only RRs of the given .\n"); printf("\t\tThis option may be given multiple times.\n"); printf("\t\t-E is not meant to be used together with -e.\n"); printf("\t-h show this text\n"); printf("\t-n do not print the SOA record\n"); printf("\t-p prepend SOA serial with spaces so" " it takes exactly ten characters.\n"); printf("\t-s strip DNSSEC data from the zone\n"); printf("\t-S [[+|-] | YYYYMMDDxx | " " unixtime ]\n" "\t\tSet serial number to or," " when preceded by a sign,\n" "\t\toffset the existing number with " ". With YYYYMMDDxx\n" "\t\tthe serial is formatted as a datecounter" ", and with unixtime as\n" "\t\tthe number of seconds since 1-1-1970." " However, on serial\n" "\t\tnumber decrease, +1 is used in stead" ". (implies -s)\n"); printf("\t-u \n"); printf("\t\tMark for printing in unknown type format.\n"); printf("\t\tThis option may be given multiple times.\n"); printf("\t\t-u is not meant to be used together with -U.\n"); printf("\t-U \n"); printf("\t\tMark for not printing in unknown type format.\n"); printf("\t\tThis option may be given multiple times.\n"); printf( "\t\tThe first occurrence of the -U option marks all RR types for" "\n\t\tprinting in unknown type format except for the given ." "\n\t\tSubsequent -U options will clear the mark for those s" "\n\t\ttoo, so that only the given s will be printed in the" "\n\t\tpresentation format specific for those s.\n"); printf("\t\t-U is not meant to be used together with -u.\n"); printf("\t-v shows the version and exits\n"); printf("\t-z sort the zone (implies -c).\n"); printf("\nif no file is given standard input is read\n"); exit(EXIT_SUCCESS); } static void exclude_type(ldns_rdf **show_types, ldns_rr_type t) { ldns_status s; assert(show_types != NULL); if (! *show_types && LDNS_STATUS_OK != (s = ldns_rdf_bitmap_known_rr_types(show_types))) goto fail; s = ldns_nsec_bitmap_clear_type(*show_types, t); if (s == LDNS_STATUS_OK) return; fail: fprintf(stderr, "Cannot exclude rr type %s: %s\n" , ldns_rr_descript(t)->_name , ldns_get_errorstr_by_id(s)); exit(EXIT_FAILURE); } static void include_type(ldns_rdf **show_types, ldns_rr_type t) { ldns_status s; assert(show_types != NULL); if (! *show_types && LDNS_STATUS_OK != (s = ldns_rdf_bitmap_known_rr_types_space(show_types))) goto fail; s = ldns_nsec_bitmap_set_type(*show_types, t); if (s == LDNS_STATUS_OK) return; fail: fprintf(stderr, "Cannot exclude all rr types except %s: %s\n" , ldns_rr_descript(t)->_name , ldns_get_errorstr_by_id(s)); exit(EXIT_FAILURE); } int main(int argc, char **argv) { char *filename; FILE *fp; ldns_zone *z; int line_nr = 0; int c; bool canonicalize = false; bool sort = false; bool print_soa = true; ldns_status s; size_t i; ldns_rr_list *stripped_list; ldns_rr *cur_rr; ldns_output_format_storage fmt_storage; ldns_output_format* fmt = ldns_output_format_init(&fmt_storage); ldns_rdf *show_types = NULL; ldns_soa_serial_increment_func_t soa_serial_increment_func = NULL; int soa_serial_increment_func_data = 0; while ((c = getopt(argc, argv, "0bcde:E:hnpsS:u:U:vz")) != -1) { switch(c) { case '0': fmt->flags |= LDNS_FMT_ZEROIZE_RRSIGS; break; case 'b': fmt->flags |= ( LDNS_COMMENT_BUBBLEBABBLE | LDNS_COMMENT_FLAGS ); break; case 'c': canonicalize = true; break; case 'd': include_type(&show_types, LDNS_RR_TYPE_RRSIG); include_type(&show_types, LDNS_RR_TYPE_NSEC); include_type(&show_types, LDNS_RR_TYPE_NSEC3); break; case 'e': exclude_type(&show_types, ldns_get_rr_type_by_name(optarg)); break; case 'E': include_type(&show_types, ldns_get_rr_type_by_name(optarg)); break; case 'h': print_usage("ldns-read-zone"); break; case 'n': print_soa = false; break; case 'p': fmt->flags |= LDNS_FMT_PAD_SOA_SERIAL; break; case 's': case 'S': exclude_type(&show_types, LDNS_RR_TYPE_RRSIG); exclude_type(&show_types, LDNS_RR_TYPE_NSEC); exclude_type(&show_types, LDNS_RR_TYPE_NSEC3); if (c == 's') break; if (*optarg == '+' || *optarg == '-') { soa_serial_increment_func_data = atoi(optarg); soa_serial_increment_func = ldns_soa_serial_increment_by; } else if (! strtok(optarg, "0123456789")) { soa_serial_increment_func_data = atoi(optarg); soa_serial_increment_func = ldns_soa_serial_identity; } else if (!strcasecmp(optarg, "YYYYMMDDxx")){ soa_serial_increment_func = ldns_soa_serial_datecounter; } else if (!strcasecmp(optarg, "unixtime")){ soa_serial_increment_func = ldns_soa_serial_unixtime; } else { fprintf(stderr, "-S expects a number " "optionally preceded by a " "+ or - sign to indicate an " "offset, or the text YYYYMM" "DDxx or unixtime\n"); exit(EXIT_FAILURE); } break; case 'u': s = ldns_output_format_set_type(fmt, ldns_get_rr_type_by_name(optarg)); if (s != LDNS_STATUS_OK) { fprintf( stderr , "Cannot set rr type %s " "in output format to " "print as unknown type: %s\n" , ldns_rr_descript( ldns_get_rr_type_by_name(optarg) )->_name , ldns_get_errorstr_by_id(s) ); exit(EXIT_FAILURE); } break; case 'U': s = ldns_output_format_clear_type(fmt, ldns_get_rr_type_by_name(optarg)); if (s != LDNS_STATUS_OK) { fprintf( stderr , "Cannot set rr type %s " "in output format to not " "print as unknown type: %s\n" , ldns_rr_descript( ldns_get_rr_type_by_name(optarg) )->_name , ldns_get_errorstr_by_id(s) ); exit(EXIT_FAILURE); } break; case 'v': printf("read zone version %s (ldns version %s)\n", LDNS_VERSION, ldns_version()); exit(EXIT_SUCCESS); break; case 'z': canonicalize = true; sort = true; break; } } argc -= optind; argv += optind; if (argc == 0) { fp = stdin; } else { filename = argv[0]; fp = fopen(filename, "r"); if (!fp) { fprintf(stderr, "Unable to open %s: %s\n", filename, strerror(errno)); exit(EXIT_FAILURE); } } s = ldns_zone_new_frm_fp_l(&z, fp, NULL, 0, LDNS_RR_CLASS_IN, &line_nr); fclose(fp); if (s != LDNS_STATUS_OK) { fprintf(stderr, "%s at %d\n", ldns_get_errorstr_by_id(s), line_nr); exit(EXIT_FAILURE); } if (show_types) { if (print_soa) print_soa = ldns_nsec_bitmap_covers_type(show_types, LDNS_RR_TYPE_SOA); stripped_list = ldns_rr_list_new(); while ((cur_rr = ldns_rr_list_pop_rr(ldns_zone_rrs(z)))) if (ldns_nsec_bitmap_covers_type(show_types, ldns_rr_get_type(cur_rr))) ldns_rr_list_push_rr(stripped_list, cur_rr); else ldns_rr_free(cur_rr); ldns_rr_list_free(ldns_zone_rrs(z)); ldns_zone_set_rrs(z, stripped_list); } if (canonicalize) { ldns_rr2canonical(ldns_zone_soa(z)); for (i = 0; i < ldns_rr_list_rr_count(ldns_zone_rrs(z)); i++) { ldns_rr2canonical(ldns_rr_list_rr(ldns_zone_rrs(z), i)); } } if (sort) { ldns_zone_sort(z); } if (print_soa && ldns_zone_soa(z)) { if (soa_serial_increment_func) { ldns_rr_soa_increment_func_int( ldns_zone_soa(z) , soa_serial_increment_func , soa_serial_increment_func_data ); } ldns_rr_print_fmt(stdout, fmt, ldns_zone_soa(z)); } ldns_rr_list_print_fmt(stdout, fmt, ldns_zone_rrs(z)); ldns_zone_deep_free(z); exit(EXIT_SUCCESS); }