docu
[oweals/gnunet.git] / src / dns / gnunet-service-dns.c
index b6d5a1967c2a8c0468ae2218f6a7c7146a7abb2d..d1689f4d2dc85c82ee072b544162831cf1592b27 100644 (file)
 #include "gnunet_dns_service.h"
 #include "gnunet_dnsparser_lib.h"
 #include "gnunet_dnsstub_lib.h"
-#include "gnunet_mesh_service.h"
 #include "gnunet_statistics_service.h"
 #include "gnunet_tun_lib.h"
 
+/**
+ * Port number for DNS
+ */
+#define DNS_PORT 53
+
+
+/**
+ * Generic logging shorthand
+ */
+#define LOG(kind, ...)                          \
+  GNUNET_log_from (kind, "dns", __VA_ARGS__);
+
 
 /**
  * Phases each request goes through.
@@ -185,50 +196,6 @@ struct RequestRecord
 };
 
 
-/**
- * State we keep for each DNS tunnel that terminates at this node.
- */
-struct TunnelState
-{
-
-  /**
-   * Associated MESH tunnel.
-   */
-  struct GNUNET_MESH_Tunnel *tunnel;
-
-  /**
-   * Active request for sending a reply.
-   */
-  struct GNUNET_MESH_TransmitHandle *th;
-
-  /**
-   * DNS reply ready for transmission.
-   */
-  char *reply;
-
-  /**
-   * Socket we are using to transmit this request (must match if we receive
-   * a response).
-   */
-  struct GNUNET_DNSSTUB_RequestSocket *rs;
-
-  /**
-   * Number of bytes in 'reply'.
-   */
-  size_t reply_length;
-
-  /**
-   * Original DNS request ID as used by the client.
-   */
-  uint16_t original_id;
-
-  /**
-   * DNS request ID that we used for forwarding.
-   */
-  uint16_t my_id;
-};
-
-
 /**
  * Global return value from 'main'.
  */
@@ -269,11 +236,6 @@ static struct ClientRecord *clients_tail;
  */
 static struct GNUNET_SERVER_NotificationContext *nc;
 
-/**
- * Array of all open requests from tunnels.
- */
-static struct TunnelState *tunnels[UINT16_MAX + 1];
-
 /**
  * Array of all open requests.
  */
@@ -284,12 +246,6 @@ static struct RequestRecord requests[UINT16_MAX + 1];
  */
 static uint64_t request_id_gen;
 
-/**
- * Handle to the MESH service (for receiving DNS queries), or NULL 
- * if we are not a DNS exit.
- */
-static struct GNUNET_MESH_Handle *mesh;
-
 /**
  * Handle to the DNS Stub resolver.
  */
@@ -343,11 +299,6 @@ cleanup_task (void *cls GNUNET_UNUSED,
     GNUNET_DNSSTUB_stop (dnsstub);
     dnsstub = NULL;
   }
-  if (NULL != mesh)
-  {
-    GNUNET_MESH_disconnect(mesh);
-    mesh = NULL;
-  }
 }
 
 
@@ -370,10 +321,16 @@ request_done (struct RequestRecord *rr)
   if (RP_RESPONSE_MONITOR != rr->phase)
   {
     /* no response, drop */
+    LOG (GNUNET_ERROR_TYPE_DEBUG,
+        "Got no response for request %llu, dropping\n",
+        (unsigned long long) rr->request_id);
     cleanup_rr (rr);
     return;
   }
-  
+
+  LOG (GNUNET_ERROR_TYPE_DEBUG,
+       "Transmitting response for request %llu\n",
+       (unsigned long long) rr->request_id);  
   /* send response via hijacker */
   reply_len = sizeof (struct GNUNET_MessageHeader);
   reply_len += sizeof (struct GNUNET_TUN_Layer2PacketHeader);
@@ -524,6 +481,9 @@ send_request_to_client (struct RequestRecord *rr,
     cleanup_rr (rr);
     return;
   }
+  LOG (GNUNET_ERROR_TYPE_DEBUG,
+       "Sending information about request %llu to local client\n",
+       (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));
@@ -588,6 +548,10 @@ next_phase (struct RequestRecord *rr)
     return;
   }
   /* done with current phase, advance! */
+  LOG (GNUNET_ERROR_TYPE_DEBUG,
+       "Request %llu now in phase %d\n",
+       rr->request_id,
+       rr->phase);  
   switch (rr->phase)
   {
   case RP_INIT:
@@ -721,53 +685,6 @@ client_disconnect (void *cls, struct GNUNET_SERVER_Client *client)
 }
 
 
-/**
- * We got a reply from DNS for a request of a MESH tunnel.  Send it
- * via the tunnel (after changing the request ID back).
- *
- * @param cls the 'struct TunnelState'
- * @param size number of bytes available in buf
- * @param buf where to copy the reply
- * @return number of bytes written to buf
- */
-static size_t
-transmit_reply_to_mesh (void *cls,
-                       size_t size,
-                       void *buf)
-{
-  struct TunnelState *ts = cls;
-  size_t off;
-  size_t ret;
-  char *cbuf = buf;
-  struct GNUNET_MessageHeader hdr;
-  struct GNUNET_TUN_DnsHeader dns;
-
-  ts->th = NULL;
-  GNUNET_assert (ts->reply != NULL);
-  if (size == 0)
-    return 0;
-  ret = sizeof (struct GNUNET_MessageHeader) + ts->reply_length; 
-  GNUNET_assert (ret <= size);
-  hdr.size = htons (ret);
-  hdr.type = htons (GNUNET_MESSAGE_TYPE_VPN_DNS_FROM_INTERNET);
-  memcpy (&dns, ts->reply, sizeof (dns));
-  dns.id = ts->original_id;
-  off = 0;
-  memcpy (&cbuf[off], &hdr, sizeof (hdr));
-  off += sizeof (hdr);
-  memcpy (&cbuf[off], &dns, sizeof (dns));
-  off += sizeof (dns);
-  memcpy (&cbuf[off], &ts->reply[sizeof (dns)], ts->reply_length - sizeof (dns));
-  off += ts->reply_length - sizeof (dns);
-  GNUNET_free (ts->reply);
-  ts->reply = NULL;
-  ts->reply_length = 0;  
-  GNUNET_assert (ret == off);
-  return ret;
-}
-
-
-
 /**
  * Callback called from DNSSTUB resolver when a resolution
  * succeeded.
@@ -784,45 +701,25 @@ process_dns_result (void *cls,
                    size_t r)
 {
   struct RequestRecord *rr;
-  struct TunnelState *ts;
-    
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+             "Processing DNS result from stub resolver\n");
   GNUNET_assert (NULL == cls);
-  /* Handle case that this is a reply to a request from a MESH DNS tunnel */
-  ts = tunnels[dns->id];
-  if ( (NULL == ts) ||
-       (ts->rs != rs) )
-    ts = NULL; /* DNS responder address missmatch */
-  if (NULL != ts)
-    {
-      tunnels[dns->id] = NULL;
-      GNUNET_free_non_null (ts->reply);
-      ts->reply = GNUNET_malloc (r);
-      ts->reply_length = r;
-      memcpy (ts->reply, dns, r);
-      if (ts->th != NULL)
-       GNUNET_MESH_notify_transmit_ready_cancel (ts->th);
-      ts->th = GNUNET_MESH_notify_transmit_ready (ts->tunnel,
-                                                 GNUNET_NO,
-                                                 GNUNET_TIME_UNIT_FOREVER_REL,
-                                                 NULL,
-                                                 sizeof (struct GNUNET_MessageHeader) + r,
-                                                 &transmit_reply_to_mesh,
-                                                 ts);
-    }
-  /* Handle case that this is a reply to a local request (intercepted from TUN interface) */
   rr = &requests[dns->id];
   if ( (rr->phase != RP_INTERNET_DNS) ||
        (rr->rs != rs) )
-    {
-      if (NULL == ts)
-       {
-         /* unexpected / bogus reply */
-         GNUNET_STATISTICS_update (stats,
-                                   gettext_noop ("# External DNS response discarded (no matching request)"),
-                                   1, GNUNET_NO);
-       }
-      return; 
-    }
+  {
+    /* unexpected / bogus reply */
+    GNUNET_STATISTICS_update (stats,
+                             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; 
+  }
+  LOG (GNUNET_ERROR_TYPE_DEBUG,
+       "Got a response from the stub resolver for DNS request %llu intercepted locally!\n",
+       (unsigned long long) rr->request_id);
   GNUNET_free_non_null (rr->payload);
   rr->payload = GNUNET_malloc (r);
   memcpy (rr->payload, dns, r);
@@ -886,6 +783,9 @@ handle_client_response (void *cls GNUNET_UNUSED,
   resp = (const struct GNUNET_DNS_Response*) message;
   off = (uint16_t) resp->request_id;
   rr = &requests[off];
+  LOG (GNUNET_ERROR_TYPE_DEBUG,
+       "Received DNS response with ID %llu from local client!\n",
+       (unsigned long long) resp->request_id);
   if (rr->request_id != resp->request_id)
   {
     GNUNET_STATISTICS_update (stats,
@@ -979,6 +879,8 @@ process_helper_messages (void *cls GNUNET_UNUSED, void *client,
   struct sockaddr_in *dsta4;
   struct sockaddr_in6 *dsta6;
 
+  LOG (GNUNET_ERROR_TYPE_DEBUG,
+       "Intercepted message via DNS hijacker\n");
   msize = ntohs (message->size);
   if (msize < sizeof (struct GNUNET_MessageHeader) + sizeof (struct GNUNET_TUN_Layer2PacketHeader) + sizeof (struct GNUNET_TUN_IPv4Header))
   {
@@ -1032,7 +934,8 @@ process_helper_messages (void *cls GNUNET_UNUSED, void *client,
                ntohs (tun->proto));
     return GNUNET_OK;
   }
-  if (msize <= sizeof (struct GNUNET_TUN_UdpHeader) + sizeof (struct GNUNET_TUN_DnsHeader))
+  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,
@@ -1099,7 +1002,9 @@ process_helper_messages (void *cls GNUNET_UNUSED, void *client,
   memcpy (rr->payload, dns, msize);
   rr->request_id = dns->id | (request_id_gen << 16);
   request_id_gen++;
-
+  LOG (GNUNET_ERROR_TYPE_DEBUG,
+       "Creating new DNS request %llu\n",
+       (unsigned long long) rr->request_id);
   GNUNET_STATISTICS_update (stats,
                            gettext_noop ("# DNS requests received via TUN interface"),
                            1, GNUNET_NO);
@@ -1109,109 +1014,6 @@ process_helper_messages (void *cls GNUNET_UNUSED, void *client,
 }
 
 
-/**
- * Process a request via mesh to perform a DNS query.
- *
- * @param cls closure, NULL
- * @param tunnel connection to the other end
- * @param tunnel_ctx pointer to our 'struct TunnelState *'
- * @param sender who sent the message
- * @param message the actual message
- * @param atsi performance data for the connection
- * @return GNUNET_OK to keep the connection open,
- *         GNUNET_SYSERR to close it (signal serious error)
- */
-static int
-receive_dns_request (void *cls GNUNET_UNUSED, struct GNUNET_MESH_Tunnel *tunnel,
-                     void **tunnel_ctx,
-                     const struct GNUNET_PeerIdentity *sender GNUNET_UNUSED,
-                     const struct GNUNET_MessageHeader *message,
-                     const struct GNUNET_ATS_Information *atsi GNUNET_UNUSED)
-{
-  struct TunnelState *ts = *tunnel_ctx;
-  const struct GNUNET_TUN_DnsHeader *dns;
-  size_t mlen = ntohs (message->size);
-  size_t dlen = mlen - sizeof (struct GNUNET_MessageHeader);
-  char buf[dlen] GNUNET_ALIGN;
-  struct GNUNET_TUN_DnsHeader *dout;
-  if (dlen < sizeof (struct GNUNET_TUN_DnsHeader))
-  {
-    GNUNET_break_op (0);
-    return GNUNET_SYSERR;
-  }
-  dns = (const struct GNUNET_TUN_DnsHeader *) &message[1];
-  ts->original_id = dns->id;
-  if (tunnels[ts->my_id] == ts)
-    tunnels[ts->my_id] = NULL;
-  ts->my_id = (uint16_t) GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, 
-                                                  UINT16_MAX + 1);
-  tunnels[ts->my_id] = ts;
-  memcpy (buf, dns, dlen);
-  dout = (struct GNUNET_TUN_DnsHeader *) buf;
-  dout->id = ts->my_id;
-  ts->rs = GNUNET_DNSSTUB_resolve2 (dnsstub,
-                                   buf, dlen,
-                                   &process_dns_result,
-                                   NULL);
-  if (NULL == ts->rs)
-    return GNUNET_SYSERR;
-  return GNUNET_OK;
-}
-
-
-/**
- * Callback from GNUNET_MESH for new tunnels.
- *
- * @param cls closure
- * @param tunnel new handle to the tunnel
- * @param initiator peer that started the tunnel
- * @param ats performance information for the tunnel
- * @return initial tunnel context for the tunnel
- */
-static void *
-accept_dns_tunnel (void *cls GNUNET_UNUSED, struct GNUNET_MESH_Tunnel *tunnel,
-                  const struct GNUNET_PeerIdentity *initiator GNUNET_UNUSED,
-                  const struct GNUNET_ATS_Information *ats GNUNET_UNUSED)
-{
-  struct TunnelState *ts = GNUNET_malloc (sizeof (struct TunnelState));
-
-  GNUNET_STATISTICS_update (stats,
-                           gettext_noop ("# Inbound MESH tunnels created"),
-                           1, GNUNET_NO);
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-             "Received inbound tunnel from `%s'\n",
-             GNUNET_i2s (initiator));
-  ts->tunnel = tunnel;
-  return ts;
-}
-
-
-/**
- * Function called by mesh whenever an inbound tunnel is destroyed.
- * Should clean up any associated state.
- *
- * @param cls closure (set from GNUNET_MESH_connect)
- * @param tunnel connection to the other end (henceforth invalid)
- * @param tunnel_ctx place where local state associated
- *                   with the tunnel is stored
- */
-static void
-destroy_dns_tunnel (void *cls GNUNET_UNUSED, 
-                   const struct GNUNET_MESH_Tunnel *tunnel,
-                   void *tunnel_ctx)
-{
-  struct TunnelState *ts = tunnel_ctx;
-
-  if (tunnels[ts->my_id] == ts)
-    tunnels[ts->my_id] = NULL;
-  if (NULL != ts->th)
-    GNUNET_MESH_notify_transmit_ready_cancel (ts->th);
-  GNUNET_free_non_null (ts->reply);
-  GNUNET_free (ts);
-}
-
-
 /**
  * @param cls closure
  * @param server the initialized server
@@ -1236,34 +1038,35 @@ run (void *cls, struct GNUNET_SERVER_Handle *server,
   struct in_addr dns_exit4;
   struct in6_addr dns_exit6;
   char *dns_exit;
+  char *binary;
 
   cfg = cfg_;
+  binary = GNUNET_OS_get_libexec_binary_path ("gnunet-helper-dns");
   if (GNUNET_YES !=
-      GNUNET_OS_check_helper_binary ("gnunet-helper-dns"))
+      GNUNET_OS_check_helper_binary (binary))
   {
     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
                _("`%s' must be installed SUID, refusing to run\n"),
-               "gnunet-helper-dns");
+               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);
   dns_exit = NULL;
-  if ( (GNUNET_YES ==
-       GNUNET_CONFIGURATION_get_value_yesno (cfg_, "dns", "PROVIDE_EXIT")) &&
-       ( (GNUNET_OK !=
+  if ( ( (GNUNET_OK !=
          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 (GNUNET_ERROR_TYPE_ERROR,
-               _("Configured to provide DNS exit, but no valid DNS server configured!\n"));
+    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;
   }
@@ -1320,24 +1123,6 @@ run (void *cls, struct GNUNET_SERVER_Handle *server,
   }
   helper_argv[5] = ipv4mask;
   helper_argv[6] = NULL;
-
-  if (NULL != dns_exit)
-  {
-    static struct GNUNET_MESH_MessageHandler mesh_handlers[] = {
-      {&receive_dns_request, GNUNET_MESSAGE_TYPE_VPN_DNS_TO_INTERNET, 0},
-      {NULL, 0, 0}
-    };
-    static GNUNET_MESH_ApplicationType mesh_types[] = {
-      GNUNET_APPLICATION_TYPE_INTERNET_RESOLVER,
-      GNUNET_APPLICATION_TYPE_END
-    };
-    mesh = GNUNET_MESH_connect (cfg,
-                               NULL,
-                               &accept_dns_tunnel, 
-                               &destroy_dns_tunnel,
-                               mesh_handlers,
-                               mesh_types);
-  }
   hijacker = GNUNET_HELPER_start (GNUNET_NO,
                                  "gnunet-helper-dns",
                                  helper_argv,