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