summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWillem Toorop <willem@NLnetLabs.nl>2013-05-07 16:22:45 +0200
committerWillem Toorop <willem@NLnetLabs.nl>2013-05-07 16:22:45 +0200
commit3978ca2cd2d9529c37a568d5f9b775b1a5c682da (patch)
tree77e47fd49e4f94065b55beafb415d3c3503fcd46
parent612889453e3e36cf38aa59379079f4f4c4d77b4a (diff)
downloadldns-3978ca2cd2d9529c37a568d5f9b775b1a5c682da.tar.gz
HIP
-rw-r--r--Changelog3
-rw-r--r--host2str.c2
-rw-r--r--host2wire.c93
-rw-r--r--ldns/rr.h2
-rw-r--r--rr.c91
-rw-r--r--wire2host.c105
6 files changed, 245 insertions, 51 deletions
diff --git a/Changelog b/Changelog
index bb134b20..f2443963 100644
--- a/Changelog
+++ b/Changelog
@@ -1,5 +1,6 @@
1.6.17
- * New RR types NINFO, RKEY, CDS, EUI48, EUI64, URI, CAA and TA.
+ * 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.
* -T option for ldns-dane that has specific exit status for PKIX
validated connections without (secure) TLSA records.
diff --git a/host2str.c b/host2str.c
index a3bae5bc..08d62b5b 100644
--- a/host2str.c
+++ b/host2str.c
@@ -813,10 +813,8 @@ ldns_rdf2buffer_str_nsec(ldns_buffer *output, const ldns_rdf *rdf)
}
}
}
-
pos += (uint16_t) bitmap_length;
}
-
return ldns_buffer_status(output);
}
diff --git a/host2wire.c b/host2wire.c
index de1e01e9..c9d099c4 100644
--- a/host2wire.c
+++ b/host2wire.c
@@ -81,6 +81,64 @@ ldns_rr_list2buffer_wire(ldns_buffer *buffer,const ldns_rr_list *rr_list)
return ldns_buffer_status(buffer);
}
+static ldns_status
+ldns_hip_rdata2buffer_wire(ldns_buffer *buffer, const ldns_rr *rr)
+{
+ uint16_t i;
+
+ assert(ldns_rr_get_type(rr) == LDNS_RR_TYPE_HIP);
+
+ if (ldns_rr_rd_count(rr) >= 3 &&
+ ldns_rdf_get_type(ldns_rr_rdf(rr, 0)) == LDNS_RDF_TYPE_INT8 &&
+ ldns_rdf_get_type(ldns_rr_rdf(rr, 1)) == LDNS_RDF_TYPE_HEX &&
+ ldns_rdf_size(ldns_rr_rdf(rr, 1)) > 0 &&
+ ldns_rdf_size(ldns_rr_rdf(rr, 1)) <= 255 &&
+ ldns_rdf_get_type(ldns_rr_rdf(rr, 2)) == LDNS_RDF_TYPE_B64) {
+
+ /* From RFC 5205 section 5. HIP RR Storage Format:
+ *************************************************
+
+ 0 1 2 3
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | HIT length | PK algorithm | PK length |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | |
+ ~ HIT ~
+ | |
+ + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | | |
+ +-+-+-+-+-+-+-+-+-+-+-+ +
+ | Public Key |
+ ~ ~
+ | |
+ + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | | |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +
+ | |
+ ~ Rendezvous Servers ~
+ | |
+ + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | |
+ +-+-+-+-+-+-+-+ */
+
+ ldns_buffer_write_u8(buffer,
+ (uint8_t) ldns_rdf_size(ldns_rr_rdf(rr, 1)));
+ ldns_rdf2buffer_wire(buffer, ldns_rr_rdf(rr, 0));
+ ldns_buffer_write_u16(buffer,
+ (uint16_t) ldns_rdf_size(ldns_rr_rdf(rr, 2)));
+ i = 1;
+ } else {
+ i = 0;
+ }
+ while (i < ldns_rr_rd_count(rr)) {
+ (void) ldns_rdf2buffer_wire(buffer, ldns_rr_rdf(rr, i));
+ i++;
+ }
+ return ldns_buffer_status(buffer);
+}
+
+
ldns_status
ldns_rr2buffer_wire_canonical(ldns_buffer *buffer,
const ldns_rr *rr,
@@ -137,16 +195,19 @@ ldns_rr2buffer_wire_canonical(ldns_buffer *buffer,
ldns_buffer_write_u16(buffer, 0);
}
- for (i = 0; i < ldns_rr_rd_count(rr); i++) {
- if (pre_rfc3597) {
- (void) ldns_rdf2buffer_wire_canonical(
+ if (ldns_rr_get_type(rr) == LDNS_RR_TYPE_HIP) {
+ (void) ldns_hip_rdata2buffer_wire(buffer, rr);
+ } else {
+ for (i = 0; i < ldns_rr_rd_count(rr); i++) {
+ if (pre_rfc3597) {
+ (void) ldns_rdf2buffer_wire_canonical(
buffer, ldns_rr_rdf(rr, i));
- } else {
- (void) ldns_rdf2buffer_wire(
+ } else {
+ (void) ldns_rdf2buffer_wire(
buffer, ldns_rr_rdf(rr, i));
+ }
}
}
-
if (rdl_pos != 0) {
ldns_buffer_write_u16_at(buffer, rdl_pos,
ldns_buffer_position(buffer)
@@ -177,13 +238,15 @@ ldns_rr2buffer_wire(ldns_buffer *buffer, const ldns_rr *rr, int section)
/* remember pos for later */
rdl_pos = ldns_buffer_position(buffer);
ldns_buffer_write_u16(buffer, 0);
- }
-
- for (i = 0; i < ldns_rr_rd_count(rr); i++) {
- (void) ldns_rdf2buffer_wire(
- buffer, ldns_rr_rdf(rr, i));
}
-
+ if (ldns_rr_get_type(rr) == LDNS_RR_TYPE_HIP) {
+ (void) ldns_hip_rdata2buffer_wire(buffer, rr);
+ } else {
+ for (i = 0; i < ldns_rr_rd_count(rr); i++) {
+ (void) ldns_rdf2buffer_wire(
+ buffer, ldns_rr_rdf(rr, i));
+ }
+ }
if (rdl_pos != 0) {
ldns_buffer_write_u16_at(buffer, rdl_pos,
ldns_buffer_position(buffer)
@@ -216,11 +279,13 @@ ldns_status
ldns_rr_rdata2buffer_wire(ldns_buffer *buffer, const ldns_rr *rr)
{
uint16_t i;
+ if (ldns_rr_get_type(rr) == LDNS_RR_TYPE_HIP) {
+ return ldns_hip_rdata2buffer_wire(buffer, rr);
+ }
/* convert all the rdf's */
for (i = 0; i < ldns_rr_rd_count(rr); i++) {
- (void) ldns_rdf2buffer_wire(buffer, ldns_rr_rdf(rr, i));
+ (void) ldns_rdf2buffer_wire(buffer, ldns_rr_rdf(rr,i));
}
-
return ldns_buffer_status(buffer);
}
diff --git a/ldns/rr.h b/ldns/rr.h
index 57015cee..7d90a734 100644
--- a/ldns/rr.h
+++ b/ldns/rr.h
@@ -181,6 +181,8 @@ enum ldns_enum_rr_type
LDNS_RR_TYPE_NSEC3PARAMS = 51,
LDNS_RR_TYPE_TLSA = 52, /* RFC 6698 */
+ LDNS_RR_TYPE_HIP = 55, /* RFC 5205 */
+
/** draft-reid-dnsext-zs */
LDNS_RR_TYPE_NINFO = 56,
/** draft-reid-dnsext-rkey */
diff --git a/rr.c b/rr.c
index ea870ee0..2ec02e81 100644
--- a/rr.c
+++ b/rr.c
@@ -341,22 +341,18 @@ ldns_rr_new_frm_str_internal(ldns_rr **newrr, const char *str,
for (done = false, r_cnt = 0; !done && r_cnt < r_max; r_cnt++) {
quoted = false;
- /* if type = B64, the field may contain spaces */
- if (ldns_rr_descriptor_field_type(desc,
- r_cnt) == LDNS_RDF_TYPE_B64 ||
- ldns_rr_descriptor_field_type(desc,
- r_cnt) == LDNS_RDF_TYPE_HEX ||
- ldns_rr_descriptor_field_type(desc,
- r_cnt) == LDNS_RDF_TYPE_LOC ||
- ldns_rr_descriptor_field_type(desc,
- r_cnt) == LDNS_RDF_TYPE_WKS ||
- ldns_rr_descriptor_field_type(desc,
- r_cnt) == LDNS_RDF_TYPE_IPSECKEY ||
- ldns_rr_descriptor_field_type(desc,
- r_cnt) == LDNS_RDF_TYPE_NSEC) {
- delimiters = "\n\t";
- } else {
- delimiters = "\n\t ";
+
+ switch (ldns_rr_descriptor_field_type(desc, r_cnt)) {
+ case LDNS_RDF_TYPE_B64 :
+ case LDNS_RDF_TYPE_HEX : /* These rdf types may con- */
+ case LDNS_RDF_TYPE_LOC : /* tain whitespace, only if */
+ case LDNS_RDF_TYPE_WKS : /* it is the last rd field. */
+ case LDNS_RDF_TYPE_IPSECKEY :
+ case LDNS_RDF_TYPE_NSEC : if (r_cnt == r_max - 1) {
+ delimiters = "\n\t";
+ break;
+ }
+ default : delimiters = "\n\t ";
}
if (ldns_rdf_type_maybe_quoted(
@@ -487,14 +483,18 @@ ldns_rr_new_frm_str_internal(ldns_rr **newrr, const char *str,
case LDNS_RDF_TYPE_HEX:
case LDNS_RDF_TYPE_B64:
- /* can have spaces, and will always be the
- * last record of the rrdata. Read in the rest
+ /* When this is the last rdata field, then the
+ * rest should be read in (cause then these
+ * rdf types may contain spaces).
*/
- c = ldns_bget_token(rd_buf, b64,
- "\n", LDNS_MAX_RDFLEN);
- if (c != -1) {
- rd = strncat(rd, b64, LDNS_MAX_RDFLEN
- - strlen(rd) - 1);
+ if (r_cnt == r_max - 1) {
+ c = ldns_bget_token(rd_buf, b64,
+ "\n", LDNS_MAX_RDFLEN);
+ if (c != -1) {
+ rd = strncat(rd, b64,
+ LDNS_MAX_RDFLEN -
+ strlen(rd) - 1);
+ }
}
r = ldns_rdf_new_frm_str(
ldns_rr_descriptor_field_type(
@@ -1931,6 +1931,37 @@ static const ldns_rdf_type type_tlsa_wireformat[] = {
LDNS_RDF_TYPE_INT8,
LDNS_RDF_TYPE_HEX
};
+
+/**
+ * With HIP, wire and presentation format are out of step.
+ * In presentation format, we have:
+ * - a PK algorithm presented as integer in range [0..255]
+ * - a variable length HIT field presented as hexstring
+ * - a variable length Public Key field presented as Base64
+ *
+ * Unfortunately in the wireformat the lengths of the variable
+ * length HIT and Public Key fields do not directly preceed them.
+ * In stead we have:
+ * - 1 byte HIT length: h
+ * - 1 byte PK algorithm
+ * - 2 bytes Public Key length: p
+ * - h bytes HIT
+ * - p bytes Public Key
+ *
+ * In ldns those deviations from the conventions for rdata fields are best
+ * tackeled by letting the array refered to by the descriptor for HIP represent
+ * host format only.
+ *
+ * BEWARE! Unlike other RR types, actual HIP wire format does not directly
+ * follow the RDF types enumerated in the array pointed to by _wireformat in
+ * its descriptor record.
+ */
+static const ldns_rdf_type type_hip_hostformat[] = {
+ LDNS_RDF_TYPE_INT8,
+ LDNS_RDF_TYPE_HEX,
+ LDNS_RDF_TYPE_B64
+};
+
static const ldns_rdf_type type_nid_wireformat[] = {
LDNS_RDF_TYPE_INT16,
LDNS_RDF_TYPE_ILNP64
@@ -2066,7 +2097,7 @@ static ldns_rr_descriptor rdata_field_descriptors[] = {
/* 46 */
{LDNS_RR_TYPE_RRSIG, "RRSIG", 9, 9, type_rrsig_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 1 },
/* 47 */
- {LDNS_RR_TYPE_NSEC, "NSEC", 1, 2, type_nsec_wireformat, LDNS_RDF_TYPE_NSEC, LDNS_RR_NO_COMPRESS, 1 },
+ {LDNS_RR_TYPE_NSEC, "NSEC", 1, 2, type_nsec_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 1 },
/* 48 */
{LDNS_RR_TYPE_DNSKEY, "DNSKEY", 4, 4, type_dnskey_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
/* 49 */
@@ -2080,7 +2111,17 @@ static ldns_rr_descriptor rdata_field_descriptors[] = {
{LDNS_RR_TYPE_NULL, "TYPE53", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
{LDNS_RR_TYPE_NULL, "TYPE54", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
-{LDNS_RR_TYPE_NULL, "TYPE55", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+
+ /* 55
+ * Hip ends with 0 or more Rendezvous Servers represented as dname's.
+ * Hence the LDNS_RDF_TYPE_DNAME _variable field and the _maximum field
+ * set to 0.
+ *
+ * BEWARE! Unlike other RR types, actual HIP wire format does not
+ * directly follow the RDF types enumerated in the array pointed to
+ * by _wireformat. For more info see type_hip_hostformat declaration.
+ */
+ {LDNS_RR_TYPE_HIP, "HIP", 3, 3, type_hip_hostformat, LDNS_RDF_TYPE_DNAME, LDNS_RR_NO_COMPRESS, 0 },
/* 56 */
{LDNS_RR_TYPE_NINFO, "NINFO", 1, 0, NULL, LDNS_RDF_TYPE_STR, LDNS_RR_NO_COMPRESS, 0 },
diff --git a/wire2host.c b/wire2host.c
index d018e7bd..9ba2c3fb 100644
--- a/wire2host.c
+++ b/wire2host.c
@@ -165,8 +165,14 @@ ldns_wire2rdf(ldns_rr *rr, const uint8_t *wire, size_t max, size_t *pos)
uint16_t rd_length;
ldns_rdf *cur_rdf = NULL;
ldns_rdf_type cur_rdf_type;
- const ldns_rr_descriptor *descriptor = ldns_rr_descript(ldns_rr_get_type(rr));
+ const ldns_rr_descriptor *descriptor;
ldns_status status;
+ uint8_t hip_hit_length;
+ uint16_t hip_pubkey_length;
+
+ assert(rr != NULL);
+
+ descriptor = ldns_rr_descript(ldns_rr_get_type(rr));
if (*pos + 2 > max) {
return LDNS_STATUS_PACKET_OVERFLOW;
@@ -181,14 +187,86 @@ ldns_wire2rdf(ldns_rr *rr, const uint8_t *wire, size_t max, size_t *pos)
end = *pos + (size_t) rd_length;
- for (rdf_index = 0;
- rdf_index < ldns_rr_descriptor_maximum(descriptor); rdf_index++) {
- if (*pos >= end) {
- break;
+ if (ldns_rr_get_type(rr) == LDNS_RR_TYPE_HIP) {
+
+ /* From RFC 5205 section 5. HIP RR Storage Format:
+ *************************************************
+
+ 0 1 2 3
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | HIT length | PK algorithm | PK length |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | |
+ ~ HIT ~
+ | |
+ + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | | |
+ +-+-+-+-+-+-+-+-+-+-+-+ +
+ | Public Key |
+ ~ ~
+ | |
+ + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | | |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +
+ | |
+ ~ Rendezvous Servers ~
+ | |
+ + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | |
+ +-+-+-+-+-+-+-+ */
+
+ /* Space for HIT length, PK algorithm, PK length available? */
+ if (*pos + 4 > end) {
+ return LDNS_STATUS_PACKET_OVERFLOW;
+ }
+ /* Get HIT length and PK length */
+ hip_hit_length = wire[*pos];
+ hip_pubkey_length = ldns_read_uint16(&wire[*pos + 2]);
+
+ /* Space for HIT length, PK algorithm, PK length, HIT and
+ * Public Key available?
+ */
+ if (*pos + 4 + hip_hit_length + hip_pubkey_length > end) {
+ return LDNS_STATUS_PACKET_OVERFLOW;
+ }
+ /* Read PK algorithm rdf */
+ cur_rdf = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_INT8,
+ 1, &wire[*pos + 1]);
+ if (cur_rdf) {
+ ldns_rr_push_rdf(rr, cur_rdf);
+ }
+ *pos += 4;
+
+ /* Read HIT rdf */
+ cur_rdf = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_HEX,
+ hip_hit_length, &wire[*pos]);
+ if (cur_rdf) {
+ ldns_rr_push_rdf(rr, cur_rdf);
+ }
+ *pos += hip_hit_length;
+
+ /* Read Public Key rdf */
+ cur_rdf = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64,
+ hip_pubkey_length, &wire[*pos]);
+ if (cur_rdf) {
+ ldns_rr_push_rdf(rr, cur_rdf);
}
+ *pos += hip_pubkey_length;
+
+ /* Variable number of Rendezvous Servers may follow */
+ rdf_index = 3;
+ } else {
+ rdf_index = 0;
+ }
+ while (*pos < end &&
+ rdf_index < ldns_rr_descriptor_maximum(descriptor)) {
+
cur_rdf_length = 0;
- cur_rdf_type = ldns_rr_descriptor_field_type(descriptor, rdf_index);
+ cur_rdf_type = ldns_rr_descriptor_field_type(
+ descriptor, rdf_index);
+
/* handle special cases immediately, set length
for fixed length rdata and do them below */
switch (cur_rdf_type) {
@@ -244,7 +322,11 @@ ldns_wire2rdf(ldns_rr *rr, const uint8_t *wire, size_t max, size_t *pos)
}
break;
case LDNS_RDF_TYPE_INT16_DATA:
- cur_rdf_length = (size_t) ldns_read_uint16(&wire[*pos]) + 2;
+ if (*pos + 2 > end) {
+ return LDNS_STATUS_PACKET_OVERFLOW;
+ }
+ cur_rdf_length =
+ (size_t) ldns_read_uint16(&wire[*pos]) + 2;
break;
case LDNS_RDF_TYPE_B32_EXT:
case LDNS_RDF_TYPE_NSEC3_NEXT_OWNER:
@@ -283,7 +365,8 @@ ldns_wire2rdf(ldns_rr *rr, const uint8_t *wire, size_t max, size_t *pos)
}
memcpy(data, &wire[*pos], cur_rdf_length);
- cur_rdf = ldns_rdf_new(cur_rdf_type, cur_rdf_length, data);
+ cur_rdf = ldns_rdf_new(cur_rdf_type,
+ cur_rdf_length, data);
*pos = *pos + cur_rdf_length;
}
@@ -291,7 +374,11 @@ ldns_wire2rdf(ldns_rr *rr, const uint8_t *wire, size_t max, size_t *pos)
ldns_rr_push_rdf(rr, cur_rdf);
cur_rdf = NULL;
}
- }
+
+ rdf_index++;
+
+ } /* while (rdf_index < ldns_rr_descriptor_maximum(descriptor)) */
+
return LDNS_STATUS_OK;
}