mrdataset = NULL;
mname = NULL;
- CHECK(dns_message_buildopt(message, &opt, 0, 0, DNS_MESSAGEEXTFLAG_DO,
- NULL, 0));
+ dns_message_ednsinit(message, 0, 0, DNS_MESSAGEEXTFLAG_DO, 0);
+ CHECK(dns_message_buildopt(message, &opt));
CHECK(dns_message_setopt(message, opt));
CHECK(dns_requestmgr_create(isc_g_mctx, dispatchmgr, NULL, NULL,
lookup->ednsoptscnt++;
}
-/*%
- * Add EDNS0 option record to a message. Currently, the only supported
- * options are UDP buffer size, the DO bit, and EDNS options
- * (e.g., NSID, COOKIE, client-subnet)
- */
-static void
-add_opt(dns_message_t *msg, uint16_t udpsize, uint16_t edns, unsigned int flags,
- dns_ednsopt_t *opts, size_t count) {
- dns_rdataset_t *rdataset = NULL;
- isc_result_t result;
-
- debug("add_opt()");
- result = dns_message_buildopt(msg, &rdataset, edns, udpsize, flags,
- opts, count);
- check_result(result, "dns_message_buildopt");
- result = dns_message_setopt(msg, rdataset);
- check_result(result, "dns_message_setopt");
-}
-
/*%
* Add a question section to a message, asking for the specified name,
* type, and class.
char cookiebuf[256];
char *origin = NULL;
char *textname = NULL;
+ dns_rdataset_t *rdataset = NULL;
REQUIRE(lookup != NULL);
if (lookup->udpsize > -1 || lookup->dnssec || lookup->edns > -1 ||
lookup->ecs_addr != NULL)
{
-#define MAXOPTS (EDNSOPT_OPTIONS + DNS_EDNSOPTIONS)
- dns_ednsopt_t opts[MAXOPTS];
- unsigned int flags;
- unsigned int i = 0;
+ dns_ednsopt_t option;
- /*
- * There can't be more than MAXOPTS options to send:
- * a maximum of EDNSOPT_OPTIONS set by +ednsopt
- * and DNS_EDNSOPTIONS set by other arguments
- * (+nsid, +cookie, etc).
- */
+ /* Set the EDNS flags */
+ unsigned int flags = lookup->ednsflags;
+ flags &= ~(DNS_MESSAGEEXTFLAG_DO | DNS_MESSAGEEXTFLAG_CO);
+ if (lookup->dnssec) {
+ flags |= DNS_MESSAGEEXTFLAG_DO;
+ }
+ if (lookup->coflag) {
+ flags |= DNS_MESSAGEEXTFLAG_CO;
+ }
+
+ /* Set the EDNS UDP size */
if (lookup->udpsize < 0) {
lookup->udpsize = DEFAULT_EDNS_BUFSIZE;
}
DEFAULT_EDNS_VERSION;
}
+ /*
+ * Initialize EDNS in the message.
+ *
+ * Allow space for EDNSOPT_OPTIONS options to be
+ * set by +ednsopt, plus DNS_EDNSOPTIONS to be set
+ * by other arguments (+nsid, +cookie, etc).
+ */
+ constexpr size_t MAXOPTS =
+ (EDNSOPT_OPTIONS + DNS_EDNS_MAX_OPTIONS);
+
+ dns_message_ednsinit(lookup->sendmsg, lookup->edns,
+ lookup->udpsize, flags, MAXOPTS);
+
if (lookup->nsid) {
- INSIST(i < MAXOPTS);
- opts[i].code = DNS_OPT_NSID;
- opts[i].length = 0;
- opts[i].value = NULL;
- i++;
+ option = (dns_ednsopt_t){ .code = DNS_OPT_NSID };
+ result = dns_message_ednsaddopt(lookup->sendmsg,
+ &option);
+ check_result(result, "dns_message_ednsaddopt");
}
if (lookup->ecs_addr != NULL) {
uint8_t addr[16];
uint16_t family = 0;
uint32_t plen;
- struct sockaddr *sa;
- struct sockaddr_in *sin;
- struct sockaddr_in6 *sin6;
+ struct sockaddr *sa = NULL;
+ struct sockaddr_in *sin = NULL;
+ struct sockaddr_in6 *sin6 = NULL;
size_t addrl;
sa = &lookup->ecs_addr->type.sa;
/* Round up prefix len to a multiple of 8 */
addrl = (plen + 7) / 8;
- INSIST(i < MAXOPTS);
- opts[i].code = DNS_OPT_CLIENT_SUBNET;
- opts[i].length = (uint16_t)addrl + 4;
- check_result(result, "isc_buffer_allocate");
+ option.code = DNS_OPT_CLIENT_SUBNET;
+ option.length = (uint16_t)addrl + 4;
/*
* XXXMUKS: According to RFC7871, "If there is
(unsigned int)addrl);
}
- opts[i].value = (uint8_t *)ecsbuf;
- i++;
+ option.value = (uint8_t *)ecsbuf;
+ result = dns_message_ednsaddopt(lookup->sendmsg,
+ &option);
+ check_result(result, "dns_message_ednsaddopt");
}
if (lookup->sendcookie) {
- INSIST(i < MAXOPTS);
- opts[i].code = DNS_OPT_COOKIE;
+ option.code = DNS_OPT_COOKIE;
if (lookup->cookie != NULL) {
isc_buffer_init(&b, cookiebuf,
sizeof(cookiebuf));
result = isc_hex_decodestring(lookup->cookie,
&b);
check_result(result, "isc_hex_decodestring");
- opts[i].value = isc_buffer_base(&b);
- opts[i].length = isc_buffer_usedlength(&b);
+ option.value = isc_buffer_base(&b);
+ option.length = isc_buffer_usedlength(&b);
} else {
compute_cookie(cookie, sizeof(cookie));
- opts[i].length = 8;
- opts[i].value = cookie;
+ option.length = 8;
+ option.value = cookie;
}
- i++;
+
+ result = dns_message_ednsaddopt(lookup->sendmsg,
+ &option);
+ check_result(result, "dns_message_ednsaddopt");
}
if (lookup->expire) {
- INSIST(i < MAXOPTS);
- opts[i].code = DNS_OPT_EXPIRE;
- opts[i].length = 0;
- opts[i].value = NULL;
- i++;
+ option = (dns_ednsopt_t){ .code = DNS_OPT_EXPIRE };
+ result = dns_message_ednsaddopt(lookup->sendmsg,
+ &option);
+ check_result(result, "dns_message_ednsaddopt");
}
if (lookup->tcp_keepalive) {
- INSIST(i < MAXOPTS);
- opts[i].code = DNS_OPT_TCP_KEEPALIVE;
- opts[i].length = 0;
- opts[i].value = NULL;
- i++;
+ option = (dns_ednsopt_t){
+ .code = DNS_OPT_TCP_KEEPALIVE,
+ };
+ result = dns_message_ednsaddopt(lookup->sendmsg,
+ &option);
+ check_result(result, "dns_message_ednsaddopt");
}
if (lookup->zoneversion) {
- INSIST(i < MAXOPTS);
- opts[i].code = DNS_OPT_ZONEVERSION;
- opts[i].length = 0;
- opts[i].value = NULL;
- i++;
+ option = (dns_ednsopt_t){
+ .code = DNS_OPT_ZONEVERSION,
+ };
+ result = dns_message_ednsaddopt(lookup->sendmsg,
+ &option);
+ check_result(result, "dns_message_ednsaddopt");
}
if (lookup->ednsoptscnt != 0) {
- INSIST(i + lookup->ednsoptscnt <= MAXOPTS);
- memmove(&opts[i], lookup->ednsopts,
- sizeof(dns_ednsopt_t) * lookup->ednsoptscnt);
- i += lookup->ednsoptscnt;
- }
-
- if (lookup->padding != 0 && (i >= MAXOPTS)) {
- debug("turned off padding because of EDNS overflow");
- lookup->padding = 0;
+ for (size_t i = 0; i < lookup->ednsoptscnt; i++) {
+ result = dns_message_ednsaddopt(
+ lookup->sendmsg, &lookup->ednsopts[i]);
+ check_result(result, "dns_message_ednsaddopt");
+ }
}
if (lookup->padding != 0) {
- INSIST(i < MAXOPTS);
- opts[i].code = DNS_OPT_PAD;
- opts[i].length = 0;
- opts[i].value = NULL;
- i++;
+ option = (dns_ednsopt_t){ .code = DNS_OPT_PAD };
+ /* This can fail harmlessly */
+ (void)dns_message_ednsaddopt(lookup->sendmsg, &option);
dns_message_setpadding(lookup->sendmsg,
lookup->padding);
}
- flags = lookup->ednsflags;
- flags &= ~(DNS_MESSAGEEXTFLAG_DO | DNS_MESSAGEEXTFLAG_CO);
- if (lookup->dnssec) {
- flags |= DNS_MESSAGEEXTFLAG_DO;
- }
- if (lookup->coflag) {
- flags |= DNS_MESSAGEEXTFLAG_CO;
- }
- add_opt(lookup->sendmsg, lookup->udpsize, lookup->edns, flags,
- opts, i);
+ result = dns_message_buildopt(lookup->sendmsg, &rdataset);
+ check_result(result, "dns_message_buildopt");
+ result = dns_message_setopt(lookup->sendmsg, rdataset);
+ check_result(result, "dns_message_setopt");
}
result = dns_message_rendersection(lookup->sendmsg,
case DNS_SECTION_ADDITIONAL:
puts(" ADDITIONAL RECORDS:");
break;
+ default:
+ UNREACHABLE();
}
}
static void
updateopt(void) {
isc_result_t result;
- dns_ednsopt_t ednsopts[1];
+ dns_rdataset_t *opt = NULL;
unsigned char ul[8];
- unsigned int count = 0;
+ isc_buffer_t b;
+ dns_ednsopt_t option = {
+ .code = DNS_OPT_UL,
+ .length = keylease_set ? 8 : 4,
+ .value = ul,
+ };
- if (lease_set) {
- isc_buffer_t b;
- INSIST(count < ARRAY_SIZE(ednsopts));
- ednsopts[count++] = (dns_ednsopt_t){ .code = DNS_OPT_UL,
- .length = keylease_set ? 8
- : 4,
- .value = ul };
-
- isc_buffer_init(&b, ul, sizeof(ul));
- isc_buffer_putuint32(&b, lease);
- isc_buffer_putuint32(&b, keylease);
- }
-
- if (count != 0) {
- dns_rdataset_t *opt = NULL;
- result = dns_message_buildopt(updatemsg, &opt, 0,
- DEFAULT_EDNS_BUFSIZE, 0, ednsopts,
- count);
- check_result(result, "dns_message_buildopt");
- result = dns_message_setopt(updatemsg, opt);
- check_result(result, "dns_message_setopt");
- } else {
- result = dns_message_setopt(updatemsg, NULL);
- check_result(result, "dns_message_setopt");
+ if (!lease_set) {
+ return;
}
+
+ isc_buffer_init(&b, ul, sizeof(ul));
+ isc_buffer_putuint32(&b, lease);
+ isc_buffer_putuint32(&b, keylease);
+
+ dns_message_ednsinit(updatemsg, 0, DEFAULT_EDNS_BUFSIZE, 0, 0);
+ dns_message_ednsaddopt(updatemsg, &option);
+ result = dns_message_buildopt(updatemsg, &opt);
+ check_result(result, "dns_message_buildopt");
+ result = dns_message_setopt(updatemsg, opt);
}
static uint16_t
return;
}
-/*%
- * Add EDNS0 option record to a message. Currently, the only supported
- * options are UDP buffer size, the DO bit, and EDNS options
- * (e.g., NSID, COOKIE, client-subnet)
- */
-static void
-add_opt(dns_message_t *msg, uint16_t udpsize, uint16_t edns, unsigned int flags,
- dns_ednsopt_t *opts, size_t count) {
- dns_rdataset_t *rdataset = NULL;
- isc_result_t result;
-
- result = dns_message_buildopt(msg, &rdataset, edns, udpsize, flags,
- opts, count);
- CHECK("dns_message_buildopt", result);
- result = dns_message_setopt(msg, rdataset);
- CHECK("dns_message_setopt", result);
-}
-
static void
compute_cookie(unsigned char *cookie, size_t len) {
/* XXXMPA need to fix, should be per server. */
if (query->udpsize > 0 || query->dnssec || query->edns > -1 ||
query->ecs_addr != NULL)
{
- dns_ednsopt_t opts[EDNSOPTS + DNS_EDNSOPTIONS];
unsigned int flags;
- int i = 0;
char ecsbuf[20];
unsigned char cookie[40];
+ dns_rdataset_t *rdataset = NULL;
+
+ flags = query->ednsflags;
+ flags &= ~DNS_MESSAGEEXTFLAG_DO;
+ if (query->dnssec) {
+ flags |= DNS_MESSAGEEXTFLAG_DO;
+ }
if (query->udpsize == 0) {
query->udpsize = 1232;
query->edns = 0;
}
+ dns_message_ednsinit(message, query->edns, query->udpsize,
+ flags, 0);
+
if (query->nsid) {
- INSIST(i < DNS_EDNSOPTIONS);
- opts[i].code = DNS_OPT_NSID;
- opts[i].length = 0;
- opts[i].value = NULL;
- i++;
+ dns_ednsopt_t option = { .code = DNS_OPT_NSID };
+ result = dns_message_ednsaddopt(message, &option);
+ CHECK("dns_message_ednsaddopt", result);
}
if (query->ecs_addr != NULL) {
/* Round up prefix len to a multiple of 8 */
addrl = (plen + 7) / 8;
- INSIST(i < DNS_EDNSOPTIONS);
- opts[i].code = DNS_OPT_CLIENT_SUBNET;
- opts[i].length = (uint16_t)addrl + 4;
- CHECK("isc_buffer_allocate", result);
isc_buffer_init(&b, ecsbuf, sizeof(ecsbuf));
if (sa->sa_family == AF_INET) {
family = 1;
(unsigned int)addrl);
}
- opts[i].value = (uint8_t *)ecsbuf;
- i++;
+ dns_ednsopt_t option = { .code = DNS_OPT_CLIENT_SUBNET,
+ .value = (uint8_t *)ecsbuf,
+ .length = (uint16_t)addrl +
+ 4 };
+ result = dns_message_ednsaddopt(message, &option);
+ CHECK("dns_message_ednsaddopt", result);
}
if (query->send_cookie) {
- INSIST(i < DNS_EDNSOPTIONS);
- opts[i].code = DNS_OPT_COOKIE;
+ dns_ednsopt_t option = { .code = DNS_OPT_COOKIE };
if (query->cookie != NULL) {
isc_buffer_t b;
result = isc_hex_decodestring(query->cookie,
&b);
CHECK("isc_hex_decodestring", result);
- opts[i].value = isc_buffer_base(&b);
- opts[i].length = isc_buffer_usedlength(&b);
+ option.value = isc_buffer_base(&b);
+ option.length = isc_buffer_usedlength(&b);
} else {
compute_cookie(cookie, 8);
- opts[i].length = 8;
- opts[i].value = cookie;
+ option.length = 8;
+ option.value = cookie;
}
- i++;
+
+ result = dns_message_ednsaddopt(message, &option);
+ CHECK("dns_message_ednsaddopt", result);
}
if (query->expire) {
- INSIST(i < DNS_EDNSOPTIONS);
- opts[i].code = DNS_OPT_EXPIRE;
- opts[i].length = 0;
- opts[i].value = NULL;
- i++;
+ dns_ednsopt_t option = { .code = DNS_OPT_EXPIRE };
+ result = dns_message_ednsaddopt(message, &option);
+ CHECK("dns_message_ednsaddopt", result);
}
if (query->ednsoptscnt != 0) {
- memmove(&opts[i], query->ednsopts,
- sizeof(dns_ednsopt_t) * query->ednsoptscnt);
- i += query->ednsoptscnt;
+ for (size_t i = 0; i < query->ednsoptscnt; i++) {
+ result = dns_message_ednsaddopt(
+ message, &query->ednsopts[i]);
+ CHECK("dns_message_ednsaddopt", result);
+ }
}
- flags = query->ednsflags;
- flags &= ~DNS_MESSAGEEXTFLAG_DO;
- if (query->dnssec) {
- flags |= DNS_MESSAGEEXTFLAG_DO;
- }
- add_opt(message, query->udpsize, query->edns, flags, opts, i);
+ result = dns_message_buildopt(message, &rdataset);
+ CHECK("dns_message_buildopt", result);
+ result = dns_message_setopt(message, rdataset);
+ CHECK("dns_message_setopt", result);
}
if (tcp_mode) {
void
dns_ede_add(dns_edectx_t *edectx, uint16_t code, const char *text) {
REQUIRE(DNS_EDE_VALID(edectx));
- REQUIRE(code <= DNS_EDE_MAX_CODE);
+ REQUIRE(code < DNS_EDE_MAX_CODE);
uint16_t becode = htobe16(code);
dns_ednsopt_t *edns = NULL;
#include <dns/message.h>
/*%< EDNS0 extended DNS errors */
-#define DNS_EDE_OTHER 0 /*%< Other Error */
-#define DNS_EDE_DNSKEYALG 1 /*%< Unsupported DNSKEY Algorithm */
-#define DNS_EDE_DSDIGESTTYPE 2 /*%< Unsupported DS Digest Type */
-#define DNS_EDE_STALEANSWER 3 /*%< Stale Answer */
-#define DNS_EDE_FORGEDANSWER 4 /*%< Forged Answer */
-#define DNS_EDE_DNSSECINDETERMINATE 5 /*%< DNSSEC Indeterminate */
-#define DNS_EDE_DNSSECBOGUS 6 /*%< DNSSEC Bogus */
-#define DNS_EDE_SIGNATUREEXPIRED 7 /*%< Signature Expired */
-#define DNS_EDE_SIGNATURENOTYETVALID 8 /*%< Signature Not Yet Valid */
-#define DNS_EDE_DNSKEYMISSING 9 /*%< DNSKEY Missing */
-#define DNS_EDE_RRSIGSMISSING 10 /*%< RRSIGs Missing */
-#define DNS_EDE_NOZONEKEYBITSET 11 /*%< No Zone Key Bit Set */
-#define DNS_EDE_NSECMISSING 12 /*%< NSEC Missing */
-#define DNS_EDE_CACHEDERROR 13 /*%< Cached Error */
-#define DNS_EDE_NOTREADY 14 /*%< Not Ready */
-#define DNS_EDE_BLOCKED 15 /*%< Blocked */
-#define DNS_EDE_CENSORED 16 /*%< Censored */
-#define DNS_EDE_FILTERED 17 /*%< Filtered */
-#define DNS_EDE_PROHIBITED 18 /*%< Prohibited */
-#define DNS_EDE_STALENXANSWER 19 /*%< Stale NXDomain Answer */
-#define DNS_EDE_NOTAUTH 20 /*%< Not Authoritative */
-#define DNS_EDE_NOTSUPPORTED 21 /*%< Not Supported */
-#define DNS_EDE_NOREACHABLEAUTH 22 /*%< No Reachable Authority */
-#define DNS_EDE_NETWORKERROR 23 /*%< Network Error */
-#define DNS_EDE_INVALIDDATA 24 /*%< Invalid Data */
-
-#define DNS_EDE_MAX_CODE DNS_EDE_INVALIDDATA
+enum {
+ DNS_EDE_OTHER = 0, /*%< Other Error */
+ DNS_EDE_DNSKEYALG = 1, /*%< Unsupported DNSKEY Algorithm */
+ DNS_EDE_DSDIGESTTYPE = 2, /*%< Unsupported DS Digest Type */
+ DNS_EDE_STALEANSWER = 3, /*%< Stale Answer */
+ DNS_EDE_FORGEDANSWER = 4, /*%< Forged Answer */
+ DNS_EDE_DNSSECINDETERMINATE = 5, /*%< DNSSEC Indeterminate */
+ DNS_EDE_DNSSECBOGUS = 6, /*%< DNSSEC Bogus */
+ DNS_EDE_SIGNATUREEXPIRED = 7, /*%< Signature Expired */
+ DNS_EDE_SIGNATURENOTYETVALID = 8, /*%< Signature Not Yet Valid */
+ DNS_EDE_DNSKEYMISSING = 9, /*%< DNSKEY Missing */
+ DNS_EDE_RRSIGSMISSING = 10, /*%< RRSIGs Missing */
+ DNS_EDE_NOZONEKEYBITSET = 11, /*%< No Zone Key Bit Set */
+ DNS_EDE_NSECMISSING = 12, /*%< NSEC Missing */
+ DNS_EDE_CACHEDERROR = 13, /*%< Cached Error */
+ DNS_EDE_NOTREADY = 14, /*%< Not Ready */
+ DNS_EDE_BLOCKED = 15, /*%< Blocked */
+ DNS_EDE_CENSORED = 16, /*%< Censored */
+ DNS_EDE_FILTERED = 17, /*%< Filtered */
+ DNS_EDE_PROHIBITED = 18, /*%< Prohibited */
+ DNS_EDE_STALENXANSWER = 19, /*%< Stale NXDomain Answer */
+ DNS_EDE_NOTAUTH = 20, /*%< Not Authoritative */
+ DNS_EDE_NOTSUPPORTED = 21, /*%< Not Supported */
+ DNS_EDE_NOREACHABLEAUTH = 22, /*%< No Reachable Authority */
+ DNS_EDE_NETWORKERROR = 23, /*%< Network Error */
+ DNS_EDE_INVALIDDATA = 24, /*%< Invalid Data */
+ DNS_EDE_MAX_CODE
+};
/*
* From RFC 8914:
*/
#define DNS_EDE_EXTRATEXT_LEN 64
-#define DNS_EDE_MAX_ERRORS 3
-
typedef struct dns_edectx dns_edectx_t;
struct dns_edectx {
int magic;
#include <isc/refcount.h>
#include <dns/compress.h>
-#include <dns/ede.h>
#include <dns/masterdump.h>
#include <dns/types.h>
* section, move rdata from one section to another, remove rdata, etc.
*/
-#define DNS_MESSAGEFLAG_QR 0x8000U
-#define DNS_MESSAGEFLAG_AA 0x0400U
-#define DNS_MESSAGEFLAG_TC 0x0200U
-#define DNS_MESSAGEFLAG_RD 0x0100U
-#define DNS_MESSAGEFLAG_RA 0x0080U
-#define DNS_MESSAGEFLAG_AD 0x0020U
-#define DNS_MESSAGEFLAG_CD 0x0010U
+enum {
+ DNS_MESSAGEFLAG_QR = 0x8000U,
+ DNS_MESSAGEFLAG_AA = 0x0400U,
+ DNS_MESSAGEFLAG_TC = 0x0200U,
+ DNS_MESSAGEFLAG_RD = 0x0100U,
+ DNS_MESSAGEFLAG_RA = 0x0080U,
+ DNS_MESSAGEFLAG_AD = 0x0020U,
+ DNS_MESSAGEFLAG_CD = 0x0010U,
+};
/*%< EDNS0 extended message flags */
-#define DNS_MESSAGEEXTFLAG_DO 0x8000U /* DNSSEC OK */
-#define DNS_MESSAGEEXTFLAG_CO 0x4000U /* Compact denial of existence OK */
+enum {
+ DNS_MESSAGEEXTFLAG_DO = 0x8000U, /* DNSSEC OK */
+ DNS_MESSAGEEXTFLAG_CO = 0x4000U, /* Compact denial of existence OK */
+};
/*%< EDNS0 extended OPT codes */
-#define DNS_OPT_LLQ 1 /*%< LLQ opt code */
-#define DNS_OPT_UL 2 /*%< UL opt code */
-#define DNS_OPT_NSID 3 /*%< NSID opt code */
-#define DNS_OPT_DAU 5 /*%< DNSSEC algorithm understood */
-#define DNS_OPT_DHU 6 /*%< DNSSEC hash understood */
-#define DNS_OPT_N3U 7 /*%< NSEC3 hash understood */
-#define DNS_OPT_CLIENT_SUBNET 8 /*%< client subnet opt code */
-#define DNS_OPT_EXPIRE 9 /*%< EXPIRE opt code */
-#define DNS_OPT_COOKIE 10 /*%< COOKIE opt code */
-#define DNS_OPT_TCP_KEEPALIVE 11 /*%< TCP keepalive opt code */
-#define DNS_OPT_PAD 12 /*%< PAD opt code */
-#define DNS_OPT_CHAIN 13 /*%< CHAIN opt code */
-#define DNS_OPT_KEY_TAG 14 /*%< Key tag opt code */
-#define DNS_OPT_EDE 15 /*%< Extended DNS Error opt code */
-#define DNS_OPT_CLIENT_TAG 16 /*%< Client tag opt code */
-#define DNS_OPT_SERVER_TAG 17 /*%< Server tag opt code */
-#define DNS_OPT_REPORT_CHANNEL 18 /*%< DNS Reporting Channel */
-#define DNS_OPT_ZONEVERSION 19 /*%< Zoneversion opt code */
+enum {
+ DNS_OPT_LLQ = 1, /*%< LLQ opt code */
+ DNS_OPT_UL = 2, /*%< UL opt code */
+ DNS_OPT_NSID = 3, /*%< NSID opt code */
+ DNS_OPT_DAU = 5, /*%< DNSSEC algorithm understood */
+ DNS_OPT_DHU = 6, /*%< DNSSEC hash understood */
+ DNS_OPT_N3U = 7, /*%< NSEC3 hash understood */
+ DNS_OPT_CLIENT_SUBNET = 8, /*%< client subnet opt code */
+ DNS_OPT_EXPIRE = 9, /*%< EXPIRE opt code */
+ DNS_OPT_COOKIE = 10, /*%< COOKIE opt code */
+ DNS_OPT_TCP_KEEPALIVE = 11, /*%< TCP keepalive opt code */
+ DNS_OPT_PAD = 12, /*%< PAD opt code */
+ DNS_OPT_CHAIN = 13, /*%< CHAIN opt code */
+ DNS_OPT_KEY_TAG = 14, /*%< Key tag opt code */
+ DNS_OPT_EDE = 15, /*%< Extended DNS Error opt code */
+ DNS_OPT_CLIENT_TAG = 16, /*%< Client tag opt code */
+ DNS_OPT_SERVER_TAG = 17, /*%< Server tag opt code */
+ DNS_OPT_REPORT_CHANNEL = 18, /*%< DNS Reporting Channel */
+ DNS_OPT_ZONEVERSION = 19, /*%< Zoneversion opt code */
+
+ DNS_OPT_COUNT = 18, /*%< Number of elements defined in this enum. */
+};
/*%< Experimental options [65001...65534] as per RFC6891 */
/*%<
* The maximum number of EDNS options we allow to set. Reserve space for the
- * options we know about. Extended DNS Errors may occur multiple times, see
- * DNS_EDE_MAX_ERRORS.
+ * options we know about. Extended DNS Errors may occur multiple times,
+ * controlled by DNS_EDE_MAX_ERRORS.
*/
-#define DNS_EDNSOPTIONS 9 + DNS_EDE_MAX_ERRORS
+#define DNS_EDE_MAX_ERRORS 3
+#define DNS_EDNS_MAX_OPTIONS DNS_OPT_COUNT + DNS_EDE_MAX_ERRORS
#define DNS_MESSAGE_REPLYPRESERVE (DNS_MESSAGEFLAG_RD | DNS_MESSAGEFLAG_CD)
#define DNS_MESSAGEEXTFLAG_REPLYPRESERVE (DNS_MESSAGEEXTFLAG_DO)
* Ordering here matters. DNS_SECTION_ANY must be the lowest and negative,
* and DNS_SECTION_MAX must be one greater than the last used section.
*/
-typedef int dns_section_t;
-#define DNS_SECTION_ANY (-1)
-#define DNS_SECTION_QUESTION 0
-#define DNS_SECTION_ANSWER 1
-#define DNS_SECTION_AUTHORITY 2
-#define DNS_SECTION_ADDITIONAL 3
-#define DNS_SECTION_MAX 4
-
-typedef int dns_pseudosection_t;
-#define DNS_PSEUDOSECTION_ANY (-1)
-#define DNS_PSEUDOSECTION_OPT 0
-#define DNS_PSEUDOSECTION_TSIG 1
-#define DNS_PSEUDOSECTION_SIG0 2
-#define DNS_PSEUDOSECTION_MAX 3
-
-typedef int dns_messagetextflag_t;
-#define DNS_MESSAGETEXTFLAG_NOCOMMENTS 0x0001
-#define DNS_MESSAGETEXTFLAG_NOHEADERS 0x0002
-#define DNS_MESSAGETEXTFLAG_ONESOA 0x0004
-#define DNS_MESSAGETEXTFLAG_OMITSOA 0x0008
+typedef enum {
+ DNS_SECTION_ANY = -1,
+ DNS_SECTION_QUESTION = 0,
+ DNS_SECTION_ZONE = DNS_SECTION_QUESTION,
+ DNS_SECTION_ANSWER = 1,
+ DNS_SECTION_PREREQUISITE = DNS_SECTION_ANSWER,
+ DNS_SECTION_AUTHORITY = 2,
+ DNS_SECTION_UPDATE = DNS_SECTION_AUTHORITY,
+ DNS_SECTION_ADDITIONAL = 3,
+ DNS_SECTION_MAX
+} dns_section_t;
+
+typedef enum {
+ DNS_PSEUDOSECTION_ANY = -1,
+ DNS_PSEUDOSECTION_OPT = 0,
+ DNS_PSEUDOSECTION_TSIG = 1,
+ DNS_PSEUDOSECTION_SIG0 = 2,
+ DNS_PSEUDOSECTION_MAX
+} dns_pseudosection_t;
+
+typedef enum {
+ DNS_MESSAGETEXTFLAG_NOCOMMENTS = 1 << 0,
+ DNS_MESSAGETEXTFLAG_NOHEADERS = 1 << 1,
+ DNS_MESSAGETEXTFLAG_ONESOA = 1 << 2,
+ DNS_MESSAGETEXTFLAG_OMITSOA = 1 << 3,
+} dns_messagetextflag_t;
/*
* Dynamic update names for these sections.
dns_ttl_t ttl;
} dns_minttl_t;
+struct dns_ednsopt {
+ uint16_t code;
+ uint16_t length;
+ uint8_t *value;
+};
+
struct dns_message {
/* public from here down */
unsigned int magic;
dns_indent_t indent;
dns_minttl_t minttl[DNS_SECTION_MAX];
-};
-struct dns_ednsopt {
- uint16_t code;
- uint16_t length;
- uint8_t *value;
+ struct {
+ dns_ednsopt_t *opts;
+ uint8_t maxopts;
+ uint8_t count;
+ int16_t version;
+ uint16_t udpsize;
+ uint32_t flags;
+ } edns;
};
typedef void (*dns_message_cb_t)(void *arg, isc_result_t result);
*\li 'mctx' to be a valid memory context.
*/
+void
+dns_message_ednsinit(dns_message_t *msg, int16_t version, uint16_t udpsize,
+ uint32_t flags, uint8_t maxopts);
+/*%<
+ * Initialize the EDNS data in 'msg'. EDNS version is set to 'version',
+ * UDP size is set to 'udpsize', flags is set to 'flags'; EDNS options
+ * are cleared, and ready to be added via subsequent calls to
+ * dns_message_ednsaddopt(). If 'maxopts' is nonzero, space is allocated
+ * for that many EDNS options; if it is zero, space is allocated for
+ * DNS_EDNS_MAX_OPTIONS options.
+ *
+ * If 'version' is -1, the message has no EDNS, any existing EDNS data
+ * is cleared, and no OPT record will be rendered.
+ *
+ * Requires:
+ *\li 'msg' be a valid message.
+ */
+
+isc_result_t
+dns_message_ednsaddopt(dns_message_t *msg, dns_ednsopt_t *ednsopt);
+/*%<
+ * Add the EDNS option 'ednsopt' to 'msg->edns.opts' and increment
+ * 'msg->edns.count'.
+ *
+ * Requires:
+ *\li 'msg' to be a valid message.
+ *\li dns_message_ednsinit() to have been called.
+ *
+ * Returns:
+ *\li ISC_R_SUCCESS
+ *\li ISC_R_NOSPACE
+ */
+
isc_result_t
-dns_message_buildopt(dns_message_t *msg, dns_rdataset_t **opt,
- unsigned int version, uint16_t udpsize, unsigned int flags,
- dns_ednsopt_t *ednsopts, size_t count);
+dns_message_buildopt(dns_message_t *msg, dns_rdataset_t **opt);
+
/*%<
- * Built a opt record.
+ * Build an opt record.
*
* Requires:
*\li msg be a valid message.
}
}
+static void
+msgresetedns(dns_message_t *msg) {
+ if (msg->edns.opts != NULL) {
+ INSIST(msg->edns.maxopts != 0);
+ for (size_t i = 0; i < msg->edns.count; i++) {
+ if (msg->edns.opts[i].value != NULL) {
+ isc_mem_put(msg->mctx, msg->edns.opts[i].value,
+ msg->edns.opts[i].length);
+ }
+ }
+ isc_mem_cput(msg->mctx, msg->edns.opts,
+ (size_t)msg->edns.maxopts, sizeof(dns_ednsopt_t));
+ }
+ msg->edns.maxopts = 0;
+ msg->edns.count = 0;
+}
+
/*
* Free all but one (or everything) for this message. This is used by
* both dns_message_reset() and dns__message_destroy().
msgresetnames(msg, 0);
msgresetopt(msg);
msgresetsigs(msg, false);
+ msgresetedns(msg);
/*
* Clean up linked lists.
ADD_STRING(target, "\n");
}
goto cleanup;
+ default:
+ break;
}
result = ISC_R_UNEXPECTED;
ADD_STRING(target, "\n");
}
return result;
+ default:
+ break;
}
result = ISC_R_UNEXPECTED;
cleanup:
}
}
+void
+dns_message_ednsinit(dns_message_t *msg, int16_t version, uint16_t udpsize,
+ uint32_t flags, uint8_t maxopts) {
+ REQUIRE(DNS_MESSAGE_VALID(msg));
+
+ /* Clear existing EDNS data */
+ msgresetedns(msg);
+
+ msg->edns.version = version;
+ if (version == -1) {
+ return;
+ }
+
+ if (maxopts == 0) {
+ maxopts = DNS_EDNS_MAX_OPTIONS;
+ }
+
+ msg->edns.flags = flags;
+ msg->edns.udpsize = udpsize;
+ msg->edns.opts = isc_mem_cget(msg->mctx, (size_t)maxopts,
+ sizeof(dns_ednsopt_t));
+ msg->edns.maxopts = maxopts;
+}
+
isc_result_t
-dns_message_buildopt(dns_message_t *message, dns_rdataset_t **rdatasetp,
- unsigned int version, uint16_t udpsize, unsigned int flags,
- dns_ednsopt_t *ednsopts, size_t count) {
+dns_message_ednsaddopt(dns_message_t *msg, dns_ednsopt_t *option) {
+ REQUIRE(DNS_MESSAGE_VALID(msg));
+ REQUIRE(msg->edns.opts != NULL);
+
+ if (msg->edns.count >= msg->edns.maxopts) {
+ isc_log_write(ISC_LOGCATEGORY_GENERAL, DNS_LOGMODULE_MESSAGE,
+ ISC_LOG_DEBUG(3),
+ "dns_message_ednsaddopt: limit of %u EDNS "
+ "options exceeded",
+ msg->edns.maxopts);
+ return ISC_R_NOSPACE;
+ }
+
+ size_t i = msg->edns.count;
+ msg->edns.opts[i].code = option->code;
+ if (option->value != NULL) {
+ msg->edns.opts[i].value = isc_mem_get(msg->mctx,
+ option->length);
+ memmove(msg->edns.opts[i].value, option->value, option->length);
+ msg->edns.opts[i].length = option->length;
+ }
+ msg->edns.count++;
+ return ISC_R_SUCCESS;
+}
+
+isc_result_t
+dns_message_buildopt(dns_message_t *message, dns_rdataset_t **rdatasetp) {
dns_rdataset_t *rdataset = NULL;
dns_rdatalist_t *rdatalist = NULL;
dns_rdata_t *rdata = NULL;
isc_result_t result;
- unsigned int len = 0, i;
REQUIRE(DNS_MESSAGE_VALID(message));
REQUIRE(rdatasetp != NULL && *rdatasetp == NULL);
/*
* Set Maximum UDP buffer size.
*/
- rdatalist->rdclass = udpsize;
+ rdatalist->rdclass = message->edns.udpsize;
/*
* Set EXTENDED-RCODE and Z to 0.
*/
- rdatalist->ttl = (version << 16);
- rdatalist->ttl |= (flags & 0xffff);
+ rdatalist->ttl = (message->edns.version << 16);
+ rdatalist->ttl |= (message->edns.flags & 0xffff);
/*
* Set EDNS options if applicable
*/
- if (count != 0U) {
+ if (message->edns.count != 0U) {
isc_buffer_t *buf = NULL;
bool seenpad = false;
- for (i = 0; i < count; i++) {
- len += ednsopts[i].length + 4;
+ size_t len = 0;
+
+ for (size_t i = 0; i < message->edns.count; i++) {
+ len += message->edns.opts[i].length + 4;
}
if (len > 0xffffU) {
isc_buffer_allocate(message->mctx, &buf, len);
- for (i = 0; i < count; i++) {
- if (ednsopts[i].code == DNS_OPT_PAD &&
- ednsopts[i].length == 0U && !seenpad)
+ for (size_t i = 0; i < message->edns.count; i++) {
+ if (message->edns.opts[i].code == DNS_OPT_PAD &&
+ message->edns.opts[i].length == 0U && !seenpad)
{
seenpad = true;
continue;
}
- isc_buffer_putuint16(buf, ednsopts[i].code);
- isc_buffer_putuint16(buf, ednsopts[i].length);
- if (ednsopts[i].length != 0) {
- isc_buffer_putmem(buf, ednsopts[i].value,
- ednsopts[i].length);
+ isc_buffer_putuint16(buf, message->edns.opts[i].code);
+ isc_buffer_putuint16(buf, message->edns.opts[i].length);
+ if (message->edns.opts[i].length != 0) {
+ isc_buffer_putmem(buf,
+ message->edns.opts[i].value,
+ message->edns.opts[i].length);
}
}
default:
return "add";
}
+ default:
+ break;
}
return "invalid";
}
resquery_detach(&query);
}
-static isc_result_t
-fctx_addopt(dns_message_t *message, unsigned int version, uint16_t udpsize,
- dns_ednsopt_t *ednsopts, size_t count) {
- dns_rdataset_t *rdataset = NULL;
- isc_result_t result;
-
- result = dns_message_buildopt(message, &rdataset, version, udpsize,
- DNS_MESSAGEEXTFLAG_DO, ednsopts, count);
- if (result != ISC_R_SUCCESS) {
- return result;
- }
- return dns_message_setopt(message, rdataset);
-}
-
static void
fctx_setretryinterval(fetchctx_t *fctx, unsigned int rtt) {
unsigned int seconds, us;
dns_compress_t cctx;
bool useedns;
bool tcp = ((query->options & DNS_FETCHOPT_TCP) != 0);
- dns_ednsopt_t ednsopts[DNS_EDNSOPTIONS];
- unsigned int ednsopt = 0;
uint16_t hint = 0, udpsize = 0; /* No EDNS */
isc_sockaddr_t localaddr, *la = NULL;
#ifdef HAVE_DNSTAP
bool tcpkeepalive = false;
unsigned char cookie[COOKIE_BUFFER_SIZE];
uint16_t padding = 0;
+ dns_rdataset_t *rdataset = NULL;
/*
* Set the default UDP size to what was
if (NOCOOKIE(query->addrinfo)) {
sendcookie = false;
}
+
+ query->ednsversion = version;
+ dns_message_ednsinit(fctx->qmessage, version, udpsize,
+ DNS_MESSAGEEXTFLAG_DO, 0);
+
if (reqnsid) {
- INSIST(ednsopt < DNS_EDNSOPTIONS);
- ednsopts[ednsopt].code = DNS_OPT_NSID;
- ednsopts[ednsopt].length = 0;
- ednsopts[ednsopt].value = NULL;
- ednsopt++;
+ dns_ednsopt_t option = {
+ .code = DNS_OPT_NSID,
+ };
+ result = dns_message_ednsaddopt(fctx->qmessage,
+ &option);
+ if (result != ISC_R_SUCCESS) {
+ goto cleanup_message;
+ }
}
if (reqzoneversion) {
- INSIST(ednsopt < DNS_EDNSOPTIONS);
- ednsopts[ednsopt].code = DNS_OPT_ZONEVERSION;
- ednsopts[ednsopt].length = 0;
- ednsopts[ednsopt].value = NULL;
- ednsopt++;
+ dns_ednsopt_t option = {
+ .code = DNS_OPT_ZONEVERSION,
+ };
+ result = dns_message_ednsaddopt(fctx->qmessage,
+ &option);
+ if (result != ISC_R_SUCCESS) {
+ goto cleanup_message;
+ }
}
if (sendcookie) {
- INSIST(ednsopt < DNS_EDNSOPTIONS);
- ednsopts[ednsopt].code = DNS_OPT_COOKIE;
- ednsopts[ednsopt].length =
- (uint16_t)dns_adb_getcookie(
- query->addrinfo, cookie,
- sizeof(cookie));
- if (ednsopts[ednsopt].length != 0) {
- ednsopts[ednsopt].value = cookie;
+ dns_ednsopt_t option = {
+ .code = DNS_OPT_COOKIE,
+ };
+ option.length = (uint16_t)dns_adb_getcookie(
+ query->addrinfo, cookie,
+ sizeof(cookie));
+ if (option.length != 0) {
+ option.value = cookie;
inc_stats(
fctx->res,
dns_resstatscounter_cookieout);
} else {
compute_cc(query, cookie,
CLIENT_COOKIE_SIZE);
- ednsopts[ednsopt].value = cookie;
- ednsopts[ednsopt].length =
- CLIENT_COOKIE_SIZE;
+ option.value = cookie;
+ option.length = CLIENT_COOKIE_SIZE;
inc_stats(
fctx->res,
dns_resstatscounter_cookienew);
}
- ednsopt++;
+ result = dns_message_ednsaddopt(fctx->qmessage,
+ &option);
+ if (result != ISC_R_SUCCESS) {
+ goto cleanup_message;
+ }
}
/* Add TCP keepalive option if appropriate */
&tcpkeepalive);
}
if (tcpkeepalive) {
- INSIST(ednsopt < DNS_EDNSOPTIONS);
- ednsopts[ednsopt].code = DNS_OPT_TCP_KEEPALIVE;
- ednsopts[ednsopt].length = 0;
- ednsopts[ednsopt].value = NULL;
- ednsopt++;
+ dns_ednsopt_t option = {
+ .code = DNS_OPT_TCP_KEEPALIVE,
+ };
+ result = dns_message_ednsaddopt(fctx->qmessage,
+ &option);
+ if (result != ISC_R_SUCCESS) {
+ goto cleanup_message;
+ }
}
/* Add PAD for current peer? Require TCP for now
(void)dns_peer_getpadding(peer, &padding);
}
if (padding != 0) {
- INSIST(ednsopt < DNS_EDNSOPTIONS);
- ednsopts[ednsopt].code = DNS_OPT_PAD;
- ednsopts[ednsopt].length = 0;
- ednsopt++;
+ dns_ednsopt_t option = {
+ .code = DNS_OPT_PAD,
+ };
+ result = dns_message_ednsaddopt(fctx->qmessage,
+ &option);
+ if (result != ISC_R_SUCCESS) {
+ goto cleanup_message;
+ }
dns_message_setpadding(fctx->qmessage, padding);
}
- query->ednsversion = version;
- result = fctx_addopt(fctx->qmessage, version, udpsize,
- ednsopts, ednsopt);
+ result = dns_message_buildopt(fctx->qmessage,
+ &rdataset);
+ if (result == ISC_R_SUCCESS) {
+ result = dns_message_setopt(fctx->qmessage,
+ rdataset);
+ }
+
if (result == ISC_R_SUCCESS) {
if (reqnsid) {
query->options |= DNS_FETCHOPT_WANTNSID;
query->options |=
DNS_FETCHOPT_WANTZONEVERSION;
}
- } else if (result != ISC_R_SUCCESS) {
+ } else {
/*
* We couldn't add the OPT, but we'll
* press on. We're not using EDNS0, so
bool reqexpire) {
isc_result_t result;
dns_rdataset_t *rdataset = NULL;
- dns_ednsopt_t ednsopts[DNS_EDNSOPTIONS];
- int count = 0;
+
+ dns_message_ednsinit(message, 0, udpsize, 0, 0);
/* Set EDNS options if applicable. */
if (reqnsid) {
- INSIST(count < DNS_EDNSOPTIONS);
- ednsopts[count].code = DNS_OPT_NSID;
- ednsopts[count].length = 0;
- ednsopts[count].value = NULL;
- count++;
+ dns_ednsopt_t option = { .code = DNS_OPT_NSID };
+ result = dns_message_ednsaddopt(message, &option);
+ if (result != ISC_R_SUCCESS) {
+ return result;
+ }
}
if (reqexpire) {
- INSIST(count < DNS_EDNSOPTIONS);
- ednsopts[count].code = DNS_OPT_EXPIRE;
- ednsopts[count].length = 0;
- ednsopts[count].value = NULL;
- count++;
- }
- result = dns_message_buildopt(message, &rdataset, 0, udpsize, 0,
- ednsopts, count);
+ dns_ednsopt_t option = { .code = DNS_OPT_EXPIRE };
+ result = dns_message_ednsaddopt(message, &option);
+ if (result != ISC_R_SUCCESS) {
+ return result;
+ }
+ }
+
+ result = dns_message_buildopt(message, &rdataset);
if (result != ISC_R_SUCCESS) {
return result;
}
bool reqexpire) {
isc_result_t result;
dns_rdataset_t *rdataset = NULL;
- dns_ednsopt_t ednsopts[DNS_EDNSOPTIONS];
- int count = 0;
+
+ dns_message_ednsinit(message, 0, udpsize, 0, 0);
/* Set EDNS options if applicable. */
if (reqnsid) {
- INSIST(count < DNS_EDNSOPTIONS);
- ednsopts[count].code = DNS_OPT_NSID;
- ednsopts[count].length = 0;
- ednsopts[count].value = NULL;
- count++;
+ dns_ednsopt_t option = { .code = DNS_OPT_NSID };
+ result = dns_message_ednsaddopt(message, &option);
+ if (result != ISC_R_SUCCESS) {
+ return result;
+ }
}
if (reqexpire) {
- INSIST(count < DNS_EDNSOPTIONS);
- ednsopts[count].code = DNS_OPT_EXPIRE;
- ednsopts[count].length = 0;
- ednsopts[count].value = NULL;
- count++;
+ dns_ednsopt_t option = { .code = DNS_OPT_EXPIRE };
+ result = dns_message_ednsaddopt(message, &option);
+ if (result != ISC_R_SUCCESS) {
+ return result;
+ }
}
- result = dns_message_buildopt(message, &rdataset, 0, udpsize, 0,
- ednsopts, count);
+
+ result = dns_message_buildopt(message, &rdataset);
if (result != ISC_R_SUCCESS) {
return result;
}
ns_client_addopt(ns_client_t *client, dns_message_t *message,
dns_rdataset_t **opt) {
unsigned char ecs[ECS_SIZE];
- char nsid[_POSIX_HOST_NAME_MAX + 1], *nsidp = NULL;
unsigned char cookie[COOKIE_SIZE];
isc_result_t result;
dns_view_t *view = NULL;
uint16_t udpsize;
- dns_ednsopt_t ednsopts[DNS_EDNSOPTIONS];
- int count = 0;
unsigned int flags;
unsigned char expire[4];
unsigned char advtimo[2];
flags = client->inner.extflags & DNS_MESSAGEEXTFLAG_REPLYPRESERVE;
+ dns_message_ednsinit(message, 0, udpsize, flags, 0);
+
/* Set EDNS options if applicable */
if (WANTNSID(client)) {
+ char nsid[_POSIX_HOST_NAME_MAX + 1];
+ char *nsidp = NULL;
+
if (client->manager->sctx->server_id != NULL) {
nsidp = client->manager->sctx->server_id;
- } else if (client->manager->sctx->usehostname) {
- if (gethostname(nsid, sizeof(nsid)) != 0) {
- goto no_nsid;
- }
+ } else if (client->manager->sctx->usehostname &&
+ gethostname(nsid, sizeof(nsid)) == 0)
+ {
nsidp = nsid;
- } else {
- goto no_nsid;
}
-
- INSIST(count < DNS_EDNSOPTIONS);
- ednsopts[count].code = DNS_OPT_NSID;
- ednsopts[count].length = (uint16_t)strlen(nsidp);
- ednsopts[count].value = (unsigned char *)nsidp;
- count++;
+ if (nsidp != NULL) {
+ dns_ednsopt_t option = {
+ .code = DNS_OPT_NSID,
+ .value = (unsigned char *)nsidp,
+ .length = (uint16_t)strlen(nsidp),
+ };
+ result = dns_message_ednsaddopt(message, &option);
+ if (result != ISC_R_SUCCESS) {
+ return result;
+ }
+ }
}
-no_nsid:
+
if ((client->inner.attributes & NS_CLIENTATTR_WANTCOOKIE) != 0) {
isc_buffer_t buf;
isc_stdtime_t now = isc_stdtime_now();
compute_cookie(client, now, client->manager->sctx->secret,
&buf);
- INSIST(count < DNS_EDNSOPTIONS);
- ednsopts[count].code = DNS_OPT_COOKIE;
- ednsopts[count].length = COOKIE_SIZE;
- ednsopts[count].value = cookie;
- count++;
+ dns_ednsopt_t option = { .code = DNS_OPT_COOKIE,
+ .length = COOKIE_SIZE,
+ .value = cookie };
+ result = dns_message_ednsaddopt(message, &option);
+ if (result != ISC_R_SUCCESS) {
+ return result;
+ }
}
+
if ((client->inner.attributes & NS_CLIENTATTR_HAVEEXPIRE) != 0) {
isc_buffer_t buf;
- INSIST(count < DNS_EDNSOPTIONS);
-
isc_buffer_init(&buf, expire, sizeof(expire));
isc_buffer_putuint32(&buf, client->inner.expire);
- ednsopts[count].code = DNS_OPT_EXPIRE;
- ednsopts[count].length = 4;
- ednsopts[count].value = expire;
- count++;
+
+ dns_ednsopt_t option = { .code = DNS_OPT_EXPIRE,
+ .value = expire,
+ .length = 4 };
+ result = dns_message_ednsaddopt(message, &option);
+ if (result != ISC_R_SUCCESS) {
+ return result;
+ }
}
+
if (((client->inner.attributes & NS_CLIENTATTR_HAVEECS) != 0) &&
(client->inner.ecs.addr.family == AF_INET ||
client->inner.ecs.addr.family == AF_INET6 ||
isc_buffer_putmem(&buf, addr, (unsigned int)addrl);
}
- ednsopts[count].code = DNS_OPT_CLIENT_SUBNET;
- ednsopts[count].length = addrl + 4;
- ednsopts[count].value = ecs;
- count++;
+ dns_ednsopt_t option = { .code = DNS_OPT_CLIENT_SUBNET,
+ .length = addrl + 4,
+ .value = ecs };
+ result = dns_message_ednsaddopt(message, &option);
+ if (result != ISC_R_SUCCESS) {
+ return result;
+ }
}
+
if (TCP_CLIENT(client) && USEKEEPALIVE(client)) {
- isc_buffer_t buf;
uint32_t advertised_timeout = isc_nm_getadvertisedtimeout();
-
- INSIST(count < DNS_EDNSOPTIONS);
+ isc_buffer_t buf;
advertised_timeout /= 100; /* units of 100 milliseconds */
isc_buffer_init(&buf, advtimo, sizeof(advtimo));
isc_buffer_putuint16(&buf, (uint16_t)advertised_timeout);
- ednsopts[count].code = DNS_OPT_TCP_KEEPALIVE;
- ednsopts[count].length = 2;
- ednsopts[count].value = advtimo;
- count++;
+
+ dns_ednsopt_t option = { .code = DNS_OPT_TCP_KEEPALIVE,
+ .length = 2,
+ .value = advtimo };
+ result = dns_message_ednsaddopt(message, &option);
+ if (result != ISC_R_SUCCESS) {
+ return result;
+ }
}
for (size_t i = 0; i < DNS_EDE_MAX_ERRORS; i++) {
break;
}
- INSIST(count < DNS_EDNSOPTIONS);
- ednsopts[count].code = DNS_OPT_EDE;
- ednsopts[count].length = ede->length;
- ednsopts[count].value = ede->value;
- count++;
+ dns_ednsopt_t option = { .code = DNS_OPT_EDE,
+ .length = ede->length,
+ .value = ede->value };
+ result = dns_message_ednsaddopt(message, &option);
+ if (result != ISC_R_SUCCESS) {
+ return result;
+ }
}
if ((client->inner.attributes & NS_CLIENTATTR_HAVEZONEVERSION) != 0) {
- INSIST(count < DNS_EDNSOPTIONS);
- ednsopts[count].code = DNS_OPT_ZONEVERSION;
- ednsopts[count].length = client->inner.zoneversionlength;
- ednsopts[count].value = client->inner.zoneversion;
- count++;
+ dns_ednsopt_t option = {
+ .code = DNS_OPT_ZONEVERSION,
+ .length = client->inner.zoneversionlength,
+ .value = client->inner.zoneversion
+ };
+ result = dns_message_ednsaddopt(message, &option);
+ if (result != ISC_R_SUCCESS) {
+ return result;
+ }
}
if (WANTRC(client)) {
rad = &client->inner.rad;
}
if (rad != NULL && !dns_name_equal(rad, dns_rootname)) {
- INSIST(count < DNS_EDNSOPTIONS);
- ednsopts[count].code = DNS_OPT_REPORT_CHANNEL;
- ednsopts[count].length = rad->length;
- ednsopts[count].value = rad->ndata;
- count++;
+ dns_ednsopt_t option = {
+ .code = DNS_OPT_REPORT_CHANNEL,
+ .length = rad->length,
+ .value = rad->ndata,
+ };
+ result = dns_message_ednsaddopt(message, &option);
+ if (result != ISC_R_SUCCESS) {
+ return result;
+ }
}
}
result = dns_acl_match(&netaddr, NULL, view->pad_acl, env,
&match, NULL);
if (result == ISC_R_SUCCESS && match > 0) {
- INSIST(count < DNS_EDNSOPTIONS);
-
- ednsopts[count].code = DNS_OPT_PAD;
- ednsopts[count].length = 0;
- ednsopts[count].value = NULL;
- count++;
-
+ dns_ednsopt_t option = { .code = DNS_OPT_PAD };
+ /* This can fail harmlessly */
+ dns_message_ednsaddopt(message, &option);
dns_message_setpadding(message, view->padding);
}
}
- result = dns_message_buildopt(message, opt, 0, udpsize, flags, ednsopts,
- count);
+ result = dns_message_buildopt(message, opt);
return result;
}