b35ea6c27376ab60250f685f4aa15b9bca5ca548
[oweals/gnunet.git] / src / dns / gnunet-service-dns.c
1 /*
2      This file is part of GNUnet.
3      (C) 2012 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  * @brief service to intercept and modify DNS queries (and replies) of this system
24  * @author Christian Grothoff
25  *
26  * For "secure" interaction with the legacy DNS system, we permit
27  * replies only to arrive within a 5s window (and they must match
28  * ports, IPs and request IDs).  Furthermore, we let the OS pick a
29  * source port, opening up to 128 sockets per address family (IPv4 or
30  * IPv6).  Those sockets are closed if they are not in use for 5s
31  * (which means they will be freshly randomized afterwards).  For new
32  * requests, we pick a random slot in the array with 128 socket slots
33  * (and re-use an existing socket if the slot is still in use).  Thus
34  * each request will be given one of 128 random source ports, and the
35  * 128 random source ports will also change "often" (less often if the
36  * system is very busy, each time if we are mostly idle).  At the same
37  * time, the system will never use more than 256 UDP sockets.  
38  */
39 #include "platform.h"
40 #include "gnunet_util_lib.h"
41 #include "gnunet_applications.h"
42 #include "gnunet_constants.h"
43 #include "gnunet_protocols.h"
44 #include "gnunet_signatures.h"
45 #include "dns.h"
46 #include "gnunet_dns_service.h"
47 #include "gnunet_mesh_service.h"
48 #include "gnunet_statistics_service.h"
49 #include "gnunet_tun_lib.h"
50
51
52 /**
53  * Timeout for an external (Internet-DNS) DNS resolution
54  */
55 #define REQUEST_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5)
56
57 /**
58  * How many DNS sockets do we open at most at the same time?
59  * (technical socket maximum is this number x2 for IPv4+IPv6)
60  */
61 #define DNS_SOCKET_MAX 128
62
63 /**
64  * Phases each request goes through.
65  */
66 enum RequestPhase
67 {
68   /**
69    * Request has just been received.
70    */
71   RP_INIT,
72
73   /**
74    * Showing the request to all monitor clients.  If
75    * client list is empty, will enter QUERY phase.
76    */
77   RP_REQUEST_MONITOR,
78
79   /**
80    * Showing the request to PRE-RESOLUTION clients to find an answer.
81    * If client list is empty, will trigger global DNS request.
82    */
83   RP_QUERY,
84
85   /**
86    * Global Internet query is now pending.
87    */
88   RP_INTERNET_DNS,
89   
90   /**
91    * Client (or global DNS request) has resulted in a response.
92    * Forward to all POST-RESOLUTION clients.  If client list is empty,
93    * will enter RESPONSE_MONITOR phase.
94    */
95   RP_MODIFY,
96
97   /**
98    * Showing the request to all monitor clients.  If
99    * client list is empty, give the result to the hijacker (and be done).
100    */
101   RP_RESPONSE_MONITOR,
102
103   /**
104    * Some client has told us to drop the request.
105    */
106   RP_DROP
107 };
108
109
110 /**
111  * Entry we keep for each client.
112  */ 
113 struct ClientRecord
114 {
115   /**
116    * Kept in doubly-linked list.
117    */ 
118   struct ClientRecord *next;
119
120   /**
121    * Kept in doubly-linked list.
122    */ 
123   struct ClientRecord *prev;
124
125   /**
126    * Handle to the client.
127    */ 
128   struct GNUNET_SERVER_Client *client;
129
130   /**
131    * Flags for the client.
132    */
133   enum GNUNET_DNS_Flags flags;
134
135 };
136
137
138 /**
139  * UDP socket we are using for sending DNS requests to the Internet.
140  */
141 struct RequestSocket
142 {
143   
144   /**
145    * UDP socket we use for this request for IPv4
146    */
147   struct GNUNET_NETWORK_Handle *dnsout4;
148
149   /**
150    * UDP socket we use for this request for IPv6
151    */
152   struct GNUNET_NETWORK_Handle *dnsout6;
153
154   /**
155    * Task for reading from dnsout4 and dnsout6.
156    */
157   GNUNET_SCHEDULER_TaskIdentifier read_task;
158
159   /**
160    * When should this socket be closed?
161    */
162   struct GNUNET_TIME_Absolute timeout;
163 };
164
165
166 /**
167  * Entry we keep for each active request.
168  */ 
169 struct RequestRecord
170 {
171
172   /**
173    * List of clients that still need to see this request (each entry
174    * is set to NULL when the client is done).
175    */
176   struct ClientRecord **client_wait_list;
177
178   /**
179    * Payload of the UDP packet (the UDP payload), can be either query
180    * or already the response.
181    */
182   char *payload;
183
184   /**
185    * Socket we are using to transmit this request (must match if we receive
186    * a response).  Must NOT be freed as part of this request record (as it
187    * might be shared with other requests).
188    */
189   struct GNUNET_NETWORK_Handle *dnsout;
190
191   /**
192    * Source address of the original request (for sending response).
193    */
194   struct sockaddr_storage src_addr;
195
196   /**
197    * Destination address of the original request (for potential use as exit).
198    */
199   struct sockaddr_storage dst_addr;
200
201   /**
202    * When should this request time out?
203    */
204   struct GNUNET_TIME_Absolute timeout;
205
206   /**
207    * ID of this request, also basis for hashing.  Lowest 16 bit will
208    * be our message ID when doing a global DNS request and our index
209    * into the 'requests' array.
210    */
211   uint64_t request_id;
212
213   /**
214    * Number of bytes in payload.
215    */ 
216   size_t payload_length;
217
218   /**
219    * Length of the client wait list.
220    */
221   unsigned int client_wait_list_length;
222
223   /**
224    * In which phase this this request?
225    */
226   enum RequestPhase phase;
227
228 };
229
230
231 /**
232  * State we keep for each DNS tunnel that terminates at this node.
233  */
234 struct TunnelState
235 {
236
237   /**
238    * Associated MESH tunnel.
239    */
240   struct GNUNET_MESH_Tunnel *tunnel;
241
242   /**
243    * Active request for sending a reply.
244    */
245   struct GNUNET_MESH_TransmitHandle *th;
246
247   /**
248    * DNS reply ready for transmission.
249    */
250   char *reply;
251
252   /**
253    * Socket we are using to transmit this request (must match if we receive
254    * a response).  Must NOT be freed as part of this request record (as it
255    * might be shared with other requests).
256    */
257   struct GNUNET_NETWORK_Handle *dnsout;
258
259   /**
260    * Address we sent the DNS request to.
261    */
262   struct sockaddr_storage addr;
263
264   /**
265    * When should this request time out?
266    */
267   struct GNUNET_TIME_Absolute timeout;
268
269   /**
270    * Number of bytes in 'addr'.
271    */
272   socklen_t addrlen;
273
274   /**
275    * Number of bytes in 'reply'.
276    */
277   size_t reply_length;
278
279   /**
280    * Original DNS request ID as used by the client.
281    */
282   uint16_t original_id;
283
284   /**
285    * DNS request ID that we used for forwarding.
286    */
287   uint16_t my_id;
288 };
289
290
291 /**
292  * The configuration to use
293  */
294 static const struct GNUNET_CONFIGURATION_Handle *cfg;
295
296 /**
297  * Statistics.
298  */
299 static struct GNUNET_STATISTICS_Handle *stats;
300
301 /**
302  * Handle to DNS hijacker helper process ("gnunet-helper-dns").
303  */
304 static struct GNUNET_HELPER_Handle *hijacker;
305
306 /**
307  * Command-line arguments we are giving to the hijacker process.
308  */
309 static char *helper_argv[7];
310
311 /**
312  * Head of DLL of clients we consult.
313  */
314 static struct ClientRecord *clients_head;
315
316 /**
317  * Tail of DLL of clients we consult.
318  */
319 static struct ClientRecord *clients_tail;
320
321 /**
322  * Our notification context.
323  */
324 static struct GNUNET_SERVER_NotificationContext *nc;
325
326 /**
327  * Array of all open requests.
328  */
329 static struct RequestRecord requests[UINT16_MAX + 1];
330
331 /**
332  * Array of all open requests from tunnels.
333  */
334 static struct TunnelState *tunnels[UINT16_MAX + 1];
335
336 /**
337  * Array of all open sockets for DNS requests. 
338  */
339 static struct RequestSocket sockets[DNS_SOCKET_MAX];
340
341 /**
342  * Generator for unique request IDs.
343  */
344 static uint64_t request_id_gen;
345
346 /**
347  * IP address to use for the DNS server if we are a DNS exit service
348  * (for VPN via mesh); otherwise NULL.
349  */
350 static char *dns_exit;
351
352 /**
353  * Handle to the MESH service (for receiving DNS queries), or NULL 
354  * if we are not a DNS exit.
355  */
356 static struct GNUNET_MESH_Handle *mesh;
357
358
359 /**
360  * We're done with a RequestSocket, close it for now.
361  *
362  * @param rs request socket to clean up
363  */
364 static void
365 cleanup_rs (struct RequestSocket *rs)
366 {
367   if (NULL != rs->dnsout4)
368   {
369     GNUNET_NETWORK_socket_close (rs->dnsout4);
370     rs->dnsout4 = NULL;
371   }
372   if (NULL != rs->dnsout6)
373   {
374     GNUNET_NETWORK_socket_close (rs->dnsout6);
375     rs->dnsout6 = NULL;
376   }
377   if (GNUNET_SCHEDULER_NO_TASK != rs->read_task)
378   {
379     GNUNET_SCHEDULER_cancel (rs->read_task);
380     rs->read_task = GNUNET_SCHEDULER_NO_TASK;
381   }
382 }
383
384
385 /**
386  * We're done processing a DNS request, free associated memory.
387  *
388  * @param rr request to clean up
389  */
390 static void
391 cleanup_rr (struct RequestRecord *rr)
392 {
393   GNUNET_free_non_null (rr->payload);
394   rr->payload = NULL;
395   rr->payload_length = 0;
396   GNUNET_array_grow (rr->client_wait_list,
397                      rr->client_wait_list_length,
398                      0);
399 }
400
401
402 /**
403  * Task run during shutdown.
404  *
405  * @param cls unused
406  * @param tc unused
407  */
408 static void
409 cleanup_task (void *cls GNUNET_UNUSED,
410               const struct GNUNET_SCHEDULER_TaskContext *tc)
411 {
412   unsigned int i;
413
414   GNUNET_HELPER_stop (hijacker);
415   hijacker = NULL;
416   for (i=0;i<7;i++)
417     GNUNET_free_non_null (helper_argv[i]);
418   for (i=0;i<=UINT16_MAX;i++)
419     cleanup_rr (&requests[i]);
420   GNUNET_SERVER_notification_context_destroy (nc);
421   nc = NULL;
422   if (stats != NULL)
423   {
424     GNUNET_STATISTICS_destroy (stats, GNUNET_NO);
425     stats = NULL;
426   }
427   if (NULL != dns_exit)
428   {
429     GNUNET_free (dns_exit);
430     dns_exit = NULL;
431   }
432   if (NULL != mesh)
433   {
434     GNUNET_MESH_disconnect(mesh);
435     mesh = NULL;
436   }
437 }
438
439
440 /**
441  * Open source port for sending DNS requests
442  *
443  * @param af AF_INET or AF_INET6
444  * @return GNUNET_OK on success
445  */ 
446 static struct GNUNET_NETWORK_Handle *
447 open_socket (int af)
448 {
449   struct sockaddr_in a4;
450   struct sockaddr_in6 a6;
451   struct sockaddr *sa;
452   socklen_t alen;
453   struct GNUNET_NETWORK_Handle *ret;
454
455   ret = GNUNET_NETWORK_socket_create (af, SOCK_DGRAM, 0);
456   if (NULL == ret)
457     return NULL;
458   switch (af)
459   {
460   case AF_INET:
461     memset (&a4, 0, alen = sizeof (struct sockaddr_in));
462     sa = (struct sockaddr *) &a4;
463     break;
464   case AF_INET6:
465     memset (&a6, 0, alen = sizeof (struct sockaddr_in6));
466     sa = (struct sockaddr *) &a6;
467     break;
468   default:
469     GNUNET_break (0);
470     GNUNET_NETWORK_socket_close (ret);
471     return NULL;
472   }
473   sa->sa_family = af;
474   if (GNUNET_OK != GNUNET_NETWORK_socket_bind (ret,
475                                                sa, 
476                                                alen))
477   {
478     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 
479                 _("Could not bind to any port: %s\n"),
480                 STRERROR (errno));
481     GNUNET_NETWORK_socket_close (ret);
482     return NULL;
483   }
484   return ret;
485 }
486
487
488 /**
489  * We're done with some request, finish processing.
490  *
491  * @param rr request send to the network or just clean up.
492  */
493 static void
494 request_done (struct RequestRecord *rr)
495 {
496   struct GNUNET_MessageHeader *hdr;
497   size_t reply_len;
498   uint16_t source_port;
499   uint16_t destination_port;
500
501   GNUNET_array_grow (rr->client_wait_list,
502                      rr->client_wait_list_length,
503                      0); 
504   if (RP_RESPONSE_MONITOR != rr->phase)
505   {
506     /* no response, drop */
507     cleanup_rr (rr);
508     return;
509   }
510   
511   /* send response via hijacker */
512   reply_len = sizeof (struct GNUNET_MessageHeader);
513   reply_len += sizeof (struct GNUNET_TUN_Layer2PacketHeader);
514   switch (rr->src_addr.ss_family)
515   {
516   case AF_INET:
517     reply_len += sizeof (struct GNUNET_TUN_IPv4Header);
518     break;
519   case AF_INET6:
520     reply_len += sizeof (struct GNUNET_TUN_IPv6Header);
521     break;
522   default:
523     GNUNET_break (0);
524     cleanup_rr (rr);
525     return;   
526   }
527   reply_len += sizeof (struct GNUNET_TUN_UdpHeader);
528   reply_len += rr->payload_length;
529   if (reply_len >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
530   {
531     /* response too big, drop */
532     GNUNET_break (0); /* how can this be? */
533     cleanup_rr(rr);
534     return;    
535   }
536   {
537     char buf[reply_len];
538     size_t off;
539     struct GNUNET_TUN_IPv4Header ip4;
540     struct GNUNET_TUN_IPv6Header ip6;
541
542     /* first, GNUnet message header */
543     hdr = (struct GNUNET_MessageHeader*) buf;
544     hdr->type = htons (GNUNET_MESSAGE_TYPE_DNS_HELPER);
545     hdr->size = htons ((uint16_t) reply_len);
546     off = sizeof (struct GNUNET_MessageHeader);
547
548     /* first, TUN header */
549     {
550       struct GNUNET_TUN_Layer2PacketHeader tun;
551
552       tun.flags = htons (0);
553       if (rr->src_addr.ss_family == AF_INET)
554         tun.proto = htons (ETH_P_IPV4); 
555       else
556         tun.proto = htons (ETH_P_IPV6);
557       memcpy (&buf[off], &tun, sizeof (struct GNUNET_TUN_Layer2PacketHeader));
558       off += sizeof (struct GNUNET_TUN_Layer2PacketHeader);
559     }
560
561     /* now IP header */
562     switch (rr->src_addr.ss_family)
563     {
564     case AF_INET:
565       {
566         struct sockaddr_in *src = (struct sockaddr_in *) &rr->src_addr;
567         struct sockaddr_in *dst = (struct sockaddr_in *) &rr->dst_addr;
568         
569         source_port = dst->sin_port;
570         destination_port = src->sin_port;
571         GNUNET_TUN_initialize_ipv4_header (&ip4,
572                                            IPPROTO_UDP,
573                                            reply_len - off - sizeof (struct GNUNET_TUN_IPv4Header),
574                                            &dst->sin_addr,
575                                            &src->sin_addr);
576         memcpy (&buf[off], &ip4, sizeof (ip4));
577         off += sizeof (ip4);
578       }
579       break;
580     case AF_INET6:
581       {
582         struct sockaddr_in6 *src = (struct sockaddr_in6 *) &rr->src_addr;
583         struct sockaddr_in6 *dst = (struct sockaddr_in6 *) &rr->dst_addr;
584
585         source_port = dst->sin6_port;
586         destination_port = src->sin6_port;
587         GNUNET_TUN_initialize_ipv6_header (&ip6,
588                                            IPPROTO_UDP,
589                                            reply_len - sizeof (struct GNUNET_TUN_IPv6Header),
590                                            &dst->sin6_addr,
591                                            &src->sin6_addr);
592         memcpy (&buf[off], &ip6, sizeof (ip6));
593         off += sizeof (ip6);
594       }
595       break;
596     default:
597       GNUNET_assert (0);
598     }
599
600     /* now UDP header */
601     {
602       struct GNUNET_TUN_UdpHeader udp;
603
604       udp.source_port = source_port;
605       udp.destination_port = destination_port;
606       udp.len = htons (reply_len - off);
607       if (AF_INET == rr->src_addr.ss_family)
608         GNUNET_TUN_calculate_udp4_checksum (&ip4,
609                                             &udp,
610                                             rr->payload,
611                                             rr->payload_length);
612       else
613         GNUNET_TUN_calculate_udp6_checksum (&ip6,
614                                             &udp,
615                                             rr->payload,
616                                             rr->payload_length);
617       memcpy (&buf[off], &udp, sizeof (udp));
618       off += sizeof (udp);
619     }
620
621     /* now DNS payload */
622     {
623       memcpy (&buf[off], rr->payload, rr->payload_length);
624       off += rr->payload_length;
625     }
626     /* final checks & sending */
627     GNUNET_assert (off == reply_len);
628     GNUNET_HELPER_send (hijacker,
629                         hdr,
630                         GNUNET_YES,
631                         NULL, NULL);
632     GNUNET_STATISTICS_update (stats,
633                               gettext_noop ("# DNS requests answered via TUN interface"),
634                               1, GNUNET_NO);
635   }
636   /* clean up, we're done */
637   cleanup_rr (rr);
638 }
639
640
641 /**
642  * Show the payload of the given request record to the client
643  * (and wait for a response).
644  *
645  * @param rr request to send to client
646  * @param client client to send the response to
647  */
648 static void
649 send_request_to_client (struct RequestRecord *rr,
650                         struct GNUNET_SERVER_Client *client)
651 {
652   char buf[sizeof (struct GNUNET_DNS_Request) + rr->payload_length];
653   struct GNUNET_DNS_Request *req;
654
655   if (sizeof (buf) >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
656   {
657     GNUNET_break (0);
658     cleanup_rr (rr);
659     return;
660   }
661   req = (struct GNUNET_DNS_Request*) buf;
662   req->header.type = htons (GNUNET_MESSAGE_TYPE_DNS_CLIENT_REQUEST);
663   req->header.size = htons (sizeof (buf));
664   req->reserved = htonl (0);
665   req->request_id = rr->request_id;
666   memcpy (&req[1], rr->payload, rr->payload_length);
667   GNUNET_SERVER_notification_context_unicast (nc, 
668                                               client,
669                                               &req->header,
670                                               GNUNET_NO);
671 }
672
673
674 /**
675  * Read a DNS response from the (unhindered) UDP-Socket
676  *
677  * @param cls socket to read from
678  * @param tc scheduler context (must be shutdown or read ready)
679  */
680 static void
681 read_response (void *cls,
682                const struct GNUNET_SCHEDULER_TaskContext *tc);
683
684
685 /**
686  * Get a socket of the specified address family to send out a
687  * UDP DNS request to the Internet.  
688  *
689  * @param af desired address family
690  * @return NULL on error (given AF not "supported")
691  */
692 static struct GNUNET_NETWORK_Handle *
693 get_request_socket (int af)
694 {
695   struct RequestSocket *rs;
696   struct GNUNET_NETWORK_FDSet *rset;
697   static struct GNUNET_NETWORK_Handle *ret;
698
699   rs = &sockets[GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_NONCE, 
700                                           DNS_SOCKET_MAX)];
701   rs->timeout = GNUNET_TIME_relative_to_absolute (REQUEST_TIMEOUT);
702   switch (af)
703   {
704   case AF_INET:
705     if (NULL == rs->dnsout4)
706       rs->dnsout4 = open_socket (AF_INET);
707     ret = rs->dnsout4;
708     break;
709   case AF_INET6:
710     if (NULL == rs->dnsout6)
711       rs->dnsout6 = open_socket (AF_INET6);
712     ret = rs->dnsout6;
713     break;
714   default:
715     return NULL;
716   }  
717   if (GNUNET_SCHEDULER_NO_TASK != rs->read_task)
718   {
719     GNUNET_SCHEDULER_cancel (rs->read_task);
720     rs->read_task = GNUNET_SCHEDULER_NO_TASK;
721   }
722   if ( (NULL == rs->dnsout4) &&
723        (NULL == rs->dnsout6) )
724     return NULL;
725   rset = GNUNET_NETWORK_fdset_create ();
726   if (NULL != rs->dnsout4)
727     GNUNET_NETWORK_fdset_set (rset, rs->dnsout4);
728   if (NULL != rs->dnsout6)
729     GNUNET_NETWORK_fdset_set (rset, rs->dnsout6);
730   rs->read_task = GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_DEFAULT,
731                                                GNUNET_SCHEDULER_NO_TASK,
732                                                REQUEST_TIMEOUT,
733                                                rset,
734                                                NULL,
735                                                &read_response, rs);
736   GNUNET_NETWORK_fdset_destroy (rset);
737   return ret;
738 }
739
740
741 /**
742  * A client has completed its processing for this
743  * request.  Move on.
744  *
745  * @param rr request to process further
746  */
747 static void
748 next_phase (struct RequestRecord *rr)
749 {
750   struct ClientRecord *cr;
751   int nz;
752   unsigned int j;
753   socklen_t salen;
754
755   if (rr->phase == RP_DROP)
756   {
757     cleanup_rr (rr);
758     return;
759   }
760   nz = -1;
761   for (j=0;j<rr->client_wait_list_length;j++)
762   {
763     if (NULL != rr->client_wait_list[j])
764     {
765       nz = (int) j;
766       break;
767     }
768   }  
769   if (-1 != nz) 
770   {
771     send_request_to_client (rr, rr->client_wait_list[nz]->client);
772     return;
773   }
774   /* done with current phase, advance! */
775   switch (rr->phase)
776   {
777   case RP_INIT:
778     rr->phase = RP_REQUEST_MONITOR;
779     for (cr = clients_head; NULL != cr; cr = cr->next)
780     {
781       if (0 != (cr->flags & GNUNET_DNS_FLAG_REQUEST_MONITOR))
782         GNUNET_array_append (rr->client_wait_list,
783                              rr->client_wait_list_length,
784                              cr);
785     }
786     next_phase (rr);
787     return;
788   case RP_REQUEST_MONITOR:
789     rr->phase = RP_QUERY;
790     for (cr = clients_head; NULL != cr; cr = cr->next)
791     {
792       if (0 != (cr->flags & GNUNET_DNS_FLAG_PRE_RESOLUTION))
793         GNUNET_array_append (rr->client_wait_list,
794                              rr->client_wait_list_length,
795                              cr);
796     }
797     next_phase (rr);
798     return;
799   case RP_QUERY:
800     switch (rr->dst_addr.ss_family)
801     {
802     case AF_INET:
803       salen = sizeof (struct sockaddr_in);
804       break;
805     case AF_INET6:
806       salen = sizeof (struct sockaddr_in6);
807       break;
808     default:
809       GNUNET_assert (0);
810     }
811
812     rr->phase = RP_INTERNET_DNS;
813     rr->dnsout = get_request_socket (rr->dst_addr.ss_family);
814     if (NULL == rr->dnsout)
815     {
816       GNUNET_STATISTICS_update (stats,
817                                 gettext_noop ("# DNS exit failed (failed to open socket)"),
818                                 1, GNUNET_NO);
819       cleanup_rr (rr);
820       return;
821     }
822     GNUNET_NETWORK_socket_sendto (rr->dnsout,
823                                   rr->payload,
824                                   rr->payload_length,
825                                   (struct sockaddr*) &rr->dst_addr,
826                                   salen);
827     rr->timeout = GNUNET_TIME_relative_to_absolute (REQUEST_TIMEOUT);
828     return;
829   case RP_INTERNET_DNS:
830     rr->phase = RP_MODIFY;
831     for (cr = clients_head; NULL != cr; cr = cr->next)
832     {
833       if (0 != (cr->flags & GNUNET_DNS_FLAG_POST_RESOLUTION))
834         GNUNET_array_append (rr->client_wait_list,
835                              rr->client_wait_list_length,
836                              cr);
837     }
838     next_phase (rr);
839     return;
840   case RP_MODIFY:
841     rr->phase = RP_RESPONSE_MONITOR;
842     for (cr = clients_head; NULL != cr; cr = cr->next)
843     {
844       if (0 != (cr->flags & GNUNET_DNS_FLAG_RESPONSE_MONITOR))
845         GNUNET_array_append (rr->client_wait_list,
846                              rr->client_wait_list_length,
847                              cr);
848     }
849     next_phase (rr);
850     return;
851  case RP_RESPONSE_MONITOR:
852     request_done (rr);
853     break;
854   case RP_DROP:
855     cleanup_rr (rr);
856     break;
857   default:
858     GNUNET_break (0);
859     cleanup_rr (rr);
860     break;
861   }
862 }
863
864
865 /**
866  * A client disconnected, clean up after it.
867  *
868  * @param cls unused
869  * @param client handle of client that disconnected
870  */ 
871 static void
872 client_disconnect (void *cls, struct GNUNET_SERVER_Client *client)
873 {
874   struct ClientRecord *cr;
875   struct RequestRecord *rr;
876   unsigned int i;
877   unsigned int j;
878
879   for (cr = clients_head; NULL != cr; cr = cr->next)
880   {
881     if (cr->client == client)
882     {
883       GNUNET_SERVER_client_drop (client);
884       GNUNET_CONTAINER_DLL_remove (clients_head,
885                                    clients_tail,
886                                    cr);
887       for (i=0;i<UINT16_MAX;i++)
888       {
889         rr = &requests[i];
890         if (0 == rr->client_wait_list_length)
891           continue; /* not in use */
892         for (j=0;j<rr->client_wait_list_length;j++)
893         {
894           if (rr->client_wait_list[j] == cr)
895           {
896             rr->client_wait_list[j] = NULL;
897             next_phase (rr); 
898           }
899         }
900       }
901       GNUNET_free (cr);
902       return;
903     }
904   }
905 }
906
907
908 /**
909  * We got a reply from DNS for a request of a MESH tunnel.  Send it
910  * via the tunnel (after changing the request ID back).
911  *
912  * @param cls the 'struct TunnelState'
913  * @param size number of bytes available in buf
914  * @param buf where to copy the reply
915  * @return number of bytes written to buf
916  */
917 static size_t
918 transmit_reply_to_mesh (void *cls,
919                         size_t size,
920                         void *buf)
921 {
922   struct TunnelState *ts = cls;
923   size_t off;
924   size_t ret;
925   char *cbuf = buf;
926   struct GNUNET_MessageHeader hdr;
927   struct GNUNET_TUN_DnsHeader dns;
928
929   ts->th = NULL;
930   GNUNET_assert (ts->reply != NULL);
931   if (size == 0)
932     return 0;
933   ret = sizeof (struct GNUNET_MessageHeader) + ts->reply_length; 
934   GNUNET_assert (ret <= size);
935   hdr.size = htons (ret);
936   hdr.type = htons (GNUNET_MESSAGE_TYPE_VPN_DNS_FROM_INTERNET);
937   memcpy (&dns, ts->reply, sizeof (dns));
938   dns.id = ts->original_id;
939   off = 0;
940   memcpy (&cbuf[off], &hdr, sizeof (hdr));
941   off += sizeof (hdr);
942   memcpy (&cbuf[off], &dns, sizeof (dns));
943   off += sizeof (dns);
944   memcpy (&cbuf[off], &ts->reply[sizeof (dns)], ts->reply_length - sizeof (dns));
945   off += ts->reply_length - sizeof (dns);
946   GNUNET_free (ts->reply);
947   ts->reply = NULL;
948   ts->reply_length = 0;  
949   GNUNET_assert (ret == off);
950   return ret;
951 }
952
953
954 /**
955  * Actually do the reading of a DNS packet from our UDP socket and see
956  * if we have a valid, matching, pending request.
957  *
958  * @param dnsout socket to read from
959  * @return GNUNET_OK on success, GNUNET_NO on drop, GNUNET_SYSERR on IO-errors (closed socket)
960  */
961 static int
962 do_dns_read (struct GNUNET_NETWORK_Handle *dnsout)
963 {
964   struct sockaddr_storage addr;
965   socklen_t addrlen;
966   struct GNUNET_TUN_DnsHeader *dns;
967   struct RequestRecord *rr;
968   struct TunnelState *ts;
969   ssize_t r;
970   int len;
971
972 #ifndef MINGW
973   if (0 != ioctl (GNUNET_NETWORK_get_fd (dnsout), FIONREAD, &len))
974   {
975     /* conservative choice: */
976     len = UINT16_MAX;
977   }
978 #else
979   /* port the code above? */
980   len = UINT16_MAX;
981 #endif
982
983   {
984     unsigned char buf[len];
985
986     addrlen = sizeof (addr);
987     memset (&addr, 0, sizeof (addr));  
988     r = GNUNET_NETWORK_socket_recvfrom (dnsout, 
989                                         buf, sizeof (buf),
990                                         (struct sockaddr*) &addr, &addrlen);
991     if (-1 == r)
992     {
993       GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "recvfrom");
994       GNUNET_NETWORK_socket_close (dnsout);
995       return GNUNET_SYSERR;
996     }
997     if (sizeof (struct GNUNET_TUN_DnsHeader) > r)
998     {
999       GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 
1000                   _("Received DNS response that is too small (%u bytes)"),
1001                   r);
1002       return GNUNET_NO;
1003     }
1004     dns = (struct GNUNET_TUN_DnsHeader *) buf;
1005     /* Handle case that this is a reply to a request from a MESH DNS tunnel */
1006     ts = tunnels[dns->id];
1007     if ( (NULL == ts) ||
1008          (ts->dnsout != dnsout) ||
1009          (addrlen != ts->addrlen) ||
1010          (0 != memcmp (&ts->addr,
1011                        &addr,
1012                        addrlen)) ||      
1013          (0 == GNUNET_TIME_absolute_get_remaining (ts->timeout).rel_value) )
1014       ts = NULL; /* DNS responder address missmatch */
1015     if (NULL != ts)
1016     {
1017       tunnels[dns->id] = NULL;
1018       GNUNET_free_non_null (ts->reply);
1019       ts->reply = GNUNET_malloc (r);
1020       ts->reply_length = r;
1021       memcpy (ts->reply, dns, r);
1022       if (ts->th != NULL)
1023         GNUNET_MESH_notify_transmit_ready_cancel (ts->th);
1024       ts->th = GNUNET_MESH_notify_transmit_ready (ts->tunnel,
1025                                                   GNUNET_NO, 0,
1026                                                   GNUNET_TIME_UNIT_FOREVER_REL,
1027                                                   NULL,
1028                                                   sizeof (struct GNUNET_MessageHeader) + r,
1029                                                   &transmit_reply_to_mesh,
1030                                                   ts);
1031     }
1032     /* Handle case that this is a reply to a local request (intercepted from TUN interface) */
1033     rr = &requests[dns->id];
1034     if ( (rr->phase != RP_INTERNET_DNS) ||
1035          (rr->dnsout != dnsout) ||
1036          (0 != memcmp (&rr->dst_addr,
1037                        &addr,
1038                        addrlen)) ||
1039          (0 == GNUNET_TIME_absolute_get_remaining (rr->timeout).rel_value) )
1040     {
1041       if (NULL == ts)
1042       {
1043         /* unexpected / bogus reply */
1044         GNUNET_STATISTICS_update (stats,
1045                                   gettext_noop ("# External DNS response discarded (no matching request)"),
1046                                   1, GNUNET_NO);
1047       }
1048       return GNUNET_NO; 
1049     }
1050     GNUNET_free_non_null (rr->payload);
1051     rr->payload = GNUNET_malloc (r);
1052     memcpy (rr->payload, buf, r);
1053     rr->payload_length = r;
1054     next_phase (rr);
1055   }  
1056   return GNUNET_OK;
1057 }
1058
1059
1060 /**
1061  * Read a DNS response from the (unhindered) UDP-Socket
1062  *
1063  * @param cls socket to read from
1064  * @param tc scheduler context (must be shutdown or read ready)
1065  */
1066 static void
1067 read_response (void *cls,
1068                const struct GNUNET_SCHEDULER_TaskContext *tc)
1069 {
1070   struct RequestSocket *rs = cls;
1071   struct GNUNET_NETWORK_FDSet *rset;
1072
1073   rs->read_task = GNUNET_SCHEDULER_NO_TASK;
1074   if (0 == (tc->reason & GNUNET_SCHEDULER_REASON_READ_READY))
1075   {
1076     /* timeout or shutdown */
1077     cleanup_rs (rs);
1078     return;
1079   }
1080   /* read and process ready sockets */
1081   if ((NULL != rs->dnsout4) &&
1082       (GNUNET_NETWORK_fdset_isset (tc->read_ready, rs->dnsout4)) &&
1083       (GNUNET_SYSERR == do_dns_read (rs->dnsout4)))
1084     rs->dnsout4 = NULL;
1085   if ((NULL != rs->dnsout6) &&
1086       (GNUNET_NETWORK_fdset_isset (tc->read_ready, rs->dnsout6)) &&
1087       (GNUNET_SYSERR == do_dns_read (rs->dnsout6)))
1088     rs->dnsout6 = NULL;
1089
1090   /* re-schedule read task */
1091   rset = GNUNET_NETWORK_fdset_create ();
1092   if (NULL != rs->dnsout4)
1093     GNUNET_NETWORK_fdset_set (rset, rs->dnsout4);
1094   if (NULL != rs->dnsout6)
1095     GNUNET_NETWORK_fdset_set (rset, rs->dnsout6);
1096   rs->read_task = GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_DEFAULT,
1097                                                GNUNET_SCHEDULER_NO_TASK,
1098                                                GNUNET_TIME_absolute_get_remaining (rs->timeout),
1099                                                rset,
1100                                                NULL,
1101                                                &read_response, rs);
1102   GNUNET_NETWORK_fdset_destroy (rset);
1103 }
1104
1105
1106 /**
1107  * We got a new client.  Make sure all new DNS requests pass by its desk.
1108  *
1109  * @param cls unused
1110  * @param client the new client
1111  * @param message the init message (unused)
1112  */
1113 static void
1114 handle_client_init (void *cls GNUNET_UNUSED, 
1115                     struct GNUNET_SERVER_Client *client,
1116                     const struct GNUNET_MessageHeader *message)
1117 {
1118   struct ClientRecord *cr;
1119   const struct GNUNET_DNS_Register *reg = (const struct GNUNET_DNS_Register*) message;
1120
1121   cr = GNUNET_malloc (sizeof (struct ClientRecord));
1122   cr->client = client;
1123   cr->flags = (enum GNUNET_DNS_Flags) ntohl (reg->flags);  
1124   GNUNET_SERVER_client_keep (client);
1125   GNUNET_CONTAINER_DLL_insert (clients_head,
1126                                clients_tail,
1127                                cr);
1128   GNUNET_SERVER_notification_context_add (nc, client);
1129   GNUNET_SERVER_receive_done (client, GNUNET_OK);
1130 }
1131
1132
1133 /**
1134  * We got a response from a client.
1135  *
1136  * @param cls unused
1137  * @param client the client
1138  * @param message the response
1139  */
1140 static void
1141 handle_client_response (void *cls GNUNET_UNUSED, 
1142                         struct GNUNET_SERVER_Client *client,
1143                         const struct GNUNET_MessageHeader *message)
1144 {
1145   const struct GNUNET_DNS_Response *resp;
1146   struct RequestRecord *rr;
1147   unsigned int i;
1148   uint16_t msize;
1149   uint16_t off;
1150
1151   msize = ntohs (message->size);
1152   if (msize < sizeof (struct GNUNET_DNS_Response))
1153   {
1154     GNUNET_break (0);
1155     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1156     return;
1157   }
1158   resp = (const struct GNUNET_DNS_Response*) message;
1159   off = (uint16_t) resp->request_id;
1160   rr = &requests[off];
1161   if (rr->request_id != resp->request_id)
1162   {
1163     GNUNET_STATISTICS_update (stats,
1164                               gettext_noop ("# Client response discarded (no matching request)"),
1165                               1, GNUNET_NO);
1166     GNUNET_SERVER_receive_done (client, GNUNET_OK);
1167     return;
1168   }
1169   for (i=0;i<rr->client_wait_list_length;i++)
1170   {
1171     if (NULL == rr->client_wait_list[i])
1172       continue;
1173     if (rr->client_wait_list[i]->client != client)
1174       continue;
1175     rr->client_wait_list[i] = NULL;
1176     switch (ntohl (resp->drop_flag))
1177     {
1178     case 0: /* drop */
1179       rr->phase = RP_DROP;
1180       break;
1181     case 1: /* no change */
1182       break;
1183     case 2: /* update */
1184       msize -= sizeof (struct GNUNET_DNS_Response);
1185       if ( (sizeof (struct GNUNET_TUN_DnsHeader) > msize) ||
1186            (RP_REQUEST_MONITOR == rr->phase) ||
1187            (RP_RESPONSE_MONITOR == rr->phase) )
1188       {
1189         GNUNET_break (0);
1190         GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1191         next_phase (rr); 
1192         return;
1193       }
1194       GNUNET_free_non_null (rr->payload);
1195 #if DEBUG_DNS
1196       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1197                   _("Changing DNS reply according to client specifications\n"));
1198 #endif
1199       rr->payload = GNUNET_malloc (msize);
1200       rr->payload_length = msize;
1201       memcpy (rr->payload, &resp[1], msize);
1202       if (rr->phase == RP_QUERY)
1203       {
1204         /* clear wait list, we're moving to MODIFY phase next */
1205         GNUNET_array_grow (rr->client_wait_list,
1206                            rr->client_wait_list_length,
1207                            0);
1208       }
1209       break;
1210     }
1211     next_phase (rr); 
1212     GNUNET_SERVER_receive_done (client, GNUNET_OK);
1213     return;      
1214   }
1215   /* odd, client was not on our list for the request, that ought
1216      to be an error */
1217   GNUNET_break (0);
1218   GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1219 }
1220
1221
1222 /**
1223  * Functions with this signature are called whenever a complete
1224  * message is received by the tokenizer from the DNS hijack process.
1225  *
1226  * @param cls closure
1227  * @param client identification of the client
1228  * @param message the actual message, a DNS request we should handle
1229  */
1230 static void
1231 process_helper_messages (void *cls GNUNET_UNUSED, void *client,
1232                          const struct GNUNET_MessageHeader *message)
1233 {
1234   uint16_t msize;
1235   const struct GNUNET_TUN_Layer2PacketHeader *tun;
1236   const struct GNUNET_TUN_IPv4Header *ip4;
1237   const struct GNUNET_TUN_IPv6Header *ip6;
1238   const struct GNUNET_TUN_UdpHeader *udp;
1239   const struct GNUNET_TUN_DnsHeader *dns;
1240   struct RequestRecord *rr;
1241   struct sockaddr_in *srca4;
1242   struct sockaddr_in6 *srca6;
1243   struct sockaddr_in *dsta4;
1244   struct sockaddr_in6 *dsta6;
1245
1246   msize = ntohs (message->size);
1247   if (msize < sizeof (struct GNUNET_MessageHeader) + sizeof (struct GNUNET_TUN_Layer2PacketHeader) + sizeof (struct GNUNET_TUN_IPv4Header))
1248   {
1249     /* non-IP packet received on TUN!? */
1250     GNUNET_break (0);
1251     return;
1252   }
1253   msize -= sizeof (struct GNUNET_MessageHeader);
1254   tun = (const struct GNUNET_TUN_Layer2PacketHeader *) &message[1];
1255   msize -= sizeof (struct GNUNET_TUN_Layer2PacketHeader);
1256   switch (ntohs (tun->proto))
1257   {
1258   case ETH_P_IPV4:
1259     ip4 = (const struct GNUNET_TUN_IPv4Header *) &tun[1];
1260     if ( (msize < sizeof (struct GNUNET_TUN_IPv4Header)) ||
1261          (ip4->version != 4) ||
1262          (ip4->header_length != sizeof (struct GNUNET_TUN_IPv4Header) / 4) ||
1263          (ntohs(ip4->total_length) != msize) ||
1264          (ip4->protocol != IPPROTO_UDP) )
1265     {
1266       /* non-IP/UDP packet received on TUN (or with options) */
1267       GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1268                   _("Received malformed IPv4-UDP packet on TUN interface.\n"));
1269       return;
1270     }
1271     udp = (const struct GNUNET_TUN_UdpHeader*) &ip4[1];
1272     msize -= sizeof (struct GNUNET_TUN_IPv4Header);
1273     break;
1274   case ETH_P_IPV6:
1275     ip6 = (const struct GNUNET_TUN_IPv6Header *) &tun[1];
1276     if ( (msize < sizeof (struct GNUNET_TUN_IPv6Header)) ||
1277          (ip6->version != 6) ||
1278          (ntohs (ip6->payload_length) != msize) ||
1279          (ip6->next_header != IPPROTO_UDP) )
1280     {
1281       /* non-IP/UDP packet received on TUN (or with extensions) */
1282       GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1283                   _("Received malformed IPv6-UDP packet on TUN interface.\n"));
1284       return;
1285     }
1286     udp = (const struct GNUNET_TUN_UdpHeader*) &ip6[1];
1287     msize -= sizeof (struct GNUNET_TUN_IPv6Header);
1288     break;
1289   default:
1290     /* non-IP packet received on TUN!? */
1291     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1292                 _("Got non-IP packet with %u bytes and protocol %u from TUN\n"),
1293                 (unsigned int) msize,
1294                 ntohs (tun->proto));
1295     return;
1296   }
1297   if (msize <= sizeof (struct GNUNET_TUN_UdpHeader) + sizeof (struct GNUNET_TUN_DnsHeader))
1298   {    
1299     /* non-DNS packet received on TUN, ignore */
1300     GNUNET_STATISTICS_update (stats,
1301                               gettext_noop ("# Non-DNS UDP packet received via TUN interface"),
1302                               1, GNUNET_NO);
1303     return;
1304   }
1305   msize -= sizeof (struct GNUNET_TUN_UdpHeader);
1306   dns = (const struct GNUNET_TUN_DnsHeader*) &udp[1];
1307   rr = &requests[dns->id];
1308
1309   /* clean up from previous request */
1310   GNUNET_free_non_null (rr->payload);
1311   rr->payload = NULL;
1312   GNUNET_array_grow (rr->client_wait_list,
1313                      rr->client_wait_list_length,
1314                      0);
1315
1316   /* setup new request */
1317   rr->phase = RP_INIT;
1318   switch (ntohs (tun->proto))
1319   {
1320   case ETH_P_IPV4:
1321     {
1322       srca4 = (struct sockaddr_in*) &rr->src_addr;
1323       dsta4 = (struct sockaddr_in*) &rr->dst_addr;
1324       memset (srca4, 0, sizeof (struct sockaddr_in));
1325       memset (dsta4, 0, sizeof (struct sockaddr_in));
1326       srca4->sin_family = AF_INET;
1327       dsta4->sin_family = AF_INET;
1328       srca4->sin_addr = ip4->source_address;
1329       dsta4->sin_addr = ip4->destination_address;
1330       srca4->sin_port = udp->source_port;
1331       dsta4->sin_port = udp->destination_port;
1332 #if HAVE_SOCKADDR_IN_SIN_LEN
1333       srca4->sin_len = sizeof (struct sockaddr_in);
1334       dsta4->sin_len = sizeof (struct sockaddr_in);
1335 #endif
1336     }
1337     break;
1338   case ETH_P_IPV6:
1339     {
1340       srca6 = (struct sockaddr_in6*) &rr->src_addr;
1341       dsta6 = (struct sockaddr_in6*) &rr->dst_addr;
1342       memset (srca6, 0, sizeof (struct sockaddr_in6));
1343       memset (dsta6, 0, sizeof (struct sockaddr_in6));
1344       srca6->sin6_family = AF_INET6;
1345       dsta6->sin6_family = AF_INET6;
1346       srca6->sin6_addr = ip6->source_address;
1347       dsta6->sin6_addr = ip6->destination_address;
1348       srca6->sin6_port = udp->source_port;
1349       dsta6->sin6_port = udp->destination_port;
1350 #if HAVE_SOCKADDR_IN_SIN_LEN
1351       srca6->sin6_len = sizeof (struct sockaddr_in6);
1352       dsta6->sin6_len = sizeof (struct sockaddr_in6);
1353 #endif
1354     }
1355   break;
1356   default:
1357     GNUNET_assert (0);
1358   }
1359   rr->payload = GNUNET_malloc (msize);
1360   rr->payload_length = msize;
1361   memcpy (rr->payload, dns, msize);
1362   rr->request_id = dns->id | (request_id_gen << 16);
1363   request_id_gen++;
1364
1365   GNUNET_STATISTICS_update (stats,
1366                             gettext_noop ("# DNS requests received via TUN interface"),
1367                             1, GNUNET_NO);
1368   /* start request processing state machine */
1369   next_phase (rr);
1370 }
1371
1372
1373 /**
1374  * Process a request via mesh to perform a DNS query.
1375  *
1376  * @param cls closure, NULL
1377  * @param tunnel connection to the other end
1378  * @param tunnel_ctx pointer to our 'struct TunnelState *'
1379  * @param sender who sent the message
1380  * @param message the actual message
1381  * @param atsi performance data for the connection
1382  * @return GNUNET_OK to keep the connection open,
1383  *         GNUNET_SYSERR to close it (signal serious error)
1384  */
1385 static int
1386 receive_dns_request (void *cls GNUNET_UNUSED, struct GNUNET_MESH_Tunnel *tunnel,
1387                      void **tunnel_ctx,
1388                      const struct GNUNET_PeerIdentity *sender GNUNET_UNUSED,
1389                      const struct GNUNET_MessageHeader *message,
1390                      const struct GNUNET_ATS_Information *atsi GNUNET_UNUSED)
1391 {
1392   struct TunnelState *ts = *tunnel_ctx;
1393   const struct GNUNET_TUN_DnsHeader *dns;
1394   size_t mlen = ntohs (message->size);
1395   size_t dlen = mlen - sizeof (struct GNUNET_MessageHeader);
1396   char buf[dlen];
1397   struct GNUNET_TUN_DnsHeader *dout;
1398   struct sockaddr_in v4;
1399   struct sockaddr_in6 v6;
1400   struct sockaddr *so;
1401   socklen_t salen;
1402   
1403   if (dlen < sizeof (struct GNUNET_TUN_DnsHeader))
1404   {
1405     GNUNET_break_op (0);
1406     return GNUNET_SYSERR;
1407   }
1408   dns = (const struct GNUNET_TUN_DnsHeader *) &message[1];
1409   ts->original_id = dns->id;
1410   if (tunnels[ts->my_id] == ts)
1411     tunnels[ts->my_id] = NULL;
1412   ts->my_id = (uint16_t) GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, 
1413                                                    UINT16_MAX + 1);
1414   tunnels[ts->my_id] = ts;
1415   memcpy (buf, dns, dlen);
1416   dout = (struct GNUNET_TUN_DnsHeader*) buf;
1417   dout->id = ts->my_id;
1418   memset (&v4, 0, sizeof (v4));
1419   memset (&v6, 0, sizeof (v6));
1420   if (1 == inet_pton (AF_INET, dns_exit, &v4.sin_addr))
1421   {
1422     salen = sizeof (v4);
1423     v4.sin_family = AF_INET;
1424     v4.sin_port = htons (53);
1425 #if HAVE_SOCKADDR_IN_SIN_LEN
1426     v4.sin_len = (u_char) salen;
1427 #endif
1428     so = (struct sockaddr *) &v4;
1429     ts->dnsout = get_request_socket (AF_INET);
1430   }
1431   else if (1 == inet_pton (AF_INET6, dns_exit, &v6.sin6_addr))
1432   {
1433     salen = sizeof (v6);
1434     v6.sin6_family = AF_INET6;
1435     v6.sin6_port = htons (53);
1436 #if HAVE_SOCKADDR_IN_SIN_LEN
1437     v6.sin6_len = (u_char) salen;
1438 #endif
1439     so = (struct sockaddr *) &v6;
1440     ts->dnsout = get_request_socket (AF_INET6);
1441   }  
1442   else
1443   {
1444     GNUNET_break (0);
1445     return GNUNET_SYSERR;
1446   }
1447   if (NULL == ts->dnsout)
1448   {
1449     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1450                 _("Configured DNS exit `%s' is not working / valid.\n"),
1451                 dns_exit);
1452     return GNUNET_SYSERR;
1453   }
1454   memcpy (&ts->addr,
1455           so,
1456           salen);
1457   ts->addrlen = salen;
1458   GNUNET_NETWORK_socket_sendto (ts->dnsout,
1459                                 buf, dlen, so, salen); 
1460   ts->timeout = GNUNET_TIME_relative_to_absolute (REQUEST_TIMEOUT);
1461   return GNUNET_OK;
1462 }
1463
1464
1465 /**
1466  * Callback from GNUNET_MESH for new tunnels.
1467  *
1468  * @param cls closure
1469  * @param tunnel new handle to the tunnel
1470  * @param initiator peer that started the tunnel
1471  * @param ats performance information for the tunnel
1472  * @return initial tunnel context for the tunnel
1473  */
1474 static void *
1475 accept_dns_tunnel (void *cls GNUNET_UNUSED, struct GNUNET_MESH_Tunnel *tunnel,
1476                    const struct GNUNET_PeerIdentity *initiator GNUNET_UNUSED,
1477                    const struct GNUNET_ATS_Information *ats GNUNET_UNUSED)
1478 {
1479   struct TunnelState *ts = GNUNET_malloc (sizeof (struct TunnelState));
1480
1481   GNUNET_STATISTICS_update (stats,
1482                             gettext_noop ("# Inbound MESH tunnels created"),
1483                             1, GNUNET_NO);
1484   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1485               "Received inbound tunnel from `%s'\n",
1486               GNUNET_i2s (initiator));
1487   ts->tunnel = tunnel;
1488   return ts;
1489 }
1490
1491
1492 /**
1493  * Function called by mesh whenever an inbound tunnel is destroyed.
1494  * Should clean up any associated state.
1495  *
1496  * @param cls closure (set from GNUNET_MESH_connect)
1497  * @param tunnel connection to the other end (henceforth invalid)
1498  * @param tunnel_ctx place where local state associated
1499  *                   with the tunnel is stored
1500  */
1501 static void
1502 destroy_dns_tunnel (void *cls GNUNET_UNUSED, 
1503                     const struct GNUNET_MESH_Tunnel *tunnel,
1504                     void *tunnel_ctx)
1505 {
1506   struct TunnelState *ts = tunnel_ctx;
1507
1508   if (tunnels[ts->my_id] == ts)
1509     tunnels[ts->my_id] = NULL;
1510   if (NULL != ts->th)
1511     GNUNET_MESH_notify_transmit_ready_cancel (ts->th);
1512   GNUNET_free_non_null (ts->reply);
1513   GNUNET_free (ts);
1514 }
1515
1516
1517 /**
1518  * @param cls closure
1519  * @param server the initialized server
1520  * @param cfg_ configuration to use
1521  */
1522 static void
1523 run (void *cls, struct GNUNET_SERVER_Handle *server,
1524      const struct GNUNET_CONFIGURATION_Handle *cfg_)
1525 {
1526   static const struct GNUNET_SERVER_MessageHandler handlers[] = {
1527     /* callback, cls, type, size */
1528     {&handle_client_init, NULL, GNUNET_MESSAGE_TYPE_DNS_CLIENT_INIT, 
1529      sizeof (struct GNUNET_DNS_Register)},
1530     {&handle_client_response, NULL, GNUNET_MESSAGE_TYPE_DNS_CLIENT_RESPONSE, 0},
1531     {NULL, NULL, 0, 0}
1532   };
1533   char *ifc_name;
1534   char *ipv4addr;
1535   char *ipv4mask;
1536   char *ipv6addr;
1537   char *ipv6prefix;
1538   struct in_addr dns_exit4;
1539   struct in6_addr dns_exit6;
1540
1541   cfg = cfg_;
1542   stats = GNUNET_STATISTICS_create ("dns", cfg);
1543   nc = GNUNET_SERVER_notification_context_create (server, 1);
1544   GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &cleanup_task,
1545                                 cls);
1546   if ( (GNUNET_YES ==
1547         GNUNET_CONFIGURATION_get_value_yesno (cfg_, "dns", "PROVIDE_EXIT")) &&
1548        ( (GNUNET_OK !=
1549           GNUNET_CONFIGURATION_get_value_string (cfg, "dns", 
1550                                                  "DNS_EXIT",
1551                                                  &dns_exit)) ||
1552          ( (1 != inet_pton (AF_INET, dns_exit, &dns_exit4)) &&
1553            (1 != inet_pton (AF_INET6, dns_exit, &dns_exit6)) ) ) )
1554   {
1555     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1556                 _("Configured to provide DNS exit, but no valid DNS server configured!\n"));
1557     GNUNET_free_non_null (dns_exit);
1558     dns_exit = NULL;
1559   }
1560
1561   helper_argv[0] = GNUNET_strdup ("gnunet-dns");
1562   if (GNUNET_SYSERR ==
1563       GNUNET_CONFIGURATION_get_value_string (cfg, "dns", "IFNAME", &ifc_name))
1564   {
1565     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1566                 "No entry 'IFNAME' in configuration!\n");
1567     GNUNET_SCHEDULER_shutdown ();
1568     return;
1569   }
1570   helper_argv[1] = ifc_name;
1571   if ( (GNUNET_SYSERR ==
1572         GNUNET_CONFIGURATION_get_value_string (cfg, "dns", "IPV6ADDR",
1573                                                &ipv6addr)) )
1574   {
1575     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1576                 "No entry 'IPV6ADDR' in configuration!\n");
1577     GNUNET_SCHEDULER_shutdown ();
1578     return;
1579   }
1580   helper_argv[2] = ipv6addr;
1581   if (GNUNET_SYSERR ==
1582       GNUNET_CONFIGURATION_get_value_string (cfg, "dns", "IPV6PREFIX",
1583                                              &ipv6prefix))
1584   {
1585     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1586                 "No entry 'IPV6PREFIX' in configuration!\n");
1587     GNUNET_SCHEDULER_shutdown ();
1588     return;
1589   }
1590   helper_argv[3] = ipv6prefix;
1591
1592   if (GNUNET_SYSERR ==
1593       GNUNET_CONFIGURATION_get_value_string (cfg, "dns", "IPV4ADDR",
1594                                              &ipv4addr))
1595   {
1596     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1597                 "No entry 'IPV4ADDR' in configuration!\n");
1598     GNUNET_SCHEDULER_shutdown ();
1599     return;
1600   }
1601   helper_argv[4] = ipv4addr;
1602   if (GNUNET_SYSERR ==
1603       GNUNET_CONFIGURATION_get_value_string (cfg, "dns", "IPV4MASK",
1604                                              &ipv4mask))
1605   {
1606     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1607                 "No entry 'IPV4MASK' in configuration!\n");
1608     GNUNET_SCHEDULER_shutdown ();
1609     return;
1610   }
1611   helper_argv[5] = ipv4mask;
1612   helper_argv[6] = NULL;
1613
1614   if (NULL != dns_exit)
1615   {
1616     static struct GNUNET_MESH_MessageHandler mesh_handlers[] = {
1617       {&receive_dns_request, GNUNET_MESSAGE_TYPE_VPN_DNS_TO_INTERNET, 0},
1618       {NULL, 0, 0}
1619     };
1620     static GNUNET_MESH_ApplicationType mesh_types[] = {
1621       GNUNET_APPLICATION_TYPE_INTERNET_RESOLVER,
1622       GNUNET_APPLICATION_TYPE_END
1623     };
1624     mesh = GNUNET_MESH_connect (cfg,
1625                                 1, NULL,
1626                                 &accept_dns_tunnel, 
1627                                 &destroy_dns_tunnel,
1628                                 mesh_handlers,
1629                                 mesh_types);
1630   }
1631   hijacker = GNUNET_HELPER_start ("gnunet-helper-dns",
1632                                   helper_argv,
1633                                   &process_helper_messages,
1634                                   NULL);
1635   GNUNET_SERVER_add_handlers (server, handlers);
1636   GNUNET_SERVER_disconnect_notify (server, &client_disconnect, NULL);
1637 }
1638
1639
1640 /**
1641  * The main function for the dns service.
1642  *
1643  * @param argc number of arguments from the command line
1644  * @param argv command line arguments
1645  * @return 0 ok, 1 on error
1646  */
1647 int
1648 main (int argc, char *const *argv)
1649 {
1650   return (GNUNET_OK ==
1651           GNUNET_SERVICE_run (argc, argv, "dns", GNUNET_SERVICE_OPTION_NONE,
1652                               &run, NULL)) ? 0 : 1;
1653 }
1654
1655
1656 /* end of gnunet-service-dns.c */