]> git.pld-linux.org Git - packages/bind.git/blob - bind-edns-client-subnet.patch
- release 2 (by relup.sh)
[packages/bind.git] / bind-edns-client-subnet.patch
1 These patches add the ability to send and receive DNS messages with
2 edns-client-subnet options to BIND's dig utility.
3
4 Example:
5
6 wilmer@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:
16 www.google.com.         604800  IN      CNAME   www.l.google.com.
17 www.l.google.com.       300     IN      A       74.125.79.104
18 www.l.google.com.       300     IN      A       74.125.79.99
19 www.l.google.com.       300     IN      A       74.125.79.147
20
21 Copyright 2010 Google Inc.
22 Author: Wilmer van der Gaast <wilmer@google.com>
23
24
25 diff -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");
64 diff -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,
250 diff -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  
273 diff -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)
284 diff -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.059065 seconds and 3 git commands to generate.