463176fbc5232dda7199d80e80a08b7963b6602a
[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 }
433
434
435 /**
436  * Open source port for sending DNS requests
437  *
438  * @param af AF_INET or AF_INET6
439  * @return GNUNET_OK on success
440  */ 
441 static struct GNUNET_NETWORK_Handle *
442 open_socket (int af)
443 {
444   struct sockaddr_in a4;
445   struct sockaddr_in6 a6;
446   struct sockaddr *sa;
447   socklen_t alen;
448   struct GNUNET_NETWORK_Handle *ret;
449
450   ret = GNUNET_NETWORK_socket_create (af, SOCK_DGRAM, 0);
451   if (NULL == ret)
452     return NULL;
453   switch (af)
454   {
455   case AF_INET:
456     memset (&a4, 0, alen = sizeof (struct sockaddr_in));
457     sa = (struct sockaddr *) &a4;
458     break;
459   case AF_INET6:
460     memset (&a6, 0, alen = sizeof (struct sockaddr_in6));
461     sa = (struct sockaddr *) &a6;
462     break;
463   default:
464     GNUNET_break (0);
465     return NULL;
466   }
467   sa->sa_family = af;
468   if (GNUNET_OK != GNUNET_NETWORK_socket_bind (ret,
469                                                sa, 
470                                                alen))
471   {
472     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 
473                 _("Could not bind to any port: %s\n"),
474                 STRERROR (errno));
475     GNUNET_NETWORK_socket_close (ret);
476     return NULL;
477   }
478   return ret;
479 }
480
481
482 /**
483  * We're done with some request, finish processing.
484  *
485  * @param rr request send to the network or just clean up.
486  */
487 static void
488 request_done (struct RequestRecord *rr)
489 {
490   struct GNUNET_MessageHeader *hdr;
491   size_t reply_len;
492   uint16_t source_port;
493   uint16_t destination_port;
494
495   GNUNET_array_grow (rr->client_wait_list,
496                      rr->client_wait_list_length,
497                      0); 
498   if (RP_RESPONSE_MONITOR != rr->phase)
499   {
500     /* no response, drop */
501     cleanup_rr (rr);
502     return;
503   }
504   
505   /* send response via hijacker */
506   reply_len = sizeof (struct GNUNET_MessageHeader);
507   reply_len += sizeof (struct GNUNET_TUN_Layer2PacketHeader);
508   switch (rr->src_addr.ss_family)
509   {
510   case AF_INET:
511     reply_len += sizeof (struct GNUNET_TUN_IPv4Header);
512     break;
513   case AF_INET6:
514     reply_len += sizeof (struct GNUNET_TUN_IPv6Header);
515     break;
516   default:
517     GNUNET_break (0);
518     cleanup_rr (rr);
519     return;   
520   }
521   reply_len += sizeof (struct GNUNET_TUN_UdpHeader);
522   reply_len += rr->payload_length;
523   if (reply_len >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
524   {
525     /* response too big, drop */
526     GNUNET_break (0); /* how can this be? */
527     cleanup_rr(rr);
528     return;    
529   }
530   {
531     char buf[reply_len];
532     size_t off;
533     struct GNUNET_TUN_IPv4Header ip4;
534     struct GNUNET_TUN_IPv6Header ip6;
535
536     /* first, GNUnet message header */
537     hdr = (struct GNUNET_MessageHeader*) buf;
538     hdr->type = htons (GNUNET_MESSAGE_TYPE_DNS_HELPER);
539     hdr->size = htons ((uint16_t) reply_len);
540     off = sizeof (struct GNUNET_MessageHeader);
541
542     /* first, TUN header */
543     {
544       struct GNUNET_TUN_Layer2PacketHeader tun;
545
546       tun.flags = htons (0);
547       if (rr->src_addr.ss_family == AF_INET)
548         tun.proto = htons (ETH_P_IPV4); 
549       else
550         tun.proto = htons (ETH_P_IPV6);
551       memcpy (&buf[off], &tun, sizeof (struct GNUNET_TUN_Layer2PacketHeader));
552       off += sizeof (struct GNUNET_TUN_Layer2PacketHeader);
553     }
554
555     /* now IP header */
556     switch (rr->src_addr.ss_family)
557     {
558     case AF_INET:
559       {
560         struct sockaddr_in *src = (struct sockaddr_in *) &rr->src_addr;
561         struct sockaddr_in *dst = (struct sockaddr_in *) &rr->dst_addr;
562         
563         source_port = dst->sin_port;
564         destination_port = src->sin_port;
565         GNUNET_TUN_initialize_ipv4_header (&ip4,
566                                            IPPROTO_UDP,
567                                            reply_len - off - sizeof (struct GNUNET_TUN_IPv4Header),
568                                            &dst->sin_addr,
569                                            &src->sin_addr);
570         memcpy (&buf[off], &ip4, sizeof (ip4));
571         off += sizeof (ip4);
572       }
573       break;
574     case AF_INET6:
575       {
576         struct sockaddr_in6 *src = (struct sockaddr_in6 *) &rr->src_addr;
577         struct sockaddr_in6 *dst = (struct sockaddr_in6 *) &rr->dst_addr;
578
579         source_port = dst->sin6_port;
580         destination_port = src->sin6_port;
581         GNUNET_TUN_initialize_ipv6_header (&ip6,
582                                            IPPROTO_UDP,
583                                            reply_len - sizeof (struct GNUNET_TUN_IPv6Header),
584                                            &dst->sin6_addr,
585                                            &src->sin6_addr);
586         memcpy (&buf[off], &ip6, sizeof (ip6));
587         off += sizeof (ip6);
588       }
589       break;
590     default:
591       GNUNET_assert (0);
592     }
593
594     /* now UDP header */
595     {
596       struct GNUNET_TUN_UdpHeader udp;
597
598       udp.source_port = source_port;
599       udp.destination_port = destination_port;
600       udp.len = htons (reply_len - off);
601       if (AF_INET == rr->src_addr.ss_family)
602         GNUNET_TUN_calculate_udp4_checksum (&ip4,
603                                             &udp,
604                                             rr->payload,
605                                             rr->payload_length);
606       else
607         GNUNET_TUN_calculate_udp6_checksum (&ip6,
608                                             &udp,
609                                             rr->payload,
610                                             rr->payload_length);
611       memcpy (&buf[off], &udp, sizeof (udp));
612       off += sizeof (udp);
613     }
614
615     /* now DNS payload */
616     {
617       memcpy (&buf[off], rr->payload, rr->payload_length);
618       off += rr->payload_length;
619     }
620     /* final checks & sending */
621     GNUNET_assert (off == reply_len);
622     GNUNET_HELPER_send (hijacker,
623                         hdr,
624                         GNUNET_YES,
625                         NULL, NULL);
626     GNUNET_STATISTICS_update (stats,
627                               gettext_noop ("# DNS requests answered via TUN interface"),
628                               1, GNUNET_NO);
629   }
630   /* clean up, we're done */
631   cleanup_rr (rr);
632 }
633
634
635 /**
636  * Show the payload of the given request record to the client
637  * (and wait for a response).
638  *
639  * @param rr request to send to client
640  * @param client client to send the response to
641  */
642 static void
643 send_request_to_client (struct RequestRecord *rr,
644                         struct GNUNET_SERVER_Client *client)
645 {
646   char buf[sizeof (struct GNUNET_DNS_Request) + rr->payload_length];
647   struct GNUNET_DNS_Request *req;
648
649   if (sizeof (buf) >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
650   {
651     GNUNET_break (0);
652     cleanup_rr (rr);
653     return;
654   }
655   req = (struct GNUNET_DNS_Request*) buf;
656   req->header.type = htons (GNUNET_MESSAGE_TYPE_DNS_CLIENT_REQUEST);
657   req->header.size = htons (sizeof (buf));
658   req->reserved = htonl (0);
659   req->request_id = rr->request_id;
660   memcpy (&req[1], rr->payload, rr->payload_length);
661   GNUNET_SERVER_notification_context_unicast (nc, 
662                                               client,
663                                               &req->header,
664                                               GNUNET_NO);
665 }
666
667
668 /**
669  * Read a DNS response from the (unhindered) UDP-Socket
670  *
671  * @param cls socket to read from
672  * @param tc scheduler context (must be shutdown or read ready)
673  */
674 static void
675 read_response (void *cls,
676                const struct GNUNET_SCHEDULER_TaskContext *tc);
677
678
679 /**
680  * Get a socket of the specified address family to send out a
681  * UDP DNS request to the Internet.  
682  *
683  * @param af desired address family
684  * @return NULL on error (given AF not "supported")
685  */
686 static struct GNUNET_NETWORK_Handle *
687 get_request_socket (int af)
688 {
689   struct RequestSocket *rs;
690   struct GNUNET_NETWORK_FDSet *rset;
691   static struct GNUNET_NETWORK_Handle *ret;
692
693   rs = &sockets[GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_NONCE, 
694                                           DNS_SOCKET_MAX)];
695   rs->timeout = GNUNET_TIME_relative_to_absolute (REQUEST_TIMEOUT);
696   switch (af)
697   {
698   case AF_INET:
699     if (NULL == rs->dnsout4)
700       rs->dnsout4 = open_socket (AF_INET);
701     ret = rs->dnsout4;
702     break;
703   case AF_INET6:
704     if (NULL == rs->dnsout6)
705       rs->dnsout6 = open_socket (AF_INET6);
706     ret = rs->dnsout6;
707     break;
708   default:
709     return NULL;
710   }  
711   if (GNUNET_SCHEDULER_NO_TASK != rs->read_task)
712   {
713     GNUNET_SCHEDULER_cancel (rs->read_task);
714     rs->read_task = GNUNET_SCHEDULER_NO_TASK;
715   }
716   if ( (NULL == rs->dnsout4) &&
717        (NULL == rs->dnsout6) )
718     return NULL;
719   rset = GNUNET_NETWORK_fdset_create ();
720   if (NULL != rs->dnsout4)
721     GNUNET_NETWORK_fdset_set (rset, rs->dnsout4);
722   if (NULL != rs->dnsout6)
723     GNUNET_NETWORK_fdset_set (rset, rs->dnsout6);
724   rs->read_task = GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_DEFAULT,
725                                                GNUNET_SCHEDULER_NO_TASK,
726                                                REQUEST_TIMEOUT,
727                                                rset,
728                                                NULL,
729                                                &read_response, rs);
730   GNUNET_NETWORK_fdset_destroy (rset);
731   return ret;
732 }
733
734
735 /**
736  * A client has completed its processing for this
737  * request.  Move on.
738  *
739  * @param rr request to process further
740  */
741 static void
742 next_phase (struct RequestRecord *rr)
743 {
744   struct ClientRecord *cr;
745   int nz;
746   unsigned int j;
747   socklen_t salen;
748
749   if (rr->phase == RP_DROP)
750   {
751     cleanup_rr (rr);
752     return;
753   }
754   nz = -1;
755   for (j=0;j<rr->client_wait_list_length;j++)
756   {
757     if (NULL != rr->client_wait_list[j])
758     {
759       nz = (int) j;
760       break;
761     }
762   }  
763   if (-1 != nz) 
764   {
765     send_request_to_client (rr, rr->client_wait_list[nz]->client);
766     return;
767   }
768   /* done with current phase, advance! */
769   switch (rr->phase)
770   {
771   case RP_INIT:
772     rr->phase = RP_REQUEST_MONITOR;
773     for (cr = clients_head; NULL != cr; cr = cr->next)
774     {
775       if (0 != (cr->flags & GNUNET_DNS_FLAG_REQUEST_MONITOR))
776         GNUNET_array_append (rr->client_wait_list,
777                              rr->client_wait_list_length,
778                              cr);
779     }
780     next_phase (rr);
781     return;
782   case RP_REQUEST_MONITOR:
783     rr->phase = RP_QUERY;
784     for (cr = clients_head; NULL != cr; cr = cr->next)
785     {
786       if (0 != (cr->flags & GNUNET_DNS_FLAG_PRE_RESOLUTION))
787         GNUNET_array_append (rr->client_wait_list,
788                              rr->client_wait_list_length,
789                              cr);
790     }
791     next_phase (rr);
792     return;
793   case RP_QUERY:
794     switch (rr->dst_addr.ss_family)
795     {
796     case AF_INET:
797       salen = sizeof (struct sockaddr_in);
798       break;
799     case AF_INET6:
800       salen = sizeof (struct sockaddr_in6);
801       break;
802     default:
803       GNUNET_assert (0);
804     }
805
806     rr->phase = RP_INTERNET_DNS;
807     rr->dnsout = get_request_socket (rr->dst_addr.ss_family);
808     if (NULL == rr->dnsout)
809     {
810       GNUNET_STATISTICS_update (stats,
811                                 gettext_noop ("# DNS exit failed (failed to open socket)"),
812                                 1, GNUNET_NO);
813       cleanup_rr (rr);
814       return;
815     }
816     GNUNET_NETWORK_socket_sendto (rr->dnsout,
817                                   rr->payload,
818                                   rr->payload_length,
819                                   (struct sockaddr*) &rr->dst_addr,
820                                   salen);
821     rr->timeout = GNUNET_TIME_relative_to_absolute (REQUEST_TIMEOUT);
822     return;
823   case RP_INTERNET_DNS:
824     rr->phase = RP_MODIFY;
825     for (cr = clients_head; NULL != cr; cr = cr->next)
826     {
827       if (0 != (cr->flags & GNUNET_DNS_FLAG_POST_RESOLUTION))
828         GNUNET_array_append (rr->client_wait_list,
829                              rr->client_wait_list_length,
830                              cr);
831     }
832     next_phase (rr);
833     return;
834   case RP_MODIFY:
835     rr->phase = RP_RESPONSE_MONITOR;
836     for (cr = clients_head; NULL != cr; cr = cr->next)
837     {
838       if (0 != (cr->flags & GNUNET_DNS_FLAG_RESPONSE_MONITOR))
839         GNUNET_array_append (rr->client_wait_list,
840                              rr->client_wait_list_length,
841                              cr);
842     }
843     next_phase (rr);
844     return;
845  case RP_RESPONSE_MONITOR:
846     request_done (rr);
847     break;
848   case RP_DROP:
849     cleanup_rr (rr);
850     break;
851   default:
852     GNUNET_break (0);
853     cleanup_rr (rr);
854     break;
855   }
856 }
857
858
859 /**
860  * A client disconnected, clean up after it.
861  *
862  * @param cls unused
863  * @param client handle of client that disconnected
864  */ 
865 static void
866 client_disconnect (void *cls, struct GNUNET_SERVER_Client *client)
867 {
868   struct ClientRecord *cr;
869   struct RequestRecord *rr;
870   unsigned int i;
871   unsigned int j;
872
873   for (cr = clients_head; NULL != cr; cr = cr->next)
874   {
875     if (cr->client == client)
876     {
877       GNUNET_SERVER_client_drop (client);
878       GNUNET_CONTAINER_DLL_remove (clients_head,
879                                    clients_tail,
880                                    cr);
881       for (i=0;i<UINT16_MAX;i++)
882       {
883         rr = &requests[i];
884         if (0 == rr->client_wait_list_length)
885           continue; /* not in use */
886         for (j=0;j<rr->client_wait_list_length;j++)
887         {
888           if (rr->client_wait_list[j] == cr)
889           {
890             rr->client_wait_list[j] = NULL;
891             next_phase (rr); 
892           }
893         }
894       }
895       GNUNET_free (cr);
896       return;
897     }
898   }
899 }
900
901
902 /**
903  * We got a reply from DNS for a request of a MESH tunnel.  Send it
904  * via the tunnel (after changing the request ID back).
905  *
906  * @param cls the 'struct TunnelState'
907  * @param size number of bytes available in buf
908  * @param buf where to copy the reply
909  * @return number of bytes written to buf
910  */
911 static size_t
912 transmit_reply_to_mesh (void *cls,
913                         size_t size,
914                         void *buf)
915 {
916   struct TunnelState *ts = cls;
917   size_t off;
918   size_t ret;
919   char *cbuf = buf;
920   struct GNUNET_MessageHeader hdr;
921   struct GNUNET_TUN_DnsHeader dns;
922
923   ts->th = NULL;
924   GNUNET_assert (ts->reply != NULL);
925   if (size == 0)
926     return 0;
927   ret = sizeof (struct GNUNET_MessageHeader) + ts->reply_length; 
928   GNUNET_assert (ret <= size);
929   hdr.size = htons (ret);
930   hdr.type = htons (GNUNET_MESSAGE_TYPE_VPN_DNS_FROM_INTERNET);
931   memcpy (&dns, ts->reply, sizeof (dns));
932   dns.id = ts->original_id;
933   off = 0;
934   memcpy (&cbuf[off], &hdr, sizeof (hdr));
935   off += sizeof (hdr);
936   memcpy (&cbuf[off], &dns, sizeof (dns));
937   off += sizeof (dns);
938   memcpy (&cbuf[off], &ts->reply[sizeof (dns)], ts->reply_length - sizeof (dns));
939   off += ts->reply_length - sizeof (dns);
940   GNUNET_free (ts->reply);
941   ts->reply = NULL;
942   ts->reply_length = 0;  
943   GNUNET_assert (ret == off);
944   return ret;
945 }
946
947
948 /**
949  * Actually do the reading of a DNS packet from our UDP socket and see
950  * if we have a valid, matching, pending request.
951  *
952  * @param dnsout socket to read from
953  * @return GNUNET_OK on success, GNUNET_NO on drop, GNUNET_SYSERR on IO-errors (closed socket)
954  */
955 static int
956 do_dns_read (struct GNUNET_NETWORK_Handle *dnsout)
957 {
958   struct sockaddr_storage addr;
959   socklen_t addrlen;
960   struct GNUNET_TUN_DnsHeader *dns;
961   struct RequestRecord *rr;
962   struct TunnelState *ts;
963   ssize_t r;
964   int len;
965
966 #ifndef MINGW
967   if (0 != ioctl (GNUNET_NETWORK_get_fd (dnsout), FIONREAD, &len))
968   {
969     /* conservative choice: */
970     len = UINT16_MAX;
971   }
972 #else
973   /* port the code above? */
974   len = UINT16_MAX;
975 #endif
976
977   {
978     unsigned char buf[len];
979
980     addrlen = sizeof (addr);
981     memset (&addr, 0, sizeof (addr));  
982     r = GNUNET_NETWORK_socket_recvfrom (dnsout, 
983                                         buf, sizeof (buf),
984                                         (struct sockaddr*) &addr, &addrlen);
985     if (-1 == r)
986     {
987       GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "recvfrom");
988       GNUNET_NETWORK_socket_close (dnsout);
989       return GNUNET_SYSERR;
990     }
991     if (sizeof (struct GNUNET_TUN_DnsHeader) > r)
992     {
993       GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 
994                   _("Received DNS response that is too small (%u bytes)"),
995                   r);
996       return GNUNET_NO;
997     }
998     dns = (struct GNUNET_TUN_DnsHeader *) buf;
999     /* Handle case that this is a reply to a request from a MESH DNS tunnel */
1000     ts = tunnels[dns->id];
1001     if ( (NULL == ts) ||
1002          (ts->dnsout != dnsout) ||
1003          (addrlen != ts->addrlen) ||
1004          (0 != memcmp (&ts->addr,
1005                        &addr,
1006                        addrlen)) ||      
1007          (0 == GNUNET_TIME_absolute_get_remaining (ts->timeout).rel_value) )
1008       ts = NULL; /* DNS responder address missmatch */
1009     if (NULL != ts)
1010     {
1011       tunnels[dns->id] = NULL;
1012       GNUNET_free_non_null (ts->reply);
1013       ts->reply = GNUNET_malloc (r);
1014       ts->reply_length = r;
1015       memcpy (ts->reply, dns, r);
1016       if (ts->th != NULL)
1017         GNUNET_MESH_notify_transmit_ready_cancel (ts->th);
1018       ts->th = GNUNET_MESH_notify_transmit_ready (ts->tunnel,
1019                                                   GNUNET_NO, 0,
1020                                                   GNUNET_TIME_UNIT_FOREVER_REL,
1021                                                   NULL,
1022                                                   sizeof (struct GNUNET_MessageHeader) + r,
1023                                                   &transmit_reply_to_mesh,
1024                                                   ts);
1025     }
1026     /* Handle case that this is a reply to a local request (intercepted from TUN interface) */
1027     rr = &requests[dns->id];
1028     if ( (rr->phase != RP_INTERNET_DNS) ||
1029          (rr->dnsout != dnsout) ||
1030          (0 != memcmp (&rr->dst_addr,
1031                        &addr,
1032                        addrlen)) ||
1033          (0 == GNUNET_TIME_absolute_get_remaining (rr->timeout).rel_value) )
1034     {
1035       if (NULL == ts)
1036       {
1037         /* unexpected / bogus reply */
1038         GNUNET_STATISTICS_update (stats,
1039                                   gettext_noop ("# External DNS response discarded (no matching request)"),
1040                                   1, GNUNET_NO);
1041       }
1042       return GNUNET_NO; 
1043     }
1044     GNUNET_free_non_null (rr->payload);
1045     rr->payload = GNUNET_malloc (r);
1046     memcpy (rr->payload, buf, r);
1047     rr->payload_length = r;
1048     next_phase (rr);
1049   }  
1050   return GNUNET_OK;
1051 }
1052
1053
1054 /**
1055  * Read a DNS response from the (unhindered) UDP-Socket
1056  *
1057  * @param cls socket to read from
1058  * @param tc scheduler context (must be shutdown or read ready)
1059  */
1060 static void
1061 read_response (void *cls,
1062                const struct GNUNET_SCHEDULER_TaskContext *tc)
1063 {
1064   struct RequestSocket *rs = cls;
1065   struct GNUNET_NETWORK_FDSet *rset;
1066
1067   rs->read_task = GNUNET_SCHEDULER_NO_TASK;
1068   if (0 == (tc->reason & GNUNET_SCHEDULER_REASON_READ_READY))
1069   {
1070     /* timeout or shutdown */
1071     cleanup_rs (rs);
1072     return;
1073   }
1074   /* read and process ready sockets */
1075   if ((NULL != rs->dnsout4) &&
1076       (GNUNET_NETWORK_fdset_isset (tc->read_ready, rs->dnsout4)) &&
1077       (GNUNET_SYSERR == do_dns_read (rs->dnsout4)))
1078     rs->dnsout4 = NULL;
1079   if ((NULL != rs->dnsout6) &&
1080       (GNUNET_NETWORK_fdset_isset (tc->read_ready, rs->dnsout6)) &&
1081       (GNUNET_SYSERR == do_dns_read (rs->dnsout6)))
1082     rs->dnsout6 = NULL;
1083
1084   /* re-schedule read task */
1085   rset = GNUNET_NETWORK_fdset_create ();
1086   if (NULL != rs->dnsout4)
1087     GNUNET_NETWORK_fdset_set (rset, rs->dnsout4);
1088   if (NULL != rs->dnsout6)
1089     GNUNET_NETWORK_fdset_set (rset, rs->dnsout6);
1090   rs->read_task = GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_DEFAULT,
1091                                                GNUNET_SCHEDULER_NO_TASK,
1092                                                GNUNET_TIME_absolute_get_remaining (rs->timeout),
1093                                                rset,
1094                                                NULL,
1095                                                &read_response, rs);
1096   GNUNET_NETWORK_fdset_destroy (rset);
1097 }
1098
1099
1100 /**
1101  * We got a new client.  Make sure all new DNS requests pass by its desk.
1102  *
1103  * @param cls unused
1104  * @param client the new client
1105  * @param message the init message (unused)
1106  */
1107 static void
1108 handle_client_init (void *cls GNUNET_UNUSED, 
1109                     struct GNUNET_SERVER_Client *client,
1110                     const struct GNUNET_MessageHeader *message)
1111 {
1112   struct ClientRecord *cr;
1113   const struct GNUNET_DNS_Register *reg = (const struct GNUNET_DNS_Register*) message;
1114
1115   cr = GNUNET_malloc (sizeof (struct ClientRecord));
1116   cr->client = client;
1117   cr->flags = (enum GNUNET_DNS_Flags) ntohl (reg->flags);  
1118   GNUNET_SERVER_client_keep (client);
1119   GNUNET_CONTAINER_DLL_insert (clients_head,
1120                                clients_tail,
1121                                cr);
1122   GNUNET_SERVER_notification_context_add (nc, client);
1123   GNUNET_SERVER_receive_done (client, GNUNET_OK);
1124 }
1125
1126
1127 /**
1128  * We got a response from a client.
1129  *
1130  * @param cls unused
1131  * @param client the client
1132  * @param message the response
1133  */
1134 static void
1135 handle_client_response (void *cls GNUNET_UNUSED, 
1136                         struct GNUNET_SERVER_Client *client,
1137                         const struct GNUNET_MessageHeader *message)
1138 {
1139   const struct GNUNET_DNS_Response *resp;
1140   struct RequestRecord *rr;
1141   unsigned int i;
1142   uint16_t msize;
1143   uint16_t off;
1144
1145   msize = ntohs (message->size);
1146   if (msize < sizeof (struct GNUNET_DNS_Response))
1147   {
1148     GNUNET_break (0);
1149     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1150     return;
1151   }
1152   resp = (const struct GNUNET_DNS_Response*) message;
1153   off = (uint16_t) resp->request_id;
1154   rr = &requests[off];
1155   if (rr->request_id != resp->request_id)
1156   {
1157     GNUNET_STATISTICS_update (stats,
1158                               gettext_noop ("# Client response discarded (no matching request)"),
1159                               1, GNUNET_NO);
1160     GNUNET_SERVER_receive_done (client, GNUNET_OK);
1161     return;
1162   }
1163   for (i=0;i<rr->client_wait_list_length;i++)
1164   {
1165     if (NULL == rr->client_wait_list[i])
1166       continue;
1167     if (rr->client_wait_list[i]->client != client)
1168       continue;
1169     rr->client_wait_list[i] = NULL;
1170     switch (ntohl (resp->drop_flag))
1171     {
1172     case 0: /* drop */
1173       rr->phase = RP_DROP;
1174       break;
1175     case 1: /* no change */
1176       break;
1177     case 2: /* update */
1178       msize -= sizeof (struct GNUNET_DNS_Response);
1179       if ( (sizeof (struct GNUNET_TUN_DnsHeader) > msize) ||
1180            (RP_REQUEST_MONITOR == rr->phase) ||
1181            (RP_RESPONSE_MONITOR == rr->phase) )
1182       {
1183         GNUNET_break (0);
1184         GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1185         next_phase (rr); 
1186         return;
1187       }
1188       GNUNET_free_non_null (rr->payload);
1189 #if DEBUG_DNS
1190       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1191                   _("Changing DNS reply according to client specifications\n"));
1192 #endif
1193       rr->payload = GNUNET_malloc (msize);
1194       rr->payload_length = msize;
1195       memcpy (rr->payload, &resp[1], msize);
1196       if (rr->phase == RP_QUERY)
1197       {
1198         /* clear wait list, we're moving to MODIFY phase next */
1199         GNUNET_array_grow (rr->client_wait_list,
1200                            rr->client_wait_list_length,
1201                            0);
1202       }
1203       break;
1204     }
1205     next_phase (rr); 
1206     GNUNET_SERVER_receive_done (client, GNUNET_OK);
1207     return;      
1208   }
1209   /* odd, client was not on our list for the request, that ought
1210      to be an error */
1211   GNUNET_break (0);
1212   GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1213 }
1214
1215
1216 /**
1217  * Functions with this signature are called whenever a complete
1218  * message is received by the tokenizer from the DNS hijack process.
1219  *
1220  * @param cls closure
1221  * @param client identification of the client
1222  * @param message the actual message, a DNS request we should handle
1223  */
1224 static void
1225 process_helper_messages (void *cls GNUNET_UNUSED, void *client,
1226                          const struct GNUNET_MessageHeader *message)
1227 {
1228   uint16_t msize;
1229   const struct GNUNET_TUN_Layer2PacketHeader *tun;
1230   const struct GNUNET_TUN_IPv4Header *ip4;
1231   const struct GNUNET_TUN_IPv6Header *ip6;
1232   const struct GNUNET_TUN_UdpHeader *udp;
1233   const struct GNUNET_TUN_DnsHeader *dns;
1234   struct RequestRecord *rr;
1235   struct sockaddr_in *srca4;
1236   struct sockaddr_in6 *srca6;
1237   struct sockaddr_in *dsta4;
1238   struct sockaddr_in6 *dsta6;
1239
1240   msize = ntohs (message->size);
1241   if (msize < sizeof (struct GNUNET_MessageHeader) + sizeof (struct GNUNET_TUN_Layer2PacketHeader) + sizeof (struct GNUNET_TUN_IPv4Header))
1242   {
1243     /* non-IP packet received on TUN!? */
1244     GNUNET_break (0);
1245     return;
1246   }
1247   msize -= sizeof (struct GNUNET_MessageHeader);
1248   tun = (const struct GNUNET_TUN_Layer2PacketHeader *) &message[1];
1249   msize -= sizeof (struct GNUNET_TUN_Layer2PacketHeader);
1250   switch (ntohs (tun->proto))
1251   {
1252   case ETH_P_IPV4:
1253     ip4 = (const struct GNUNET_TUN_IPv4Header *) &tun[1];
1254     if ( (msize < sizeof (struct GNUNET_TUN_IPv4Header)) ||
1255          (ip4->version != 4) ||
1256          (ip4->header_length != sizeof (struct GNUNET_TUN_IPv4Header) / 4) ||
1257          (ntohs(ip4->total_length) != msize) ||
1258          (ip4->protocol != IPPROTO_UDP) )
1259     {
1260       /* non-IP/UDP packet received on TUN (or with options) */
1261       GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1262                   _("Received malformed IPv4-UDP packet on TUN interface.\n"));
1263       return;
1264     }
1265     udp = (const struct GNUNET_TUN_UdpHeader*) &ip4[1];
1266     msize -= sizeof (struct GNUNET_TUN_IPv4Header);
1267     break;
1268   case ETH_P_IPV6:
1269     ip6 = (const struct GNUNET_TUN_IPv6Header *) &tun[1];
1270     if ( (msize < sizeof (struct GNUNET_TUN_IPv6Header)) ||
1271          (ip6->version != 6) ||
1272          (ntohs (ip6->payload_length) != msize) ||
1273          (ip6->next_header != IPPROTO_UDP) )
1274     {
1275       /* non-IP/UDP packet received on TUN (or with extensions) */
1276       GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1277                   _("Received malformed IPv6-UDP packet on TUN interface.\n"));
1278       return;
1279     }
1280     udp = (const struct GNUNET_TUN_UdpHeader*) &ip6[1];
1281     msize -= sizeof (struct GNUNET_TUN_IPv6Header);
1282     break;
1283   default:
1284     /* non-IP packet received on TUN!? */
1285     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1286                 _("Got non-IP packet with %u bytes and protocol %u from TUN\n"),
1287                 (unsigned int) msize,
1288                 ntohs (tun->proto));
1289     return;
1290   }
1291   if (msize <= sizeof (struct GNUNET_TUN_UdpHeader) + sizeof (struct GNUNET_TUN_DnsHeader))
1292   {    
1293     /* non-DNS packet received on TUN, ignore */
1294     GNUNET_STATISTICS_update (stats,
1295                               gettext_noop ("# Non-DNS UDP packet received via TUN interface"),
1296                               1, GNUNET_NO);
1297     return;
1298   }
1299   msize -= sizeof (struct GNUNET_TUN_UdpHeader);
1300   dns = (const struct GNUNET_TUN_DnsHeader*) &udp[1];
1301   rr = &requests[dns->id];
1302
1303   /* clean up from previous request */
1304   GNUNET_free_non_null (rr->payload);
1305   rr->payload = NULL;
1306   GNUNET_array_grow (rr->client_wait_list,
1307                      rr->client_wait_list_length,
1308                      0);
1309
1310   /* setup new request */
1311   rr->phase = RP_INIT;
1312   switch (ntohs (tun->proto))
1313   {
1314   case ETH_P_IPV4:
1315     {
1316       srca4 = (struct sockaddr_in*) &rr->src_addr;
1317       dsta4 = (struct sockaddr_in*) &rr->dst_addr;
1318       memset (srca4, 0, sizeof (struct sockaddr_in));
1319       memset (dsta4, 0, sizeof (struct sockaddr_in));
1320       srca4->sin_family = AF_INET;
1321       dsta4->sin_family = AF_INET;
1322       srca4->sin_addr = ip4->source_address;
1323       dsta4->sin_addr = ip4->destination_address;
1324       srca4->sin_port = udp->source_port;
1325       dsta4->sin_port = udp->destination_port;
1326 #if HAVE_SOCKADDR_IN_SIN_LEN
1327       srca4->sin_len = sizeof (struct sockaddr_in))
1328       dsta4->sin_len = sizeof (struct sockaddr_in);
1329 #endif
1330     }
1331     break;
1332   case ETH_P_IPV6:
1333     {
1334       srca6 = (struct sockaddr_in6*) &rr->src_addr;
1335       dsta6 = (struct sockaddr_in6*) &rr->dst_addr;
1336       memset (srca6, 0, sizeof (struct sockaddr_in6));
1337       memset (dsta6, 0, sizeof (struct sockaddr_in6));
1338       srca6->sin6_family = AF_INET6;
1339       dsta6->sin6_family = AF_INET6;
1340       srca6->sin6_addr = ip6->source_address;
1341       dsta6->sin6_addr = ip6->destination_address;
1342       srca6->sin6_port = udp->source_port;
1343       dsta6->sin6_port = udp->destination_port;
1344 #if HAVE_SOCKADDR_IN_SIN_LEN
1345       srca6->sin6_len = sizeof (struct sockaddr_in6);
1346       dsta6->sin6_len = sizeof (struct sockaddr_in6);
1347 #endif
1348     }
1349   break;
1350   default:
1351     GNUNET_assert (0);
1352   }
1353   rr->payload = GNUNET_malloc (msize);
1354   rr->payload_length = msize;
1355   memcpy (rr->payload, dns, msize);
1356   rr->request_id = dns->id | (request_id_gen << 16);
1357   request_id_gen++;
1358
1359   GNUNET_STATISTICS_update (stats,
1360                             gettext_noop ("# DNS requests received via TUN interface"),
1361                             1, GNUNET_NO);
1362   /* start request processing state machine */
1363   next_phase (rr);
1364 }
1365
1366
1367 /**
1368  * Process a request via mesh to perform a DNS query.
1369  *
1370  * @param cls closure, NULL
1371  * @param tunnel connection to the other end
1372  * @param tunnel_ctx pointer to our 'struct TunnelState *'
1373  * @param sender who sent the message
1374  * @param message the actual message
1375  * @param atsi performance data for the connection
1376  * @return GNUNET_OK to keep the connection open,
1377  *         GNUNET_SYSERR to close it (signal serious error)
1378  */
1379 static int
1380 receive_dns_request (void *cls GNUNET_UNUSED, struct GNUNET_MESH_Tunnel *tunnel,
1381                      void **tunnel_ctx,
1382                      const struct GNUNET_PeerIdentity *sender GNUNET_UNUSED,
1383                      const struct GNUNET_MessageHeader *message,
1384                      const struct GNUNET_ATS_Information *atsi GNUNET_UNUSED)
1385 {
1386   struct TunnelState *ts = *tunnel_ctx;
1387   const struct GNUNET_TUN_DnsHeader *dns;
1388   size_t mlen = ntohs (message->size);
1389   size_t dlen = mlen - sizeof (struct GNUNET_MessageHeader);
1390   char buf[dlen];
1391   struct GNUNET_TUN_DnsHeader *dout;
1392   struct sockaddr_in v4;
1393   struct sockaddr_in6 v6;
1394   struct sockaddr *so;
1395   socklen_t salen;
1396
1397   if (dlen < sizeof (struct GNUNET_TUN_DnsHeader))
1398   {
1399     GNUNET_break_op (0);
1400     return GNUNET_SYSERR;
1401   }
1402   dns = (const struct GNUNET_TUN_DnsHeader *) &message[1];
1403   ts->original_id = dns->id;
1404   if (tunnels[ts->my_id] == ts)
1405     tunnels[ts->my_id] = NULL;
1406   ts->my_id = (uint16_t) GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, 
1407                                                    UINT16_MAX + 1);
1408   tunnels[ts->my_id] = ts;
1409   memcpy (buf, dns, dlen);
1410   dout = (struct GNUNET_TUN_DnsHeader*) buf;
1411   dout->id = ts->my_id;
1412   
1413   memset (&v4, 0, sizeof (v4));
1414   memset (&v6, 0, sizeof (v6));
1415   if (1 == inet_pton (AF_INET, dns_exit, &v4.sin_addr))
1416   {
1417     salen = sizeof (v4);
1418     v4.sin_family = AF_INET;
1419     v4.sin_port = htons (53);
1420 #if HAVE_SOCKADDR_IN_SIN_LEN
1421     v4.sin_len = (u_char) salen;
1422 #endif
1423     so = (struct sockaddr *) &v4;
1424     ts->dnsout = get_request_socket (AF_INET);
1425   } 
1426   if (1 == inet_pton (AF_INET6, dns_exit, &v6.sin6_addr))
1427   {
1428     salen = sizeof (v6);
1429     v6.sin6_family = AF_INET6;
1430     v6.sin6_port = htons (53);
1431 #if HAVE_SOCKADDR_IN_SIN_LEN
1432     v6.sin6_len = (u_char) salen;
1433 #endif
1434     so = (struct sockaddr *) &v6;
1435     ts->dnsout = get_request_socket (AF_INET6);
1436   }  
1437   if (NULL == ts->dnsout)
1438   {
1439     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1440                 _("Configured DNS exit `%s' is not working / valid.\n"),
1441                 dns_exit);
1442     return GNUNET_SYSERR;
1443   }
1444   memcpy (&ts->addr,
1445           so,
1446           salen);
1447   ts->addrlen = salen;
1448   GNUNET_NETWORK_socket_sendto (ts->dnsout,
1449                                 buf, dlen, so, salen); 
1450   ts->timeout = GNUNET_TIME_relative_to_absolute (REQUEST_TIMEOUT);
1451   return GNUNET_OK;
1452 }
1453
1454
1455 /**
1456  * Callback from GNUNET_MESH for new tunnels.
1457  *
1458  * @param cls closure
1459  * @param tunnel new handle to the tunnel
1460  * @param initiator peer that started the tunnel
1461  * @param ats performance information for the tunnel
1462  * @return initial tunnel context for the tunnel
1463  */
1464 static void *
1465 accept_dns_tunnel (void *cls GNUNET_UNUSED, struct GNUNET_MESH_Tunnel *tunnel,
1466                    const struct GNUNET_PeerIdentity *initiator GNUNET_UNUSED,
1467                    const struct GNUNET_ATS_Information *ats GNUNET_UNUSED)
1468 {
1469   struct TunnelState *ts = GNUNET_malloc (sizeof (struct TunnelState));
1470
1471   GNUNET_STATISTICS_update (stats,
1472                             gettext_noop ("# Inbound MESH tunnels created"),
1473                             1, GNUNET_NO);
1474   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1475               "Received inbound tunnel from `%s'\n",
1476               GNUNET_i2s (initiator));
1477   ts->tunnel = tunnel;
1478   return ts;
1479 }
1480
1481
1482 /**
1483  * Function called by mesh whenever an inbound tunnel is destroyed.
1484  * Should clean up any associated state.
1485  *
1486  * @param cls closure (set from GNUNET_MESH_connect)
1487  * @param tunnel connection to the other end (henceforth invalid)
1488  * @param tunnel_ctx place where local state associated
1489  *                   with the tunnel is stored
1490  */
1491 static void
1492 destroy_dns_tunnel (void *cls GNUNET_UNUSED, 
1493                     const struct GNUNET_MESH_Tunnel *tunnel,
1494                     void *tunnel_ctx)
1495 {
1496   struct TunnelState *ts = tunnel_ctx;
1497
1498   if (tunnels[ts->my_id] == ts)
1499     tunnels[ts->my_id] = NULL;
1500   if (NULL != ts->th)
1501     GNUNET_MESH_notify_transmit_ready_cancel (ts->th);
1502   GNUNET_free_non_null (ts->reply);
1503   GNUNET_free (ts);
1504 }
1505
1506
1507 /**
1508  * @param cls closure
1509  * @param server the initialized server
1510  * @param cfg_ configuration to use
1511  */
1512 static void
1513 run (void *cls, struct GNUNET_SERVER_Handle *server,
1514      const struct GNUNET_CONFIGURATION_Handle *cfg_)
1515 {
1516   static const struct GNUNET_SERVER_MessageHandler handlers[] = {
1517     /* callback, cls, type, size */
1518     {&handle_client_init, NULL, GNUNET_MESSAGE_TYPE_DNS_CLIENT_INIT, 
1519      sizeof (struct GNUNET_DNS_Register)},
1520     {&handle_client_response, NULL, GNUNET_MESSAGE_TYPE_DNS_CLIENT_RESPONSE, 0},
1521     {NULL, NULL, 0, 0}
1522   };
1523   char *ifc_name;
1524   char *ipv4addr;
1525   char *ipv4mask;
1526   char *ipv6addr;
1527   char *ipv6prefix;
1528   struct in_addr dns_exit4;
1529   struct in6_addr dns_exit6;
1530
1531   cfg = cfg_;
1532   stats = GNUNET_STATISTICS_create ("dns", cfg);
1533   nc = GNUNET_SERVER_notification_context_create (server, 1);
1534   GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &cleanup_task,
1535                                 cls);
1536   if ( (GNUNET_YES ==
1537         GNUNET_CONFIGURATION_get_value_yesno (cfg_, "dns", "PROVIDE_EXIT")) &&
1538        ( (GNUNET_OK !=
1539           GNUNET_CONFIGURATION_get_value_string (cfg, "dns", 
1540                                                  "DNS_EXIT",
1541                                                  &dns_exit)) ||
1542          ( (1 != inet_pton (AF_INET, dns_exit, &dns_exit4)) &&
1543            (1 != inet_pton (AF_INET6, dns_exit, &dns_exit6)) ) ) )
1544     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1545                 _("Configured to provide DNS exit, but no valid DNS server configured!\n"));
1546
1547   helper_argv[0] = GNUNET_strdup ("gnunet-dns");
1548   if (GNUNET_SYSERR ==
1549       GNUNET_CONFIGURATION_get_value_string (cfg, "dns", "IFNAME", &ifc_name))
1550   {
1551     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1552                 "No entry 'IFNAME' in configuration!\n");
1553     GNUNET_SCHEDULER_shutdown ();
1554     return;
1555   }
1556   helper_argv[1] = ifc_name;
1557   if ( (GNUNET_SYSERR ==
1558         GNUNET_CONFIGURATION_get_value_string (cfg, "dns", "IPV6ADDR",
1559                                                &ipv6addr)) )
1560   {
1561     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1562                 "No entry 'IPV6ADDR' in configuration!\n");
1563     GNUNET_SCHEDULER_shutdown ();
1564     return;
1565   }
1566   helper_argv[2] = ipv6addr;
1567   if (GNUNET_SYSERR ==
1568       GNUNET_CONFIGURATION_get_value_string (cfg, "dns", "IPV6PREFIX",
1569                                              &ipv6prefix))
1570   {
1571     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1572                 "No entry 'IPV6PREFIX' in configuration!\n");
1573     GNUNET_SCHEDULER_shutdown ();
1574     return;
1575   }
1576   helper_argv[3] = ipv6prefix;
1577
1578   if (GNUNET_SYSERR ==
1579       GNUNET_CONFIGURATION_get_value_string (cfg, "dns", "IPV4ADDR",
1580                                              &ipv4addr))
1581   {
1582     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1583                 "No entry 'IPV4ADDR' in configuration!\n");
1584     GNUNET_SCHEDULER_shutdown ();
1585     return;
1586   }
1587   helper_argv[4] = ipv4addr;
1588   if (GNUNET_SYSERR ==
1589       GNUNET_CONFIGURATION_get_value_string (cfg, "dns", "IPV4MASK",
1590                                              &ipv4mask))
1591   {
1592     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1593                 "No entry 'IPV4MASK' in configuration!\n");
1594     GNUNET_SCHEDULER_shutdown ();
1595     return;
1596   }
1597   helper_argv[5] = ipv4mask;
1598   helper_argv[6] = NULL;
1599
1600   if (NULL != dns_exit)
1601   {
1602     static struct GNUNET_MESH_MessageHandler mesh_handlers[] = {
1603       {&receive_dns_request, GNUNET_MESSAGE_TYPE_VPN_DNS_TO_INTERNET, 0},
1604       {NULL, 0, 0}
1605     };
1606     static GNUNET_MESH_ApplicationType mesh_types[] = {
1607       GNUNET_APPLICATION_TYPE_INTERNET_RESOLVER,
1608       GNUNET_APPLICATION_TYPE_END
1609     };
1610     mesh = GNUNET_MESH_connect (cfg,
1611                                 1, NULL,
1612                                 &accept_dns_tunnel, 
1613                                 &destroy_dns_tunnel,
1614                                 mesh_handlers,
1615                                 mesh_types);
1616   }
1617   hijacker = GNUNET_HELPER_start ("gnunet-helper-dns",
1618                                   helper_argv,
1619                                   &process_helper_messages,
1620                                   NULL);
1621   GNUNET_SERVER_add_handlers (server, handlers);
1622   GNUNET_SERVER_disconnect_notify (server, &client_disconnect, NULL);
1623 }
1624
1625
1626 /**
1627  * The main function for the dns service.
1628  *
1629  * @param argc number of arguments from the command line
1630  * @param argv command line arguments
1631  * @return 0 ok, 1 on error
1632  */
1633 int
1634 main (int argc, char *const *argv)
1635 {
1636   return (GNUNET_OK ==
1637           GNUNET_SERVICE_run (argc, argv, "dns", GNUNET_SERVICE_OPTION_NONE,
1638                               &run, NULL)) ? 0 : 1;
1639 }
1640
1641
1642 /* end of gnunet-service-dns.c */