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