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