]> git.pld-linux.org Git - packages/bind.git/blame - bind-edns-client-subnet.patch
- release 2 (by relup.sh)
[packages/bind.git] / bind-edns-client-subnet.patch
CommitLineData
d085b054 1These patches add the ability to send and receive DNS messages with
2edns-client-subnet options to BIND's dig utility.
3
4Example:
5
6wilmer@fiona:~/src/bind-ecs$ bin/dig/dig @ns1.google.com www.google.com +client=130.89.89.130
7
8; <<>> DiG 9.7.1-P2 <<>> @ns1.google.com www.google.com +client=130.89.89.130
9;; OPT PSEUDOSECTION:
10; EDNS: version: 0, flags:; udp: 512
11; CLIENT-SUBNET: 130.89.89.130/32/21
12;; QUESTION SECTION:
13;www.google.com. IN A
14
15;; ANSWER SECTION:
16www.google.com. 604800 IN CNAME www.l.google.com.
17www.l.google.com. 300 IN A 74.125.79.104
18www.l.google.com. 300 IN A 74.125.79.99
19www.l.google.com. 300 IN A 74.125.79.147
20
21Copyright 2010 Google Inc.
22Author: Wilmer van der Gaast <wilmer@google.com>
23
24
25diff -uNr bin/dig/dig.c bin/dig/dig.c
26--- bin/dig/dig.c 2010-05-13 01:42:26.000000000 +0100
27+++ bin/dig/dig.c 2011-02-16 15:58:31.000000000 +0000
28@@ -188,6 +188,7 @@
29 " +bufsize=### (Set EDNS0 Max UDP packet size)\n"
30 " +ndots=### (Set NDOTS value)\n"
31 " +edns=### (Set EDNS version)\n"
32+" +client=addr (Set edns-client-subnet option)\n"
33 " +[no]search (Set whether to use searchlist)\n"
34 " +[no]showsearch (Search with intermediate results)\n"
35 " +[no]defname (Ditto)\n"
36@@ -804,8 +805,25 @@
37 }
38 break;
39 case 'l': /* cl */
40- FULLCHECK("cl");
41- noclass = ISC_TF(!state);
42+ switch (cmd[2]) {
43+ case 'i':/* client */
44+ FULLCHECK("client");
45+ if (value == NULL)
46+ goto need_value;
47+ if (state && lookup->edns == -1)
48+ lookup->edns = 0;
49+ if (parse_netprefix(&lookup->ecs_addr,
50+ &lookup->ecs_len,
51+ value) != ISC_R_SUCCESS)
52+ fatal("Couldn't parse client");
53+ break;
54+ case '\0':
55+ FULLCHECK("cl");
56+ noclass = ISC_TF(!state);
57+ break;
58+ default:
59+ goto invalid_option;
60+ }
61 break;
62 case 'm': /* cmd */
63 FULLCHECK("cmd");
64diff -uNr bin/dig/dighost.c bin/dig/dighost.c
65--- bin/dig/dighost.c 2010-12-09 01:05:27.000000000 +0000
66+++ bin/dig/dighost.c 2011-02-16 15:58:31.000000000 +0000
67@@ -96,6 +96,9 @@
68
69 #include <dig/dig.h>
70
71+/* parse_netprefix */
72+#include <netdb.h>
73+
74 #if ! defined(NS_INADDRSZ)
75 #define NS_INADDRSZ 4
76 #endif
77@@ -789,6 +792,8 @@
78 looknew->new_search = ISC_FALSE;
79 looknew->done_as_is = ISC_FALSE;
80 looknew->need_search = ISC_FALSE;
81+ looknew->ecs_addr = NULL;
82+ looknew->ecs_len = 0;
83 ISC_LINK_INIT(looknew, link);
84 ISC_LIST_INIT(looknew->q);
85 ISC_LIST_INIT(looknew->my_server_list);
86@@ -805,6 +810,7 @@
87 dig_lookup_t *
88 clone_lookup(dig_lookup_t *lookold, isc_boolean_t servers) {
89 dig_lookup_t *looknew;
90+ size_t len;
91
92 debug("clone_lookup()");
93
94@@ -865,6 +871,19 @@
95 looknew->need_search = lookold->need_search;
96 looknew->done_as_is = lookold->done_as_is;
97
98+ if (lookold->ecs_addr) {
99+ if (lookold->ecs_addr->sa_family == AF_INET)
100+ len = sizeof(struct sockaddr_in);
101+ else if (lookold->ecs_addr->sa_family == AF_INET6)
102+ len = sizeof(struct sockaddr_in6);
103+ else
104+ INSIST(0);
105+
106+ looknew->ecs_addr = isc_mem_allocate(mctx, len);
107+ memcpy(looknew->ecs_addr, lookold->ecs_addr, len);
108+ looknew->ecs_len = lookold->ecs_len;
109+ }
110+
111 if (servers)
112 clone_server_list(lookold->my_server_list,
113 &looknew->my_server_list);
114@@ -974,6 +993,48 @@
115 return (tmp);
116 }
117
118+isc_result_t
119+parse_netprefix(struct sockaddr **sa, isc_uint32_t *netmask,
120+ const char *value) {
121+ struct addrinfo *res, hints;
122+ char *addr, *slash;
123+ isc_uint32_t result;
124+
125+ addr = isc_mem_strdup(mctx, value);
126+ if ((slash = strchr(addr, '/'))) {
127+ *slash = '\0';
128+ result = isc_parse_uint32(netmask, slash + 1, 10);
129+ if (result != ISC_R_SUCCESS) {
130+ isc_mem_free(mctx, addr);
131+ printf("invalid %s '%s': %s\n", "prefix length",
132+ value, isc_result_totext(result));
133+ return (result);
134+ }
135+ } else {
136+ *netmask = 128;
137+ }
138+
139+ memset(&hints, 0, sizeof(hints));
140+ hints.ai_flags = AI_NUMERICHOST;
141+ if ((result = getaddrinfo(addr, NULL, &hints, &res)) != 0) {
142+ isc_mem_free(mctx, addr);
143+ printf("getaddrinfo() error: %s\n", gai_strerror(result));
144+ return ISC_R_FAILURE;
145+ }
146+ isc_mem_free(mctx, addr);
147+
148+ *sa = isc_mem_allocate(mctx, res->ai_addrlen);
149+ memcpy(*sa, res->ai_addr, res->ai_addrlen);
150+
151+ if (res->ai_family == AF_INET && *netmask > 32)
152+ *netmask = 32;
153+ else if (res->ai_family == AF_INET6 && *netmask > 128)
154+ *netmask = 128;
155+
156+ freeaddrinfo(res);
157+ return (ISC_R_SUCCESS);
158+}
159+
160
161 /*
162 * Parse HMAC algorithm specification
163@@ -1361,12 +1422,15 @@
164 */
165 static void
166 add_opt(dns_message_t *msg, isc_uint16_t udpsize, isc_uint16_t edns,
167- isc_boolean_t dnssec, isc_boolean_t nsid)
168+ isc_boolean_t dnssec, isc_boolean_t nsid,
169+ struct sockaddr *ecs_addr, isc_uint32_t ecs_len)
170 {
171 dns_rdataset_t *rdataset = NULL;
172 dns_rdatalist_t *rdatalist = NULL;
173 dns_rdata_t *rdata = NULL;
174 isc_result_t result;
175+ unsigned char data[64];
176+ isc_buffer_t buf;
177
178 debug("add_opt()");
179 result = dns_message_gettemprdataset(msg, &rdataset);
180@@ -1384,20 +1448,37 @@
181 rdatalist->ttl = edns << 16;
182 if (dnssec)
183 rdatalist->ttl |= DNS_MESSAGEEXTFLAG_DO;
184- if (nsid) {
185- isc_buffer_t *b = NULL;
186
187- result = isc_buffer_allocate(mctx, &b, 4);
188- check_result(result, "isc_buffer_allocate");
189- isc_buffer_putuint16(b, DNS_OPT_NSID);
190- isc_buffer_putuint16(b, 0);
191- rdata->data = isc_buffer_base(b);
192- rdata->length = isc_buffer_usedlength(b);
193- dns_message_takebuffer(msg, &b);
194- } else {
195- rdata->data = NULL;
196- rdata->length = 0;
197+ isc_buffer_init(&buf, data, sizeof(data));
198+ if (nsid) {
199+ isc_buffer_putuint16(&buf, DNS_OPT_NSID);
200+ isc_buffer_putuint16(&buf, 0);
201 }
202+ if (ecs_addr) {
203+ size_t addrl = (ecs_len + 7) / 8;
204+
205+ isc_buffer_putuint16(&buf, DNS_OPT_CLIENT_SUBNET);
206+ isc_buffer_putuint16(&buf, 4 + addrl);
207+ if (ecs_addr->sa_family == AF_INET) {
208+ struct sockaddr_in *ad = (struct sockaddr_in *) ecs_addr;
209+ isc_buffer_putuint16(&buf, 1);
210+ isc_buffer_putuint8(&buf, ecs_len);
211+ isc_buffer_putuint8(&buf, 0);
212+ isc_buffer_putmem(&buf, (isc_uint8_t*) &ad->sin_addr, addrl);
213+ }
214+ else /* if (ecs_addr->sa_family == AF_INET6) */ {
215+ struct sockaddr_in6 *ad = (struct sockaddr_in6 *) ecs_addr;
216+ isc_buffer_putuint16(&buf, 2);
217+ isc_buffer_putuint8(&buf, ecs_len);
218+ isc_buffer_putuint8(&buf, 0);
219+ isc_buffer_putmem(&buf, (isc_uint8_t*) &ad->sin6_addr, addrl);
220+ }
221+ }
222+ if ((rdata->length = isc_buffer_usedlength(&buf)) > 0)
223+ rdata->data = data;
224+ else
225+ rdata->data = NULL;
226+
227 ISC_LIST_INIT(rdatalist->rdata);
228 ISC_LIST_APPEND(rdatalist->rdata, rdata, link);
229 dns_rdatalist_tordataset(rdatalist, rdataset);
230@@ -1546,6 +1627,9 @@
231 if (lookup->tsigctx != NULL)
232 dst_context_destroy(&lookup->tsigctx);
233
234+ if (lookup->ecs_addr != NULL)
235+ isc_mem_free(mctx, lookup->ecs_addr);
236+
237 isc_mem_free(mctx, lookup);
238 }
239
240@@ -2210,7 +2294,8 @@
241 if (lookup->edns < 0)
242 lookup->edns = 0;
243 add_opt(lookup->sendmsg, lookup->udpsize,
244- lookup->edns, lookup->dnssec, lookup->nsid);
245+ lookup->edns, lookup->dnssec, lookup->nsid,
246+ lookup->ecs_addr, lookup->ecs_len);
247 }
248
249 result = dns_message_rendersection(lookup->sendmsg,
250diff -uNr bin/dig/include/dig/dig.h bin/dig/include/dig/dig.h
251--- bin/dig/include/dig/dig.h 2009-09-29 16:06:06.000000000 +0100
252+++ bin/dig/include/dig/dig.h 2011-02-16 15:58:31.000000000 +0000
253@@ -183,6 +183,8 @@
254 isc_buffer_t *querysig;
255 isc_uint32_t msgcounter;
256 dns_fixedname_t fdomain;
257+ struct sockaddr *ecs_addr; /*% edns-client-subnet */
258+ isc_uint32_t ecs_len;
259 };
260
261 /*% The dig_query structure */
262@@ -330,6 +332,10 @@
263 parse_uint(isc_uint32_t *uip, const char *value, isc_uint32_t max,
264 const char *desc);
265
266+isc_result_t
267+parse_netprefix(struct sockaddr **sa, isc_uint32_t *netmask,
268+ const char *value);
269+
270 void
271 parse_hmac(const char *hmacstr);
272
273diff -uNr lib/dns/include/dns/message.h lib/dns/include/dns/message.h
274--- lib/dns/include/dns/message.h 2009-10-26 23:47:35.000000000 +0000
275+++ lib/dns/include/dns/message.h 2011-02-16 15:58:31.000000000 +0000
276@@ -105,6 +105,7 @@
277
278 /*%< EDNS0 extended OPT codes */
279 #define DNS_OPT_NSID 0x0003 /*%< NSID opt code */
280+#define DNS_OPT_CLIENT_SUBNET 0x50fa /*%< client subnet opt code */
281
282 #define DNS_MESSAGE_REPLYPRESERVE (DNS_MESSAGEFLAG_RD|DNS_MESSAGEFLAG_CD)
283 #define DNS_MESSAGEEXTFLAG_REPLYPRESERVE (DNS_MESSAGEEXTFLAG_DO)
284diff -uNr lib/dns/message.c lib/dns/message.c
285--- lib/dns/message.c 2010-06-03 06:27:59.000000000 +0100
286+++ lib/dns/message.c 2011-02-16 15:58:31.000000000 +0000
287@@ -3236,6 +3236,35 @@
288
289 if (optcode == DNS_OPT_NSID) {
290 ADD_STRING(target, "; NSID");
291+ } else if (optcode == DNS_OPT_CLIENT_SUBNET) {
292+ int i;
293+ char addr[16], addr_text[64];
294+ isc_uint16_t family;
295+ isc_uint8_t addrlen, addrbytes, scopelen;
296+
297+ family = isc_buffer_getuint16(&optbuf);
298+ addrlen = isc_buffer_getuint8(&optbuf);
299+ scopelen = isc_buffer_getuint8(&optbuf);
300+ addrbytes = (addrlen + 7) / 8;
301+ memset(addr, 0, sizeof(addr));
302+ for (i = 0; i < addrbytes; i ++)
303+ addr[i] = isc_buffer_getuint8(&optbuf);
304+
305+ ADD_STRING(target, "; CLIENT-SUBNET: ");
306+ if (family == 1)
307+ inet_ntop(AF_INET, addr, addr_text, sizeof(addr_text));
308+ else if (family == 2)
309+ inet_ntop(AF_INET6, addr, addr_text, sizeof(addr_text));
310+ else
311+ snprintf(addr_text, sizeof(addr_text),
312+ "Unsupported(family=%d)", family);
313+
314+ ADD_STRING(target, addr_text);
315+ sprintf(addr_text, "/%d/%d", addrlen, scopelen);
316+ ADD_STRING(target, addr_text);
317+
318+ /* Disable the dumb byte representation below. */
319+ optlen = 0;
320 } else {
321 ADD_STRING(target, "; OPT=");
322 sprintf(buf, "%u", optcode);
This page took 0.109077 seconds and 4 git commands to generate.