aboutsummaryrefslogtreecommitdiff
path: root/src/gns
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2012-07-20 20:17:19 +0000
committerChristian Grothoff <christian@grothoff.org>2012-07-20 20:17:19 +0000
commit2687ea5fca3effa07f9b58aa41dfeac203dfb65f (patch)
treeb5fdf25e7f814e3754ba38c10cabec8f8d80544a /src/gns
parent7f2aed62fe8506e0f7a2f551875f7eb16326e9ad (diff)
downloadgnunet-2687ea5fca3effa07f9b58aa41dfeac203dfb65f.tar.gz
gnunet-2687ea5fca3effa07f9b58aa41dfeac203dfb65f.zip
ns2gns
Diffstat (limited to 'src/gns')
-rw-r--r--src/gns/Makefile.am1
-rw-r--r--src/gns/gnunet-dns2gns.c356
2 files changed, 354 insertions, 3 deletions
diff --git a/src/gns/Makefile.am b/src/gns/Makefile.am
index 45bacda3c..21c144d5a 100644
--- a/src/gns/Makefile.am
+++ b/src/gns/Makefile.am
@@ -293,6 +293,7 @@ gnunet_dns2gns_LDADD = \
293 $(top_builddir)/src/gns/libgnunetgns.la \ 293 $(top_builddir)/src/gns/libgnunetgns.la \
294 $(top_builddir)/src/util/libgnunetutil.la \ 294 $(top_builddir)/src/util/libgnunetutil.la \
295 $(top_builddir)/src/namestore/libgnunetnamestore.la \ 295 $(top_builddir)/src/namestore/libgnunetnamestore.la \
296 $(top_builddir)/src/dns/libgnunetdnsparser.la \
296 $(GN_LIBINTL) 297 $(GN_LIBINTL)
297 298
298gnunet_gns_proxy_SOURCES = \ 299gnunet_gns_proxy_SOURCES = \
diff --git a/src/gns/gnunet-dns2gns.c b/src/gns/gnunet-dns2gns.c
index a33020f16..cb7abe6ec 100644
--- a/src/gns/gnunet-dns2gns.c
+++ b/src/gns/gnunet-dns2gns.c
@@ -24,21 +24,78 @@
24 */ 24 */
25#include "platform.h" 25#include "platform.h"
26#include <gnunet_util_lib.h> 26#include <gnunet_util_lib.h>
27#include <gnunet_namestore_service.h> 27#include <gnunet_dnsparser_lib.h>
28#include <gnunet_gns_service.h>
29
30/**
31 * Timeout for DNS requests.
32 */
33#define TIMEOUT GNUNET_TIME_UNIT_MINUTES
28 34
29/** 35/**
30 * Data kept per request. 36 * Data kept per request.
31 */ 37 */
32struct Request 38struct Request
33{ 39{
40 /**
41 * Socket to use for sending the reply.
42 */
43 struct GNUNET_NETWORK_Handle *lsock;
44
45 /**
46 * Destination address to use.
47 */
48 const void *addr;
49
50 /**
51 * Initially, this is the DNS request, it will then be
52 * converted to the DNS response.
53 */
54 struct GNUNET_DNSPARSER_Packet *packet;
55
56 /**
57 * Our GNS request handle.
58 */
59 struct GNUNET_GNS_LookupRequest *lookup;
60
61 /**
62 * Task run on timeout or shutdown to clean up without
63 * response.
64 */
65 GNUNET_SCHEDULER_TaskIdentifier timeout_task;
66
67 /**
68 * Number of bytes in 'addr'.
69 */
70 size_t addr_len;
34 71
35}; 72};
36 73
37 74
38/** 75/**
39 * Listen socket. 76 * Handle to GNS resolver.
77 */
78struct GNUNET_GNS_Handle *gns;
79
80/**
81 * Listen socket for IPv4.
82 */
83static struct GNUNET_NETWORK_Handle *listen_socket4;
84
85/**
86 * Listen socket for IPv6.
87 */
88static struct GNUNET_NETWORK_Handle *listen_socket6;
89
90/**
91 * Task for IPv4 socket.
92 */
93static GNUNET_SCHEDULER_TaskIdentifier t4;
94
95/**
96 * Task for IPv6 socket.
40 */ 97 */
41static struct GNUNET_NETWORK_Handle *listen_socket; 98static GNUNET_SCHEDULER_TaskIdentifier t6;
42 99
43 100
44/** 101/**
@@ -51,6 +108,236 @@ static void
51do_shutdown (void *cls, 108do_shutdown (void *cls,
52 const struct GNUNET_SCHEDULER_TaskContext *tc) 109 const struct GNUNET_SCHEDULER_TaskContext *tc)
53{ 110{
111 if (GNUNET_SCHEDULER_NO_TASK != t4)
112 GNUNET_SCHEDULER_cancel (t4);
113 if (GNUNET_SCHEDULER_NO_TASK != t6)
114 GNUNET_SCHEDULER_cancel (t6);
115 if (NULL != listen_socket4)
116 {
117 GNUNET_NETWORK_socket_close (listen_socket4);
118 listen_socket4 = NULL;
119 }
120 if (NULL != listen_socket6)
121 {
122 GNUNET_NETWORK_socket_close (listen_socket6);
123 listen_socket6 = NULL;
124 }
125 GNUNET_GNS_disconnect (gns);
126 gns = NULL;
127}
128
129
130/**
131 * Send the response for the given request and clean up.
132 *
133 * @param request context for the request.
134 */
135static void
136send_response (struct Request *request)
137{
138 char *buf;
139 size_t size;
140
141 if (GNUNET_SYSERR ==
142 GNUNET_DNSPARSER_pack (request->packet,
143 UINT16_MAX /* is this not too much? */,
144 &buf,
145 &size))
146 {
147 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
148 _("Failed to pack DNS response into UDP packet!\n"));
149 }
150 else
151 {
152 if (size !=
153 GNUNET_NETWORK_socket_sendto (request->lsock,
154 buf, size,
155 request->addr,
156 request->addr_len))
157 GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "sendto");
158 GNUNET_free (buf);
159 }
160 GNUNET_SCHEDULER_cancel (request->timeout_task);
161 GNUNET_DNSPARSER_free_packet (request->packet);
162 GNUNET_free (request);
163}
164
165
166/**
167 * Task run on timeout. Cleans up request.
168 *
169 * @param cls 'struct Request' of the request to clean up
170 * @param tc scheduler context
171 */
172static void
173do_timeout (void *cls,
174 const struct GNUNET_SCHEDULER_TaskContext *tc)
175{
176 struct Request *request = cls;
177
178 GNUNET_DNSPARSER_free_packet (request->packet);
179 GNUNET_GNS_cancel_lookup_request (request->lookup);
180 GNUNET_free (request);
181}
182
183
184/**
185 * Iterator called on obtained result for a GNS
186 * lookup
187 *
188 * @param cls closure
189 * @param name "name" of the original lookup
190 * @param rd_count number of records
191 * @param rd the records in reply
192 */
193static void
194result_processor (void *cls,
195 uint32_t rd_count,
196 const struct GNUNET_NAMESTORE_RecordData *rd)
197{
198 struct Request *request = cls;
199
200 // FIXME: is 'processor' called only once or
201 // possibly more than once?
202 request->lookup = NULL;
203 GNUNET_break (0);
204 // FIXME: convert 'rd' to response here...
205 send_response (request);
206}
207
208
209/**
210 * Handle DNS request.
211 *
212 * @param lsock socket to use for sending the reply
213 * @param addr address to use for sending the reply
214 * @param addr_len number of bytes in addr
215 * @param udp_msg DNS request payload
216 * @param udp_msg_size number of bytes in udp_msg
217 */
218static void
219handle_request (struct GNUNET_NETWORK_Handle *lsock,
220 const void *addr,
221 size_t addr_len,
222 const char *udp_msg,
223 size_t udp_msg_size)
224{
225 struct Request *request;
226 struct GNUNET_DNSPARSER_Packet *packet;
227
228 packet = GNUNET_DNSPARSER_parse (udp_msg, udp_msg_size);
229 if (NULL == packet)
230 {
231 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
232 _("Received malformed DNS request from %s\n"),
233 GNUNET_a2s (addr, addr_len));
234 return;
235 }
236 request = GNUNET_malloc (sizeof (struct Request) + addr_len);
237 request->lsock = lsock;
238 request->packet = packet;
239 request->addr = &request[1];
240 request->addr_len = addr_len;
241 memcpy (&request[1], addr, addr_len);
242 request->timeout_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT,
243 &do_timeout,
244 request);
245 // FIXME: extract name and type from 'request->packet'
246 const char *name = "foo";
247 enum GNUNET_GNS_RecordType type = GNUNET_GNS_RECORD_A;
248 request->lookup = GNUNET_GNS_lookup (gns,
249 name,
250 type,
251 GNUNET_NO,
252 NULL,
253 &result_processor,
254 request);
255}
256
257
258/**
259 * Task to read IPv4 DNS packets.
260 *
261 * @param cls the 'listen_socket4'
262 * @param tc scheduler context
263 */
264static void
265read_dns4 (void *cls,
266 const struct GNUNET_SCHEDULER_TaskContext *tc)
267{
268 struct sockaddr_in v4;
269 socklen_t addrlen;
270 ssize_t size;
271
272 GNUNET_assert (listen_socket4 == cls);
273 t4 = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL,
274 listen_socket4,
275 &read_dns4,
276 listen_socket4);
277 if (0 == (GNUNET_SCHEDULER_REASON_READ_READY & tc->reason))
278 return; /* shutdown? */
279 size = GNUNET_NETWORK_socket_recvfrom_amount (listen_socket4);
280 if (0 > size)
281 {
282 GNUNET_break (0);
283 return; /* read error!? */
284 }
285 {
286 char buf[size];
287
288 addrlen = sizeof (v4);
289 GNUNET_break (size ==
290 GNUNET_NETWORK_socket_recvfrom (listen_socket4,
291 buf,
292 size,
293 (struct sockaddr *) &v4,
294 &addrlen));
295 handle_request (listen_socket4, &v4, addrlen,
296 buf, size);
297 }
298}
299
300
301/**
302 * Task to read IPv6 DNS packets.
303 *
304 * @param cls the 'listen_socket6'
305 * @param tc scheduler context
306 */
307static void
308read_dns6 (void *cls,
309 const struct GNUNET_SCHEDULER_TaskContext *tc)
310{
311 struct sockaddr_in6 v6;
312 socklen_t addrlen;
313 ssize_t size;
314
315 GNUNET_assert (listen_socket6 == cls);
316 t6 = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL,
317 listen_socket6,
318 &read_dns6,
319 listen_socket6);
320 if (0 == (GNUNET_SCHEDULER_REASON_READ_READY & tc->reason))
321 return; /* shutdown? */
322 size = GNUNET_NETWORK_socket_recvfrom_amount (listen_socket6);
323 if (0 > size)
324 {
325 GNUNET_break (0);
326 return; /* read error!? */
327 }
328 {
329 char buf[size];
330
331 addrlen = sizeof (v6);
332 GNUNET_break (size ==
333 GNUNET_NETWORK_socket_recvfrom (listen_socket6,
334 buf,
335 size,
336 (struct sockaddr *) &v6,
337 &addrlen));
338 handle_request (listen_socket6, &v6, addrlen,
339 buf, size);
340 }
54} 341}
55 342
56 343
@@ -66,6 +353,69 @@ static void
66run (void *cls, char *const *args, const char *cfgfile, 353run (void *cls, char *const *args, const char *cfgfile,
67 const struct GNUNET_CONFIGURATION_Handle *cfg) 354 const struct GNUNET_CONFIGURATION_Handle *cfg)
68{ 355{
356 gns = GNUNET_GNS_connect (cfg);
357 if (NULL == gns)
358 return;
359 listen_socket4 = GNUNET_NETWORK_socket_create (PF_INET,
360 SOCK_DGRAM,
361 IPPROTO_UDP);
362 if (NULL != listen_socket4)
363 {
364 struct sockaddr_in v4;
365
366 memset (&v4, 0, sizeof (v4));
367 v4.sin_family = AF_INET;
368#if HAVE_SOCKADDR_IN_SIN_LEN
369 v4.sin_len = sizeof (v4);
370#endif
371 v4.sin_port = htons (53);
372 if (GNUNET_OK !=
373 GNUNET_NETWORK_socket_bind (listen_socket4,
374 (struct sockaddr *) &v4,
375 sizeof (v4)))
376 {
377 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "bind");
378 GNUNET_NETWORK_socket_close (listen_socket4);
379 listen_socket4 = NULL;
380 }
381 }
382 listen_socket6 = GNUNET_NETWORK_socket_create (PF_INET6,
383 SOCK_DGRAM,
384 IPPROTO_UDP);
385 if (NULL != listen_socket6)
386 {
387 struct sockaddr_in6 v6;
388
389 memset (&v6, 0, sizeof (v6));
390 v6.sin6_family = AF_INET6;
391#if HAVE_SOCKADDR_IN_SIN_LEN
392 v6.sin6_len = sizeof (v6);
393#endif
394 v6.sin6_port = htons (53);
395 if (GNUNET_OK !=
396 GNUNET_NETWORK_socket_bind (listen_socket6,
397 (struct sockaddr *) &v6,
398 sizeof (v6)))
399 {
400 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "bind");
401 GNUNET_NETWORK_socket_close (listen_socket6);
402 listen_socket6 = NULL;
403 }
404 }
405 if ( (NULL == listen_socket4) &&
406 (NULL == listen_socket6) )
407 return;
408 if (NULL != listen_socket4)
409 t4 = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL,
410 listen_socket4,
411 &read_dns4,
412 listen_socket4);
413 if (NULL != listen_socket6)
414 t6 = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL,
415 listen_socket6,
416 &read_dns6,
417 listen_socket6);
418
69 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, 419 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL,
70 &do_shutdown, NULL); 420 &do_shutdown, NULL);
71} 421}