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