summaryrefslogtreecommitdiff
path: root/lib/dns/resolver.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/dns/resolver.c')
-rw-r--r--lib/dns/resolver.c148
1 files changed, 60 insertions, 88 deletions
diff --git a/lib/dns/resolver.c b/lib/dns/resolver.c
index e19659ff..10d1f75f 100644
--- a/lib/dns/resolver.c
+++ b/lib/dns/resolver.c
@@ -134,6 +134,7 @@
* Maximum EDNS0 input packet size.
*/
#define RECV_BUFFER_SIZE 4096 /* XXXRTH Constant. */
+#define EDNSOPTS 2
/*%
* This defines the maximum number of timeouts we will permit before we
@@ -1278,67 +1279,15 @@ resquery_senddone(isc_task_t *task, isc_event_t *event) {
static inline isc_result_t
fctx_addopt(dns_message_t *message, unsigned int version,
- isc_uint16_t udpsize, isc_boolean_t request_nsid)
+ isc_uint16_t udpsize, dns_ednsopt_t *ednsopts, size_t count)
{
- dns_rdataset_t *rdataset;
- dns_rdatalist_t *rdatalist;
- dns_rdata_t *rdata;
+ dns_rdataset_t *rdataset = NULL;
isc_result_t result;
- rdatalist = NULL;
- result = dns_message_gettemprdatalist(message, &rdatalist);
- if (result != ISC_R_SUCCESS)
- return (result);
- rdata = NULL;
- result = dns_message_gettemprdata(message, &rdata);
- if (result != ISC_R_SUCCESS)
- return (result);
- rdataset = NULL;
- result = dns_message_gettemprdataset(message, &rdataset);
+ result = dns_message_buildopt(message, &rdataset, version, udpsize,
+ DNS_MESSAGEEXTFLAG_DO, ednsopts, count);
if (result != ISC_R_SUCCESS)
return (result);
- dns_rdataset_init(rdataset);
-
- rdatalist->type = dns_rdatatype_opt;
- rdatalist->covers = 0;
-
- /*
- * Set Maximum UDP buffer size.
- */
- rdatalist->rdclass = udpsize;
-
- /*
- * Set EXTENDED-RCODE and Z to 0, DO to 1.
- */
- rdatalist->ttl = (version << 16);
- rdatalist->ttl |= DNS_MESSAGEEXTFLAG_DO;
-
- /*
- * Set EDNS options if applicable
- */
- if (request_nsid) {
- /* Send empty NSID option (RFC5001) */
- unsigned char data[4];
- isc_buffer_t buf;
-
- isc_buffer_init(&buf, data, sizeof(data));
- isc_buffer_putuint16(&buf, DNS_OPT_NSID);
- isc_buffer_putuint16(&buf, 0);
- rdata->data = data;
- rdata->length = sizeof(data);
- } else {
- rdata->data = NULL;
- rdata->length = 0;
- }
-
- rdata->rdclass = rdatalist->rdclass;
- rdata->type = rdatalist->type;
- rdata->flags = 0;
-
- ISC_LIST_INIT(rdatalist->rdata);
- ISC_LIST_APPEND(rdatalist->rdata, rdata, link);
- RUNTIME_CHECK(dns_rdatalist_tordataset(rdatalist, rdataset) == ISC_R_SUCCESS);
-
return (dns_message_setopt(message, rdataset));
}
@@ -1720,6 +1669,8 @@ resquery_send(resquery_t *query) {
isc_boolean_t cleanup_cctx = ISC_FALSE;
isc_boolean_t secure_domain;
isc_boolean_t connecting = ISC_FALSE;
+ dns_ednsopt_t ednsopts[EDNSOPTS];
+ unsigned ednsopt = 0;
fctx = query->fctx;
QTRACE("send");
@@ -1902,8 +1853,15 @@ resquery_send(resquery_t *query) {
/* request NSID for current view or peer? */
if (peer != NULL)
(void) dns_peer_getrequestnsid(peer, &reqnsid);
+ if (reqnsid) {
+ INSIST(ednsopt < EDNSOPTS);
+ ednsopts[ednsopt].code = DNS_OPT_NSID;
+ ednsopts[ednsopt].length = 0;
+ ednsopts[ednsopt].value = NULL;
+ ednsopt++;
+ }
result = fctx_addopt(fctx->qmessage, version,
- udpsize, reqnsid);
+ udpsize, ednsopts, ednsopt);
if (reqnsid && result == ISC_R_SUCCESS) {
query->options |= DNS_FETCHOPT_WANTNSID;
} else if (result != ISC_R_SUCCESS) {
@@ -6670,44 +6628,24 @@ checknames(dns_message_t *message) {
/*
* Log server NSID at log level 'level'
*/
-static isc_result_t
-log_nsid(dns_rdataset_t *opt, resquery_t *query, int level, isc_mem_t *mctx)
+static void
+log_nsid(isc_buffer_t *opt, size_t nsid_len, resquery_t *query,
+ int level, isc_mem_t *mctx)
{
static const char hex[17] = "0123456789abcdef";
char addrbuf[ISC_SOCKADDR_FORMATSIZE];
- isc_uint16_t optcode, nsid_len, buflen, i;
- isc_result_t result;
- isc_buffer_t nsidbuf;
- dns_rdata_t rdata;
+ isc_uint16_t buflen, i;
unsigned char *p, *buf, *nsid;
- /* Extract rdata from OPT rdataset */
- result = dns_rdataset_first(opt);
- if (result != ISC_R_SUCCESS)
- return (ISC_R_FAILURE);
-
- dns_rdata_init(&rdata);
- dns_rdataset_current(opt, &rdata);
- if (rdata.length < 4)
- return (ISC_R_FAILURE);
-
- /* Check for NSID */
- isc_buffer_init(&nsidbuf, rdata.data, rdata.length);
- isc_buffer_add(&nsidbuf, rdata.length);
- optcode = isc_buffer_getuint16(&nsidbuf);
- nsid_len = isc_buffer_getuint16(&nsidbuf);
- if (optcode != DNS_OPT_NSID || nsid_len == 0)
- return (ISC_R_FAILURE);
-
/* Allocate buffer for storing hex version of the NSID */
buflen = nsid_len * 2 + 1;
buf = isc_mem_get(mctx, buflen);
if (buf == NULL)
- return (ISC_R_NOSPACE);
+ return;
/* Convert to hex */
p = buf;
- nsid = rdata.data + 4;
+ nsid = isc_buffer_current(opt);
for (i = 0; i < nsid_len; i++) {
*p++ = hex[(nsid[0] >> 4) & 0xf];
*p++ = hex[nsid[0] & 0xf];
@@ -6723,7 +6661,7 @@ log_nsid(dns_rdataset_t *opt, resquery_t *query, int level, isc_mem_t *mctx)
/* Clean up */
isc_mem_put(mctx, buf, buflen);
- return (ISC_R_SUCCESS);
+ return;
}
static void
@@ -6797,6 +6735,41 @@ betterreferral(fetchctx_t *fctx) {
}
static void
+process_opt(resquery_t *query, dns_rdataset_t *opt) {
+ dns_rdata_t rdata;
+ isc_buffer_t optbuf;
+ isc_result_t result;
+ isc_uint16_t optcode;
+ isc_uint16_t optlen;
+
+ result = dns_rdataset_first(opt);
+ if (result == ISC_R_SUCCESS) {
+ dns_rdata_init(&rdata);
+ dns_rdataset_current(opt, &rdata);
+ isc_buffer_init(&optbuf, rdata.data, rdata.length);
+ isc_buffer_add(&optbuf, rdata.length);
+ while (isc_buffer_remaininglength(&optbuf) >= 4) {
+ optcode = isc_buffer_getuint16(&optbuf);
+ optlen = isc_buffer_getuint16(&optbuf);
+ INSIST(optlen <= isc_buffer_remaininglength(&optbuf));
+ switch (optcode) {
+ case DNS_OPT_NSID:
+ if (query->options & DNS_FETCHOPT_WANTNSID)
+ log_nsid(&optbuf, optlen, query,
+ ISC_LOG_INFO,
+ query->fctx->res->mctx);
+ isc_buffer_forward(&optbuf, optlen);
+ break;
+ default:
+ isc_buffer_forward(&optbuf, optlen);
+ break;
+ }
+ }
+ INSIST(isc_buffer_remaininglength(&optbuf) == 0U);
+ }
+}
+
+static void
resquery_response(isc_task_t *task, isc_event_t *event) {
isc_result_t result = ISC_R_SUCCESS;
resquery_t *query = event->ev_arg;
@@ -6986,12 +6959,11 @@ resquery_response(isc_task_t *task, isc_event_t *event) {
log_packet(message, ISC_LOG_DEBUG(10), fctx->res->mctx);
/*
- * Did we request NSID? If so, and if the response contains
- * NSID data, log it at INFO level.
+ * Process receive opt record.
*/
opt = dns_message_getopt(message);
- if (opt != NULL && (query->options & DNS_FETCHOPT_WANTNSID) != 0)
- log_nsid(opt, query, ISC_LOG_INFO, fctx->res->mctx);
+ if (opt != NULL)
+ process_opt(query, opt);
/*
* If the message is signed, check the signature. If not, this