From 3b0a0dfcfbe03d7926375d92b086a83838a75287 Mon Sep 17 00:00:00 2001 From: Mukund Sivaraman 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 061a023..e160a19 100644 --- a/dns.c +++ b/dns.c @@ -301,7 +301,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) { @@ -320,7 +323,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 */ @@ -805,6 +863,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; @@ -832,7 +892,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 5f86c32..dee3b7b 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); -- GitLab