update tests to use new MQ API
[oweals/gnunet.git] / src / dns / gnunet-service-dns.c
index b7ecee0d78abd00c2b48ecc99a2a81b60cd8b861..b580f433fc851872a83b400c26758eb0e09bc4ec 100644 (file)
@@ -1,6 +1,6 @@
 /*
      This file is part of GNUnet.
-     (C) 2012 Christian Grothoff (and other contributing authors)
+     Copyright (C) 2012 GNUnet e.V.
 
      GNUnet is free software; you can redistribute it and/or modify
      it under the terms of the GNU General Public License as published
@@ -14,8 +14,8 @@
 
      You should have received a copy of the GNU General Public License
      along with GNUnet; see the file COPYING.  If not, write to the
-     Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-     Boston, MA 02111-1307, USA.
+     Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+     Boston, MA 02110-1301, USA.
 */
 
 /**
@@ -34,7 +34,7 @@
  * each request will be given one of 128 random source ports, and the
  * 128 random source ports will also change "often" (less often if the
  * system is very busy, each time if we are mostly idle).  At the same
- * time, the system will never use more than 256 UDP sockets.  
+ * time, the system will never use more than 256 UDP sockets.
  */
 #include "platform.h"
 #include "gnunet_util_lib.h"
@@ -88,7 +88,7 @@ enum RequestPhase
    * Global Internet query is now pending.
    */
   RP_INTERNET_DNS,
-  
+
   /**
    * Client (or global DNS request) has resulted in a response.
    * Forward to all POST-RESOLUTION clients.  If client list is empty,
@@ -111,22 +111,22 @@ enum RequestPhase
 
 /**
  * Entry we keep for each client.
- */ 
+ */
 struct ClientRecord
 {
   /**
    * Kept in doubly-linked list.
-   */ 
+   */
   struct ClientRecord *next;
 
   /**
    * Kept in doubly-linked list.
-   */ 
+   */
   struct ClientRecord *prev;
 
   /**
    * Handle to the client.
-   */ 
+   */
   struct GNUNET_SERVER_Client *client;
 
   /**
@@ -139,7 +139,7 @@ struct ClientRecord
 
 /**
  * Entry we keep for each active request.
- */ 
+ */
 struct RequestRecord
 {
 
@@ -180,7 +180,7 @@ struct RequestRecord
 
   /**
    * Number of bytes in payload.
-   */ 
+   */
   size_t payload_length;
 
   /**
@@ -219,7 +219,7 @@ static struct GNUNET_HELPER_Handle *hijacker;
 /**
  * Command-line arguments we are giving to the hijacker process.
  */
-static char *helper_argv[7];
+static char *helper_argv[8];
 
 /**
  * Head of DLL of clients we consult.
@@ -273,17 +273,18 @@ cleanup_rr (struct RequestRecord *rr)
  * Task run during shutdown.
  *
  * @param cls unused
- * @param tc unused
  */
 static void
-cleanup_task (void *cls GNUNET_UNUSED,
-              const struct GNUNET_SCHEDULER_TaskContext *tc)
+cleanup_task (void *cls GNUNET_UNUSED)
 {
   unsigned int i;
 
-  GNUNET_HELPER_stop (hijacker);
-  hijacker = NULL;
-  for (i=0;i<7;i++)
+  if (NULL != hijacker)
+  {
+    GNUNET_HELPER_stop (hijacker, GNUNET_NO);
+    hijacker = NULL;
+  }
+  for (i=0;i<8;i++)
     GNUNET_free_non_null (helper_argv[i]);
   for (i=0;i<=UINT16_MAX;i++)
     cleanup_rr (&requests[i]);
@@ -317,7 +318,7 @@ request_done (struct RequestRecord *rr)
 
   GNUNET_array_grow (rr->client_wait_list,
                     rr->client_wait_list_length,
-                    0); 
+                    0);
   if (RP_RESPONSE_MONITOR != rr->phase)
   {
     /* no response, drop */
@@ -330,7 +331,7 @@ request_done (struct RequestRecord *rr)
 
   LOG (GNUNET_ERROR_TYPE_DEBUG,
        "Transmitting response for request %llu\n",
-       (unsigned long long) rr->request_id);  
+       (unsigned long long) rr->request_id);
   /* send response via hijacker */
   reply_len = sizeof (struct GNUNET_MessageHeader);
   reply_len += sizeof (struct GNUNET_TUN_Layer2PacketHeader);
@@ -345,7 +346,7 @@ request_done (struct RequestRecord *rr)
   default:
     GNUNET_break (0);
     cleanup_rr (rr);
-    return;   
+    return;
   }
   reply_len += sizeof (struct GNUNET_TUN_UdpHeader);
   reply_len += rr->payload_length;
@@ -354,7 +355,7 @@ request_done (struct RequestRecord *rr)
     /* response too big, drop */
     GNUNET_break (0); /* how can this be? */
     cleanup_rr(rr);
-    return;    
+    return;
   }
   {
     char buf[reply_len] GNUNET_ALIGN;
@@ -374,7 +375,7 @@ request_done (struct RequestRecord *rr)
 
       tun.flags = htons (0);
       if (rr->src_addr.ss_family == AF_INET)
-       tun.proto = htons (ETH_P_IPV4); 
+       tun.proto = htons (ETH_P_IPV4);
       else
        tun.proto = htons (ETH_P_IPV6);
       memcpy (&buf[off], &tun, sizeof (struct GNUNET_TUN_Layer2PacketHeader));
@@ -388,7 +389,7 @@ request_done (struct RequestRecord *rr)
       {
        struct sockaddr_in *src = (struct sockaddr_in *) &rr->src_addr;
        struct sockaddr_in *dst = (struct sockaddr_in *) &rr->dst_addr;
-       
+
        source_port = dst->sin_port;
        destination_port = src->sin_port;
        GNUNET_TUN_initialize_ipv4_header (&ip4,
@@ -483,14 +484,14 @@ send_request_to_client (struct RequestRecord *rr,
   }
   LOG (GNUNET_ERROR_TYPE_DEBUG,
        "Sending information about request %llu to local client\n",
-       (unsigned long long) rr->request_id);  
+       (unsigned long long) rr->request_id);
   req = (struct GNUNET_DNS_Request*) buf;
   req->header.type = htons (GNUNET_MESSAGE_TYPE_DNS_CLIENT_REQUEST);
   req->header.size = htons (sizeof (buf));
   req->reserved = htonl (0);
   req->request_id = rr->request_id;
   memcpy (&req[1], rr->payload, rr->payload_length);
-  GNUNET_SERVER_notification_context_unicast (nc, 
+  GNUNET_SERVER_notification_context_unicast (nc,
                                              client,
                                              &req->header,
                                              GNUNET_NO);
@@ -541,8 +542,8 @@ next_phase (struct RequestRecord *rr)
       nz = (int) j;
       break;
     }
-  }  
-  if (-1 != nz) 
+  }
+  if (-1 != nz)
   {
     send_request_to_client (rr, rr->client_wait_list[nz]->client);
     return;
@@ -551,7 +552,7 @@ next_phase (struct RequestRecord *rr)
   LOG (GNUNET_ERROR_TYPE_DEBUG,
        "Request %llu now in phase %d\n",
        rr->request_id,
-       rr->phase);  
+       rr->phase);
   switch (rr->phase)
   {
   case RP_INIT:
@@ -647,7 +648,7 @@ next_phase (struct RequestRecord *rr)
  *
  * @param cls unused
  * @param client handle of client that disconnected
- */ 
+ */
 static void
 client_disconnect (void *cls, struct GNUNET_SERVER_Client *client)
 {
@@ -674,7 +675,7 @@ client_disconnect (void *cls, struct GNUNET_SERVER_Client *client)
          if (rr->client_wait_list[j] == cr)
          {
            rr->client_wait_list[j] = NULL;
-           next_phase (rr); 
+           next_phase (rr);
          }
        }
       }
@@ -714,8 +715,8 @@ process_dns_result (void *cls,
                              gettext_noop ("# External DNS response discarded (no matching request)"),
                              1, GNUNET_NO);
     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-               "Received DNS reply that does not match any pending request.  Dropping.\n"); 
-    return; 
+               "Received DNS reply that does not match any pending request.  Dropping.\n");
+    return;
   }
   LOG (GNUNET_ERROR_TYPE_DEBUG,
        "Got a response from the stub resolver for DNS request %llu intercepted locally!\n",
@@ -736,16 +737,16 @@ process_dns_result (void *cls,
  * @param message the init message (unused)
  */
 static void
-handle_client_init (void *cls GNUNET_UNUSED, 
+handle_client_init (void *cls GNUNET_UNUSED,
                    struct GNUNET_SERVER_Client *client,
                    const struct GNUNET_MessageHeader *message)
 {
   struct ClientRecord *cr;
   const struct GNUNET_DNS_Register *reg = (const struct GNUNET_DNS_Register*) message;
 
-  cr = GNUNET_malloc (sizeof (struct ClientRecord));
+  cr = GNUNET_new (struct ClientRecord);
   cr->client = client;
-  cr->flags = (enum GNUNET_DNS_Flags) ntohl (reg->flags);  
+  cr->flags = (enum GNUNET_DNS_Flags) ntohl (reg->flags);
   GNUNET_SERVER_client_keep (client);
   GNUNET_CONTAINER_DLL_insert (clients_head,
                               clients_tail,
@@ -763,7 +764,7 @@ handle_client_init (void *cls GNUNET_UNUSED,
  * @param message the response
  */
 static void
-handle_client_response (void *cls GNUNET_UNUSED, 
+handle_client_response (void *cls GNUNET_UNUSED,
                        struct GNUNET_SERVER_Client *client,
                        const struct GNUNET_MessageHeader *message)
 {
@@ -816,7 +817,7 @@ handle_client_response (void *cls GNUNET_UNUSED,
       {
        GNUNET_break (0);
        GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
-       next_phase (rr); 
+       next_phase (rr);
        return;
       }
       GNUNET_free_non_null (rr->payload);
@@ -835,7 +836,7 @@ handle_client_response (void *cls GNUNET_UNUSED,
       /* if query changed to answer, move past DNS resolution phase... */
       if ( (RP_QUERY == rr->phase) &&
           (rr->payload_length > sizeof (struct GNUNET_TUN_DnsHeader)) &&
-          ((struct GNUNET_DNSPARSER_Flags*)&(((struct GNUNET_TUN_DnsHeader*) rr->payload)->flags))->query_or_response == 1)
+          ((struct GNUNET_TUN_DnsFlags*)&(((struct GNUNET_TUN_DnsHeader*) rr->payload)->flags))->query_or_response == 1)
       {
        rr->phase = RP_INTERNET_DNS;
        GNUNET_array_grow (rr->client_wait_list,
@@ -844,9 +845,9 @@ handle_client_response (void *cls GNUNET_UNUSED,
       }
       break;
     }
-    next_phase (rr); 
+    next_phase (rr);
     GNUNET_SERVER_receive_done (client, GNUNET_OK);
-    return;      
+    return;
   }
   /* odd, client was not on our list for the request, that ought
      to be an error */
@@ -936,7 +937,7 @@ process_helper_messages (void *cls GNUNET_UNUSED, void *client,
   }
   if ( (msize <= sizeof (struct GNUNET_TUN_UdpHeader) + sizeof (struct GNUNET_TUN_DnsHeader)) ||
        (DNS_PORT != ntohs (udp->destination_port)) )
-  {    
+  {
     /* non-DNS packet received on TUN, ignore */
     GNUNET_STATISTICS_update (stats,
                              gettext_noop ("# Non-DNS UDP packet received via TUN interface"),
@@ -1025,7 +1026,7 @@ run (void *cls, struct GNUNET_SERVER_Handle *server,
 {
   static const struct GNUNET_SERVER_MessageHandler handlers[] = {
     /* callback, cls, type, size */
-    {&handle_client_init, NULL, GNUNET_MESSAGE_TYPE_DNS_CLIENT_INIT, 
+    {&handle_client_init, NULL, GNUNET_MESSAGE_TYPE_DNS_CLIENT_INIT,
      sizeof (struct GNUNET_DNS_Register)},
     {&handle_client_response, NULL, GNUNET_MESSAGE_TYPE_DNS_CLIENT_RESPONSE, 0},
     {NULL, NULL, 0, 0}
@@ -1039,38 +1040,51 @@ run (void *cls, struct GNUNET_SERVER_Handle *server,
   struct in6_addr dns_exit6;
   char *dns_exit;
   char *binary;
+  int nortsetup;
 
   cfg = cfg_;
-  binary = GNUNET_OS_get_libexec_binary_path ("gnunet-helper-dns");
-  if (GNUNET_YES !=
-      GNUNET_OS_check_helper_binary (binary, GNUNET_YES, NULL))
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-               _("`%s' must be installed SUID, refusing to run\n"),
-               binary);
-    global_ret = 1;
-    GNUNET_free (binary);
-    return;
-  }
-  GNUNET_free (binary);
   stats = GNUNET_STATISTICS_create ("dns", cfg);
   nc = GNUNET_SERVER_notification_context_create (server, 1);
-  GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &cleanup_task,
-                                cls);
+  GNUNET_SCHEDULER_add_shutdown (&cleanup_task,
+                                cls);
   dns_exit = NULL;
   if ( ( (GNUNET_OK !=
-         GNUNET_CONFIGURATION_get_value_string (cfg, "dns", 
+         GNUNET_CONFIGURATION_get_value_string (cfg,
+                                                 "dns",
                                                 "DNS_EXIT",
                                                 &dns_exit)) ||
         ( (1 != inet_pton (AF_INET, dns_exit, &dns_exit4)) &&
           (1 != inet_pton (AF_INET6, dns_exit, &dns_exit6)) ) ) )
   {
-    GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, "dns", "DNS_EXIT",
+    GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
+                               "dns",
+                               "DNS_EXIT",
                               _("need a valid IPv4 or IPv6 address\n"));
     GNUNET_free_non_null (dns_exit);
     dns_exit = NULL;
   }
   dnsstub = GNUNET_DNSSTUB_start (dns_exit);
+  GNUNET_free_non_null (dns_exit);
+  GNUNET_SERVER_add_handlers (server,
+                              handlers);
+  GNUNET_SERVER_disconnect_notify (server,
+                                   &client_disconnect,
+                                   NULL);
+  binary = GNUNET_OS_get_libexec_binary_path ("gnunet-helper-dns");
+  if (GNUNET_YES !=
+      GNUNET_OS_check_helper_binary (binary,
+                                     GNUNET_YES,
+                                     NULL)) // TODO: once we have a windows-testcase, add test parameters here
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+               _("`%s' must be installed SUID, will not run DNS interceptor\n"),
+               binary);
+    global_ret = 1;
+    GNUNET_free (binary);
+    return;
+  }
+  GNUNET_free (binary);
+
   helper_argv[0] = GNUNET_strdup ("gnunet-dns");
   if (GNUNET_SYSERR ==
       GNUNET_CONFIGURATION_get_value_string (cfg, "dns", "IFNAME", &ifc_name))
@@ -1122,14 +1136,20 @@ run (void *cls, struct GNUNET_SERVER_Handle *server,
     return;
   }
   helper_argv[5] = ipv4mask;
-  helper_argv[6] = NULL;
+
+  nortsetup = GNUNET_CONFIGURATION_get_value_yesno (cfg, "dns",
+                                                     "SKIP_ROUTING_SETUP");
+  if (GNUNET_YES == nortsetup)
+    helper_argv[6] = GNUNET_strdup("1");
+  else
+    helper_argv[6] = GNUNET_strdup("0");
+
+  helper_argv[7] = NULL;
   hijacker = GNUNET_HELPER_start (GNUNET_NO,
                                  "gnunet-helper-dns",
                                  helper_argv,
                                  &process_helper_messages,
                                  NULL, NULL);
-  GNUNET_SERVER_add_handlers (server, handlers);
-  GNUNET_SERVER_disconnect_notify (server, &client_disconnect, NULL);
 }
 
 
@@ -1157,8 +1177,8 @@ main (int argc, char *const *argv)
             strerror (errno));
   }
   else if (sgid != rgid)
-  {    
-    if (-1 ==  setregid (sgid, sgid))
+  {
+    if (-1 == setregid (sgid, sgid))
       fprintf (stderr, "setregid failed: %s\n", strerror (errno));
   }
 #endif