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