]> git.ipfire.org Git - thirdparty/unbound.git/commitdiff
- sldns has type HIP.
authorWouter Wijngaards <wouter@nlnetlabs.nl>
Thu, 6 Feb 2014 10:57:42 +0000 (10:57 +0000)
committerWouter Wijngaards <wouter@nlnetlabs.nl>
Thu, 6 Feb 2014 10:57:42 +0000 (10:57 +0000)
git-svn-id: file:///svn/unbound/trunk@3071 be551aaa-1e26-0410-a405-d3ace91eadb9

doc/Changelog
ldns/rrdef.c
ldns/rrdef.h
ldns/str2wire.c
ldns/str2wire.h
ldns/wire2str.c
ldns/wire2str.h
testdata/test_ldnsrr.c4

index 70cb0df13903e20f21ba1b6772efd8f1e7143e7e..262efbb93ac01e2ab90666207757ed05a654bf12 100644 (file)
@@ -1,3 +1,6 @@
+6 February 2014: Wouter
+       - sldns has type HIP.
+
 5 February 2014: Wouter
        - Fix sldns parse tests on osx.
 
index 12d1a6da69bbe312e0a449198dbfd599afb7926e..8f7dd3036eca1295f7a2472c06acda572c98dc1a 100644 (file)
@@ -188,37 +188,9 @@ static const sldns_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 sldns_rdf_type type_hip_hostformat[] = {
-       LDNS_RDF_TYPE_INT8,
-       LDNS_RDF_TYPE_HEX,
-       LDNS_RDF_TYPE_B64
+static const sldns_rdf_type type_hip_wireformat[] = {
+       LDNS_RDF_TYPE_HIP
 };
-
 static const sldns_rdf_type type_nid_wireformat[] = {
        LDNS_RDF_TYPE_INT16,
        LDNS_RDF_TYPE_ILNP64
@@ -368,17 +340,12 @@ static sldns_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 },
-
-       /* 55
+        /* 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_NONE, LDNS_RR_NO_COMPRESS, 0 },
+       {LDNS_RR_TYPE_HIP, "HIP", 1, 1, type_hip_wireformat, LDNS_RDF_TYPE_DNAME, LDNS_RR_NO_COMPRESS, 0 },
 
 #ifdef DRAFT_RRTYPES
        /* 56 */
index 508d6c62b2a79035bc793815a75c7743b86c256a..442eb26e0e03421ce91c4a37743e9435c09eb03f 100644 (file)
@@ -302,10 +302,13 @@ enum sldns_enum_rdf_type
         LDNS_RDF_TYPE_PERIOD,
         /** tsig time 48 bits */
         LDNS_RDF_TYPE_TSIGTIME,
-       /** skip 21 unused */
+       /** Represents the Public Key Algorithm, HIT and Public Key fields
+           for the HIP RR types.  A HIP specific rdf type is used because of
+           the unusual layout in wireformat (see RFC 5205 Section 5) */
+       LDNS_RDF_TYPE_HIP,
         /** variable length any type rdata where the length
             is specified by the first 2 bytes */
-        LDNS_RDF_TYPE_INT16_DATA = 22,
+        LDNS_RDF_TYPE_INT16_DATA,
         /** protocol and port bitmaps */
         LDNS_RDF_TYPE_SERVICE,
         /** location data */
index 60b0b88c8c70c9836804733ac4e3b7555d59094a..e1eb84fba2a9db83c9e0e99ddcaddd699868dffe 100644 (file)
@@ -525,6 +525,67 @@ rrinternal_parse_rdf(sldns_buffer* strbuf, char* token, size_t token_len,
        return LDNS_WIREPARSE_ERR_OK;
 }
 
+/**
+ * Parse one rdf token.  Takes care of quotes and parenthesis.
+ */
+static int
+sldns_parse_rdf_token(sldns_buffer* strbuf, char* token, size_t token_len,
+       int* quoted, int* parens, int* tokquote, size_t* pre_data_pos,
+       const char* delimiters, sldns_rdf_type rdftype, size_t* token_strlen)
+{
+       size_t slen;
+
+       /* skip spaces */
+       while(sldns_buffer_remaining(strbuf) > 0 && !*quoted &&
+               *(sldns_buffer_current(strbuf)) == ' ') {
+               sldns_buffer_skip(strbuf, 1);
+       }
+
+       *pre_data_pos = sldns_buffer_position(strbuf);
+       if(sldns_bget_token_par(strbuf, token, (*quoted)?"\"":delimiters,
+               token_len, parens, (*quoted)?NULL:" \t") == -1) {
+               return 0;
+       }
+       slen = strlen(token);
+       /* check if not quoted yet, and we have encountered quotes */
+       if(!*quoted && sldns_rdf_type_maybe_quoted(rdftype) &&
+               slen >= 2 &&
+               (token[0] == '"' || token[0] == '\'') && 
+               (token[slen-1] == '"' || token[slen-1] == '\'')) {
+               /* move token two smaller (quotes) with endnull */
+               memmove(token, token+1, slen-2);
+               token[slen-2] = 0;
+               slen -= 2;
+               *quoted = 1;
+               *tokquote = 1; /* do not read endquotechar from buffer */
+       } else if(!*quoted && sldns_rdf_type_maybe_quoted(rdftype) &&
+               slen >= 2 &&
+               (token[0] == '"' || token[0] == '\'')) {
+               /* got the start quote (remove it) but read remainder
+                * of quoted string as well into remainder of token */
+               memmove(token, token+1, slen-1);
+               token[slen-1] = 0;
+               slen -= 1;
+               *quoted = 1;
+               *tokquote = 0;
+               /* rewind buffer over skipped whitespace */
+               while(sldns_buffer_position(strbuf) > 0 &&
+                       (sldns_buffer_current(strbuf)[-1] == ' ' ||
+                       sldns_buffer_current(strbuf)[-1] == '\t')) {
+                       sldns_buffer_skip(strbuf, -1);
+               }
+               if(sldns_bget_token_par(strbuf, token+slen,
+                       "\"", token_len-slen,
+                       parens, NULL) == -1) {
+                       return 0;
+               }
+               slen = strlen(token);
+       } else *tokquote = 0;
+       *token_strlen = slen;
+       return 1;
+}
+
+
 /** parse rdata from string into rr buffer(-remainder after dname). */
 static int
 rrinternal_parse_rdata(sldns_buffer* strbuf, char* token, size_t token_len,
@@ -553,52 +614,10 @@ rrinternal_parse_rdata(sldns_buffer* strbuf, char* token, size_t token_len,
                delimiters = rrinternal_get_delims(rdftype, r_cnt, r_max);
                quoted = rrinternal_get_quoted(strbuf, &delimiters, rdftype);
 
-               /* skip spaces */
-               while(sldns_buffer_remaining(strbuf) > 0 && !quoted &&
-                       *(sldns_buffer_current(strbuf)) == ' ') {
-                       sldns_buffer_skip(strbuf, 1);
-               }
-
-               pre_data_pos = sldns_buffer_position(strbuf);
-               if(sldns_bget_token_par(strbuf, token, quoted?"\"":delimiters,
-                       token_len, &parens, quoted?NULL:" \t") == -1) {
+               if(!sldns_parse_rdf_token(strbuf, token, token_len, &quoted,
+                       &parens, &tokquote, &pre_data_pos, delimiters, rdftype,
+                       &token_strlen))
                        break;
-               }
-               token_strlen = strlen(token);
-               /* check if not quoted yet, and we have encountered quotes */
-               if(!quoted && sldns_rdf_type_maybe_quoted(rdftype) &&
-                       token_strlen >= 2 &&
-                       (token[0] == '"' || token[0] == '\'') && 
-                       (token[token_strlen-1] == '"' || token[token_strlen-1] == '\'')) {
-                       /* move token two smaller (quotes) with endnull */
-                       memmove(token, token+1, token_strlen-2);
-                       token[token_strlen-2] = 0;
-                       token_strlen -= 2;
-                       quoted = 1;
-                       tokquote = 1; /* do not read endquotechar from buffer */
-               } else if(!quoted && sldns_rdf_type_maybe_quoted(rdftype) &&
-                       token_strlen >= 2 &&
-                       (token[0] == '"' || token[0] == '\'')) {
-                       /* got the start quote (remove it) but read remainder
-                        * of quoted string as well into remainder of token */
-                       memmove(token, token+1, token_strlen-1);
-                       token[token_strlen-1] = 0;
-                       token_strlen -= 1;
-                       quoted = 1;
-                       tokquote = 0;
-                       /* rewind buffer over skipped whitespace */
-                       while(sldns_buffer_position(strbuf) > 0 &&
-                               (sldns_buffer_current(strbuf)[-1] == ' ' ||
-                               sldns_buffer_current(strbuf)[-1] == '\t')) {
-                               sldns_buffer_skip(strbuf, -1);
-                       }
-                       if(sldns_bget_token_par(strbuf, token+token_strlen,
-                               "\"", token_len-token_strlen,
-                               &parens, NULL) == -1) {
-                               break;
-                       }
-                       token_strlen = strlen(token);
-               } else tokquote = 0;
 
                /* rfc3597 specifies that any type can be represented
                 * with \# method, which can contain spaces...
@@ -613,6 +632,38 @@ rrinternal_parse_rdata(sldns_buffer* strbuf, char* token, size_t token_len,
                                pre_data_pos)) != 0)
                                return status;
                } else if(token_strlen > 0 || quoted) {
+                       if(rdftype == LDNS_RDF_TYPE_HIP) {
+                               /* affix the HIT and PK fields, with a space */
+                               size_t addlen = token_len - token_strlen;
+                               size_t addstrlen = 0;
+                               /* add space */
+                               if(addlen < 1) break;
+                               token[token_strlen] = ' ';
+                               token[++token_strlen] = 0;
+                               /* read another token */
+                               addlen = token_len - token_strlen;
+                               if(!sldns_parse_rdf_token(strbuf,
+                                       token+token_strlen, addlen, &quoted,
+                                       &parens, &tokquote, &pre_data_pos,
+                                       delimiters, rdftype, &addstrlen))
+                                       break;
+                               token_strlen += addstrlen;
+                               /* add space */
+                               addlen = token_len - token_strlen;
+                               if(addlen < 1) break;
+                               token[token_strlen] = ' ';
+                               token[++token_strlen] = 0;
+                               /* read another token */
+                               addlen = token_len - token_strlen;
+                               addstrlen = 0;
+                               if(!sldns_parse_rdf_token(strbuf,
+                                       token+token_strlen, addlen, &quoted,
+                                       &parens, &tokquote, &pre_data_pos,
+                                       delimiters, rdftype, &addstrlen))
+                                       break;
+                               token_strlen += addstrlen;
+                       }
+
                        /* normal RR */
                        if((status=rrinternal_parse_rdf(strbuf, token,
                                token_len, rr, *rr_len, &rr_cur_len, rdftype,
@@ -907,6 +958,8 @@ int sldns_str2wire_rdf_buf(const char* str, uint8_t* rd, size_t* len,
                return sldns_str2wire_tag_buf(str, rd, len);
        case LDNS_RDF_TYPE_LONG_STR:
                return sldns_str2wire_long_str_buf(str, rd, len);
+       case LDNS_RDF_TYPE_HIP:
+               return sldns_str2wire_hip_buf(str, rd, len);
        case LDNS_RDF_TYPE_INT16_DATA:
                return sldns_str2wire_int16_data_buf(str, rd, len);
        case LDNS_RDF_TYPE_UNKNOWN:
@@ -1863,6 +1916,56 @@ int sldns_str2wire_long_str_buf(const char* str, uint8_t* rd, size_t* len)
        return LDNS_WIREPARSE_ERR_OK;
 }
 
+int sldns_str2wire_hip_buf(const char* str, uint8_t* rd, size_t* len)
+{
+       char* s, *end;
+       int e;
+       size_t hitlen, pklen = 0;
+       /* presentation format:
+        *      pk-algo HIThex pubkeybase64
+        * wireformat:
+        *      hitlen[1byte] pkalgo[1byte] pubkeylen[2byte] [hit] [pubkey] */
+       if(*len < 4)
+               return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL;
+
+       /* read PK algorithm */
+       rd[1] = (uint8_t)strtol((char*)str, &s, 10);
+       if(*s != ' ')
+               return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_INT, s-(char*)str);
+       s++;
+       while(*s == ' ')
+               s++;
+
+       /* read HIT hex tag */
+       /* zero terminate the tag (replace later) */
+       end = strchr(s, ' ');
+       if(!end) return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX, s-(char*)str);
+       *end = 0;
+       hitlen = *len - 4;
+       if((e = sldns_str2wire_hex_buf(s, rd+4, &hitlen)) != 0) {
+               *end = ' ';
+               return RET_ERR_SHIFT(e, s-(char*)str);
+       }
+       if(hitlen > 255) {
+               *end = ' ';
+               return RET_ERR(LDNS_WIREPARSE_ERR_LABEL_OVERFLOW, s-(char*)str+255*2);
+       }
+       rd[0] = (uint8_t)hitlen;
+       *end = ' ';
+       s = end+1;
+
+       /* read pubkey base64 sequence */
+       pklen = *len - 4 - hitlen;
+       if((e = sldns_str2wire_b64_buf(s, rd+4+hitlen, &pklen)) != 0)
+               return RET_ERR_SHIFT(e, s-(char*)str);
+       if(pklen > 65535)
+               return RET_ERR(LDNS_WIREPARSE_ERR_LABEL_OVERFLOW, s-(char*)str+65535);
+       sldns_write_uint16(rd+2, pklen);
+
+       *len = 4 + hitlen + pklen;
+       return LDNS_WIREPARSE_ERR_OK;
+}
+
 int sldns_str2wire_int16_data_buf(const char* str, uint8_t* rd, size_t* len)
 {
        size_t sz = sldns_b64_pton_calculate_size(strlen(str));
index 990c9fcbb0aa7102542a2c2da6c4c810a1bbb337..94c8933897c05f2f7dd1e03fb79695d1b725fb93 100644 (file)
@@ -516,6 +516,15 @@ int sldns_str2wire_tag_buf(const char* str, uint8_t* rd, size_t* len);
  */
 int sldns_str2wire_long_str_buf(const char* str, uint8_t* rd, size_t* len);
 
+/**
+ * Convert rdf of type LDNS_RDF_TYPE_HIP from string to wireformat.
+ * @param str: the text to convert for this rdata element.
+ * @param rd: rdata buffer for the wireformat.
+ * @param len: length of rd buffer on input, used length on output.
+ * @return 0 on success, error on failure.
+ */
+int sldns_str2wire_hip_buf(const char* str, uint8_t* rd, size_t* len);
+
 /**
  * Convert rdf of type LDNS_RDF_TYPE_INT16_DATA from string to wireformat.
  * @param str: the text to convert for this rdata element.
index 76920c17f4ed518b6d38760eb374500881da71ef..79cc96292197cfd70e105dba4771a6d38c62b149 100644 (file)
@@ -946,6 +946,8 @@ int sldns_wire2str_rdf_scan(uint8_t** d, size_t* dlen, char** s, size_t* slen,
        case LDNS_RDF_TYPE_IPSECKEY:
                return sldns_wire2str_ipseckey_scan(d, dlen, s, slen, pkt,
                        pktlen);
+       case LDNS_RDF_TYPE_HIP:
+               return sldns_wire2str_hip_scan(d, dlen, s, slen);
        case LDNS_RDF_TYPE_INT16_DATA:
                return sldns_wire2str_int16_data_scan(d, dlen, s, slen);
        case LDNS_RDF_TYPE_NSEC3_NEXT_OWNER:
@@ -1531,6 +1533,31 @@ int sldns_wire2str_ipseckey_scan(uint8_t** d, size_t* dl, char** s, size_t* sl,
        return w;
 }
 
+int sldns_wire2str_hip_scan(uint8_t** d, size_t* dl, char** s, size_t* sl)
+{
+       int w;
+       uint8_t algo, hitlen;
+       uint16_t pklen;
+
+       /* read lengths */
+       if(*dl < 4)
+               return -1;
+       hitlen = (*d)[0];
+       algo = (*d)[1];
+       pklen = sldns_read_uint16((*d)+2);
+       if(*dl < (size_t)4 + (size_t)hitlen + (size_t)pklen)
+               return -1;
+
+       /* write: algo hit pubkey */
+       w = sldns_str_print(s, sl, "%u ", (unsigned)algo);
+       w += print_hex_buf(s, sl, (*d)+4, hitlen);
+       w += sldns_str_print(s, sl, " ");
+       (*d)+=4+hitlen;
+       (*dl)-= (4+hitlen);
+       w += sldns_wire2str_b64_scan_num(d, dl, s, sl, pklen);
+       return w;
+}
+
 int sldns_wire2str_int16_data_scan(uint8_t** d, size_t* dl, char** s, size_t* sl)
 {
        uint16_t n;
index 072d01292ad2c196a7295ddd49166599565896c8..67f543566267414757894ddb02547bf51d8ef00c 100644 (file)
@@ -770,6 +770,19 @@ int sldns_wire2str_atma_scan(uint8_t** data, size_t* data_len, char** str,
 int sldns_wire2str_ipseckey_scan(uint8_t** data, size_t* data_len, char** str,
        size_t* str_len, uint8_t* pkt, size_t pktlen);
 
+/**
+ * Scan wireformat HIP (algo, HIT, pubkey) field to string, with user buffers.
+ * It shifts the arguments to move along (see sldns_wire2str_pkt_scan).
+ * @param data: wireformat data.
+ * @param data_len: length of data buffer.
+ * @param str: string buffer.
+ * @param str_len: length of string buffer.
+ * @return number of characters (except null) needed to print.
+ *     Can return -1 on failure.
+ */
+int sldns_wire2str_hip_scan(uint8_t** data, size_t* data_len, char** str,
+       size_t* str_len);
+
 /**
  * Scan wireformat int16_data field to string, with user buffers.
  * It shifts the arguments to move along (see sldns_wire2str_pkt_scan).
index 2dc4a7ebd12f743dd6690a2a16ff60f5e2388911..78591fcbc3a17d46eb06928e61648969ad6293d6 100644 (file)
@@ -70,8 +70,8 @@ all.rr.org.   3600    IN      DHCID   AAIBY2/AuCccgoJbsaxcQc9TUapptP69lOjxfNuVAA2kjEA=
 ee19kl3631qol646kjjrh6lh96pduqii.all.rr.org.   3600    IN      NSEC3   1 0 5 6467B16F6F36BA4D 13k9b8dv58kcn28us3fc0lqa60jeadp0 A RRSIG
 03616C6C027272036F7267000033000100000E10000D01000005086467B16F6F36BA4D
 all.rr.org.    3600    IN      NSEC3PARAM      1 0 5 6467B16F6F36BA4D
-03616C6C027272036F7267000037000100000E10009E02200100107B1A74DF365639CC39F1D57803010001B771CA136E4AEB5CE44333C53B3D2C13C22243851FC708BCCE29F7E2EB5787B5F56CCAD34F8223ACC10904DDB56B2EC4A6D6232F3B50EA094F0914B3B941BBE529AF582C36BBADEFDAF2ADAF9B4911906F5B2522603C615272B880EC8FB930CC6EE39C444DAA75B1678F005A4B2499D1DA5433F805C7A5AD3237ACC5DD5C5E43AEFB1EC5A9A995E728
-all.rr.org.    3600    IN      HIP     \# 158 02200100107B1A74DF365639CC39F1D57803010001B771CA136E4AEB5CE44333C53B3D2C13C22243851FC708BCCE29F7E2EB5787B5F56CCAD34F8223ACC10904DDB56B2EC4A6D6232F3B50EA094F0914B3B941BBE529AF582C36BBADEFDAF2ADAF9B4911906F5B2522603C615272B880EC8FB930CC6EE39C444DAA75B1678F005A4B2499D1DA5433F805C7A5AD3237ACC5DD5C5E43AEFB1EC5A9A995E728
+03616C6C027272036F7267000037000100000E1000A910020084200100107B1A74DF365639CC39F1D57803010001B771CA136E4AEB5CE44333C53B3D2C13C22243851FC708BCCE29F7E2EB5787B5F56CCAD34F8223ACC10904DDB56B2EC4A6D6232F3B50EA094F0914B3B941BBE529AF582C36BBADEFDAF2ADAF9B4911906F5B2522603C615272B880EC8FB930CC6EE39C444DAA75B1678F005A4B2499D1DA5433F805C7A5AD3237ACC5DD5C5E4303727673076578616D706C6503636F6D00
+all.rr.org.    3600    IN      HIP     2 200100107B1A74DF365639CC39F1D578 AwEAAbdxyhNuSutc5EMzxTs9LBPCIkOFH8cIvM4p9+LrV4e19WzK00+CI6zBCQTdtWsuxKbWIy87UOoJTwkUs7lBu+Upr1gsNrut79ryra+bSRGQb1slImA8YVJyuIDsj7kwzG7jnERNqnWxZ48AWkskmdHaVDP4BcelrTI3rMXdXF5D rvs.example.com.
 03616C6C027272036F7267000063000100000E10002625763D73706631202B6D7820613A636F6C6F2E6578616D706C652E636F6D2F3238202D616C6C
 all.rr.org.    3600    IN      SPF     "v=spf1 +mx a:colo.example.com/28 -all"
 03616C6C027272036F7267008001000100000E10001830390301123456789ABCDEF67890123456789ABCDEF67890