aboutsummaryrefslogtreecommitdiff
path: root/contrib/unbound/sldns
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/unbound/sldns')
-rw-r--r--contrib/unbound/sldns/keyraw.c6
-rw-r--r--contrib/unbound/sldns/parse.c55
-rw-r--r--contrib/unbound/sldns/parse.h6
-rw-r--r--contrib/unbound/sldns/parseutil.c45
-rw-r--r--contrib/unbound/sldns/parseutil.h4
-rw-r--r--contrib/unbound/sldns/pkthdr.h4
-rw-r--r--contrib/unbound/sldns/rrdef.c26
-rw-r--r--contrib/unbound/sldns/rrdef.h54
-rw-r--r--contrib/unbound/sldns/str2wire.c207
-rw-r--r--contrib/unbound/sldns/str2wire.h13
-rw-r--r--contrib/unbound/sldns/wire2str.c160
-rw-r--r--contrib/unbound/sldns/wire2str.h28
12 files changed, 512 insertions, 96 deletions
diff --git a/contrib/unbound/sldns/keyraw.c b/contrib/unbound/sldns/keyraw.c
index befe1f722424..42a9262a30da 100644
--- a/contrib/unbound/sldns/keyraw.c
+++ b/contrib/unbound/sldns/keyraw.c
@@ -124,7 +124,7 @@ uint16_t sldns_calc_keytag_raw(uint8_t* key, size_t keysize)
size_t i;
uint32_t ac32 = 0;
for (i = 0; i < keysize; ++i) {
- ac32 += (i & 1) ? key[i] : key[i] << 8;
+ ac32 += ((i & 1)) ? key[i] : key[i] << 8;
}
ac32 += (ac32 >> 16) & 0xFFFF;
return (uint16_t) (ac32 & 0xFFFF);
@@ -195,6 +195,7 @@ void sldns_key_EVP_unload_gost(void)
}
#endif /* USE_GOST */
+#ifdef USE_DSA
/* Retrieve params as BIGNUM from raw buffer */
static int
sldns_key_dsa_buf_bignum(unsigned char* key, size_t len, BIGNUM** p,
@@ -271,7 +272,7 @@ sldns_key_buf2dsa_raw(unsigned char* key, size_t len)
return NULL;
}
if (!DSA_set0_key(dsa, Y, NULL)) {
- /* QPG attached, cleaned up by DSA_fre() */
+ /* QPG attached, cleaned up by DSA_free() */
DSA_free(dsa);
BN_free(Y);
return NULL;
@@ -370,6 +371,7 @@ EVP_PKEY *sldns_key_dsa2pkey_raw(unsigned char* key, size_t len)
return evp_key;
#endif
}
+#endif /* USE_DSA */
/* Retrieve params as BIGNUM from raw buffer, n is modulus, e is exponent */
static int
diff --git a/contrib/unbound/sldns/parse.c b/contrib/unbound/sldns/parse.c
index 491c8f51bf10..8ea084661db6 100644
--- a/contrib/unbound/sldns/parse.c
+++ b/contrib/unbound/sldns/parse.c
@@ -34,7 +34,7 @@ sldns_fget_token_l(FILE *f, char *token, const char *delim, size_t limit, int *l
{
int c, prev_c;
int p; /* 0 -> no parentheses seen, >0 nr of ( seen */
- int com, quoted;
+ int com, quoted, only_blank;
char *t;
size_t i;
const char *d;
@@ -53,6 +53,7 @@ sldns_fget_token_l(FILE *f, char *token, const char *delim, size_t limit, int *l
com = 0;
quoted = 0;
prev_c = 0;
+ only_blank = 1; /* Assume we got only <blank> until now */
t = token;
if (del[0] == '"') {
quoted = 1;
@@ -101,6 +102,22 @@ sldns_fget_token_l(FILE *f, char *token, const char *delim, size_t limit, int *l
if (line_nr) {
*line_nr = *line_nr + 1;
}
+ if (only_blank && i > 0) {
+ /* Got only <blank> so far. Reset and try
+ * again with the next line.
+ */
+ i = 0;
+ t = token;
+ }
+ if (p == 0) {
+ /* If p != 0 then the next line is a continuation. So
+ * we assume that the next line starts with a blank only
+ * if it is actually a new line.
+ */
+ only_blank = 1; /* Assume next line starts with
+ * <blank>.
+ */
+ }
if (p == 0 && i > 0) {
goto tokenread;
} else {
@@ -131,12 +148,29 @@ sldns_fget_token_l(FILE *f, char *token, const char *delim, size_t limit, int *l
/* check if we hit the delim */
for (d = del; *d; d++) {
- if (c == *d && i > 0 && prev_c != '\\' && p == 0) {
- if (c == '\n' && line_nr) {
- *line_nr = *line_nr + 1;
- }
- goto tokenread;
+ if (c == *d)
+ break;
+ }
+
+ if (c == *d && i > 0 && prev_c != '\\' && p == 0) {
+ if (c == '\n' && line_nr) {
+ *line_nr = *line_nr + 1;
}
+ if (only_blank) {
+ /* Got only <blank> so far. Reset and
+ * try again with the next line.
+ */
+ i = 0;
+ t = token;
+ only_blank = 1;
+ prev_c = c;
+ continue;
+ }
+ goto tokenread;
+ }
+ if (c != ' ' && c != '\t') {
+ /* Found something that is not <blank> */
+ only_blank= 0;
}
if (c != '\0' && c != '\n') {
i++;
@@ -149,8 +183,13 @@ sldns_fget_token_l(FILE *f, char *token, const char *delim, size_t limit, int *l
if (c != '\0' && c != '\n') {
*t++ = c;
}
- if (c == '\n' && line_nr) {
- *line_nr = *line_nr + 1;
+ if (c == '\n') {
+ if (line_nr) {
+ *line_nr = *line_nr + 1;
+ }
+ only_blank = 1; /* Assume next line starts with
+ * <blank>.
+ */
}
if (c == '\\' && prev_c == '\\')
prev_c = 0;
diff --git a/contrib/unbound/sldns/parse.h b/contrib/unbound/sldns/parse.h
index fa8f51a924c4..504a78b676e2 100644
--- a/contrib/unbound/sldns/parse.h
+++ b/contrib/unbound/sldns/parse.h
@@ -106,7 +106,7 @@ ssize_t sldns_bget_token(struct sldns_buffer *b, char *token, const char *delim,
* \param[in] k_del keyword delimiter
* \param[out] data the data found
* \param[in] d_del the data delimiter
- * \param[in] data_limit maximum size the the data buffer
+ * \param[in] data_limit maximum size the data buffer
* \return the number of character read
*/
ssize_t sldns_fget_keyword_data(FILE *f, const char *keyword, const char *k_del, char *data, const char *d_del, size_t data_limit);
@@ -119,7 +119,7 @@ ssize_t sldns_fget_keyword_data(FILE *f, const char *keyword, const char *k_del,
* \param[in] k_del keyword delimiter
* \param[out] data the data found
* \param[in] d_del the data delimiter
- * \param[in] data_limit maximum size the the data buffer
+ * \param[in] data_limit maximum size the data buffer
* \param[in] line_nr pointer to an integer containing the current line number (for
debugging purposes)
* \return the number of character read
@@ -134,7 +134,7 @@ ssize_t sldns_fget_keyword_data_l(FILE *f, const char *keyword, const char *k_de
* \param[in] k_del keyword delimiter
* \param[out] data the data found
* \param[in] d_del the data delimiter
- * \param[in] data_limit maximum size the the data buffer
+ * \param[in] data_limit maximum size the data buffer
* \return the number of character read
*/
ssize_t sldns_bget_keyword_data(struct sldns_buffer *b, const char *keyword, const char *k_del, char *data, const char *d_del, size_t data_limit);
diff --git a/contrib/unbound/sldns/parseutil.c b/contrib/unbound/sldns/parseutil.c
index ba71df55d501..f696c6af1331 100644
--- a/contrib/unbound/sldns/parseutil.c
+++ b/contrib/unbound/sldns/parseutil.c
@@ -209,11 +209,13 @@ sldns_hexdigit_to_int(char ch)
}
uint32_t
-sldns_str2period(const char *nptr, const char **endptr)
+sldns_str2period(const char *nptr, const char **endptr, int* overflow)
{
int sign = 0;
uint32_t i = 0;
uint32_t seconds = 0;
+ const uint32_t maxint = 0xffffffff;
+ *overflow = 0;
for(*endptr = nptr; **endptr; (*endptr)++) {
switch (**endptr) {
@@ -236,26 +238,46 @@ sldns_str2period(const char *nptr, const char **endptr)
break;
case 's':
case 'S':
+ if(seconds > maxint-i) {
+ *overflow = 1;
+ return 0;
+ }
seconds += i;
i = 0;
break;
case 'm':
case 'M':
+ if(i > maxint/60 || seconds > maxint-(i*60)) {
+ *overflow = 1;
+ return 0;
+ }
seconds += i * 60;
i = 0;
break;
case 'h':
case 'H':
+ if(i > maxint/(60*60) || seconds > maxint-(i*60*60)) {
+ *overflow = 1;
+ return 0;
+ }
seconds += i * 60 * 60;
i = 0;
break;
case 'd':
case 'D':
+ if(i > maxint/(60*60*24) || seconds > maxint-(i*60*60*24)) {
+ *overflow = 1;
+ return 0;
+ }
seconds += i * 60 * 60 * 24;
i = 0;
break;
case 'w':
case 'W':
+ if(i > maxint/(60*60*24*7) || seconds > maxint-(i*60*60*24*7)) {
+ *overflow = 1;
+ return 0;
+ }
seconds += i * 60 * 60 * 24 * 7;
i = 0;
break;
@@ -269,15 +291,27 @@ sldns_str2period(const char *nptr, const char **endptr)
case '7':
case '8':
case '9':
+ if(i > maxint/10 || i*10 > maxint - (**endptr - '0')) {
+ *overflow = 1;
+ return 0;
+ }
i *= 10;
i += (**endptr - '0');
break;
default:
+ if(seconds > maxint-i) {
+ *overflow = 1;
+ return 0;
+ }
seconds += i;
/* disregard signedness */
return seconds;
}
}
+ if(seconds > maxint-i) {
+ *overflow = 1;
+ return 0;
+ }
seconds += i;
/* disregard signedness */
return seconds;
@@ -402,11 +436,13 @@ sldns_b32_ntop_base(const uint8_t* src, size_t src_sz, char* dst, size_t dst_sz,
/* ........ ........ ....4444 4....... ........ */
c = src[3] >> 7 ;
+ ATTR_FALLTHROUGH
/* fallthrough */
case 3: dst[4] = b32[(src[2] & 0x0f) << 1 | c];
/* ........ .......3 3333.... ........ ........ */
c = src[2] >> 4 ;
+ ATTR_FALLTHROUGH
/* fallthrough */
case 2: dst[3] = b32[(src[1] & 0x01) << 4 | c];
@@ -415,6 +451,7 @@ sldns_b32_ntop_base(const uint8_t* src, size_t src_sz, char* dst, size_t dst_sz,
/* .....111 11...... ........ ........ ........ */
c = src[1] >> 6 ;
+ ATTR_FALLTHROUGH
/* fallthrough */
case 1: dst[1] = b32[(src[0] & 0x07) << 2 | c];
@@ -426,11 +463,14 @@ sldns_b32_ntop_base(const uint8_t* src, size_t src_sz, char* dst, size_t dst_sz,
switch (src_sz) {
case 1: dst[2] = '=';
dst[3] = '=';
+ ATTR_FALLTHROUGH
/* fallthrough */
case 2: dst[4] = '=';
+ ATTR_FALLTHROUGH
/* fallthrough */
case 3: dst[5] = '=';
dst[6] = '=';
+ ATTR_FALLTHROUGH
/* fallthrough */
case 4: dst[7] = '=';
}
@@ -543,17 +583,20 @@ sldns_b32_pton_base(const char* src, size_t src_sz, uint8_t* dst, size_t dst_sz,
/* ........ ........ ........ .55555.. ........ */
/* ........ ........ ....4444 4....... ........ */
dst[3] = buf[4] << 7 | buf[5] << 2 | buf[6] >> 3;
+ ATTR_FALLTHROUGH
/* fallthrough */
case 5: /* ........ ........ ....4444 4....... ........ */
/* ........ .......3 3333.... ........ ........ */
dst[2] = buf[3] << 4 | buf[4] >> 1;
+ ATTR_FALLTHROUGH
/* fallthrough */
case 4: /* ........ .......3 3333.... ........ ........ */
/* ........ ..22222. ........ ........ ........ */
/* .....111 11...... ........ ........ ........ */
dst[1] = buf[1] << 6 | buf[2] << 1 | buf[3] >> 4;
+ ATTR_FALLTHROUGH
/* fallthrough */
case 2: /* .....111 11...... ........ ........ ........ */
diff --git a/contrib/unbound/sldns/parseutil.h b/contrib/unbound/sldns/parseutil.h
index 208fd2fbca8b..683f34e23070 100644
--- a/contrib/unbound/sldns/parseutil.h
+++ b/contrib/unbound/sldns/parseutil.h
@@ -74,9 +74,11 @@ struct tm * sldns_serial_arithmetics_gmtime_r(int32_t time, time_t now, struct t
* converts a ttl value (like 5d2h) to a long.
* \param[in] nptr the start of the string
* \param[out] endptr points to the last char in case of error
+ * \param[out] overflow returns if the string causes integer overflow error,
+ * the number is too big, string of digits too long.
* \return the convert duration value
*/
-uint32_t sldns_str2period(const char *nptr, const char **endptr);
+uint32_t sldns_str2period(const char *nptr, const char **endptr, int* overflow);
/**
* Returns the int value of the given (hex) digit
diff --git a/contrib/unbound/sldns/pkthdr.h b/contrib/unbound/sldns/pkthdr.h
index de9952ea71f8..c32e7d285567 100644
--- a/contrib/unbound/sldns/pkthdr.h
+++ b/contrib/unbound/sldns/pkthdr.h
@@ -97,18 +97,22 @@ extern "C" {
#define QDCOUNT(wirebuf) (ntohs(*(uint16_t *)(wirebuf+QDCOUNT_OFF)))
*/
#define LDNS_QDCOUNT(wirebuf) (sldns_read_uint16(wirebuf+LDNS_QDCOUNT_OFF))
+#define LDNS_QDCOUNT_SET(wirebuf, i) (sldns_write_uint16(wirebuf+LDNS_QDCOUNT_OFF, i))
/* Counter of the answer section */
#define LDNS_ANCOUNT_OFF 6
#define LDNS_ANCOUNT(wirebuf) (sldns_read_uint16(wirebuf+LDNS_ANCOUNT_OFF))
+#define LDNS_ANCOUNT_SET(wirebuf, i) (sldns_write_uint16(wirebuf+LDNS_ANCOUNT_OFF, i))
/* Counter of the authority section */
#define LDNS_NSCOUNT_OFF 8
#define LDNS_NSCOUNT(wirebuf) (sldns_read_uint16(wirebuf+LDNS_NSCOUNT_OFF))
+#define LDNS_NSCOUNT_SET(wirebuf, i) (sldns_write_uint16(wirebuf+LDNS_NSCOUNT_OFF, i))
/* Counter of the additional section */
#define LDNS_ARCOUNT_OFF 10
#define LDNS_ARCOUNT(wirebuf) (sldns_read_uint16(wirebuf+LDNS_ARCOUNT_OFF))
+#define LDNS_ARCOUNT_SET(wirebuf, i) (sldns_write_uint16(wirebuf+LDNS_ARCOUNT_OFF, i))
/**
* The sections of a packet
diff --git a/contrib/unbound/sldns/rrdef.c b/contrib/unbound/sldns/rrdef.c
index fe5c8e104a88..9e2100d53843 100644
--- a/contrib/unbound/sldns/rrdef.c
+++ b/contrib/unbound/sldns/rrdef.c
@@ -72,7 +72,7 @@ static const sldns_rdf_type type_nsap_wireformat[] = {
LDNS_RDF_TYPE_NSAP
};
static const sldns_rdf_type type_nsap_ptr_wireformat[] = {
- LDNS_RDF_TYPE_STR
+ LDNS_RDF_TYPE_UNQUOTED
};
static const sldns_rdf_type type_sig_wireformat[] = {
LDNS_RDF_TYPE_TYPE, LDNS_RDF_TYPE_ALG, LDNS_RDF_TYPE_INT8, LDNS_RDF_TYPE_INT32,
@@ -86,7 +86,7 @@ static const sldns_rdf_type type_px_wireformat[] = {
LDNS_RDF_TYPE_INT16, LDNS_RDF_TYPE_DNAME, LDNS_RDF_TYPE_DNAME
};
static const sldns_rdf_type type_gpos_wireformat[] = {
- LDNS_RDF_TYPE_STR, LDNS_RDF_TYPE_STR, LDNS_RDF_TYPE_STR
+ LDNS_RDF_TYPE_UNQUOTED, LDNS_RDF_TYPE_UNQUOTED, LDNS_RDF_TYPE_UNQUOTED
};
static const sldns_rdf_type type_aaaa_wireformat[] = { LDNS_RDF_TYPE_AAAA };
static const sldns_rdf_type type_loc_wireformat[] = { LDNS_RDF_TYPE_LOC };
@@ -381,9 +381,9 @@ static sldns_rr_descriptor rdata_field_descriptors[] = {
/* 63 */
{LDNS_RR_TYPE_ZONEMD, "ZONEMD", 4, 4, type_zonemd_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 },
+ {LDNS_RR_TYPE_SVCB, "SVCB", 2, 2, type_svcb_wireformat, LDNS_RDF_TYPE_SVCPARAM, LDNS_RR_NO_COMPRESS, 1 },
/* 65 */
- {LDNS_RR_TYPE_HTTPS, "HTTPS", 2, 2, type_svcb_wireformat, LDNS_RDF_TYPE_SVCPARAM, LDNS_RR_NO_COMPRESS, 0 },
+ {LDNS_RR_TYPE_HTTPS, "HTTPS", 2, 2, type_svcb_wireformat, LDNS_RDF_TYPE_SVCPARAM, LDNS_RR_NO_COMPRESS, 1 },
{(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 },
{(enum sldns_enum_rr_type)0, "TYPE68", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
@@ -617,6 +617,12 @@ static sldns_rr_descriptor rdata_field_descriptors[] = {
{(enum sldns_enum_rr_type)0, "TYPE258", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
#endif
+{(enum sldns_enum_rr_type)0, "TYPE259", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+{(enum sldns_enum_rr_type)0, "TYPE260", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+
+ /* 261 */
+ {LDNS_RR_TYPE_RESINFO, "RESINFO", 1, 0, NULL, LDNS_RDF_TYPE_UNQUOTED, LDNS_RR_NO_COMPRESS, 0 },
+
/* split in array, no longer contiguous */
#ifdef DRAFT_RRTYPES
@@ -702,7 +708,11 @@ sldns_get_rr_type_by_name(const char *name)
/* TYPEXX representation */
if (strlen(name) > 4 && strncasecmp(name, "TYPE", 4) == 0) {
- return atoi(name + 4);
+ unsigned int a = atoi(name + 4);
+ if (a > LDNS_RR_TYPE_LAST) {
+ return (enum sldns_enum_rr_type)0;
+ }
+ return a;
}
/* Normal types */
@@ -740,7 +750,11 @@ sldns_get_rr_class_by_name(const char *name)
/* CLASSXX representation */
if (strlen(name) > 5 && strncasecmp(name, "CLASS", 5) == 0) {
- return atoi(name + 5);
+ unsigned int a = atoi(name + 5);
+ if (a > LDNS_RR_CLASS_LAST) {
+ return (enum sldns_enum_rr_class)0;
+ }
+ return a;
}
/* Normal types */
diff --git a/contrib/unbound/sldns/rrdef.h b/contrib/unbound/sldns/rrdef.h
index 42d5de064eea..540468889880 100644
--- a/contrib/unbound/sldns/rrdef.h
+++ b/contrib/unbound/sldns/rrdef.h
@@ -196,8 +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_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 */
@@ -229,6 +229,8 @@ enum sldns_enum_rr_type
LDNS_RR_TYPE_CAA = 257, /* RFC 6844 */
LDNS_RR_TYPE_AVC = 258,
+ LDNS_RR_TYPE_RESINFO = 261, /* RFC 9606 */
+
/** DNSSEC Trust Authorities */
LDNS_RR_TYPE_TA = 32768,
/* RFC 4431, 5074, DNSSEC Lookaside Validation */
@@ -341,6 +343,9 @@ enum sldns_enum_rdf_type
/** 8 * 8 bit hex numbers separated by dashes. For EUI64. */
LDNS_RDF_TYPE_EUI64,
+ /** Character string without quotes. */
+ LDNS_RDF_TYPE_UNQUOTED,
+
/** A non-zero sequence of US-ASCII letters and numbers in lower case.
* For CAA.
*/
@@ -433,12 +438,52 @@ enum sldns_enum_edns_option
LDNS_EDNS_DHU = 6, /* RFC6975 */
LDNS_EDNS_N3U = 7, /* RFC6975 */
LDNS_EDNS_CLIENT_SUBNET = 8, /* RFC7871 */
+ LDNS_EDNS_COOKIE = 10, /* RFC7873 */
LDNS_EDNS_KEEPALIVE = 11, /* draft-ietf-dnsop-edns-tcp-keepalive*/
LDNS_EDNS_PADDING = 12, /* RFC7830 */
- LDNS_EDNS_CLIENT_TAG = 16 /* draft-bellis-dnsop-edns-tags-01 */
+ LDNS_EDNS_EDE = 15, /* RFC8914 */
+ LDNS_EDNS_CLIENT_TAG = 16, /* draft-bellis-dnsop-edns-tags-01 */
+ LDNS_EDNS_REPORT_CHANNEL = 18, /* RFC9567 */
+ LDNS_EDNS_UNBOUND_CACHEDB_TESTFRAME_TEST = 65534
};
typedef enum sldns_enum_edns_option sldns_edns_option;
+enum sldns_enum_ede_code
+{
+ LDNS_EDE_NONE = -1, /* EDE undefined for internal use */
+ LDNS_EDE_OTHER = 0,
+ LDNS_EDE_UNSUPPORTED_DNSKEY_ALG = 1,
+ LDNS_EDE_UNSUPPORTED_DS_DIGEST = 2,
+ LDNS_EDE_STALE_ANSWER = 3,
+ LDNS_EDE_FORGED_ANSWER = 4,
+ LDNS_EDE_DNSSEC_INDETERMINATE = 5,
+ LDNS_EDE_DNSSEC_BOGUS = 6,
+ LDNS_EDE_SIGNATURE_EXPIRED = 7,
+ LDNS_EDE_SIGNATURE_NOT_YET_VALID = 8,
+ LDNS_EDE_DNSKEY_MISSING = 9,
+ LDNS_EDE_RRSIGS_MISSING = 10,
+ LDNS_EDE_NO_ZONE_KEY_BIT_SET = 11,
+ LDNS_EDE_NSEC_MISSING = 12,
+ LDNS_EDE_CACHED_ERROR = 13,
+ LDNS_EDE_NOT_READY = 14,
+ LDNS_EDE_BLOCKED = 15,
+ LDNS_EDE_CENSORED = 16,
+ LDNS_EDE_FILTERED = 17,
+ LDNS_EDE_PROHIBITED = 18,
+ LDNS_EDE_STALE_NXDOMAIN_ANSWER = 19,
+ LDNS_EDE_NOT_AUTHORITATIVE = 20,
+ LDNS_EDE_NOT_SUPPORTED = 21,
+ LDNS_EDE_NO_REACHABLE_AUTHORITY = 22,
+ LDNS_EDE_NETWORK_ERROR = 23,
+ LDNS_EDE_INVALID_DATA = 24,
+ LDNS_EDE_SIGNATURE_EXPIRED_BEFORE_VALID = 25,
+ LDNS_EDE_TOO_EARLY = 26,
+ LDNS_EDE_UNSUPPORTED_NSEC3_ITERATIONS = 27,
+ LDNS_EDE_BADPROXYPOLICY = 28,
+ LDNS_EDE_SYNTHESIZED = 29
+};
+typedef enum sldns_enum_ede_code sldns_ede_code;
+
#define LDNS_EDNS_MASK_DO_BIT 0x8000
/** TSIG and TKEY extended rcodes (16bit), 0-15 are the normal rcodes. */
@@ -450,6 +495,9 @@ typedef enum sldns_enum_edns_option sldns_edns_option;
#define LDNS_TSIG_ERROR_BADNAME 20
#define LDNS_TSIG_ERROR_BADALG 21
+/** DNS Cookie extended rcode */
+#define LDNS_EXT_RCODE_BADCOOKIE 23
+
/**
* Contains all information about resource record types.
*
diff --git a/contrib/unbound/sldns/str2wire.c b/contrib/unbound/sldns/str2wire.c
index d2cefae1c09e..392fc8f1d32a 100644
--- a/contrib/unbound/sldns/str2wire.c
+++ b/contrib/unbound/sldns/str2wire.c
@@ -249,11 +249,16 @@ rrinternal_get_ttl(sldns_buffer* strbuf, char* token, size_t token_len,
int* not_there, uint32_t* ttl, uint32_t default_ttl)
{
const char* endptr;
+ int overflow;
if(sldns_bget_token(strbuf, token, "\t\n ", token_len) == -1) {
return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_TTL,
sldns_buffer_position(strbuf));
}
- *ttl = (uint32_t) sldns_str2period(token, &endptr);
+ *ttl = (uint32_t) sldns_str2period(token, &endptr, &overflow);
+ if(overflow) {
+ return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_INTEGER_OVERFLOW,
+ sldns_buffer_position(strbuf));
+ }
if (strlen(token) > 0 && !isdigit((unsigned char)token[0])) {
*not_there = 1;
@@ -352,7 +357,7 @@ rrinternal_get_delims(sldns_rdf_type rdftype, size_t r_cnt, size_t r_max)
break;
default : break;
}
- return "\n\t ";
+ return "\n\t ";
}
/* Syntactic sugar for sldns_rr_new_frm_str_internal */
@@ -360,7 +365,8 @@ static int
sldns_rdf_type_maybe_quoted(sldns_rdf_type rdf_type)
{
return rdf_type == LDNS_RDF_TYPE_STR ||
- rdf_type == LDNS_RDF_TYPE_LONG_STR;
+ rdf_type == LDNS_RDF_TYPE_LONG_STR ||
+ rdf_type == LDNS_RDF_TYPE_UNQUOTED;
}
/** see if rdata is quoted */
@@ -373,7 +379,8 @@ rrinternal_get_quoted(sldns_buffer* strbuf, const char** delimiters,
/* skip spaces */
while(sldns_buffer_remaining(strbuf) > 0 &&
- *(sldns_buffer_current(strbuf)) == ' ') {
+ (*(sldns_buffer_current(strbuf)) == ' ' ||
+ *(sldns_buffer_current(strbuf)) == '\t')) {
sldns_buffer_skip(strbuf, 1);
}
@@ -442,7 +449,7 @@ rrinternal_parse_unknown(sldns_buffer* strbuf, char* token, size_t token_len,
sldns_buffer_position(strbuf));
}
hex_data_size = (size_t)atoi(token);
- if(hex_data_size > LDNS_MAX_RDFLEN ||
+ if(hex_data_size > LDNS_MAX_RDFLEN ||
*rr_cur_len + hex_data_size > *rr_len) {
return RET_ERR(LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL,
sldns_buffer_position(strbuf));
@@ -561,7 +568,7 @@ sldns_parse_rdf_token(sldns_buffer* strbuf, char* token, size_t token_len,
/* 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[0] == '"' || token[0] == '\'') &&
(token[slen-1] == '"' || token[slen-1] == '\'')) {
/* move token two smaller (quotes) with endnull */
memmove(token, token+1, slen-2);
@@ -606,7 +613,7 @@ sldns_affix_token(sldns_buffer* strbuf, char* token, size_t* token_len,
/* add space */
/* when addlen < 2, the token buffer is full considering the NULL byte
* from strlen and will lead to buffer overflow with the second
- * assignement below. */
+ * assignment below. */
if(addlen < 2) return 0;
token[*token_strlen] = ' ';
token[++(*token_strlen)] = 0;
@@ -670,10 +677,10 @@ static int sldns_str2wire_check_svcbparams(uint8_t* rdata, uint16_t rdata_len)
,sldns_str2wire_svcparam_key_cmp);
- /* The code below revolves around sematic errors in the SVCParam set.
+ /* The code below revolves around semantic errors in the SVCParam set.
* So long as we do not distinguish between running Unbound as a primary
* or as a secondary, we default to secondary behavior and we ignore the
- * sematic errors. */
+ * semantic errors. */
#ifdef SVCB_SEMANTIC_ERRORS
{
@@ -692,7 +699,7 @@ static int sldns_str2wire_check_svcbparams(uint8_t* rdata, uint16_t rdata_len)
mandatory = svcparams[i];
}
- /* 4. verify that all the SvcParamKeys in mandatory are present */
+ /* Verify that all the SvcParamKeys in mandatory are present */
if(mandatory) {
/* Divide by sizeof(uint16_t)*/
uint16_t mandatory_nkeys = sldns_read_uint16(mandatory + 2) / sizeof(uint16_t);
@@ -775,10 +782,11 @@ rrinternal_parse_rdata(sldns_buffer* strbuf, char* token, size_t token_len,
/* unknown RR data */
if(token_strlen>=2 && strncmp(token, "\\#", 2) == 0 &&
- !quoted && (token_strlen == 2 || token[2]==' ')) {
+ !quoted && (token_strlen == 2 || token[2]==' ' ||
+ token[2]=='\t')) {
was_unknown_rr_format = 1;
if((status=rrinternal_parse_unknown(strbuf, token,
- token_len, rr, rr_len, &rr_cur_len,
+ token_len, rr, rr_len, &rr_cur_len,
pre_data_pos)) != 0)
return status;
} else if(token_strlen > 0 || quoted) {
@@ -837,7 +845,7 @@ rrinternal_parse_rdata(sldns_buffer* strbuf, char* token, size_t token_len,
if (rr_type == LDNS_RR_TYPE_SVCB || rr_type == LDNS_RR_TYPE_HTTPS) {
size_t rdata_len = rr_cur_len - dname_len - 10;
uint8_t *rdata = rr+dname_len + 10;
-
+
/* skip 1st rdata field SvcPriority (uint16_t) */
if (rdata_len < sizeof(uint16_t))
return LDNS_WIREPARSE_ERR_OK;
@@ -849,7 +857,7 @@ rrinternal_parse_rdata(sldns_buffer* strbuf, char* token, size_t token_len,
while (rdata_len && *rdata != 0) {
uint8_t label_len;
- if (*rdata & 0xC0)
+ if ((*rdata & 0xC0))
return LDNS_WIREPARSE_ERR_OK;
label_len = *rdata + 1;
@@ -1055,12 +1063,15 @@ int sldns_fp2wire_rr_buf(FILE* in, uint8_t* rr, size_t* len, size_t* dname_len,
return s;
} else if(strncmp(line, "$TTL", 4) == 0 && isspace((unsigned char)line[4])) {
const char* end = NULL;
+ int overflow = 0;
strlcpy((char*)rr, line, *len);
*len = 0;
*dname_len = 0;
if(!parse_state) return LDNS_WIREPARSE_ERR_OK;
parse_state->default_ttl = sldns_str2period(
- sldns_strip_ws(line+5), &end);
+ sldns_strip_ws(line+5), &end, &overflow);
+ if(overflow)
+ return LDNS_WIREPARSE_ERR_SYNTAX_INTEGER_OVERFLOW;
} else if (strncmp(line, "$INCLUDE", 8) == 0) {
strlcpy((char*)rr, line, *len);
*len = 0;
@@ -1113,36 +1124,40 @@ sldns_str2wire_svcparam_key_lookup(const char *key, size_t key_len)
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" */
+ case 3:
+ if (!strncmp(key, "ech", key_len))
+ return SVCB_KEY_ECH;
break;
- case sizeof("alpn")-1:
- if (!strncmp(key, "alpn", sizeof("alpn")-1))
+ case 4:
+ if (!strncmp(key, "alpn", key_len))
return SVCB_KEY_ALPN;
- if (!strncmp(key, "port", sizeof("port")-1))
+ if (!strncmp(key, "port", key_len))
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;
+ case 7:
+ if (!strncmp(key, "dohpath", key_len))
+ return SVCB_KEY_DOHPATH;
break;
- case sizeof("ipv4hint")-1:
- if (!strncmp(key, "ipv4hint", sizeof("ipv4hint")-1))
+ case 8:
+ if (!strncmp(key, "ipv4hint", key_len))
return SVCB_KEY_IPV4HINT;
- if (!strncmp(key, "ipv6hint", sizeof("ipv6hint")-1))
+ if (!strncmp(key, "ipv6hint", key_len))
return SVCB_KEY_IPV6HINT;
break;
- case sizeof("ech")-1:
- if (!strncmp(key, "ech", sizeof("ech")-1))
- return SVCB_KEY_ECH;
+ case 9:
+ if (!strncmp(key, "mandatory", key_len))
+ return SVCB_KEY_MANDATORY;
+ if (!strncmp(key, "echconfig", key_len))
+ return SVCB_KEY_ECH; /* allow "echconfig" as well as "ech" */
+ break;
+
+ case 15:
+ if (!strncmp(key, "no-default-alpn", key_len))
+ return SVCB_KEY_NO_DEFAULT_ALPN;
break;
default:
@@ -1356,7 +1371,7 @@ sldns_str2wire_svcbparam_mandatory(const char* val, uint8_t* rd, size_t* rd_len)
*/
qsort((void *)(rd + 4), count, sizeof(uint16_t), sldns_network_uint16_cmp);
- /* The code below revolves around sematic errors in the SVCParam set.
+ /* The code below revolves around semantic errors in the SVCParam set.
* So long as we do not distinguish between running Unbound as a primary
* or as a secondary, we default to secondary behavior and we ignore the
* semantic errors. */
@@ -1467,7 +1482,7 @@ sldns_str2wire_svcbparam_alpn_value(const char* val,
size_t str_len;
size_t dst_len;
size_t val_len;
-
+
val_len = strlen(val);
if (val_len > sizeof(unescaped_dst)) {
@@ -1501,7 +1516,34 @@ sldns_str2wire_svcbparam_alpn_value(const char* val,
sldns_write_uint16(rd + 2, dst_len);
memcpy(rd + 4, unescaped_dst, dst_len);
*rd_len = 4 + dst_len;
-
+
+ return LDNS_WIREPARSE_ERR_OK;
+}
+
+static int
+sldns_str2wire_svcbparam_dohpath_value(const char* val,
+ uint8_t* rd, size_t* rd_len)
+{
+ size_t val_len;
+
+ /* RFC6570#section-2.1
+ * "The characters outside of expressions in a URI Template string are
+ * intended to be copied literally"
+ * Practically this means we do not have to look for "double escapes"
+ * like in the alpn value list.
+ */
+
+ val_len = strlen(val);
+
+ if (*rd_len < 4 + val_len) {
+ return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL;
+ }
+
+ sldns_write_uint16(rd, SVCB_KEY_DOHPATH);
+ sldns_write_uint16(rd + 2, val_len);
+ memcpy(rd + 4, val, val_len);
+ *rd_len = 4 + val_len;
+
return LDNS_WIREPARSE_ERR_OK;
}
@@ -1525,6 +1567,7 @@ sldns_str2wire_svcparam_value(const char *key, size_t key_len,
case SVCB_KEY_PORT:
case SVCB_KEY_IPV4HINT:
case SVCB_KEY_IPV6HINT:
+ case SVCB_KEY_DOHPATH:
return LDNS_WIREPARSE_ERR_SVCB_MISSING_PARAM;
#endif
default:
@@ -1556,6 +1599,8 @@ sldns_str2wire_svcparam_value(const char *key, size_t key_len,
return sldns_str2wire_svcbparam_ech_value(val, rd, rd_len);
case SVCB_KEY_ALPN:
return sldns_str2wire_svcbparam_alpn_value(val, rd, rd_len);
+ case SVCB_KEY_DOHPATH:
+ return sldns_str2wire_svcbparam_dohpath_value(val, rd, rd_len);
default:
str_len = strlen(val);
if (*rd_len < 4 + str_len)
@@ -1583,28 +1628,28 @@ static int sldns_str2wire_svcparam_buf(const char* str, uint8_t* rd, size_t* rd_
/* case: key=value */
if (eq_pos != NULL && eq_pos[1]) {
val_in = eq_pos + 1;
-
+
/* unescape characters and "" blocks */
if (*val_in == '"') {
val_in++;
while (*val_in != '"'
- && (unsigned)(val_out - unescaped_val + 1) < sizeof(unescaped_val)
+ && (size_t)(val_out - unescaped_val + 1) < sizeof(unescaped_val)
&& sldns_parse_char( (uint8_t*) val_out, &val_in)) {
val_out++;
}
} else {
- while ((unsigned)(val_out - unescaped_val + 1) < sizeof(unescaped_val)
+ while ((size_t)(val_out - unescaped_val + 1) < sizeof(unescaped_val)
&& sldns_parse_char( (uint8_t*) val_out, &val_in)) {
val_out++;
}
}
*val_out = 0;
- return sldns_str2wire_svcparam_value(str, eq_pos - str,
- unescaped_val[0] ? unescaped_val : NULL, rd, rd_len);
+ return sldns_str2wire_svcparam_value(str, eq_pos - str,
+ unescaped_val[0] ? unescaped_val : NULL, rd, rd_len);
}
/* case: key= */
- else if (eq_pos != NULL && !(eq_pos[1])) {
+ else if (eq_pos != NULL && !(eq_pos[1])) {
return sldns_str2wire_svcparam_value(str, eq_pos - str, NULL, rd, rd_len);
}
/* case: key */
@@ -1675,6 +1720,8 @@ int sldns_str2wire_rdf_buf(const char* str, uint8_t* rd, size_t* len,
return sldns_str2wire_eui48_buf(str, rd, len);
case LDNS_RDF_TYPE_EUI64:
return sldns_str2wire_eui64_buf(str, rd, len);
+ case LDNS_RDF_TYPE_UNQUOTED:
+ return sldns_str2wire_unquoted_buf(str, rd, len);
case LDNS_RDF_TYPE_TAG:
return sldns_str2wire_tag_buf(str, rd, len);
case LDNS_RDF_TYPE_LONG_STR:
@@ -2157,9 +2204,13 @@ int sldns_str2wire_tsigtime_buf(const char* str, uint8_t* rd, size_t* len)
int sldns_str2wire_period_buf(const char* str, uint8_t* rd, size_t* len)
{
const char* end;
- uint32_t p = sldns_str2period(str, &end);
+ int overflow;
+ uint32_t p = sldns_str2period(str, &end, &overflow);
if(*end != 0)
return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_PERIOD, end-str);
+ if(overflow)
+ return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_INTEGER_OVERFLOW,
+ end-str);
if(*len < 4)
return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL;
sldns_write_uint32(rd, p);
@@ -2411,12 +2462,13 @@ int sldns_str2wire_wks_buf(const char* str, uint8_t* rd, size_t* len)
(void)strlcpy(proto_str, token, sizeof(proto_str));
} else {
int serv_port;
- struct servent *serv = getservbyname(token, proto_str);
- if(serv) serv_port=(int)ntohs((uint16_t)serv->s_port);
+ if(atoi(token) != 0) serv_port=atoi(token);
+ else if(strcmp(token, "0") == 0) serv_port=0;
else if(strcasecmp(token, "domain")==0) serv_port=53;
else {
- serv_port = atoi(token);
- if(serv_port == 0 && strcmp(token, "0") != 0) {
+ struct servent *serv = getservbyname(token, proto_str);
+ if(serv) serv_port=(int)ntohs((uint16_t)serv->s_port);
+ else {
#ifdef HAVE_ENDSERVENT
endservent();
#endif
@@ -2426,16 +2478,16 @@ int sldns_str2wire_wks_buf(const char* str, uint8_t* rd, size_t* len)
return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX,
sldns_buffer_position(&strbuf));
}
- if(serv_port < 0 || serv_port > 65535) {
+ }
+ if(serv_port < 0 || serv_port > 65535) {
#ifdef HAVE_ENDSERVENT
- endservent();
+ endservent();
#endif
#ifdef HAVE_ENDPROTOENT
- endprotoent();
+ endprotoent();
#endif
- return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX,
- sldns_buffer_position(&strbuf));
- }
+ return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX,
+ sldns_buffer_position(&strbuf));
}
if(rd_len < 1+serv_port/8+1) {
/* bitmap is larger, init new bytes at 0 */
@@ -2505,12 +2557,42 @@ int sldns_str2wire_atma_buf(const char* str, uint8_t* rd, size_t* len)
{
const char* s = str;
size_t slen = strlen(str);
- size_t dlen = 0; /* number of hexdigits parsed */
+ size_t dlen = 0; /* number of hexdigits parsed for hex,
+ digits for E.164 */
- /* just a hex string with optional dots? */
- /* notimpl e.164 format */
if(slen > LDNS_MAX_RDFLEN*2)
return LDNS_WIREPARSE_ERR_LABEL_OVERFLOW;
+ if(*len < 1)
+ return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL;
+ if(*s == 0) {
+ /* empty string */
+ rd[0] = 0;
+ *len = 1;
+ return LDNS_WIREPARSE_ERR_OK;
+ }
+ if(s[0] == '+') {
+ rd[0] = 1; /* E.164 format */
+ /* digits '0'..'9', with skipped dots. */
+ s++;
+ while(*s) {
+ if(isspace((unsigned char)*s) || *s == '.') {
+ s++;
+ continue;
+ }
+ if(*s < '0' || *s > '9')
+ return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX, s-str);
+ if(*len < dlen + 2)
+ return RET_ERR(LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL,
+ s-str);
+ rd[dlen+1] = *s++;
+ dlen++;
+ }
+ *len = dlen+1;
+ return LDNS_WIREPARSE_ERR_OK;
+ }
+
+ rd[0] = 0; /* AESA format */
+ /* hex, with skipped dots. */
while(*s) {
if(isspace((unsigned char)*s) || *s == '.') {
s++;
@@ -2518,17 +2600,17 @@ int sldns_str2wire_atma_buf(const char* str, uint8_t* rd, size_t* len)
}
if(!isxdigit((unsigned char)*s))
return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_HEX, s-str);
- if(*len < dlen/2 + 1)
+ if(*len < dlen/2 + 2)
return RET_ERR(LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL,
s-str);
if((dlen&1)==0)
- rd[dlen/2] = (uint8_t)sldns_hexdigit_to_int(*s++) * 16;
- else rd[dlen/2] += sldns_hexdigit_to_int(*s++);
+ rd[dlen/2 + 1] = (uint8_t)sldns_hexdigit_to_int(*s++) * 16;
+ else rd[dlen/2 + 1] += sldns_hexdigit_to_int(*s++);
dlen++;
}
if((dlen&1)!=0)
return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_HEX, s-str);
- *len = dlen/2;
+ *len = dlen/2 + 1;
return LDNS_WIREPARSE_ERR_OK;
}
@@ -2697,6 +2779,11 @@ int sldns_str2wire_eui64_buf(const char* str, uint8_t* rd, size_t* len)
return LDNS_WIREPARSE_ERR_OK;
}
+int sldns_str2wire_unquoted_buf(const char* str, uint8_t* rd, size_t* len)
+{
+ return sldns_str2wire_str_buf(str, rd, len);
+}
+
int sldns_str2wire_tag_buf(const char* str, uint8_t* rd, size_t* len)
{
size_t slen = strlen(str);
diff --git a/contrib/unbound/sldns/str2wire.h b/contrib/unbound/sldns/str2wire.h
index baee4236fe55..db6528a2f9bf 100644
--- a/contrib/unbound/sldns/str2wire.h
+++ b/contrib/unbound/sldns/str2wire.h
@@ -38,7 +38,8 @@ struct sldns_struct_lookup_table;
#define SVCB_KEY_IPV4HINT 4
#define SVCB_KEY_ECH 5
#define SVCB_KEY_IPV6HINT 6
-#define SVCPARAMKEY_COUNT 7
+#define SVCB_KEY_DOHPATH 7
+#define SVCPARAMKEY_COUNT 8
#define MAX_NUMBER_OF_SVCPARAMS 64
@@ -236,6 +237,7 @@ uint8_t* sldns_wirerr_get_rdatawl(uint8_t* rr, size_t len, size_t dname_len);
#define LDNS_WIREPARSE_ERR_SVCB_NO_DEFAULT_ALPN_VALUE 385
#define LDNS_WIREPARSE_ERR_SVCPARAM_BROKEN_RDATA 386
+
/**
* Get reference to a constant string for the (parse) error.
* @param e: error return value
@@ -550,6 +552,15 @@ int sldns_str2wire_eui48_buf(const char* str, uint8_t* rd, size_t* len);
int sldns_str2wire_eui64_buf(const char* str, uint8_t* rd, size_t* len);
/**
+ * Convert rdf of type LDNS_RDF_TYPE_UNQUOTED 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_unquoted_buf(const char* str, uint8_t* rd, size_t* len);
+
+/**
* Convert rdf of type LDNS_RDF_TYPE_TAG from string to wireformat.
* @param str: the text to convert for this rdata element.
* @param rd: rdata buffer for the wireformat.
diff --git a/contrib/unbound/sldns/wire2str.c b/contrib/unbound/sldns/wire2str.c
index b70efe299d4b..1bc5b9cf6e93 100644
--- a/contrib/unbound/sldns/wire2str.c
+++ b/contrib/unbound/sldns/wire2str.c
@@ -159,7 +159,7 @@ static sldns_lookup_table sldns_wireparse_errors_data[] = {
"Mandatory SvcParamKey is missing"},
{ LDNS_WIREPARSE_ERR_SVCB_MANDATORY_DUPLICATE_KEY,
"Keys in SvcParam mandatory MUST be unique" },
- { LDNS_WIREPARSE_ERR_SVCB_MANDATORY_IN_MANDATORY,
+ { LDNS_WIREPARSE_ERR_SVCB_MANDATORY_IN_MANDATORY,
"mandatory MUST not be included as mandatory parameter" },
{ LDNS_WIREPARSE_ERR_SVCB_PORT_VALUE_SYNTAX,
"Could not parse port SvcParamValue" },
@@ -192,12 +192,51 @@ static sldns_lookup_table sldns_edns_options_data[] = {
{ 6, "DHU" },
{ 7, "N3U" },
{ 8, "edns-client-subnet" },
+ { 10, "COOKIE" },
{ 11, "edns-tcp-keepalive"},
{ 12, "Padding" },
+ { 15, "EDE"},
{ 0, NULL}
};
sldns_lookup_table* sldns_edns_options = sldns_edns_options_data;
+/* From RFC8914 5.2 Table 3, the "Extended DNS Error Codes" registry. */
+static sldns_lookup_table sldns_edns_ede_codes_data[] = {
+ { LDNS_EDE_NONE, "None" },
+ { LDNS_EDE_OTHER, "Other Error" },
+ { LDNS_EDE_UNSUPPORTED_DNSKEY_ALG, "Unsupported DNSKEY Algorithm" },
+ { LDNS_EDE_UNSUPPORTED_DS_DIGEST, "Unsupported DS Digest Type" },
+ { LDNS_EDE_STALE_ANSWER, "Stale Answer" },
+ { LDNS_EDE_FORGED_ANSWER, "Forged Answer" },
+ { LDNS_EDE_DNSSEC_INDETERMINATE, "DNSSEC Indeterminate" },
+ { LDNS_EDE_DNSSEC_BOGUS, "DNSSEC Bogus" },
+ { LDNS_EDE_SIGNATURE_EXPIRED, "Signature Expired" },
+ { LDNS_EDE_SIGNATURE_NOT_YET_VALID, "Signature Not Yet Valid" },
+ { LDNS_EDE_DNSKEY_MISSING, "DNSKEY Missing" },
+ { LDNS_EDE_RRSIGS_MISSING, "RRSIGs Missing" },
+ { LDNS_EDE_NO_ZONE_KEY_BIT_SET, "No Zone Key Bit Set" },
+ { LDNS_EDE_NSEC_MISSING, "NSEC Missing" },
+ { LDNS_EDE_CACHED_ERROR, "Cached Error" },
+ { LDNS_EDE_NOT_READY, "Not Ready" },
+ { LDNS_EDE_BLOCKED, "Blocked" },
+ { LDNS_EDE_CENSORED, "Censored" },
+ { LDNS_EDE_FILTERED, "Filtered" },
+ { LDNS_EDE_PROHIBITED, "Prohibited" },
+ { LDNS_EDE_STALE_NXDOMAIN_ANSWER, "Stale NXDOMAIN Answer" },
+ { LDNS_EDE_NOT_AUTHORITATIVE, "Not Authoritative" },
+ { LDNS_EDE_NOT_SUPPORTED, "Not Supported" },
+ { LDNS_EDE_NO_REACHABLE_AUTHORITY, "No Reachable Authority" },
+ { LDNS_EDE_NETWORK_ERROR, "Network Error" },
+ { LDNS_EDE_INVALID_DATA, "Invalid Data" },
+ { LDNS_EDE_SIGNATURE_EXPIRED_BEFORE_VALID, "Signature Expired Before Valid" },
+ { LDNS_EDE_TOO_EARLY, "Non-Replayable Transactions Received in 0-RTT Data" },
+ { LDNS_EDE_UNSUPPORTED_NSEC3_ITERATIONS, "Unsupported NSEC3 Iterations Value" },
+ { LDNS_EDE_BADPROXYPOLICY, "Unable to Conform to Policy" },
+ { LDNS_EDE_SYNTHESIZED, "Synthesized Answer" },
+ { 0, NULL}
+};
+sldns_lookup_table* sldns_edns_ede_codes = sldns_edns_ede_codes_data;
+
static sldns_lookup_table sldns_tsig_errors_data[] = {
{ LDNS_TSIG_ERROR_NOERROR, "NOERROR" },
{ LDNS_RCODE_FORMERR, "FORMERR" },
@@ -223,7 +262,7 @@ sldns_lookup_table* sldns_tsig_errors = sldns_tsig_errors_data;
/* draft-ietf-dnsop-svcb-https-06: 6. Initial SvcParamKeys */
const char *svcparamkey_strs[] = {
"mandatory", "alpn", "no-default-alpn", "port",
- "ipv4hint", "ech", "ipv6hint"
+ "ipv4hint", "ech", "ipv6hint", "dohpath"
};
char* sldns_wire2str_pkt(uint8_t* data, size_t len)
@@ -486,7 +525,7 @@ int sldns_wire2str_rr_scan(uint8_t** d, size_t* dlen, char** s, size_t* slen,
uint8_t* rr = *d;
size_t rrlen = *dlen, dname_off, rdlen, ordlen;
uint16_t rrtype = 0;
-
+
if(*dlen >= 3 && (*d)[0]==0 &&
sldns_read_uint16((*d)+1)==LDNS_RR_TYPE_OPT) {
/* perform EDNS OPT processing */
@@ -1070,7 +1109,7 @@ static int sldns_wire2str_svcparam_mandatory2str(char** s,
assert(data_len > 0);
if (data_len % sizeof(uint16_t))
- return -1; // wireformat error, data_len must be multiple of shorts
+ return -1; /* wireformat error, data_len must be multiple of shorts */
w += sldns_str_print(s, slen, "=");
w += sldns_print_svcparamkey(s, slen, sldns_read_uint16(data));
data += 2;
@@ -1118,7 +1157,7 @@ static int sldns_wire2str_svcparam_alpn2str(char** s,
w += sldns_str_print(s, slen, "%s", ",");
}
w += sldns_str_print(s, slen, "\"");
-
+
return w;
}
@@ -1138,7 +1177,7 @@ static int sldns_wire2str_svcparam_ech2str(char** s,
(*s) += size;
(*slen) -= size;
- w += sldns_str_print(s, slen, "\"");
+ w += sldns_str_print(s, slen, "\"");
return w + size;
}
@@ -1161,7 +1200,7 @@ int sldns_wire2str_svcparam_scan(uint8_t** d, size_t* dlen, char** s, size_t* sl
/* verify that we have data_len data */
if (data_len > *dlen)
- return -1;
+ return -1;
written_chars += sldns_print_svcparamkey(s, slen, svcparamkey);
if (!data_len) {
@@ -1173,6 +1212,7 @@ int sldns_wire2str_svcparam_scan(uint8_t** d, size_t* dlen, char** s, size_t* sl
case SVCB_KEY_IPV4HINT:
case SVCB_KEY_IPV6HINT:
case SVCB_KEY_MANDATORY:
+ case SVCB_KEY_DOHPATH:
return -1;
default:
return written_chars;
@@ -1200,6 +1240,9 @@ int sldns_wire2str_svcparam_scan(uint8_t** d, size_t* dlen, char** s, size_t* sl
case SVCB_KEY_ECH:
r = sldns_wire2str_svcparam_ech2str(s, slen, data_len, *d);
break;
+ case SVCB_KEY_DOHPATH:
+ ATTR_FALLTHROUGH
+ /* fallthrough */
default:
r = sldns_str_print(s, slen, "=\"");
@@ -1221,7 +1264,7 @@ int sldns_wire2str_svcparam_scan(uint8_t** d, size_t* dlen, char** s, size_t* sl
}
if (r <= 0)
return -1; /* wireformat error */
-
+
written_chars += r;
*d += data_len;
*dlen -= data_len;
@@ -1301,6 +1344,8 @@ int sldns_wire2str_rdf_scan(uint8_t** d, size_t* dlen, char** s, size_t* slen,
return sldns_wire2str_eui48_scan(d, dlen, s, slen);
case LDNS_RDF_TYPE_EUI64:
return sldns_wire2str_eui64_scan(d, dlen, s, slen);
+ case LDNS_RDF_TYPE_UNQUOTED:
+ return sldns_wire2str_unquoted_scan(d, dlen, s, slen);
case LDNS_RDF_TYPE_TAG:
return sldns_wire2str_tag_scan(d, dlen, s, slen);
case LDNS_RDF_TYPE_LONG_STR:
@@ -1550,7 +1595,7 @@ int sldns_wire2str_nsec_scan(uint8_t** d, size_t* dl, char** s, size_t* sl)
unsigned i, bit, window, block_len;
uint16_t t;
int w = 0;
-
+
/* check for errors */
while(pl) {
if(pl < 2) return -1;
@@ -1827,7 +1872,33 @@ int sldns_wire2str_nsap_scan(uint8_t** d, size_t* dl, char** s, size_t* sl)
int sldns_wire2str_atma_scan(uint8_t** d, size_t* dl, char** s, size_t* sl)
{
- return print_remainder_hex("", d, dl, s, sl);
+ uint8_t format;
+ int w = 0;
+ size_t i;
+
+ if(*dl < 1) return -1;
+ format = (*d)[0];
+ (*d)+=1;
+ (*dl)-=1;
+
+ if(format == 0) {
+ /* AESA format (ATM End System Address). */
+ return print_remainder_hex("", d, dl, s, sl);
+ } else if(format == 1) {
+ /* E.164 format. */
+ w += sldns_str_print(s, sl, "+");
+ for(i=0; i<*dl; i++) {
+ if((*d)[i] < '0' || (*d)[0] > '9')
+ return -1;
+ w += sldns_str_print(s, sl, "%c", (*d)[i]);
+ }
+ (*d) += *dl;
+ (*dl) = 0;
+ } else {
+ /* Unknown format. */
+ return -1;
+ }
+ return w;
}
/* internal scan routine that can modify arguments on failure */
@@ -1978,6 +2049,26 @@ int sldns_wire2str_eui64_scan(uint8_t** d, size_t* dl, char** s, size_t* sl)
return w;
}
+int sldns_wire2str_unquoted_scan(uint8_t** d, size_t* dl, char** s, size_t* sl)
+{
+ int w = 0;
+ size_t i, len;
+ if(*dl < 1) return -1;
+ len = **d;
+ if(*dl < 1+len) return -1;
+ (*d)++;
+ (*dl)--;
+ for(i=0; i<len; i++) {
+ if(isspace((unsigned char)(*d)[i]) || (*d)[i] == '(' ||
+ (*d)[i] == ')' || (*d)[i] == '\'')
+ w += sldns_str_print(s, sl, "\\%c", (char)(*d)[i]);
+ else w += str_char_print(s, sl, (*d)[i]);
+ }
+ (*d)+=len;
+ (*dl)-=len;
+ return w;
+}
+
int sldns_wire2str_tag_scan(uint8_t** d, size_t* dl, char** s, size_t* sl)
{
size_t i, n;
@@ -2230,6 +2321,52 @@ static int sldns_wire2str_edns_keepalive_print(char** s, size_t* sl,
return w;
}
+int sldns_wire2str_edns_ede_print(char** s, size_t* sl,
+ uint8_t* data, size_t len)
+{
+ uint16_t ede_code;
+ int w = 0;
+ sldns_lookup_table *lt;
+ size_t i;
+ int printable;
+
+ if(len < 2) {
+ w += sldns_str_print(s, sl, "malformed ede ");
+ w += print_hex_buf(s, sl, data, len);
+ return w;
+ }
+
+ ede_code = sldns_read_uint16(data);
+ lt = sldns_lookup_by_id(sldns_edns_ede_codes, (int)ede_code);
+ if(lt && lt->name)
+ w += sldns_str_print(s, sl, "%s", lt->name);
+ else w += sldns_str_print(s, sl, "%d", (int)ede_code);
+
+ if(len == 2)
+ return w;
+
+ w += sldns_str_print(s, sl, " ");
+
+ /* If it looks like text, show it as text. */
+ printable=1;
+ for(i=2; i<len; i++) {
+ if(isprint((unsigned char)data[i]) || data[i] == '\t')
+ continue;
+ printable = 0;
+ break;
+ }
+ if(printable) {
+ w += sldns_str_print(s, sl, "\"");
+ for(i=2; i<len; i++) {
+ w += str_char_print(s, sl, data[i]);
+ }
+ w += sldns_str_print(s, sl, "\"");
+ } else {
+ w += print_hex_buf(s, sl, data+2, len-2);
+ }
+ return w;
+}
+
int sldns_wire2str_edns_option_print(char** s, size_t* sl,
uint16_t option_code, uint8_t* optdata, size_t optlen)
{
@@ -2264,6 +2401,9 @@ int sldns_wire2str_edns_option_print(char** s, size_t* sl,
case LDNS_EDNS_PADDING:
w += print_hex_buf(s, sl, optdata, optlen);
break;
+ case LDNS_EDNS_EDE:
+ w += sldns_wire2str_edns_ede_print(s, sl, optdata, optlen);
+ break;
default:
/* unknown option code */
w += print_hex_buf(s, sl, optdata, optlen);
diff --git a/contrib/unbound/sldns/wire2str.h b/contrib/unbound/sldns/wire2str.h
index 548c66300d92..36c58b8b064d 100644
--- a/contrib/unbound/sldns/wire2str.h
+++ b/contrib/unbound/sldns/wire2str.h
@@ -36,6 +36,8 @@ extern struct sldns_struct_lookup_table* sldns_opcodes;
extern struct sldns_struct_lookup_table* sldns_edns_flags;
/** EDNS option codes */
extern struct sldns_struct_lookup_table* sldns_edns_options;
+/** EDNS EDE codes */
+extern struct sldns_struct_lookup_table* sldns_edns_ede_codes;
/** error string from wireparse */
extern struct sldns_struct_lookup_table* sldns_wireparse_errors;
/** tsig errors are the rcodes with extra (higher) values */
@@ -260,7 +262,7 @@ int sldns_wire2str_rdata_unknown_scan(uint8_t** data, size_t* data_len,
* @param pkt: packet for decompression, if NULL no decompression.
* @param pktlen: length of packet buffer.
* @param comprloop: inout bool, that is set true if compression loop failure
- * happens. Pass in 0, if passsed in as true, a lower bound is set
+ * happens. Pass in 0, if passed in as true, a lower bound is set
* on compression loops to stop arbitrary long packet parse times.
* This is meant so you can set it to 0 at the start of a list of dnames,
* and then scan all of them in sequence, if a loop happens, it becomes
@@ -918,6 +920,19 @@ int sldns_wire2str_eui64_scan(uint8_t** data, size_t* data_len, char** str,
size_t* str_len);
/**
+ * Scan wireformat UNQUOTED 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_unquoted_scan(uint8_t** data, size_t* data_len, char** str,
+ size_t* str_len);
+
+/**
* Scan wireformat TAG field to string, with user buffers.
* It shifts the arguments to move along (see sldns_wire2str_pkt_scan).
* @param data: wireformat data.
@@ -1021,6 +1036,17 @@ int sldns_wire2str_edns_subnet_print(char** str, size_t* str_len,
uint8_t* option_data, size_t option_len);
/**
+ * Print EDNS EDE option data to string. User buffers, moves string pointers.
+ * @param str: string buffer.
+ * @param str_len: length of string buffer.
+ * @param option_data: buffer with EDNS option code data.
+ * @param option_len: length of the data for this option.
+ * @return number of characters (except null) needed to print.
+ */
+int sldns_wire2str_edns_ede_print(char** str, size_t* str_len,
+ uint8_t* option_data, size_t option_len);
+
+/**
* Print an EDNS option as OPT: VALUE. User buffers, moves string pointers.
* @param str: string buffer.
* @param str_len: length of string buffer.