2 This file is part of GNUnet.
3 (C) 2009 Christian Grothoff (and other contributing authors)
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.
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.
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., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
22 * @file vpn/gnunet-service-dns.c
23 * @author Philipp Toelke
26 #include "gnunet_getopt_lib.h"
27 #include "gnunet_service_lib.h"
28 #include <gnunet_constants.h>
29 #include "gnunet_network_lib.h"
30 #include "gnunet_os_lib.h"
31 #include "gnunet-service-dns-p.h"
32 #include "gnunet_protocols.h"
33 #include "gnunet_applications.h"
34 #include "gnunet-vpn-packet.h"
35 #include "gnunet_container_lib.h"
36 #include "gnunet-dns-parser.h"
37 #include "gnunet_dht_service.h"
38 #include "gnunet_block_lib.h"
39 #include "block_dns.h"
40 #include "gnunet_crypto_lib.h"
41 #include "gnunet_mesh_service.h"
42 #include "gnunet_signatures.h"
44 struct GNUNET_MESH_Handle *mesh_handle;
46 struct GNUNET_CONNECTION_TransmitHandle *server_notify;
49 * The UDP-Socket through which DNS-Resolves will be sent if they are not to be
50 * sent through gnunet. The port of this socket will not be hijacked.
52 static struct GNUNET_NETWORK_Handle *dnsout;
53 static struct GNUNET_NETWORK_Handle *dnsout6;
56 * The port bound to the socket dnsout
58 static unsigned short dnsoutport;
61 * A handle to the DHT-Service
63 static struct GNUNET_DHT_Handle *dht;
66 * The configuration to use
68 static const struct GNUNET_CONFIGURATION_Handle *cfg;
71 * A list of DNS-Responses that have to be sent to the requesting client
73 static struct answer_packet_list *head;
76 * The tail of the list of DNS-responses
78 static struct answer_packet_list *tail;
81 * A structure containing a mapping from network-byte-ordered DNS-id (16 bit) to
82 * some information needed to handle this query
84 * It currently allocates at least
85 * (1 + machine-width + machine-width + 32 + 32 + 16 + machine-width + 8) * 65536 bit
92 struct GNUNET_SERVER_Client *client;
93 struct GNUNET_MESH_Tunnel *tunnel;
101 } query_states[UINT16_MAX+1];
104 * A struct used to give more than one value as
105 * closure to receive_dht
107 struct receive_dht_cls
110 struct GNUNET_DHT_GetHandle *handle;
113 struct tunnel_notify_queue
115 struct tunnel_notify_queue *next;
116 struct tunnel_notify_queue *prev;
119 GNUNET_CONNECTION_TransmitReadyNotify cb;
123 * Hijack all outgoing DNS-Traffic but for traffic leaving "our" port.
127 __attribute__ ((unused)), const struct GNUNET_SCHEDULER_TaskContext *tc)
129 if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
134 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
135 "Delaying the hijacking, port is still %d!\n", dnsoutport);
136 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS, &hijack, NULL);
142 struct GNUNET_OS_Process *proc;
145 GNUNET_CONFIGURATION_get_value_string (cfg, "vpn", "VIRTDNS", &virt_dns))
147 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
148 "No entry 'VIRTDNS' in configuration!\n");
152 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Hijacking, port is %d\n", dnsoutport);
153 snprintf (port_s, 6, "%d", dnsoutport);
156 GNUNET_OS_start_process (NULL, NULL, "gnunet-helper-hijack-dns",
157 "gnunet-hijack-dns", port_s, virt_dns, NULL)))
159 GNUNET_break (GNUNET_OK == GNUNET_OS_process_wait (proc));
160 GNUNET_OS_process_close (proc);
162 GNUNET_free (virt_dns);
166 * Delete the hijacking-routes
169 unhijack (unsigned short port)
173 struct GNUNET_OS_Process *proc;
176 GNUNET_CONFIGURATION_get_value_string (cfg, "vpn", "VIRTDNS", &virt_dns))
178 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
179 "No entry 'VIRTDNS' in configuration!\n");
183 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "unHijacking, port is %d\n", port);
184 snprintf (port_s, 6, "%d", port);
187 GNUNET_OS_start_process (NULL, NULL, "gnunet-helper-hijack-dns",
188 "gnunet-hijack-dns", "-d", port_s, virt_dns,
191 GNUNET_break (GNUNET_OK == GNUNET_OS_process_wait (proc));
192 GNUNET_OS_process_close (proc);
194 GNUNET_free (virt_dns);
198 * Send the DNS-Response to the client. Gets called via the notify_transmit_ready-
202 send_answer (void *cls, size_t size, void *buf)
204 server_notify = NULL;
205 struct answer_packet_list *query = head;
206 size_t len = ntohs (query->pkt.hdr.size);
208 GNUNET_assert (len <= size);
210 memcpy (buf, &query->pkt.hdr, len);
212 GNUNET_CONTAINER_DLL_remove (head, tail, query);
216 /* When more data is to be sent, reschedule */
218 server_notify = GNUNET_SERVER_notify_transmit_ready (cls, ntohs (head->pkt.hdr.size),
219 GNUNET_TIME_UNIT_FOREVER_REL,
227 struct GNUNET_MESH_Tunnel *tunnel GNUNET_PACKED;
228 struct GNUNET_MessageHeader hdr;
232 struct tunnel_cls *remote_pending[UINT16_MAX];
235 mesh_send_response (void *cls, size_t size, void *buf)
237 GNUNET_assert (size >= sizeof (struct GNUNET_MessageHeader));
238 struct GNUNET_MessageHeader *hdr = buf;
240 struct GNUNET_MESH_Tunnel **tunnel = (struct GNUNET_MESH_Tunnel **) (sz + 1);
241 struct dns_pkt *dns = (struct dns_pkt *) (tunnel + 1);
243 GNUNET_MESH_tunnel_set_data (*tunnel, NULL);
245 hdr->type = htons (GNUNET_MESSAGE_TYPE_VPN_REMOTE_ANSWER_DNS);
246 hdr->size = htons (*sz + sizeof (struct GNUNET_MessageHeader));
248 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
249 "Sending response, size=%d, sz=%d, sz+hdr=%d\n", size, *sz,
250 *sz + sizeof (struct GNUNET_MessageHeader));
252 GNUNET_assert (size >= (*sz + sizeof (struct GNUNET_MessageHeader)));
254 memcpy (hdr + 1, dns, *sz);
256 if (NULL != GNUNET_MESH_tunnel_get_head (*tunnel))
258 struct tunnel_notify_queue *element = GNUNET_MESH_tunnel_get_head (*tunnel);
259 struct tunnel_notify_queue *head = GNUNET_MESH_tunnel_get_head (*tunnel);
260 struct tunnel_notify_queue *tail = GNUNET_MESH_tunnel_get_tail (*tunnel);
262 GNUNET_CONTAINER_DLL_remove (head, tail, element);
264 GNUNET_MESH_tunnel_set_head (*tunnel, head);
265 GNUNET_MESH_tunnel_set_tail (*tunnel, tail);
266 struct GNUNET_MESH_TransmitHandle *th =
267 GNUNET_MESH_notify_transmit_ready (*tunnel,
270 GNUNET_TIME_relative_divide
271 (GNUNET_CONSTANTS_MAX_CORK_DELAY, 2),
272 (const struct GNUNET_PeerIdentity *)
274 element->cb, element->cls);
276 /* save the handle */
277 GNUNET_MESH_tunnel_set_data (*tunnel, th);
282 return ntohs (hdr->size);
286 mesh_send (void *cls, size_t size, void *buf)
288 struct tunnel_cls *cls_ = (struct tunnel_cls *) cls;
290 GNUNET_MESH_tunnel_set_data (cls_->tunnel, NULL);
292 GNUNET_assert (cls_->hdr.size <= size);
294 size = cls_->hdr.size;
295 cls_->hdr.size = htons (cls_->hdr.size);
297 memcpy (buf, &cls_->hdr, size);
299 if (NULL != GNUNET_MESH_tunnel_get_head (cls_->tunnel))
301 struct tunnel_notify_queue *element =
302 GNUNET_MESH_tunnel_get_head (cls_->tunnel);
303 struct tunnel_notify_queue *head =
304 GNUNET_MESH_tunnel_get_head (cls_->tunnel);
305 struct tunnel_notify_queue *tail =
306 GNUNET_MESH_tunnel_get_tail (cls_->tunnel);
308 GNUNET_CONTAINER_DLL_remove (head, tail, element);
310 GNUNET_MESH_tunnel_set_head (cls_->tunnel, head);
311 GNUNET_MESH_tunnel_set_tail (cls_->tunnel, tail);
312 struct GNUNET_MESH_TransmitHandle *th =
313 GNUNET_MESH_notify_transmit_ready (cls_->tunnel,
316 GNUNET_TIME_relative_divide
317 (GNUNET_CONSTANTS_MAX_CORK_DELAY, 2),
318 (const struct GNUNET_PeerIdentity *)
320 element->cb, element->cls);
322 /* save the handle */
323 GNUNET_MESH_tunnel_set_data (cls_->tunnel, th);
324 GNUNET_free (element);
332 mesh_connect (void *cls, const struct GNUNET_PeerIdentity *peer,
333 const struct GNUNET_ATS_Information *atsi
334 __attribute__ ((unused)),
335 unsigned int atsi_count
336 __attribute__ ((unused)))
340 struct tunnel_cls *cls_ = (struct tunnel_cls *) cls;
342 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
343 "Connected to peer %s, %x, sending query with id %d\n",
344 GNUNET_i2s (peer), peer, ntohs (cls_->dns.s.id));
346 if (NULL == GNUNET_MESH_tunnel_get_data (cls_->tunnel))
348 struct GNUNET_MESH_TransmitHandle *th =
349 GNUNET_MESH_notify_transmit_ready (cls_->tunnel,
352 GNUNET_TIME_UNIT_MINUTES,
358 GNUNET_MESH_tunnel_set_data (cls_->tunnel, th);
362 struct tunnel_notify_queue *head =
363 GNUNET_MESH_tunnel_get_head (cls_->tunnel);
364 struct tunnel_notify_queue *tail =
365 GNUNET_MESH_tunnel_get_tail (cls_->tunnel);
367 struct tunnel_notify_queue *element =
368 GNUNET_malloc (sizeof (struct tunnel_notify_queue));
370 element->len = cls_->hdr.size;
371 element->cb = mesh_send;
373 GNUNET_CONTAINER_DLL_insert_tail (head, tail, element);
374 GNUNET_MESH_tunnel_set_head (cls_->tunnel, head);
375 GNUNET_MESH_tunnel_set_tail (cls_->tunnel, tail);
381 send_mesh_query (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
383 if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
386 struct tunnel_cls *cls_ = (struct tunnel_cls *) cls;
389 GNUNET_MESH_peer_request_connect_by_type (mesh_handle,
390 GNUNET_TIME_UNIT_HOURS,
391 GNUNET_APPLICATION_TYPE_INTERNET_RESOLVER,
392 mesh_connect, NULL, cls_);
394 remote_pending[cls_->dns.s.id] = cls_;
398 receive_mesh_query (void *cls
399 __attribute__ ((unused)), struct GNUNET_MESH_Tunnel *tunnel,
401 __attribute__ ((unused)),
402 const struct GNUNET_PeerIdentity *sender
403 __attribute__ ((unused)),
404 const struct GNUNET_MessageHeader *message,
405 const struct GNUNET_ATS_Information *atsi
406 __attribute__ ((unused)),
407 unsigned int atsi_count
408 __attribute__ ((unused)))
410 struct dns_pkt *dns = (struct dns_pkt *) (message + 1);
412 struct sockaddr_in dest;
414 memset (&dest, 0, sizeof dest);
415 dest.sin_port = htons (53);
417 if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string(cfg, "dns", "EXTERNAL_DNS", &dns_resolver) ||
418 1 != inet_pton (AF_INET, dns_resolver, &dest.sin_addr))
419 inet_pton (AF_INET, "8.8.8.8", &dest.sin_addr);
421 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Querying for remote, id=%d\n",
423 query_states[dns->s.id].tunnel = tunnel;
424 query_states[dns->s.id].valid = GNUNET_YES;
426 GNUNET_NETWORK_socket_sendto (dnsout, dns,
427 ntohs (message->size) -
428 sizeof (struct GNUNET_MessageHeader),
429 (struct sockaddr *) &dest, sizeof dest);
431 return GNUNET_SYSERR;
435 receive_mesh_answer (void *cls
436 __attribute__ ((unused)),
437 struct GNUNET_MESH_Tunnel *tunnel, void **ctx
438 __attribute__ ((unused)),
439 const struct GNUNET_PeerIdentity *sender,
440 const struct GNUNET_MessageHeader *message,
441 const struct GNUNET_ATS_Information *atsi
442 __attribute__ ((unused)),
443 unsigned int atsi_count
444 __attribute__ ((unused)))
446 /* TODo: size check */
447 struct dns_pkt *dns = (struct dns_pkt *) (message + 1);
449 /* They sent us a packet we were not waiting for */
450 if (remote_pending[dns->s.id] == NULL ||
451 remote_pending[dns->s.id]->tunnel != tunnel)
454 GNUNET_free (remote_pending[dns->s.id]);
455 remote_pending[dns->s.id] = NULL;
457 if (query_states[dns->s.id].valid != GNUNET_YES)
458 return GNUNET_SYSERR;
459 query_states[dns->s.id].valid = GNUNET_NO;
461 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
462 "Received answer from peer %s, dns-id %d\n", GNUNET_i2s (sender),
465 size_t len = sizeof (struct answer_packet) - 1 + sizeof (struct dns_static) + query_states[dns->s.id].namelen + sizeof (struct dns_query_line) + 2 /* To hold the pointer (as defined in RFC1035) to the name */
466 + sizeof (struct dns_record_line) - 1 + 16; /* To hold the IPv6-Address */
468 struct answer_packet_list *answer =
469 GNUNET_malloc (len + 2 * sizeof (struct answer_packet_list *));
471 answer->pkt.hdr.type = htons (GNUNET_MESSAGE_TYPE_VPN_DNS_LOCAL_RESPONSE_DNS);
472 answer->pkt.hdr.size = htons (len);
474 struct dns_pkt_parsed *pdns = parse_dns_packet (dns);
476 if (ntohs (pdns->s.ancount) < 1)
478 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Answer only contains %d answers.\n",
479 ntohs (pdns->s.ancount));
480 free_parsed_dns_packet (pdns);
481 GNUNET_free (answer);
487 while (i < ntohs(pdns->s.ancount) &&
488 pdns->answers[i]->type != 28 &&
489 pdns->answers[i]->type != 1)
492 if (i >= ntohs (pdns->s.ancount))
494 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Answer does not contain any usable answers.\n");
495 free_parsed_dns_packet (pdns);
496 GNUNET_free (answer);
500 answer->pkt.addrsize = ntohs (pdns->answers[i]->data_len);
501 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "The first answer has the addrlen %d\n",
502 answer->pkt.addrsize);
503 memcpy (answer->pkt.addr, pdns->answers[i]->data,
504 ntohs (pdns->answers[i]->data_len));
506 memcpy(answer->pkt.from, query_states[dns->s.id].remote_ip, query_states[dns->s.id].addrlen);
507 memcpy(answer->pkt.to, query_states[dns->s.id].local_ip, query_states[dns->s.id].addrlen);
508 answer->pkt.addrlen = query_states[dns->s.id].addrlen;
509 answer->pkt.dst_port = query_states[dns->s.id].local_port;
511 struct dns_pkt *dpkt = (struct dns_pkt *) answer->pkt.data;
513 dpkt->s.id = dns->s.id;
517 dpkt->s.qdcount = htons (1);
518 dpkt->s.ancount = htons (1);
520 memcpy (dpkt->data, query_states[dns->s.id].name,
521 query_states[dns->s.id].namelen);
522 GNUNET_free (query_states[dns->s.id].name);
523 query_states[dns->s.id].name = NULL;
525 struct dns_query_line *dque =
526 (struct dns_query_line *) (dpkt->data +
527 (query_states[dns->s.id].namelen));
529 struct dns_record_line *drec_data =
530 (struct dns_record_line *) (dpkt->data +
531 (query_states[dns->s.id].namelen) +
532 sizeof (struct dns_query_line) + 2);
533 if (ntohs(28) == query_states[dns->s.id].qtype)
535 answer->pkt.subtype = GNUNET_DNS_ANSWER_TYPE_REMOTE_AAAA;
536 dque->type = htons (28); /* AAAA */
537 drec_data->type = htons (28); /* AAAA */
538 drec_data->data_len = htons (16);
540 if (ntohs(1) == query_states[dns->s.id].qtype)
542 answer->pkt.subtype = GNUNET_DNS_ANSWER_TYPE_REMOTE_A;
543 dque->type = htons (1); /* A */
544 drec_data->type = htons (1); /* A */
545 drec_data->data_len = htons (4);
549 GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "dns-answer with data_len = %d\n", answer->pkt.addrsize);
552 dque->class = htons (1); /* IN */
555 (char *) (dpkt->data + (query_states[dns->s.id].namelen) +
556 sizeof (struct dns_query_line));
557 memcpy (anname, "\xc0\x0c", 2);
558 drec_data->class = htons (1); /* IN */
560 drec_data->ttl = pdns->answers[i]->ttl;
562 /* Calculate at which offset in the packet the IPv6-Address belongs, it is
563 * filled in by the daemon-vpn */
564 answer->pkt.addroffset =
565 htons ((unsigned short) ((unsigned long) (&drec_data->data) -
566 (unsigned long) (&answer->pkt)));
568 GNUNET_CONTAINER_DLL_insert_after (head, tail, tail, answer);
570 if (server_notify == NULL)
571 server_notify = GNUNET_SERVER_notify_transmit_ready (query_states[dns->s.id].client, len,
572 GNUNET_TIME_UNIT_FOREVER_REL,
574 query_states[dns->s.id].client);
576 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
577 "Sent answer of length %d on to client, addroffset = %d\n", len,
578 answer->pkt.addroffset);
580 free_parsed_dns_packet (pdns);
586 send_rev_query (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
588 if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
591 struct dns_pkt_parsed *pdns = (struct dns_pkt_parsed *) cls;
593 unsigned short id = pdns->s.id;
595 free_parsed_dns_packet (pdns);
597 if (query_states[id].valid != GNUNET_YES)
599 query_states[id].valid = GNUNET_NO;
601 GNUNET_assert (query_states[id].namelen == 74);
603 size_t len = sizeof (struct answer_packet) - 1 + sizeof (struct dns_static) + 74 /* this is the length of a reverse ipv6-lookup */
604 + sizeof (struct dns_query_line) + 2 /* To hold the pointer (as defined in RFC1035) to the name */
605 + sizeof (struct dns_record_line) - 1 -
606 2 /* We do not know the lenght of the answer yet */ ;
608 struct answer_packet_list *answer =
609 GNUNET_malloc (len + 2 * sizeof (struct answer_packet_list *));
611 answer->pkt.hdr.type = htons (GNUNET_MESSAGE_TYPE_VPN_DNS_LOCAL_RESPONSE_DNS);
612 answer->pkt.hdr.size = htons (len);
613 answer->pkt.subtype = GNUNET_DNS_ANSWER_TYPE_REV;
615 memcpy(answer->pkt.from, query_states[id].remote_ip, query_states[id].addrlen);
616 memcpy(answer->pkt.to, query_states[id].local_ip, query_states[id].addrlen);
618 answer->pkt.dst_port = query_states[id].local_port;
620 struct dns_pkt *dpkt = (struct dns_pkt *) answer->pkt.data;
626 dpkt->s.qdcount = htons (1);
627 dpkt->s.ancount = htons (1);
629 memcpy (dpkt->data, query_states[id].name, query_states[id].namelen);
630 GNUNET_free (query_states[id].name);
631 query_states[id].name = NULL;
633 struct dns_query_line *dque =
634 (struct dns_query_line *) (dpkt->data + (query_states[id].namelen));
635 dque->type = htons (12); /* PTR */
636 dque->class = htons (1); /* IN */
639 (char *) (dpkt->data + (query_states[id].namelen) +
640 sizeof (struct dns_query_line));
641 memcpy (anname, "\xc0\x0c", 2);
643 struct dns_record_line *drec_data =
644 (struct dns_record_line *) (dpkt->data + (query_states[id].namelen) +
645 sizeof (struct dns_query_line) + 2);
646 drec_data->type = htons (12); /* AAAA */
647 drec_data->class = htons (1); /* IN */
648 /* FIXME: read the TTL from block:
649 * GNUNET_TIME_absolute_get_remaining(rec->expiration_time)
651 * But how to get the seconds out of this?
653 drec_data->ttl = htonl (3600);
655 /* Calculate at which offset in the packet the length of the name and the
656 * name, it is filled in by the daemon-vpn */
657 answer->pkt.addroffset =
658 htons ((unsigned short) ((unsigned long) (&drec_data->data_len) -
659 (unsigned long) (&answer->pkt)));
661 GNUNET_CONTAINER_DLL_insert_after (head, tail, tail, answer);
663 if (server_notify == NULL)
664 server_notify = GNUNET_SERVER_notify_transmit_ready (query_states[id].client, len,
665 GNUNET_TIME_UNIT_FOREVER_REL,
666 &send_answer, query_states[id].client);
670 * Receive a block from the dht.
673 receive_dht (void *cls, struct GNUNET_TIME_Absolute exp
674 __attribute__ ((unused)), const GNUNET_HashCode * key
675 __attribute__ ((unused)),
676 const struct GNUNET_PeerIdentity *get_path __attribute__ ((unused)),
677 unsigned int get_path_length __attribute__ ((unused)),
678 const struct GNUNET_PeerIdentity *put_path __attribute__ ((unused)),
679 unsigned int put_path_length __attribute__ ((unused)),
680 enum GNUNET_BLOCK_Type type, size_t size,
684 unsigned short id = ((struct receive_dht_cls *) cls)->id;
685 struct GNUNET_DHT_GetHandle *handle =
686 ((struct receive_dht_cls *) cls)->handle;
689 GNUNET_DHT_get_stop (handle);
691 GNUNET_assert (type == GNUNET_BLOCK_TYPE_DNS);
693 /* If no query with this id is pending, ignore the block */
694 if (query_states[id].valid != GNUNET_YES)
696 query_states[id].valid = GNUNET_NO;
698 const struct GNUNET_DNS_Record *rec = data;
700 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
701 "Got block of size %d, peer: %08x, desc: %08x\n", size,
702 *((unsigned int *) &rec->peer),
703 *((unsigned int *) &rec->service_descriptor));
705 size_t len = sizeof (struct answer_packet) - 1 + sizeof (struct dns_static) + query_states[id].namelen + sizeof (struct dns_query_line) + 2 /* To hold the pointer (as defined in RFC1035) to the name */
706 + sizeof (struct dns_record_line) - 1 + 16; /* To hold the IPv6-Address */
708 struct answer_packet_list *answer =
709 GNUNET_malloc (len + 2 * sizeof (struct answer_packet_list *));
711 answer->pkt.hdr.type = htons (GNUNET_MESSAGE_TYPE_VPN_DNS_LOCAL_RESPONSE_DNS);
712 answer->pkt.hdr.size = htons (len);
713 answer->pkt.subtype = GNUNET_DNS_ANSWER_TYPE_SERVICE;
715 GNUNET_CRYPTO_hash (&rec->peer,
716 sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded),
717 &answer->pkt.service_descr.peer);
719 memcpy (&answer->pkt.service_descr.service_descriptor,
720 &rec->service_descriptor, sizeof (GNUNET_HashCode));
721 memcpy (&answer->pkt.service_descr.service_type, &rec->service_type,
722 sizeof (answer->pkt.service_descr.service_type));
723 memcpy (&answer->pkt.service_descr.ports, &rec->ports,
724 sizeof (answer->pkt.service_descr.ports));
726 memcpy(answer->pkt.from, query_states[id].remote_ip, query_states[id].addrlen);
727 memcpy(answer->pkt.to, query_states[id].local_ip, query_states[id].addrlen);
728 answer->pkt.addrlen = query_states[id].addrlen;
730 answer->pkt.dst_port = query_states[id].local_port;
732 struct dns_pkt *dpkt = (struct dns_pkt *) answer->pkt.data;
738 dpkt->s.qdcount = htons (1);
739 dpkt->s.ancount = htons (1);
741 memcpy (dpkt->data, query_states[id].name, query_states[id].namelen);
742 GNUNET_free (query_states[id].name);
743 query_states[id].name = NULL;
745 struct dns_query_line *dque =
746 (struct dns_query_line *) (dpkt->data + (query_states[id].namelen));
747 dque->type = htons (28); /* AAAA */
748 dque->class = htons (1); /* IN */
751 (char *) (dpkt->data + (query_states[id].namelen) +
752 sizeof (struct dns_query_line));
753 memcpy (anname, "\xc0\x0c", 2);
755 struct dns_record_line *drec_data =
756 (struct dns_record_line *) (dpkt->data + (query_states[id].namelen) +
757 sizeof (struct dns_query_line) + 2);
758 drec_data->type = htons (28); /* AAAA */
759 drec_data->class = htons (1); /* IN */
761 /* FIXME: read the TTL from block:
762 * GNUNET_TIME_absolute_get_remaining(rec->expiration_time)
764 * But how to get the seconds out of this?
766 drec_data->ttl = htonl (3600);
767 drec_data->data_len = htons (16);
769 /* Calculate at which offset in the packet the IPv6-Address belongs, it is
770 * filled in by the daemon-vpn */
771 answer->pkt.addroffset =
772 htons ((unsigned short) ((unsigned long) (&drec_data->data) -
773 (unsigned long) (&answer->pkt)));
775 GNUNET_CONTAINER_DLL_insert_after (head, tail, tail, answer);
777 if (server_notify == NULL)
778 server_notify = GNUNET_SERVER_notify_transmit_ready (query_states[id].client, len,
779 GNUNET_TIME_UNIT_FOREVER_REL,
780 &send_answer, query_states[id].client);
784 * This receives a GNUNET_MESSAGE_TYPE_REHIJACK and rehijacks the DNS
788 __attribute__ ((unused)), struct GNUNET_SERVER_Client *client,
789 const struct GNUNET_MessageHeader *message __attribute__ ((unused)))
791 unhijack (dnsoutport);
792 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS, &hijack, NULL);
794 GNUNET_SERVER_receive_done (client, GNUNET_OK);
798 * This receives the dns-payload from the daemon-vpn and sends it on over the udp-socket
801 receive_query (void *cls
802 __attribute__ ((unused)), struct GNUNET_SERVER_Client *client,
803 const struct GNUNET_MessageHeader *message)
805 struct query_packet *pkt = (struct query_packet *) message;
806 struct dns_pkt *dns = (struct dns_pkt *) pkt->data;
807 struct dns_pkt_parsed *pdns = parse_dns_packet (dns);
809 query_states[dns->s.id].valid = GNUNET_YES;
810 query_states[dns->s.id].client = client;
811 memcpy(query_states[dns->s.id].local_ip, pkt->orig_from, pkt->addrlen);
812 query_states[dns->s.id].addrlen = pkt->addrlen;
813 query_states[dns->s.id].local_port = pkt->src_port;
814 memcpy(query_states[dns->s.id].remote_ip, pkt->orig_to, pkt->addrlen);
815 query_states[dns->s.id].namelen = strlen ((char *) dns->data) + 1;
816 if (query_states[dns->s.id].name != NULL)
817 GNUNET_free (query_states[dns->s.id].name);
818 query_states[dns->s.id].name =
819 GNUNET_malloc (query_states[dns->s.id].namelen);
820 memcpy (query_states[dns->s.id].name, dns->data,
821 query_states[dns->s.id].namelen);
824 for (i= 0; i < ntohs(pdns->s.qdcount); i++)
826 if (pdns->queries[i]->qtype == htons(28) ||
827 pdns->queries[i]->qtype == htons(28))
829 query_states[dns->s.id].qtype = pdns->queries[i]->qtype;
834 /* The query is for a .gnunet-address */
835 if (pdns->queries[0]->namelen > 9 &&
836 0 == strncmp (pdns->queries[0]->name + (pdns->queries[0]->namelen - 9),
839 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Query for .gnunet!\n");
842 GNUNET_CRYPTO_hash (pdns->queries[0]->name, pdns->queries[0]->namelen,
845 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Getting with key %08x, len is %d\n",
846 *((unsigned int *) &key), pdns->queries[0]->namelen);
848 struct receive_dht_cls *cls =
849 GNUNET_malloc (sizeof (struct receive_dht_cls));
853 GNUNET_DHT_get_start (dht, GNUNET_TIME_UNIT_MINUTES,
854 GNUNET_BLOCK_TYPE_DNS, &key,
855 5 /* DEFAULT_GET_REPLICATION */, GNUNET_DHT_RO_NONE, NULL,
856 0, &receive_dht, cls);
861 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Query for '%s'; namelen=%d\n",
862 pdns->queries[0]->name, pdns->queries[0]->namelen);
864 /* This is a PTR-Query. Check if it is for "our" network */
865 if (htons (pdns->queries[0]->qtype) == 12 && 74 == pdns->queries[0]->namelen)
870 "X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.ip6.arpa.";
872 unsigned long long ipv6prefix;
873 unsigned int comparelen;
875 GNUNET_assert (GNUNET_OK ==
876 GNUNET_CONFIGURATION_get_value_string (cfg, "vpn",
879 inet_pton (AF_INET6, ipv6addr, ipv6);
880 GNUNET_free (ipv6addr);
882 GNUNET_assert (GNUNET_OK ==
883 GNUNET_CONFIGURATION_get_value_number (cfg, "vpn",
886 GNUNET_assert (ipv6prefix < 127);
887 ipv6prefix = (ipv6prefix + 7) / 8;
889 for (i = ipv6prefix; i < 16; i++)
892 for (i = 0; i < 16; i++)
894 unsigned char c1 = ipv6[i] >> 4;
895 unsigned char c2 = ipv6[i] & 0xf;
898 ipv6rev[62 - (4 * i)] = c1 + '0';
900 ipv6rev[62 - (4 * i)] = c1 + 87; /* 87 is the difference between 'a' and 10 */
903 ipv6rev[62 - ((4 * i) + 2)] = c2 + '0';
905 ipv6rev[62 - ((4 * i) + 2)] = c2 + 87;
907 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "My network is %s'.\n", ipv6rev);
908 comparelen = 10 + 4 * ipv6prefix;
910 strncmp (pdns->queries[0]->name +
911 (pdns->queries[0]->namelen - comparelen),
912 ipv6rev + (74 - comparelen), comparelen))
914 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Reverse-Query for .gnunet!\n");
916 GNUNET_SCHEDULER_add_now (send_rev_query, pdns);
922 unsigned char virt_dns_bytes[16];
924 if (pkt->addrlen == 4)
929 GNUNET_CONFIGURATION_get_value_string (cfg, "vpn", "VIRTDNS", &virt_dns))
931 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
932 "No entry 'VIRTDNS' in configuration!\n");
936 if (1 != inet_pton (AF_INET, virt_dns, &virt_dns_bytes))
938 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Error parsing 'VIRTDNS': %s; %m!\n",
943 GNUNET_free (virt_dns);
945 else if (pkt->addrlen == 16)
950 GNUNET_CONFIGURATION_get_value_string (cfg, "vpn", "VIRTDNS6", &virt_dns))
952 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
953 "No entry 'VIRTDNS6' in configuration!\n");
957 if (1 != inet_pton (AF_INET6, virt_dns, &virt_dns_bytes))
959 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Error parsing 'VIRTDNS6': %s; %m!\n",
964 GNUNET_free (virt_dns);
971 if (memcmp(virt_dns_bytes,pkt->orig_to, pkt->addrlen) == 0)
973 /* This is a packet that was sent directly to the virtual dns-server
975 * This means we have to send this query over gnunet
979 sizeof (struct GNUNET_MESH_Tunnel *) +
980 sizeof (struct GNUNET_MessageHeader) + (ntohs (message->size) -
981 sizeof (struct query_packet) +
983 struct tunnel_cls *cls_ = GNUNET_malloc (size);
985 cls_->hdr.size = size - sizeof (struct GNUNET_MESH_Tunnel *);
987 cls_->hdr.type = ntohs (GNUNET_MESSAGE_TYPE_VPN_REMOTE_QUERY_DNS);
988 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "size: %d\n", size);
990 memcpy (&cls_->dns, dns,
991 cls_->hdr.size - sizeof (struct GNUNET_MessageHeader));
992 GNUNET_SCHEDULER_add_now (send_mesh_query, cls_);
994 if (pdns->s.qdcount == 1)
996 if (ntohs(pdns->queries[0]->qtype) == 1)
997 pdns->queries[0]->qtype = htons(28);
998 else if (ntohs(pdns->queries[0]->qtype) == 28)
999 pdns->queries[0]->qtype = htons(1);
1002 struct dns_pkt *rdns = unparse_dns_packet (pdns);
1004 sizeof (struct GNUNET_MESH_Tunnel *) +
1005 sizeof (struct GNUNET_MessageHeader) + (ntohs (message->size) -
1006 sizeof (struct query_packet) +
1008 struct tunnel_cls *cls_ = GNUNET_malloc (size);
1010 cls_->hdr.size = size - sizeof (struct GNUNET_MESH_Tunnel *);
1012 cls_->hdr.type = ntohs (GNUNET_MESSAGE_TYPE_VPN_REMOTE_QUERY_DNS);
1013 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "size: %d\n", size);
1015 memcpy (&cls_->dns, rdns,
1016 cls_->hdr.size - sizeof (struct GNUNET_MessageHeader));
1017 GNUNET_SCHEDULER_add_now (send_mesh_query, cls_);
1025 /* The query should be sent to the network */
1026 if (pkt->addrlen == 4)
1028 struct sockaddr_in dest;
1030 memset (&dest, 0, sizeof dest);
1031 dest.sin_port = htons (53);
1032 memcpy(&dest.sin_addr.s_addr, pkt->orig_to, pkt->addrlen);
1034 GNUNET_NETWORK_socket_sendto (dnsout, dns,
1035 ntohs (pkt->hdr.size) -
1036 sizeof (struct query_packet) + 1,
1037 (struct sockaddr *) &dest, sizeof dest);
1039 else if (pkt->addrlen == 16)
1041 struct sockaddr_in6 dest;
1043 memset (&dest, 0, sizeof dest);
1044 dest.sin6_port = htons (53);
1045 memcpy(&dest.sin6_addr, pkt->orig_to, pkt->addrlen);
1047 GNUNET_NETWORK_socket_sendto (dnsout6, dns,
1048 ntohs (pkt->hdr.size) -
1049 sizeof (struct query_packet) + 1,
1050 (struct sockaddr *) &dest, sizeof dest);
1054 free_parsed_dns_packet (pdns);
1057 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1061 read_response (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc);
1064 read_response6 (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc);
1069 struct sockaddr_in6 addr;
1071 dnsout6 = GNUNET_NETWORK_socket_create (AF_INET6, SOCK_DGRAM, 0);
1072 if (dnsout6 == NULL)
1074 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Could not create socket: %m\n");
1075 return GNUNET_SYSERR;
1077 memset (&addr, 0, sizeof (struct sockaddr_in6));
1079 addr.sin6_family = AF_INET6;
1080 int err = GNUNET_NETWORK_socket_bind (dnsout6,
1081 (struct sockaddr *) &addr,
1082 sizeof (struct sockaddr_in6));
1084 if (err != GNUNET_OK)
1086 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Could not bind a port: %m\n");
1087 return GNUNET_SYSERR;
1090 GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL, dnsout6,
1091 &read_response6, NULL);
1099 struct sockaddr_in addr;
1101 dnsout = GNUNET_NETWORK_socket_create (AF_INET, SOCK_DGRAM, 0);
1103 return GNUNET_SYSERR;
1104 memset (&addr, 0, sizeof (struct sockaddr_in));
1106 addr.sin_family = AF_INET;
1107 int err = GNUNET_NETWORK_socket_bind (dnsout,
1108 (struct sockaddr *) &addr,
1109 sizeof (struct sockaddr_in));
1111 if (err != GNUNET_OK)
1113 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Could not bind a port: %m\n");
1114 return GNUNET_SYSERR;
1117 /* Read the port we bound to */
1118 socklen_t addrlen = sizeof (struct sockaddr_in);
1121 getsockname (GNUNET_NETWORK_get_fd (dnsout), (struct sockaddr *) &addr,
1124 dnsoutport = htons (addr.sin_port);
1126 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Bound to port %d.\n", dnsoutport);
1128 GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL, dnsout,
1129 &read_response, NULL);
1134 void handle_response(struct dns_pkt* dns, struct sockaddr *addr, socklen_t addrlen, int r);
1137 * Read a response-packet of the UDP-Socket
1140 read_response6 (void *cls
1141 __attribute__ ((unused)),
1142 const struct GNUNET_SCHEDULER_TaskContext *tc)
1144 struct sockaddr_in6 addr;
1145 socklen_t addrlen = sizeof (addr);
1149 if (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)
1152 memset (&addr, 0, sizeof addr);
1155 if (0 != ioctl (GNUNET_NETWORK_get_fd (dnsout6), FIONREAD, &len))
1157 (void)open_port6 ();
1161 /* port the code above? */
1165 unsigned char buf[len];
1166 struct dns_pkt *dns = (struct dns_pkt *) buf;
1168 r = GNUNET_NETWORK_socket_recvfrom (dnsout, buf, sizeof (buf),
1169 (struct sockaddr *) &addr, &addrlen);
1173 (void)open_port6 ();
1177 struct sockaddr *addr_ = GNUNET_malloc(sizeof addr);
1178 memcpy (addr_, &addr, sizeof addr);
1179 handle_response(dns, addr_, 4, r);
1181 GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL, dnsout6,
1182 &read_response6, NULL);
1186 * Read a response-packet of the UDP-Socket
1189 read_response (void *cls
1190 __attribute__ ((unused)),
1191 const struct GNUNET_SCHEDULER_TaskContext *tc)
1193 struct sockaddr_in addr;
1194 socklen_t addrlen = sizeof (addr);
1198 if (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)
1201 memset (&addr, 0, sizeof addr);
1204 if (0 != ioctl (GNUNET_NETWORK_get_fd (dnsout), FIONREAD, &len))
1206 GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
1208 unhijack (dnsoutport);
1209 if (GNUNET_YES == open_port ())
1210 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS, &hijack, NULL);
1214 /* port the code above? */
1218 unsigned char buf[len];
1219 struct dns_pkt *dns = (struct dns_pkt *) buf;
1221 r = GNUNET_NETWORK_socket_recvfrom (dnsout, buf, sizeof (buf),
1222 (struct sockaddr *) &addr, &addrlen);
1226 GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
1228 unhijack (dnsoutport);
1229 if (GNUNET_YES == open_port ())
1230 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS, &hijack, NULL);
1234 struct sockaddr *addr_ = GNUNET_malloc(sizeof addr);
1235 memcpy (addr_, &addr, sizeof addr);
1236 handle_response(dns, addr_, 4, r);
1238 GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL, dnsout,
1239 &read_response, NULL);
1243 handle_response(struct dns_pkt* dns, struct sockaddr *addr, socklen_t addrlen, int r)
1245 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Answer to query %d\n",
1249 if (query_states[dns->s.id].valid == GNUNET_YES)
1251 if (query_states[dns->s.id].tunnel != NULL)
1253 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1254 "Answer to query %d for a remote peer!\n",
1256 /* This response should go through a tunnel */
1258 GNUNET_malloc (4 + sizeof (struct GNUNET_MESH_Tunnel *) + r);
1260 struct GNUNET_MESH_Tunnel **t = (struct GNUNET_MESH_Tunnel **) (c + 1);
1262 *t = query_states[dns->s.id].tunnel;
1263 memcpy (t + 1, dns, r);
1265 GNUNET_MESH_tunnel_get_data (query_states[dns->s.id].tunnel))
1267 struct GNUNET_MESH_TransmitHandle *th =
1268 GNUNET_MESH_notify_transmit_ready (query_states[dns->s.id].tunnel,
1271 GNUNET_TIME_UNIT_MINUTES,
1275 GNUNET_MessageHeader),
1276 mesh_send_response, c);
1278 GNUNET_MESH_tunnel_set_data (query_states[dns->s.id].tunnel, th);
1282 struct tunnel_notify_queue *head =
1283 GNUNET_MESH_tunnel_get_head (query_states[dns->s.id].tunnel);
1284 struct tunnel_notify_queue *tail =
1285 GNUNET_MESH_tunnel_get_tail (query_states[dns->s.id].tunnel);
1287 struct tunnel_notify_queue *element =
1288 GNUNET_malloc (sizeof (struct tunnel_notify_queue));
1290 element->len = r + sizeof (struct GNUNET_MessageHeader);
1291 element->cb = mesh_send_response;
1293 GNUNET_CONTAINER_DLL_insert_tail (head, tail, element);
1294 GNUNET_MESH_tunnel_set_head (query_states[dns->s.id].tunnel, head);
1295 GNUNET_MESH_tunnel_set_tail (query_states[dns->s.id].tunnel, tail);
1300 query_states[dns->s.id].valid = GNUNET_NO;
1302 size_t len = sizeof (struct answer_packet) + r - 1; /* 1 for the unsigned char data[1]; */
1303 struct answer_packet_list *answer =
1304 GNUNET_malloc (len + 2 * sizeof (struct answer_packet_list *));
1305 answer->pkt.hdr.type =
1306 htons (GNUNET_MESSAGE_TYPE_VPN_DNS_LOCAL_RESPONSE_DNS);
1307 answer->pkt.hdr.size = htons (len);
1308 answer->pkt.subtype = GNUNET_DNS_ANSWER_TYPE_IP;
1309 answer->pkt.addrlen = addrlen;
1312 struct sockaddr_in6 *addr_ = (struct sockaddr_in6*)addr;
1313 memcpy(answer->pkt.from, &addr_->sin6_addr, addrlen);
1314 memcpy(answer->pkt.to, query_states[dns->s.id].local_ip, addrlen);
1316 else if (addrlen == 4)
1318 struct sockaddr_in *addr_ = (struct sockaddr_in*)addr;
1319 memcpy(answer->pkt.from, &addr_->sin_addr.s_addr, addrlen);
1320 memcpy(answer->pkt.to, query_states[dns->s.id].local_ip, addrlen);
1324 GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "addrlen = %d\n", addrlen);
1327 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "sending answer with addrlen = %d\n", addrlen);
1328 answer->pkt.dst_port = query_states[dns->s.id].local_port;
1329 memcpy (answer->pkt.data, dns, r);
1331 GNUNET_CONTAINER_DLL_insert_after (head, tail, tail, answer);
1333 if (server_notify == NULL)
1334 server_notify = GNUNET_SERVER_notify_transmit_ready (query_states[dns->s.id].client,
1335 len, GNUNET_TIME_UNIT_FOREVER_REL,
1337 query_states[dns->s.id].client);
1345 * Task run during shutdown.
1351 cleanup_task (void *cls
1352 __attribute__ ((unused)),
1353 const struct GNUNET_SCHEDULER_TaskContext *tc)
1355 GNUNET_assert (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN));
1357 unhijack (dnsoutport);
1358 GNUNET_DHT_disconnect (dht);
1359 GNUNET_MESH_disconnect (mesh_handle);
1363 * @brief Create a port-map from udp and tcp redirects
1365 * @param udp_redirects
1366 * @param tcp_redirects
1371 get_port_from_redirects (const char *udp_redirects, const char *tcp_redirects)
1374 char *cpy, *hostname, *redirect;
1376 unsigned int count = 0;
1379 if (NULL != udp_redirects)
1381 cpy = GNUNET_strdup (udp_redirects);
1382 for (redirect = strtok (cpy, " "); redirect != NULL;
1383 redirect = strtok (NULL, " "))
1385 if (NULL == (hostname = strstr (redirect, ":")))
1387 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1388 "Warning: option %s is not formatted correctly!\n",
1393 local_port = atoi (redirect);
1394 if (!((local_port > 0) && (local_port < 65536)))
1395 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1396 "Warning: %s is not a correct port.", redirect);
1398 ret |= (0xFFFF & htons (local_port));
1412 if (NULL != tcp_redirects)
1414 cpy = GNUNET_strdup (tcp_redirects);
1415 for (redirect = strtok (cpy, " "); redirect != NULL;
1416 redirect = strtok (NULL, " "))
1418 if (NULL == (hostname = strstr (redirect, ":")))
1420 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1421 "Warning: option %s is not formatted correctly!\n",
1426 local_port = atoi (redirect);
1427 if (!((local_port > 0) && (local_port < 65536)))
1428 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1429 "Warning: %s is not a correct port.", redirect);
1431 ret |= (0xFFFF & htons (local_port));
1446 GNUNET_free_non_null (cpy);
1451 publish_name (const char *name, uint64_t ports, uint32_t service_type,
1452 struct GNUNET_CRYPTO_RsaPrivateKey *my_private_key)
1454 size_t size = sizeof (struct GNUNET_DNS_Record);
1455 struct GNUNET_DNS_Record data;
1457 memset (&data, 0, size);
1459 data.purpose.size = htonl (size - sizeof (struct GNUNET_CRYPTO_RsaSignature));
1460 data.purpose.purpose = GNUNET_SIGNATURE_PURPOSE_DNS_RECORD;
1462 GNUNET_CRYPTO_hash (name, strlen (name) + 1, &data.service_descriptor);
1463 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Store with key1 %x\n",
1464 *((unsigned long long *) &data.service_descriptor));
1466 data.service_type = service_type;
1469 GNUNET_CRYPTO_rsa_key_get_public (my_private_key, &data.peer);
1471 data.expiration_time =
1472 GNUNET_TIME_absolute_hton (GNUNET_TIME_relative_to_absolute (GNUNET_TIME_relative_multiply
1473 (GNUNET_TIME_UNIT_HOURS, 2)));
1475 /* Sign the block */
1477 GNUNET_CRYPTO_rsa_sign (my_private_key, &data.purpose, &data.signature))
1479 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "could not sign DNS_Record\n");
1483 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Putting with key %08x, size = %d\n",
1484 *((unsigned int *) &data.service_descriptor), size);
1486 GNUNET_DHT_put (dht, &data.service_descriptor, 5 /* DEFAULT_PUT_REPLICATION */,
1487 GNUNET_DHT_RO_NONE, GNUNET_BLOCK_TYPE_DNS, size,
1489 GNUNET_TIME_relative_to_absolute (GNUNET_TIME_UNIT_HOURS),
1490 GNUNET_TIME_UNIT_MINUTES, NULL, NULL);
1495 * @brief Publishes the record defined by the section section
1497 * @param cls closure
1498 * @param section the current section
1501 publish_iterate (void *cls __attribute__ ((unused)), const char *section)
1503 char *udp_redirects;
1504 char *tcp_redirects;
1505 char *alternative_names;
1506 char *alternative_name;
1509 if ((strlen (section) < 8) ||
1510 (0 != strcmp (".gnunet.", section + (strlen (section) - 8))))
1512 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Parsing dns-name %s\n", section);
1514 GNUNET_CONFIGURATION_get_value_string (cfg, section, "UDP_REDIRECTS",
1516 udp_redirects = NULL;
1518 GNUNET_CONFIGURATION_get_value_string (cfg, section, "TCP_REDIRECTS",
1520 tcp_redirects = NULL;
1523 GNUNET_CONFIGURATION_get_value_filename (cfg, "GNUNETD", "HOSTKEY",
1526 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "could not read keyfile-value\n");
1527 if (keyfile != NULL)
1528 GNUNET_free (keyfile);
1532 struct GNUNET_CRYPTO_RsaPrivateKey *my_private_key =
1533 GNUNET_CRYPTO_rsa_key_create_from_file (keyfile);
1534 GNUNET_free (keyfile);
1535 GNUNET_assert (my_private_key != NULL);
1537 uint64_t ports = get_port_from_redirects (udp_redirects, tcp_redirects);
1538 uint32_t service_type = 0;
1540 if (NULL != udp_redirects)
1541 service_type = GNUNET_DNS_SERVICE_TYPE_UDP;
1543 if (NULL != tcp_redirects)
1544 service_type |= GNUNET_DNS_SERVICE_TYPE_TCP;
1546 service_type = htonl (service_type);
1549 publish_name (section, ports, service_type, my_private_key);
1551 GNUNET_CONFIGURATION_get_value_string (cfg, section, "ALTERNATIVE_NAMES",
1552 &alternative_names))
1554 for (alternative_name = strtok (alternative_names, " ");
1555 alternative_name != NULL; alternative_name = strtok (NULL, " "))
1558 alloca (strlen (alternative_name) + strlen (section) + 1 + 1);
1559 strcpy (altname, alternative_name);
1560 strcpy (altname + strlen (alternative_name) + 1, section);
1561 altname[strlen (alternative_name)] = '.';
1563 publish_name (altname, ports, service_type, my_private_key);
1565 GNUNET_free (alternative_names);
1567 GNUNET_CRYPTO_rsa_key_free (my_private_key);
1568 GNUNET_free_non_null (udp_redirects);
1569 GNUNET_free_non_null (tcp_redirects);
1573 * Publish a DNS-record in the DHT.
1576 publish_names (void *cls
1577 __attribute__ ((unused)),
1578 const struct GNUNET_SCHEDULER_TaskContext *tc)
1580 if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
1583 GNUNET_CONFIGURATION_iterate_sections (cfg, &publish_iterate, NULL);
1585 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_HOURS, &publish_names, NULL);
1589 * @param cls closure
1590 * @param server the initialized server
1591 * @param cfg_ configuration to use
1594 run (void *cls, struct GNUNET_SERVER_Handle *server,
1595 const struct GNUNET_CONFIGURATION_Handle *cfg_)
1597 static const struct GNUNET_SERVER_MessageHandler handlers[] = {
1598 /* callback, cls, type, size */
1599 {&receive_query, NULL, GNUNET_MESSAGE_TYPE_VPN_DNS_LOCAL_QUERY_DNS, 0},
1600 {&rehijack, NULL, GNUNET_MESSAGE_TYPE_REHIJACK,
1601 sizeof (struct GNUNET_MessageHeader)},
1605 static const struct GNUNET_MESH_MessageHandler mesh_handlers[] = {
1606 {receive_mesh_query, GNUNET_MESSAGE_TYPE_VPN_REMOTE_QUERY_DNS, 0},
1607 {receive_mesh_answer, GNUNET_MESSAGE_TYPE_VPN_REMOTE_ANSWER_DNS, 0},
1611 static GNUNET_MESH_ApplicationType apptypes[] = {
1612 GNUNET_APPLICATION_TYPE_END,
1613 GNUNET_APPLICATION_TYPE_END
1616 if (GNUNET_YES != open_port6 ())
1618 GNUNET_SCHEDULER_shutdown ();
1622 if (GNUNET_YES != open_port ())
1624 GNUNET_SCHEDULER_shutdown ();
1629 GNUNET_CONFIGURATION_get_value_yesno (cfg_, "dns", "PROVIDE_EXIT"))
1630 apptypes[0] = GNUNET_APPLICATION_TYPE_INTERNET_RESOLVER;
1631 mesh_handle = GNUNET_MESH_connect (cfg_, NULL, NULL, mesh_handlers, apptypes);
1634 dht = GNUNET_DHT_connect (cfg, 1024);
1635 GNUNET_SCHEDULER_add_now (publish_names, NULL);
1636 GNUNET_SERVER_add_handlers (server, handlers);
1637 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &cleanup_task,
1642 * The main function for the dns service.
1644 * @param argc number of arguments from the command line
1645 * @param argv command line arguments
1646 * @return 0 ok, 1 on error
1649 main (int argc, char *const *argv)
1651 return (GNUNET_OK ==
1652 GNUNET_SERVICE_run (argc, argv, "dns", GNUNET_SERVICE_OPTION_NONE,
1653 &run, NULL)) ? 0 : 1;