From: Willem Toorop Date: Wed, 10 Jul 2019 10:53:38 +0000 (+0200) Subject: AMTRELAY draft rr type X-Git-Tag: release-1.7.1-rc1~23^2^2~1 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=f25e179237546eb193bfb204db6d0431939483c8;p=thirdparty%2Fldns.git AMTRELAY draft rr type enable with --enable-rrtype-amtrelay --- diff --git a/configure.ac b/configure.ac index 9368c370..40190297 100644 --- a/configure.ac +++ b/configure.ac @@ -647,6 +647,15 @@ case "$enable_rrtype_doa" in no|*) ;; esac +AC_ARG_ENABLE(rrtype-amtrelay, AC_HELP_STRING([--enable-rrtype-amtrelay], [Enable draft RR type AMTRELAY.])) +case "$enable_rrtype_amtrelay" in + yes) + AC_DEFINE_UNQUOTED([RRTYPE_AMTRELAY], [], [Define this to enable RR type AMTRELAY.]) + ;; + no|*) + ;; +esac + AC_SUBST(LIBSSL_CPPFLAGS) diff --git a/host2str.c b/host2str.c index 154504c8..474ab993 100644 --- a/host2str.c +++ b/host2str.c @@ -1290,6 +1290,93 @@ ldns_rdf2buffer_str_hip(ldns_buffer *output, const ldns_rdf *rdf) return ldns_buffer_status(output); } +/* implementation mimiced from ldns_rdf2buffer_str_ipseckey */ +ldns_status +ldns_rdf2buffer_str_amtrelay(ldns_buffer *output, const ldns_rdf *rdf) +{ + /* wire format from + * draft-ietf-mboned-driad-amt-discovery Section 4.2 + */ + uint8_t *data = ldns_rdf_data(rdf); + uint8_t precedence; + uint8_t discovery_optional; + uint8_t relay_type; + + ldns_rdf *relay = NULL; + uint8_t *relay_data; + + size_t offset = 0; + ldns_status status; + + if (ldns_rdf_size(rdf) < 2) { + return LDNS_STATUS_WIRE_RDATA_ERR; + } + precedence = data[0]; + discovery_optional = ((data[1] & 0x80) >> 7); + relay_type = data[1] & 0x7F; + offset = 2; + + switch (relay_type) { + case 0: + /* no relay */ + break; + case 1: + relay_data = LDNS_XMALLOC(uint8_t, LDNS_IP4ADDRLEN); + if(!relay_data) + return LDNS_STATUS_MEM_ERR; + if (ldns_rdf_size(rdf) < offset + LDNS_IP4ADDRLEN) { + return LDNS_STATUS_ERR; + } + memcpy(relay_data, &data[offset], LDNS_IP4ADDRLEN); + relay = ldns_rdf_new(LDNS_RDF_TYPE_A, + LDNS_IP4ADDRLEN , relay_data); + offset += LDNS_IP4ADDRLEN; + if(!relay) { + LDNS_FREE(relay_data); + return LDNS_STATUS_MEM_ERR; + } + break; + case 2: + relay_data = LDNS_XMALLOC(uint8_t, LDNS_IP6ADDRLEN); + if(!relay_data) + return LDNS_STATUS_MEM_ERR; + if (ldns_rdf_size(rdf) < offset + LDNS_IP6ADDRLEN) { + return LDNS_STATUS_ERR; + } + memcpy(relay_data, &data[offset], LDNS_IP6ADDRLEN); + offset += LDNS_IP6ADDRLEN; + relay = + ldns_rdf_new(LDNS_RDF_TYPE_AAAA, + LDNS_IP6ADDRLEN, relay_data); + if(!relay) { + LDNS_FREE(relay_data); + return LDNS_STATUS_MEM_ERR; + } + break; + case 3: + status = ldns_wire2dname(&relay, data, + ldns_rdf_size(rdf), &offset); + if(status != LDNS_STATUS_OK) + return status; + break; + default: + /* error? */ + break; + } + + if (ldns_rdf_size(rdf) != offset) { + return LDNS_STATUS_ERR; + } + ldns_buffer_printf(output, "%u %u %u ", + precedence, discovery_optional, relay_type); + if (relay) + (void) ldns_rdf2buffer_str(output, relay); + + ldns_rdf_deep_free(relay); + return ldns_buffer_status(output); +} + + static ldns_status ldns_rdf2buffer_str_fmt(ldns_buffer *buffer, const ldns_output_format* fmt, const ldns_rdf *rdf) @@ -1405,6 +1492,9 @@ ldns_rdf2buffer_str_fmt(ldns_buffer *buffer, case LDNS_RDF_TYPE_LONG_STR: res = ldns_rdf2buffer_str_long_str(buffer, rdf); break; + case LDNS_RDF_TYPE_AMTRELAY: + res = ldns_rdf2buffer_str_amtrelay(buffer, rdf); + break; } } else { /** This will write mangled RRs */ diff --git a/ldns/host2str.h b/ldns/host2str.h index 325c562f..4b443d05 100644 --- a/ldns/host2str.h +++ b/ldns/host2str.h @@ -636,6 +636,17 @@ ldns_status ldns_rdf2buffer_str_long_str(ldns_buffer *output, ldns_status ldns_rdf2buffer_str_hip(ldns_buffer *output, const ldns_rdf *rdf); +/** + * Converts an LDNS_RDF_TYPE_AMTRELAY rdata element to presentation format for + * the precedence, D-bit, type and relay and adds it to the output buffer + * \param[in] *rdf The rdata to convert + * \param[in] *output The buffer to add the data to + * \return LDNS_STATUS_OK on success, and error status on failure + */ +ldns_status ldns_rdf2buffer_str_amtrelay(ldns_buffer *output, + const ldns_rdf *rdf); + + /** * Converts the data in the rdata field to presentation format and * returns that as a char *. diff --git a/ldns/rdata.h b/ldns/rdata.h index 981dd94a..2767e8b0 100644 --- a/ldns/rdata.h +++ b/ldns/rdata.h @@ -139,6 +139,9 @@ enum ldns_enum_rdf_type LDNS_RDF_TYPE_SELECTOR, LDNS_RDF_TYPE_MATCHING_TYPE, + /** draft-ietf-mboned-driad-amt-discovery **/ + LDNS_RDF_TYPE_AMTRELAY, + /* Aliases */ LDNS_RDF_TYPE_BITMAP = LDNS_RDF_TYPE_NSEC }; diff --git a/ldns/rr.h b/ldns/rr.h index 5039d73c..89cc0b6f 100644 --- a/ldns/rr.h +++ b/ldns/rr.h @@ -223,6 +223,9 @@ enum ldns_enum_rr_type LDNS_RR_TYPE_AVC = 258, /* Cisco's DNS-AS RR, see www.dns-as.org */ LDNS_RR_TYPE_DOA = 259, /* draft-durand-doa-over-dns */ + /** draft-ietf-mboned-driad-amt-discovery **/ + LDNS_RR_TYPE_AMTRELAY = 260, + /** DNSSEC Trust Authorities */ LDNS_RR_TYPE_TA = 32768, /* RFC 4431, 5074, DNSSEC Lookaside Validation */ @@ -238,7 +241,7 @@ enum ldns_enum_rr_type typedef enum ldns_enum_rr_type ldns_rr_type; /* The first fields are contiguous and can be referenced instantly */ -#define LDNS_RDATA_FIELD_DESCRIPTORS_COMMON (LDNS_RR_TYPE_DOA + 1) +#define LDNS_RDATA_FIELD_DESCRIPTORS_COMMON (LDNS_RR_TYPE_AMTRELAY + 1) /** * Resource Record diff --git a/ldns/str2host.h b/ldns/str2host.h index d6399705..e6f70043 100644 --- a/ldns/str2host.h +++ b/ldns/str2host.h @@ -311,6 +311,16 @@ ldns_status ldns_str2rdf_long_str(ldns_rdf **rd, const char *str); */ ldns_status ldns_str2rdf_hip(ldns_rdf **rd, const char *str); +/** + * Concert a" " encoding + * of the value field as specified in Section 4.3.1 of + * [draft-ietf-mboned-driad-amt-discovery], encoded as wireformat as specified in + * ection 4.2 of [draft-ietf-mboned-driad-amt-discovery] + * \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_amtrelay(ldns_rdf **rd, const char *str); #ifdef __cplusplus } diff --git a/rdata.c b/rdata.c index 3bc4b391..caf853d6 100644 --- a/rdata.c +++ b/rdata.c @@ -360,6 +360,9 @@ ldns_rdf_new_frm_str(ldns_rdf_type type, const char *str) case LDNS_RDF_TYPE_MATCHING_TYPE: status = ldns_str2rdf_matching_type(&rdf, str); break; + case LDNS_RDF_TYPE_AMTRELAY: + status = ldns_str2rdf_amtrelay(&rdf, str); + break; case LDNS_RDF_TYPE_NONE: default: /* default default ??? */ diff --git a/rr.c b/rr.c index a6bf8da5..ec73b007 100644 --- a/rr.c +++ b/rr.c @@ -347,6 +347,7 @@ ldns_rr_new_frm_str_internal(ldns_rr **newrr, const char *str, 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_AMTRELAY : case LDNS_RDF_TYPE_NSEC : if (r_cnt == r_max - 1) { delimiters = "\n"; break; @@ -2052,6 +2053,12 @@ static const ldns_rdf_type type_doa_wireformat[] = { LDNS_RDF_TYPE_B64 }; #endif +#ifdef RRTYPE_AMTRELAY +static const ldns_rdf_type type_amtrelay_wireformat[] = { + LDNS_RDF_TYPE_AMTRELAY +}; +#endif + /** \endcond */ @@ -2447,6 +2454,12 @@ static ldns_rr_descriptor rdata_field_descriptors[] = { #else {LDNS_RR_TYPE_NULL, "TYPE259", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, #endif +#ifdef RRTYPE_AMTRELAY + /* 260 */ + {LDNS_RR_TYPE_AMTRELAY, "AMTRELAY", 1, 1, type_amtrelay_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, +#else +{LDNS_RR_TYPE_NULL, "TYPE260", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, +#endif /* split in array, no longer contiguous */ diff --git a/str2host.c b/str2host.c index 8a382e2b..231453ed 100644 --- a/str2host.c +++ b/str2host.c @@ -1657,3 +1657,144 @@ ldns_str2rdf_hip(ldns_rdf **rd, const char *str) } return LDNS_STATUS_OK; } + + +/* Implementation mimics ldns_str2rdf_ipseckey */ +ldns_status +ldns_str2rdf_amtrelay(ldns_rdf **rd, const char *str) +{ + /* From draft-ietf-mboned-driad-amt-discovery + * Section 4.2. AMTRELAY RData 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 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | precedence |D| type | | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + + ~ relay ~ + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ + + uint8_t precedence = 0; + uint8_t relay_type = 0; + uint8_t discovery_optional = 0; + char* relay = NULL; + uint8_t *data; + ldns_buffer *str_buf; + char *token; + int token_count = 0; + int amtrelay_len = 0; + ldns_rdf* relay_rdf = NULL; + ldns_status status = LDNS_STATUS_OK; + + if(strlen(str) == 0) + token = LDNS_XMALLOC(char, 256); + else token = LDNS_XMALLOC(char, strlen(str)+2); + if(!token) return LDNS_STATUS_MEM_ERR; + + str_buf = LDNS_MALLOC(ldns_buffer); + if(!str_buf) {LDNS_FREE(token); return LDNS_STATUS_MEM_ERR;} + ldns_buffer_new_frm_data(str_buf, (char *)str, strlen(str)); + if(ldns_buffer_status(str_buf) != LDNS_STATUS_OK) { + LDNS_FREE(str_buf); + LDNS_FREE(token); + return LDNS_STATUS_MEM_ERR; + } + while(ldns_bget_token(str_buf, token, "\t\n ", strlen(str)) > 0) { + switch (token_count) { + case 0: + precedence = (uint8_t)atoi(token); + break; + case 1: + discovery_optional = (uint8_t)atoi(token); + if (discovery_optional != 0 && + discovery_optional != 1) { + LDNS_FREE(relay); + LDNS_FREE(token); + ldns_buffer_free(str_buf); + return LDNS_STATUS_INVALID_STR; + } + break; + case 2: + relay_type = (uint8_t)atoi(token); + break; + case 3: + relay = strdup(token); + if (!relay || (relay_type == 0 && + (token[0] != '.' || token[1] != '\0'))) { + LDNS_FREE(relay); + LDNS_FREE(token); + ldns_buffer_free(str_buf); + return LDNS_STATUS_INVALID_STR; + } + break; + default: + LDNS_FREE(token); + ldns_buffer_free(str_buf); + return LDNS_STATUS_INVALID_STR; + break; + } + token_count++; + } + if (!relay && relay_type > 0) { + if (relay) + LDNS_FREE(relay); + LDNS_FREE(token); + ldns_buffer_free(str_buf); + return LDNS_STATUS_INVALID_STR; + } + + if (relay_type == 1) { + status = ldns_str2rdf_a(&relay_rdf, relay); + } else if (relay_type == 2) { + status = ldns_str2rdf_aaaa(&relay_rdf, relay); + } else if (relay_type == 3) { + status = ldns_str2rdf_dname(&relay_rdf, relay); + } else if (relay_type > 3) { + status = LDNS_STATUS_INVALID_STR; + } + + if (status != LDNS_STATUS_OK) { + if (relay) + LDNS_FREE(relay); + LDNS_FREE(token); + ldns_buffer_free(str_buf); + return LDNS_STATUS_INVALID_STR; + } + + /* now copy all into one amtrelay rdf */ + if (relay_type) + amtrelay_len = 2 + (int)ldns_rdf_size(relay_rdf); + else + amtrelay_len = 2; + + data = LDNS_XMALLOC(uint8_t, amtrelay_len); + if(!data) { + if (relay) + LDNS_FREE(relay); + LDNS_FREE(token); + ldns_buffer_free(str_buf); + if (relay_rdf) ldns_rdf_free(relay_rdf); + return LDNS_STATUS_MEM_ERR; + } + + data[0] = precedence; + data[1] = relay_type; + data[1] |= (discovery_optional << 7); + + if (relay_type) { + memcpy(data + 2, + ldns_rdf_data(relay_rdf), ldns_rdf_size(relay_rdf)); + } + *rd = ldns_rdf_new_frm_data( LDNS_RDF_TYPE_AMTRELAY + , (uint16_t) amtrelay_len, data); + + if (relay) + LDNS_FREE(relay); + LDNS_FREE(token); + ldns_buffer_free(str_buf); + ldns_rdf_free(relay_rdf); + LDNS_FREE(data); + if(!*rd) return LDNS_STATUS_MEM_ERR; + return LDNS_STATUS_OK; +} diff --git a/wire2host.c b/wire2host.c index a30e89e7..1473a947 100644 --- a/wire2host.c +++ b/wire2host.c @@ -272,6 +272,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_LONG_STR: + case LDNS_RDF_TYPE_AMTRELAY: case LDNS_RDF_TYPE_NONE: /* * Read to end of rr rdata