aboutsummaryrefslogtreecommitdiff
path: root/src/dns
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2018-04-06 11:45:42 +0200
committerChristian Grothoff <christian@grothoff.org>2018-04-06 11:46:01 +0200
commit9c9773bbdc8ebe9c46fd297fdd96dad5b9f19697 (patch)
tree0ed44cb9b4d6347d81b7699d2758edf9c9e22878 /src/dns
parent08ded5f88e6369ac78db4bb26bcf215f8282f27c (diff)
downloadgnunet-9c9773bbdc8ebe9c46fd297fdd96dad5b9f19697.tar.gz
gnunet-9c9773bbdc8ebe9c46fd297fdd96dad5b9f19697.zip
starting tool for zone import (very incomplete)
Diffstat (limited to 'src/dns')
-rw-r--r--src/dns/Makefile.am12
-rw-r--r--src/dns/gnunet-zoneimport.c308
2 files changed, 319 insertions, 1 deletions
diff --git a/src/dns/Makefile.am b/src/dns/Makefile.am
index 5af228121..8e5b06043 100644
--- a/src/dns/Makefile.am
+++ b/src/dns/Makefile.am
@@ -35,7 +35,9 @@ libexec_PROGRAMS = \
35 gnunet-service-dns $(HIJACKBIN) 35 gnunet-service-dns $(HIJACKBIN)
36 36
37noinst_PROGRAMS = \ 37noinst_PROGRAMS = \
38 gnunet-dns-monitor gnunet-dns-redirector 38 gnunet-dns-monitor \
39 gnunet-dns-redirector \
40 gnunet-zoneimport
39 41
40plugin_LTLIBRARIES = \ 42plugin_LTLIBRARIES = \
41 libgnunet_plugin_block_dns.la 43 libgnunet_plugin_block_dns.la
@@ -60,6 +62,14 @@ gnunet_dns_monitor_LDADD = \
60 $(top_builddir)/src/util/libgnunetutil.la \ 62 $(top_builddir)/src/util/libgnunetutil.la \
61 $(GN_LIBINTL) 63 $(GN_LIBINTL)
62 64
65gnunet_zoneimport_SOURCES = \
66 gnunet-zoneimport.c
67gnunet_zoneimport_LDADD = \
68 libgnunetdnsparser.la \
69 libgnunetdnsstub.la \
70 $(top_builddir)/src/util/libgnunetutil.la \
71 $(GN_LIBINTL)
72
63gnunet_dns_redirector_SOURCES = \ 73gnunet_dns_redirector_SOURCES = \
64 gnunet-dns-redirector.c 74 gnunet-dns-redirector.c
65gnunet_dns_redirector_LDADD = \ 75gnunet_dns_redirector_LDADD = \
diff --git a/src/dns/gnunet-zoneimport.c b/src/dns/gnunet-zoneimport.c
new file mode 100644
index 000000000..bcc742314
--- /dev/null
+++ b/src/dns/gnunet-zoneimport.c
@@ -0,0 +1,308 @@
1/*
2 This file is part of GNUnet
3 Copyright (C) 2018 GNUnet e.V.
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301, USA.
19*/
20
21/**
22 * @file src/dns/gnunet-zoneimport.c
23 * @brief import a DNS zone for analysis, brute force
24 * @author Christian Grothoff
25 */
26#include "platform.h"
27#include <gnunet_util_lib.h>
28#include <gnunet_dnsstub_lib.h>
29#include <gnunet_dnsparser_lib.h>
30
31struct Request
32{
33 struct Request *next;
34 struct Request *prev;
35 struct GNUNET_DNSSTUB_RequestSocket *rs;
36 /**
37 * Raw DNS query.
38 */
39 void *raw;
40 /**
41 * Number of bytes in @e raw.
42 */
43 size_t raw_len;
44
45 char *hostname;
46 time_t time;
47 int issueNum;
48
49 /**
50 * random 16-bit DNS query identifier.
51 */
52 uint16_t id;
53};
54
55
56static struct GNUNET_DNSSTUB_Context *ctx;
57
58// the number of queries that are outstanding
59static unsigned int pending;
60
61static unsigned int lookups;
62
63static struct Request *req_head;
64
65static struct Request *req_tail;
66
67// the number of queries that are outstanding
68static unsigned int pending;
69
70static unsigned int lookups;
71
72#define THRESH 20
73
74#define MAX_RETRIES 5
75
76
77// time_thresh is in usecs, but note that adns isn't consistent
78// in how long it takes to submit queries, so 40usecs is
79// really equivalent to 25,000 queries per second, but clearly it doesn't
80// operate in that range. Thus, 10 is just a 'magic' number that we can
81// tweak depending on how fast we want to submit queries.
82#define TIME_THRESH 10
83
84#define MAX_RETRIES 5
85
86
87/**
88 * Function called with the result of a DNS resolution.
89 *
90 * @param cls closure with the `struct Request`
91 * @param rs socket that received the response
92 * @param dns dns response, never NULL
93 * @param dns_len number of bytes in @a dns
94 */
95static void
96process_result (void *cls,
97 struct GNUNET_DNSSTUB_RequestSocket *rs,
98 const struct GNUNET_TUN_DnsHeader *dns,
99 size_t dns_len)
100{
101 struct Request *req = cls;
102 struct GNUNET_DNSPARSER_Packet *p;
103
104 if (NULL == dns)
105 {
106 /* stub gave up */
107 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
108 "Stub gave up on DNS reply for `%s'\n",
109 req->hostname);
110 GNUNET_CONTAINER_DLL_remove (req_head,
111 req_tail,
112 req);
113 GNUNET_CONTAINER_DLL_insert_tail (req_head,
114 req_tail,
115 req);
116 req->rs = NULL;
117 return;
118 }
119 if (req->id != dns->id)
120 return;
121 p = GNUNET_DNSPARSER_parse ((const char *) dns,
122 dns_len);
123 if (NULL == p)
124 {
125 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
126 "Failed to parse DNS reply for `%s'\n",
127 req->hostname);
128 GNUNET_CONTAINER_DLL_remove (req_head,
129 req_tail,
130 req);
131 GNUNET_CONTAINER_DLL_insert_tail (req_head,
132 req_tail,
133 req);
134 GNUNET_DNSSTUB_resolve_cancel (req->rs);
135 req->rs = NULL;
136 return;
137 }
138 for (unsigned int i=0;i<p->num_answers;i++)
139 {
140 struct GNUNET_DNSPARSER_Record *rs = &p->answers[i];
141 char buf[INET_ADDRSTRLEN];
142
143 switch (rs->type)
144 {
145 case GNUNET_DNSPARSER_TYPE_A:
146 fprintf (stdout,
147 "%s %s\n",
148 req->hostname,
149 inet_ntop (AF_INET,
150 rs->data.raw.data,
151 buf,
152 sizeof (buf)));
153 break;
154 }
155 }
156 GNUNET_DNSPARSER_free_packet (p);
157 GNUNET_DNSSTUB_resolve_cancel (req->rs);
158 req->rs = NULL;
159 GNUNET_CONTAINER_DLL_remove (req_head,
160 req_tail,
161 req);
162 GNUNET_free (req->hostname);
163 GNUNET_free (req->raw);
164 GNUNET_free (req);
165}
166
167
168static void
169submit_req (struct Request *req)
170{
171 static struct timeval last_request;
172 struct timeval now;
173
174 if (NULL != req->rs)
175 return; /* already submitted */
176 gettimeofday (&now,
177 NULL);
178 if ( ( ( (now.tv_sec - last_request.tv_sec) == 0) &&
179 ( (now.tv_usec - last_request.tv_usec) < TIME_THRESH) ) ||
180 (pending >= THRESH) )
181 return;
182 GNUNET_assert (NULL == req->rs);
183 req->rs = GNUNET_DNSSTUB_resolve2 (ctx,
184 req->raw,
185 req->raw_len,
186 &process_result,
187 req);
188 GNUNET_assert (NULL != req->rs);
189 last_request = now;
190 lookups++;
191 pending++;
192 req->time = time (NULL);
193}
194
195
196static void
197process_queue()
198{
199 struct Request *wl = wl = req_head;
200
201 if ( (pending < THRESH) &&
202 (NULL != wl) )
203 {
204 struct Request *req = wl;
205
206 wl = req->next;
207 submit_req (req);
208 }
209}
210
211
212static void
213run (void *cls)
214{
215 process_queue ();
216 if (NULL != req_head)
217 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_MILLISECONDS,
218 &run,
219 NULL);
220}
221
222
223static void
224queue (const char *hostname)
225{
226 struct GNUNET_DNSPARSER_Packet p;
227 struct GNUNET_DNSPARSER_Query q;
228 struct Request *req;
229 char *raw;
230 size_t raw_size;
231
232 if (GNUNET_OK !=
233 GNUNET_DNSPARSER_check_name (hostname))
234 {
235 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
236 "Refusing invalid hostname `%s'\n",
237 hostname);
238 return;
239 }
240 q.name = (char *) hostname;
241 q.type = GNUNET_DNSPARSER_TYPE_ANY;
242 q.dns_traffic_class = GNUNET_TUN_DNS_CLASS_INTERNET;
243
244 memset (&p, 0, sizeof (p));
245 p.num_queries = 1;
246 p.queries = &q;
247 p.id = (uint16_t) GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_NONCE,
248 UINT16_MAX);
249
250 if (GNUNET_OK !=
251 GNUNET_DNSPARSER_pack (&p,
252 UINT16_MAX,
253 &raw,
254 &raw_size))
255 {
256 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
257 "Failed to pack query for hostname `%s'\n",
258 hostname);
259 return;
260 }
261
262 req = GNUNET_new (struct Request);
263 req->hostname = strdup (hostname);
264 req->raw = raw;
265 req->raw_len = raw_size;
266 req->id = p.id;
267 GNUNET_CONTAINER_DLL_insert_tail (req_head,
268 req_tail,
269 req);
270}
271
272
273int
274main (int argc,
275 char **argv)
276{
277 char hn[256];
278
279 if (2 != argc)
280 {
281 fprintf (stderr,
282 "Missing required configuration argument\n");
283 return -1;
284 }
285 ctx = GNUNET_DNSSTUB_start (argv[1]);
286 if (NULL == ctx)
287 {
288 fprintf (stderr,
289 "Failed to initialize GNUnet DNS STUB\n");
290 return 1;
291 }
292 while (NULL !=
293 fgets (hn,
294 sizeof (hn),
295 stdin))
296 {
297 if (strlen(hn) > 0)
298 hn[strlen(hn)-1] = '\0'; /* eat newline */
299 queue (hn);
300 }
301 GNUNET_SCHEDULER_run (&run,
302 NULL);
303 GNUNET_DNSSTUB_stop (ctx);
304 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
305 "Did %u lookups\n",
306 lookups);
307 return 0;
308}