summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWillem Toorop <willem@NLnetLabs.nl>2013-05-22 16:58:29 +0200
committerWillem Toorop <willem@NLnetLabs.nl>2013-05-22 16:58:29 +0200
commit5062893c04bfd8adc95ba41459c094b903b878be (patch)
tree8838540bf7c6218d6d87f3bbfcd971dba74517f2
parentbb5a63e9e3a1c98240265e067c7914055e55d658 (diff)
downloadldns-5062893c04bfd8adc95ba41459c094b903b878be.tar.gz
Extend output format with ability to print certain given rr types in unknown type format (i.e. rfc3597 format).
Thanks Jelte Jansen
-rw-r--r--Changelog4
-rw-r--r--dnssec.c130
-rw-r--r--error.c3
-rw-r--r--examples/ldns-read-zone.19
-rw-r--r--examples/ldns-read-zone.c118
-rw-r--r--examples/ldns-signzone.c18
-rw-r--r--higher.c47
-rw-r--r--host2str.c378
-rw-r--r--ldns/dnssec.h28
-rw-r--r--ldns/error.h3
-rw-r--r--ldns/host2str.h97
-rw-r--r--ldns/rdata.h5
-rw-r--r--ldns/rr.h17
-rw-r--r--rr.c119
14 files changed, 705 insertions, 271 deletions
diff --git a/Changelog b/Changelog
index f2443963..3e1eec7c 100644
--- 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.
diff --git a/dnssec.c b/dnssec.c
index 684d1716..46248a2c 100644
--- 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 caa40c8c..dc7aee85 100644
--- 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 }
};
diff --git a/examples/ldns-read-zone.1 b/examples/ldns-read-zone.1
index 7d4fd7d9..163b70f6 100644
--- a/examples/ldns-read-zone.1
+++ b/examples/ldns-read-zone.1
@@ -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
diff --git a/examples/ldns-read-zone.c b/examples/ldns-read-zone.c
index efe187e6..f26876fa 100644
--- a/examples/ldns-read-zone.c
+++ b/examples/ldns-read-zone.c
@@ -15,6 +15,44 @@
#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);
diff --git a/examples/ldns-signzone.c b/examples/ldns-signzone.c
index 25ece3a6..5eaa3cc0 100644
--- a/examples/ldns-signzone.c
+++ b/examples/ldns-signzone.c
@@ -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);
}
}
diff --git a/higher.c b/higher.c
index 990fb6af..25ce3585 100644
--- 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);
}
+
diff --git a/host2str.c b/host2str.c
index 08d62b5b..86b7f1e8 100644
--- a/host2str.c
+++ b/host2str.c
@@ -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;
@@ -819,6 +880,13 @@ ldns_rdf2buffer_str_nsec(ldns_buffer *output, const ldns_rdf *rdf)
}
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)
{
uint8_t salt_length;
@@ -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;
}
}
diff --git a/ldns/dnssec.h b/ldns/dnssec.h
index 34f63714..3e992c68 100644
--- a/ldns/dnssec.h
+++ b/ldns/dnssec.h
@@ -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
diff --git a/ldns/error.h b/ldns/error.h
index d37f7467..e70f8d6a 100644
--- a/ldns/error.h
+++ b/ldns/error.h
@@ -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;
diff --git a/ldns/host2str.h b/ldns/host2str.h
index 6b5fcd03..4c7d1452 100644
--- a/ldns/host2str.h
+++ b/ldns/host2str.h
@@ -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
@@ -87,6 +93,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.
*/
@@ -108,6 +126,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
* \param[in] *output the buffer to add the data to
diff --git a/ldns/rdata.h b/ldns/rdata.h
index 70131798..8f7be8c2 100644
--- a/ldns/rdata.h
+++ b/ldns/rdata.h
@@ -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;
diff --git a/ldns/rr.h b/ldns/rr.h
index 7d90a734..1485cadf 100644
--- 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 2ec02e81..eae1f3af 100644
--- 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)
{