From 08c78a932f4fd19039d2d2cf1cb90f2390fac6e8 Mon Sep 17 00:00:00 2001
From: Mukund Sivaraman <muks@isc.org>
Date: Fri, 9 Sep 2016 13:34:13 +0530
Subject: [PATCH] Add support for sending EDNS CLIENT-SUBNET option in queries
to dnsperf and resperf (#42899)
---
dns.c | 66 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---
dns.h | 2 ++
dnsperf.c | 21 ++++++++++++++++++--
resperf.c | 18 +++++++++++++++--
4 files changed, 100 insertions(+), 7 deletions(-)
diff --git a/dns.c b/dns.c
index bfa2fa5..6e841ad 100644
--- a/dns.c
+++ b/dns.c
@@ -302,7 +302,10 @@ perf_dns_destroytsigkey(perf_dnstsigkey_t **tsigkeyp)
* Appends an OPT record to the packet.
*/
static isc_result_t
-add_edns(isc_buffer_t *packet, bool dnssec) {
+add_edns(isc_buffer_t *packet, bool dnssec,
+ bool ecs_zero, bool ecs_fixed,
+ bool ecs_random)
+{
unsigned char *base;
if (isc_buffer_availablelength(packet) < EDNSLEN) {
@@ -321,7 +324,62 @@ add_edns(isc_buffer_t *packet, bool dnssec) {
isc_buffer_putuint16(packet, 0x8000);
else
isc_buffer_putuint16(packet, 0);
- isc_buffer_putuint16(packet, 0); /* rdlen */
+ if (!ecs_zero && !ecs_fixed && !ecs_random) {
+ isc_buffer_putuint16(packet, 0); /* rdlen */
+ } else {
+ if (ecs_zero) {
+ /* rdlen */
+ isc_buffer_putuint16(packet, 8);
+ /* CLIENT-SUBNET option code */
+ isc_buffer_putuint16(packet, 0x0008);
+ /* CLIENT-SUBNET option length */
+ isc_buffer_putuint16(packet, 4);
+ /* FAMILY=IPv4 */
+ isc_buffer_putuint16(packet, 0x0001);
+ /* SOURCE PREFIX-LENGTH=0 */
+ isc_buffer_putuint8(packet, 0);
+ /* SCOPE PREFIX-LENGTH=0 */
+ isc_buffer_putuint8(packet, 0);
+ } else if (ecs_fixed) {
+ /* rdlen */
+ isc_buffer_putuint16(packet, 11);
+ /* CLIENT-SUBNET option code */
+ isc_buffer_putuint16(packet, 0x0008);
+ /* CLIENT-SUBNET option length */
+ isc_buffer_putuint16(packet, 7);
+ /* FAMILY=IPv4 */
+ isc_buffer_putuint16(packet, 0x0001);
+ /* SOURCE PREFIX-LENGTH=24 */
+ isc_buffer_putuint8(packet, 24);
+ /* SCOPE PREFIX-LENGTH=0 */
+ isc_buffer_putuint8(packet, 0);
+ isc_buffer_putuint8(packet, 149);
+ isc_buffer_putuint8(packet, 20);
+ isc_buffer_putuint8(packet, 64);
+ } else {
+ unsigned long r;
+
+ /* rdlen */
+ isc_buffer_putuint16(packet, 11);
+ /* CLIENT-SUBNET option code */
+ isc_buffer_putuint16(packet, 0x0008);
+ /* CLIENT-SUBNET option length */
+ isc_buffer_putuint16(packet, 7);
+ /* FAMILY=IPv4 */
+ isc_buffer_putuint16(packet, 0x0001);
+ /* SOURCE PREFIX-LENGTH=24 */
+ isc_buffer_putuint8(packet, 24);
+ /* SCOPE PREFIX-LENGTH=0 */
+ isc_buffer_putuint8(packet, 0);
+
+ r = (unsigned long) random();
+ isc_buffer_putuint8(packet, r & 0xff);
+ r >>= 8;
+ isc_buffer_putuint8(packet, r & 0xff);
+ r >>= 8;
+ isc_buffer_putuint8(packet, r & 0xff);
+ }
+ }
base[11]++; /* increment record count */
@@ -808,6 +866,8 @@ isc_result_t
perf_dns_buildrequest(perf_dnsctx_t *ctx, const isc_textregion_t *record,
uint16_t qid,
bool edns, bool dnssec,
+ bool ecs_zero, bool ecs_fixed,
+ bool ecs_random,
perf_dnstsigkey_t *tsigkey, isc_buffer_t *msg)
{
unsigned int flags;
@@ -835,7 +895,7 @@ perf_dns_buildrequest(perf_dnsctx_t *ctx, const isc_textregion_t *record,
return (result);
if (edns) {
- result = add_edns(msg, dnssec);
+ result = add_edns(msg, dnssec, ecs_zero, ecs_fixed, ecs_random);
if (result != ISC_R_SUCCESS)
return (result);
}
diff --git a/dns.h b/dns.h
index 5d5583f..2f223b9 100644
--- a/dns.h
+++ b/dns.h
@@ -64,6 +64,8 @@ isc_result_t
perf_dns_buildrequest(perf_dnsctx_t *ctx, const isc_textregion_t *record,
uint16_t qid,
bool edns, bool dnssec,
+ bool ecs_zero, bool ecs_fixed,
+ bool ecs_random,
perf_dnstsigkey_t *tsigkey, isc_buffer_t *msg);
#endif
diff --git a/dnsperf.c b/dnsperf.c
index 3b1e602..8a694f8 100644
--- a/dnsperf.c
+++ b/dnsperf.c
@@ -103,6 +103,9 @@ typedef struct {
uint32_t bufsize;
bool edns;
bool dnssec;
+ bool ecs_zero;
+ bool ecs_fixed;
+ bool ecs_random;
perf_dnstsigkey_t *tsigkey;
uint32_t max_outstanding;
uint32_t max_qps;
@@ -446,6 +449,15 @@ setup(int argc, char **argv, config_t *config)
perf_opt_add('D', perf_opt_boolean, NULL,
"set the DNSSEC OK bit (implies EDNS)", NULL,
&config->dnssec);
+ perf_opt_add('X', perf_opt_boolean, NULL,
+ "send 0/0 in EDNS CLIENT-SUBNET option", NULL,
+ &config->ecs_zero);
+ perf_opt_add('Y', perf_opt_boolean, NULL,
+ "send 149.20.64.0/24 in EDNS CLIENT-SUBNET option", NULL,
+ &config->ecs_fixed);
+ perf_opt_add('Z', perf_opt_boolean, NULL,
+ "send random/24 in EDNS CLIENT-SUBNET option", NULL,
+ &config->ecs_random);
perf_opt_add('y', perf_opt_string, "[alg:]name:secret",
"the TSIG algorithm, name and secret", NULL,
&tsigkey);
@@ -481,7 +493,8 @@ setup(int argc, char **argv, config_t *config)
config->maxruns = 1;
perf_datafile_setmaxruns(input, config->maxruns);
- if (config->dnssec)
+ if (config->dnssec || config->ecs_zero || config->ecs_fixed ||
+ config->ecs_random)
config->edns = true;
if (tsigkey != NULL)
@@ -645,7 +658,11 @@ do_send(void *arg)
result = perf_dns_buildrequest(tinfo->dnsctx,
(isc_textregion_t *) &used,
qid, config->edns,
- config->dnssec, config->tsigkey,
+ config->dnssec,
+ config->ecs_zero,
+ config->ecs_fixed,
+ config->ecs_random,
+ config->tsigkey,
&msg);
if (result != ISC_R_SUCCESS) {
LOCK(&tinfo->lock);
diff --git a/resperf.c b/resperf.c
index a4f6555..12b254d 100644
--- a/resperf.c
+++ b/resperf.c
@@ -110,6 +110,9 @@ static int *socks;
static uint64_t query_timeout;
static bool edns;
static bool dnssec;
+static bool ecs_zero;
+static bool ecs_fixed;
+static bool ecs_random;
static perf_datafile_t *input;
@@ -271,6 +274,15 @@ setup(int argc, char **argv)
"enable EDNS 0", NULL, &edns);
perf_opt_add('D', perf_opt_boolean, NULL,
"set the DNSSEC OK bit (implies EDNS)", NULL, &dnssec);
+ perf_opt_add('X', perf_opt_boolean, NULL,
+ "send 0/0 in EDNS CLIENT-SUBNET option", NULL,
+ &ecs_zero);
+ perf_opt_add('Y', perf_opt_boolean, NULL,
+ "send 149.20.64.0/24 in EDNS CLIENT-SUBNET option", NULL,
+ &ecs_fixed);
+ perf_opt_add('Z', perf_opt_boolean, NULL,
+ "send random/24 in EDNS CLIENT-SUBNET option", NULL,
+ &ecs_random);
perf_opt_add('y', perf_opt_string, "[alg:]name:secret",
"the TSIG algorithm, name and secret", NULL,
&tsigkey_str);
@@ -329,7 +341,7 @@ setup(int argc, char **argv)
input = perf_datafile_open(mctx, filename);
- if (dnssec)
+ if (dnssec || ecs_zero || ecs_fixed || ecs_random)
edns = true;
if (tsigkey_str != NULL)
@@ -476,7 +488,9 @@ do_one_line(isc_buffer_t *lines, isc_buffer_t *msg) {
isc_buffer_clear(msg);
result = perf_dns_buildrequest(NULL, (isc_textregion_t *) &used,
- qid, edns, dnssec, tsigkey, msg);
+ qid, edns, dnssec,
+ ecs_zero, ecs_fixed, ecs_random,
+ tsigkey, msg);
if (result != ISC_R_SUCCESS)
return (result);
--
2.14.5