summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWillem Toorop <willem@NLnetLabs.nl>2013-04-26 22:51:20 +0200
committerWillem Toorop <willem@NLnetLabs.nl>2013-04-26 22:51:20 +0200
commit070b4595981f48a21cc6b4f5047fdc2d09d3da91 (patch)
tree2ecbaa8606cc414f5384350dc1989d6dc705dc81
parent59e2c74f5e732417440e2daa8d3894b44422fc29 (diff)
downloadldns-070b4595981f48a21cc6b4f5047fdc2d09d3da91.tar.gz
CAA and URI
-rw-r--r--Changelog2
-rw-r--r--error.c3
-rw-r--r--host2str.c110
-rw-r--r--ldns/error.h3
-rw-r--r--ldns/rdata.h34
-rw-r--r--ldns/rr.h10
-rw-r--r--ldns/str2host.h29
-rw-r--r--rdata.c9
-rw-r--r--rr.c58
-rw-r--r--str2host.c238
-rw-r--r--test/08-zonereader.tpkgbin60635 -> 58187 bytes
-rw-r--r--wire2host.c14
12 files changed, 419 insertions, 91 deletions
diff --git a/Changelog b/Changelog
index e56ca144..bb134b20 100644
--- a/Changelog
+++ b/Changelog
@@ -1,5 +1,5 @@
1.6.17
- * New RR types NINFO, RKEY, CDS, EUI48, EUI64 & TA.
+ * New RR types NINFO, RKEY, CDS, EUI48, EUI64, URI, CAA and TA.
* 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/error.c b/error.c
index c8b1bdfb..caa40c8c 100644
--- a/error.c
+++ b/error.c
@@ -134,6 +134,9 @@ ldns_lookup_table ldns_error_str[] = {
"Conversion error, 8 two character hex numbers "
"seperated by dashes expected (i.e. xx-xx-xx-xx-xx-xx-xx-xx" },
{ LDNS_STATUS_WIRE_RDATA_ERR, "invalid rdata in wire format" },
+ { LDNS_STATUS_INVALID_TAG,
+ "Conversion error, a non-zero sequence of US-ASCII letters "
+ "and numbers in lower case expected" },
{ 0, NULL }
};
diff --git a/host2str.c b/host2str.c
index 3392567d..1729ad8e 100644
--- a/host2str.c
+++ b/host2str.c
@@ -381,18 +381,15 @@ ldns_rdf2buffer_str_aaaa(ldns_buffer *output, const ldns_rdf *rdf)
return ldns_buffer_status(output);
}
-ldns_status
-ldns_rdf2buffer_str_str(ldns_buffer *output, const ldns_rdf *rdf)
-{
- const uint8_t *data = ldns_rdf_data(rdf);
- uint8_t length = data[0];
- size_t i;
-
- ldns_buffer_printf(output, "\"");
- for (i = 1; i <= length; ++i) {
- char ch = (char) data[i];
- if (isprint((int)ch) || ch=='\t') {
- if (ch=='\"'||ch=='\\')
+static void
+ldns_characters2buffer_str(ldns_buffer* output,
+ size_t amount, const uint8_t* characters)
+{
+ uint8_t ch;
+ while (amount > 0) {
+ ch = *characters++;
+ if (isprint((int)ch) || ch == '\t') {
+ if (ch == '\"' || ch == '\\')
ldns_buffer_printf(output, "\\%c", ch);
else
ldns_buffer_printf(output, "%c", ch);
@@ -400,7 +397,22 @@ ldns_rdf2buffer_str_str(ldns_buffer *output, const ldns_rdf *rdf)
ldns_buffer_printf(output, "\\%03u",
(unsigned)(uint8_t) ch);
}
+ amount--;
}
+}
+
+ldns_status
+ldns_rdf2buffer_str_str(ldns_buffer *output, const ldns_rdf *rdf)
+{
+ if(ldns_rdf_size(rdf) < 1) {
+ return LDNS_STATUS_WIRE_RDATA_ERR;
+ }
+ if((int)ldns_rdf_size(rdf) < ldns_rdf_data(rdf)[0] + 1) {
+ return LDNS_STATUS_WIRE_RDATA_ERR;
+ }
+ ldns_buffer_printf(output, "\"");
+ ldns_characters2buffer_str(output,
+ ldns_rdf_data(rdf)[0], ldns_rdf_data(rdf) + 1);
ldns_buffer_printf(output, "\"");
return ldns_buffer_status(output);
}
@@ -1127,6 +1139,71 @@ ldns_rdf2buffer_str_eui64(ldns_buffer *output, const ldns_rdf *rdf)
}
ldns_status
+ldns_rdf2buffer_str_tag(ldns_buffer *output, const ldns_rdf *rdf)
+{
+ size_t nchars;
+ const uint8_t* chars;
+ char ch;
+ if (ldns_rdf_size(rdf) < 2) {
+ return LDNS_STATUS_WIRE_RDATA_ERR;
+ }
+ nchars = ldns_rdf_data(rdf)[0];
+ if (nchars >= ldns_rdf_size(rdf) || /* should be rdf_size - 1 */
+ nchars < 1) {
+ return LDNS_STATUS_WIRE_RDATA_ERR;
+ }
+ chars = ldns_rdf_data(rdf) + 1;
+ while (nchars > 0) {
+ ch = *chars++;
+ if (! isalnum(ch)) {
+ return LDNS_STATUS_WIRE_RDATA_ERR;
+ }
+ ldns_buffer_printf(output, "%c", ch);
+ nchars--;
+ }
+ return ldns_buffer_status(output);
+}
+
+ldns_status
+ldns_rdf2buffer_str_long_str(ldns_buffer *output, const ldns_rdf *rdf)
+{
+
+ ldns_buffer_printf(output, "\"");
+ ldns_characters2buffer_str(output,
+ ldns_rdf_size(rdf), ldns_rdf_data(rdf));
+ ldns_buffer_printf(output, "\"");
+ return ldns_buffer_status(output);
+}
+
+ldns_status
+ldns_rdf2buffer_str_multi_str(ldns_buffer *output, const ldns_rdf *rdf)
+{
+ size_t pos = 0;
+ if (ldns_rdf_size(rdf) < pos + 1) {
+ return LDNS_STATUS_WIRE_RDATA_ERR;
+ }
+ ldns_buffer_printf(output, "\"");
+ while (pos < ldns_rdf_size(rdf)) {
+ if (ldns_rdf_size(rdf) < pos + 1) {
+ return LDNS_STATUS_WIRE_RDATA_ERR;
+ }
+ if (ldns_rdf_size(rdf) < pos + 1 + ldns_rdf_data(rdf)[pos]) {
+ return LDNS_STATUS_WIRE_RDATA_ERR;
+ }
+ ldns_characters2buffer_str(output,
+ ldns_rdf_data(rdf)[pos],
+ &ldns_rdf_data(rdf)[pos + 1]);
+ /*
+ * if (ldns_rdf_data(rdf)[pos] < 255)
+ * break;
+ */
+ pos += 1 + ldns_rdf_data(rdf)[pos];
+ }
+ ldns_buffer_printf(output, "\"");
+ return ldns_buffer_status(output);
+}
+
+ldns_status
ldns_rdf2buffer_str(ldns_buffer *buffer, const ldns_rdf *rdf)
{
ldns_status res = LDNS_STATUS_OK;
@@ -1233,6 +1310,15 @@ ldns_rdf2buffer_str(ldns_buffer *buffer, const ldns_rdf *rdf)
case LDNS_RDF_TYPE_EUI64:
res = ldns_rdf2buffer_str_eui64(buffer, rdf);
break;
+ case LDNS_RDF_TYPE_TAG:
+ res = ldns_rdf2buffer_str_tag(buffer, rdf);
+ break;
+ case LDNS_RDF_TYPE_LONG_STR:
+ res = ldns_rdf2buffer_str_long_str(buffer, rdf);
+ break;
+ case LDNS_RDF_TYPE_MULTI_STR:
+ res = ldns_rdf2buffer_str_multi_str(buffer, rdf);
+ break;
}
} else {
/** This will write mangled RRs */
diff --git a/ldns/error.h b/ldns/error.h
index 75fa551d..d37f7467 100644
--- a/ldns/error.h
+++ b/ldns/error.h
@@ -122,7 +122,8 @@ enum ldns_enum_status {
LDNS_STATUS_INVALID_ILNP64,
LDNS_STATUS_INVALID_EUI48,
LDNS_STATUS_INVALID_EUI64,
- LDNS_STATUS_WIRE_RDATA_ERR
+ LDNS_STATUS_WIRE_RDATA_ERR,
+ LDNS_STATUS_INVALID_TAG
};
typedef enum ldns_enum_status ldns_status;
diff --git a/ldns/rdata.h b/ldns/rdata.h
index 70ce5679..70131798 100644
--- a/ldns/rdata.h
+++ b/ldns/rdata.h
@@ -28,7 +28,7 @@
extern "C" {
#endif
-#define LDNS_MAX_RDFLEN 8192
+#define LDNS_MAX_RDFLEN 65535
#define LDNS_RDF_SIZE_BYTE 1
#define LDNS_RDF_SIZE_WORD 2
@@ -106,12 +106,36 @@ enum ldns_enum_rdf_type
LDNS_RDF_TYPE_NSEC3_SALT,
/** nsec3 base32 string (with length byte on wire */
LDNS_RDF_TYPE_NSEC3_NEXT_OWNER,
- /** 4 shorts represented as 4 * 16 bit hex numbers seperated by colons */
+
+ /** 4 shorts represented as 4 * 16 bit hex numbers
+ * seperated by colons. For NID and L64.
+ */
LDNS_RDF_TYPE_ILNP64,
- /** EUI48; 6 * 8 bit hex numbers seperated by dashes */
+
+ /** 6 * 8 bit hex numbers seperated by dashes. For EUI48. */
LDNS_RDF_TYPE_EUI48,
- /** EUI64; 8 * 8 bit hex numbers seperated by dashes */
- LDNS_RDF_TYPE_EUI64
+ /** 8 * 8 bit hex numbers seperated by dashes. For EUI64. */
+ LDNS_RDF_TYPE_EUI64,
+
+ /** A non-zero sequence of US-ASCII letters and numbers in lower case.
+ * For CAA.
+ */
+ LDNS_RDF_TYPE_TAG,
+
+ /** A <character-string> encoding of the value field as specified
+ * [RFC1035], Section 5.1., encoded as remaining rdata.
+ * For CAA.
+ */
+ LDNS_RDF_TYPE_LONG_STR,
+
+ /** A <character-string> encoding of the value field as specified in
+ * section 5.1 of [RFC1035], encoded as a sequence of one or more
+ * <character-string> (as specified in section 3.3 of [RFC1035]),
+ * where all but the last <character-string> are filled up to the
+ * maximum length of 255 octets.
+ * For URI.
+ */
+ LDNS_RDF_TYPE_MULTI_STR
};
typedef enum ldns_enum_rdf_type ldns_rdf_type;
diff --git a/ldns/rr.h b/ldns/rr.h
index 00de3591..adcdf3fe 100644
--- a/ldns/rr.h
+++ b/ldns/rr.h
@@ -163,7 +163,7 @@ enum ldns_enum_rr_type
LDNS_RR_TYPE_OPT = 41,
/** RFC3123 */
LDNS_RR_TYPE_APL = 42,
- /** draft-ietf-dnsext-delegation */
+ /** RFC4034, RFC3658 */
LDNS_RR_TYPE_DS = 43,
/** SSH Key Fingerprint */
LDNS_RR_TYPE_SSHFP = 44, /* RFC 4255 */
@@ -179,8 +179,7 @@ enum ldns_enum_rr_type
LDNS_RR_TYPE_NSEC3 = 50, /* RFC 5155 */
LDNS_RR_TYPE_NSEC3PARAM = 51, /* RFC 5155 */
LDNS_RR_TYPE_NSEC3PARAMS = 51,
- /** draft-ietf-dane-protocol */
- LDNS_RR_TYPE_TLSA = 52,
+ LDNS_RR_TYPE_TLSA = 52, /* RFC 6698 */
/** draft-reid-dnsext-zs */
LDNS_RR_TYPE_NINFO = 56,
@@ -191,7 +190,7 @@ enum ldns_enum_rr_type
/** draft-barwood-dnsop-ds-publis */
LDNS_RR_TYPE_CDS = 59,
- LDNS_RR_TYPE_SPF = 99,
+ LDNS_RR_TYPE_SPF = 99, /* RFC 4408 */
LDNS_RR_TYPE_UINFO = 100,
LDNS_RR_TYPE_UID = 101,
@@ -216,6 +215,9 @@ enum ldns_enum_rr_type
LDNS_RR_TYPE_MAILA = 254,
/** any type (wildcard) */
LDNS_RR_TYPE_ANY = 255,
+ /** draft-faltstrom-uri-06 */
+ LDNS_RR_TYPE_URI = 256,
+ LDNS_RR_TYPE_CAA = 257, /* RFC 6844 */
/** DNSSEC Trust Authorities */
LDNS_RR_TYPE_TA = 32768,
diff --git a/ldns/str2host.h b/ldns/str2host.h
index cff43538..e6cee37a 100644
--- a/ldns/str2host.h
+++ b/ldns/str2host.h
@@ -268,6 +268,35 @@ ldns_status ldns_str2rdf_eui48(ldns_rdf **rd, const char *str);
*/
ldns_status ldns_str2rdf_eui64(ldns_rdf **rd, const char *str);
+/**
+ * Convert a non-zero sequence of US-ASCII letters and numbers into wireformat
+ * \param[in] rd the rdf where to put the data
+ * \param[in] str the string to be converted
+ * \return ldns_status
+ */
+ldns_status ldns_str2rdf_tag(ldns_rdf **rd, const char *str);
+
+/**
+ * Convert a <character-string> encoding of the value field as specified
+ * [RFC1035], Section 5.1., encoded as one bug chunk of data.
+ * \param[in] rd the rdf where to put the data
+ * \param[in] str the string to be converted
+ * \return ldns_status
+ */
+ldns_status ldns_str2rdf_long_str(ldns_rdf **rd, const char *str);
+
+/**
+ * Convert A <character-string> encoding of the value field as specified in
+ * section 5.1 of [RFC1035], encoded as a sequence of one or more
+ * <character-string> (as specified in section 3.3 of [RFC1035]),
+ * where all but the last <character-string> are filled up to the
+ * maximum length of 255 octets.
+ * \param[in] rd the rdf where to put the data
+ * \param[in] str the string to be converted
+ * \return ldns_status
+ */
+ldns_status ldns_str2rdf_multi_str(ldns_rdf **rd, const char *str);
+
#ifdef __cplusplus
}
#endif
diff --git a/rdata.c b/rdata.c
index f45f428d..d6850319 100644
--- a/rdata.c
+++ b/rdata.c
@@ -345,6 +345,15 @@ ldns_rdf_new_frm_str(ldns_rdf_type type, const char *str)
case LDNS_RDF_TYPE_EUI64:
status = ldns_str2rdf_eui64(&rdf, str);
break;
+ case LDNS_RDF_TYPE_TAG:
+ status = ldns_str2rdf_tag(&rdf, str);
+ break;
+ case LDNS_RDF_TYPE_LONG_STR:
+ status = ldns_str2rdf_long_str(&rdf, str);
+ break;
+ case LDNS_RDF_TYPE_MULTI_STR:
+ status = ldns_str2rdf_multi_str(&rdf, str);
+ break;
case LDNS_RDF_TYPE_NONE:
default:
/* default default ??? */
diff --git a/rr.c b/rr.c
index f97f89d2..b90af91e 100644
--- a/rr.c
+++ b/rr.c
@@ -87,6 +87,15 @@ ldns_rr_free(ldns_rr *rr)
}
}
+/* Syntactic sugar for ldns_rr_new_frm_str_internal */
+INLINE bool
+ldns_rdf_type_maybe_quoted(ldns_rdf_type rdf_type)
+{
+ return rdf_type == LDNS_RDF_TYPE_STR ||
+ rdf_type == LDNS_RDF_TYPE_LONG_STR ||
+ rdf_type == LDNS_RDF_TYPE_MULTI_STR;
+}
+
/*
* trailing spaces are allowed
* leading spaces are not allowed
@@ -359,9 +368,11 @@ ldns_rr_new_frm_str_internal(ldns_rr **newrr, const char *str,
delimiters = "\n\t ";
}
- if (ldns_rr_descriptor_field_type(desc,
- r_cnt) == LDNS_RDF_TYPE_STR &&
- ldns_buffer_remaining(rd_buf) > 0) {
+ if (ldns_rdf_type_maybe_quoted(
+ ldns_rr_descriptor_field_type(
+ desc, r_cnt)) &&
+ ldns_buffer_remaining(rd_buf) > 0){
+
/* skip spaces */
while (*(ldns_buffer_current(rd_buf)) == ' ') {
ldns_buffer_skip(rd_buf, 1);
@@ -1962,6 +1973,16 @@ static const ldns_rdf_type type_eui48_wireformat[] = {
static const ldns_rdf_type type_eui64_wireformat[] = {
LDNS_RDF_TYPE_EUI64
};
+static const ldns_rdf_type type_uri_wireformat[] = {
+ LDNS_RDF_TYPE_INT16,
+ LDNS_RDF_TYPE_INT16,
+ LDNS_RDF_TYPE_MULTI_STR
+};
+static const ldns_rdf_type type_caa_wireformat[] = {
+ LDNS_RDF_TYPE_INT8,
+ LDNS_RDF_TYPE_TAG,
+ LDNS_RDF_TYPE_LONG_STR
+};
/** \endcond */
/** \cond */
@@ -2128,23 +2149,24 @@ static ldns_rr_descriptor rdata_field_descriptors[] = {
{LDNS_RR_TYPE_NULL, "TYPE96", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
{LDNS_RR_TYPE_NULL, "TYPE97", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
{LDNS_RR_TYPE_NULL, "TYPE98", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
-{LDNS_RR_TYPE_SPF, "SPF", 1, 0, NULL, LDNS_RDF_TYPE_STR, LDNS_RR_NO_COMPRESS, 0 },
+ /* 99 */
+ {LDNS_RR_TYPE_SPF, "SPF", 1, 0, NULL, LDNS_RDF_TYPE_STR, LDNS_RR_NO_COMPRESS, 0 },
{LDNS_RR_TYPE_NULL, "TYPE100", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
{LDNS_RR_TYPE_NULL, "TYPE101", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
{LDNS_RR_TYPE_NULL, "TYPE102", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
{LDNS_RR_TYPE_NULL, "TYPE103", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
/* 104 */
-{LDNS_RR_TYPE_NID, "NID", 2, 2, type_nid_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+ {LDNS_RR_TYPE_NID, "NID", 2, 2, type_nid_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
/* 105 */
-{LDNS_RR_TYPE_L32, "L32", 2, 2, type_l32_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+ {LDNS_RR_TYPE_L32, "L32", 2, 2, type_l32_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
/* 106 */
-{LDNS_RR_TYPE_L64, "L64", 2, 2, type_l64_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+ {LDNS_RR_TYPE_L64, "L64", 2, 2, type_l64_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
/* 107 */
-{LDNS_RR_TYPE_LP, "LP", 2, 2, type_lp_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 1 },
+ {LDNS_RR_TYPE_LP, "LP", 2, 2, type_lp_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 1 },
/* 108 */
-{LDNS_RR_TYPE_EUI48, "EUI48", 1, 1, type_eui48_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+ {LDNS_RR_TYPE_EUI48, "EUI48", 1, 1, type_eui48_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
/* 109 */
-{LDNS_RR_TYPE_EUI64, "EUI64", 1, 1, type_eui64_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+ {LDNS_RR_TYPE_EUI64, "EUI64", 1, 1, type_eui64_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
{LDNS_RR_TYPE_NULL, "TYPE110", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
{LDNS_RR_TYPE_NULL, "TYPE111", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
{LDNS_RR_TYPE_NULL, "TYPE112", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
@@ -2289,10 +2311,20 @@ static ldns_rr_descriptor rdata_field_descriptors[] = {
* makes them into one. So, while in rfc 2845 is specified that a TSIG may have
* 8 or 9 rdata fields, by this implementation, the min/max are 7 each.
*/
-{LDNS_RR_TYPE_TSIG, "TSIG", 7, 7, type_tsig_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+ /* 250 */
+ {LDNS_RR_TYPE_TSIG, "TSIG", 7, 7, type_tsig_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+
/* split in array, no longer contiguous */
-{LDNS_RR_TYPE_TA, "TA", 4, 4, type_ds_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
-{LDNS_RR_TYPE_DLV, "DLV", 4, 4, type_ds_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }
+
+ /* 256 */
+ {LDNS_RR_TYPE_URI, "URI", 3, 3, type_uri_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+ /* 257 */
+ {LDNS_RR_TYPE_CAA, "CAA", 3, 3, type_caa_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+
+ /* 32768 */
+ {LDNS_RR_TYPE_TA, "TA", 4, 4, type_ds_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+ /* 32769 */
+ {LDNS_RR_TYPE_DLV, "DLV", 4, 4, type_ds_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }
};
/** \endcond */
diff --git a/str2host.c b/str2host.c
index 07154db7..ff5d5432 100644
--- a/str2host.c
+++ b/str2host.c
@@ -257,33 +257,47 @@ ldns_str2rdf_int8(ldns_rdf **rd, const char *bytestr)
* Returns the number of bytes read from the escaped string, or
* 0 on error
*/
-static int
-parse_escape(uint8_t *s, uint8_t *q) {
+INLINE bool
+parse_escape(uint8_t *ch_p, const char** str_p)
+{
uint16_t val;
- if (strlen((char *)s) > 3 &&
- isdigit((int) s[1]) &&
- isdigit((int) s[2]) &&
- isdigit((int) s[3])) {
- /* cast this so it fits */
- val = (uint16_t) ldns_hexdigit_to_int((char) s[1]) * 100 +
- ldns_hexdigit_to_int((char) s[2]) * 10 +
- ldns_hexdigit_to_int((char) s[3]);
+
+ if ((*str_p)[0] && isdigit((*str_p)[0]) &&
+ (*str_p)[1] && isdigit((*str_p)[1]) &&
+ (*str_p)[2] && isdigit((*str_p)[2])) {
+
+ val = ((*str_p)[0] - '0') * 100 +
+ ((*str_p)[1] - '0') * 10 +
+ ((*str_p)[2] - '0');
+
if (val > 255) {
- /* outside range */
- return 0;
+ *str_p = NULL;
+ return false;
}
- *q = (uint8_t) val;
- return 3;
+ *ch_p = (uint8_t)val;
+ *str_p += 3;
+
+ } else if ((*str_p)[0]) {
+
+ *ch_p = *(*str_p)++;
} else {
- s++;
- if (*s == '\0' || isdigit((int) *s)) {
- /* apparently the string terminator
- * or a digit has been escaped...
- */
- return 0;
- }
- *q = *s;
- return 1;
+ *ch_p = '\\';
+ }
+ return true;
+}
+
+INLINE bool
+parse_char(uint8_t *ch_p, const char** str_p)
+{
+ switch (**str_p) {
+
+ case '\0': return false;
+
+ case '\\': *str_p += 1;
+ return parse_escape(ch_p, str_p);
+
+ default: *ch_p = *(*str_p)++;
+ return true;
}
}
@@ -297,8 +311,8 @@ ldns_str2rdf_dname(ldns_rdf **d, const char *str)
{
size_t len;
- int esc;
- uint8_t *s, *q, *pq, label_len;
+ const char *s;
+ uint8_t *q, *pq, label_len;
uint8_t buf[LDNS_MAX_DOMAINLEN + 1];
*d = NULL;
@@ -328,7 +342,7 @@ ldns_str2rdf_dname(ldns_rdf **d, const char *str)
q = buf+1;
pq = buf;
label_len = 0;
- for (s = (uint8_t *)str; *s; s++, q++) {
+ for (s = str; *s; s++, q++) {
if (q > buf + LDNS_MAX_DOMAINLEN) {
return LDNS_STATUS_DOMAINNAME_OVERFLOW;
}
@@ -348,13 +362,11 @@ ldns_str2rdf_dname(ldns_rdf **d, const char *str)
break;
case '\\':
/* octet value or literal char */
- esc = parse_escape(s, q);
- if (esc > 0) {
- s += esc;
- label_len++;
- } else {
+ s += 1;
+ if (! parse_escape(q, &s)) {
return LDNS_STATUS_SYNTAX_BAD_ESCAPE;
}
+ label_len++;
break;
default:
*q = *s;
@@ -413,36 +425,41 @@ ldns_str2rdf_aaaa(ldns_rdf **rd, const char *str)
ldns_status
ldns_str2rdf_str(ldns_rdf **rd, const char *str)
{
- uint8_t *data;
- size_t i, str_i, esc_i;
+ uint8_t *data, *dp, ch;
- if (strlen(str) > 255) {
- return LDNS_STATUS_INVALID_STR;
+ /* Worst case space requirement. We'll realloc to actual size later. */
+ dp = data = LDNS_XMALLOC(uint8_t, strlen(str));
+ if (! data) {
+ return LDNS_STATUS_MEM_ERR;
}
- data = LDNS_XMALLOC(uint8_t, strlen(str) + 1);
- if(!data) return LDNS_STATUS_MEM_ERR;
- i = 1;
-
- for (str_i = 0; str_i < strlen(str); str_i++) {
- if (str[str_i] == '\\') {
- /* octet value or literal char */
- esc_i = (size_t) parse_escape((uint8_t*) &str[str_i], (uint8_t*) &data[i]);
- if (esc_i == 0) {
- LDNS_FREE(data);
- return LDNS_STATUS_SYNTAX_BAD_ESCAPE;
- }
- str_i += esc_i;
- } else {
- data[i] = (uint8_t) str[str_i];
+ /* Fill data (up to 255 characters) */
+ while (parse_char(&ch, &str)) {
+ if (dp - data >= 255) {
+ LDNS_FREE(data);
+ return LDNS_STATUS_INVALID_STR;
}
- i++;
+ *++dp = ch;
+ }
+ if (! str) {
+ return LDNS_STATUS_SYNTAX_BAD_ESCAPE;
}
- data[0] = i - 1;
- *rd = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_STR, i, data);
+ /* Fix last length byte */
+ data[0] = (dp - data) - 1;
- LDNS_FREE(data);
- return *rd?LDNS_STATUS_OK:LDNS_STATUS_MEM_ERR;
+ /* Lose the overmeasure */
+ data = LDNS_XREALLOC(data, uint8_t, dp - data);
+ if (! data) {
+ return LDNS_STATUS_MEM_ERR;
+ }
+
+ /* Create rdf */
+ *rd = ldns_rdf_new(LDNS_RDF_TYPE_LONG_STR, dp - data, data);
+ if (! *rd) {
+ LDNS_FREE(data);
+ return LDNS_STATUS_MEM_ERR;
+ }
+ return LDNS_STATUS_OK;
}
ldns_status
@@ -1392,3 +1409,114 @@ ldns_str2rdf_eui64(ldns_rdf **rd, const char *str)
}
return *rd ? LDNS_STATUS_OK : LDNS_STATUS_MEM_ERR;
}
+
+ldns_status
+ldns_str2rdf_tag(ldns_rdf **rd, const char *str)
+{
+ uint8_t *data;
+ const char* ptr;
+
+ if (strlen(str) > 255) {
+ return LDNS_STATUS_INVALID_TAG;
+ }
+ for (ptr = str; *ptr; ptr++) {
+ if (! isalnum(*ptr)) {
+ return LDNS_STATUS_INVALID_TAG;
+ }
+ }
+ data = LDNS_XMALLOC(uint8_t, strlen(str) + 1);
+ if (!data) {
+ return LDNS_STATUS_MEM_ERR;
+ }
+ data[0] = strlen(str);
+ memcpy(data + 1, str, strlen(str));
+
+ *rd = ldns_rdf_new(LDNS_RDF_TYPE_TAG, strlen(str) + 1, data);
+ if (!*rd) {
+ LDNS_FREE(data);
+ return LDNS_STATUS_MEM_ERR;
+ }
+ return LDNS_STATUS_OK;
+}
+
+ldns_status
+ldns_str2rdf_long_str(ldns_rdf **rd, const char *str)
+{
+ uint8_t *data, *dp, ch;
+
+ /* Worst case space requirement. We'll realloc to actual size later. */
+ dp = data = LDNS_XMALLOC(uint8_t, strlen(str));
+ if (! data) {
+ return LDNS_STATUS_MEM_ERR;
+ }
+
+ /* Fill data with parsed bytes */
+ while (parse_char(&ch, &str)) {
+ *dp++ = ch;
+ if (dp - data > LDNS_MAX_RDFLEN) {
+ LDNS_FREE(data);
+ return LDNS_STATUS_INVALID_STR;
+ }
+ }
+ if (! str) {
+ return LDNS_STATUS_SYNTAX_BAD_ESCAPE;
+ }
+
+ /* Lose the overmeasure */
+ data = LDNS_XREALLOC(data, uint8_t, dp - data);
+ if (! data) {
+ return LDNS_STATUS_MEM_ERR;
+ }
+
+ /* Create rdf */
+ *rd = ldns_rdf_new(LDNS_RDF_TYPE_LONG_STR, dp - data, data);
+ if (! *rd) {
+ LDNS_FREE(data);
+ return LDNS_STATUS_MEM_ERR;
+ }
+ return LDNS_STATUS_OK;
+}
+
+ldns_status
+ldns_str2rdf_multi_str(ldns_rdf **rd, const char *str)
+{
+ uint8_t *data, *dp, ch;
+
+ /* Worst case space requirement. We'll realloc to actual size later. */
+ dp = data = LDNS_XMALLOC(uint8_t, strlen(str) + strlen(str) / 255 + 1);
+ if (! data) {
+ return LDNS_STATUS_MEM_ERR;
+ }
+
+ /* Fill data with length byte (255) followed by 255 chars, repeatedly */
+ *dp++ = 255;
+ while (parse_char(&ch, &str)) {
+ *dp++ = ch;
+ if ((dp - data) % 256 == 0) {
+ *dp++ = 255;
+ }
+ if (dp - data > LDNS_MAX_RDFLEN) {
+ LDNS_FREE(data);
+ return LDNS_STATUS_INVALID_STR;
+ }
+ }
+ if (! str) {
+ return LDNS_STATUS_SYNTAX_BAD_ESCAPE;
+ }
+ /* Fix last length byte */
+ data[(dp - data) / 256 * 256] = (dp - data) % 256 - 1;
+
+ /* Lose the overmeasure */
+ data = LDNS_XREALLOC(data, uint8_t, dp - data);
+ if (! data) {
+ return LDNS_STATUS_MEM_ERR;
+ }
+
+ /* Create rdf */
+ *rd = ldns_rdf_new(LDNS_RDF_TYPE_LONG_STR, dp - data, data);
+ if (! *rd) {
+ LDNS_FREE(data);
+ return LDNS_STATUS_MEM_ERR;
+ }
+ return LDNS_STATUS_OK;
+}
diff --git a/test/08-zonereader.tpkg b/test/08-zonereader.tpkg
index e47c894f..46f617fa 100644
--- a/test/08-zonereader.tpkg
+++ b/test/08-zonereader.tpkg
Binary files differ
diff --git a/wire2host.c b/wire2host.c
index bd0ae8fc..d018e7bd 100644
--- a/wire2host.c
+++ b/wire2host.c
@@ -159,6 +159,7 @@ ldns_wire2rdf(ldns_rr *rr, const uint8_t *wire, size_t max, size_t *pos)
{
size_t end;
size_t cur_rdf_length;
+ size_t str_sz;
uint8_t rdf_index;
uint8_t *data;
uint16_t rd_length;
@@ -224,12 +225,24 @@ ldns_wire2rdf(ldns_rr *rr, const uint8_t *wire, size_t max, size_t *pos)
break;
case LDNS_RDF_TYPE_STR:
case LDNS_RDF_TYPE_NSEC3_SALT:
+ case LDNS_RDF_TYPE_TAG:
/* len is stored in first byte
* it should be in the rdf too, so just
* copy len+1 from this position
*/
cur_rdf_length = ((size_t) wire[*pos]) + 1;
break;
+
+ case LDNS_RDF_TYPE_MULTI_STR:
+ cur_rdf_length = 0;
+ while (*pos + cur_rdf_length < end) {
+ str_sz = wire[*pos + cur_rdf_length];
+ cur_rdf_length += str_sz + 1;
+ if (str_sz < 255) {
+ break;
+ }
+ }
+ break;
case LDNS_RDF_TYPE_INT16_DATA:
cur_rdf_length = (size_t) ldns_read_uint16(&wire[*pos]) + 2;
break;
@@ -250,6 +263,7 @@ ldns_wire2rdf(ldns_rr *rr, const uint8_t *wire, size_t max, size_t *pos)
case LDNS_RDF_TYPE_ATMA:
case LDNS_RDF_TYPE_IPSECKEY:
case LDNS_RDF_TYPE_TSIG:
+ case LDNS_RDF_TYPE_LONG_STR:
case LDNS_RDF_TYPE_NONE:
/*
* Read to end of rr rdata