curly wars / auto-indentation
[oweals/gnunet.git] / src / vpn / gnunet-service-dns.c
1 /*
2      This file is part of GNUnet.
3      (C) 2009 Christian Grothoff (and other contributing authors)
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., 59 Temple Place - Suite 330,
18      Boston, MA 02111-1307, USA.
19 */
20
21 /**
22  * @file vpn/gnunet-service-dns.c
23  * @author Philipp Toelke
24  */
25 #include "platform.h"
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_connection_lib.h"
33 #include "gnunet_protocols.h"
34 #include "gnunet_applications.h"
35 #include "gnunet-vpn-packet.h"
36 #include "gnunet_container_lib.h"
37 #include "gnunet-dns-parser.h"
38 #include "gnunet_dht_service.h"
39 #include "gnunet_block_lib.h"
40 #include "block_dns.h"
41 #include "gnunet_crypto_lib.h"
42 #include "gnunet_mesh_service.h"
43 #include "gnunet_signatures.h"
44
45 struct GNUNET_MESH_Handle *mesh_handle;
46
47 struct GNUNET_CONNECTION_TransmitHandle *server_notify;
48
49 /**
50  * The UDP-Socket through which DNS-Resolves will be sent if they are not to be
51  * sent through gnunet. The port of this socket will not be hijacked.
52  */
53 static struct GNUNET_NETWORK_Handle *dnsout;
54 static struct GNUNET_NETWORK_Handle *dnsout6;
55
56 /**
57  * The port bound to the socket dnsout
58  */
59 static unsigned short dnsoutport;
60
61 /**
62  * A handle to the DHT-Service
63  */
64 static struct GNUNET_DHT_Handle *dht;
65
66 /**
67  * The configuration to use
68  */
69 static const struct GNUNET_CONFIGURATION_Handle *cfg;
70
71 /**
72  * A list of DNS-Responses that have to be sent to the requesting client
73  */
74 static struct answer_packet_list *head;
75
76 /**
77  * The tail of the list of DNS-responses
78  */
79 static struct answer_packet_list *tail;
80
81 /**
82  * A structure containing a mapping from network-byte-ordered DNS-id (16 bit) to
83  * some information needed to handle this query
84  *
85  * It currently allocates at least
86  * (1 + machine-width + machine-width + 32 + 32 + 16 + machine-width + 8) * 65536 bit
87  * = 17 MiB on 64 bit.
88  * = 11 MiB on 32 bit.
89  */
90 static struct
91 {
92   unsigned valid:1;
93   struct GNUNET_SERVER_Client *client;
94   struct GNUNET_MESH_Tunnel *tunnel;
95   char local_ip[16];
96   char remote_ip[16];
97   char addrlen;
98   uint16_t local_port;
99   char *name;
100   uint8_t namelen;
101   uint16_t qtype;
102 } query_states[UINT16_MAX + 1];
103
104 /**
105  * A struct used to give more than one value as
106  * closure to receive_dht
107  */
108 struct receive_dht_cls
109 {
110   uint16_t id;
111   struct GNUNET_DHT_GetHandle *handle;
112 };
113
114 struct tunnel_notify_queue
115 {
116   struct tunnel_notify_queue *next;
117   struct tunnel_notify_queue *prev;
118   void *cls;
119   size_t len;
120   GNUNET_CONNECTION_TransmitReadyNotify cb;
121 };
122
123 struct tunnel_state
124 {
125   struct tunnel_notify_queue *head, *tail;
126   struct GNUNET_MESH_TransmitHandle *th;
127 };
128
129 static size_t
130 send_answer (void *cls, size_t size, void *buf);
131
132 static void
133 client_disconnect (void *cls, struct GNUNET_SERVER_Client *client)
134 {
135   if (NULL == head)
136     return;
137
138   if (head->client == client)
139   {
140     GNUNET_CONNECTION_notify_transmit_ready_cancel (server_notify);
141     server_notify =
142         GNUNET_SERVER_notify_transmit_ready (head->next->client,
143                                              ntohs (head->next->pkt.hdr.size),
144                                              GNUNET_TIME_UNIT_FOREVER_REL,
145                                              &send_answer, NULL);
146   }
147
148   struct answer_packet_list *element = head;
149
150   while (element != NULL)
151   {
152     if (element->client == client)
153     {
154       GNUNET_SERVER_client_drop (client);
155       GNUNET_CONTAINER_DLL_remove (head, tail, element);
156       struct answer_packet_list *t = element;
157
158       element = element->next;
159       GNUNET_free (t);
160     }
161     else
162       element = element->next;
163   }
164 }
165
166 /**
167  * Hijack all outgoing DNS-Traffic but for traffic leaving "our" port.
168  */
169 static void
170 hijack (void *cls
171         __attribute__ ((unused)), const struct GNUNET_SCHEDULER_TaskContext *tc)
172 {
173   if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
174     return;
175
176   if (0 == dnsoutport)
177   {
178     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
179                 "Delaying the hijacking, port is still %d!\n", dnsoutport);
180     GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS, &hijack, NULL);
181     return;
182   }
183
184   char port_s[6];
185   char *virt_dns;
186   struct GNUNET_OS_Process *proc;
187
188   if (GNUNET_SYSERR ==
189       GNUNET_CONFIGURATION_get_value_string (cfg, "vpn", "VIRTDNS", &virt_dns))
190   {
191     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
192                 "No entry 'VIRTDNS' in configuration!\n");
193     exit (1);
194   }
195
196   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Hijacking, port is %d\n", dnsoutport);
197   snprintf (port_s, 6, "%d", dnsoutport);
198   if (NULL !=
199       (proc =
200        GNUNET_OS_start_process (NULL, NULL, "gnunet-helper-hijack-dns",
201                                 "gnunet-hijack-dns", port_s, virt_dns, NULL)))
202   {
203     GNUNET_break (GNUNET_OK == GNUNET_OS_process_wait (proc));
204     GNUNET_OS_process_close (proc);
205   }
206   GNUNET_free (virt_dns);
207 }
208
209 static void *
210 new_tunnel (void *cls
211             __attribute__ ((unused)), struct GNUNET_MESH_Tunnel *tunnel,
212             const struct GNUNET_PeerIdentity *initiator
213             __attribute__ ((unused)), const struct GNUNET_ATS_Information *ats
214             __attribute__ ((unused)))
215 {
216   struct tunnel_state *s = GNUNET_malloc (sizeof *s);
217
218   s->head = NULL;
219   s->tail = NULL;
220   s->th = NULL;
221   return s;
222 }
223
224 static void
225 clean_tunnel (void *cls
226               __attribute__ ((unused)), const struct GNUNET_MESH_Tunnel *tunnel,
227               void *tunnel_ctx)
228 {
229   GNUNET_free (tunnel_ctx);
230 }
231
232 /**
233  * Delete the hijacking-routes
234  */
235 static void
236 unhijack (unsigned short port)
237 {
238   char port_s[6];
239   char *virt_dns;
240   struct GNUNET_OS_Process *proc;
241
242   if (GNUNET_SYSERR ==
243       GNUNET_CONFIGURATION_get_value_string (cfg, "vpn", "VIRTDNS", &virt_dns))
244   {
245     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
246                 "No entry 'VIRTDNS' in configuration!\n");
247     exit (1);
248   }
249
250   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "unHijacking, port is %d\n", port);
251   snprintf (port_s, 6, "%d", port);
252   if (NULL !=
253       (proc =
254        GNUNET_OS_start_process (NULL, NULL, "gnunet-helper-hijack-dns",
255                                 "gnunet-hijack-dns", "-d", port_s, virt_dns,
256                                 NULL)))
257   {
258     GNUNET_break (GNUNET_OK == GNUNET_OS_process_wait (proc));
259     GNUNET_OS_process_close (proc);
260   }
261   GNUNET_free (virt_dns);
262 }
263
264 /**
265  * Send the DNS-Response to the client. Gets called via the notify_transmit_ready-
266  * system.
267  */
268 static size_t
269 send_answer (void *cls, size_t size, void *buf)
270 {
271   server_notify = NULL;
272   struct answer_packet_list *query = head;
273   size_t len = ntohs (query->pkt.hdr.size);
274
275   GNUNET_assert (len <= size);
276
277   memcpy (buf, &query->pkt.hdr, len);
278
279   GNUNET_CONTAINER_DLL_remove (head, tail, query);
280
281   /* When more data is to be sent, reschedule */
282   if (head != NULL)
283     server_notify =
284         GNUNET_SERVER_notify_transmit_ready (head->client,
285                                              ntohs (head->pkt.hdr.size),
286                                              GNUNET_TIME_UNIT_FOREVER_REL,
287                                              &send_answer, NULL);
288
289   GNUNET_SERVER_client_drop (query->client);
290   GNUNET_free (query);
291   return len;
292 }
293
294 struct tunnel_cls
295 {
296   struct GNUNET_MESH_Tunnel *tunnel GNUNET_PACKED;
297   struct GNUNET_MessageHeader hdr;
298   struct dns_pkt dns;
299 };
300
301 struct tunnel_cls *remote_pending[UINT16_MAX];
302
303 static size_t
304 mesh_send_response (void *cls, size_t size, void *buf)
305 {
306   GNUNET_assert (size >= sizeof (struct GNUNET_MessageHeader));
307   struct GNUNET_MessageHeader *hdr = buf;
308   uint32_t *sz = cls;
309   struct GNUNET_MESH_Tunnel **tunnel = (struct GNUNET_MESH_Tunnel **) (sz + 1);
310   struct dns_pkt *dns = (struct dns_pkt *) (tunnel + 1);
311
312   GNUNET_MESH_tunnel_set_data (*tunnel, NULL);
313
314   hdr->type = htons (GNUNET_MESSAGE_TYPE_VPN_REMOTE_ANSWER_DNS);
315   hdr->size = htons (*sz + sizeof (struct GNUNET_MessageHeader));
316
317   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
318               "Sending response, size=%d, sz=%d, sz+hdr=%d\n", size, *sz,
319               *sz + sizeof (struct GNUNET_MessageHeader));
320
321   GNUNET_assert (size >= (*sz + sizeof (struct GNUNET_MessageHeader)));
322
323   memcpy (hdr + 1, dns, *sz);
324   struct tunnel_state *s = GNUNET_MESH_tunnel_get_data (*tunnel);
325
326   if (NULL != s->head)
327   {
328     struct tunnel_notify_queue *element = s->head;
329     struct tunnel_notify_queue *head = s->head;
330     struct tunnel_notify_queue *tail = s->tail;
331
332     GNUNET_CONTAINER_DLL_remove (head, tail, element);
333
334     s->th =
335         GNUNET_MESH_notify_transmit_ready (*tunnel, GNUNET_NO, 42,
336                                            GNUNET_TIME_relative_divide
337                                            (GNUNET_CONSTANTS_MAX_CORK_DELAY, 2),
338                                            (const struct GNUNET_PeerIdentity *)
339                                            NULL, element->len, element->cb,
340                                            element->cls);
341   }
342
343   GNUNET_free (cls);
344
345   return ntohs (hdr->size);
346 }
347
348 static size_t
349 mesh_send (void *cls, size_t size, void *buf)
350 {
351   struct tunnel_cls *cls_ = (struct tunnel_cls *) cls;
352
353   GNUNET_MESH_tunnel_set_data (cls_->tunnel, NULL);
354
355   GNUNET_assert (cls_->hdr.size <= size);
356
357   size = cls_->hdr.size;
358   cls_->hdr.size = htons (cls_->hdr.size);
359
360   memcpy (buf, &cls_->hdr, size);
361
362   struct tunnel_state *s = GNUNET_MESH_tunnel_get_data (cls_->tunnel);
363
364   if (NULL != s->head)
365   {
366     struct tunnel_notify_queue *element = s->head;
367     struct tunnel_notify_queue *head = s->head;
368     struct tunnel_notify_queue *tail = s->tail;;
369
370     GNUNET_CONTAINER_DLL_remove (head, tail, element);
371
372     s->th =
373         GNUNET_MESH_notify_transmit_ready (cls_->tunnel, GNUNET_NO, 42,
374                                            GNUNET_TIME_relative_divide
375                                            (GNUNET_CONSTANTS_MAX_CORK_DELAY, 2),
376                                            (const struct GNUNET_PeerIdentity *)
377                                            NULL, element->len, element->cb,
378                                            element->cls);
379
380     GNUNET_free (element);
381   }
382
383   return size;
384 }
385
386
387 void
388 mesh_connect (void *cls, const struct GNUNET_PeerIdentity *peer,
389               const struct GNUNET_ATS_Information *atsi
390               __attribute__ ((unused)))
391 {
392   if (NULL == peer)
393     return;
394   struct tunnel_cls *cls_ = (struct tunnel_cls *) cls;
395
396   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
397               "Connected to peer %s, %x, sending query with id %d\n",
398               GNUNET_i2s (peer), peer, ntohs (cls_->dns.s.id));
399
400   struct tunnel_state *s = GNUNET_MESH_tunnel_get_data (cls_->tunnel);
401
402   if (NULL == s->head)
403   {
404     s->th =
405         GNUNET_MESH_notify_transmit_ready (cls_->tunnel, GNUNET_YES, 42,
406                                            GNUNET_TIME_UNIT_MINUTES, NULL,
407                                            cls_->hdr.size, mesh_send, cls);
408
409   }
410   else
411   {
412     struct tunnel_notify_queue *head = s->head;
413     struct tunnel_notify_queue *tail = s->tail;
414
415     struct tunnel_notify_queue *element =
416         GNUNET_malloc (sizeof (struct tunnel_notify_queue));
417     element->cls = cls;
418     element->len = cls_->hdr.size;
419     element->cb = mesh_send;
420
421     GNUNET_CONTAINER_DLL_insert_tail (head, tail, element);
422   }
423 }
424
425
426 static void
427 send_mesh_query (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
428 {
429   if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
430     return;
431
432   struct tunnel_cls *cls_ = (struct tunnel_cls *) cls;
433
434   struct tunnel_state *s = GNUNET_malloc (sizeof *s);
435
436   s->head = NULL;
437   s->tail = NULL;
438   s->th = NULL;
439
440   cls_->tunnel =
441       GNUNET_MESH_tunnel_create (mesh_handle, s, mesh_connect, NULL, cls_);
442
443   GNUNET_MESH_peer_request_connect_by_type (cls_->tunnel,
444                                             GNUNET_APPLICATION_TYPE_INTERNET_RESOLVER);
445
446   remote_pending[cls_->dns.s.id] = cls_;
447 }
448
449 static int
450 receive_mesh_query (void *cls
451                     __attribute__ ((unused)), struct GNUNET_MESH_Tunnel *tunnel,
452                     void **ctx
453                     __attribute__ ((unused)),
454                     const struct GNUNET_PeerIdentity *sender
455                     __attribute__ ((unused)),
456                     const struct GNUNET_MessageHeader *message,
457                     const struct GNUNET_ATS_Information *atsi
458                     __attribute__ ((unused)))
459 {
460   struct dns_pkt *dns = (struct dns_pkt *) (message + 1);
461
462   struct sockaddr_in dest;
463
464   struct dns_pkt_parsed *pdns = parse_dns_packet (dns);
465
466   memset (&dest, 0, sizeof dest);
467   dest.sin_port = htons (53);
468   char *dns_resolver;
469
470   if (GNUNET_OK !=
471       GNUNET_CONFIGURATION_get_value_string (cfg, "dns", "EXTERNAL_DNS",
472                                              &dns_resolver) ||
473       1 != inet_pton (AF_INET, dns_resolver, &dest.sin_addr))
474     inet_pton (AF_INET, "8.8.8.8", &dest.sin_addr);
475
476   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Querying for remote, id=%d\n",
477               ntohs (dns->s.id));
478   query_states[dns->s.id].tunnel = tunnel;
479   query_states[dns->s.id].valid = GNUNET_YES;
480
481   int i;
482
483   for (i = 0; i < ntohs (pdns->s.qdcount); i++)
484   {
485     if (pdns->queries[i]->qtype == htons (28) ||
486         pdns->queries[i]->qtype == htons (1))
487     {
488       query_states[dns->s.id].qtype = pdns->queries[i]->qtype;
489       break;
490     }
491   }
492   free_parsed_dns_packet (pdns);
493
494   GNUNET_NETWORK_socket_sendto (dnsout, dns,
495                                 ntohs (message->size) -
496                                 sizeof (struct GNUNET_MessageHeader),
497                                 (struct sockaddr *) &dest, sizeof dest);
498
499   return GNUNET_SYSERR;
500 }
501
502 static int
503 receive_mesh_answer (void *cls
504                      __attribute__ ((unused)),
505                      struct GNUNET_MESH_Tunnel *tunnel, void **ctx
506                      __attribute__ ((unused)),
507                      const struct GNUNET_PeerIdentity *sender,
508                      const struct GNUNET_MessageHeader *message,
509                      const struct GNUNET_ATS_Information *atsi
510                      __attribute__ ((unused)))
511 {
512   /* TODo: size check */
513   struct dns_pkt *dns = (struct dns_pkt *) (message + 1);
514
515   /* They sent us a packet we were not waiting for */
516   if (remote_pending[dns->s.id] == NULL ||
517       remote_pending[dns->s.id]->tunnel != tunnel)
518     return GNUNET_OK;
519
520   GNUNET_free (remote_pending[dns->s.id]);
521   remote_pending[dns->s.id] = NULL;
522
523   if (query_states[dns->s.id].valid != GNUNET_YES)
524     return GNUNET_SYSERR;
525   query_states[dns->s.id].valid = GNUNET_NO;
526
527   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
528               "Received answer from peer %s, dns-id %d\n", GNUNET_i2s (sender),
529               ntohs (dns->s.id));
530
531   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 */
532       + sizeof (struct dns_record_line) - 1 + 16;       /* To hold the IPv6-Address */
533
534   struct answer_packet_list *answer =
535       GNUNET_malloc (len + sizeof (struct answer_packet_list) -
536                      sizeof (struct answer_packet));
537
538   answer->pkt.hdr.type = htons (GNUNET_MESSAGE_TYPE_VPN_DNS_LOCAL_RESPONSE_DNS);
539   answer->pkt.hdr.size = htons (len);
540
541   struct dns_pkt_parsed *pdns = parse_dns_packet (dns);
542
543   if (ntohs (pdns->s.ancount) < 1)
544   {
545     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Answer only contains %d answers.\n",
546                 ntohs (pdns->s.ancount));
547     free_parsed_dns_packet (pdns);
548     GNUNET_free (answer);
549     return GNUNET_OK;
550   }
551
552   int i = 0;
553
554   while (i < ntohs (pdns->s.ancount) && ntohs (pdns->answers[i]->type) != 28 &&
555          ntohs (pdns->answers[i]->type) != 1)
556   {
557     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Answer contains %d.\n",
558                 ntohs (pdns->answers[i]->type));
559     i++;
560   }
561
562   if (i >= ntohs (pdns->s.ancount))
563   {
564     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
565                 "Answer does not contain any usable answers.\n");
566     free_parsed_dns_packet (pdns);
567     GNUNET_free (answer);
568     return GNUNET_OK;
569   }
570
571   answer->pkt.addrsize = ntohs (pdns->answers[i]->data_len);
572   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "The first answer has the addrlen %d\n",
573               answer->pkt.addrsize);
574   memcpy (answer->pkt.addr, pdns->answers[i]->data,
575           ntohs (pdns->answers[i]->data_len));
576
577   memcpy (answer->pkt.from, query_states[dns->s.id].remote_ip,
578           query_states[dns->s.id].addrlen);
579   memcpy (answer->pkt.to, query_states[dns->s.id].local_ip,
580           query_states[dns->s.id].addrlen);
581   answer->pkt.addrlen = query_states[dns->s.id].addrlen;
582   answer->pkt.dst_port = query_states[dns->s.id].local_port;
583
584   struct dns_pkt *dpkt = (struct dns_pkt *) answer->pkt.data;
585
586   dpkt->s.id = dns->s.id;
587   dpkt->s.aa = 1;
588   dpkt->s.qr = 1;
589   dpkt->s.ra = 1;
590   dpkt->s.qdcount = htons (1);
591   dpkt->s.ancount = htons (1);
592
593   memcpy (dpkt->data, query_states[dns->s.id].name,
594           query_states[dns->s.id].namelen);
595   GNUNET_free (query_states[dns->s.id].name);
596   query_states[dns->s.id].name = NULL;
597
598   struct dns_query_line *dque =
599       (struct dns_query_line *) (dpkt->data +
600                                  (query_states[dns->s.id].namelen));
601
602   struct dns_record_line *drec_data =
603       (struct dns_record_line *) (dpkt->data +
604                                   (query_states[dns->s.id].namelen) +
605                                   sizeof (struct dns_query_line) + 2);
606   if (htons (28) == query_states[dns->s.id].qtype)
607   {
608     answer->pkt.subtype = GNUNET_DNS_ANSWER_TYPE_REMOTE_AAAA;
609     dque->type = htons (28);    /* AAAA */
610     drec_data->type = htons (28);       /* AAAA */
611     drec_data->data_len = htons (16);
612   }
613   else if (htons (1) == query_states[dns->s.id].qtype)
614   {
615     answer->pkt.subtype = GNUNET_DNS_ANSWER_TYPE_REMOTE_A;
616     dque->type = htons (1);     /* A */
617     drec_data->type = htons (1);        /* A */
618     drec_data->data_len = htons (4);
619   }
620   else
621   {
622     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "dns-answer with pending qtype = %d\n",
623                 query_states[dns->s.id].qtype);
624     GNUNET_assert (0);
625   }
626   dque->class = htons (1);      /* IN */
627
628   char *anname =
629       (char *) (dpkt->data + (query_states[dns->s.id].namelen) +
630                 sizeof (struct dns_query_line));
631   memcpy (anname, "\xc0\x0c", 2);
632   drec_data->class = htons (1); /* IN */
633
634   drec_data->ttl = pdns->answers[i]->ttl;
635
636   /* Calculate at which offset in the packet the IPv6-Address belongs, it is
637    * filled in by the daemon-vpn */
638   answer->pkt.addroffset =
639       htons ((unsigned short) ((unsigned long) (&drec_data->data) -
640                                (unsigned long) (&answer->pkt)));
641
642   GNUNET_CONTAINER_DLL_insert_after (head, tail, tail, answer);
643   answer->client = query_states[dns->s.id].client;
644
645   if (server_notify == NULL)
646     server_notify =
647         GNUNET_SERVER_notify_transmit_ready (query_states[dns->s.id].client,
648                                              len, GNUNET_TIME_UNIT_FOREVER_REL,
649                                              &send_answer, NULL);
650
651   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
652               "Sent answer of length %d on to client, addroffset = %d\n", len,
653               answer->pkt.addroffset);
654
655   free_parsed_dns_packet (pdns);
656   return GNUNET_OK;
657 }
658
659
660 static void
661 send_rev_query (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
662 {
663   if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
664     return;
665
666   struct dns_pkt_parsed *pdns = (struct dns_pkt_parsed *) cls;
667
668   unsigned short id = pdns->s.id;
669
670   free_parsed_dns_packet (pdns);
671
672   if (query_states[id].valid != GNUNET_YES)
673     return;
674   query_states[id].valid = GNUNET_NO;
675
676   GNUNET_assert (query_states[id].namelen == 74);
677
678   size_t len = sizeof (struct answer_packet) - 1 + sizeof (struct dns_static) + 74      /* this is the length of a reverse ipv6-lookup */
679       + sizeof (struct dns_query_line) + 2      /* To hold the pointer (as defined in RFC1035) to the name */
680       + sizeof (struct dns_record_line) - 1 -
681       2 /* We do not know the lenght of the answer yet */ ;
682
683   struct answer_packet_list *answer =
684       GNUNET_malloc (len + sizeof (struct answer_packet_list) -
685                      sizeof (struct answer_packet));
686
687   answer->pkt.hdr.type = htons (GNUNET_MESSAGE_TYPE_VPN_DNS_LOCAL_RESPONSE_DNS);
688   answer->pkt.hdr.size = htons (len);
689   answer->pkt.subtype = GNUNET_DNS_ANSWER_TYPE_REV;
690
691   memcpy (answer->pkt.from, query_states[id].remote_ip,
692           query_states[id].addrlen);
693   memcpy (answer->pkt.to, query_states[id].local_ip, query_states[id].addrlen);
694
695   answer->pkt.dst_port = query_states[id].local_port;
696
697   struct dns_pkt *dpkt = (struct dns_pkt *) answer->pkt.data;
698
699   dpkt->s.id = id;
700   dpkt->s.aa = 1;
701   dpkt->s.qr = 1;
702   dpkt->s.ra = 1;
703   dpkt->s.qdcount = htons (1);
704   dpkt->s.ancount = htons (1);
705
706   memcpy (dpkt->data, query_states[id].name, query_states[id].namelen);
707   GNUNET_free (query_states[id].name);
708   query_states[id].name = NULL;
709
710   struct dns_query_line *dque =
711       (struct dns_query_line *) (dpkt->data + (query_states[id].namelen));
712   dque->type = htons (12);      /* PTR */
713   dque->class = htons (1);      /* IN */
714
715   char *anname =
716       (char *) (dpkt->data + (query_states[id].namelen) +
717                 sizeof (struct dns_query_line));
718   memcpy (anname, "\xc0\x0c", 2);
719
720   struct dns_record_line *drec_data =
721       (struct dns_record_line *) (dpkt->data + (query_states[id].namelen) +
722                                   sizeof (struct dns_query_line) + 2);
723   drec_data->type = htons (12); /* AAAA */
724   drec_data->class = htons (1); /* IN */
725   /* FIXME: read the TTL from block:
726    * GNUNET_TIME_absolute_get_remaining(rec->expiration_time)
727    *
728    * But how to get the seconds out of this?
729    */
730   drec_data->ttl = htonl (3600);
731
732   /* Calculate at which offset in the packet the length of the name and the
733    * name, it is filled in by the daemon-vpn */
734   answer->pkt.addroffset =
735       htons ((unsigned short) ((unsigned long) (&drec_data->data_len) -
736                                (unsigned long) (&answer->pkt)));
737
738   GNUNET_CONTAINER_DLL_insert_after (head, tail, tail, answer);
739   answer->client = query_states[id].client;
740
741   if (server_notify == NULL)
742     server_notify =
743         GNUNET_SERVER_notify_transmit_ready (query_states[id].client, len,
744                                              GNUNET_TIME_UNIT_FOREVER_REL,
745                                              &send_answer, NULL);
746 }
747
748 /**
749  * Receive a block from the dht.
750  */
751 static void
752 receive_dht (void *cls, struct GNUNET_TIME_Absolute exp
753              __attribute__ ((unused)), const GNUNET_HashCode * key
754              __attribute__ ((unused)),
755              const struct GNUNET_PeerIdentity *get_path
756              __attribute__ ((unused)), unsigned int get_path_length
757              __attribute__ ((unused)),
758              const struct GNUNET_PeerIdentity *put_path
759              __attribute__ ((unused)), unsigned int put_path_length
760              __attribute__ ((unused)), enum GNUNET_BLOCK_Type type, size_t size,
761              const void *data)
762 {
763
764   unsigned short id = ((struct receive_dht_cls *) cls)->id;
765   struct GNUNET_DHT_GetHandle *handle =
766       ((struct receive_dht_cls *) cls)->handle;
767   GNUNET_free (cls);
768
769   GNUNET_DHT_get_stop (handle);
770
771   GNUNET_assert (type == GNUNET_BLOCK_TYPE_DNS);
772
773   /* If no query with this id is pending, ignore the block */
774   if (query_states[id].valid != GNUNET_YES)
775     return;
776   query_states[id].valid = GNUNET_NO;
777
778   const struct GNUNET_DNS_Record *rec = data;
779
780   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
781               "Got block of size %d, peer: %08x, desc: %08x\n", size,
782               *((unsigned int *) &rec->peer),
783               *((unsigned int *) &rec->service_descriptor));
784
785   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 */
786       + sizeof (struct dns_record_line) - 1 + 16;       /* To hold the IPv6-Address */
787
788   struct answer_packet_list *answer =
789       GNUNET_malloc (len + sizeof (struct answer_packet_list) -
790                      sizeof (struct answer_packet));
791
792   answer->pkt.hdr.type = htons (GNUNET_MESSAGE_TYPE_VPN_DNS_LOCAL_RESPONSE_DNS);
793   answer->pkt.hdr.size = htons (len);
794   answer->pkt.subtype = GNUNET_DNS_ANSWER_TYPE_SERVICE;
795   answer->client = query_states[id].client;
796
797   GNUNET_CRYPTO_hash (&rec->peer,
798                       sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded),
799                       &answer->pkt.service_descr.peer);
800
801   memcpy (&answer->pkt.service_descr.service_descriptor,
802           &rec->service_descriptor, sizeof (GNUNET_HashCode));
803   memcpy (&answer->pkt.service_descr.service_type, &rec->service_type,
804           sizeof (answer->pkt.service_descr.service_type));
805   memcpy (&answer->pkt.service_descr.ports, &rec->ports,
806           sizeof (answer->pkt.service_descr.ports));
807
808   memcpy (answer->pkt.from, query_states[id].remote_ip,
809           query_states[id].addrlen);
810   memcpy (answer->pkt.to, query_states[id].local_ip, query_states[id].addrlen);
811   answer->pkt.addrlen = query_states[id].addrlen;
812
813   answer->pkt.dst_port = query_states[id].local_port;
814
815   struct dns_pkt *dpkt = (struct dns_pkt *) answer->pkt.data;
816
817   dpkt->s.id = id;
818   dpkt->s.aa = 1;
819   dpkt->s.qr = 1;
820   dpkt->s.ra = 1;
821   dpkt->s.qdcount = htons (1);
822   dpkt->s.ancount = htons (1);
823
824   memcpy (dpkt->data, query_states[id].name, query_states[id].namelen);
825   GNUNET_free (query_states[id].name);
826   query_states[id].name = NULL;
827
828   struct dns_query_line *dque =
829       (struct dns_query_line *) (dpkt->data + (query_states[id].namelen));
830   dque->type = htons (28);      /* AAAA */
831   dque->class = htons (1);      /* IN */
832
833   char *anname =
834       (char *) (dpkt->data + (query_states[id].namelen) +
835                 sizeof (struct dns_query_line));
836   memcpy (anname, "\xc0\x0c", 2);
837
838   struct dns_record_line *drec_data =
839       (struct dns_record_line *) (dpkt->data + (query_states[id].namelen) +
840                                   sizeof (struct dns_query_line) + 2);
841   drec_data->type = htons (28); /* AAAA */
842   drec_data->class = htons (1); /* IN */
843
844   /* FIXME: read the TTL from block:
845    * GNUNET_TIME_absolute_get_remaining(rec->expiration_time)
846    *
847    * But how to get the seconds out of this?
848    */
849   drec_data->ttl = htonl (3600);
850   drec_data->data_len = htons (16);
851
852   /* Calculate at which offset in the packet the IPv6-Address belongs, it is
853    * filled in by the daemon-vpn */
854   answer->pkt.addroffset =
855       htons ((unsigned short) ((unsigned long) (&drec_data->data) -
856                                (unsigned long) (&answer->pkt)));
857
858   GNUNET_CONTAINER_DLL_insert_after (head, tail, tail, answer);
859
860   if (server_notify == NULL)
861     server_notify =
862         GNUNET_SERVER_notify_transmit_ready (answer->client, len,
863                                              GNUNET_TIME_UNIT_FOREVER_REL,
864                                              &send_answer, NULL);
865 }
866
867 /**
868  * This receives a GNUNET_MESSAGE_TYPE_REHIJACK and rehijacks the DNS
869  */
870 static void
871 rehijack (void *cls
872           __attribute__ ((unused)), struct GNUNET_SERVER_Client *client,
873           const struct GNUNET_MessageHeader *message __attribute__ ((unused)))
874 {
875   unhijack (dnsoutport);
876   GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS, &hijack, NULL);
877
878   GNUNET_SERVER_receive_done (client, GNUNET_OK);
879 }
880
881 /**
882  * This receives the dns-payload from the daemon-vpn and sends it on over the udp-socket
883  */
884 static void
885 receive_query (void *cls
886                __attribute__ ((unused)), struct GNUNET_SERVER_Client *client,
887                const struct GNUNET_MessageHeader *message)
888 {
889   struct query_packet *pkt = (struct query_packet *) message;
890   struct dns_pkt *dns = (struct dns_pkt *) pkt->data;
891   struct dns_pkt_parsed *pdns = parse_dns_packet (dns);
892
893   query_states[dns->s.id].valid = GNUNET_YES;
894   query_states[dns->s.id].client = client;
895   GNUNET_SERVER_client_keep (client);
896   memcpy (query_states[dns->s.id].local_ip, pkt->orig_from, pkt->addrlen);
897   query_states[dns->s.id].addrlen = pkt->addrlen;
898   query_states[dns->s.id].local_port = pkt->src_port;
899   memcpy (query_states[dns->s.id].remote_ip, pkt->orig_to, pkt->addrlen);
900   query_states[dns->s.id].namelen = strlen ((char *) dns->data) + 1;
901   if (query_states[dns->s.id].name != NULL)
902     GNUNET_free (query_states[dns->s.id].name);
903   query_states[dns->s.id].name =
904       GNUNET_malloc (query_states[dns->s.id].namelen);
905   memcpy (query_states[dns->s.id].name, dns->data,
906           query_states[dns->s.id].namelen);
907
908   int i;
909
910   for (i = 0; i < ntohs (pdns->s.qdcount); i++)
911   {
912     if (pdns->queries[i]->qtype == htons (28) ||
913         pdns->queries[i]->qtype == htons (1))
914     {
915       query_states[dns->s.id].qtype = pdns->queries[i]->qtype;
916       break;
917     }
918   }
919
920   /* The query is for a .gnunet-address */
921   if (pdns->queries[0]->namelen > 9 &&
922       0 == strncmp (pdns->queries[0]->name + (pdns->queries[0]->namelen - 9),
923                     ".gnunet.", 9))
924   {
925     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Query for .gnunet!\n");
926     GNUNET_HashCode key;
927
928     GNUNET_CRYPTO_hash (pdns->queries[0]->name, pdns->queries[0]->namelen,
929                         &key);
930
931     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Getting with key %08x, len is %d\n",
932                 *((unsigned int *) &key), pdns->queries[0]->namelen);
933
934     struct receive_dht_cls *cls =
935         GNUNET_malloc (sizeof (struct receive_dht_cls));
936     cls->id = dns->s.id;
937
938     cls->handle =
939         GNUNET_DHT_get_start (dht, GNUNET_TIME_UNIT_MINUTES,
940                               GNUNET_BLOCK_TYPE_DNS, &key,
941                               5 /* DEFAULT_GET_REPLICATION */ ,
942                               GNUNET_DHT_RO_NONE, NULL, 0, &receive_dht, cls);
943
944     goto outfree;
945   }
946
947   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Query for '%s'; namelen=%d\n",
948               pdns->queries[0]->name, pdns->queries[0]->namelen);
949
950   /* This is a PTR-Query. Check if it is for "our" network */
951   if (htons (pdns->queries[0]->qtype) == 12 && 74 == pdns->queries[0]->namelen)
952   {
953     char *ipv6addr;
954     char ipv6[16];
955     char ipv6rev[74] =
956         "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.";
957     unsigned int i;
958     unsigned long long ipv6prefix;
959     unsigned int comparelen;
960
961     GNUNET_assert (GNUNET_OK ==
962                    GNUNET_CONFIGURATION_get_value_string (cfg, "vpn",
963                                                           "IPV6ADDR",
964                                                           &ipv6addr));
965     inet_pton (AF_INET6, ipv6addr, ipv6);
966     GNUNET_free (ipv6addr);
967
968     GNUNET_assert (GNUNET_OK ==
969                    GNUNET_CONFIGURATION_get_value_number (cfg, "vpn",
970                                                           "IPV6PREFIX",
971                                                           &ipv6prefix));
972     GNUNET_assert (ipv6prefix < 127);
973     ipv6prefix = (ipv6prefix + 7) / 8;
974
975     for (i = ipv6prefix; i < 16; i++)
976       ipv6[i] = 0;
977
978     for (i = 0; i < 16; i++)
979     {
980       unsigned char c1 = ipv6[i] >> 4;
981       unsigned char c2 = ipv6[i] & 0xf;
982
983       if (c1 <= 9)
984         ipv6rev[62 - (4 * i)] = c1 + '0';
985       else
986         ipv6rev[62 - (4 * i)] = c1 + 87;        /* 87 is the difference between 'a' and 10 */
987
988       if (c2 <= 9)
989         ipv6rev[62 - ((4 * i) + 2)] = c2 + '0';
990       else
991         ipv6rev[62 - ((4 * i) + 2)] = c2 + 87;
992     }
993     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "My network is %s'.\n", ipv6rev);
994     comparelen = 10 + 4 * ipv6prefix;
995     if (0 ==
996         strncmp (pdns->queries[0]->name +
997                  (pdns->queries[0]->namelen - comparelen),
998                  ipv6rev + (74 - comparelen), comparelen))
999     {
1000       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Reverse-Query for .gnunet!\n");
1001
1002       GNUNET_SCHEDULER_add_now (send_rev_query, pdns);
1003
1004       goto out;
1005     }
1006   }
1007
1008   unsigned char virt_dns_bytes[16];
1009
1010   if (pkt->addrlen == 4)
1011   {
1012     char *virt_dns;
1013
1014     if (GNUNET_SYSERR ==
1015         GNUNET_CONFIGURATION_get_value_string (cfg, "vpn", "VIRTDNS",
1016                                                &virt_dns))
1017     {
1018       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1019                   "No entry 'VIRTDNS' in configuration!\n");
1020       exit (1);
1021     }
1022
1023     if (1 != inet_pton (AF_INET, virt_dns, &virt_dns_bytes))
1024     {
1025       GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Error parsing 'VIRTDNS': %s; %m!\n",
1026                   virt_dns);
1027       exit (1);
1028     }
1029
1030     GNUNET_free (virt_dns);
1031   }
1032   else if (pkt->addrlen == 16)
1033   {
1034     char *virt_dns;
1035
1036     if (GNUNET_SYSERR ==
1037         GNUNET_CONFIGURATION_get_value_string (cfg, "vpn", "VIRTDNS6",
1038                                                &virt_dns))
1039     {
1040       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1041                   "No entry 'VIRTDNS6' in configuration!\n");
1042       exit (1);
1043     }
1044
1045     if (1 != inet_pton (AF_INET6, virt_dns, &virt_dns_bytes))
1046     {
1047       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1048                   "Error parsing 'VIRTDNS6': %s; %m!\n", virt_dns);
1049       exit (1);
1050     }
1051
1052     GNUNET_free (virt_dns);
1053   }
1054   else
1055   {
1056     GNUNET_assert (0);
1057   }
1058
1059   if (memcmp (virt_dns_bytes, pkt->orig_to, pkt->addrlen) == 0)
1060   {
1061     /* This is a packet that was sent directly to the virtual dns-server
1062      *
1063      * This means we have to send this query over gnunet
1064      */
1065
1066     size_t size =
1067         sizeof (struct GNUNET_MESH_Tunnel *) +
1068         sizeof (struct GNUNET_MessageHeader) + (ntohs (message->size) -
1069                                                 sizeof (struct query_packet) +
1070                                                 1);
1071     struct tunnel_cls *cls_ = GNUNET_malloc (size);
1072
1073     cls_->hdr.size = size - sizeof (struct GNUNET_MESH_Tunnel *);
1074
1075     cls_->hdr.type = ntohs (GNUNET_MESSAGE_TYPE_VPN_REMOTE_QUERY_DNS);
1076     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "size: %d\n", size);
1077
1078     memcpy (&cls_->dns, dns,
1079             cls_->hdr.size - sizeof (struct GNUNET_MessageHeader));
1080     GNUNET_SCHEDULER_add_now (send_mesh_query, cls_);
1081
1082     if (ntohs (pdns->s.qdcount) == 1)
1083     {
1084       if (ntohs (pdns->queries[0]->qtype) == 1)
1085         pdns->queries[0]->qtype = htons (28);
1086       else if (ntohs (pdns->queries[0]->qtype) == 28)
1087         pdns->queries[0]->qtype = htons (1);
1088       else
1089       {
1090         GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "not sending second packet\n");
1091         goto outfree;
1092       }
1093       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "sending second packet\n");
1094       struct dns_pkt *rdns = unparse_dns_packet (pdns);
1095       size_t size =
1096           sizeof (struct GNUNET_MESH_Tunnel *) +
1097           sizeof (struct GNUNET_MessageHeader) + (ntohs (message->size) -
1098                                                   sizeof (struct query_packet) +
1099                                                   1);
1100       struct tunnel_cls *cls_ = GNUNET_malloc (size);
1101
1102       cls_->hdr.size = size - sizeof (struct GNUNET_MESH_Tunnel *);
1103
1104       cls_->hdr.type = ntohs (GNUNET_MESSAGE_TYPE_VPN_REMOTE_QUERY_DNS);
1105       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "size: %d\n", size);
1106
1107       memcpy (&cls_->dns, rdns,
1108               cls_->hdr.size - sizeof (struct GNUNET_MessageHeader));
1109       GNUNET_SCHEDULER_add_now (send_mesh_query, cls_);
1110       GNUNET_free (rdns);
1111     }
1112
1113     goto outfree;
1114   }
1115
1116
1117   /* The query should be sent to the network */
1118   if (pkt->addrlen == 4)
1119   {
1120     struct sockaddr_in dest;
1121
1122     memset (&dest, 0, sizeof dest);
1123     dest.sin_port = htons (53);
1124     memcpy (&dest.sin_addr.s_addr, pkt->orig_to, pkt->addrlen);
1125
1126     GNUNET_NETWORK_socket_sendto (dnsout, dns,
1127                                   ntohs (pkt->hdr.size) -
1128                                   sizeof (struct query_packet) + 1,
1129                                   (struct sockaddr *) &dest, sizeof dest);
1130   }
1131   else if (pkt->addrlen == 16)
1132   {
1133     struct sockaddr_in6 dest;
1134
1135     memset (&dest, 0, sizeof dest);
1136     dest.sin6_port = htons (53);
1137     memcpy (&dest.sin6_addr, pkt->orig_to, pkt->addrlen);
1138
1139     GNUNET_NETWORK_socket_sendto (dnsout6, dns,
1140                                   ntohs (pkt->hdr.size) -
1141                                   sizeof (struct query_packet) + 1,
1142                                   (struct sockaddr *) &dest, sizeof dest);
1143   }
1144
1145 outfree:
1146   free_parsed_dns_packet (pdns);
1147   pdns = NULL;
1148 out:
1149   GNUNET_SERVER_receive_done (client, GNUNET_OK);
1150 }
1151
1152 static void
1153 read_response (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc);
1154
1155 static void
1156 read_response6 (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc);
1157
1158 static int
1159 open_port6 ()
1160 {
1161   struct sockaddr_in6 addr;
1162
1163   dnsout6 = GNUNET_NETWORK_socket_create (AF_INET6, SOCK_DGRAM, 0);
1164   if (dnsout6 == NULL)
1165   {
1166     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Could not create socket: %m\n");
1167     return GNUNET_SYSERR;
1168   }
1169   memset (&addr, 0, sizeof (struct sockaddr_in6));
1170
1171   addr.sin6_family = AF_INET6;
1172   int err = GNUNET_NETWORK_socket_bind (dnsout6,
1173                                         (struct sockaddr *) &addr,
1174                                         sizeof (struct sockaddr_in6));
1175
1176   if (err != GNUNET_OK)
1177   {
1178     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Could not bind a port: %m\n");
1179     return GNUNET_SYSERR;
1180   }
1181
1182   GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL, dnsout6,
1183                                  &read_response6, NULL);
1184
1185   return GNUNET_YES;
1186 }
1187
1188 static int
1189 open_port ()
1190 {
1191   struct sockaddr_in addr;
1192
1193   dnsout = GNUNET_NETWORK_socket_create (AF_INET, SOCK_DGRAM, 0);
1194   if (dnsout == NULL)
1195     return GNUNET_SYSERR;
1196   memset (&addr, 0, sizeof (struct sockaddr_in));
1197
1198   addr.sin_family = AF_INET;
1199   int err = GNUNET_NETWORK_socket_bind (dnsout,
1200                                         (struct sockaddr *) &addr,
1201                                         sizeof (struct sockaddr_in));
1202
1203   if (err != GNUNET_OK)
1204   {
1205     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Could not bind a port: %m\n");
1206     return GNUNET_SYSERR;
1207   }
1208
1209   /* Read the port we bound to */
1210   socklen_t addrlen = sizeof (struct sockaddr_in);
1211
1212   err =
1213       getsockname (GNUNET_NETWORK_get_fd (dnsout), (struct sockaddr *) &addr,
1214                    &addrlen);
1215
1216   dnsoutport = htons (addr.sin_port);
1217
1218   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Bound to port %d.\n", dnsoutport);
1219
1220   GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL, dnsout,
1221                                  &read_response, NULL);
1222
1223   return GNUNET_YES;
1224 }
1225
1226 void
1227 handle_response (struct dns_pkt *dns, struct sockaddr *addr, socklen_t addrlen,
1228                  int r);
1229
1230 /**
1231  * Read a response-packet of the UDP-Socket
1232  */
1233 static void
1234 read_response6 (void *cls
1235                 __attribute__ ((unused)),
1236                 const struct GNUNET_SCHEDULER_TaskContext *tc)
1237 {
1238   struct sockaddr_in6 addr;
1239   socklen_t addrlen = sizeof (addr);
1240   int r;
1241   int len;
1242
1243   if (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)
1244     return;
1245
1246   memset (&addr, 0, sizeof addr);
1247
1248 #ifndef MINGW
1249   if (0 != ioctl (GNUNET_NETWORK_get_fd (dnsout6), FIONREAD, &len))
1250   {
1251     (void) open_port6 ();
1252     return;
1253   }
1254 #else
1255   /* port the code above? */
1256   len = 65536;
1257 #endif
1258
1259   unsigned char buf[len];
1260   struct dns_pkt *dns = (struct dns_pkt *) buf;
1261
1262   r = GNUNET_NETWORK_socket_recvfrom (dnsout, buf, sizeof (buf),
1263                                       (struct sockaddr *) &addr, &addrlen);
1264
1265   if (r < 0)
1266   {
1267     (void) open_port6 ();
1268     return;
1269   }
1270
1271   struct sockaddr *addr_ = GNUNET_malloc (sizeof addr);
1272
1273   memcpy (addr_, &addr, sizeof addr);
1274   handle_response (dns, addr_, 4, r);
1275
1276   GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL, dnsout6,
1277                                  &read_response6, NULL);
1278 }
1279
1280 /**
1281  * Read a response-packet of the UDP-Socket
1282  */
1283 static void
1284 read_response (void *cls
1285                __attribute__ ((unused)),
1286                const struct GNUNET_SCHEDULER_TaskContext *tc)
1287 {
1288   struct sockaddr_in addr;
1289   socklen_t addrlen = sizeof (addr);
1290   int r;
1291   int len;
1292
1293   if (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)
1294     return;
1295
1296   memset (&addr, 0, sizeof addr);
1297
1298 #ifndef MINGW
1299   if (0 != ioctl (GNUNET_NETWORK_get_fd (dnsout), FIONREAD, &len))
1300   {
1301     GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "ioctl");
1302     unhijack (dnsoutport);
1303     if (GNUNET_YES == open_port ())
1304       GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS, &hijack, NULL);
1305     return;
1306   }
1307 #else
1308   /* port the code above? */
1309   len = 65536;
1310 #endif
1311
1312   unsigned char buf[len];
1313   struct dns_pkt *dns = (struct dns_pkt *) buf;
1314
1315   r = GNUNET_NETWORK_socket_recvfrom (dnsout, buf, sizeof (buf),
1316                                       (struct sockaddr *) &addr, &addrlen);
1317
1318   if (r < 0)
1319   {
1320     GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "recvfrom");
1321     unhijack (dnsoutport);
1322     if (GNUNET_YES == open_port ())
1323       GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS, &hijack, NULL);
1324     return;
1325   }
1326
1327   struct sockaddr *addr_ = GNUNET_malloc (sizeof addr);
1328
1329   memcpy (addr_, &addr, sizeof addr);
1330   handle_response (dns, addr_, 4, r);
1331
1332   GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL, dnsout,
1333                                  &read_response, NULL);
1334 }
1335
1336 void
1337 handle_response (struct dns_pkt *dns, struct sockaddr *addr, socklen_t addrlen,
1338                  int r)
1339 {
1340   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Answer to query %d\n",
1341               ntohs (dns->s.id));
1342
1343
1344   if (query_states[dns->s.id].valid == GNUNET_YES)
1345   {
1346     if (query_states[dns->s.id].tunnel != NULL)
1347     {
1348       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1349                   "Answer to query %d for a remote peer!\n", ntohs (dns->s.id));
1350       /* This response should go through a tunnel */
1351       uint32_t *c =
1352           GNUNET_malloc (4 + sizeof (struct GNUNET_MESH_Tunnel *) + r);
1353       *c = r;
1354       struct GNUNET_MESH_Tunnel **t = (struct GNUNET_MESH_Tunnel **) (c + 1);
1355
1356       *t = query_states[dns->s.id].tunnel;
1357       memcpy (t + 1, dns, r);
1358       struct tunnel_state *s =
1359           GNUNET_MESH_tunnel_get_data (query_states[dns->s.id].tunnel);
1360       if (NULL == s->th)
1361       {
1362         s->th =
1363             GNUNET_MESH_notify_transmit_ready (query_states[dns->s.id].tunnel,
1364                                                GNUNET_YES, 32,
1365                                                GNUNET_TIME_UNIT_MINUTES, NULL,
1366                                                r +
1367                                                sizeof (struct
1368                                                        GNUNET_MessageHeader),
1369                                                mesh_send_response, c);
1370       }
1371       else
1372       {
1373         struct tunnel_notify_queue *element =
1374             GNUNET_malloc (sizeof (struct tunnel_notify_queue));
1375         element->cls = c;
1376         element->len = r + sizeof (struct GNUNET_MessageHeader);
1377         element->cb = mesh_send_response;
1378
1379         GNUNET_CONTAINER_DLL_insert_tail (s->head, s->tail, element);
1380       }
1381     }
1382     else
1383     {
1384       query_states[dns->s.id].valid = GNUNET_NO;
1385
1386       size_t len = sizeof (struct answer_packet) + r - 1;       /* 1 for the unsigned char data[1]; */
1387       struct answer_packet_list *answer =
1388           GNUNET_malloc (len + sizeof (struct answer_packet_list) -
1389                          (sizeof (struct answer_packet)));
1390       answer->pkt.hdr.type =
1391           htons (GNUNET_MESSAGE_TYPE_VPN_DNS_LOCAL_RESPONSE_DNS);
1392       answer->pkt.hdr.size = htons (len);
1393       answer->pkt.subtype = GNUNET_DNS_ANSWER_TYPE_IP;
1394       answer->pkt.addrlen = addrlen;
1395       if (addrlen == 16)
1396       {
1397         struct sockaddr_in6 *addr_ = (struct sockaddr_in6 *) addr;
1398
1399         memcpy (answer->pkt.from, &addr_->sin6_addr, addrlen);
1400         memcpy (answer->pkt.to, query_states[dns->s.id].local_ip, addrlen);
1401       }
1402       else if (addrlen == 4)
1403       {
1404         struct sockaddr_in *addr_ = (struct sockaddr_in *) addr;
1405
1406         memcpy (answer->pkt.from, &addr_->sin_addr.s_addr, addrlen);
1407         memcpy (answer->pkt.to, query_states[dns->s.id].local_ip, addrlen);
1408       }
1409       else
1410       {
1411         GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "addrlen = %d\n", addrlen);
1412         GNUNET_assert (0);
1413       }
1414       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "sending answer with addrlen = %d\n",
1415                   addrlen);
1416       answer->pkt.dst_port = query_states[dns->s.id].local_port;
1417       memcpy (answer->pkt.data, dns, r);
1418       answer->client = query_states[dns->s.id].client;
1419
1420       GNUNET_CONTAINER_DLL_insert_after (head, tail, tail, answer);
1421
1422       if (server_notify == NULL)
1423         server_notify =
1424             GNUNET_SERVER_notify_transmit_ready (query_states[dns->s.id].client,
1425                                                  len,
1426                                                  GNUNET_TIME_UNIT_FOREVER_REL,
1427                                                  &send_answer, NULL);
1428     }
1429   }
1430   GNUNET_free (addr);
1431 }
1432
1433
1434 /**
1435  * Task run during shutdown.
1436  *
1437  * @param cls unused
1438  * @param tc unused
1439  */
1440 static void
1441 cleanup_task (void *cls
1442               __attribute__ ((unused)),
1443               const struct GNUNET_SCHEDULER_TaskContext *tc)
1444 {
1445   GNUNET_assert (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN));
1446
1447   unhijack (dnsoutport);
1448   GNUNET_DHT_disconnect (dht);
1449   GNUNET_MESH_disconnect (mesh_handle);
1450 }
1451
1452 /**
1453  * @brief Create a port-map from udp and tcp redirects
1454  *
1455  * @param udp_redirects
1456  * @param tcp_redirects
1457  *
1458  * @return
1459  */
1460 static uint64_t
1461 get_port_from_redirects (const char *udp_redirects, const char *tcp_redirects)
1462 {
1463   uint64_t ret = 0;
1464   char *cpy, *hostname, *redirect;
1465   int local_port;
1466   unsigned int count = 0;
1467
1468   cpy = NULL;
1469   if (NULL != udp_redirects)
1470   {
1471     cpy = GNUNET_strdup (udp_redirects);
1472     for (redirect = strtok (cpy, " "); redirect != NULL;
1473          redirect = strtok (NULL, " "))
1474     {
1475       if (NULL == (hostname = strstr (redirect, ":")))
1476       {
1477         GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1478                     "Warning: option %s is not formatted correctly!\n",
1479                     redirect);
1480         continue;
1481       }
1482       hostname[0] = '\0';
1483       local_port = atoi (redirect);
1484       if (!((local_port > 0) && (local_port < 65536)))
1485         GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1486                     "Warning: %s is not a correct port.", redirect);
1487
1488       ret |= (0xFFFF & htons (local_port));
1489       ret <<= 16;
1490       count++;
1491
1492       if (count > 4)
1493       {
1494         ret = 0;
1495         goto out;
1496       }
1497     }
1498     GNUNET_free (cpy);
1499     cpy = NULL;
1500   }
1501
1502   if (NULL != tcp_redirects)
1503   {
1504     cpy = GNUNET_strdup (tcp_redirects);
1505     for (redirect = strtok (cpy, " "); redirect != NULL;
1506          redirect = strtok (NULL, " "))
1507     {
1508       if (NULL == (hostname = strstr (redirect, ":")))
1509       {
1510         GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1511                     "Warning: option %s is not formatted correctly!\n",
1512                     redirect);
1513         continue;
1514       }
1515       hostname[0] = '\0';
1516       local_port = atoi (redirect);
1517       if (!((local_port > 0) && (local_port < 65536)))
1518         GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1519                     "Warning: %s is not a correct port.", redirect);
1520
1521       ret |= (0xFFFF & htons (local_port));
1522       ret <<= 16;
1523       count++;
1524
1525       if (count > 4)
1526       {
1527         ret = 0;
1528         goto out;
1529       }
1530     }
1531     GNUNET_free (cpy);
1532     cpy = NULL;
1533   }
1534
1535 out:
1536   GNUNET_free_non_null (cpy);
1537   return ret;
1538 }
1539
1540 static void
1541 publish_name (const char *name, uint64_t ports, uint32_t service_type,
1542               struct GNUNET_CRYPTO_RsaPrivateKey *my_private_key)
1543 {
1544   size_t size = sizeof (struct GNUNET_DNS_Record);
1545   struct GNUNET_DNS_Record data;
1546
1547   memset (&data, 0, size);
1548
1549   data.purpose.size = htonl (size - sizeof (struct GNUNET_CRYPTO_RsaSignature));
1550   data.purpose.purpose = GNUNET_SIGNATURE_PURPOSE_DNS_RECORD;
1551
1552   GNUNET_CRYPTO_hash (name, strlen (name) + 1, &data.service_descriptor);
1553   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Store with key1 %x\n",
1554               *((unsigned long long *) &data.service_descriptor));
1555
1556   data.service_type = service_type;
1557   data.ports = ports;
1558
1559   GNUNET_CRYPTO_rsa_key_get_public (my_private_key, &data.peer);
1560
1561   data.expiration_time =
1562       GNUNET_TIME_absolute_hton (GNUNET_TIME_relative_to_absolute
1563                                  (GNUNET_TIME_relative_multiply
1564                                   (GNUNET_TIME_UNIT_HOURS, 2)));
1565
1566   /* Sign the block */
1567   if (GNUNET_OK !=
1568       GNUNET_CRYPTO_rsa_sign (my_private_key, &data.purpose, &data.signature))
1569   {
1570     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "could not sign DNS_Record\n");
1571     return;
1572   }
1573
1574   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Putting with key %08x, size = %d\n",
1575               *((unsigned int *) &data.service_descriptor), size);
1576
1577   GNUNET_DHT_put (dht, &data.service_descriptor,
1578                   5 /* DEFAULT_PUT_REPLICATION */ ,
1579                   GNUNET_DHT_RO_NONE, GNUNET_BLOCK_TYPE_DNS, size,
1580                   (char *) &data,
1581                   GNUNET_TIME_relative_to_absolute (GNUNET_TIME_UNIT_HOURS),
1582                   GNUNET_TIME_UNIT_MINUTES, NULL, NULL);
1583 }
1584
1585
1586 /**
1587  * @brief Publishes the record defined by the section section
1588  *
1589  * @param cls closure
1590  * @param section the current section
1591  */
1592 static void
1593 publish_iterate (void *cls __attribute__ ((unused)), const char *section)
1594 {
1595   char *udp_redirects;
1596   char *tcp_redirects;
1597   char *alternative_names;
1598   char *alternative_name;
1599   char *keyfile;
1600
1601   if ((strlen (section) < 8) ||
1602       (0 != strcmp (".gnunet.", section + (strlen (section) - 8))))
1603     return;
1604   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Parsing dns-name %s\n", section);
1605   if (GNUNET_OK !=
1606       GNUNET_CONFIGURATION_get_value_string (cfg, section, "UDP_REDIRECTS",
1607                                              &udp_redirects))
1608     udp_redirects = NULL;
1609   if (GNUNET_OK !=
1610       GNUNET_CONFIGURATION_get_value_string (cfg, section, "TCP_REDIRECTS",
1611                                              &tcp_redirects))
1612     tcp_redirects = NULL;
1613
1614   if (GNUNET_OK !=
1615       GNUNET_CONFIGURATION_get_value_filename (cfg, "GNUNETD", "HOSTKEY",
1616                                                &keyfile))
1617   {
1618     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "could not read keyfile-value\n");
1619     if (keyfile != NULL)
1620       GNUNET_free (keyfile);
1621     return;
1622   }
1623
1624   struct GNUNET_CRYPTO_RsaPrivateKey *my_private_key =
1625       GNUNET_CRYPTO_rsa_key_create_from_file (keyfile);
1626   GNUNET_free (keyfile);
1627   GNUNET_assert (my_private_key != NULL);
1628
1629   uint64_t ports = get_port_from_redirects (udp_redirects, tcp_redirects);
1630   uint32_t service_type = 0;
1631
1632   if (NULL != udp_redirects)
1633     service_type = GNUNET_DNS_SERVICE_TYPE_UDP;
1634
1635   if (NULL != tcp_redirects)
1636     service_type |= GNUNET_DNS_SERVICE_TYPE_TCP;
1637
1638   service_type = htonl (service_type);
1639
1640
1641   publish_name (section, ports, service_type, my_private_key);
1642   if (GNUNET_OK ==
1643       GNUNET_CONFIGURATION_get_value_string (cfg, section, "ALTERNATIVE_NAMES",
1644                                              &alternative_names))
1645   {
1646     for (alternative_name = strtok (alternative_names, " ");
1647          alternative_name != NULL; alternative_name = strtok (NULL, " "))
1648     {
1649       char *altname =
1650           alloca (strlen (alternative_name) + strlen (section) + 1 + 1);
1651       strcpy (altname, alternative_name);
1652       strcpy (altname + strlen (alternative_name) + 1, section);
1653       altname[strlen (alternative_name)] = '.';
1654
1655       publish_name (altname, ports, service_type, my_private_key);
1656     }
1657     GNUNET_free (alternative_names);
1658   }
1659   GNUNET_CRYPTO_rsa_key_free (my_private_key);
1660   GNUNET_free_non_null (udp_redirects);
1661   GNUNET_free_non_null (tcp_redirects);
1662 }
1663
1664 /**
1665  * Publish a DNS-record in the DHT.
1666  */
1667 static void
1668 publish_names (void *cls
1669                __attribute__ ((unused)),
1670                const struct GNUNET_SCHEDULER_TaskContext *tc)
1671 {
1672   if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
1673     return;
1674
1675   GNUNET_CONFIGURATION_iterate_sections (cfg, &publish_iterate, NULL);
1676
1677   GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_HOURS, &publish_names, NULL);
1678 }
1679
1680 /**
1681  * @param cls closure
1682  * @param server the initialized server
1683  * @param cfg_ configuration to use
1684  */
1685 static void
1686 run (void *cls, struct GNUNET_SERVER_Handle *server,
1687      const struct GNUNET_CONFIGURATION_Handle *cfg_)
1688 {
1689   static const struct GNUNET_SERVER_MessageHandler handlers[] = {
1690     /* callback, cls, type, size */
1691     {&receive_query, NULL, GNUNET_MESSAGE_TYPE_VPN_DNS_LOCAL_QUERY_DNS, 0},
1692     {&rehijack, NULL, GNUNET_MESSAGE_TYPE_REHIJACK,
1693      sizeof (struct GNUNET_MessageHeader)},
1694     {NULL, NULL, 0, 0}
1695   };
1696
1697   static const struct GNUNET_MESH_MessageHandler mesh_handlers[] = {
1698     {receive_mesh_query, GNUNET_MESSAGE_TYPE_VPN_REMOTE_QUERY_DNS, 0},
1699     {receive_mesh_answer, GNUNET_MESSAGE_TYPE_VPN_REMOTE_ANSWER_DNS, 0},
1700     {NULL, 0, 0}
1701   };
1702
1703   static GNUNET_MESH_ApplicationType apptypes[] = {
1704     GNUNET_APPLICATION_TYPE_END,
1705     GNUNET_APPLICATION_TYPE_END
1706   };
1707
1708   if (GNUNET_YES != open_port6 ())
1709   {
1710     GNUNET_SCHEDULER_shutdown ();
1711     return;
1712   }
1713
1714   if (GNUNET_YES != open_port ())
1715   {
1716     GNUNET_SCHEDULER_shutdown ();
1717     return;
1718   }
1719
1720   if (GNUNET_YES ==
1721       GNUNET_CONFIGURATION_get_value_yesno (cfg_, "dns", "PROVIDE_EXIT"))
1722     apptypes[0] = GNUNET_APPLICATION_TYPE_INTERNET_RESOLVER;
1723   mesh_handle =
1724       GNUNET_MESH_connect (cfg_, 42, NULL, new_tunnel, clean_tunnel,
1725                            mesh_handlers, apptypes);
1726
1727   cfg = cfg_;
1728   dht = GNUNET_DHT_connect (cfg, 1024);
1729   GNUNET_SCHEDULER_add_now (publish_names, NULL);
1730   GNUNET_SERVER_add_handlers (server, handlers);
1731   GNUNET_SERVER_disconnect_notify (server, &client_disconnect, NULL);
1732   GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &cleanup_task,
1733                                 cls);
1734 }
1735
1736 /**
1737  * The main function for the dns service.
1738  *
1739  * @param argc number of arguments from the command line
1740  * @param argv command line arguments
1741  * @return 0 ok, 1 on error
1742  */
1743 int
1744 main (int argc, char *const *argv)
1745 {
1746   return (GNUNET_OK ==
1747           GNUNET_SERVICE_run (argc, argv, "dns", GNUNET_SERVICE_OPTION_NONE,
1748                               &run, NULL)) ? 0 : 1;
1749 }