aboutsummaryrefslogtreecommitdiff
path: root/src/gns/gnunet-dns2gns.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/gns/gnunet-dns2gns.c')
-rw-r--r--src/gns/gnunet-dns2gns.c1026
1 files changed, 0 insertions, 1026 deletions
diff --git a/src/gns/gnunet-dns2gns.c b/src/gns/gnunet-dns2gns.c
deleted file mode 100644
index 46659cdda..000000000
--- a/src/gns/gnunet-dns2gns.c
+++ /dev/null
@@ -1,1026 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2012-2013 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your 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 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20/**
21 * @file gnunet-dns2gns.c
22 * @brief DNS server that translates DNS requests to GNS
23 * @author Christian Grothoff
24 */
25#include "platform.h"
26#include <gnunet_util_lib.h>
27#include <gnunet_dnsparser_lib.h>
28#include <gnunet_gns_service.h>
29#include <gnunet_dnsstub_lib.h>
30#include "gnunet_vpn_service.h"
31#include "gns.h"
32
33/**
34 * Timeout for DNS requests.
35 */
36#define TIMEOUT GNUNET_TIME_UNIT_MINUTES
37
38/**
39 * Default timeout for VPN redirections.
40 */
41#define VPN_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 30)
42
43
44struct Request;
45
46/**
47 * Closure for #vpn_allocation_cb.
48 */
49struct VpnContext
50{
51 /**
52 * Which resolution process are we processing.
53 */
54 struct Request *request;
55
56 /**
57 * Handle to the VPN request that we were performing.
58 */
59 struct GNUNET_VPN_RedirectionRequest *vpn_request;
60
61 /**
62 * Number of records serialized in @e rd_data.
63 */
64 unsigned int rd_count;
65
66 /**
67 * Serialized records.
68 */
69 char *rd_data;
70
71 /**
72 * Number of bytes in @e rd_data.
73 */
74 ssize_t rd_data_size;
75};
76
77
78/**
79 * Data kept per request.
80 */
81struct Request
82{
83 /**
84 * Socket to use for sending the reply.
85 */
86 struct GNUNET_NETWORK_Handle *lsock;
87
88 /**
89 * Destination address to use.
90 */
91 const void *addr;
92
93 /**
94 * Initially, this is the DNS request, it will then be
95 * converted to the DNS response.
96 */
97 struct GNUNET_DNSPARSER_Packet *packet;
98
99 /**
100 * Our GNS request handle.
101 */
102 struct GNUNET_GNS_LookupWithTldRequest *lookup;
103
104 /**
105 * Our DNS request handle
106 */
107 struct GNUNET_DNSSTUB_RequestSocket *dns_lookup;
108
109 /**
110 * Task run on timeout or shutdown to clean up without
111 * response.
112 */
113 struct GNUNET_SCHEDULER_Task *timeout_task;
114
115 /**
116 * Vpn resulution context
117 */
118 struct VpnContext *vpn_ctx;
119
120 /**
121 * Original UDP request message.
122 */
123 char *udp_msg;
124
125 /**
126 * Number of bytes in @e addr.
127 */
128 size_t addr_len;
129
130 /**
131 * Number of bytes in @e udp_msg.
132 */
133 size_t udp_msg_size;
134
135 /**
136 * ID of the original request.
137 */
138 uint16_t original_request_id;
139
140};
141
142/**
143 * The address to bind to
144 */
145static in_addr_t address;
146
147/**
148 * The IPv6 address to bind to
149 */
150static struct in6_addr address6;
151
152
153/**
154 * Handle to GNS resolver.
155 */
156struct GNUNET_GNS_Handle *gns;
157
158/**
159 * Our handle to the vpn service
160 */
161static struct GNUNET_VPN_Handle *vpn_handle;
162
163/**
164 * Stub resolver
165 */
166struct GNUNET_DNSSTUB_Context *dns_stub;
167
168/**
169 * Listen socket for IPv4.
170 */
171static struct GNUNET_NETWORK_Handle *listen_socket4;
172
173/**
174 * Listen socket for IPv6.
175 */
176static struct GNUNET_NETWORK_Handle *listen_socket6;
177
178/**
179 * Task for IPv4 socket.
180 */
181static struct GNUNET_SCHEDULER_Task *t4;
182
183/**
184 * Task for IPv6 socket.
185 */
186static struct GNUNET_SCHEDULER_Task *t6;
187
188/**
189 * IP of DNS server
190 */
191static char *dns_ip;
192
193/**
194 * UDP Port we listen on for inbound DNS requests.
195 */
196static unsigned int listen_port = 53;
197
198/**
199 * Configuration to use.
200 */
201static const struct GNUNET_CONFIGURATION_Handle *cfg;
202
203
204/**
205 * Task run on shutdown. Cleans up everything.
206 *
207 * @param cls unused
208 */
209static void
210do_shutdown (void *cls)
211{
212 (void) cls;
213 if (NULL != t4)
214 {
215 GNUNET_SCHEDULER_cancel (t4);
216 t4 = NULL;
217 }
218 if (NULL != t6)
219 {
220 GNUNET_SCHEDULER_cancel (t6);
221 t6 = NULL;
222 }
223 if (NULL != listen_socket4)
224 {
225 GNUNET_NETWORK_socket_close (listen_socket4);
226 listen_socket4 = NULL;
227 }
228 if (NULL != listen_socket6)
229 {
230 GNUNET_NETWORK_socket_close (listen_socket6);
231 listen_socket6 = NULL;
232 }
233 if (NULL != gns)
234 {
235 GNUNET_GNS_disconnect (gns);
236 gns = NULL;
237 }
238 if (NULL != vpn_handle)
239 {
240 GNUNET_VPN_disconnect (vpn_handle);
241 vpn_handle = NULL;
242 }
243 if (NULL != dns_stub)
244 {
245 GNUNET_DNSSTUB_stop (dns_stub);
246 dns_stub = NULL;
247 }
248}
249
250
251/**
252 * Shuffle answers
253 * Fisher-Yates (aka Knuth) Shuffle
254 *
255 * @param request context for the request (with answers)
256 */
257static void
258shuffle_answers (struct Request *request)
259{
260 unsigned int idx = request->packet->num_answers;
261 unsigned int r_idx;
262 struct GNUNET_DNSPARSER_Record tmp_answer;
263
264 while (0 != idx)
265 {
266 r_idx = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
267 request->packet->num_answers);
268 idx--;
269 tmp_answer = request->packet->answers[idx];
270 memcpy (&request->packet->answers[idx], &request->packet->answers[r_idx],
271 sizeof (struct GNUNET_DNSPARSER_Record));
272 memcpy (&request->packet->answers[r_idx], &tmp_answer,
273 sizeof (struct GNUNET_DNSPARSER_Record));
274 }
275}
276
277
278/**
279 * Send the response for the given request and clean up.
280 *
281 * @param request context for the request.
282 */
283static void
284send_response (struct Request *request)
285{
286 char *buf;
287 size_t size;
288 ssize_t sret;
289
290 shuffle_answers (request);
291 if (GNUNET_SYSERR ==
292 GNUNET_DNSPARSER_pack (request->packet,
293 UINT16_MAX /* is this not too much? */,
294 &buf,
295 &size))
296 {
297 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
298 _ ("Failed to pack DNS response into UDP packet!\n"));
299 }
300 else
301 {
302 sret = GNUNET_NETWORK_socket_sendto (request->lsock,
303 buf,
304 size,
305 request->addr,
306 request->addr_len);
307 if ((sret < 0) ||
308 (size != (size_t) sret))
309 GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
310 "sendto");
311 GNUNET_free (buf);
312 }
313 GNUNET_SCHEDULER_cancel (request->timeout_task);
314 GNUNET_DNSPARSER_free_packet (request->packet);
315 GNUNET_free (request->udp_msg);
316 GNUNET_free (request);
317}
318
319
320/**
321 * Task run on timeout. Cleans up request.
322 *
323 * @param cls `struct Request *` of the request to clean up
324 */
325static void
326do_timeout (void *cls)
327{
328 struct Request *request = cls;
329 struct VpnContext *vpn_ctx;
330
331 if (NULL != request->packet)
332 GNUNET_DNSPARSER_free_packet (request->packet);
333 if (NULL != request->lookup)
334 GNUNET_GNS_lookup_with_tld_cancel (request->lookup);
335 if (NULL != request->dns_lookup)
336 GNUNET_DNSSTUB_resolve_cancel (request->dns_lookup);
337 GNUNET_free (request->udp_msg);
338 if (NULL != (vpn_ctx = request->vpn_ctx))
339 {
340 GNUNET_VPN_cancel_request (vpn_ctx->vpn_request);
341 GNUNET_free (vpn_ctx->rd_data);
342 GNUNET_free (vpn_ctx);
343 }
344 GNUNET_free (request);
345}
346
347
348/**
349 * Iterator called on obtained result for a DNS lookup
350 *
351 * @param cls closure
352 * @param dns the DNS udp payload
353 * @param r size of the DNS payload
354 */
355static void
356dns_result_processor (void *cls,
357 const struct GNUNET_TUN_DnsHeader *dns,
358 size_t r)
359{
360 struct Request *request = cls;
361
362 if (NULL == dns)
363 {
364 /* DNSSTUB gave up, so we trigger timeout early */
365 GNUNET_SCHEDULER_cancel (request->timeout_task);
366 do_timeout (request);
367 return;
368 }
369 if (request->original_request_id != dns->id)
370 {
371 /* for a another query, ignore */
372 return;
373 }
374 request->packet = GNUNET_DNSPARSER_parse ((char *) dns,
375 r);
376 if (NULL == request->packet)
377 {
378 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
379 _ ("Failed to parse DNS response!\n"));
380 GNUNET_SCHEDULER_cancel (request->timeout_task);
381 do_timeout (request);
382 return;
383 }
384 GNUNET_DNSSTUB_resolve_cancel (request->dns_lookup);
385 send_response (request);
386}
387
388/**
389 * Callback invoked from the VPN service once a redirection is
390 * available. Provides the IP address that can now be used to
391 * reach the requested destination. Replaces the "VPN" record
392 * with the respective A/AAAA record and continues processing.
393 *
394 * @param cls closure
395 * @param af address family, AF_INET or AF_INET6; AF_UNSPEC on error;
396 * will match 'result_af' from the request
397 * @param address IP address (struct in_addr or struct in_addr6, depending on 'af')
398 * that the VPN allocated for the redirection;
399 * traffic to this IP will now be redirected to the
400 * specified target peer; NULL on error
401 */
402static void
403vpn_allocation_cb (void *cls,
404 int af,
405 const void *address)
406{
407 struct VpnContext *vpn_ctx = cls;
408 struct Request *request = vpn_ctx->request;
409 struct GNUNET_GNSRECORD_Data rd[vpn_ctx->rd_count];
410 unsigned int i;
411
412 vpn_ctx->vpn_request = NULL;
413 request->vpn_ctx = NULL;
414 GNUNET_assert (GNUNET_OK ==
415 GNUNET_GNSRECORD_records_deserialize (
416 (size_t) vpn_ctx->rd_data_size,
417 vpn_ctx->rd_data,
418 vpn_ctx->rd_count,
419 rd));
420 for (i = 0; i < vpn_ctx->rd_count; i++)
421 {
422 if (GNUNET_GNSRECORD_TYPE_VPN == rd[i].record_type)
423 {
424 switch (af)
425 {
426 case AF_INET:
427 rd[i].record_type = GNUNET_DNSPARSER_TYPE_A;
428 rd[i].data_size = sizeof(struct in_addr);
429 rd[i].expiration_time = GNUNET_TIME_relative_to_absolute (
430 VPN_TIMEOUT).abs_value_us;
431 rd[i].flags = 0;
432 rd[i].data = address;
433 break;
434
435 case AF_INET6:
436 rd[i].record_type = GNUNET_DNSPARSER_TYPE_AAAA;
437 rd[i].expiration_time = GNUNET_TIME_relative_to_absolute (
438 VPN_TIMEOUT).abs_value_us;
439 rd[i].flags = 0;
440 rd[i].data = address;
441 rd[i].data_size = sizeof(struct in6_addr);
442 break;
443
444 default:
445 GNUNET_assert (0);
446 }
447 break;
448 }
449 }
450 GNUNET_assert (i < vpn_ctx->rd_count);
451 if (0 == vpn_ctx->rd_count)
452 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
453 _ ("VPN returned empty result for `%s'\n"),
454 request->packet->queries[0].name);
455 send_response (request);
456 GNUNET_free (vpn_ctx->rd_data);
457 GNUNET_free (vpn_ctx);
458}
459
460
461
462/**
463 * Iterator called on obtained result for a GNS lookup.
464 *
465 * @param cls closure
466 * @param was_gns #GNUNET_NO if the TLD is not configured for GNS
467 * @param rd_count number of records in @a rd
468 * @param rd the records in reply
469 */
470static void
471result_processor (void *cls,
472 int was_gns,
473 uint32_t rd_count,
474 const struct GNUNET_GNSRECORD_Data *rd)
475{
476 struct Request *request = cls;
477 struct GNUNET_DNSPARSER_Packet *packet;
478 struct GNUNET_DNSPARSER_Record rec;
479 struct VpnContext *vpn_ctx;
480 const struct GNUNET_TUN_GnsVpnRecord *vpn;
481 const char *vname;
482 struct GNUNET_HashCode vhash;
483 int af;
484
485 request->lookup = NULL;
486 if (GNUNET_NO == was_gns)
487 {
488 /* TLD not configured for GNS, fall back to DNS */
489 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
490 "Using DNS resolver IP `%s' to resolve `%s'\n",
491 dns_ip,
492 request->packet->queries[0].name);
493 request->original_request_id = request->packet->id;
494 GNUNET_DNSPARSER_free_packet (request->packet);
495 request->packet = NULL;
496 request->dns_lookup = GNUNET_DNSSTUB_resolve (dns_stub,
497 request->udp_msg,
498 request->udp_msg_size,
499 &dns_result_processor,
500 request);
501 return;
502 }
503 packet = request->packet;
504 packet->flags.query_or_response = 1;
505 packet->flags.return_code = GNUNET_TUN_DNS_RETURN_CODE_NO_ERROR;
506 packet->flags.checking_disabled = 0;
507 packet->flags.authenticated_data = 1;
508 packet->flags.zero = 0;
509 packet->flags.recursion_available = 1;
510 packet->flags.message_truncated = 0;
511 packet->flags.authoritative_answer = 0;
512 // packet->flags.opcode = GNUNET_TUN_DNS_OPCODE_STATUS; // ???
513 for (uint32_t i = 0; i < rd_count; i++)
514 {
515 rec.expiration_time.abs_value_us = rd[i].expiration_time;
516 switch (rd[i].record_type)
517 {
518 case GNUNET_DNSPARSER_TYPE_A:
519 GNUNET_assert (sizeof(struct in_addr) == rd[i].data_size);
520 rec.name = GNUNET_strdup (packet->queries[0].name);
521 rec.dns_traffic_class = GNUNET_TUN_DNS_CLASS_INTERNET;
522 rec.type = GNUNET_DNSPARSER_TYPE_A;
523 rec.data.raw.data = GNUNET_new (struct in_addr);
524 GNUNET_memcpy (rec.data.raw.data,
525 rd[i].data,
526 rd[i].data_size);
527 rec.data.raw.data_len = sizeof(struct in_addr);
528 GNUNET_array_append (packet->answers,
529 packet->num_answers,
530 rec);
531 break;
532
533 case GNUNET_DNSPARSER_TYPE_AAAA:
534 GNUNET_assert (sizeof(struct in6_addr) == rd[i].data_size);
535 rec.name = GNUNET_strdup (packet->queries[0].name);
536 rec.data.raw.data = GNUNET_new (struct in6_addr);
537 rec.dns_traffic_class = GNUNET_TUN_DNS_CLASS_INTERNET;
538 rec.type = GNUNET_DNSPARSER_TYPE_AAAA;
539 GNUNET_memcpy (rec.data.raw.data,
540 rd[i].data,
541 rd[i].data_size);
542 rec.data.raw.data_len = sizeof(struct in6_addr);
543 GNUNET_array_append (packet->answers,
544 packet->num_answers,
545 rec);
546 break;
547
548 case GNUNET_DNSPARSER_TYPE_CNAME:
549 rec.name = GNUNET_strdup (packet->queries[0].name);
550 rec.data.hostname = GNUNET_strdup (rd[i].data);
551 rec.dns_traffic_class = GNUNET_TUN_DNS_CLASS_INTERNET;
552 rec.type = GNUNET_DNSPARSER_TYPE_CNAME;
553 GNUNET_memcpy (rec.data.hostname,
554 rd[i].data,
555 rd[i].data_size);
556 GNUNET_array_append (packet->answers,
557 packet->num_answers,
558 rec);
559 break;
560 case GNUNET_GNSRECORD_TYPE_VPN:
561 if ((GNUNET_DNSPARSER_TYPE_A != request->packet->queries[0].type) &&
562 (GNUNET_DNSPARSER_TYPE_AAAA != request->packet->queries[0].type))
563 break;
564 af = (GNUNET_DNSPARSER_TYPE_A == request->packet->queries[0].type) ? AF_INET :
565 AF_INET6;
566 if (sizeof(struct GNUNET_TUN_GnsVpnRecord) >
567 rd[i].data_size)
568 {
569 GNUNET_break_op (0);
570 break;
571 }
572 vpn = (const struct GNUNET_TUN_GnsVpnRecord *) rd[i].data;
573 vname = (const char *) &vpn[1];
574 if ('\0' != vname[rd[i].data_size - 1 - sizeof(struct
575 GNUNET_TUN_GnsVpnRecord)
576 ])
577 {
578 GNUNET_break_op (0);
579 break;
580 }
581 GNUNET_TUN_service_name_to_hash (vname,
582 &vhash);
583 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
584 "Attempting VPN allocation for %s-%s (AF: %d, proto %d)\n",
585 GNUNET_i2s (&vpn->peer),
586 vname,
587 (int) af,
588 (int) ntohs (vpn->proto));
589 vpn_ctx = GNUNET_new (struct VpnContext);
590 request->vpn_ctx = vpn_ctx;
591 vpn_ctx->request = request;
592 vpn_ctx->rd_data_size = GNUNET_GNSRECORD_records_get_size (rd_count,
593 rd);
594 if (vpn_ctx->rd_data_size < 0)
595 {
596 GNUNET_break_op (0);
597 GNUNET_free (vpn_ctx);
598 break;
599 }
600 vpn_ctx->rd_data = GNUNET_malloc ((size_t) vpn_ctx->rd_data_size);
601 vpn_ctx->rd_count = rd_count;
602 GNUNET_assert (vpn_ctx->rd_data_size ==
603 GNUNET_GNSRECORD_records_serialize (rd_count,
604 rd,
605 (size_t) vpn_ctx
606 ->rd_data_size,
607 vpn_ctx->rd_data));
608 vpn_ctx->vpn_request = GNUNET_VPN_redirect_to_peer (vpn_handle,
609 af,
610 ntohs (
611 vpn->proto),
612 &vpn->peer,
613 &vhash,
614 GNUNET_TIME_relative_to_absolute (
615 VPN_TIMEOUT),
616 &
617 vpn_allocation_cb,
618 vpn_ctx);
619 return;
620
621
622 default:
623 /* skip */
624 break;
625 }
626 }
627 send_response (request);
628}
629
630
631/**
632 * Handle DNS request.
633 *
634 * @param lsock socket to use for sending the reply
635 * @param addr address to use for sending the reply
636 * @param addr_len number of bytes in @a addr
637 * @param udp_msg DNS request payload
638 * @param udp_msg_size number of bytes in @a udp_msg
639 */
640static void
641handle_request (struct GNUNET_NETWORK_Handle *lsock,
642 const void *addr,
643 size_t addr_len,
644 const char *udp_msg,
645 size_t udp_msg_size)
646{
647 struct Request *request;
648 struct GNUNET_DNSPARSER_Packet *packet;
649
650 packet = GNUNET_DNSPARSER_parse (udp_msg,
651 udp_msg_size);
652 if (NULL == packet)
653 {
654 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
655 _ ("Cannot parse DNS request from %s\n"),
656 GNUNET_a2s (addr, addr_len));
657 return;
658 }
659 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
660 "Received request for `%s' with flags %u, #answers %d, #auth %d, #additional %d\n",
661 packet->queries[0].name,
662 (unsigned int) packet->flags.query_or_response,
663 (int) packet->num_answers,
664 (int) packet->num_authority_records,
665 (int) packet->num_additional_records);
666 if ((0 != packet->flags.query_or_response) ||
667 (0 != packet->num_answers) ||
668 (0 != packet->num_authority_records))
669 {
670 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
671 _ ("Received malformed DNS request from %s\n"),
672 GNUNET_a2s (addr, addr_len));
673 GNUNET_DNSPARSER_free_packet (packet);
674 return;
675 }
676 if ((1 != packet->num_queries))
677 {
678 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
679 _ ("Received unsupported DNS request from %s\n"),
680 GNUNET_a2s (addr,
681 addr_len));
682 GNUNET_DNSPARSER_free_packet (packet);
683 return;
684 }
685 request = GNUNET_malloc (sizeof(struct Request) + addr_len);
686 request->lsock = lsock;
687 request->packet = packet;
688 request->addr = &request[1];
689 request->addr_len = addr_len;
690 GNUNET_memcpy (&request[1],
691 addr,
692 addr_len);
693 request->udp_msg_size = udp_msg_size;
694 request->udp_msg = GNUNET_memdup (udp_msg,
695 udp_msg_size);
696 request->timeout_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT,
697 &do_timeout,
698 request);
699 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
700 "Calling GNS on `%s'\n",
701 packet->queries[0].name);
702 request->lookup = GNUNET_GNS_lookup_with_tld (gns,
703 packet->queries[0].name,
704 packet->queries[0].type,
705 GNUNET_GNS_LO_DEFAULT,
706 &result_processor,
707 request);
708}
709
710
711/**
712 * Task to read IPv4 DNS packets.
713 *
714 * @param cls the 'listen_socket4'
715 */
716static void
717read_dns4 (void *cls)
718{
719 struct sockaddr_in v4;
720 socklen_t addrlen;
721 ssize_t size;
722 const struct GNUNET_SCHEDULER_TaskContext *tc;
723
724 GNUNET_assert (listen_socket4 == cls);
725 t4 = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL,
726 listen_socket4,
727 &read_dns4,
728 listen_socket4);
729 tc = GNUNET_SCHEDULER_get_task_context ();
730 if (0 == (GNUNET_SCHEDULER_REASON_READ_READY & tc->reason))
731 return; /* shutdown? */
732 size = GNUNET_NETWORK_socket_recvfrom_amount (listen_socket4);
733 if (0 > size)
734 {
735 GNUNET_break (0);
736 return; /* read error!? */
737 }
738 {
739 char buf[size + 1];
740 ssize_t sret;
741
742 addrlen = sizeof(v4);
743 sret = GNUNET_NETWORK_socket_recvfrom (listen_socket4,
744 buf,
745 size + 1,
746 (struct sockaddr *) &v4,
747 &addrlen);
748 if (0 > sret)
749 {
750 GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
751 "recvfrom");
752 return;
753 }
754 GNUNET_break (size == sret);
755 handle_request (listen_socket4,
756 &v4,
757 addrlen,
758 buf,
759 size);
760 }
761}
762
763
764/**
765 * Task to read IPv6 DNS packets.
766 *
767 * @param cls the 'listen_socket6'
768 */
769static void
770read_dns6 (void *cls)
771{
772 struct sockaddr_in6 v6;
773 socklen_t addrlen;
774 ssize_t size;
775 const struct GNUNET_SCHEDULER_TaskContext *tc;
776
777 GNUNET_assert (listen_socket6 == cls);
778 t6 = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL,
779 listen_socket6,
780 &read_dns6,
781 listen_socket6);
782 tc = GNUNET_SCHEDULER_get_task_context ();
783 if (0 == (GNUNET_SCHEDULER_REASON_READ_READY & tc->reason))
784 return; /* shutdown? */
785 size = GNUNET_NETWORK_socket_recvfrom_amount (listen_socket6);
786 if (0 > size)
787 {
788 GNUNET_break (0);
789 return; /* read error!? */
790 }
791 {
792 char buf[size];
793 ssize_t sret;
794
795 addrlen = sizeof(v6);
796 sret = GNUNET_NETWORK_socket_recvfrom (listen_socket6,
797 buf,
798 size,
799 (struct sockaddr *) &v6,
800 &addrlen);
801 if (0 > sret)
802 {
803 GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
804 "recvfrom");
805 return;
806 }
807 GNUNET_break (size == sret);
808 handle_request (listen_socket6,
809 &v6,
810 addrlen,
811 buf,
812 size);
813 }
814}
815
816
817/**
818 * Main function that will be run.
819 *
820 * @param cls closure
821 * @param args remaining command-line arguments
822 * @param cfgfile name of the configuration file used (for saving, can be NULL!)
823 * @param c configuration
824 */
825static void
826run (void *cls,
827 char *const *args,
828 const char *cfgfile,
829 const struct GNUNET_CONFIGURATION_Handle *c)
830{
831 char *addr_str;
832
833 (void) cls;
834 (void) args;
835 (void) cfgfile;
836 cfg = c;
837 if (NULL == dns_ip)
838 {
839 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
840 _ ("No DNS server specified!\n"));
841 return;
842 }
843 GNUNET_SCHEDULER_add_shutdown (&do_shutdown,
844 NULL);
845 if (NULL == (gns = GNUNET_GNS_connect (cfg)))
846 return;
847 if (NULL == (vpn_handle = GNUNET_VPN_connect (cfg)))
848 return;
849 GNUNET_assert (NULL != (dns_stub = GNUNET_DNSSTUB_start (128)));
850 if (GNUNET_OK !=
851 GNUNET_DNSSTUB_add_dns_ip (dns_stub,
852 dns_ip))
853 {
854 GNUNET_DNSSTUB_stop (dns_stub);
855 GNUNET_GNS_disconnect (gns);
856 gns = NULL;
857 GNUNET_VPN_disconnect (vpn_handle);
858 vpn_handle = NULL;
859 return;
860 }
861
862 /* Get address to bind to */
863 if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string (c, "dns2gns",
864 "BIND_TO",
865 &addr_str))
866 {
867 // No address specified
868 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
869 "Don't know what to bind to...\n");
870 GNUNET_free (addr_str);
871 GNUNET_SCHEDULER_shutdown ();
872 return;
873 }
874 if (1 != inet_pton (AF_INET, addr_str, &address))
875 {
876 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
877 "Unable to parse address %s\n",
878 addr_str);
879 GNUNET_free (addr_str);
880 GNUNET_SCHEDULER_shutdown ();
881 return;
882 }
883 GNUNET_free (addr_str);
884 /* Get address to bind to */
885 if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string (c, "dns2gns",
886 "BIND_TO6",
887 &addr_str))
888 {
889 // No address specified
890 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
891 "Don't know what to bind6 to...\n");
892 GNUNET_free (addr_str);
893 GNUNET_SCHEDULER_shutdown ();
894 return;
895 }
896 if (1 != inet_pton (AF_INET6, addr_str, &address6))
897 {
898 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
899 "Unable to parse IPv6 address %s\n",
900 addr_str);
901 GNUNET_free (addr_str);
902 GNUNET_SCHEDULER_shutdown ();
903 return;
904 }
905 GNUNET_free (addr_str);
906
907 listen_socket4 = GNUNET_NETWORK_socket_create (PF_INET,
908 SOCK_DGRAM,
909 IPPROTO_UDP);
910 if (NULL != listen_socket4)
911 {
912 struct sockaddr_in v4;
913
914 memset (&v4, 0, sizeof(v4));
915 v4.sin_family = AF_INET;
916 v4.sin_addr.s_addr = address;
917#if HAVE_SOCKADDR_IN_SIN_LEN
918 v4.sin_len = sizeof(v4);
919#endif
920 v4.sin_port = htons (listen_port);
921 if (GNUNET_OK !=
922 GNUNET_NETWORK_socket_bind (listen_socket4,
923 (struct sockaddr *) &v4,
924 sizeof(v4)))
925 {
926 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "bind");
927 GNUNET_NETWORK_socket_close (listen_socket4);
928 listen_socket4 = NULL;
929 }
930 }
931 listen_socket6 = GNUNET_NETWORK_socket_create (PF_INET6,
932 SOCK_DGRAM,
933 IPPROTO_UDP);
934 if (NULL != listen_socket6)
935 {
936 struct sockaddr_in6 v6;
937
938 memset (&v6, 0, sizeof(v6));
939 v6.sin6_family = AF_INET6;
940 v6.sin6_addr = address6;
941#if HAVE_SOCKADDR_IN_SIN_LEN
942 v6.sin6_len = sizeof(v6);
943#endif
944 v6.sin6_port = htons (listen_port);
945 if (GNUNET_OK !=
946 GNUNET_NETWORK_socket_bind (listen_socket6,
947 (struct sockaddr *) &v6,
948 sizeof(v6)))
949 {
950 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "bind");
951 GNUNET_NETWORK_socket_close (listen_socket6);
952 listen_socket6 = NULL;
953 }
954 }
955 if ((NULL == listen_socket4) &&
956 (NULL == listen_socket6))
957 {
958 GNUNET_GNS_disconnect (gns);
959 gns = NULL;
960 GNUNET_VPN_disconnect (vpn_handle);
961 vpn_handle = NULL;
962 GNUNET_DNSSTUB_stop (dns_stub);
963 dns_stub = NULL;
964 return;
965 }
966 if (NULL != listen_socket4)
967 t4 = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL,
968 listen_socket4,
969 &read_dns4,
970 listen_socket4);
971 if (NULL != listen_socket6)
972 t6 = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL,
973 listen_socket6,
974 &read_dns6,
975 listen_socket6);
976}
977
978
979/**
980 * The main function for the dns2gns daemon.
981 *
982 * @param argc number of arguments from the command line
983 * @param argv command line arguments
984 * @return 0 ok, 1 on error
985 */
986int
987main (int argc,
988 char *const *argv)
989{
990 struct GNUNET_GETOPT_CommandLineOption options[] = {
991 GNUNET_GETOPT_option_string ('d',
992 "dns",
993 "IP",
994 gettext_noop (
995 "IP of recursive DNS resolver to use (required)"),
996 &dns_ip),
997 GNUNET_GETOPT_option_uint ('p',
998 "port",
999 "UDPPORT",
1000 gettext_noop (
1001 "UDP port to listen on for inbound DNS requests; default: 2853"),
1002 &listen_port),
1003 GNUNET_GETOPT_OPTION_END
1004 };
1005 int ret;
1006
1007 if (GNUNET_OK !=
1008 GNUNET_STRINGS_get_utf8_args (argc, argv,
1009 &argc, &argv))
1010 return 2;
1011 GNUNET_log_setup ("gnunet-dns2gns",
1012 "WARNING",
1013 NULL);
1014 ret =
1015 (GNUNET_OK ==
1016 GNUNET_PROGRAM_run (argc, argv,
1017 "gnunet-dns2gns",
1018 _ ("GNUnet DNS-to-GNS proxy (a DNS server)"),
1019 options,
1020 &run, NULL)) ? 0 : 1;
1021 GNUNET_free_nz ((void *) argv);
1022 return ret;
1023}
1024
1025
1026/* end of gnunet-dns2gns.c */