]> git.ipfire.org Git - thirdparty/ldns.git/commitdiff
Extend output format with ability to print certain given rr types in unknown type...
authorWillem Toorop <willem@NLnetLabs.nl>
Wed, 22 May 2013 14:58:29 +0000 (14:58 +0000)
committerWillem Toorop <willem@NLnetLabs.nl>
Wed, 22 May 2013 14:58:29 +0000 (14:58 +0000)
Thanks Jelte Jansen

14 files changed:
Changelog
dnssec.c
error.c
examples/ldns-read-zone.1
examples/ldns-read-zone.c
examples/ldns-signzone.c
higher.c
host2str.c
ldns/dnssec.h
ldns/error.h
ldns/host2str.h
ldns/rdata.h
ldns/rr.h
rr.c

index f2443963edd3768fa413745503aa10f4af5848df..3e1eec7cb3761a14c4288201750e50eff70b759f 100644 (file)
--- a/Changelog
+++ b/Changelog
@@ -1,4 +1,8 @@
 1.6.17
+       * -u and -U parameter for ldns-read-zone to mark/unmark a RR type
+         for printing as unknown type
+       * New output format flag (and accompanying funtions) to print certain
+         RR's as unknown type
        * New RR types HIP, NINFO, RKEY, CDS, EUI48, EUI64, URI, CAA and TA.
        * New RR type TKEY, but without operational practice.
        * Fix b{32,64}_{ntop,pton} detection and handling.
index 684d17169e2a12b93734859e9e42854d462d0c50..46248a2c77b9a862ef40ea789a6c7e289b85da95 100644 (file)
--- a/dnssec.c
+++ b/dnssec.c
@@ -1338,38 +1338,120 @@ ldns_nsec3_hash_name_frm_nsec3(const ldns_rr *nsec, ldns_rdf *name)
 }
 
 bool
-ldns_nsec_bitmap_covers_type(const ldns_rdf *nsec_bitmap, ldns_rr_type type)
+ldns_nsec_bitmap_covers_type(const  ldns_rdf* bitmap, ldns_rr_type type)
 {
-       uint8_t window_block_nr;
-       uint8_t bitmap_length;
-       uint16_t cur_type;
-       uint16_t pos = 0;
-       uint16_t bit_pos;
-       uint8_t *data;
-
-       if (nsec_bitmap == NULL) {
+       uint8_t* dptr;
+       uint8_t* dend;
+
+       /* From RFC3845 Section 2.1.2:
+        *
+        *      "The RR type space is split into 256 window blocks, each re-
+        *       presenting the low-order 8 bits of the 16-bit RR type space."
+        */
+       uint8_t  window = type >> 8;
+       uint8_t subtype = type & 0xff;
+
+       if (! bitmap) {
                return false;
        }
-       data = ldns_rdf_data(nsec_bitmap);
-       while(pos < ldns_rdf_size(nsec_bitmap)) {
-               window_block_nr = data[pos];
-               bitmap_length = data[pos + 1];
-               pos += 2;
-
-               for (bit_pos = 0; bit_pos < (bitmap_length) * 8; bit_pos++) {
-                       if (ldns_get_bit(&data[pos], bit_pos)) {
-                               cur_type = 256 * (uint16_t) window_block_nr + bit_pos;
-                               if (cur_type == type) {
-                                       return true;
-                               }
-                       }
-               }
+       assert(ldns_rdf_get_type(bitmap) == LDNS_RDF_TYPE_BITMAP);
 
-               pos += (uint16_t) bitmap_length;
+       dptr = ldns_rdf_data(bitmap);
+       dend = ldns_rdf_data(bitmap) + ldns_rdf_size(bitmap);
+
+       /* Type Bitmap = ( Window Block # | Bitmap Length | Bitmap ) +
+        *                 dptr[0]          dptr[1]         dptr[2:]
+        */
+       while (dptr < dend && dptr[0] <= window) {
+
+               if (dptr[0] == window && subtype / 8 < dptr[1] &&
+                               dptr + dptr[1] + 2 <= dend) {
+
+                       return dptr[2 + subtype / 8] & (1 << (subtype % 8));
+               }
+               dptr += dptr[1] + 2; /* next window */
        }
        return false;
 }
 
+ldns_status
+ldns_nsec_bitmap_set_type(ldns_rdf* bitmap, ldns_rr_type type)
+{
+       uint8_t* dptr;
+       uint8_t* dend;
+
+       /* From RFC3845 Section 2.1.2:
+        *
+        *      "The RR type space is split into 256 window blocks, each re-
+        *       presenting the low-order 8 bits of the 16-bit RR type space."
+        */
+       uint8_t  window = type >> 8;
+       uint8_t subtype = type & 0xff;
+
+       if (! bitmap) {
+               return false;
+       }
+       assert(ldns_rdf_get_type(bitmap) == LDNS_RDF_TYPE_BITMAP);
+
+       dptr = ldns_rdf_data(bitmap);
+       dend = ldns_rdf_data(bitmap) + ldns_rdf_size(bitmap);
+
+       /* Type Bitmap = ( Window Block # | Bitmap Length | Bitmap ) +
+        *                 dptr[0]          dptr[1]         dptr[2:]
+        */
+       while (dptr < dend && dptr[0] <= window) {
+
+               if (dptr[0] == window && subtype / 8 < dptr[1] &&
+                               dptr + dptr[1] + 2 <= dend) {
+
+                       dptr[2 + subtype / 8] |= (1 << (subtype % 8));
+                       return LDNS_STATUS_OK;
+               }
+               dptr += dptr[1] + 2; /* next window */
+       }
+       return LDNS_STATUS_TYPE_NOT_IN_BITMAP;
+}
+
+ldns_status
+ldns_nsec_bitmap_clear_type(ldns_rdf* bitmap, ldns_rr_type type)
+{
+       uint8_t* dptr;
+       uint8_t* dend;
+
+       /* From RFC3845 Section 2.1.2:
+        *
+        *      "The RR type space is split into 256 window blocks, each re-
+        *       presenting the low-order 8 bits of the 16-bit RR type space."
+        */
+       uint8_t  window = type >> 8;
+       uint8_t subtype = type & 0xff;
+
+       if (! bitmap) {
+               return false;
+       }
+
+       assert(ldns_rdf_get_type(bitmap) == LDNS_RDF_TYPE_BITMAP);
+
+       dptr = ldns_rdf_data(bitmap);
+       dend = ldns_rdf_data(bitmap) + ldns_rdf_size(bitmap);
+
+       /* Type Bitmap = ( Window Block # | Bitmap Length | Bitmap ) +
+        *                 dptr[0]          dptr[1]         dptr[2:]
+        */
+       while (dptr < dend && dptr[0] <= window) {
+
+               if (dptr[0] == window && subtype / 8 < dptr[1] &&
+                               dptr + dptr[1] + 2 <= dend) {
+
+                       dptr[2 + subtype / 8] &= ~(1 << (subtype % 8));
+                       return LDNS_STATUS_OK;
+               }
+               dptr += dptr[1] + 2; /* next window */
+       }
+       return LDNS_STATUS_TYPE_NOT_IN_BITMAP;
+}
+
+
 bool
 ldns_nsec_covers_name(const ldns_rr *nsec, const ldns_rdf *name)
 {
diff --git a/error.c b/error.c
index caa40c8c0bd6193742160de81a01250ecaa99a4d..dc7aee85a259a41b27c2421d2cce59a6436e7763 100644 (file)
--- a/error.c
+++ b/error.c
@@ -137,6 +137,9 @@ ldns_lookup_table ldns_error_str[] = {
         { LDNS_STATUS_INVALID_TAG, 
                "Conversion error, a non-zero sequence of US-ASCII letters "
                "and numbers in lower case expected" },
+        { LDNS_STATUS_TYPE_NOT_IN_BITMAP, 
+               "The RR type bitmap rdata field did not have "
+               "a bit reserved for the specific RR type" },
        { 0, NULL }
 };
 
index 7d4fd7d949418f90d70b9a2498f19fdec3451421..163b70f6ca9bfa53661378d90379c154966319a8 100644 (file)
@@ -58,6 +58,15 @@ increased by one.
 When updating a serial number, records of type NSEC, NSEC3, RRSIG and DNSKEY
 will be skipped when printing the zone.
 
+.TP
+\fB-u\fR \fIRR type\fR
+Mark \fIRR type\fR for printing in unknown type format
+
+.TP
+\fB-U\fR \fIRR type\fR
+Mark \fIRR type\fR for \fBnot\fR printing in unknown type format
+When only \fB-U\fR options are given, all types are printed in
+unknown type format except the given RR types
 
 .TP
 \fB-v\fR
index efe187e6a223cc97e9a6d361fec845c37d47a9e2..f26876fa79206214eced6b57a7ec4aa2af2b8ab6 100644 (file)
 
 #include <errno.h>
 
+void print_usage(const char* progname)
+{
+       printf("Usage: %s [OPTIONS] <zonefile>\n", progname);
+       printf("\tReads the zonefile and prints it.\n");
+       printf("\tThe RR count of the zone is printed to stderr.\n");
+       printf("\t-b include bubblebabble of DS's.\n");
+       printf("\t-0 zeroize timestamps and signature in RRSIG records.\n");
+       printf("\t-c canonicalize all rrs in the zone.\n");
+       printf("\t-d only show DNSSEC data from the zone\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 [[+|-]<number> | YYYYMMDDxx | "
+                       " unixtime ]\n"
+               "\t\tSet serial number to <number> or,"
+                       " when preceded by a sign,\n"
+               "\t\toffset the existing number with "
+                       "<number>.  With YYYYMMDDxx\n"
+               "\t\tthe serial is formatted as a datecounter"
+                       ", and with unixtime as the\n"
+               "\t\tnumber of seconds since 1-1-1970."
+                       "  However, on serial number"
+               "\n\t\tdecrease, +1 is used in stead"
+                       ".  (implies -s)\n");
+       printf("\t-u <rr type>\n");
+       printf("\t\tMark <rr type> for printing in unknown type format\n");
+       printf("\t-U <rr type>\n");
+       printf("\t\tMark <rr type> for not printing in unknown type format\n");
+       printf("\t\tWhen only -U options are given, all types are printed in"
+               "\n\t\tunknown type format except the given RR types\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);
+}
+
 int
 main(int argc, char **argv)
 {
@@ -33,22 +71,21 @@ main(int argc, char **argv)
        ldns_rr_list *stripped_list;
        ldns_rr *cur_rr;
        ldns_rr_type cur_rr_type;
-       ldns_output_format fmt = { 
-               ldns_output_format_default->flags,
-               ldns_output_format_default->data
-       };
+       ldns_output_format_storage fmt_storage;
+       ldns_output_format* fmt = ldns_output_format_init(&fmt_storage);
+
        ldns_soa_serial_increment_func_t soa_serial_increment_func = NULL;
        int soa_serial_increment_func_data = 0;
 
-        while ((c = getopt(argc, argv, "0bcdhnpsvzS:")) != -1) {
+        while ((c = getopt(argc, argv, "0bcdhnpsu:U:vzS:")) != -1) {
                 switch(c) {
                        case 'b':
-                               fmt.flags |= 
+                               fmt->flags |= 
                                        ( LDNS_COMMENT_BUBBLEBABBLE |
                                          LDNS_COMMENT_FLAGS        );
                                break;
                        case '0':
-                               fmt.flags |= LDNS_FMT_ZEROIZE_RRSIGS;
+                               fmt->flags |= LDNS_FMT_ZEROIZE_RRSIGS;
                                break;
                        case 'c':
                                canonicalize = true;
@@ -60,40 +97,13 @@ main(int argc, char **argv)
                                }
                                break;
                        case 'h':
-                               printf("Usage: %s [OPTIONS] <zonefile>\n", argv[0]);
-                               printf("\tReads the zonefile and prints it.\n");
-                               printf("\tThe RR count of the zone is printed to stderr.\n");
-                               printf("\t-b include bubblebabble of DS's.\n");
-                               printf("\t-0 zeroize timestamps and signature in RRSIG records.\n");
-                               printf("\t-c canonicalize all rrs in the zone.\n");
-                               printf("\t-d only show DNSSEC data from the zone\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 [[+|-]<number> | YYYYMMDDxx | "
-                                               " unixtime ]\n"
-                                      "\t\tSet serial number to <number> or,"
-                                               " when preceded by a sign,\n"
-                                      "\t\toffset the existing number with "
-                                               "<number>.  With YYYYMMDDxx\n"
-                                      "\t\tthe serial is formatted as a datecounter"
-                                               ", and with unixtime as the\n"
-                                      "\t\tnumber of seconds since 1-1-1970."
-                                               "  However, on serial number"
-                                      "\n\t\tdecrease, +1 is used in stead"
-                                               ".  (implies -s)\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);
+                               print_usage("ldns-read-zone");
                                break;
                        case 'n':
                                print_soa = false;
                                break;
                        case 'p':
-                               fmt.flags |= LDNS_FMT_PAD_SOA_SERIAL;
+                               fmt->flags |= LDNS_FMT_PAD_SOA_SERIAL;
                                break;
                         case 's':
                                strip = true;
@@ -101,6 +111,38 @@ main(int argc, char **argv)
                                        fprintf(stderr, "Warning: stripping both DNSSEC and non-DNSSEC records. Output will be sparse.\n");
                                }
                                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);
@@ -218,9 +260,9 @@ main(int argc, char **argv)
                                , soa_serial_increment_func_data
                                );
                }
-               ldns_rr_print_fmt(stdout, &fmt, ldns_zone_soa(z));
+               ldns_rr_print_fmt(stdout, fmt, ldns_zone_soa(z));
        }
-       ldns_rr_list_print_fmt(stdout, &fmt, ldns_zone_rrs(z));
+       ldns_rr_list_print_fmt(stdout, fmt, ldns_zone_rrs(z));
 
        ldns_zone_deep_free(z);
 
index 25ece3a651e9a2cf4506d084210526eff2122be9..5eaa3cc003bd6611330f02cc0cfe83f50dde108c 100644 (file)
@@ -368,9 +368,8 @@ main(int argc, char *argv[])
        char *prog = strdup(argv[0]);
        ldns_status result;
 
-       ldns_output_format fmt = { ldns_output_format_default->flags, NULL };
-       void **hashmap = NULL;
-
+       ldns_output_format_storage fmt_st;
+       ldns_output_format* fmt = ldns_output_format_init(&fmt_st);
        
        inception = 0;
        expiration = 0;
@@ -389,11 +388,10 @@ main(int argc, char *argv[])
                        }
                        break;
                case 'b':
-                       fmt.flags |= LDNS_COMMENT_BUBBLEBABBLE;
-                       fmt.flags |= LDNS_COMMENT_FLAGS;
-                       fmt.flags |= LDNS_COMMENT_NSEC3_CHAIN;
-                       fmt.flags |= LDNS_COMMENT_LAYOUT;
-                       hashmap = &fmt.data;
+                       ldns_output_format_set(fmt, LDNS_COMMENT_FLAGS
+                                                 | LDNS_COMMENT_LAYOUT      
+                                                 | LDNS_COMMENT_NSEC3_CHAIN
+                                                 | LDNS_COMMENT_BUBBLEBABBLE);
                        break;
                case 'd':
                        add_keys = false;
@@ -767,7 +765,7 @@ main(int argc, char *argv[])
                        nsec3_salt_length,
                        nsec3_salt,
                        signflags,
-                       (ldns_rbtree_t**) hashmap);
+                       &fmt_st.hashmap);
        } else {
                result = ldns_dnssec_zone_sign_flg(signed_zone,
                                added_rrs,
@@ -796,7 +794,7 @@ main(int argc, char *argv[])
                                           outputfile_name, strerror(errno));
                        } else {
                                ldns_dnssec_zone_print_fmt(
-                                               outputfile, &fmt, signed_zone);
+                                               outputfile, fmt, signed_zone);
                                fclose(outputfile);
                        }
                }
index 990fb6afb25bc696187362235fc0e1c1fec85ff7..25ce35852eaf5a0c248d4e866a9f5592c2425c47 100644 (file)
--- a/higher.c
+++ b/higher.c
@@ -303,39 +303,21 @@ ldns_getaddrinfo(ldns_resolver *res, ldns_rdf *node, ldns_rr_class c,
 bool
 ldns_nsec_type_check(ldns_rr *nsec, ldns_rr_type t)
 {
-       /* does the nsec cover the t given? */
-       /* copied from host2str.c line 465: ldns_rdf2buffer_str_nsec */
-        uint8_t window_block_nr;
-        uint8_t bitmap_length;
-        uint16_t type;
-        uint16_t pos = 0;
-        uint16_t bit_pos;
-       ldns_rdf *nsec_type_list = ldns_rr_rdf(nsec, 1); 
-       uint8_t *data;
-       
-       if (nsec_type_list == NULL) {
-               return false;
+       switch (ldns_rr_get_type(nsec)) {
+       case LDNS_RR_TYPE_NSEC  : if (ldns_rr_rd_count(nsec) < 2) {
+                                         return false;
+                                 }
+                                 return ldns_nsec_bitmap_covers_type(
+                                                 ldns_rr_rdf(nsec, 1), t);
+
+       case LDNS_RR_TYPE_NSEC3 : if (ldns_rr_rd_count(nsec) < 6) {
+                                         return false;
+                                 }
+                                 return ldns_nsec_bitmap_covers_type(
+                                                 ldns_rr_rdf(nsec, 5), t);
+
+       default                 : return false;
        }
-       data  = ldns_rdf_data(nsec_type_list);
-
-       while(pos < ldns_rdf_size(nsec_type_list)) {
-               window_block_nr = data[pos];
-               bitmap_length = data[pos + 1];
-               pos += 2;
-
-               for (bit_pos = 0; bit_pos < (bitmap_length) * 8; bit_pos++) {
-                       if (ldns_get_bit(&data[pos], bit_pos)) {
-                               type = 256 * (uint16_t) window_block_nr + bit_pos;
-
-                               if ((ldns_rr_type)type == t) {
-                                       /* we have a winner */
-                                       return true;
-                               }
-                       }
-               }
-               pos += (uint16_t) bitmap_length;
-       }
-       return false;
 }
 
 void
@@ -358,3 +340,4 @@ ldns_print_rr_rdf(FILE *fp, ldns_rr *r, int rdfnum, ...)
        }
        va_end(va_rdf);
 }
+
index 08d62b5bb5915899092eb4e6c501a68e47a25775..86b7f1e83116e4b7b3b597b5a95a6646474a0ac2 100644 (file)
@@ -130,6 +130,55 @@ const ldns_output_format   ldns_output_format_bubblebabble_record = {
 const ldns_output_format  *ldns_output_format_bubblebabble 
                        = &ldns_output_format_bubblebabble_record;
 
+static bool
+ldns_output_format_covers_type(const ldns_output_format* fmt, ldns_rr_type t)
+{
+       return fmt && (fmt->flags & LDNS_FMT_RFC3597) &&
+               ((ldns_output_format_storage*)fmt)->bitmap &&
+               ldns_nsec_bitmap_covers_type(
+                               ((ldns_output_format_storage*)fmt)->bitmap, t);
+}
+
+ldns_status
+ldns_output_format_set_type(ldns_output_format* fmt, ldns_rr_type t)
+{
+       ldns_output_format_storage* fmt_st = (ldns_output_format_storage*)fmt;
+       ldns_status s;
+       
+       assert(fmt != NULL);
+       
+       if (!(fmt_st->flags & LDNS_FMT_RFC3597)) {
+               ldns_output_format_set(fmt, LDNS_FMT_RFC3597);
+       }
+       if (! fmt_st->bitmap) {
+               s = ldns_rdf_bitmap_known_rr_types_space(&fmt_st->bitmap);
+               if (s != LDNS_STATUS_OK) {
+                       return s;
+               }
+       }
+       return ldns_nsec_bitmap_set_type(fmt_st->bitmap, t);
+}
+
+ldns_status
+ldns_output_format_clear_type(ldns_output_format* fmt, ldns_rr_type t)
+{
+       ldns_output_format_storage* fmt_st = (ldns_output_format_storage*)fmt;
+       ldns_status s;
+       
+       assert(fmt != NULL);
+
+       if (!(fmt_st->flags & LDNS_FMT_RFC3597)) {
+               ldns_output_format_set(fmt, LDNS_FMT_RFC3597);
+       }
+       if (! fmt_st->bitmap) {
+               s = ldns_rdf_bitmap_known_rr_types(&fmt_st->bitmap);
+               if (s != LDNS_STATUS_OK) {
+                       return s;
+               }
+       }
+       return ldns_nsec_bitmap_clear_type(fmt_st->bitmap, t);
+}
+
 ldns_status
 ldns_pkt_opcode2buffer_str(ldns_buffer *output, ldns_pkt_opcode opcode)
 {
@@ -463,18 +512,27 @@ ldns_rdf2buffer_str_hex(ldns_buffer *output, const ldns_rdf *rdf)
 }
 
 ldns_status
-ldns_rdf2buffer_str_type(ldns_buffer *output, const ldns_rdf *rdf)
+ldns_rdf2buffer_str_type_fmt(ldns_buffer *output,
+               const ldns_output_format* fmt, const ldns_rdf *rdf)
 {
         uint16_t data = ldns_read_uint16(ldns_rdf_data(rdf));
-       const ldns_rr_descriptor *descriptor;
 
-       descriptor = ldns_rr_descript(data);
-       if (descriptor && descriptor->_name) {
-               ldns_buffer_printf(output, "%s", descriptor->_name);
+       if (! ldns_output_format_covers_type(fmt, data) &&
+                       ldns_rr_descript(data) &&
+                       ldns_rr_descript(data)->_name) {
+
+               ldns_buffer_printf(output, "%s",ldns_rr_descript(data)->_name);
        } else {
                ldns_buffer_printf(output, "TYPE%u", data);
        }
-       return ldns_buffer_status(output);
+       return  ldns_buffer_status(output);
+}
+
+ldns_status
+ldns_rdf2buffer_str_type(ldns_buffer *output, const ldns_rdf *rdf)
+{
+       return ldns_rdf2buffer_str_type_fmt(output,
+                       ldns_output_format_default, rdf);
 }
 
 ldns_status
@@ -780,7 +838,8 @@ ldns_rdf2buffer_str_wks(ldns_buffer *output, const ldns_rdf *rdf)
 }
 
 ldns_status
-ldns_rdf2buffer_str_nsec(ldns_buffer *output, const ldns_rdf *rdf)
+ldns_rdf2buffer_str_nsec_fmt(ldns_buffer *output,
+               const ldns_output_format* fmt, const ldns_rdf *rdf)
 {
        /* Note: this code is duplicated in higher.c in
         * ldns_nsec_type_check() function
@@ -791,7 +850,6 @@ ldns_rdf2buffer_str_nsec(ldns_buffer *output, const ldns_rdf *rdf)
        uint16_t pos = 0;
        uint16_t bit_pos;
        uint8_t *data = ldns_rdf_data(rdf);
-       const ldns_rr_descriptor *descriptor;
 
        while((size_t)(pos + 2) < ldns_rdf_size(rdf)) {
                window_block_nr = data[pos];
@@ -801,16 +859,19 @@ ldns_rdf2buffer_str_nsec(ldns_buffer *output, const ldns_rdf *rdf)
                        return LDNS_STATUS_WIRE_RDATA_ERR;
                }
                for (bit_pos = 0; bit_pos < (bitmap_length) * 8; bit_pos++) {
-                       if (ldns_get_bit(&data[pos], bit_pos)) {
-                               type = 256 * (uint16_t) window_block_nr + bit_pos;
-                               descriptor = ldns_rr_descript(type);
+                       if (! ldns_get_bit(&data[pos], bit_pos)) {
+                               continue;
+                       }
+                       type = 256 * (uint16_t) window_block_nr + bit_pos;
 
-                               if (descriptor && descriptor->_name) {
-                                       ldns_buffer_printf(output, "%s ",
-                                                       descriptor->_name);
-                               } else {
-                                       ldns_buffer_printf(output, "TYPE%u ", type);
-                               }
+                       if (! ldns_output_format_covers_type(fmt, type) &&
+                                       ldns_rr_descript(type) &&
+                                       ldns_rr_descript(type)->_name){
+
+                               ldns_buffer_printf(output, "%s ",
+                                               ldns_rr_descript(type)->_name);
+                       } else {
+                               ldns_buffer_printf(output, "TYPE%u ", type);
                        }
                }
                pos += (uint16_t) bitmap_length;
@@ -818,6 +879,13 @@ ldns_rdf2buffer_str_nsec(ldns_buffer *output, const ldns_rdf *rdf)
        return ldns_buffer_status(output);
 }
 
+ldns_status
+ldns_rdf2buffer_str_nsec(ldns_buffer *output, const ldns_rdf *rdf)
+{
+       return ldns_rdf2buffer_str_nsec_fmt(output,
+                       ldns_output_format_default, rdf);
+}
+
 ldns_status
 ldns_rdf2buffer_str_nsec3_salt(ldns_buffer *output, const ldns_rdf *rdf)
 {
@@ -1202,7 +1270,8 @@ ldns_rdf2buffer_str_multi_str(ldns_buffer *output, const ldns_rdf *rdf)
 }
 
 ldns_status
-ldns_rdf2buffer_str(ldns_buffer *buffer, const ldns_rdf *rdf)
+ldns_rdf2buffer_str_fmt(ldns_buffer *buffer,
+               const ldns_output_format* fmt, const ldns_rdf *rdf)
 {
        ldns_status res = LDNS_STATUS_OK;
 
@@ -1251,13 +1320,13 @@ ldns_rdf2buffer_str(ldns_buffer *buffer, const ldns_rdf *rdf)
                        res = ldns_rdf2buffer_str_hex(buffer, rdf);
                        break;
                case LDNS_RDF_TYPE_NSEC:
-                       res = ldns_rdf2buffer_str_nsec(buffer, rdf);
+                       res = ldns_rdf2buffer_str_nsec_fmt(buffer, fmt, rdf);
                        break;
                case LDNS_RDF_TYPE_NSEC3_SALT:
                        res = ldns_rdf2buffer_str_nsec3_salt(buffer, rdf);
                        break;
                case LDNS_RDF_TYPE_TYPE:
-                       res = ldns_rdf2buffer_str_type(buffer, rdf);
+                       res = ldns_rdf2buffer_str_type_fmt(buffer, fmt, rdf);
                        break;
                case LDNS_RDF_TYPE_CLASS:
                        res = ldns_rdf2buffer_str_class(buffer, rdf);
@@ -1326,6 +1395,12 @@ ldns_rdf2buffer_str(ldns_buffer *buffer, const ldns_rdf *rdf)
        return res;
 }
 
+ldns_status
+ldns_rdf2buffer_str(ldns_buffer *buffer, const ldns_rdf *rdf)
+{
+       return ldns_rdf2buffer_str_fmt(buffer,ldns_output_format_default,rdf);
+}
+
 static ldns_rdf *
 ldns_b32_ext2dname(const ldns_rdf *rdf)
 {
@@ -1353,18 +1428,45 @@ ldns_b32_ext2dname(const ldns_rdf *rdf)
        return NULL;
 }
 
+static ldns_status
+ldns_rr2buffer_str_rfc3597(ldns_buffer *output, const ldns_rr *rr)
+{
+       size_t total_rdfsize = 0;
+       size_t i, j;
+
+       ldns_buffer_printf(output, "TYPE%u\t", ldns_rr_get_type(rr));
+       for (i = 0; i < ldns_rr_rd_count(rr); i++) {
+               total_rdfsize += ldns_rdf_size(ldns_rr_rdf(rr, i));
+       }
+       if (total_rdfsize == 0) {
+               ldns_buffer_printf(output, "\\# 0\n");
+               return ldns_buffer_status(output);
+       }
+       ldns_buffer_printf(output, "\\# %d ", total_rdfsize);
+       for (i = 0; i < ldns_rr_rd_count(rr); i++) {
+               for (j = 0; j < ldns_rdf_size(ldns_rr_rdf(rr, i)); j++) {
+                       ldns_buffer_printf(output, "%.2x",
+                                       ldns_rdf_data(ldns_rr_rdf(rr, i))[j]);
+               }
+       }
+       ldns_buffer_printf(output, "\n");
+       return ldns_buffer_status(output);
+}
+
 ldns_status
 ldns_rr2buffer_str_fmt(ldns_buffer *output, 
                const ldns_output_format *fmt, const ldns_rr *rr)
 {
        uint16_t i, flags;
        ldns_status status = LDNS_STATUS_OK;
+       ldns_output_format_storage* fmt_st = (ldns_output_format_storage*)fmt;
 
-       if (fmt == NULL) {
-               fmt = ldns_output_format_default;
+       if (fmt_st == NULL) {
+               fmt_st = (ldns_output_format_storage*)
+                         ldns_output_format_default;
        }
        if (!rr) {
-               if (LDNS_COMMENT_NULLS & fmt->flags) {
+               if (LDNS_COMMENT_NULLS & fmt_st->flags) {
                        ldns_buffer_printf(output, "; (null)\n");
                }
                return ldns_buffer_status(output);
@@ -1388,6 +1490,9 @@ ldns_rr2buffer_str_fmt(ldns_buffer *output,
        }
        ldns_buffer_printf(output, "\t");
 
+       if (ldns_output_format_covers_type(fmt, ldns_rr_get_type(rr))) {
+               return ldns_rr2buffer_str_rfc3597(output, rr);
+       }
        status = ldns_rr_type2buffer_str(output, ldns_rr_get_type(rr));
        if (status != LDNS_STATUS_OK) {
                return status;
@@ -1401,7 +1506,7 @@ ldns_rr2buffer_str_fmt(ldns_buffer *output,
 
        for (i = 0; i < ldns_rr_rd_count(rr); i++) {
                /* ldns_rdf2buffer_str handles NULL input fine! */
-               if ((fmt->flags & LDNS_FMT_ZEROIZE_RRSIGS) &&
+               if ((fmt_st->flags & LDNS_FMT_ZEROIZE_RRSIGS) &&
                                (ldns_rr_get_type(rr) == LDNS_RR_TYPE_RRSIG) &&
                                ((/* inception  */ i == 4 &&
                                  ldns_rdf_get_type(ldns_rr_rdf(rr, 4)) == 
@@ -1415,7 +1520,7 @@ ldns_rr2buffer_str_fmt(ldns_buffer *output,
 
                        ldns_buffer_printf(output, "(null)");
                        status = ldns_buffer_status(output);
-               } else if ((fmt->flags & LDNS_FMT_PAD_SOA_SERIAL) &&
+               } else if ((fmt_st->flags & LDNS_FMT_PAD_SOA_SERIAL) &&
                                (ldns_rr_get_type(rr) == LDNS_RR_TYPE_SOA) &&
                                /* serial */ i == 2 &&
                                ldns_rdf_get_type(ldns_rr_rdf(rr, 2)) ==
@@ -1425,8 +1530,8 @@ ldns_rr2buffer_str_fmt(ldns_buffer *output,
                                        ldns_rdf_data(ldns_rr_rdf(rr, 2))));
                        status = ldns_buffer_status(output);
                } else {
-                       status = ldns_rdf2buffer_str(output,
-                                       ldns_rr_rdf(rr, i));
+                       status = ldns_rdf2buffer_str_fmt(output,
+                                       fmt, ldns_rr_rdf(rr, i));
                }
                if(status != LDNS_STATUS_OK)
                        return status;
@@ -1439,137 +1544,120 @@ ldns_rr2buffer_str_fmt(ldns_buffer *output,
         * getting here */
        if (ldns_rr_rd_count(rr) > 0) {
                switch (ldns_rr_get_type(rr)) {
-                       case LDNS_RR_TYPE_DNSKEY:
-                               /* if ldns_rr_rd_count(rr) > 0
-                                  then ldns_rr_rdf(rr, 0) exists! */
-                               if (! (fmt->flags & LDNS_COMMENT_KEY)) {
-                                       break;
-                               }
-                               flags = ldns_rdf2native_int16(
-                                               ldns_rr_rdf(rr, 0));
-                               ldns_buffer_printf(output, " ;{");
-                               if (fmt->flags & LDNS_COMMENT_KEY_ID) {
-                                       ldns_buffer_printf(output, "id = %u",
-                                                       (unsigned int)
-                                                       ldns_calc_keytag(rr));
-                               }
-                               if ((fmt->flags & LDNS_COMMENT_KEY_TYPE)
-                                               && (flags & LDNS_KEY_ZONE_KEY)){
-                                       if (flags & LDNS_KEY_SEP_KEY) {
-                                               ldns_buffer_printf(
-                                                       output, " (ksk)");
-                                       }
-                                       else {
-                                               ldns_buffer_printf(
-                                                       output, " (zsk)");
-                                       }
-                                       if (fmt->flags & LDNS_COMMENT_KEY_SIZE){
-                                               ldns_buffer_printf(
-                                                       output, ", ");
-                                       }
-                               } else if (fmt->flags
-                                               & (LDNS_COMMENT_KEY_ID
-                                                 |LDNS_COMMENT_KEY_SIZE)) {
-                                       ldns_buffer_printf( output, ", ");
+               case LDNS_RR_TYPE_DNSKEY:
+                       /* if ldns_rr_rd_count(rr) > 0
+                               then ldns_rr_rdf(rr, 0) exists! */
+                       if (! (fmt_st->flags & LDNS_COMMENT_KEY)) {
+                               break;
+                       }
+                       flags = ldns_rdf2native_int16(ldns_rr_rdf(rr, 0));
+                       ldns_buffer_printf(output, " ;{");
+                       if (fmt_st->flags & LDNS_COMMENT_KEY_ID) {
+                               ldns_buffer_printf(output, "id = %u",
+                                       (unsigned int) ldns_calc_keytag(rr));
+                       }
+                       if ((fmt_st->flags & LDNS_COMMENT_KEY_TYPE) &&
+                                       (flags & LDNS_KEY_ZONE_KEY)){
+
+                               if (flags & LDNS_KEY_SEP_KEY) {
+                                       ldns_buffer_printf(output, " (ksk)");
+                               } else {
+                                       ldns_buffer_printf(output, " (zsk)");
                                }
-                               if (fmt->flags & LDNS_COMMENT_KEY_SIZE) {
-                                       ldns_buffer_printf(output, "size = %db",
-                                               ldns_rr_dnskey_key_size(rr));
+                               if (fmt_st->flags & LDNS_COMMENT_KEY_SIZE){
+                                       ldns_buffer_printf(output, ", ");
                                }
-                               ldns_buffer_printf(output, "}");
-                               break;
-                       case LDNS_RR_TYPE_RRSIG:
-                               if ((fmt->flags & LDNS_COMMENT_KEY)
-                                               && (fmt->flags 
-                                                       & LDNS_COMMENT_RRSIGS)
-                                               && ldns_rr_rdf(rr, 6) != NULL) {
-                                       ldns_buffer_printf(output
-                                               , " ;{id = %d}"
-                                               , ldns_rdf2native_int16(
+                       } else if (fmt_st->flags
+                                       & (LDNS_COMMENT_KEY_ID
+                                               |LDNS_COMMENT_KEY_SIZE)) {
+                               ldns_buffer_printf( output, ", ");
+                       }
+                       if (fmt_st->flags & LDNS_COMMENT_KEY_SIZE) {
+                               ldns_buffer_printf(output, "size = %db",
+                                       ldns_rr_dnskey_key_size(rr));
+                       }
+                       ldns_buffer_printf(output, "}");
+                       break;
+               case LDNS_RR_TYPE_RRSIG:
+                       if ((fmt_st->flags & LDNS_COMMENT_KEY)
+                                       && (fmt_st->flags& LDNS_COMMENT_RRSIGS)
+                                       && ldns_rr_rdf(rr, 6) != NULL) {
+                               ldns_buffer_printf(output, " ;{id = %d}",
+                                               ldns_rdf2native_int16(
                                                        ldns_rr_rdf(rr, 6)));
+                       }
+                       break;
+               case LDNS_RR_TYPE_DS:
+                       if ((fmt_st->flags & LDNS_COMMENT_BUBBLEBABBLE) &&
+                                       ldns_rr_rdf(rr, 3) != NULL) {
+
+                               uint8_t *data = ldns_rdf_data(
+                                               ldns_rr_rdf(rr, 3));
+                               size_t len = ldns_rdf_size(ldns_rr_rdf(rr, 3));
+                               char *babble = ldns_bubblebabble(data, len);
+                               if(babble) {
+                                       ldns_buffer_printf(output,
+                                                       " ;{%s}", babble);
                                }
+                               LDNS_FREE(babble);
+                       }
+                       break;
+               case LDNS_RR_TYPE_NSEC3:
+                       if (! (fmt_st->flags & LDNS_COMMENT_FLAGS) &&
+                               ! (fmt_st->flags & LDNS_COMMENT_NSEC3_CHAIN)) {
                                break;
-                       case LDNS_RR_TYPE_DS:
-                               if ((fmt->flags & LDNS_COMMENT_BUBBLEBABBLE)
-                                               && ldns_rr_rdf(rr, 3) != NULL) {
-                                       uint8_t *data = ldns_rdf_data(
-                                                       ldns_rr_rdf(rr, 3));
-                                       size_t len = ldns_rdf_size(
-                                                       ldns_rr_rdf(rr, 3));
-                                       char *babble = ldns_bubblebabble(
-                                                       data, len);
-                                       if(babble) {
-                                               ldns_buffer_printf(output
-                                                       , " ;{%s}", babble);
-                                       }
-                                       LDNS_FREE(babble);
+                       }
+                       ldns_buffer_printf(output, " ;{");
+                       if ((fmt_st->flags & LDNS_COMMENT_FLAGS)) {
+                               if (ldns_nsec3_optout(rr)) {
+                                       ldns_buffer_printf(output,
+                                               " flags: optout");
+                               } else {
+                                       ldns_buffer_printf(output," flags: -");
                                }
-                               break;
-                       case LDNS_RR_TYPE_NSEC3:
-                               if (! (fmt->flags & LDNS_COMMENT_FLAGS) &&
-                                   ! (fmt->flags & LDNS_COMMENT_NSEC3_CHAIN)) {
-                                       break;
+                               if (fmt_st->flags & LDNS_COMMENT_NSEC3_CHAIN &&
+                                               fmt_st->hashmap != NULL) {
+                                       ldns_buffer_printf(output, ", ");
                                }
-                               ldns_buffer_printf(output, " ;{");
-                               if ((fmt->flags & LDNS_COMMENT_FLAGS)) {
-                                       if (ldns_nsec3_optout(rr)) {
-                                               ldns_buffer_printf(output,
-                                                       " flags: optout");
-                                       } else {
+                       }
+                       if (fmt_st->flags & LDNS_COMMENT_NSEC3_CHAIN &&
+                                       fmt_st->hashmap != NULL) {
+                               ldns_rbnode_t *node;
+                               ldns_rdf *key = ldns_dname_label(
+                                               ldns_rr_owner(rr), 0);
+                               if (key) {
+                                       node = ldns_rbtree_search(
+                                               fmt_st->hashmap,
+                                               (void *) key);
+                                       if (node->data) {
                                                ldns_buffer_printf(output,
-                                                       " flags: -");
-                                       }
-                                       if (fmt->flags & LDNS_COMMENT_NSEC3_CHAIN
-                                                       && fmt->data != NULL) {
-                                               ldns_buffer_printf(output, ", ");
+                                                       "from: ");
+                                               (void) ldns_rdf2buffer_str(
+                                                       output,
+                                                       (ldns_rdf*)node->data);
                                        }
+                                       ldns_rdf_free(key);
                                }
-                               if (fmt->flags & LDNS_COMMENT_NSEC3_CHAIN
-                                               && fmt->data != NULL) {
-                                       ldns_rbnode_t *node;
-                                       ldns_rdf *key = ldns_dname_label(
-                                                       ldns_rr_owner(rr), 0);
-                                       if (key) {
-                                               node = ldns_rbtree_search(
-                                                       (ldns_rbtree_t *)
-                                                               fmt->data,
-                                                       (void *) key);
-                                               if (node->data) {
-                                                       ldns_buffer_printf(
-                                                               output,
-                                                               "from: ");
-                                                       (void)
-                                                       ldns_rdf2buffer_str(
-                                                               output, 
-                                                               (ldns_rdf *)
-                                                               node->data);
-                                               }
-                                               ldns_rdf_free(key);
-                                       }
-                                       key = ldns_b32_ext2dname(
+                               key = ldns_b32_ext2dname(
                                                ldns_nsec3_next_owner(rr));
-                                       if (key) {
-                                               node = ldns_rbtree_search(
-                                                       (ldns_rbtree_t *)
-                                                               fmt->data,
-                                                       (void *) key);
-                                               if (node->data) {
-                                                       ldns_buffer_printf(
-                                                               output,
-                                                               " to: ");
-                                                       (void)
-                                                       ldns_rdf2buffer_str(
-                                                               output, 
-                                                               (ldns_rdf *)
-                                                               node->data);
-                                               }
-                                               ldns_rdf_free(key);
+                               if (key) {
+                                       node = ldns_rbtree_search(
+                                               fmt_st->hashmap,
+                                               (void *) key);
+                                       if (node->data) {
+                                               ldns_buffer_printf(output,
+                                                       " to: ");
+                                               (void) ldns_rdf2buffer_str(
+                                                       output, 
+                                                       (ldns_rdf*)node->data);
                                        }
+                                       ldns_rdf_free(key);
                                }
-                               ldns_buffer_printf(output, "}");
-                               break;
-                       default:
-                               break;
+                       }
+                       ldns_buffer_printf(output, "}");
+                       break;
+               default:
+                       break;
 
                }
        }
index 34f63714c34d1f1b421cdeea966178af996e3024..3e992c686f3a5665021628428767e7be0a21b852 100644 (file)
@@ -364,12 +364,30 @@ ldns_rdf *ldns_nsec3_bitmap(const ldns_rr *nsec3_rr);
 ldns_rdf *ldns_nsec3_hash_name_frm_nsec3(const ldns_rr *nsec, ldns_rdf *name);
 
 /**
- * Checks coverage of NSEC RR type bitmap
- * \param[in] nsec_bitmap The NSEC bitmap rdata field to check
- * \param[in] type The type to check
- * \return true if the NSEC RR covers the type
+ * Check if RR type t is enumerated and set in the RR type bitmap rdf.
+ * \param[in] bitmap the RR type bitmap rdf to look in
+ * \param[in] type the type to check for
+ * \return true when t is found and set, otherwise return false
  */
-bool ldns_nsec_bitmap_covers_type(const ldns_rdf *nsec_bitmap, ldns_rr_type type);
+bool ldns_nsec_bitmap_covers_type(const ldns_rdf* bitmap, ldns_rr_type type);
+
+/**
+ * Check if RR type t is enumerated in the type bitmap rdf and sets the bit.
+ * \param[in] bitmap the RR type bitmap rdf to look in
+ * \param[in] type the type to for which the bit to set
+ * \return LDNS_STATUS_OK on success. LDNS_STATUS_TYPE_NOT_IN_BITMAP is 
+ *         returned when the bitmap does not contain the bit to set.
+ */
+ldns_status ldns_nsec_bitmap_set_type(ldns_rdf* bitmap, ldns_rr_type type);
+
+/**
+ * Check if RR type t is enumerated in the type bitmap rdf and sets the bit.
+ * \param[in] bitmap the RR type bitmap rdf to look in
+ * \param[in] type the type to for which the bit to set
+ * \return LDNS_STATUS_OK on success. LDNS_STATUS_TYPE_NOT_IN_BITMAP is 
+ *         returned when the bitmap does not contain the bit to set.
+ */
+ldns_status ldns_nsec_bitmap_clear_type(ldns_rdf* rdf, ldns_rr_type t);
 
 /**
  * Checks coverage of NSEC(3) RR name span
index d37f74674d8449ee76c84df3369016eeecce0964..e70f8d6aa093694714e6e4081657242444b6eb46 100644 (file)
@@ -123,7 +123,8 @@ enum ldns_enum_status {
        LDNS_STATUS_INVALID_EUI48,
        LDNS_STATUS_INVALID_EUI64,
        LDNS_STATUS_WIRE_RDATA_ERR,
-       LDNS_STATUS_INVALID_TAG
+       LDNS_STATUS_INVALID_TAG,
+       LDNS_STATUS_TYPE_NOT_IN_BITMAP,
 };
 typedef enum ldns_enum_status ldns_status;
 
index 6b5fcd035b0b658c82be6ed54df957245396f533..4c7d14527fb162c7cbdecb6b95d04ad68273574f 100644 (file)
@@ -43,29 +43,35 @@ extern "C" {
  * Represent a NULL pointer (in stead of a pointer to a ldns_rr as "; (null)" 
  * as opposed to outputting nothing at all in such a case.
  */
-#define LDNS_COMMENT_NULLS             0x0001
+/*     Flag Name                       Flag Nr.        Has data associated
+       ---------------------------------------------------------------------*/
+#define LDNS_COMMENT_NULLS             (1 <<  0)
 /** Show key id with DNSKEY RR's as comment */
-#define LDNS_COMMENT_KEY_ID            0x0002
+#define LDNS_COMMENT_KEY_ID            (1 <<  1)
 /** Show if a DNSKEY is a ZSK or KSK as comment */
-#define LDNS_COMMENT_KEY_TYPE          0x0004
+#define LDNS_COMMENT_KEY_TYPE          (1 <<  2)
 /** Show DNSKEY key size as comment */
-#define LDNS_COMMENT_KEY_SIZE          0x0008
-/** Show key id, type and size as comment for DNSKEY RR's */
-#define LDNS_COMMENT_KEY               (LDNS_COMMENT_KEY_ID  \
-                                       |LDNS_COMMENT_KEY_TYPE\
-                                       |LDNS_COMMENT_KEY_SIZE)
+#define LDNS_COMMENT_KEY_SIZE          (1 <<  3)
 /** Provide bubblebabble representation for DS RR's as comment */
-#define LDNS_COMMENT_BUBBLEBABBLE      0x0010
+#define LDNS_COMMENT_BUBBLEBABBLE      (1 <<  4)
 /** Show when a NSEC3 RR has the optout flag set as comment */
-#define LDNS_COMMENT_FLAGS             0x0020
+#define LDNS_COMMENT_FLAGS             (1 <<  5)
 /** Show the unhashed owner and next owner names for NSEC3 RR's as comment */
-#define LDNS_COMMENT_NSEC3_CHAIN       0x0040
+#define LDNS_COMMENT_NSEC3_CHAIN       (1 <<  6)       /* yes */
 /** Print mark up */
-#define LDNS_COMMENT_LAYOUT            0x0080
+#define LDNS_COMMENT_LAYOUT            (1 <<  7)
 /** Also comment KEY_ID with RRSIGS **/
-#define LDNS_COMMENT_RRSIGS            0x0100
-#define LDNS_FMT_ZEROIZE_RRSIGS                0x0200
-#define LDNS_FMT_PAD_SOA_SERIAL                0x0400
+#define LDNS_COMMENT_RRSIGS            (1 <<  8)
+#define LDNS_FMT_ZEROIZE_RRSIGS                (1 <<  9)
+#define LDNS_FMT_PAD_SOA_SERIAL                (1 << 10)
+#define LDNS_FMT_RFC3597               (1 << 11)       /* yes */
+
+#define LDNS_FMT_FLAGS_WITH_DATA                           2
+
+/** Show key id, type and size as comment for DNSKEY RR's */
+#define LDNS_COMMENT_KEY               (LDNS_COMMENT_KEY_ID  \
+                                       |LDNS_COMMENT_KEY_TYPE\
+                                       |LDNS_COMMENT_KEY_SIZE)
 
 /**
  * Output format specifier
@@ -86,6 +92,18 @@ struct ldns_struct_output_format
 };
 typedef struct ldns_struct_output_format ldns_output_format;
 
+/**
+ * Output format struct with additional data for flags that use them.
+ * This struct may not be initialized directly. Use ldns_output_format_init
+ * to initialize.
+ */
+struct ldns_struct_output_format_storage
+{      int   flags;
+       ldns_rbtree_t* hashmap;    /* for LDNS_FMT_NSEC3_CHAIN */
+       ldns_rdf*      bitmap;     /* for LDNS_FMT_RFC3597     */
+};
+typedef struct ldns_struct_output_format_storage ldns_output_format_storage;
+
 /**
  * Standard output format record that disables commenting in the textual 
  * representation of Resource Records completely.
@@ -107,6 +125,55 @@ extern const ldns_output_format *ldns_output_format_default;
  */
 extern const ldns_output_format *ldns_output_format_bubblebabble;
 
+/**
+ * Initialize output format storage to the default value.
+ * \param[in] fmt A reference to an output_format_ storage struct
+ * \return The initialized storage struct typecasted to ldns_output_format
+ */
+INLINE
+ldns_output_format* ldns_output_format_init(ldns_output_format_storage* fmt) {
+       fmt->flags   = ldns_output_format_default->flags;
+       fmt->hashmap = NULL;
+       fmt->bitmap  = NULL;
+       return (ldns_output_format*)fmt;
+}
+
+/**
+ * Set an ouput format flag.
+ */
+INLINE void ldns_output_format_set(ldns_output_format* fmt, int flag) {
+        fmt->flags |= flag;
+}
+
+/**
+ * Clear an ouput format flag.
+ */
+INLINE void ldns_output_format_clear(ldns_output_format* fmt, int flag) {
+        fmt->flags &= !flag;
+}
+
+/**
+ * Makes sure the LDNS_FMT_RFC3597 is set in the output format.
+ * Marks the type to be printed in RFC3597 format.
+ * /param[in] fmt the output format to update
+ * /param[in] the type to be printed in RFC3597 format
+ * /return LDNS_STATUS_OK on success
+ */
+ldns_status
+ldns_output_format_set_type(ldns_output_format* fmt, ldns_rr_type type);
+
+/**
+ * Makes sure the LDNS_FMT_RFC3597 is set in the output format.
+ * Marks the type to not be printed in RFC3597 format. When no other types
+ * have been marked before, all known types (except the given one) will be
+ * marked for printing in RFC3597 format.
+ * /param[in] fmt the output format to update
+ * /param[in] the type not to be printed in RFC3597 format
+ * /return LDNS_STATUS_OK on success
+ */
+ldns_status
+ldns_output_format_clear_type(ldns_output_format* fmt, ldns_rr_type type);
+
 /**
  * Converts an ldns packet opcode value to its mnemonic, and adds that
  * to the output buffer
index 70131798cfc94794e7f237b9f6a35445bd2cd57b..8f7be8c2d74197db2a84a61b516669aff85263c7 100644 (file)
@@ -135,7 +135,10 @@ enum ldns_enum_rdf_type
         *  maximum length of 255 octets.
         * For URI.
         */
-       LDNS_RDF_TYPE_MULTI_STR
+       LDNS_RDF_TYPE_MULTI_STR,
+
+       /* Aliases */
+       LDNS_RDF_TYPE_BITMAP = LDNS_RDF_TYPE_NSEC
 };
 typedef enum ldns_enum_rdf_type ldns_rdf_type;
 
index 7d90a73499c5db54322e5f3ff0aef31d919fd4c7..1485cadf1ee5e9fbc9829e610cf81bb97063440b 100644 (file)
--- a/ldns/rr.h
+++ b/ldns/rr.h
@@ -359,6 +359,23 @@ struct ldns_struct_rr_descriptor
 };
 typedef struct ldns_struct_rr_descriptor ldns_rr_descriptor;
 
+
+/**
+ * Create a rr type bitmap rdf providing enough space to set all 
+ * known (to ldns) rr types.
+ * \param[out] rdf the constructed rdf
+ * \return LDNS_STATUS_OK if all went well.
+ */
+ldns_status ldns_rdf_bitmap_known_rr_types_space(ldns_rdf** rdf);
+
+/**
+ * Create a rr type bitmap rdf with at least all known (to ldns) rr types set.
+ * \param[out] rdf the constructed rdf
+ * \return LDNS_STATUS_OK if all went well.
+ */
+ldns_status ldns_rdf_bitmap_known_rr_types(ldns_rdf** rdf);
+
+
 /**
  * creates a new rr structure.
  * \return ldns_rr *
diff --git a/rr.c b/rr.c
index 2ec02e81c05fc4e6426903c0abd501830a08c0cf..eae1f3af196badb713552230993d378aeb4198c1 100644 (file)
--- a/rr.c
+++ b/rr.c
@@ -2380,6 +2380,125 @@ static ldns_rr_descriptor rdata_field_descriptors[] = {
 #define LDNS_RDATA_FIELD_DESCRIPTORS_COUNT \
        (sizeof(rdata_field_descriptors)/sizeof(rdata_field_descriptors[0]))
 
+
+/*---------------------------------------------------------------------------*
+ * The functions below return an bitmap RDF with the space required to set
+ * or unset all known RR types. Arguably these functions are better situated
+ * in rdata.c, however for the space calculation it is necesarry to walk
+ * through rdata_field_descriptors which is not easily possible from anywhere
+ * other than rr.c where it is declared static.
+ *
+ * Alternatively rr.c could have provided an iterator for rr_type or 
+ * rdf_descriptors, but this seemed overkill for internal use only.
+ */
+static ldns_rr_descriptor* rdata_field_descriptors_end =
+       &rdata_field_descriptors[LDNS_RDATA_FIELD_DESCRIPTORS_COUNT];
+
+/* From RFC3845:
+ *
+ * 2.1.2.  The List of Type Bit Map(s) Field
+ * 
+ *    The RR type space is split into 256 window blocks, each representing
+ *    the low-order 8 bits of the 16-bit RR type space.  Each block that
+ *    has at least one active RR type is encoded using a single octet
+ *    window number (from 0 to 255), a single octet bitmap length (from 1
+ *    to 32) indicating the number of octets used for the window block's
+ *    bitmap, and up to 32 octets (256 bits) of bitmap.
+ * 
+ *    Window blocks are present in the NSEC RR RDATA in increasing
+ *    numerical order.
+ * 
+ *    "|" denotes concatenation
+ * 
+ *    Type Bit Map(s) Field = ( Window Block # | Bitmap Length | Bitmap ) +
+ * 
+ *    <cut>
+ * 
+ *    Blocks with no types present MUST NOT be included.  Trailing zero
+ *    octets in the bitmap MUST be omitted.  The length of each block's
+ *    bitmap is determined by the type code with the largest numerical
+ *    value within that block, among the set of RR types present at the
+ *    NSEC RR's owner name.  Trailing zero octets not specified MUST be
+ *    interpreted as zero octets.
+ */
+static ldns_status
+ldns_rdf_bitmap_known_rr_types_set(ldns_rdf** rdf, int value)
+{
+       uint8_t  window;                /*  most significant octet of type */
+       uint8_t  subtype;               /* least significant octet of type */
+       uint16_t windows[256]           /* Max subtype per window */
+#ifndef S_SPLINT_S
+                             = { 0 }
+#endif
+                                    ;
+       ldns_rr_descriptor* d;  /* used to traverse rdata_field_descriptors */
+       size_t i;               /* used to traverse windows array */
+
+       size_t sz;                      /* size needed for type bitmap rdf */
+       uint8_t* data = NULL;           /* rdf data */
+       uint8_t* dptr;                  /* used to itraverse rdf data */
+
+       assert(rdf != NULL);
+
+       /* Which windows need to be in the bitmap rdf?
+        */
+       for (d=rdata_field_descriptors; d < rdata_field_descriptors_end; d++) {
+               window  = d->_type >> 8;
+               subtype = d->_type & 0xff;
+               if (windows[window] < subtype) {
+                       windows[window] = subtype;
+               }
+       }
+
+       /* How much space do we need in the rdf for those windows?
+        */
+       sz = 0;
+       for (i = 0; i < 256; i++) {
+               if (windows[i]) {
+                       sz += windows[i] / 8 + 3;
+               }
+       }
+       if (sz > 0) {
+               /* Format rdf data according RFC3845 Section 2.1.2 (see above)
+                */
+               dptr = data = LDNS_XMALLOC(uint8_t, sz);
+               if (!data) {
+                       return LDNS_STATUS_MEM_ERR;
+               }
+               for (i = 0; i < 256; i++) {
+                       if (windows[i]) {
+                               *dptr++ = (uint8_t)i;
+                               *dptr++ = (uint8_t)(windows[i] / 8 + 1);
+                               memset(dptr, value, dptr[-1]);
+                               dptr += dptr[-1];
+                       }
+               }
+       }
+       /* Allocate and return rdf structure for the data
+        */
+       *rdf = ldns_rdf_new(LDNS_RDF_TYPE_BITMAP, sz, data);
+       if (!*rdf) {
+               LDNS_FREE(data);
+               return LDNS_STATUS_MEM_ERR;
+       }
+       return LDNS_STATUS_OK;
+}
+
+ldns_status
+ldns_rdf_bitmap_known_rr_types_space(ldns_rdf** rdf)
+{
+       return ldns_rdf_bitmap_known_rr_types_set(rdf, 0);
+}
+
+ldns_status
+ldns_rdf_bitmap_known_rr_types(ldns_rdf** rdf)
+{
+       return ldns_rdf_bitmap_known_rr_types_set(rdf, 255);
+}
+/* End of RDF bitmap functions
+ *---------------------------------------------------------------------------*/
+
+
 const ldns_rr_descriptor *
 ldns_rr_descript(uint16_t type)
 {