i simply do not learn
[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_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"
43
44 struct GNUNET_MESH_Handle *mesh_handle;
45
46 struct GNUNET_CONNECTION_TransmitHandle *server_notify;
47
48 /**
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.
51  */
52 static struct GNUNET_NETWORK_Handle *dnsout;
53 static struct GNUNET_NETWORK_Handle *dnsout6;
54
55 /**
56  * The port bound to the socket dnsout
57  */
58 static unsigned short dnsoutport;
59
60 /**
61  * A handle to the DHT-Service
62  */
63 static struct GNUNET_DHT_Handle *dht;
64
65 /**
66  * The configuration to use
67  */
68 static const struct GNUNET_CONFIGURATION_Handle *cfg;
69
70 /**
71  * A list of DNS-Responses that have to be sent to the requesting client
72  */
73 static struct answer_packet_list *head;
74
75 /**
76  * The tail of the list of DNS-responses
77  */
78 static struct answer_packet_list *tail;
79
80 /**
81  * A structure containing a mapping from network-byte-ordered DNS-id (16 bit) to
82  * some information needed to handle this query
83  *
84  * It currently allocates at least
85  * (1 + machine-width + machine-width + 32 + 32 + 16 + machine-width + 8) * 65536 bit
86  * = 17 MiB on 64 bit.
87  * = 11 MiB on 32 bit.
88  */
89 static struct
90 {
91   unsigned valid:1;
92   struct GNUNET_SERVER_Client *client;
93   struct GNUNET_MESH_Tunnel *tunnel;
94   char local_ip[16];
95   char remote_ip[16];
96   char addrlen;
97   uint16_t local_port;
98   char *name;
99   uint8_t namelen;
100   uint16_t qtype;
101 } query_states[UINT16_MAX+1];
102
103 /**
104  * A struct used to give more than one value as
105  * closure to receive_dht
106  */
107 struct receive_dht_cls
108 {
109   uint16_t id;
110   struct GNUNET_DHT_GetHandle *handle;
111 };
112
113 struct tunnel_notify_queue
114 {
115   struct tunnel_notify_queue *next;
116   struct tunnel_notify_queue *prev;
117   void *cls;
118   size_t len;
119   GNUNET_CONNECTION_TransmitReadyNotify cb;
120 };
121
122 /**
123  * Hijack all outgoing DNS-Traffic but for traffic leaving "our" port.
124  */
125 static void
126 hijack (void *cls
127         __attribute__ ((unused)), const struct GNUNET_SCHEDULER_TaskContext *tc)
128 {
129   if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
130     return;
131
132   if (0 == dnsoutport)
133   {
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);
137     return;
138   }
139
140   char port_s[6];
141   char *virt_dns;
142   struct GNUNET_OS_Process *proc;
143
144   if (GNUNET_SYSERR ==
145       GNUNET_CONFIGURATION_get_value_string (cfg, "vpn", "VIRTDNS", &virt_dns))
146   {
147     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
148                 "No entry 'VIRTDNS' in configuration!\n");
149     exit (1);
150   }
151
152   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Hijacking, port is %d\n", dnsoutport);
153   snprintf (port_s, 6, "%d", dnsoutport);
154   if (NULL !=
155       (proc =
156        GNUNET_OS_start_process (NULL, NULL, "gnunet-helper-hijack-dns",
157                                 "gnunet-hijack-dns", port_s, virt_dns, NULL)))
158   {
159     GNUNET_break (GNUNET_OK == GNUNET_OS_process_wait (proc));
160     GNUNET_OS_process_close (proc);
161   }
162   GNUNET_free (virt_dns);
163 }
164
165 /**
166  * Delete the hijacking-routes
167  */
168 static void
169 unhijack (unsigned short port)
170 {
171   char port_s[6];
172   char *virt_dns;
173   struct GNUNET_OS_Process *proc;
174
175   if (GNUNET_SYSERR ==
176       GNUNET_CONFIGURATION_get_value_string (cfg, "vpn", "VIRTDNS", &virt_dns))
177   {
178     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
179                 "No entry 'VIRTDNS' in configuration!\n");
180     exit (1);
181   }
182
183   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "unHijacking, port is %d\n", port);
184   snprintf (port_s, 6, "%d", port);
185   if (NULL !=
186       (proc =
187        GNUNET_OS_start_process (NULL, NULL, "gnunet-helper-hijack-dns",
188                                 "gnunet-hijack-dns", "-d", port_s, virt_dns,
189                                 NULL)))
190     {
191       GNUNET_break (GNUNET_OK == GNUNET_OS_process_wait (proc));
192       GNUNET_OS_process_close (proc);
193     }
194   GNUNET_free (virt_dns);
195 }
196
197 /**
198  * Send the DNS-Response to the client. Gets called via the notify_transmit_ready-
199  * system.
200  */
201 static size_t
202 send_answer (void *cls, size_t size, void *buf)
203 {
204   server_notify = NULL;
205   struct answer_packet_list *query = head;
206   size_t len = ntohs (query->pkt.hdr.size);
207
208   GNUNET_assert (len <= size);
209
210   memcpy (buf, &query->pkt.hdr, len);
211
212   GNUNET_CONTAINER_DLL_remove (head, tail, query);
213
214   GNUNET_free (query);
215
216   /* When more data is to be sent, reschedule */
217   if (head != NULL)
218     server_notify = GNUNET_SERVER_notify_transmit_ready (cls, ntohs (head->pkt.hdr.size),
219                                                          GNUNET_TIME_UNIT_FOREVER_REL,
220                                                          &send_answer, cls);
221
222   return len;
223 }
224
225 struct tunnel_cls
226 {
227   struct GNUNET_MESH_Tunnel *tunnel GNUNET_PACKED;
228   struct GNUNET_MessageHeader hdr;
229   struct dns_pkt dns;
230 };
231
232 struct tunnel_cls *remote_pending[UINT16_MAX];
233
234 static size_t
235 mesh_send_response (void *cls, size_t size, void *buf)
236 {
237   GNUNET_assert (size >= sizeof (struct GNUNET_MessageHeader));
238   struct GNUNET_MessageHeader *hdr = buf;
239   uint32_t *sz = cls;
240   struct GNUNET_MESH_Tunnel **tunnel = (struct GNUNET_MESH_Tunnel **) (sz + 1);
241   struct dns_pkt *dns = (struct dns_pkt *) (tunnel + 1);
242
243   GNUNET_MESH_tunnel_set_data (*tunnel, NULL);
244
245   hdr->type = htons (GNUNET_MESSAGE_TYPE_VPN_REMOTE_ANSWER_DNS);
246   hdr->size = htons (*sz + sizeof (struct GNUNET_MessageHeader));
247
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));
251
252   GNUNET_assert (size >= (*sz + sizeof (struct GNUNET_MessageHeader)));
253
254   memcpy (hdr + 1, dns, *sz);
255
256   if (NULL != GNUNET_MESH_tunnel_get_head (*tunnel))
257   {
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);
261
262     GNUNET_CONTAINER_DLL_remove (head, tail, element);
263
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,
268                                            GNUNET_NO,
269                                            42,
270                                            GNUNET_TIME_relative_divide
271                                            (GNUNET_CONSTANTS_MAX_CORK_DELAY, 2),
272                                            (const struct GNUNET_PeerIdentity *)
273                                            NULL, element->len,
274                                            element->cb, element->cls);
275
276     /* save the handle */
277     GNUNET_MESH_tunnel_set_data (*tunnel, th);
278   }
279
280   GNUNET_free (cls);
281
282   return ntohs (hdr->size);
283 }
284
285 static size_t
286 mesh_send (void *cls, size_t size, void *buf)
287 {
288   struct tunnel_cls *cls_ = (struct tunnel_cls *) cls;
289
290   GNUNET_MESH_tunnel_set_data (cls_->tunnel, NULL);
291
292   GNUNET_assert (cls_->hdr.size <= size);
293
294   size = cls_->hdr.size;
295   cls_->hdr.size = htons (cls_->hdr.size);
296
297   memcpy (buf, &cls_->hdr, size);
298
299   if (NULL != GNUNET_MESH_tunnel_get_head (cls_->tunnel))
300   {
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);
307
308     GNUNET_CONTAINER_DLL_remove (head, tail, element);
309
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,
314                                            GNUNET_NO,
315                                            42,
316                                            GNUNET_TIME_relative_divide
317                                            (GNUNET_CONSTANTS_MAX_CORK_DELAY, 2),
318                                            (const struct GNUNET_PeerIdentity *)
319                                            NULL, element->len,
320                                            element->cb, element->cls);
321
322     /* save the handle */
323     GNUNET_MESH_tunnel_set_data (cls_->tunnel, th);
324     GNUNET_free (element);
325   }
326
327   return size;
328 }
329
330
331 void
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)))
337 {
338   if (NULL == peer)
339     return;
340   struct tunnel_cls *cls_ = (struct tunnel_cls *) cls;
341
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));
345
346   if (NULL == GNUNET_MESH_tunnel_get_data (cls_->tunnel))
347   {
348     struct GNUNET_MESH_TransmitHandle *th =
349         GNUNET_MESH_notify_transmit_ready (cls_->tunnel,
350                                            GNUNET_YES,
351                                            42,
352                                            GNUNET_TIME_UNIT_MINUTES,
353                                            NULL,
354                                            cls_->hdr.size,
355                                            mesh_send,
356                                            cls);
357
358     GNUNET_MESH_tunnel_set_data (cls_->tunnel, th);
359   }
360   else
361   {
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);
366
367     struct tunnel_notify_queue *element =
368         GNUNET_malloc (sizeof (struct tunnel_notify_queue));
369     element->cls = cls;
370     element->len = cls_->hdr.size;
371     element->cb = mesh_send;
372
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);
376   }
377 }
378
379
380 static void
381 send_mesh_query (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
382 {
383   if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
384     return;
385
386   struct tunnel_cls *cls_ = (struct tunnel_cls *) cls;
387
388   cls_->tunnel =
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_);
393
394   remote_pending[cls_->dns.s.id] = cls_;
395 }
396
397 static int
398 receive_mesh_query (void *cls
399                     __attribute__ ((unused)), struct GNUNET_MESH_Tunnel *tunnel,
400                     void **ctx
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)))
409 {
410   struct dns_pkt *dns = (struct dns_pkt *) (message + 1);
411
412   struct sockaddr_in dest;
413
414   memset (&dest, 0, sizeof dest);
415   dest.sin_port = htons (53);
416   char *dns_resolver;
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);
420
421   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Querying for remote, id=%d\n",
422               ntohs (dns->s.id));
423   query_states[dns->s.id].tunnel = tunnel;
424   query_states[dns->s.id].valid = GNUNET_YES;
425
426   GNUNET_NETWORK_socket_sendto (dnsout, dns,
427                                 ntohs (message->size) -
428                                 sizeof (struct GNUNET_MessageHeader),
429                                 (struct sockaddr *) &dest, sizeof dest);
430
431   return GNUNET_SYSERR;
432 }
433
434 static int
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)))
445 {
446   /* TODo: size check */
447   struct dns_pkt *dns = (struct dns_pkt *) (message + 1);
448
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)
452     return GNUNET_OK;
453
454   GNUNET_free (remote_pending[dns->s.id]);
455   remote_pending[dns->s.id] = NULL;
456
457   if (query_states[dns->s.id].valid != GNUNET_YES)
458     return GNUNET_SYSERR;
459   query_states[dns->s.id].valid = GNUNET_NO;
460
461   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
462               "Received answer from peer %s, dns-id %d\n", GNUNET_i2s (sender),
463               ntohs (dns->s.id));
464
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 */
467
468   struct answer_packet_list *answer =
469       GNUNET_malloc (len + 2 * sizeof (struct answer_packet_list *));
470
471   answer->pkt.hdr.type = htons (GNUNET_MESSAGE_TYPE_VPN_DNS_LOCAL_RESPONSE_DNS);
472   answer->pkt.hdr.size = htons (len);
473
474   struct dns_pkt_parsed *pdns = parse_dns_packet (dns);
475
476   if (ntohs (pdns->s.ancount) < 1)
477   {
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);
482     return GNUNET_OK;
483   }
484
485   int i = 0;
486
487   while (i < ntohs(pdns->s.ancount) &&
488          pdns->answers[i]->type != 28 &&
489          pdns->answers[i]->type != 1)
490     i++;
491
492   if (i >= ntohs (pdns->s.ancount))
493   {
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);
497     return GNUNET_OK;
498   }
499
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));
505
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;
510
511   struct dns_pkt *dpkt = (struct dns_pkt *) answer->pkt.data;
512
513   dpkt->s.id = dns->s.id;
514   dpkt->s.aa = 1;
515   dpkt->s.qr = 1;
516   dpkt->s.ra = 1;
517   dpkt->s.qdcount = htons (1);
518   dpkt->s.ancount = htons (1);
519
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;
524
525   struct dns_query_line *dque =
526       (struct dns_query_line *) (dpkt->data +
527                                  (query_states[dns->s.id].namelen));
528
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)
534   {
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);
539   }
540   if (ntohs(1) == query_states[dns->s.id].qtype)
541   {
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);
546   }
547   else
548     {
549       GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "dns-answer with data_len = %d\n", answer->pkt.addrsize);
550       GNUNET_break(0);
551     }
552   dque->class = htons (1);      /* IN */
553
554   char *anname =
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 */
559
560   drec_data->ttl = pdns->answers[i]->ttl;
561
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)));
567
568   GNUNET_CONTAINER_DLL_insert_after (head, tail, tail, answer);
569
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,
573                                                          &send_answer,
574                                                          query_states[dns->s.id].client);
575
576   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
577               "Sent answer of length %d on to client, addroffset = %d\n", len,
578               answer->pkt.addroffset);
579
580   free_parsed_dns_packet (pdns);
581   return GNUNET_OK;
582 }
583
584
585 static void
586 send_rev_query (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
587 {
588   if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
589     return;
590
591   struct dns_pkt_parsed *pdns = (struct dns_pkt_parsed *) cls;
592
593   unsigned short id = pdns->s.id;
594
595   free_parsed_dns_packet (pdns);
596
597   if (query_states[id].valid != GNUNET_YES)
598     return;
599   query_states[id].valid = GNUNET_NO;
600
601   GNUNET_assert (query_states[id].namelen == 74);
602
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 */ ;
607
608   struct answer_packet_list *answer =
609       GNUNET_malloc (len + 2 * sizeof (struct answer_packet_list *));
610
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;
614
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);
617
618   answer->pkt.dst_port = query_states[id].local_port;
619
620   struct dns_pkt *dpkt = (struct dns_pkt *) answer->pkt.data;
621
622   dpkt->s.id = id;
623   dpkt->s.aa = 1;
624   dpkt->s.qr = 1;
625   dpkt->s.ra = 1;
626   dpkt->s.qdcount = htons (1);
627   dpkt->s.ancount = htons (1);
628
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;
632
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 */
637
638   char *anname =
639       (char *) (dpkt->data + (query_states[id].namelen) +
640                 sizeof (struct dns_query_line));
641   memcpy (anname, "\xc0\x0c", 2);
642
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)
650    *
651    * But how to get the seconds out of this?
652    */
653   drec_data->ttl = htonl (3600);
654
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)));
660
661   GNUNET_CONTAINER_DLL_insert_after (head, tail, tail, answer);
662
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);
667 }
668
669 /**
670  * Receive a block from the dht.
671  */
672 static void
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,
681              const void *data)
682 {
683
684   unsigned short id = ((struct receive_dht_cls *) cls)->id;
685   struct GNUNET_DHT_GetHandle *handle =
686       ((struct receive_dht_cls *) cls)->handle;
687   GNUNET_free (cls);
688
689   GNUNET_DHT_get_stop (handle);
690
691   GNUNET_assert (type == GNUNET_BLOCK_TYPE_DNS);
692
693   /* If no query with this id is pending, ignore the block */
694   if (query_states[id].valid != GNUNET_YES)
695     return;
696   query_states[id].valid = GNUNET_NO;
697
698   const struct GNUNET_DNS_Record *rec = data;
699
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));
704
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 */
707
708   struct answer_packet_list *answer =
709       GNUNET_malloc (len + 2 * sizeof (struct answer_packet_list *));
710
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;
714
715   GNUNET_CRYPTO_hash (&rec->peer,
716                       sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded),
717                       &answer->pkt.service_descr.peer);
718
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));
725
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;
729
730   answer->pkt.dst_port = query_states[id].local_port;
731
732   struct dns_pkt *dpkt = (struct dns_pkt *) answer->pkt.data;
733
734   dpkt->s.id = id;
735   dpkt->s.aa = 1;
736   dpkt->s.qr = 1;
737   dpkt->s.ra = 1;
738   dpkt->s.qdcount = htons (1);
739   dpkt->s.ancount = htons (1);
740
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;
744
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 */
749
750   char *anname =
751       (char *) (dpkt->data + (query_states[id].namelen) +
752                 sizeof (struct dns_query_line));
753   memcpy (anname, "\xc0\x0c", 2);
754
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 */
760
761   /* FIXME: read the TTL from block:
762    * GNUNET_TIME_absolute_get_remaining(rec->expiration_time)
763    *
764    * But how to get the seconds out of this?
765    */
766   drec_data->ttl = htonl (3600);
767   drec_data->data_len = htons (16);
768
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)));
774
775   GNUNET_CONTAINER_DLL_insert_after (head, tail, tail, answer);
776
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);
781 }
782
783 /**
784  * This receives a GNUNET_MESSAGE_TYPE_REHIJACK and rehijacks the DNS
785  */
786 static void
787 rehijack (void *cls
788           __attribute__ ((unused)), struct GNUNET_SERVER_Client *client,
789           const struct GNUNET_MessageHeader *message __attribute__ ((unused)))
790 {
791   unhijack (dnsoutport);
792   GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS, &hijack, NULL);
793
794   GNUNET_SERVER_receive_done (client, GNUNET_OK);
795 }
796
797 /**
798  * This receives the dns-payload from the daemon-vpn and sends it on over the udp-socket
799  */
800 static void
801 receive_query (void *cls
802                __attribute__ ((unused)), struct GNUNET_SERVER_Client *client,
803                const struct GNUNET_MessageHeader *message)
804 {
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);
808
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);
822
823   int i;
824   for (i= 0; i < ntohs(pdns->s.qdcount); i++)
825     {
826       if (pdns->queries[i]->qtype == htons(28) ||
827           pdns->queries[i]->qtype == htons(28))
828         {
829           query_states[dns->s.id].qtype = pdns->queries[i]->qtype;
830             break;
831         }
832     }
833
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),
837                     ".gnunet.", 9))
838   {
839     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Query for .gnunet!\n");
840     GNUNET_HashCode key;
841
842     GNUNET_CRYPTO_hash (pdns->queries[0]->name, pdns->queries[0]->namelen,
843                         &key);
844
845     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Getting with key %08x, len is %d\n",
846                 *((unsigned int *) &key), pdns->queries[0]->namelen);
847
848     struct receive_dht_cls *cls =
849         GNUNET_malloc (sizeof (struct receive_dht_cls));
850     cls->id = dns->s.id;
851
852     cls->handle =
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);
857
858     goto outfree;
859   }
860
861   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Query for '%s'; namelen=%d\n",
862               pdns->queries[0]->name, pdns->queries[0]->namelen);
863
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)
866   {
867     char *ipv6addr;
868     char ipv6[16];
869     char ipv6rev[74] =
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.";
871     unsigned int i;
872     unsigned long long ipv6prefix;
873     unsigned int comparelen;
874
875     GNUNET_assert (GNUNET_OK ==
876                    GNUNET_CONFIGURATION_get_value_string (cfg, "vpn",
877                                                           "IPV6ADDR",
878                                                           &ipv6addr));
879     inet_pton (AF_INET6, ipv6addr, ipv6);
880     GNUNET_free (ipv6addr);
881
882     GNUNET_assert (GNUNET_OK ==
883                    GNUNET_CONFIGURATION_get_value_number (cfg, "vpn",
884                                                           "IPV6PREFIX",
885                                                           &ipv6prefix));
886     GNUNET_assert (ipv6prefix < 127);
887     ipv6prefix = (ipv6prefix + 7) / 8;
888
889     for (i = ipv6prefix; i < 16; i++)
890       ipv6[i] = 0;
891
892     for (i = 0; i < 16; i++)
893     {
894       unsigned char c1 = ipv6[i] >> 4;
895       unsigned char c2 = ipv6[i] & 0xf;
896
897       if (c1 <= 9)
898         ipv6rev[62 - (4 * i)] = c1 + '0';
899       else
900         ipv6rev[62 - (4 * i)] = c1 + 87;        /* 87 is the difference between 'a' and 10 */
901
902       if (c2 <= 9)
903         ipv6rev[62 - ((4 * i) + 2)] = c2 + '0';
904       else
905         ipv6rev[62 - ((4 * i) + 2)] = c2 + 87;
906     }
907     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "My network is %s'.\n", ipv6rev);
908     comparelen = 10 + 4 * ipv6prefix;
909     if (0 ==
910         strncmp (pdns->queries[0]->name +
911                  (pdns->queries[0]->namelen - comparelen),
912                  ipv6rev + (74 - comparelen), comparelen))
913     {
914       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Reverse-Query for .gnunet!\n");
915
916       GNUNET_SCHEDULER_add_now (send_rev_query, pdns);
917
918       goto out;
919     }
920   }
921
922   unsigned char virt_dns_bytes[16];
923
924   if (pkt->addrlen == 4)
925     {
926       char *virt_dns;
927
928       if (GNUNET_SYSERR ==
929           GNUNET_CONFIGURATION_get_value_string (cfg, "vpn", "VIRTDNS", &virt_dns))
930       {
931         GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
932                     "No entry 'VIRTDNS' in configuration!\n");
933         exit (1);
934       }
935
936       if (1 != inet_pton (AF_INET, virt_dns, &virt_dns_bytes))
937       {
938         GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Error parsing 'VIRTDNS': %s; %m!\n",
939                     virt_dns);
940         exit (1);
941       }
942
943       GNUNET_free (virt_dns);
944     }
945   else if (pkt->addrlen == 16)
946     {
947       char *virt_dns;
948
949       if (GNUNET_SYSERR ==
950           GNUNET_CONFIGURATION_get_value_string (cfg, "vpn", "VIRTDNS6", &virt_dns))
951       {
952         GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
953                     "No entry 'VIRTDNS6' in configuration!\n");
954         exit (1);
955       }
956
957       if (1 != inet_pton (AF_INET6, virt_dns, &virt_dns_bytes))
958       {
959         GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Error parsing 'VIRTDNS6': %s; %m!\n",
960                     virt_dns);
961         exit (1);
962       }
963
964       GNUNET_free (virt_dns);
965     }
966   else
967     {
968       GNUNET_assert(0);
969     }
970
971   if (memcmp(virt_dns_bytes,pkt->orig_to, pkt->addrlen) == 0)
972   {
973     /* This is a packet that was sent directly to the virtual dns-server
974      *
975      * This means we have to send this query over gnunet
976      */
977
978     size_t size =
979         sizeof (struct GNUNET_MESH_Tunnel *) +
980         sizeof (struct GNUNET_MessageHeader) + (ntohs (message->size) -
981                                                 sizeof (struct query_packet) +
982                                                 1);
983     struct tunnel_cls *cls_ = GNUNET_malloc (size);
984
985     cls_->hdr.size = size - sizeof (struct GNUNET_MESH_Tunnel *);
986
987     cls_->hdr.type = ntohs (GNUNET_MESSAGE_TYPE_VPN_REMOTE_QUERY_DNS);
988     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "size: %d\n", size);
989
990     memcpy (&cls_->dns, dns,
991             cls_->hdr.size - sizeof (struct GNUNET_MessageHeader));
992     GNUNET_SCHEDULER_add_now (send_mesh_query, cls_);
993
994     if (pdns->s.qdcount == 1)
995       {
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);
1000         else
1001           goto outfree;
1002         struct dns_pkt *rdns = unparse_dns_packet (pdns);
1003         size_t size =
1004           sizeof (struct GNUNET_MESH_Tunnel *) +
1005           sizeof (struct GNUNET_MessageHeader) + (ntohs (message->size) -
1006                                                   sizeof (struct query_packet) +
1007                                                   1);
1008         struct tunnel_cls *cls_ = GNUNET_malloc (size);
1009
1010         cls_->hdr.size = size - sizeof (struct GNUNET_MESH_Tunnel *);
1011
1012         cls_->hdr.type = ntohs (GNUNET_MESSAGE_TYPE_VPN_REMOTE_QUERY_DNS);
1013         GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "size: %d\n", size);
1014
1015         memcpy (&cls_->dns, rdns,
1016                 cls_->hdr.size - sizeof (struct GNUNET_MessageHeader));
1017         GNUNET_SCHEDULER_add_now (send_mesh_query, cls_);
1018         GNUNET_free (rdns);
1019       }
1020
1021     goto outfree;
1022   }
1023
1024
1025   /* The query should be sent to the network */
1026   if (pkt->addrlen == 4)
1027     {
1028       struct sockaddr_in dest;
1029
1030       memset (&dest, 0, sizeof dest);
1031       dest.sin_port = htons (53);
1032       memcpy(&dest.sin_addr.s_addr, pkt->orig_to, pkt->addrlen);
1033
1034       GNUNET_NETWORK_socket_sendto (dnsout, dns,
1035                                     ntohs (pkt->hdr.size) -
1036                                     sizeof (struct query_packet) + 1,
1037                                     (struct sockaddr *) &dest, sizeof dest);
1038     }
1039   else if (pkt->addrlen == 16)
1040     {
1041       struct sockaddr_in6 dest;
1042
1043       memset (&dest, 0, sizeof dest);
1044       dest.sin6_port = htons (53);
1045       memcpy(&dest.sin6_addr, pkt->orig_to, pkt->addrlen);
1046
1047       GNUNET_NETWORK_socket_sendto (dnsout6, dns,
1048                                     ntohs (pkt->hdr.size) -
1049                                     sizeof (struct query_packet) + 1,
1050                                     (struct sockaddr *) &dest, sizeof dest);
1051     }
1052
1053 outfree:
1054   free_parsed_dns_packet (pdns);
1055   pdns = NULL;
1056 out:
1057   GNUNET_SERVER_receive_done (client, GNUNET_OK);
1058 }
1059
1060 static void
1061 read_response (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc);
1062
1063 static void
1064 read_response6 (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc);
1065
1066 static int
1067 open_port6 ()
1068 {
1069   struct sockaddr_in6 addr;
1070
1071   dnsout6 = GNUNET_NETWORK_socket_create (AF_INET6, SOCK_DGRAM, 0);
1072   if (dnsout6 == NULL)
1073     {
1074       GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Could not create socket: %m\n");
1075       return GNUNET_SYSERR;
1076     }
1077   memset (&addr, 0, sizeof (struct sockaddr_in6));
1078
1079   addr.sin6_family = AF_INET6;
1080   int err = GNUNET_NETWORK_socket_bind (dnsout6,
1081                                         (struct sockaddr *) &addr,
1082                                         sizeof (struct sockaddr_in6));
1083
1084   if (err != GNUNET_OK)
1085   {
1086     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Could not bind a port: %m\n");
1087     return GNUNET_SYSERR;
1088   }
1089
1090   GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL, dnsout6,
1091                                  &read_response6, NULL);
1092
1093   return GNUNET_YES;
1094 }
1095
1096 static int
1097 open_port ()
1098 {
1099   struct sockaddr_in addr;
1100
1101   dnsout = GNUNET_NETWORK_socket_create (AF_INET, SOCK_DGRAM, 0);
1102   if (dnsout == NULL)
1103     return GNUNET_SYSERR;
1104   memset (&addr, 0, sizeof (struct sockaddr_in));
1105
1106   addr.sin_family = AF_INET;
1107   int err = GNUNET_NETWORK_socket_bind (dnsout,
1108                                         (struct sockaddr *) &addr,
1109                                         sizeof (struct sockaddr_in));
1110
1111   if (err != GNUNET_OK)
1112   {
1113     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Could not bind a port: %m\n");
1114     return GNUNET_SYSERR;
1115   }
1116
1117   /* Read the port we bound to */
1118   socklen_t addrlen = sizeof (struct sockaddr_in);
1119
1120   err =
1121       getsockname (GNUNET_NETWORK_get_fd (dnsout), (struct sockaddr *) &addr,
1122                    &addrlen);
1123
1124   dnsoutport = htons (addr.sin_port);
1125
1126   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Bound to port %d.\n", dnsoutport);
1127
1128   GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL, dnsout,
1129                                  &read_response, NULL);
1130
1131   return GNUNET_YES;
1132 }
1133
1134 void handle_response(struct dns_pkt* dns, struct sockaddr *addr, socklen_t addrlen, int r);
1135
1136 /**
1137  * Read a response-packet of the UDP-Socket
1138  */
1139 static void
1140 read_response6 (void *cls
1141                 __attribute__ ((unused)),
1142                 const struct GNUNET_SCHEDULER_TaskContext *tc)
1143 {
1144   struct sockaddr_in6 addr;
1145   socklen_t addrlen = sizeof (addr);
1146   int r;
1147   int len;
1148
1149   if (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)
1150     return;
1151
1152   memset (&addr, 0, sizeof addr);
1153
1154 #ifndef MINGW
1155   if (0 != ioctl (GNUNET_NETWORK_get_fd (dnsout6), FIONREAD, &len))
1156   {
1157     (void)open_port6 ();
1158     return;
1159   }
1160 #else
1161   /* port the code above? */
1162   len = 65536;
1163 #endif
1164
1165   unsigned char buf[len];
1166   struct dns_pkt *dns = (struct dns_pkt *) buf;
1167
1168   r = GNUNET_NETWORK_socket_recvfrom (dnsout, buf, sizeof (buf),
1169                                       (struct sockaddr *) &addr, &addrlen);
1170
1171   if (r < 0)
1172     {
1173       (void)open_port6 ();
1174       return;
1175     }
1176
1177   struct sockaddr *addr_ = GNUNET_malloc(sizeof addr);
1178   memcpy (addr_, &addr, sizeof addr);
1179   handle_response(dns, addr_, 4, r);
1180
1181   GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL, dnsout6,
1182                                  &read_response6, NULL);
1183 }
1184
1185 /**
1186  * Read a response-packet of the UDP-Socket
1187  */
1188 static void
1189 read_response (void *cls
1190                __attribute__ ((unused)),
1191                const struct GNUNET_SCHEDULER_TaskContext *tc)
1192 {
1193   struct sockaddr_in addr;
1194   socklen_t addrlen = sizeof (addr);
1195   int r;
1196   int len;
1197
1198   if (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)
1199     return;
1200
1201   memset (&addr, 0, sizeof addr);
1202
1203 #ifndef MINGW
1204   if (0 != ioctl (GNUNET_NETWORK_get_fd (dnsout), FIONREAD, &len))
1205   {
1206     GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
1207                         "ioctl");
1208     unhijack (dnsoutport);
1209     if (GNUNET_YES == open_port ())
1210       GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS, &hijack, NULL);
1211     return;
1212   }
1213 #else
1214   /* port the code above? */
1215   len = 65536;
1216 #endif
1217
1218   unsigned char buf[len];
1219   struct dns_pkt *dns = (struct dns_pkt *) buf;
1220
1221   r = GNUNET_NETWORK_socket_recvfrom (dnsout, buf, sizeof (buf),
1222                                       (struct sockaddr *) &addr, &addrlen);
1223
1224   if (r < 0)
1225     {
1226       GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
1227                           "recvfrom");
1228       unhijack (dnsoutport);
1229       if (GNUNET_YES == open_port ())
1230         GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS, &hijack, NULL);
1231       return;
1232     }
1233
1234   struct sockaddr *addr_ = GNUNET_malloc(sizeof addr);
1235   memcpy (addr_, &addr, sizeof addr);
1236   handle_response(dns, addr_, 4, r);
1237
1238   GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL, dnsout,
1239                                  &read_response, NULL);
1240 }
1241
1242 void
1243 handle_response(struct dns_pkt* dns, struct sockaddr *addr, socklen_t addrlen, int r)
1244 {
1245   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Answer to query %d\n",
1246               ntohs (dns->s.id));
1247
1248
1249   if (query_states[dns->s.id].valid == GNUNET_YES)
1250     {
1251       if (query_states[dns->s.id].tunnel != NULL)
1252         {
1253           GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1254                       "Answer to query %d for a remote peer!\n",
1255                       ntohs (dns->s.id));
1256           /* This response should go through a tunnel */
1257           uint32_t *c =
1258             GNUNET_malloc (4 + sizeof (struct GNUNET_MESH_Tunnel *) + r);
1259           *c = r;
1260           struct GNUNET_MESH_Tunnel **t = (struct GNUNET_MESH_Tunnel **) (c + 1);
1261
1262           *t = query_states[dns->s.id].tunnel;
1263           memcpy (t + 1, dns, r);
1264           if (NULL ==
1265               GNUNET_MESH_tunnel_get_data (query_states[dns->s.id].tunnel))
1266             {
1267               struct GNUNET_MESH_TransmitHandle *th =
1268                 GNUNET_MESH_notify_transmit_ready (query_states[dns->s.id].tunnel,
1269                                                    GNUNET_YES,
1270                                                    32,
1271                                                    GNUNET_TIME_UNIT_MINUTES,
1272                                                    NULL,
1273                                                    r +
1274                                                    sizeof (struct
1275                                                            GNUNET_MessageHeader),
1276                                                    mesh_send_response, c);
1277
1278               GNUNET_MESH_tunnel_set_data (query_states[dns->s.id].tunnel, th);
1279             }
1280           else
1281             {
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);
1286
1287               struct tunnel_notify_queue *element =
1288                 GNUNET_malloc (sizeof (struct tunnel_notify_queue));
1289               element->cls = c;
1290               element->len = r + sizeof (struct GNUNET_MessageHeader);
1291               element->cb = mesh_send_response;
1292
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);
1296             }
1297         }
1298       else
1299         {
1300           query_states[dns->s.id].valid = GNUNET_NO;
1301
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;
1310           if (addrlen == 16)
1311             {
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);
1315             }
1316           else if (addrlen == 4)
1317             {
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);
1321             }
1322           else
1323             {
1324               GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "addrlen = %d\n", addrlen);
1325               GNUNET_assert(0);
1326             }
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);
1330
1331           GNUNET_CONTAINER_DLL_insert_after (head, tail, tail, answer);
1332
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,
1336                                                                  &send_answer,
1337                                                                  query_states[dns->s.id].client);
1338         }
1339     }
1340   GNUNET_free(addr);
1341 }
1342
1343
1344 /**
1345  * Task run during shutdown.
1346  *
1347  * @param cls unused
1348  * @param tc unused
1349  */
1350 static void
1351 cleanup_task (void *cls
1352               __attribute__ ((unused)),
1353               const struct GNUNET_SCHEDULER_TaskContext *tc)
1354 {
1355   GNUNET_assert (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN));
1356
1357   unhijack (dnsoutport);
1358   GNUNET_DHT_disconnect (dht);
1359   GNUNET_MESH_disconnect (mesh_handle);
1360 }
1361
1362 /**
1363  * @brief Create a port-map from udp and tcp redirects
1364  *
1365  * @param udp_redirects
1366  * @param tcp_redirects
1367  *
1368  * @return
1369  */
1370 static uint64_t
1371 get_port_from_redirects (const char *udp_redirects, const char *tcp_redirects)
1372 {
1373   uint64_t ret = 0;
1374   char *cpy, *hostname, *redirect;
1375   int local_port;
1376   unsigned int count = 0;
1377
1378   cpy = NULL;
1379   if (NULL != udp_redirects)
1380   {
1381     cpy = GNUNET_strdup (udp_redirects);
1382     for (redirect = strtok (cpy, " "); redirect != NULL;
1383          redirect = strtok (NULL, " "))
1384     {
1385       if (NULL == (hostname = strstr (redirect, ":")))
1386       {
1387         GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1388                     "Warning: option %s is not formatted correctly!\n",
1389                     redirect);
1390         continue;
1391       }
1392       hostname[0] = '\0';
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);
1397
1398       ret |= (0xFFFF & htons (local_port));
1399       ret <<= 16;
1400       count++;
1401
1402       if (count > 4)
1403       {
1404         ret = 0;
1405         goto out;
1406       }
1407     }
1408     GNUNET_free (cpy);
1409     cpy = NULL;
1410   }
1411
1412   if (NULL != tcp_redirects)
1413   {
1414     cpy = GNUNET_strdup (tcp_redirects);
1415     for (redirect = strtok (cpy, " "); redirect != NULL;
1416          redirect = strtok (NULL, " "))
1417     {
1418       if (NULL == (hostname = strstr (redirect, ":")))
1419       {
1420         GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1421                     "Warning: option %s is not formatted correctly!\n",
1422                     redirect);
1423         continue;
1424       }
1425       hostname[0] = '\0';
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);
1430
1431       ret |= (0xFFFF & htons (local_port));
1432       ret <<= 16;
1433       count++;
1434
1435       if (count > 4)
1436       {
1437         ret = 0;
1438         goto out;
1439       }
1440     }
1441     GNUNET_free (cpy);
1442     cpy = NULL;
1443   }
1444
1445 out:
1446   GNUNET_free_non_null (cpy);
1447   return ret;
1448 }
1449
1450 static void
1451 publish_name (const char *name, uint64_t ports, uint32_t service_type,
1452               struct GNUNET_CRYPTO_RsaPrivateKey *my_private_key)
1453 {
1454   size_t size = sizeof (struct GNUNET_DNS_Record);
1455   struct GNUNET_DNS_Record data;
1456
1457   memset (&data, 0, size);
1458
1459   data.purpose.size = htonl (size - sizeof (struct GNUNET_CRYPTO_RsaSignature));
1460   data.purpose.purpose = GNUNET_SIGNATURE_PURPOSE_DNS_RECORD;
1461
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));
1465
1466   data.service_type = service_type;
1467   data.ports = ports;
1468
1469   GNUNET_CRYPTO_rsa_key_get_public (my_private_key, &data.peer);
1470
1471   data.expiration_time =
1472     GNUNET_TIME_absolute_hton (GNUNET_TIME_relative_to_absolute (GNUNET_TIME_relative_multiply
1473                                                                  (GNUNET_TIME_UNIT_HOURS, 2)));
1474
1475   /* Sign the block */
1476   if (GNUNET_OK !=
1477       GNUNET_CRYPTO_rsa_sign (my_private_key, &data.purpose, &data.signature))
1478   {
1479     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "could not sign DNS_Record\n");
1480     return;
1481   }
1482
1483   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Putting with key %08x, size = %d\n",
1484               *((unsigned int *) &data.service_descriptor), size);
1485
1486   GNUNET_DHT_put (dht, &data.service_descriptor, 5 /* DEFAULT_PUT_REPLICATION */,
1487                   GNUNET_DHT_RO_NONE, GNUNET_BLOCK_TYPE_DNS, size,
1488                   (char *) &data,
1489                   GNUNET_TIME_relative_to_absolute (GNUNET_TIME_UNIT_HOURS),
1490                   GNUNET_TIME_UNIT_MINUTES, NULL, NULL);
1491 }
1492
1493
1494 /**
1495  * @brief Publishes the record defined by the section section
1496  *
1497  * @param cls closure
1498  * @param section the current section
1499  */
1500 static void
1501 publish_iterate (void *cls __attribute__ ((unused)), const char *section)
1502 {
1503   char *udp_redirects;
1504   char *tcp_redirects;
1505   char *alternative_names;
1506   char *alternative_name;
1507   char *keyfile;
1508
1509   if ((strlen (section) < 8) ||
1510       (0 != strcmp (".gnunet.", section + (strlen (section) - 8))))
1511     return;
1512   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Parsing dns-name %s\n", section);
1513   if (GNUNET_OK !=
1514       GNUNET_CONFIGURATION_get_value_string (cfg, section, "UDP_REDIRECTS",
1515                                              &udp_redirects))
1516     udp_redirects = NULL;
1517   if (GNUNET_OK !=
1518       GNUNET_CONFIGURATION_get_value_string (cfg, section, "TCP_REDIRECTS",
1519                                              &tcp_redirects))
1520     tcp_redirects = NULL;
1521
1522   if (GNUNET_OK !=
1523       GNUNET_CONFIGURATION_get_value_filename (cfg, "GNUNETD", "HOSTKEY",
1524                                                &keyfile))
1525   {
1526     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "could not read keyfile-value\n");
1527     if (keyfile != NULL)
1528       GNUNET_free (keyfile);
1529     return;
1530   }
1531
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);
1536
1537   uint64_t ports = get_port_from_redirects (udp_redirects, tcp_redirects);
1538   uint32_t service_type = 0;
1539
1540   if (NULL != udp_redirects)
1541     service_type = GNUNET_DNS_SERVICE_TYPE_UDP;
1542
1543   if (NULL != tcp_redirects)
1544     service_type |= GNUNET_DNS_SERVICE_TYPE_TCP;
1545
1546   service_type = htonl (service_type);
1547
1548
1549   publish_name (section, ports, service_type, my_private_key);
1550   if (GNUNET_OK ==
1551       GNUNET_CONFIGURATION_get_value_string (cfg, section, "ALTERNATIVE_NAMES",
1552                                              &alternative_names))
1553   {
1554     for (alternative_name = strtok (alternative_names, " ");
1555          alternative_name != NULL; alternative_name = strtok (NULL, " "))
1556     {
1557       char *altname =
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)] = '.';
1562
1563       publish_name (altname, ports, service_type, my_private_key);
1564     }
1565     GNUNET_free (alternative_names);
1566   }
1567   GNUNET_CRYPTO_rsa_key_free (my_private_key);
1568   GNUNET_free_non_null (udp_redirects);
1569   GNUNET_free_non_null (tcp_redirects);
1570 }
1571
1572 /**
1573  * Publish a DNS-record in the DHT.
1574  */
1575 static void
1576 publish_names (void *cls
1577                __attribute__ ((unused)),
1578                const struct GNUNET_SCHEDULER_TaskContext *tc)
1579 {
1580   if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
1581     return;
1582
1583   GNUNET_CONFIGURATION_iterate_sections (cfg, &publish_iterate, NULL);
1584
1585   GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_HOURS, &publish_names, NULL);
1586 }
1587
1588 /**
1589  * @param cls closure
1590  * @param server the initialized server
1591  * @param cfg_ configuration to use
1592  */
1593 static void
1594 run (void *cls, struct GNUNET_SERVER_Handle *server,
1595      const struct GNUNET_CONFIGURATION_Handle *cfg_)
1596 {
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)},
1602     {NULL, NULL, 0, 0}
1603   };
1604
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},
1608     {NULL, 0, 0}
1609   };
1610
1611   static GNUNET_MESH_ApplicationType apptypes[] = {
1612     GNUNET_APPLICATION_TYPE_END,
1613     GNUNET_APPLICATION_TYPE_END
1614   };
1615
1616   if (GNUNET_YES != open_port6 ())
1617   {
1618     GNUNET_SCHEDULER_shutdown ();
1619     return;
1620   }
1621
1622   if (GNUNET_YES != open_port ())
1623   {
1624     GNUNET_SCHEDULER_shutdown ();
1625     return;
1626   }
1627
1628   if (GNUNET_YES ==
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);
1632
1633   cfg = cfg_;
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,
1638                                 cls);
1639 }
1640
1641 /**
1642  * The main function for the dns service.
1643  *
1644  * @param argc number of arguments from the command line
1645  * @param argv command line arguments
1646  * @return 0 ok, 1 on error
1647  */
1648 int
1649 main (int argc, char *const *argv)
1650 {
1651   return (GNUNET_OK ==
1652           GNUNET_SERVICE_run (argc, argv, "dns", GNUNET_SERVICE_OPTION_NONE,
1653                               &run, NULL)) ? 0 : 1;
1654 }