]> git.ipfire.org Git - thirdparty/ldns.git/commitdiff
CAA and URI
authorWillem Toorop <willem@NLnetLabs.nl>
Fri, 26 Apr 2013 20:51:20 +0000 (20:51 +0000)
committerWillem Toorop <willem@NLnetLabs.nl>
Fri, 26 Apr 2013 20:51:20 +0000 (20:51 +0000)
12 files changed:
Changelog
error.c
host2str.c
ldns/error.h
ldns/rdata.h
ldns/rr.h
ldns/str2host.h
rdata.c
rr.c
str2host.c
test/08-zonereader.tpkg
wire2host.c

index e56ca144cc60ea083854a326f86e0b65ad566d82..bb134b20ec222505ec91daffdea38d5497c6c929 100644 (file)
--- 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 c8b1bdfb0cf819821e2ab893fb037e4606d92b36..caa40c8c0bd6193742160de81a01250ecaa99a4d 100644 (file)
--- 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 }
 };
 
index 3392567ddcf86c4cc5fc5e4701cc397aa8f8639a..1729ad8edadd4e4e358017b320af1fd75fda3831 100644 (file)
@@ -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);
 }
@@ -1126,6 +1138,71 @@ ldns_rdf2buffer_str_eui64(ldns_buffer *output, const ldns_rdf *rdf)
        return ldns_buffer_status(output);
 }
 
+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)
 {
@@ -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 */
index 75fa551db44c559a0550b3cedf7d478c4005c62c..d37f74674d8449ee76c84df3369016eeecce0964 100644 (file)
@@ -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;
 
index 70ce5679aa3367fad95b69d9170bdf7dd4abce21..70131798cfc94794e7f237b9f6a35445bd2cd57b 100644 (file)
@@ -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;
 
index 00de359144c2cd9d09c96911f51502fb366d13d3..adcdf3fed5c74ab7f6c5a4b1f32bfc85a4b05d60 100644 (file)
--- 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,
index cff435384deb529f996069b463b173b48b772478..e6cee37a18740325bfebcbdd6094af2ca85d04a4 100644 (file)
@@ -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 f45f428d6f18b4dda3c9d54d96fbd9a5f95145b9..d68503194b84da2416396ac3267d1793b02d33bb 100644 (file)
--- 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 f97f89d21c1a72214e271583535afb26e1f9a233..b90af91e816e7667172c34c02b4e0679915f0a46 100644 (file)
--- 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 */
 
index 07154db7fb651cf2f9ca67354715856ab44e182b..ff5d5432568cadd3860f4605cd102ae6c9297509 100644 (file)
@@ -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;
+}
index e47c894f07f121e9f0f86942bce730dff63dd66a..46f617fa052284c48195e1cd6daacdcb836e9e75 100644 (file)
Binary files a/test/08-zonereader.tpkg and b/test/08-zonereader.tpkg differ
index bd0ae8fc9ae5c2a38bebc99ae5430020cd4f146f..d018e7bd88d436d665631f875990da93155d7aee 100644 (file)
@@ -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