summaryrefslogtreecommitdiff
path: root/bin/named/client.c
diff options
context:
space:
mode:
Diffstat (limited to 'bin/named/client.c')
-rw-r--r--bin/named/client.c227
1 files changed, 97 insertions, 130 deletions
diff --git a/bin/named/client.c b/bin/named/client.c
index ff4ab691c184..4cc814efc0ba 100644
--- a/bin/named/client.c
+++ b/bin/named/client.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004-2012 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2013 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1999-2003 Internet Software Consortium.
*
* Permission to use, copy, modify, and/or distribute this software for any
@@ -972,6 +972,7 @@ ns_client_send(ns_client_t *client) {
result = dns_compress_init(&cctx, -1, client->mctx);
if (result != ISC_R_SUCCESS)
goto done;
+ dns_compress_setsensitive(&cctx, ISC_TRUE);
cleanup_cctx = ISC_TRUE;
result = dns_message_renderbegin(client->message, &cctx, &buffer);
@@ -1188,62 +1189,30 @@ ns_client_error(ns_client_t *client, isc_result_t result) {
static inline isc_result_t
client_addopt(ns_client_t *client) {
- dns_rdataset_t *rdataset;
- dns_rdatalist_t *rdatalist;
- dns_rdata_t *rdata;
+ char nsid[BUFSIZ], *nsidp;
isc_result_t result;
dns_view_t *view;
dns_resolver_t *resolver;
isc_uint16_t udpsize;
+ dns_ednsopt_t ednsopts[2];
+ int count = 0;
+ unsigned int flags;
REQUIRE(client->opt == NULL); /* XXXRTH free old. */
- rdatalist = NULL;
- result = dns_message_gettemprdatalist(client->message, &rdatalist);
- if (result != ISC_R_SUCCESS)
- return (result);
- rdata = NULL;
- result = dns_message_gettemprdata(client->message, &rdata);
- if (result != ISC_R_SUCCESS)
- return (result);
- rdataset = NULL;
- result = dns_message_gettemprdataset(client->message, &rdataset);
- if (result != ISC_R_SUCCESS)
- return (result);
- dns_rdataset_init(rdataset);
-
- rdatalist->type = dns_rdatatype_opt;
- rdatalist->covers = 0;
-
- /*
- * Set the maximum UDP buffer size.
- */
view = client->view;
resolver = (view != NULL) ? view->resolver : NULL;
if (resolver != NULL)
udpsize = dns_resolver_getudpsize(resolver);
else
udpsize = ns_g_udpsize;
- rdatalist->rdclass = udpsize;
- /*
- * Set EXTENDED-RCODE, VERSION and Z to 0.
- */
- rdatalist->ttl = (client->extflags & DNS_MESSAGEEXTFLAG_REPLYPRESERVE);
+ flags = client->extflags & DNS_MESSAGEEXTFLAG_REPLYPRESERVE;
/* Set EDNS options if applicable */
- if (client->attributes & NS_CLIENTATTR_WANTNSID &&
+ if ((client->attributes & NS_CLIENTATTR_WANTNSID) != 0 &&
(ns_g_server->server_id != NULL ||
ns_g_server->server_usehostname)) {
- /*
- * Space required for NSID data:
- * 2 bytes for opt code
- * + 2 bytes for NSID length
- * + NSID itself
- */
- char nsid[BUFSIZ], *nsidp;
- isc_buffer_t *buffer = NULL;
-
if (ns_g_server->server_usehostname) {
isc_result_t result;
result = ns_os_gethostname(nsid, sizeof(nsid));
@@ -1254,35 +1223,15 @@ client_addopt(ns_client_t *client) {
} else
nsidp = ns_g_server->server_id;
- rdata->length = strlen(nsidp) + 4;
- result = isc_buffer_allocate(client->mctx, &buffer,
- rdata->length);
- if (result != ISC_R_SUCCESS)
- goto no_nsid;
-
- isc_buffer_putuint16(buffer, DNS_OPT_NSID);
- isc_buffer_putuint16(buffer, strlen(nsidp));
- isc_buffer_putstr(buffer, nsidp);
- rdata->data = buffer->base;
- dns_message_takebuffer(client->message, &buffer);
- } else {
-no_nsid:
- rdata->data = NULL;
- rdata->length = 0;
+ ednsopts[count].code = DNS_OPT_NSID;
+ ednsopts[count].length = strlen(nsidp);
+ ednsopts[count].value = (unsigned char *)nsidp;
+ count++;
}
-
- 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);
-
- client->opt = rdataset;
-
- return (ISC_R_SUCCESS);
+ no_nsid:
+ result = dns_message_buildopt(client->message, &client->opt, 0,
+ udpsize, flags, ednsopts, count);
+ return (result);
}
static inline isc_boolean_t
@@ -1363,6 +1312,83 @@ ns_client_isself(dns_view_t *myview, dns_tsigkey_t *mykey,
return (ISC_TF(view == myview));
}
+static isc_result_t
+process_opt(ns_client_t *client, dns_rdataset_t *opt) {
+ dns_rdata_t rdata;
+ isc_buffer_t optbuf;
+ isc_result_t result;
+ isc_uint16_t optcode;
+ isc_uint16_t optlen;
+
+ /*
+ * Set the client's UDP buffer size.
+ */
+ client->udpsize = opt->rdclass;
+
+ /*
+ * If the requested UDP buffer size is less than 512,
+ * ignore it and use 512.
+ */
+ if (client->udpsize < 512)
+ client->udpsize = 512;
+
+ /*
+ * Get the flags out of the OPT record.
+ */
+ client->extflags = (isc_uint16_t)(opt->ttl & 0xFFFF);
+
+ /*
+ * Do we understand this version of EDNS?
+ *
+ * XXXRTH need library support for this!
+ */
+ client->ednsversion = (opt->ttl & 0x00FF0000) >> 16;
+ if (client->ednsversion > 0) {
+ isc_stats_increment(ns_g_server->nsstats,
+ dns_nsstatscounter_badednsver);
+ result = client_addopt(client);
+ if (result == ISC_R_SUCCESS)
+ result = DNS_R_BADVERS;
+ ns_client_error(client, result);
+ goto cleanup;
+ }
+
+ /* Check for NSID request */
+ 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);
+ switch (optcode) {
+ case DNS_OPT_NSID:
+ client->attributes |= NS_CLIENTATTR_WANTNSID;
+ isc_buffer_forward(&optbuf, optlen);
+ break;
+ default:
+ isc_buffer_forward(&optbuf, optlen);
+ break;
+ }
+ }
+ }
+
+ isc_stats_increment(ns_g_server->nsstats, dns_nsstatscounter_edns0in);
+
+ /*
+ * Create an OPT for our reply.
+ */
+ result = client_addopt(client);
+ if (result != ISC_R_SUCCESS) {
+ ns_client_error(client, result);
+ goto cleanup;
+ }
+ cleanup:
+ return (result);
+}
+
/*
* Handle an incoming request event from the socket (UDP case)
* or tcpmsg (TCP case).
@@ -1384,8 +1410,6 @@ client_request(isc_task_t *task, isc_event_t *event) {
dns_messageid_t id;
unsigned int flags;
isc_boolean_t notimp;
- dns_rdata_t rdata;
- isc_uint16_t optcode;
REQUIRE(event != NULL);
client = event->ev_arg;
@@ -1585,67 +1609,9 @@ client_request(isc_task_t *task, isc_event_t *event) {
*/
opt = dns_message_getopt(client->message);
if (opt != NULL) {
- /*
- * Set the client's UDP buffer size.
- */
- client->udpsize = opt->rdclass;
-
- /*
- * If the requested UDP buffer size is less than 512,
- * ignore it and use 512.
- */
- if (client->udpsize < 512)
- client->udpsize = 512;
-
- /*
- * Get the flags out of the OPT record.
- */
- client->extflags = (isc_uint16_t)(opt->ttl & 0xFFFF);
-
- /*
- * Do we understand this version of EDNS?
- *
- * XXXRTH need library support for this!
- */
- client->ednsversion = (opt->ttl & 0x00FF0000) >> 16;
- if (client->ednsversion > 0) {
- isc_stats_increment(ns_g_server->nsstats,
- dns_nsstatscounter_badednsver);
- result = client_addopt(client);
- if (result == ISC_R_SUCCESS)
- result = DNS_R_BADVERS;
- ns_client_error(client, result);
- goto cleanup;
- }
-
- /* Check for NSID request */
- result = dns_rdataset_first(opt);
- if (result == ISC_R_SUCCESS) {
- dns_rdata_init(&rdata);
- dns_rdataset_current(opt, &rdata);
- if (rdata.length >= 2) {
- isc_buffer_t nsidbuf;
- isc_buffer_init(&nsidbuf,
- rdata.data, rdata.length);
- isc_buffer_add(&nsidbuf, rdata.length);
- optcode = isc_buffer_getuint16(&nsidbuf);
- if (optcode == DNS_OPT_NSID)
- client->attributes |=
- NS_CLIENTATTR_WANTNSID;
- }
- }
-
- isc_stats_increment(ns_g_server->nsstats,
- dns_nsstatscounter_edns0in);
-
- /*
- * Create an OPT for our reply.
- */
- result = client_addopt(client);
- if (result != ISC_R_SUCCESS) {
- ns_client_error(client, result);
+ result = process_opt(client, opt);
+ if (result != ISC_R_SUCCESS)
goto cleanup;
- }
}
if (client->message->rdclass == 0) {
@@ -2691,7 +2657,8 @@ ns_client_checkacl(ns_client_t *client, isc_sockaddr_t *sockaddr,
static void
ns_client_name(ns_client_t *client, char *peerbuf, size_t len) {
if (client->peeraddr_valid)
- isc_sockaddr_format(&client->peeraddr, peerbuf, len);
+ isc_sockaddr_format(&client->peeraddr, peerbuf,
+ (unsigned int)len);
else
snprintf(peerbuf, len, "@%p", client);
}