bin/173118: Add EDNS Client Subnet support to BIND dig (patch included)
Steven Hartland
steven.hartland at multiplay.co.uk
Fri Oct 26 09:10:01 UTC 2012
>Number: 173118
>Category: bin
>Synopsis: Add EDNS Client Subnet support to BIND dig (patch included)
>Confidential: no
>Severity: non-critical
>Priority: low
>Responsible: freebsd-bugs
>State: open
>Quarter:
>Keywords:
>Date-Required:
>Class: update
>Submitter-Id: current-users
>Arrival-Date: Fri Oct 26 09:10:00 UTC 2012
>Closed-Date:
>Last-Modified:
>Originator: Steven Hartland
>Release: 8.3-RELEASE
>Organization:
Multiplay
>Environment:
FreeBSD dev 8.3-RELEASE-p4 FreeBSD 8.3-RELEASE-p4 #22: Mon Sep 17 17:18:32 UTC 2012 root at dev:/usr/obj/usr/src/sys/MULTIPLAY amd64
>Description:
Add the ability to send and receive DNS messages with edns-client-subnet options to BIND's dig utility.
>How-To-Repeat:
N/A
>Fix:
Apply the attached patch
Patch attached with submission follows:
A patch for bind-9.6.-ESV-R5-P1 (FreeBSD 8.3-RELEASE) based on the work by
Wilmer van der Gaast @
http://wilmer.gaa.st/edns-client-subnet/bind-9.7.1-dig-edns-client-subnet.diff
These patches add the ability to send and receive DNS messages with
edns-client-subnet options to BIND's dig utility.
Example:
wilmer at fiona:~/src/bind-ecs$ bin/dig/dig @ns1.google.com www.google.com +client=130.89.89.130
; <<>> DiG 9.7.1-P2 <<>> @ns1.google.com www.google.com +client=130.89.89.130
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 512
; CLIENT-SUBNET: 130.89.89.130/32/21
;; QUESTION SECTION:
;www.google.com. IN A
;; ANSWER SECTION:
www.google.com. 604800 IN CNAME www.l.google.com.
www.l.google.com. 300 IN A 74.125.79.104
www.l.google.com. 300 IN A 74.125.79.99
www.l.google.com. 300 IN A 74.125.79.147
Copyright 2010 Google Inc.
Author: Wilmer van der Gaast <wilmer at google.com>
--- contrib/bind9/bin/dig/dig.c.orig 2012-05-10 14:21:33.000000000 +0000
+++ contrib/bind9/bin/dig/dig.c 2012-10-16 11:25:33.000000000 +0000
@@ -183,6 +183,7 @@
" +bufsize=### (Set EDNS0 Max UDP packet size)\n"
" +ndots=### (Set NDOTS value)\n"
" +edns=### (Set EDNS version)\n"
+" +client=addr (Set edns-client-subnet option)\n"
" +[no]search (Set whether to use searchlist)\n"
" +[no]showsearch (Search with intermediate results)\n"
" +[no]defname (Ditto)\n"
@@ -797,8 +798,25 @@
lookup->cdflag = state;
break;
case 'l': /* cl */
- FULLCHECK("cl");
- noclass = ISC_TF(!state);
+ switch (cmd[2]) {
+ case 'i':/* client */
+ FULLCHECK("client");
+ if (value == NULL)
+ goto need_value;
+ if (state && lookup->edns == -1)
+ lookup->edns = 0;
+ if (parse_netprefix(&lookup->ecs_addr,
+ &lookup->ecs_len,
+ value) != ISC_R_SUCCESS)
+ fatal("Couldn't parse client");
+ break;
+ case '\0':
+ FULLCHECK("cl");
+ noclass = ISC_TF(!state);
+ break;
+ default:
+ goto invalid_option;
+ }
break;
case 'm': /* cmd */
FULLCHECK("cmd");
--- contrib/bind9/bin/dig/dighost.c.orig 2012-05-10 14:21:34.000000000 +0000
+++ contrib/bind9/bin/dig/dighost.c 2012-10-16 12:02:23.000000000 +0000
@@ -66,6 +66,7 @@
#include <dst/dst.h>
+#include <isc/parseint.h>
#include <isc/app.h>
#include <isc/base64.h>
#include <isc/entropy.h>
@@ -91,6 +92,9 @@
#include <dig/dig.h>
+/* parse_netprefix */
+#include <netdb.h>
+
#if ! defined(NS_INADDRSZ)
#define NS_INADDRSZ 4
#endif
@@ -763,6 +767,8 @@
looknew->new_search = ISC_FALSE;
looknew->done_as_is = ISC_FALSE;
looknew->need_search = ISC_FALSE;
+ looknew->ecs_addr = NULL;
+ looknew->ecs_len = 0;
ISC_LINK_INIT(looknew, link);
ISC_LIST_INIT(looknew->q);
ISC_LIST_INIT(looknew->my_server_list);
@@ -779,6 +785,7 @@
dig_lookup_t *
clone_lookup(dig_lookup_t *lookold, isc_boolean_t servers) {
dig_lookup_t *looknew;
+ size_t len;
debug("clone_lookup()");
@@ -839,6 +846,19 @@
looknew->need_search = lookold->need_search;
looknew->done_as_is = lookold->done_as_is;
+ if (lookold->ecs_addr) {
+ if (lookold->ecs_addr->sa_family == AF_INET)
+ len = sizeof(struct sockaddr_in);
+ else if (lookold->ecs_addr->sa_family == AF_INET6)
+ len = sizeof(struct sockaddr_in6);
+ else
+ INSIST(0);
+
+ looknew->ecs_addr = isc_mem_allocate(mctx, len);
+ memcpy(looknew->ecs_addr, lookold->ecs_addr, len);
+ looknew->ecs_len = lookold->ecs_len;
+ }
+
if (servers)
clone_server_list(lookold->my_server_list,
&looknew->my_server_list);
@@ -922,6 +942,48 @@
isc_buffer_free(&namebuf);
}
+isc_result_t
+parse_netprefix(struct sockaddr **sa, isc_uint32_t *netmask,
+ const char *value) {
+ struct addrinfo *res, hints;
+ char *addr, *slash;
+ isc_uint32_t result;
+
+ addr = isc_mem_strdup(mctx, value);
+ if ((slash = strchr(addr, '/'))) {
+ *slash = '\0';
+ result = isc_parse_uint32(netmask, slash + 1, 10);
+ if (result != ISC_R_SUCCESS) {
+ isc_mem_free(mctx, addr);
+ printf("invalid %s '%s': %s\n", "prefix length",
+ value, isc_result_totext(result));
+ return (result);
+ }
+ } else {
+ *netmask = 128;
+ }
+
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_flags = AI_NUMERICHOST;
+ if ((result = getaddrinfo(addr, NULL, &hints, &res)) != 0) {
+ isc_mem_free(mctx, addr);
+ printf("getaddrinfo() error: %s\n", gai_strerror(result));
+ return ISC_R_FAILURE;
+ }
+ isc_mem_free(mctx, addr);
+
+ *sa = isc_mem_allocate(mctx, res->ai_addrlen);
+ memcpy(*sa, res->ai_addr, res->ai_addrlen);
+
+ if (res->ai_family == AF_INET && *netmask > 32)
+ *netmask = 32;
+ else if (res->ai_family == AF_INET6 && *netmask > 128)
+ *netmask = 128;
+
+ freeaddrinfo(res);
+ return (ISC_R_SUCCESS);
+}
+
static void
setup_file_key(void) {
isc_result_t result;
@@ -1174,12 +1236,14 @@
*/
static void
add_opt(dns_message_t *msg, isc_uint16_t udpsize, isc_uint16_t edns,
- isc_boolean_t dnssec, isc_boolean_t nsid)
+ isc_boolean_t dnssec, isc_boolean_t nsid,
+ struct sockaddr *ecs_addr, isc_uint32_t ecs_len)
{
dns_rdataset_t *rdataset = NULL;
dns_rdatalist_t *rdatalist = NULL;
dns_rdata_t *rdata = NULL;
isc_result_t result;
+ isc_buffer_t *b = NULL;
debug("add_opt()");
result = dns_message_gettemprdataset(msg, &rdataset);
@@ -1197,20 +1261,40 @@
rdatalist->ttl = edns << 16;
if (dnssec)
rdatalist->ttl |= DNS_MESSAGEEXTFLAG_DO;
+
+ result = isc_buffer_allocate(mctx, &b, 64);
+ check_result(result, "isc_buffer_allocate");
if (nsid) {
- isc_buffer_t *b = NULL;
- result = isc_buffer_allocate(mctx, &b, 4);
- check_result(result, "isc_buffer_allocate");
isc_buffer_putuint16(b, DNS_OPT_NSID);
isc_buffer_putuint16(b, 0);
+ }
+ if (ecs_addr) {
+ size_t addrl = (ecs_len + 7) / 8;
+
+ isc_buffer_putuint16(b, DNS_OPT_CLIENT_SUBNET);
+ isc_buffer_putuint16(b, 4 + addrl);
+ if (ecs_addr->sa_family == AF_INET) {
+ struct sockaddr_in *ad = (struct sockaddr_in *) ecs_addr;
+ isc_buffer_putuint16(b, 1);
+ isc_buffer_putuint8(b, ecs_len);
+ isc_buffer_putuint8(b, 0);
+ isc_buffer_putmem(b, (isc_uint8_t*) &ad->sin_addr, addrl);
+ }
+ else /* if (ecs_addr->sa_family == AF_INET6) */ {
+ struct sockaddr_in6 *ad = (struct sockaddr_in6 *) ecs_addr;
+ isc_buffer_putuint16(b, 2);
+ isc_buffer_putuint8(b, ecs_len);
+ isc_buffer_putuint8(b, 0);
+ isc_buffer_putmem(b, (isc_uint8_t*) &ad->sin6_addr, addrl);
+ }
+ }
+ if ((rdata->length = isc_buffer_usedlength(b)) > 0) {
rdata->data = isc_buffer_base(b);
- rdata->length = isc_buffer_usedlength(b);
dns_message_takebuffer(msg, &b);
- } else {
+ } else
rdata->data = NULL;
- rdata->length = 0;
- }
+
ISC_LIST_INIT(rdatalist->rdata);
ISC_LIST_APPEND(rdatalist->rdata, rdata, link);
dns_rdatalist_tordataset(rdatalist, rdataset);
@@ -1359,6 +1443,9 @@
if (lookup->tsigctx != NULL)
dst_context_destroy(&lookup->tsigctx);
+ if (lookup->ecs_addr != NULL)
+ isc_mem_free(mctx, lookup->ecs_addr);
+
isc_mem_free(mctx, lookup);
}
@@ -2031,7 +2118,8 @@
if (lookup->edns < 0)
lookup->edns = 0;
add_opt(lookup->sendmsg, lookup->udpsize,
- lookup->edns, lookup->dnssec, lookup->nsid);
+ lookup->edns, lookup->dnssec, lookup->nsid,
+ lookup->ecs_addr, lookup->ecs_len);
}
result = dns_message_rendersection(lookup->sendmsg,
@@ -5336,7 +5424,6 @@
#endif
}
-
/*
* return 1 if name1 < name2
* 0 if name1 == name2
--- contrib/bind9/bin/dig/include/dig/dig.h.orig 2012-05-10 14:21:34.000000000 +0000
+++ contrib/bind9/bin/dig/include/dig/dig.h 2012-10-16 11:25:33.000000000 +0000
@@ -183,6 +183,8 @@
isc_buffer_t *querysig;
isc_uint32_t msgcounter;
dns_fixedname_t fdomain;
+ struct sockaddr *ecs_addr; /*% edns-client-subnet */
+ isc_uint32_t ecs_len;
};
/*% The dig_query structure */
@@ -325,6 +327,10 @@
void
setup_libs(void);
+isc_result_t
+parse_netprefix(struct sockaddr **sa, isc_uint32_t *netmask,
+ const char *value);
+
void
setup_system(void);
--- contrib/bind9/lib/dns/message.c.orig 2012-05-10 14:21:48.000000000 +0000
+++ contrib/bind9/lib/dns/message.c 2012-10-20 00:56:27.157757171 +0000
@@ -3189,6 +3189,35 @@
if (optcode == DNS_OPT_NSID) {
ADD_STRING(target, "; NSID");
+ } else if (optcode == DNS_OPT_CLIENT_SUBNET) {
+ int i;
+ char addr[16], addr_text[64];
+ isc_uint16_t family;
+ isc_uint8_t addrlen, addrbytes, scopelen;
+
+ family = isc_buffer_getuint16(&optbuf);
+ addrlen = isc_buffer_getuint8(&optbuf);
+ scopelen = isc_buffer_getuint8(&optbuf);
+ addrbytes = (addrlen + 7) / 8;
+ memset(addr, 0, sizeof(addr));
+ for (i = 0; i < addrbytes; i ++)
+ addr[i] = isc_buffer_getuint8(&optbuf);
+
+ ADD_STRING(target, "; CLIENT-SUBNET: ");
+ if (family == 1)
+ inet_ntop(AF_INET, addr, addr_text, sizeof(addr_text));
+ else if (family == 2)
+ inet_ntop(AF_INET6, addr, addr_text, sizeof(addr_text));
+ else
+ snprintf(addr_text, sizeof(addr_text),
+ "Unsupported(family=%d)", family);
+
+ ADD_STRING(target, addr_text);
+ sprintf(addr_text, "/%d/%d", addrlen, scopelen);
+ ADD_STRING(target, addr_text);
+
+ /* Disable the dumb byte representation below. */
+ optlen = 0;
} else {
ADD_STRING(target, "; OPT=");
sprintf(buf, "%u", optcode);
--- contrib/bind9/lib/dns/include/dns/message.h.orig 2012-05-10 14:21:48.000000000 +0000
+++ contrib/bind9/lib/dns/include/dns/message.h 2012-10-20 00:56:27.155745851 +0000
@@ -106,6 +106,7 @@
/*%< EDNS0 extended OPT codes */
#define DNS_OPT_NSID 0x0003 /*%< NSID opt code */
+#define DNS_OPT_CLIENT_SUBNET 0x50fa /*%< client subnet opt code */
#define DNS_MESSAGE_REPLYPRESERVE (DNS_MESSAGEFLAG_RD|DNS_MESSAGEFLAG_CD)
#define DNS_MESSAGEEXTFLAG_REPLYPRESERVE (DNS_MESSAGEEXTFLAG_DO)
>Release-Note:
>Audit-Trail:
>Unformatted:
More information about the freebsd-bugs
mailing list