ldns-read-zone.c
Go to the documentation of this file.
00001 /*
00002  * read a zone file from disk and prints it, one RR per line
00003  *
00004  * (c) NLnetLabs 2005-2008
00005  *
00006  * See the file LICENSE for the license
00007  */
00008 
00009 #include "config.h"
00010 #include <unistd.h>
00011 #include <stdlib.h>
00012 
00013 #include <ldns/ldns.h>
00014 #include <ldns/host2str.h>
00015 
00016 #include <errno.h>
00017 
00018 void print_usage(const char* progname)
00019 {
00020         printf("Usage: %s [OPTIONS] <zonefile>\n", progname);
00021         printf("\tReads the zonefile and prints it.\n");
00022         printf("\tThe RR count of the zone is printed to stderr.\n");
00023         printf("\t-b include Bubble Babble encoding of DS's.\n");
00024         printf("\t-0 zeroize timestamps and signature in RRSIG records.\n");
00025         printf("\t-c canonicalize all rrs in the zone.\n");
00026         printf("\t-d only show DNSSEC data from the zone\n");
00027         printf("\t-h show this text\n");
00028         printf("\t-n do not print the SOA record\n");
00029         printf("\t-p prepend SOA serial with spaces so"
00030                 " it takes exactly ten characters.\n");
00031         printf("\t-s strip DNSSEC data from the zone\n");
00032         printf("\t-S [[+|-]<number> | YYYYMMDDxx | "
00033                         " unixtime ]\n"
00034                 "\t\tSet serial number to <number> or,"
00035                         " when preceded by a sign,\n"
00036                 "\t\toffset the existing number with "
00037                         "<number>.  With YYYYMMDDxx\n"
00038                 "\t\tthe serial is formatted as a datecounter"
00039                         ", and with unixtime as\n"
00040                 "\t\tthe number of seconds since 1-1-1970."
00041                         "  However, on serial\n"
00042                 "\t\tnumber decrease, +1 is used in stead"
00043                         ".  (implies -s)\n");
00044         printf("\t-u <rr type>\n");
00045         printf("\t\tMark <rr type> for printing in unknown type format.\n");
00046         printf("\t\tThis option may be given multiple times.\n");
00047         printf("\t\t-u is not meant to be used together with -U.\n");
00048         printf("\t-U <rr type>\n");
00049         printf("\t\tMark <rr type> for not printing in unknown type format.\n");
00050         printf("\t\tThis option may be given multiple times.\n");
00051         printf(
00052         "\t\tThe first occurrence of the -U option marks all RR types for"
00053         "\n\t\tprinting in unknown type format except for the given <rr type>."
00054         "\n\t\tSubsequent -U options will clear the mark for those <rr type>s"
00055         "\n\t\ttoo, so that only the given <rr type>s will be printed in the"
00056         "\n\t\tpresentation format specific for those <rr type>s.\n");
00057         printf("\t\t-U is not meant to be used together with -u.\n");
00058         printf("\t-v shows the version and exits\n");
00059         printf("\t-z sort the zone (implies -c).\n");
00060         printf("\nif no file is given standard input is read\n");
00061         exit(EXIT_SUCCESS);
00062 }
00063 
00064 int
00065 main(int argc, char **argv)
00066 {
00067         char *filename;
00068         FILE *fp;
00069         ldns_zone *z;
00070         int line_nr = 0;
00071         int c;
00072         bool canonicalize = false;
00073         bool sort = false;
00074         bool strip = false;
00075         bool only_dnssec = false;
00076         bool print_soa = true;
00077         ldns_status s;
00078         size_t i;
00079         ldns_rr_list *stripped_list;
00080         ldns_rr *cur_rr;
00081         ldns_rr_type cur_rr_type;
00082         ldns_output_format_storage fmt_storage;
00083         ldns_output_format* fmt = ldns_output_format_init(&fmt_storage);
00084 
00085         ldns_soa_serial_increment_func_t soa_serial_increment_func = NULL;
00086         int soa_serial_increment_func_data = 0;
00087 
00088         while ((c = getopt(argc, argv, "0bcdhnpsu:U:vzS:")) != -1) {
00089                 switch(c) {
00090                         case 'b':
00091                                 fmt->flags |= 
00092                                         ( LDNS_COMMENT_BUBBLEBABBLE |
00093                                           LDNS_COMMENT_FLAGS        );
00094                                 break;
00095                         case '0':
00096                                 fmt->flags |= LDNS_FMT_ZEROIZE_RRSIGS;
00097                                 break;
00098                         case 'c':
00099                                 canonicalize = true;
00100                                 break;
00101                         case 'd':
00102                                 only_dnssec = true;
00103                                 if (strip) {
00104                                         fprintf(stderr, "Warning: stripping both DNSSEC and non-DNSSEC records. Output will be sparse.\n");
00105                                 }
00106                                 break;
00107                         case 'h':
00108                                 print_usage("ldns-read-zone");
00109                                 break;
00110                         case 'n':
00111                                 print_soa = false;
00112                                 break;
00113                         case 'p':
00114                                 fmt->flags |= LDNS_FMT_PAD_SOA_SERIAL;
00115                                 break;
00116                         case 's':
00117                                 strip = true;
00118                                 if (only_dnssec) {
00119                                         fprintf(stderr, "Warning: stripping both DNSSEC and non-DNSSEC records. Output will be sparse.\n");
00120                                 }
00121                                 break;
00122                         case 'u':
00123                                 s = ldns_output_format_set_type(fmt,
00124                                         ldns_get_rr_type_by_name(optarg));
00125                                 if (s != LDNS_STATUS_OK) {
00126                                         fprintf( stderr
00127                                                , "Cannot set rr type %s "
00128                                                  "in output format to "
00129                                                  "print as unknown type: %s\n"
00130                                                , ldns_rr_descript(
00131                                                ldns_get_rr_type_by_name(optarg)
00132                                                        )->_name
00133                                                , ldns_get_errorstr_by_id(s)
00134                                                );
00135                                         exit(EXIT_FAILURE);
00136                                 }
00137                                 break;
00138                         case 'U':
00139                                 s = ldns_output_format_clear_type(fmt,
00140                                         ldns_get_rr_type_by_name(optarg));
00141                                 if (s != LDNS_STATUS_OK) {
00142                                         fprintf( stderr
00143                                                , "Cannot set rr type %s "
00144                                                  "in output format to not "
00145                                                  "print as unknown type: %s\n"
00146                                                , ldns_rr_descript(
00147                                                ldns_get_rr_type_by_name(optarg)
00148                                                        )->_name
00149                                                , ldns_get_errorstr_by_id(s)
00150                                                );
00151                                         exit(EXIT_FAILURE);
00152                                 }
00153                                 break;
00154                         case 'v':
00155                                 printf("read zone version %s (ldns version %s)\n", LDNS_VERSION, ldns_version());
00156                                 exit(EXIT_SUCCESS);
00157                                 break;
00158                         case 'z':
00159                                 canonicalize = true;
00160                                 sort = true;
00161                                 break;
00162                         case 'S':
00163                                 strip = true;
00164                                 if (*optarg == '+' || *optarg == '-') {
00165                                         soa_serial_increment_func_data =
00166                                                 atoi(optarg);
00167                                         soa_serial_increment_func =
00168                                                 ldns_soa_serial_increment_by;
00169                                 } else if (! strtok(optarg, "0123456789")) {
00170                                         soa_serial_increment_func_data =
00171                                                 atoi(optarg);
00172                                         soa_serial_increment_func =
00173                                                 ldns_soa_serial_identity;
00174                                 } else if (!strcasecmp(optarg, "YYYYMMDDxx")){
00175                                         soa_serial_increment_func =
00176                                                 ldns_soa_serial_datecounter;
00177                                 } else if (!strcasecmp(optarg, "unixtime")){
00178                                         soa_serial_increment_func =
00179                                                 ldns_soa_serial_unixtime;
00180                                 } else {
00181                                         fprintf(stderr, "-S expects a number "
00182                                                 "optionally preceded by a "
00183                                                 "+ or - sign to indicate an "
00184                                                 "offset, or the text YYYYMM"
00185                                                 "DDxx or unixtime\n");
00186                                         exit(EXIT_FAILURE);
00187                                 }
00188                                 break;
00189                 }
00190         }
00191 
00192         argc -= optind;
00193         argv += optind;
00194 
00195         if (argc == 0) {
00196                 fp = stdin;
00197         } else {
00198                 filename = argv[0];
00199 
00200                 fp = fopen(filename, "r");
00201                 if (!fp) {
00202                         fprintf(stderr, "Unable to open %s: %s\n", filename, strerror(errno));
00203                         exit(EXIT_FAILURE);
00204                 }
00205         }
00206         
00207         s = ldns_zone_new_frm_fp_l(&z, fp, NULL, 0, LDNS_RR_CLASS_IN, &line_nr);
00208 
00209         fclose(fp);
00210         if (s != LDNS_STATUS_OK) {
00211                 fprintf(stderr, "%s at %d\n", 
00212                                 ldns_get_errorstr_by_id(s),
00213                                 line_nr);
00214                 exit(EXIT_FAILURE);
00215         }
00216 
00217 
00218         if (strip) {
00219                 stripped_list = ldns_rr_list_new();
00220                 while ((cur_rr = ldns_rr_list_pop_rr(ldns_zone_rrs(z)))) {
00221                         cur_rr_type = ldns_rr_get_type(cur_rr);
00222                         if (cur_rr_type == LDNS_RR_TYPE_RRSIG ||
00223                             cur_rr_type == LDNS_RR_TYPE_NSEC ||
00224                             cur_rr_type == LDNS_RR_TYPE_NSEC3 ||
00225                             cur_rr_type == LDNS_RR_TYPE_NSEC3PARAM
00226                            ) {
00227                                 ldns_rr_free(cur_rr);
00228                         } else {
00229                                 ldns_rr_list_push_rr(stripped_list, cur_rr);
00230                         }
00231                 }
00232                 ldns_rr_list_free(ldns_zone_rrs(z));
00233                 ldns_zone_set_rrs(z, stripped_list);
00234         }
00235         if (only_dnssec) {
00236                 stripped_list = ldns_rr_list_new();
00237                 while ((cur_rr = ldns_rr_list_pop_rr(ldns_zone_rrs(z)))) {
00238                         cur_rr_type = ldns_rr_get_type(cur_rr);
00239                         if (cur_rr_type == LDNS_RR_TYPE_RRSIG ||
00240                             cur_rr_type == LDNS_RR_TYPE_NSEC ||
00241                             cur_rr_type == LDNS_RR_TYPE_NSEC3 ||
00242                             cur_rr_type == LDNS_RR_TYPE_NSEC3PARAM
00243                            ) {
00244                                 ldns_rr_list_push_rr(stripped_list, cur_rr);
00245                         } else {
00246                                 ldns_rr_free(cur_rr);
00247                         }
00248                 }
00249                 ldns_rr_list_free(ldns_zone_rrs(z));
00250                 ldns_zone_set_rrs(z, stripped_list);
00251         }
00252 
00253         if (canonicalize) {
00254                 ldns_rr2canonical(ldns_zone_soa(z));
00255                 for (i = 0; i < ldns_rr_list_rr_count(ldns_zone_rrs(z)); i++) {
00256                         ldns_rr2canonical(ldns_rr_list_rr(ldns_zone_rrs(z), i));
00257                 }
00258         }
00259         if (sort) {
00260                 ldns_zone_sort(z);
00261         }
00262 
00263         if (print_soa && ldns_zone_soa(z)) {
00264                 if (soa_serial_increment_func) {
00265                         ldns_rr_soa_increment_func_int(
00266                                         ldns_zone_soa(z)
00267                                 , soa_serial_increment_func
00268                                 , soa_serial_increment_func_data
00269                                 );
00270                 }
00271                 ldns_rr_print_fmt(stdout, fmt, ldns_zone_soa(z));
00272         }
00273         ldns_rr_list_print_fmt(stdout, fmt, ldns_zone_rrs(z));
00274 
00275         ldns_zone_deep_free(z);
00276 
00277         exit(EXIT_SUCCESS);
00278 }