From: Tom Carpay Date: Mon, 10 May 2021 09:03:08 +0000 (+0200) Subject: basic implementation of a selection of svcb params X-Git-Tag: release-1.13.2rc1~42^2~36 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=5b28b213fafc0cc6ce131495044645d298f01687;p=thirdparty%2Funbound.git basic implementation of a selection of svcb params --- diff --git a/sldns/rrdef.c b/sldns/rrdef.c index 54051313a..125d3d0ab 100644 --- a/sldns/rrdef.c +++ b/sldns/rrdef.c @@ -153,6 +153,9 @@ static const sldns_rdf_type type_csync_wireformat[] = { static const sldns_rdf_type type_zonemd_wireformat[] = { LDNS_RDF_TYPE_INT32, LDNS_RDF_TYPE_INT8, LDNS_RDF_TYPE_INT8, LDNS_RDF_TYPE_HEX }; +static const sldns_rdf_type type_svcb_wireformat[] = { + LDNS_RDF_TYPE_INT16, LDNS_RDF_TYPE_DNAME +}; /* nsec3 is some vars, followed by same type of data of nsec */ static const sldns_rdf_type type_nsec3_wireformat[] = { /* LDNS_RDF_TYPE_NSEC3_VARS, LDNS_RDF_TYPE_NSEC3_NEXT_OWNER, LDNS_RDF_TYPE_NSEC*/ @@ -377,7 +380,8 @@ static sldns_rr_descriptor rdata_field_descriptors[] = { {LDNS_RR_TYPE_CSYNC, "CSYNC", 3, 3, type_csync_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, /* 63 */ {LDNS_RR_TYPE_ZONEMD, "ZONEMD", 4, 4, type_zonemd_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, -{(enum sldns_enum_rr_type)0, "TYPE64", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, + /* 64 */ + {LDNS_RR_TYPE_SVCB, "SVCB", 2, 2, type_svcb_wireformat, LDNS_RDF_TYPE_SVCPARAM, LDNS_RR_NO_COMPRESS, 0 }, {(enum sldns_enum_rr_type)0, "TYPE65", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, {(enum sldns_enum_rr_type)0, "TYPE66", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, {(enum sldns_enum_rr_type)0, "TYPE67", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, diff --git a/sldns/rrdef.h b/sldns/rrdef.h index ece632c3c..cd65c4126 100644 --- a/sldns/rrdef.h +++ b/sldns/rrdef.h @@ -196,6 +196,8 @@ enum sldns_enum_rr_type LDNS_RR_TYPE_OPENPGPKEY = 61, /* RFC 7929 */ LDNS_RR_TYPE_CSYNC = 62, /* RFC 7477 */ LDNS_RR_TYPE_ZONEMD = 63, /* draft-ietf-dnsop-dns-zone-digest-12 */ + LDNS_RR_TYPE_SVCB = 64, /* draft-ietf-dnsop-svcb-https-04 */ + LDNS_RR_TYPE_HTTPS = 65, /* draft-ietf-dnsop-svcb-https-04 */ LDNS_RR_TYPE_SPF = 99, /* RFC 4408 */ @@ -353,8 +355,13 @@ enum sldns_enum_rdf_type /** TSIG extended 16bit error value */ LDNS_RDF_TYPE_TSIGERROR, + /* draft-ietf-dnsop-svcb-https-04: + * each SvcParam consisting of a SvcParamKey=SvcParamValue pair or + * a standalone SvcParamKey */ + LDNS_RDF_TYPE_SVCPARAM, + /* Aliases */ - LDNS_RDF_TYPE_BITMAP = LDNS_RDF_TYPE_NSEC + LDNS_RDF_TYPE_BITMAP = LDNS_RDF_TYPE_NSEC, }; typedef enum sldns_enum_rdf_type sldns_rdf_type; diff --git a/sldns/str2wire.c b/sldns/str2wire.c index 70eec6dab..8a3a1e22a 100644 --- a/sldns/str2wire.c +++ b/sldns/str2wire.c @@ -29,7 +29,6 @@ #define RET_ERR(e, off) ((int)((e)|((off)<= 4 && key_len <= 8 && !strncmp(key, "key", 3)) { + memcpy(buf, key + 3, key_len - 3); + buf[key_len - 3] = 0; + key_value = strtoul(buf, &endptr, 10); + if (endptr > buf /* digits seen */ + && *endptr == 0 /* no non-digit chars after digits */ + && key_value <= 65535) /* no overflow */ + return key_value; + + } else switch (key_len) { + case sizeof("mandatory")-1: + if (!strncmp(key, "mandatory", sizeof("mandatory")-1)) + return SVCB_KEY_MANDATORY; + if (!strncmp(key, "echconfig", sizeof("echconfig")-1)) + return SVCB_KEY_ECH; /* allow "echconfig as well as "ech" */ + break; + + case sizeof("alpn")-1: + if (!strncmp(key, "alpn", sizeof("alpn")-1)) + return SVCB_KEY_ALPN; + if (!strncmp(key, "port", sizeof("port")-1)) + return SVCB_KEY_PORT; + break; + + case sizeof("no-default-alpn")-1: + if (!strncmp( key , "no-default-alpn" + , sizeof("no-default-alpn")-1)) + return SVCB_KEY_NO_DEFAULT_ALPN; + break; + + case sizeof("ipv4hint")-1: + if (!strncmp(key, "ipv4hint", sizeof("ipv4hint")-1)) + return SVCB_KEY_IPV4HINT; + if (!strncmp(key, "ipv6hint", sizeof("ipv6hint")-1)) + return SVCB_KEY_IPV6HINT; + break; + case sizeof("ech")-1: + if (!strncmp(key, "ech", sizeof("ech")-1)) + return SVCB_KEY_ECH; + break; + default: + break; + } + if (key_len > sizeof(buf) - 1) {} + // ERROR: Unknown SvcParamKey + else { + memcpy(buf, key, key_len); + buf[key_len] = 0; + // Error: "Unknown SvcParamKey: %s" + } + /* Although the returned value might be used by the caller, + * the parser has erred, so the zone will not be loaded. + */ + return -1; +} + +static int +sldns_str2wire_svcparam_port(const char* val, uint8_t* rd, size_t* rd_len) +{ + unsigned long int port; + char *endptr; + + if (*rd_len < 6) + return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; + + port = strtoul(val, &endptr, 10); + + if (endptr > val /* digits seen */ + && *endptr == 0 /* no non-digit chars after digits */ + && port <= 65535) { /* no overflow */ + + sldns_write_uint16(rd, htons(SVCB_KEY_PORT)); + sldns_write_uint16(rd + 2, htons(sizeof(uint16_t))); + sldns_write_uint16(rd + 4, htons(port)); + *rd_len = 6; + + return LDNS_WIREPARSE_ERR_OK; + } + // ERROR: "Could not parse port SvcParamValue" + return -1; +} + +static int +sldns_str2wire_svcbparam_ipv4hint(const char* val, uint8_t* rd, size_t* rd_len) +{ + + int count; + char ip_str[INET_ADDRSTRLEN+1]; + char *next_ip_str; + uint32_t *ip_wire_dst; + size_t i; + + for (i = 0, count = 1; val[i]; i++) { + if (val[i] == ',') + count += 1; + if (count > SVCB_MAX_COMMA_SEPARATED_VALUES) { + // ERROR "Too many IPV4 addresses in ipv4hint" + return -1; + } + } + + if (*rd_len < (LDNS_IP4ADDRLEN * count) + 4) + return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; + + /* count is number of comma's in val + 1; so the actual number of IPv4 + * addresses in val + */ + sldns_write_uint16(rd, htons(SVCB_KEY_IPV4HINT)); + sldns_write_uint16(rd + 2, htons(LDNS_IP4ADDRLEN * count)); + *rd_len = 4; + + while (count) { + if (!(next_ip_str = strchr(val, ','))) { + if (inet_pton(AF_INET, val, rd + *rd_len) != 1) + *rd_len += LDNS_IP4ADDRLEN; + break; + + assert(count == 1); + + } else if (next_ip_str - val >= (int)sizeof(ip_str)) + break; + + else { + memcpy(ip_str, val, next_ip_str - val); + ip_str[next_ip_str - val] = 0; + if (inet_pton(AF_INET, ip_str, rd + *rd_len) != 1) { + *rd_len += LDNS_IP4ADDRLEN; + val = ip_str; /* to use in error reporting below */ + break; + } + + val = next_ip_str + 1; + } + ip_wire_dst++; + count--; + } + // if (count) /* verify that we parsed all values */ + // ERROR "Could not parse ipv4hint SvcParamValue: " + + return LDNS_WIREPARSE_ERR_OK; +} + +static int +sldns_str2wire_svcbparam_ipv6hint(const char* val, uint8_t* rd, size_t* rd_len) +{ + int count; + char ip_str[INET_ADDRSTRLEN+1]; + char *next_ip_str; + uint32_t *ip_wire_dst; + size_t i; + + for (i = 0, count = 1; val[i]; i++) { + if (val[i] == ',') + count += 1; + if (count > SVCB_MAX_COMMA_SEPARATED_VALUES) { + // ERROR "Too many IPV4 addresses in ipv4hint" + return -1; + } + } + + if (*rd_len < (LDNS_IP6ADDRLEN * count) + 4) + return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; + + /* count is number of comma's in val + 1; so the actual number of IPv6 + * addresses in val + */ + sldns_write_uint16(rd, htons(SVCB_KEY_IPV6HINT)); + sldns_write_uint16(rd + 2, htons(LDNS_IP6ADDRLEN * count)); + *rd_len = 4; + + while (count) { + if (!(next_ip_str = strchr(val, ','))) { + if (inet_pton(AF_INET, val, rd + *rd_len) != 1) + *rd_len += LDNS_IP6ADDRLEN; + break; + + assert(count == 1); + + } else if (next_ip_str - val >= (int)sizeof(ip_str)) + break; + + else { + memcpy(ip_str, val, next_ip_str - val); + ip_str[next_ip_str - val] = 0; + if (inet_pton(AF_INET, ip_str, rd + *rd_len) != 1) { + *rd_len += LDNS_IP6ADDRLEN; + + val = ip_str; /* to use in error reporting below */ + break; + } + + val = next_ip_str + 1; + } + ip_wire_dst++; + count--; + } + // if (count) /* verify that we parsed all values */ + // ERROR "Could not parse ipv6hint SvcParamValue: " + + return LDNS_WIREPARSE_ERR_OK; +} + +/* compare function used for sorting uint16_t's */ +static int +sldns_network_uint16_cmp(const void *a, const void *b) +{ + return ((int)sldns_read_uint16(a)) - ((int)sldns_read_uint16(b)); +} + +static int +sldns_str2wire_svcbparam_mandatory(const char* val, uint8_t* rd, size_t* rd_len) +{ + size_t i, count, val_len; + char* next_key; + uint16_t* key_dst; + + val_len = strlen(val); + + for (i = 0, count = 1; val[i]; i++) { + if (val[i] == ',') + count += 1; + if (count > SVCB_MAX_COMMA_SEPARATED_VALUES) { + // ERROR "Too many keys in mandatory" + return -1; + } + } + + // @TODO check if we have space to write in rd_len; look for the best spot + + sldns_write_uint16(rd, htons(SVCB_KEY_MANDATORY)); + sldns_write_uint16(rd + 2, htons(sizeof(uint16_t) * count)); + *rd_len = 4; + + for(;;) { + if (!(next_key = strchr(val, ','))) { + sldns_write_uint16(rd + *rd_len, + htons(sldns_str2wire_svcparam_key_lookup(val, val_len))); + *rd_len += LDNS_IP6ADDRLEN; + break; + } else { + sldns_write_uint16(rd + *rd_len, + htons(sldns_str2wire_svcparam_key_lookup(val, next_key - val))); + *rd_len += LDNS_IP6ADDRLEN; + } + + val_len -= next_key - val + 1; + val = next_key + 1; /* skip the comma */ + key_dst += 1; + } + + /* In draft-ietf-dnsop-svcb-https-04 Section 7: + * + * "In wire format, the keys are represented by their numeric + * values in network byte order, concatenated in ascending order." + */ + qsort((void *)(rd + 4), count, sizeof(uint16_t), sldns_network_uint16_cmp); + + return LDNS_WIREPARSE_ERR_OK; +} + +static int +sldns_str2wire_svcbparam_no_default_alpn(const char* val, uint8_t* rd, size_t* rd_len) +{ + if (*rd_len < 4) + return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; + + sldns_write_uint16(rd, htons(SVCB_KEY_NO_DEFAULT_ALPN)); + sldns_write_uint16(rd + 2, htons(0)); + *rd_len = 4; + + return LDNS_WIREPARSE_ERR_OK; +} + +static int +sldns_str2wire_svcbparam_ech_value(const char* val, uint8_t* rd, size_t* rd_len) +{ + uint8_t buffer[LDNS_MAX_RDFLEN]; + int wire_len; + + // @TODO fix this + // if(strcmp(b64, "0") == 0) { + /* single 0 represents empty buffer */ + // } + + wire_len = sldns_b64_pton(val, buffer, LDNS_MAX_RDFLEN); + + if (wire_len == -1) { + // zc_error_prev_line("invalid base64 data in ech"); + return LDNS_WIREPARSE_ERR_INVALID_STR; + } else { + sldns_write_uint16(rd, htons(SVCB_KEY_ECH)); + sldns_write_uint16(rd + 2, htons(wire_len)); + + // @TODO memcpy? + sldns_write_uint16(rd + 4, htons(buffer)); + *rd_len = 4 + wire_len; + + return LDNS_WIREPARSE_ERR_OK; + } +} + +static int +sldns_str2wire_svcparam_key_value(const char *key, size_t key_len, + const char *val, uint8_t* rd, size_t* rd_len) +{ + uint16_t svcparamkey = sldns_str2wire_svcparam_key_lookup(key, key_len); + + switch (svcparamkey) { + case SVCB_KEY_PORT: + return sldns_str2wire_svcparam_port(val, rd, rd_len); + case SVCB_KEY_IPV4HINT: + return sldns_str2wire_svcbparam_ipv4hint(val, rd, rd_len); + case SVCB_KEY_IPV6HINT: + return sldns_str2wire_svcbparam_ipv6hint(val, rd, rd_len); + case SVCB_KEY_MANDATORY: + return sldns_str2wire_svcbparam_mandatory(val, rd, rd_len); + case SVCB_KEY_NO_DEFAULT_ALPN: + return sldns_str2wire_svcbparam_no_default_alpn(val, rd, rd_len); + // if(zone_is_slave(parser->current_zone->opts)) + // zc_warning_prev_line("no-default-alpn should not have a value"); + // else + // zc_error_prev_line("no-default-alpn should not have a value"); + // break; + case SVCB_KEY_ECH: + return sldns_str2wire_svcbparam_ech_value(val, rd, rd_len); + case SVCB_KEY_ALPN: + // return sldns_str2wire_svcbparam_alpn_value(val, rd, rd_len); + default: + break; + } + + // @TODO change to error? + return LDNS_WIREPARSE_ERR_OK; +} + +int sldns_str2wire_svcparam_buf(const char* str, uint8_t* rd, size_t* rd_len) +{ + const char* eq_pos; + + int ret; + + eq_pos = strchr(str, '='); + + // @TODO handle "key=" case + + /* Verify that we have a have a value */ + if (eq_pos != NULL) { + return sldns_str2wire_svcparam_key_value(str, eq_pos - str, eq_pos + 1, rd, rd_len); + } else { + return sldns_str2wire_svcparam_key_value(str, strlen(str), NULL, rd, rd_len); + } + + return LDNS_WIREPARSE_ERR_OK; +} + int sldns_str2wire_rdf_buf(const char* str, uint8_t* rd, size_t* len, sldns_rdf_type rdftype) { @@ -1006,6 +1367,8 @@ int sldns_str2wire_rdf_buf(const char* str, uint8_t* rd, size_t* len, 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_SVCPARAM: + return sldns_str2wire_svcparam_buf(str, rd, len); case LDNS_RDF_TYPE_UNKNOWN: case LDNS_RDF_TYPE_SERVICE: return LDNS_WIREPARSE_ERR_NOT_IMPL; diff --git a/sldns/str2wire.h b/sldns/str2wire.h index 70070e4f5..b687546a7 100644 --- a/sldns/str2wire.h +++ b/sldns/str2wire.h @@ -23,10 +23,25 @@ extern "C" { #endif struct sldns_struct_lookup_table; +#define LDNS_IP4ADDRLEN (32/8) +#define LDNS_IP6ADDRLEN (128/8) + /** buffer to read an RR, cannot be larger than 64K because of packet size */ #define LDNS_RR_BUF_SIZE 65535 /* bytes */ #define LDNS_DEFAULT_TTL 3600 +/* SVCB keys currently defined in draft-ietf-dnsop-svcb-https */ +#define SVCB_KEY_MANDATORY 0 +#define SVCB_KEY_ALPN 1 +#define SVCB_KEY_NO_DEFAULT_ALPN 2 +#define SVCB_KEY_PORT 3 +#define SVCB_KEY_IPV4HINT 4 +#define SVCB_KEY_ECH 5 +#define SVCB_KEY_IPV6HINT 6 +#define SVCPARAMKEY_COUNT 7 + +#define SVCB_MAX_COMMA_SEPARATED_VALUES 1000 + /* * To convert class and type to string see * sldns_get_rr_class_by_name(str) diff --git a/sldns/wire2str.c b/sldns/wire2str.c index d0d1632d4..3fea10fcd 100644 --- a/sldns/wire2str.c +++ b/sldns/wire2str.c @@ -196,6 +196,12 @@ static sldns_lookup_table sldns_tsig_errors_data[] = { }; sldns_lookup_table* sldns_tsig_errors = sldns_tsig_errors_data; +/* draft-ietf-dnsop-svcb-https-04: 6. Initial SvcParamKeys */ +const char *svcparamkey_strs[] = { + "mandatory", "alpn", "no-default-alpn", "port", + "ipv4hint", "echconfig", "ipv6hint" +}; + char* sldns_wire2str_pkt(uint8_t* data, size_t len) { size_t slen = (size_t)sldns_wire2str_pkt_buf(data, len, NULL, 0); @@ -940,6 +946,179 @@ int sldns_wire2str_ttl_scan(uint8_t** d, size_t* dlen, char** s, size_t* slen) return sldns_str_print(s, slen, "%u", (unsigned)ttl); } +static int +sldns_print_svcparamkey(char** s, size_t* slen, uint16_t svcparamkey) +{ + if (svcparamkey < SVCPARAMKEY_COUNT) { + // fprintf(stderr, "HERE\n"); + return sldns_str_print(s, slen, "%s", svcparamkey_strs[svcparamkey]); + } + else { + return sldns_str_print(s, slen, "key%d", (int)svcparamkey); + } +} + +int sldns_wire2str_svcparam_port2str(char** s, + size_t* slen, uint16_t val_len, uint16_t val) +{ + int w = 0; + + if (val_len != 2) + return -1; /* wireformat error, a short is 2 bytes */ + w = sldns_str_print(s, slen, "=%d", (int)ntohs(val)); + return w; +} + +static int +sldns_wire2str_svcparam_ipv4hint2str(char** s, + size_t* slen, uint16_t val_len, uint8_t* data) +{ + char ip_str[INET_ADDRSTRLEN + 1]; + + // @TODO actually incorporate this + int w = 0; + + assert(val_len > 0); + + if ((val_len % LDNS_IP4ADDRLEN) == 0) { + if (inet_ntop(AF_INET, data, ip_str, sizeof(ip_str)) == NULL) + return 0; /* wireformat error, incorrect size or inet family */ + + sldns_str_print(s, slen, "=%s", ip_str); + data += LDNS_IP4ADDRLEN / sizeof(uint16_t); + + while ((val_len -= LDNS_IP4ADDRLEN) > 0) { + if (inet_ntop(AF_INET, data, ip_str, sizeof(ip_str)) == NULL) + return 0; /* wireformat error, incorrect size or inet family */ + + sldns_str_print(s, slen, ",%s", ip_str); + data += LDNS_IP4ADDRLEN / sizeof(uint16_t); + } + return 1; + } else + return 0; +} + +int sldns_wire2str_svcparam_ipv6hint2str(char** s, + size_t* slen, uint16_t val_len, uint8_t* data) +{ + char ip_str[INET6_ADDRSTRLEN + 1]; + + // @TODO actually incorporate this + int w = 0; + + assert(val_len > 0); + + if ((val_len % LDNS_IP6ADDRLEN) == 0) { + if (inet_ntop(AF_INET6, data, ip_str, sizeof(ip_str)) == NULL) + return 0; /* wireformat error, incorrect size or inet family */ + + sldns_str_print(s, slen, "=%s", ip_str); + data += LDNS_IP6ADDRLEN / sizeof(uint16_t); + + while ((val_len -= LDNS_IP6ADDRLEN) > 0) { + if (inet_ntop(AF_INET6, data, ip_str, sizeof(ip_str)) == NULL) + return 0; /* wireformat error, incorrect size or inet family */ + + sldns_str_print(s, slen, ",%s", ip_str); + data += LDNS_IP6ADDRLEN / sizeof(uint16_t); + } + return 1; + } else + return 0; +} + +int sldns_wire2str_svcparam_mandatory2str(char** s, + size_t* slen, uint16_t val_len, uint8_t* data) +{ + int w = 0; + + assert(val_len > 0); + + // if (val_len % sizeof(uint16_t)) + // return 0; // wireformat error, val_len must be multiple of shorts + w += sldns_str_print(s, slen, "="); + w += sldns_print_svcparamkey(s, slen, ntohs(sldns_read_uint16(data))); + data += 2; + + while ((val_len -= sizeof(uint16_t))) { + w += sldns_str_print(s, slen, ","); + w += sldns_print_svcparamkey(s, slen, ntohs(sldns_read_uint16(data))); + data += 2; + } + + return w; +} + +int sldns_wire2str_svcparam_scan(uint8_t** d, size_t* dlen, char** s, size_t* slen) +{ + uint16_t svcparamkey, val_len; + uint8_t* data = *d; + int written_chars = 0; + + if(*dlen == 0) return 0; /* verify that we actualy have data */ + + svcparamkey = ntohs(sldns_read_uint16(data)); + + written_chars += sldns_print_svcparamkey(s, slen, svcparamkey); + + // (*dlen) -= written_chars; + + // @TODO fix this to be dynamic and correct + // fprintf(stderr, "*dlen2: %zu\n", *dlen); + // fprintf(stderr, "val_len %zu\n", val_len); + (*dlen) = 0; + + val_len = ntohs(sldns_read_uint16(data+2)); + + // if (size != val_len + 4) + // return 0; wireformat error + + // if (!val_len) { + // /* Some SvcParams MUST have values */ + // switch (svcparamkey) { + // case SVCB_KEY_ALPN: + // case SVCB_KEY_PORT: + // case SVCB_KEY_IPV4HINT: + // case SVCB_KEY_IPV6HINT: + // case SVCB_KEY_MANDATORY: + // return 0; + // default: + // return 1; + // } + // } + switch (svcparamkey) { + case SVCB_KEY_PORT: + written_chars += sldns_wire2str_svcparam_port2str(s, slen, val_len, sldns_read_uint16(data+4)); + break; + case SVCB_KEY_IPV4HINT: + written_chars += sldns_wire2str_svcparam_ipv4hint2str(s, slen, val_len, data+4); + break; + case SVCB_KEY_IPV6HINT: + written_chars += sldns_wire2str_svcparam_ipv6hint2str(s, slen, val_len, data+4); + break; + case SVCB_KEY_MANDATORY: + written_chars += sldns_wire2str_svcparam_mandatory2str(s, slen, val_len, data+4); + break; + case SVCB_KEY_NO_DEFAULT_ALPN: + return 0; /* wireformat error, should not have a value */ + case SVCB_KEY_ALPN: + // written_chars += sldns_wire2str_svcparam_alpn2str(output, val_len, data+2); + // break; + case SVCB_KEY_ECH: + // written_chars += sldns_wire2str_svcparam_ech2str(output, val_len, data+2); + // break; + default: + break; + } + + // @TODO set str_len to 0: "If the end of the + // * output string is reached, *str_len is set to 0" + // *str_len = 0; + + return written_chars; +} + int sldns_wire2str_rdf_scan(uint8_t** d, size_t* dlen, char** s, size_t* slen, int rdftype, uint8_t* pkt, size_t pktlen, int* comprloop) { @@ -1017,6 +1196,8 @@ int sldns_wire2str_rdf_scan(uint8_t** d, size_t* dlen, char** s, size_t* slen, return sldns_wire2str_tag_scan(d, dlen, s, slen); case LDNS_RDF_TYPE_LONG_STR: return sldns_wire2str_long_str_scan(d, dlen, s, slen); + case LDNS_RDF_TYPE_SVCPARAM: + return sldns_wire2str_svcparam_scan(d, dlen, s, slen); case LDNS_RDF_TYPE_TSIGERROR: return sldns_wire2str_tsigerror_scan(d, dlen, s, slen); } diff --git a/sldns/wire2str.h b/sldns/wire2str.h index 0167fe7c1..3c777367c 100644 --- a/sldns/wire2str.h +++ b/sldns/wire2str.h @@ -41,6 +41,9 @@ extern struct sldns_struct_lookup_table* sldns_wireparse_errors; /** tsig errors are the rcodes with extra (higher) values */ extern struct sldns_struct_lookup_table* sldns_tsig_errors; +/* draft-ietf-dnsop-svcb-https-04: 6. Initial SvcParamKeys */ +extern const char *svcparamkey_strs[]; + /** * Convert wireformat packet to a string representation * @param data: wireformat packet data (starting at ID bytes).