gnunet-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[GNUnet-SVN] r19180 - gnunet/src/pt


From: gnunet
Subject: [GNUnet-SVN] r19180 - gnunet/src/pt
Date: Mon, 16 Jan 2012 21:00:28 +0100

Author: grothoff
Date: 2012-01-16 21:00:28 +0100 (Mon, 16 Jan 2012)
New Revision: 19180

Modified:
   gnunet/src/pt/gnunet-daemon-pt.c
Log:
-finishing first implementation of protocol translation daemon

Modified: gnunet/src/pt/gnunet-daemon-pt.c
===================================================================
--- gnunet/src/pt/gnunet-daemon-pt.c    2012-01-16 19:21:48 UTC (rev 19179)
+++ gnunet/src/pt/gnunet-daemon-pt.c    2012-01-16 20:00:28 UTC (rev 19180)
@@ -23,6 +23,10 @@
  * @brief tool to manipulate DNS and VPN services to perform protocol 
translation (IPvX over GNUnet)
  * @author Christian Grothoff
  *
+ * TODO:
+ * - add statistics
+ * - add logging?
+ * - figure out how/where/when/who tunnels DNS over mesh when necessary!
  */
 #include "platform.h"
 #include "gnunet_util_lib.h"
@@ -33,6 +37,76 @@
 
 
 /**
+ * After how long do we time out if we could not get an IP from VPN?
+ */
+#define TIMEOUT GNUNET_TIME_UNIT_MINUTES
+
+
+/**
+ * Which group of DNS records are we currently processing?
+ */
+enum RequestGroup
+  {
+    /**
+     * DNS answers
+     */
+    ANSWERS = 0, 
+
+    /**
+     * DNS authority records
+     */
+    AUTHORITY_RECORDS = 1,
+
+    /**
+     * DNS additional records
+     */
+    ADDITIONAL_RECORDS = 2,
+    /**
+     * We're done processing.
+     */
+    END = 3
+  };
+
+
+/**
+ * Information tracked per DNS request that we are processing.
+ */
+struct RequestContext
+{
+  /**
+   * Handle to submit the final result.
+   */
+  struct GNUNET_DNS_RequestHandle *rh;
+  
+  /**
+   * DNS packet that is being modified.
+   */
+  struct GNUNET_DNSPARSER_Packet *dns;
+
+  /**
+   * Active redirection request with the VPN.
+   */
+  struct GNUNET_VPN_RedirectionRequest *rr;
+
+  /**
+   * Record for which we have an active redirection request.
+   */
+  struct GNUNET_DNSPARSER_Record *rec;
+
+  /**
+   * Offset in the current record group that is being modified.
+   */
+  unsigned int offset;
+
+  /**
+   * Group that is being modified
+   */
+  enum RequestGroup group;
+  
+};
+
+
+/**
  * The handle to the configuration used throughout the process
  */
 static const struct GNUNET_CONFIGURATION_Handle *cfg;
@@ -64,6 +138,202 @@
 
 
 /**
+ * We're done modifying all records in the response.  Submit the reply
+ * and free the resources of the rc.
+ *
+ * @param rc context to process
+ */
+static void
+finish_request (struct RequestContext *rc)
+{
+  char *buf;
+  size_t buf_len;
+
+  if (GNUNET_SYSERR ==
+      GNUNET_DNSPARSER_pack (rc->dns,
+                            16 * 1024,
+                            &buf,
+                            &buf_len))
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+               _("Failed to pack DNS request.  Dropping.\n"));
+    GNUNET_DNS_request_drop (rc->rh);
+  }
+  else
+  {
+    GNUNET_DNS_request_answer (rc->rh,
+                              buf_len, buf);
+    GNUNET_free (buf);
+  }
+  GNUNET_DNSPARSER_free_packet (rc->dns);
+  GNUNET_free (rc);
+}
+
+
+/**
+ * Process the next record of the given request context.
+ * When done, submit the reply and free the resources of
+ * the rc.
+ *
+ * @param rc context to process
+ */
+static void
+submit_request (struct RequestContext *rc);
+
+
+/**
+ * Callback invoked from the VPN service once a redirection is
+ * available.  Provides the IP address that can now be used to
+ * reach the requested destination.  We substitute the active
+ * record and then continue with 'submit_request' to look at
+ * the other records.
+ *
+ * @param cls our 'struct RequestContext'
+ * @param af address family, AF_INET or AF_INET6; AF_UNSPEC on error;
+ *                will match 'result_af' from the request
+ * @param address IP address (struct in_addr or struct in_addr6, depending on 
'af')
+ *                that the VPN allocated for the redirection;
+ *                traffic to this IP will now be redirected to the 
+ *                specified target peer; NULL on error
+ */
+static void
+vpn_allocation_callback (void *cls,
+                        int af,
+                        const void *address)
+{
+  struct RequestContext *rc = cls;
+
+  rc->rr = NULL;
+  if (af == AF_UNSPEC)
+  {
+    GNUNET_DNS_request_drop (rc->rh);
+    GNUNET_DNSPARSER_free_packet (rc->dns);
+    GNUNET_free (rc);
+    return;
+  }
+  switch (rc->rec->type)
+    {
+  case GNUNET_DNSPARSER_TYPE_A:
+    GNUNET_assert (AF_INET == af);
+    memcpy (rc->rec->data.raw.data, address, sizeof (struct in_addr));
+    break;
+  case GNUNET_DNSPARSER_TYPE_AAAA:
+    GNUNET_assert (AF_INET6 == af);
+    memcpy (rc->rec->data.raw.data, address, sizeof (struct in6_addr));
+    break;
+  default:
+    GNUNET_assert (0);
+    return;
+  }
+  rc->rec = NULL;
+  submit_request (rc);
+}
+
+
+/**
+ * Modify the given DNS record by asking VPN to create a tunnel
+ * to the given address.  When done, continue with submitting
+ * other records from the request context ('submit_request' is
+ * our continuation).
+ *
+ * @param rc context to process
+ * @param rec record to modify
+ */
+static void
+modify_address (struct RequestContext *rc,
+               struct GNUNET_DNSPARSER_Record *rec)
+{
+  int af;
+
+  switch (rec->type)
+  {
+  case GNUNET_DNSPARSER_TYPE_A:
+    af = AF_INET;
+    GNUNET_assert (rec->data.raw.data_len == sizeof (struct in_addr));
+    break;
+  case GNUNET_DNSPARSER_TYPE_AAAA:
+    af = AF_INET6;
+    GNUNET_assert (rec->data.raw.data_len == sizeof (struct in6_addr));
+    break;
+  default:
+    GNUNET_assert (0);
+    return;
+  }
+  rc->rec = rec;
+  rc->rr = GNUNET_VPN_redirect_to_ip (vpn_handle,
+                                     af, af,
+                                     rec->data.raw.data,
+                                     GNUNET_NO /* nac */,
+                                     GNUNET_TIME_relative_to_absolute 
(TIMEOUT),
+                                     &vpn_allocation_callback,
+                                     rc);
+}
+
+
+/**
+ * Process the next record of the given request context.
+ * When done, submit the reply and free the resources of
+ * the rc.
+ *
+ * @param rc context to process
+ */
+static void
+submit_request (struct RequestContext *rc)
+{
+  struct GNUNET_DNSPARSER_Record *ra;
+  unsigned int ra_len;
+  unsigned int i;
+
+  while (1)
+  {
+    switch (rc->group)
+    {
+    case ANSWERS:
+      ra = rc->dns->answers;
+      ra_len = rc->dns->num_answers;
+      break;
+    case AUTHORITY_RECORDS:
+      ra = rc->dns->authority_records;
+      ra_len = rc->dns->num_authority_records;
+      break;
+    case ADDITIONAL_RECORDS:
+      ra = rc->dns->additional_records;
+      ra_len = rc->dns->num_additional_records;
+      break;
+    case END:
+      finish_request (rc);
+      return;
+    default:
+      GNUNET_assert (0);      
+    }
+    for (i=rc->offset;i<ra_len;i++)
+    {
+      switch (ra[i].type)
+      {
+      case GNUNET_DNSPARSER_TYPE_A:
+       if (ipv4_pt)
+       {
+         rc->offset = i + 1;
+         modify_address (rc, &ra[i]);
+         return;
+       }
+       break;
+      case GNUNET_DNSPARSER_TYPE_AAAA:
+       if (ipv6_pt)
+       {
+         rc->offset = i + 1;
+         modify_address (rc, &ra[i]);
+         return;
+       }
+       break;
+      }
+    }
+    rc->group++;
+  }
+}
+
+
+/**
  * Test if any of the given records need protocol-translation work.
  *
  * @param ra array of records
@@ -124,6 +394,7 @@
                     const char *request)
 {
   struct GNUNET_DNSPARSER_Packet *dns;
+  struct RequestContext *rc;
   int work;
 
   dns = GNUNET_DNSPARSER_parse (request, request_length);
@@ -143,7 +414,12 @@
     GNUNET_DNS_request_forward (rh);
     return;
   }
-  /* FIXME: translate A/AAAA records using VPN! */
+  rc = GNUNET_malloc (sizeof (struct RequestContext));
+  rc->rh = rh;
+  rc->dns = dns;
+  rc->offset = 0;
+  rc->group = ANSWERS;
+  submit_request (rc);
 }
 
 




reply via email to

[Prev in Thread] Current Thread [Next in Thread]