Add VPN resolution
authorMartin Schanzenbach <mschanzenbach@posteo.de>
Sat, 16 Jun 2012 09:44:58 +0000 (09:44 +0000)
committerMartin Schanzenbach <mschanzenbach@posteo.de>
Sat, 16 Jun 2012 09:44:58 +0000 (09:44 +0000)
src/gns/Makefile.am
src/gns/gnunet-service-gns_resolver.c
src/gns/gnunet-service-gns_resolver.h
src/include/gnunet_gns_service.h

index 2e5aa193ab723c375a964fc950b8fc63bdf5130e..a65ab994b6f9b4982104af760514104f1c971bc0 100644 (file)
@@ -226,6 +226,7 @@ gnunet_service_gns_LDADD = \
        $(top_builddir)/src/dns/libgnunetdnsparser.la \
        $(top_builddir)/src/dht/libgnunetdht.la \
        $(top_builddir)/src/namestore/libgnunetnamestore.la \
+       $(top_builddir)/src/vpn/libgnunetvpn.la \
   $(GN_LIBINTL)
 gnunet_service_gns_DEPENDENCIES = \
   $(top_builddir)/src/statistics/libgnunetstatistics.la \
@@ -233,7 +234,8 @@ gnunet_service_gns_DEPENDENCIES = \
        $(top_builddir)/src/dns/libgnunetdns.la \
        $(top_builddir)/src/dns/libgnunetdnsparser.la \
        $(top_builddir)/src/dht/libgnunetdht.la \
-       $(top_builddir)/src/namestore/libgnunetnamestore.la
+       $(top_builddir)/src/namestore/libgnunetnamestore.la \
+       $(top_builddir)/src/vpn/libgnunetvpn.la
 
 
 gnunet_gns_fcfsd_SOURCES = \
index 3d58c33f68a9a107528c8b9433782def0ba34bab..6e20c3f9cf1e2f6f4a41a46a80992efa8bfa9397 100644 (file)
@@ -31,6 +31,7 @@
 #include "gnunet_dns_service.h"
 #include "gnunet_dht_service.h"
 #include "gnunet_namestore_service.h"
+#include "gnunet_vpn_service.h"
 #include "gnunet_dns_service.h"
 #include "gnunet_dnsparser_lib.h"
 #include "gnunet_gns_service.h"
  */
 static struct GNUNET_NAMESTORE_Handle *namestore_handle;
 
+/**
+ * Our handle to the vpn service
+ */
+static struct GNUNET_VPN_Handle *vpn_handle;
+
 /**
  * Resolver handle to the dht
  */
@@ -1165,12 +1171,203 @@ process_record_result_ns(void* cls,
 }
 
 
+/**
+ * VPN redirect result callback
+ *
+ * @param cls the resolver handle
+ * @param af the requested address family
+ * @param address in_addr(6) respectively
+ */
+static void
+process_record_result_vpn (void* cls, int af, const void *address)
+{
+  struct ResolverHandle *rh = cls;
+  struct RecordLookupHandle *rlh;
+  struct GNUNET_NAMESTORE_RecordData rd;
+
+  rlh = (struct RecordLookupHandle *)rh->proc_cls;
+
+  GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
+             "GNS_PHASE_REC_VPN-%d: Got answer from VPN to query!\n",
+             rh->id);
+  if (af == AF_INET)
+  {
+    GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
+               "GNS_PHASE_REC-%d: Answer is IPv4!\n",
+               rh->id);
+    if (rlh->record_type != GNUNET_GNS_RECORD_TYPE_A)
+    {
+      GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
+                 "GNS_PHASE_REC-%d: Requested record is not IPv4!\n",
+                 rh->id);
+      rh->proc (rh->proc_cls, rh, 0, NULL);
+      return;
+    }
+    rd.record_type = GNUNET_GNS_RECORD_TYPE_A;
+    rd.expiration = GNUNET_TIME_UNIT_FOREVER_ABS;
+    rd.data = address;
+    rd.data_size = sizeof (struct in_addr);
+    rd.flags = 0;
+    rh->proc (rh->proc_cls, rh, 1, &rd);
+    return;
+  }
+  else if (af == AF_INET6)
+  {
+    GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
+               "GNS_PHASE_REC-%d: Answer is IPv6!\n",
+               rh->id);
+    if (rlh->record_type != GNUNET_GNS_RECORD_AAAA)
+    {
+      GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
+                 "GNS_PHASE_REC-%d: Requested record is not IPv6!\n",
+                 rh->id);
+      rh->proc (rh->proc_cls, rh, 0, NULL);
+      return;
+    }
+    rd.record_type = GNUNET_GNS_RECORD_AAAA;
+    rd.expiration = GNUNET_TIME_UNIT_FOREVER_ABS;
+    rd.data = address;
+    rd.data_size = sizeof (struct in6_addr);
+    rd.flags = 0;
+    rh->proc (rh->proc_cls, rh, 1, &rd);
+    return;
+  }
+  
+  GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
+             "GNS_PHASE_REC-%d: Got garbage from VPN!\n",
+             rh->id);
+  rh->proc (rh->proc_cls, rh, 0, NULL);
+}
+
+
+/**
+ * finish lookup
+ *
+ * @param rh resolver handle
+ * @param rlh record lookup handle
+ * @param rd_cound number of results
+ * @param rd results
+ */
+static void
+finish_lookup(struct ResolverHandle *rh,
+              struct RecordLookupHandle* rlh,
+              unsigned int rd_count,
+              const struct GNUNET_NAMESTORE_RecordData *rd);
+
+/**
+ * Process VPN lookup result for record
+ *
+ * @param cls the record lookup handle
+ * @param rh resolver handle
+ * @param rd_count number of results (1)
+ * @param rd record data containing the result
+ */
+static void
+handle_record_vpn (void* cls, struct ResolverHandle *rh,
+                   unsigned int rd_count,
+                   const struct GNUNET_NAMESTORE_RecordData *rd)
+{
+  struct RecordLookupHandle* rlh = (struct RecordLookupHandle*) cls;
+  
+  if (rd_count == 0)
+  {
+    GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
+               "GNS_PHASE_REC_VPN-%d: VPN returned no records. (status: %d)!\n",
+               rh->id,
+               rh->status);
+    /* give up, cannot resolve */
+    finish_lookup(rh, rlh, 0, NULL);
+    free_resolver_handle(rh);
+    return;
+  }
+
+  /* results found yay */
+  GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
+             "GNS_PHASE_REC_VPN-%d: Record resolved from VPN!", rh->id);
+
+  finish_lookup(rh, rlh, rd_count, rd);
+
+  free_resolver_handle(rh);
+}
+
+
+/**
+ * The final phase of resoution.
+ * We found a VPN RR and want to request an IPv4/6 address
+ *
+ * @param rh the pending lookup handle
+ * @param rd_count length of record data
+ * @param rd record data containing VPN RR
+ */
+static void
+resolve_record_vpn (struct ResolverHandle *rh,
+                    int rd_count,
+                    const struct GNUNET_NAMESTORE_RecordData *rd)
+{
+  int af;
+  int proto;
+  struct GNUNET_HashCode peer_id;
+  struct GNUNET_CRYPTO_HashAsciiEncoded s_pid;
+  struct GNUNET_HashCode serv_desc;
+  struct GNUNET_CRYPTO_HashAsciiEncoded s_sd;
+  
+  /* We cancel here as to not include the ns lookup in the timeout */
+  if (rh->timeout_task != GNUNET_SCHEDULER_NO_TASK)
+  {
+    GNUNET_SCHEDULER_cancel(rh->timeout_task);
+    rh->timeout_task = GNUNET_SCHEDULER_NO_TASK;
+  }
+  /* Start shortening */
+  if ((rh->priv_key != NULL) && is_canonical (rh->name))
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+             "GNS_PHASE_REC_VPN-%llu: Trying to shorten authority chain\n",
+             rh->id);
+             start_shorten (rh->authority_chain_tail,
+             rh->priv_key);
+  }
+
+  /* Extracting VPN information FIXME rd parsing with NS API?*/
+  if (4 != SSCANF ((char*)rd, "%d:%d:%s:%s", &af, &proto,
+                   (char*)&s_pid, (char*)&s_sd))
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "GNS_PHASE_REC_VPN-%llu: Error parsing VPN RR!\n",
+                rh->id);
+    rh->proc(rh->proc_cls, rh, 0, NULL);
+    return;
+  }
+
+  if ((GNUNET_OK != GNUNET_CRYPTO_hash_from_string ((char*)&s_pid, &peer_id)) ||
+      (GNUNET_OK != GNUNET_CRYPTO_hash_from_string ((char*)&s_sd, &serv_desc)))
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "GNS_PHASE_REC_VPN-%llu: Error parsing VPN RR hashes!\n",
+                rh->id);
+    rh->proc(rh->proc_cls, rh, 0, NULL);
+    return;
+  }
+
+  rh->proc = &handle_record_vpn;
+  
+  //FIXME timeout??
+  rh->vpn_handle = GNUNET_VPN_redirect_to_peer (vpn_handle,
+                                          af, proto,
+                                          (struct GNUNET_PeerIdentity*)&peer_id,
+                                          &serv_desc,
+                                          GNUNET_NO, //nac
+                                          GNUNET_TIME_UNIT_FOREVER_ABS, //FIXME
+                                          &process_record_result_vpn,
+                                          rh);
+
+}
+
 /**
  * The final phase of resolution.
  * rh->name is a name that is canonical and we do not have a delegation.
  * Query namestore for this record
  *
- * @param rh the pending lookup
+ * @param rh the pending lookup handle
  */
 static void
 resolve_record_ns(struct ResolverHandle *rh)
@@ -1665,6 +1862,8 @@ handle_record_dht(void* cls, struct ResolverHandle *rh,
 }
 
 
+
+
 /**
  * Process namestore lookup result for record.
  *
@@ -1674,9 +1873,9 @@ handle_record_dht(void* cls, struct ResolverHandle *rh,
  * @param rd record data
  */
 static void
-handle_record_ns(void* cls, struct ResolverHandle *rh,
-                       unsigned int rd_count,
-                       const struct GNUNET_NAMESTORE_RecordData *rd)
+handle_record_ns (void* cls, struct ResolverHandle *rh,
+                  unsigned int rd_count,
+                  const struct GNUNET_NAMESTORE_RecordData *rd)
 {
   struct RecordLookupHandle* rlh;
   rlh = (struct RecordLookupHandle*) cls;
@@ -1956,9 +2155,25 @@ handle_delegation_ns(void* cls, struct ResolverHandle *rh,
     GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
               "GNS_PHASE_DELEGATE_NS-%llu: Resolved full name for delegation.\n",
               rh->id);
-    strcpy(rh->name, "+\0");
-    rh->proc = &handle_record_ns;
-    resolve_record_ns(rh);
+
+    if (rh->status & RSL_DELEGATE_VPN)
+    {
+      GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
+             "GNS_PHASE_DELEGATE_NS-%llu: VPN delegation starting.\n",
+             rh->id);
+      GNUNET_assert (NULL != rd);
+      rh->proc = &handle_record_vpn;
+      resolve_record_vpn (rh, rd_count, rd);
+    }
+    else
+    {
+      GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
+                 "GNS_PHASE_DELEGATE_NS-%llu: Resolving record +\n",
+                 rh->id);
+      strcpy(rh->name, "+\0");
+      rh->proc = &handle_record_ns;
+      resolve_record_ns(rh);
+    }
     return;
   }
 
@@ -2118,6 +2333,18 @@ process_delegation_result_ns(void* cls,
   int i;
   for (i=0; i<rd_count;i++)
   {
+    /**
+     * Redirect via VPN
+     */
+    if (rd[i].record_type == GNUNET_GNS_RECORD_VPN)
+    {
+      GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
+                 "GNS_PHASE_DELEGATE_NS-%llu: VPNRR found.\n",
+                 rh->id);
+      rh->status |= RSL_DELEGATE_VPN;
+      rh->proc(rh->proc_cls, rh, rd_count, rd);
+      return;
+    }
   
     if (rd[i].record_type != GNUNET_GNS_RECORD_PKEY)
       continue;
@@ -2127,8 +2354,8 @@ process_delegation_result_ns(void* cls,
     {
       GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
       "GNS_PHASE_DELEGATE_NS-%llu: PKEY for %s is pending user confirmation.\n",
-        name,
-        rh->id);
+        rh->id,
+        name);
       continue;
     }
     
index 1b54d3c2ce3f2f14ba0e68911c19a4db520aaf61..8387e1166f05309b987d4efe6c95d4e4e0c1df09 100644 (file)
@@ -93,7 +93,8 @@ enum ResolutionStatus
 {
   RSL_RECORD_EXISTS = 1,
   RSL_RECORD_EXPIRED = 2,
-  RSL_TIMED_OUT = 4
+  RSL_TIMED_OUT = 4,
+  RSL_DELEGATE_VPN = 8
 };
 
 /**
@@ -129,6 +130,9 @@ struct ResolverHandle
   /* timeout set for this lookup task */
   struct GNUNET_TIME_Relative timeout;
 
+  /* a handle to a vpn request */
+  struct GNUNET_VPN_RedirectionRequest *vpn_handle;
+
   /* timeout task for the lookup */
   GNUNET_SCHEDULER_TaskIdentifier timeout_task;
 
index 5bebee633cddca4fa7cb14c9462ce028ecbe495f..827b6a482a88a673c4fe05fb513921c521e4c7df 100644 (file)
@@ -80,7 +80,8 @@ enum GNUNET_GNS_RecordType
   GNUNET_GNS_RECORD_PKEY = GNUNET_NAMESTORE_TYPE_PKEY,
   GNUNET_GNS_RECORD_PSEU = GNUNET_NAMESTORE_TYPE_PSEU,
   GNUNET_GNS_RECORD_ANY  = GNUNET_NAMESTORE_TYPE_ANY,
-  GNUNET_GNS_RECORD_LEHO = GNUNET_NAMESTORE_TYPE_LEHO
+  GNUNET_GNS_RECORD_LEHO = GNUNET_NAMESTORE_TYPE_LEHO,
+  GNUNET_GNS_RECORD_VPN
 };
 
 /**