-fix tld guessing code
[oweals/gnunet.git] / src / gns / gnunet-service-gns_resolver.c
index 51a316202016bec4c11bf964827d51c1597a59cd..11ea5a993d233e26b5a20f7b9a893aa158e373cc 100644 (file)
@@ -35,6 +35,7 @@
 #include "gnunet_dnsparser_lib.h"
 #include "gns_protocol.h"
 #include "gnunet_gns_service.h"
+#include "gns_common.h"
 #include "block_gns.h"
 #include "gns.h"
 #include "gnunet-service-gns_resolver.h"
@@ -176,38 +177,51 @@ is_srv (char* name)
 }
 
 /**
- * Determine if this name is canonical.
- * i.e.
- * a.b.gnunet  = not canonical
- * a           = canonical
+ * Determine if this name is canonical (is a legal name in a zone, without delegation);
+ * note that we do not test that the name does not contain illegal characters, we only
+ * test for delegation.  Note that service records (i.e. _foo._srv) are canonical names
+ * even though they consist of multiple labels.
+ *
+ * Examples:
+ * a.b.gads  = not canonical
+ * a         = canonical
+ * _foo._srv = canonical
+ * _f.bar    = not canonical
  *
  * @param name the name to test
  * @return GNUNET_YES if canonical
  */
 static int
-is_canonical (char* name)
+is_canonical (const char* name)
 {
-  char* ndup;
-  char* tok;
-
-  ndup = GNUNET_strdup (name);
-  strtok (ndup, ".");
+  const char *pos;
+  const char *dot;
 
-  for (tok = strtok (NULL, "."); tok != NULL; tok = strtok (NULL, "."))
-  {
-    /*
-     * probably srv
-     */
-    if (*tok == '_')
-      continue;
-    GNUNET_free (ndup);
+  if (NULL == strchr (name, '.'))
+    return GNUNET_YES;
+  if ('_' != name[0])
     return GNUNET_NO;
-  }
-  GNUNET_free (ndup);
+  pos = &name[1];
+  while (NULL != (dot = strchr (pos, '.')))    
+    if ('_' != dot[1])
+      return GNUNET_NO;
+    else
+      pos = dot + 1;
   return GNUNET_YES;
 }
 
 
+static void
+free_get_pseu_authority_handle (struct GetPseuAuthorityHandle *gph)
+{
+  gph->namestore_task = NULL;
+  GNUNET_free (gph->auth);
+  GNUNET_CRYPTO_rsa_key_free (gph->key);
+  GNUNET_CONTAINER_DLL_remove (gph_head, gph_tail, gph);
+  GNUNET_free (gph);
+}
+
+
 /**
  * Callback that shortens authorities
  *
@@ -228,13 +242,9 @@ static void
 create_pkey_cont (void* cls, int32_t success, const char* emsg)
 {
   //FIXME do sth with error
-  struct GetPseuAuthorityHandle* gph = (struct GetPseuAuthorityHandle*)cls;
+  struct GetPseuAuthorityHandle* gph = cls;
 
-  gph->namestore_task = NULL;
-  GNUNET_free (gph->auth);
-  GNUNET_CRYPTO_rsa_key_free (gph->key);
-  GNUNET_CONTAINER_DLL_remove (gph_head, gph_tail, gph);
-  GNUNET_free (gph);
+  free_get_pseu_authority_handle (gph);
 }
 
 
@@ -252,13 +262,13 @@ create_pkey_cont (void* cls, int32_t success, const char* emsg)
  */
 static void
 process_pseu_lookup_ns (void* cls,
-                      const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *key,
-                      struct GNUNET_TIME_Absolute expiration,
-                      const char *name, unsigned int rd_count,
-                      const struct GNUNET_NAMESTORE_RecordData *rd,
-                      const struct GNUNET_CRYPTO_RsaSignature *signature)
+                       const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *key,
+                       struct GNUNET_TIME_Absolute expiration,
+                       const char *name, unsigned int rd_count,
+                       const struct GNUNET_NAMESTORE_RecordData *rd,
+                       const struct GNUNET_CRYPTO_RsaSignature *signature)
 {
-  struct GetPseuAuthorityHandle* gph = (struct GetPseuAuthorityHandle*)cls;
+  struct GetPseuAuthorityHandle* gph = cls;
   struct GNUNET_NAMESTORE_RecordData new_pkey;
 
   gph->namestore_task = NULL;
@@ -266,10 +276,7 @@ process_pseu_lookup_ns (void* cls,
   {
     GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
                "GNS_AUTO_PSEU: Name %s already taken in NS!\n", name);
-    GNUNET_free (gph->auth);
-    GNUNET_CRYPTO_rsa_key_free (gph->key);
-    GNUNET_CONTAINER_DLL_remove (gph_head, gph_tail, gph);
-    GNUNET_free (gph);
+    free_get_pseu_authority_handle (gph);
     return;
   }
 
@@ -285,11 +292,11 @@ process_pseu_lookup_ns (void* cls,
                  | GNUNET_NAMESTORE_RF_PRIVATE
                  | GNUNET_NAMESTORE_RF_PENDING;
   gph->namestore_task = GNUNET_NAMESTORE_record_create (namestore_handle,
-                                  gph->key,
-                                  gph->test_name,
-                                  &new_pkey,
-                                  &create_pkey_cont, //cont
-                                  gph); //cls
+                                                       gph->key,
+                                                       gph->test_name,
+                                                       &new_pkey,
+                                                       &create_pkey_cont, 
+                                                       gph);
 }
 
 /**
@@ -305,15 +312,11 @@ process_pseu_result (struct GetPseuAuthorityHandle* gph, char* name)
   {
     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
                 "GNS_AUTO_PSEU: No PSEU, no shorten. Finished.\n");
-    GNUNET_free (gph->auth);
-    GNUNET_CRYPTO_rsa_key_free (gph->key);
-    GNUNET_CONTAINER_DLL_remove (gph_head, gph_tail, gph);
-    GNUNET_free (gph);
+    free_get_pseu_authority_handle (gph);
     return;
   }
   
-  memcpy (gph->test_name, name, strlen(name)+1);
-
+  memcpy (gph->test_name, name, strlen(name) + 1);
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
               "GNS_AUTO_PSEU: Checking %s for collision in NS\n",
               gph->test_name);
@@ -321,13 +324,14 @@ process_pseu_result (struct GetPseuAuthorityHandle* gph, char* name)
    * Check for collision
    */
   gph->namestore_task = GNUNET_NAMESTORE_lookup_record (namestore_handle,
-                                  &gph->our_zone,
-                                  gph->test_name,
-                                  GNUNET_NAMESTORE_TYPE_ANY,
-                                  &process_pseu_lookup_ns,
-                                  gph);
+                                                       &gph->our_zone,
+                                                       gph->test_name,
+                                                       GNUNET_NAMESTORE_TYPE_ANY,
+                                                       &process_pseu_lookup_ns,
+                                                       gph);
 }
 
+
 /**
  * Handle timeout for dht request
  *
@@ -375,7 +379,7 @@ process_auth_discovery_dht_result (void* cls,
 {
   struct GetPseuAuthorityHandle* gph = cls;
   struct GNSNameRecordBlock *nrb;
-  char* rd_data = (char*)data;
+  const char* rd_data = data;
   char* name;
   int num_records;
   size_t rd_size;
@@ -389,14 +393,11 @@ process_auth_discovery_dht_result (void* cls,
   gph->get_handle = NULL;
   GNUNET_SCHEDULER_cancel (gph->timeout);
   
-  if (data == NULL)
+  if (NULL == data)
   {
     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
                 "GNS_GET_AUTH: got dht result null!\n", size);
-    GNUNET_free (gph->auth);
-    GNUNET_CRYPTO_rsa_key_free (gph->key);
-    GNUNET_CONTAINER_DLL_remove (gph_head, gph_tail, gph);
-    GNUNET_free (gph);
+    free_get_pseu_authority_handle (gph);
     return;
   }
   
@@ -457,30 +458,19 @@ process_auth_discovery_ns_result (void* cls,
                       const struct GNUNET_CRYPTO_RsaSignature *signature)
 {
   struct GetPseuAuthorityHandle* gph = cls;
-  struct GNUNET_CRYPTO_ShortHashCode name_hash;
   struct GNUNET_HashCode lookup_key;
-  struct GNUNET_CRYPTO_HashAsciiEncoded lookup_key_string;
-  struct GNUNET_HashCode name_hash_double;
-  struct GNUNET_HashCode zone_hash_double;
-  int i;
+  unsigned int i;
   uint32_t xquery;
   
   gph->namestore_task = NULL;
   /* no pseu found */
   if (0 == rd_count)
   {
-    /**
-     * check dht
-     */
-    GNUNET_CRYPTO_short_hash ("+", strlen ("+"), &name_hash);
-    GNUNET_CRYPTO_short_hash_double (&name_hash, &name_hash_double);
-    GNUNET_CRYPTO_short_hash_double (&gph->auth->zone, &zone_hash_double);
-    GNUNET_CRYPTO_hash_xor (&name_hash_double, &zone_hash_double, &lookup_key);
-    GNUNET_CRYPTO_hash_to_enc (&lookup_key, &lookup_key_string);
-
+    GNUNET_GNS_get_key_for_record (GNUNET_GNS_TLD_PLUS, &gph->auth->zone, &lookup_key);
     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-               "GNS_AUTO_PSEU: starting dht lookup for %s with key: %s\n",
-               "+", (char*)&lookup_key_string);
+               "GNS_AUTO_PSEU: starting dht lookup for %s with key: %s\n",
+               GNUNET_GNS_TLD_PLUS, 
+               GNUNET_h2s (&lookup_key));
 
     gph->timeout = GNUNET_SCHEDULER_add_delayed (DHT_LOOKUP_TIMEOUT,
                                          &handle_auth_discovery_timeout, gph);
@@ -490,20 +480,20 @@ process_auth_discovery_ns_result (void* cls,
     GNUNET_assert (gph->get_handle == NULL);
 
     gph->get_handle = GNUNET_DHT_get_start (dht_handle,
-                                            GNUNET_BLOCK_TYPE_GNS_NAMERECORD,
-                                            &lookup_key,
-                                            DHT_GNS_REPLICATION_LEVEL,
-                                            GNUNET_DHT_RO_NONE,
-                                            &xquery,
-                                            sizeof(xquery),
-                                            &process_auth_discovery_dht_result,
-                                            gph);
+                                           GNUNET_BLOCK_TYPE_GNS_NAMERECORD,
+                                           &lookup_key,
+                                           DHT_GNS_REPLICATION_LEVEL,
+                                           GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE,
+                                           &xquery,
+                                           sizeof(xquery),
+                                           &process_auth_discovery_dht_result,
+                                           gph);
     return;
   }
 
   for (i=0; i < rd_count; i++)
   {
-    if (0 != (strcmp (name, "+")))
+    if (0 != (strcmp (name, GNUNET_GNS_TLD_PLUS)))
       continue;
 
     if (rd[i].record_type != GNUNET_GNS_RECORD_PSEU)
@@ -553,12 +543,9 @@ process_zone_to_name_discover (void *cls,
     return;
   }
   /* we found a match in our own zone */
-  GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
-             "GNS_AUTO_PSEU: name for zone in our root %s\n", name);
-  GNUNET_free (gph->auth);
-  GNUNET_CRYPTO_rsa_key_free (gph->key);
-  GNUNET_CONTAINER_DLL_remove (gph_head, gph_tail, gph);
-  GNUNET_free (gph);
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+             "GNS_AUTO_PSEU: name for zone in our root %s\n", name);
+  free_get_pseu_authority_handle (gph);
 }
 
 
@@ -583,27 +570,25 @@ shorten_authority_chain (struct GetPseuAuthorityHandle *gph)
 
 }
 
+
 static void
 start_shorten (struct AuthorityChain *auth,
-               struct GNUNET_CRYPTO_RsaPrivateKey *key)
+               const struct GNUNET_CRYPTO_RsaPrivateKey *key)
 {
   struct GetPseuAuthorityHandle *gph;
   struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded pkey;
   struct GNUNET_CRYPTO_RsaPrivateKeyBinaryEncoded *pb_key;
   
   GNUNET_CRYPTO_rsa_key_get_public (key, &pkey);
-  pb_key = GNUNET_CRYPTO_rsa_encode_key (key);
-
-  if (NULL == pb_key)
+  if (NULL == (pb_key = GNUNET_CRYPTO_rsa_encode_key (key)))
   {
     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
                 "Failed to encode RSA key on shorten\n");
     return;
   }
-
   gph = GNUNET_malloc (sizeof (struct GetPseuAuthorityHandle));
-  gph->key = GNUNET_CRYPTO_rsa_decode_key ((char*)pb_key, ntohs (pb_key->len));
-
+  gph->key = GNUNET_CRYPTO_rsa_decode_key ((const char*) pb_key, ntohs (pb_key->len));
+  GNUNET_free (pb_key);
   if (NULL == gph->key)
   {
     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
@@ -640,9 +625,8 @@ gns_resolver_init (struct GNUNET_NAMESTORE_Handle *nh,
                   unsigned long long max_bg_queries,
                   int ignore_pending)
 {
-  if (NULL == nh)
-    return GNUNET_SYSERR;
-  if (NULL == dh)
+  if ( (NULL == nh) ||
+       (NULL == dh) )
     return GNUNET_SYSERR;
   
   cfg = c;
@@ -655,16 +639,7 @@ gns_resolver_init (struct GNUNET_NAMESTORE_Handle *nh,
     GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN);
   max_allowed_background_queries = max_bg_queries;
   max_allowed_ns_tasks = GNUNET_GNS_MAX_NS_TASKS;
-  ignore_pending_records = ignore_pending;
-  gph_head = NULL;
-  gph_tail = NULL;
-  rlh_head = NULL;
-  rlh_tail = NULL;
-  nsh_head = NULL;
-  nsh_tail = NULL;
-  nah_head = NULL;
-  nah_tail = NULL;
-  
+  ignore_pending_records = ignore_pending; 
   GNUNET_RESOLVER_connect (cfg);
   return GNUNET_OK;
 }
@@ -686,17 +661,12 @@ cleanup_pending_ns_tasks (void* cls,
                           GNUNET_CONTAINER_HeapCostType cost)
 {
   struct NamestoreBGTask *nbg = element;
-  ResolverCleanupContinuation cont = cls;
 
   GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
              "GNS_CLEANUP: Terminating ns task\n");
   GNUNET_NAMESTORE_cancel (nbg->qe);
 
   GNUNET_CONTAINER_heap_remove_node (node);
-
-  if (0 == GNUNET_CONTAINER_heap_get_size (ns_task_heap))
-    cont ();
-
   return GNUNET_YES;
 }
 
@@ -733,7 +703,6 @@ cleanup_pending_background_queries (void* cls,
                                     GNUNET_CONTAINER_HeapCostType cost)
 {
   struct ResolverHandle *rh = element;
-  ResolverCleanupContinuation cont = cls;
 
   GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
              "GNS_CLEANUP-%llu: Terminating background lookup for %s\n",
@@ -741,17 +710,10 @@ cleanup_pending_background_queries (void* cls,
   GNUNET_CONTAINER_heap_remove_node (node);
   if (0 == GNUNET_CONTAINER_heap_get_size (dht_lookup_heap))
   {
-    if (GNUNET_CONTAINER_heap_get_size (ns_task_heap) == 0)
-      cont ();
-    else
-    {
-      GNUNET_CONTAINER_heap_iterate (ns_task_heap,
-                                     &cleanup_pending_ns_tasks,
-                                     cont);
-    }
+    GNUNET_CONTAINER_heap_iterate (ns_task_heap,
+                                  &cleanup_pending_ns_tasks,
+                                  NULL);    
   }
-
-
   return GNUNET_YES;
 }
 
@@ -824,33 +786,35 @@ finish_shorten (struct ResolverHandle *rh,
 static void
 finish_get_auth (struct ResolverHandle *rh,
                  struct GetNameAuthorityHandle* rlh);
+
+
 /**
  * Shutdown resolver
  */
 void
-gns_resolver_cleanup (ResolverCleanupContinuation cont)
+gns_resolver_cleanup ()
 {
   unsigned int s;
   struct GetPseuAuthorityHandle *tmp;
 
-  
-  tmp = gph_head;
-  for (tmp = gph_head; tmp != NULL; tmp = gph_head)
+  while (NULL != (tmp = gph_head))
   {
     if (tmp->get_handle != NULL)
+    {
       GNUNET_DHT_get_stop (tmp->get_handle);
-    tmp->get_handle = NULL;
+      tmp->get_handle = NULL;
+    }
     if (tmp->timeout != GNUNET_SCHEDULER_NO_TASK)
+    {
       GNUNET_SCHEDULER_cancel (tmp->timeout);
-    tmp->timeout = GNUNET_SCHEDULER_NO_TASK;
-
+      tmp->timeout = GNUNET_SCHEDULER_NO_TASK;
+    }
     if (NULL != tmp->namestore_task)
+    {
       GNUNET_NAMESTORE_cancel (tmp->namestore_task);
-    tmp->namestore_task = NULL;
-    GNUNET_free (tmp->auth);
-    GNUNET_CRYPTO_rsa_key_free (tmp->key);
-    GNUNET_CONTAINER_DLL_remove (gph_head, gph_tail, tmp);
-    GNUNET_free (tmp);
+      tmp->namestore_task = NULL;
+    }
+    free_get_pseu_authority_handle (tmp);
   }
 
   while (NULL != rlh_head)
@@ -872,15 +836,13 @@ gns_resolver_cleanup (ResolverCleanupContinuation cont)
   if (0 != s)
     GNUNET_CONTAINER_heap_iterate (dht_lookup_heap,
                                    &cleanup_pending_background_queries,
-                                   cont);
+                                   NULL);
   else if (0 != GNUNET_CONTAINER_heap_get_size (ns_task_heap))
   {
     GNUNET_CONTAINER_heap_iterate (ns_task_heap,
                                    &cleanup_pending_ns_tasks,
-                                   cont);
+                                   NULL);
   }
-  else
-    cont ();
 }
 
 
@@ -975,7 +937,7 @@ dht_lookup_timeout (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
               "GNS_PHASE_REC-%llu: Starting background lookup for %s type %d\n",
               rh->id, new_name, rlh->record_type);
-
+  
   gns_resolver_lookup_record (rh->authority,
                               rh->private_local_zone,
                               rlh->record_type,
@@ -985,6 +947,7 @@ dht_lookup_timeout (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
                               GNUNET_NO,
                               &background_lookup_result_processor,
                               NULL);
+                              
   rh->timeout_task = GNUNET_SCHEDULER_NO_TASK;
 
   GNUNET_DHT_get_stop (rh->get_handle);
@@ -1112,6 +1075,9 @@ process_record_result_dht (void* cls,
     }
     
     /* Save to namestore */
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "GNS_PHASE_REC-%llu: Caching record for %s\n",
+                rh->id, name);
     namestore_bg_task = GNUNET_malloc (sizeof (struct NamestoreBGTask));
     namestore_bg_task->qe = GNUNET_NAMESTORE_record_put (namestore_handle,
                                  &nrb->public_key,
@@ -1147,23 +1113,14 @@ static void
 resolve_record_dht (struct ResolverHandle *rh)
 {
   uint32_t xquery;
-  struct GNUNET_CRYPTO_ShortHashCode name_hash;
   struct GNUNET_HashCode lookup_key;
-  struct GNUNET_HashCode name_hash_double;
-  struct GNUNET_HashCode zone_hash_double;
-  struct GNUNET_CRYPTO_HashAsciiEncoded lookup_key_string;
   struct RecordLookupHandle *rlh = rh->proc_cls;
   struct ResolverHandle *rh_heap_root;
 
-  GNUNET_CRYPTO_short_hash (rh->name, strlen (rh->name), &name_hash);
-  GNUNET_CRYPTO_short_hash_double (&name_hash, &name_hash_double);
-  GNUNET_CRYPTO_short_hash_double (&rh->authority, &zone_hash_double);
-  GNUNET_CRYPTO_hash_xor (&name_hash_double, &zone_hash_double, &lookup_key);
-  GNUNET_CRYPTO_hash_to_enc (&lookup_key, &lookup_key_string);
-
+  GNUNET_GNS_get_key_for_record (rh->name, &rh->authority, &lookup_key);
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
               "GNS_PHASE_REC-%llu: starting dht lookup for %s with key: %s\n",
-              rh->id, rh->name, (char*)&lookup_key_string);
+              rh->id, rh->name, GNUNET_h2s (&lookup_key));
 
   //rh->timeout_task = GNUNET_SCHEDULER_NO_TASK;
   rh->dht_heap_node = NULL;
@@ -1218,7 +1175,7 @@ resolve_record_dht (struct ResolverHandle *rh)
                                          GNUNET_BLOCK_TYPE_GNS_NAMERECORD,
                                          &lookup_key,
                                          DHT_GNS_REPLICATION_LEVEL,
-                                         GNUNET_DHT_RO_NONE,
+                                         GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE,
                                          &xquery,
                                          sizeof (xquery),
                                          &process_record_result_dht,
@@ -1751,6 +1708,7 @@ resolve_record_dns (struct ResolverHandle *rh,
   struct RecordLookupHandle *rlh = rh->proc_cls;
 
   memset (&packet, 0, sizeof (struct GNUNET_DNSPARSER_Packet));
+  memset (rh->dns_name, 0, sizeof (rh->dns_name));
   
   /* We cancel here as to not include the ns lookup in the timeout */
   if (GNUNET_SCHEDULER_NO_TASK != rh->timeout_task)
@@ -2033,16 +1991,15 @@ dht_authority_lookup_timeout(void *cls,
         "GNS_PHASE_DELEGATE_DHT-%llu: Starting background query for %s type %d\n",
         rh->id, rh->name, rlh->record_type);
 
-  gns_resolver_lookup_record(rh->authority,
-                             rh->private_local_zone,
-                             rlh->record_type,
-                             new_name,
-                             NULL,
-                             GNUNET_TIME_UNIT_FOREVER_REL,
-                             GNUNET_NO,
-                             &background_lookup_result_processor,
-                             NULL);
-
+  gns_resolver_lookup_record (rh->authority,
+                              rh->private_local_zone,
+                              rlh->record_type,
+                              new_name,
+                              NULL,
+                              GNUNET_TIME_UNIT_FOREVER_REL,
+                              GNUNET_NO,
+                              &background_lookup_result_processor,
+                              NULL);
   rh->proc(rh->proc_cls, rh, 0, NULL);
 }
 
@@ -2118,7 +2075,7 @@ process_pkey_revocation_result_ns (void *cls,
     {
       GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
         "GNS_PHASE_DELEGATE_REV-%llu: Starting background lookup for %s type %d\n",
-        rh->id, "+.gnunet", GNUNET_GNS_RECORD_REV);
+        rh->id, "+.gads", GNUNET_GNS_RECORD_REV);
 
       gns_resolver_lookup_record(rh->authority,
                                  rh->private_local_zone,
@@ -2211,10 +2168,9 @@ process_delegation_result_dht(void* cls,
   uint32_t num_records;
   char* name = NULL;
   char* rd_data = (char*) data;
-  int i;
+  uint32_t i;
   int rd_size;
-  struct GNUNET_CRYPTO_ShortHashCode zone, name_hash;
-  struct GNUNET_HashCode zone_hash_double, name_hash_double;
+  struct GNUNET_CRYPTO_ShortHashCode zone;
 
   GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
              "GNS_PHASE_DELEGATE_DHT-%llu: Got DHT result\n", rh->id);
@@ -2321,17 +2277,13 @@ process_delegation_result_dht(void* cls,
       }
 
     }
+    GNUNET_GNS_get_zone_from_key (name, key, &zone);
 
 
-    GNUNET_CRYPTO_short_hash(name, strlen(name), &name_hash);
-    GNUNET_CRYPTO_short_hash_double(&name_hash, &name_hash_double);
-    GNUNET_CRYPTO_hash_xor(key, &name_hash_double, &zone_hash_double);
-    GNUNET_CRYPTO_short_hash_from_truncation (&zone_hash_double, &zone);
-
-    /* Save to namestore */
-    if (0 != GNUNET_CRYPTO_short_hash_cmp(&rh->authority_chain_tail->zone,
+    /* Save to namestore
+    if (0 != GNUNET_CRYPTO_short_hash_cmp(&rh->authority_chain_head->zone,
                                           &zone))
-    {
+    {*/
       if (max_allowed_ns_tasks <=
           GNUNET_CONTAINER_heap_get_size (ns_task_heap))
       {
@@ -2339,10 +2291,12 @@ process_delegation_result_dht(void* cls,
         GNUNET_NAMESTORE_cancel (ns_heap_root->qe);
 
         GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
-                   "GNS_PHASE_REC-%llu: Replacing oldest background ns task\n",
+                   "GNS_PHASE_DELEGATE_DHT-%llu: Replacing oldest background ns task\n",
                    rh->id);
       }
-      
+      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                  "GNS_PHASE_DELEGATE_DHT-%llu: Caching record for %s\n",
+                  rh->id, name);
       namestore_bg_task = GNUNET_malloc (sizeof (struct NamestoreBGTask));
 
       namestore_bg_task->node = GNUNET_CONTAINER_heap_insert (ns_task_heap,
@@ -2358,7 +2312,7 @@ process_delegation_result_dht(void* cls,
                                  &on_namestore_delegation_put_result, //cont
                                  namestore_bg_task); //cls
     }
-  }
+  //}
 
   if (0 != rh->answered)
   {
@@ -2600,17 +2554,17 @@ handle_record_dht(void* cls, struct ResolverHandle *rh,
 
   if (0 == rd_count)
   {
-    GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
                "GNS_PHASE_REC-%llu: No records for %s found in DHT. Aborting\n",
                rh->id, rh->name);
     /* give up, cannot resolve */
-    finish_lookup(rh, rlh, 0, NULL);
+    finish_lookup (rh, rlh, 0, NULL);
     return;
   }
   /* results found yay */
-  GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
              "GNS_PHASE_REC-%llu: Record resolved from DHT!", rh->id);
-  finish_lookup(rh, rlh, rd_count, rd);
+  finish_lookup (rh, rlh, rd_count, rd);
 }
 
 
@@ -2635,16 +2589,16 @@ handle_record_ns (void* cls, struct ResolverHandle *rh,
   if (0 != rd_count)
   {
     /* results found yay */
-    GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
                "GNS_PHASE_REC-%llu: Record resolved from namestore!\n", rh->id);
-    finish_lookup(rh, rlh, rd_count, rd);
+    finish_lookup (rh, rlh, rd_count, rd);
     return;
   }
   
-  GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
-             "GNS_PHASE_REC-%llu: NS returned no records. (status: %d)!\n",
-             rh->id,
-             rh->status);
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "GNS_PHASE_REC-%llu: NS returned no records. (status: %d)!\n",
+              rh->id,
+              rh->status);
   /**
    * There are 5 conditions that have to met for us to consult the DHT:
    * 1. The entry in the DHT is RSL_RECORD_EXPIRED OR
@@ -2658,11 +2612,23 @@ handle_record_ns (void* cls, struct ResolverHandle *rh,
    */
   if ((0 != (rh->status & RSL_RECORD_EXPIRED)) &&
       (0 == (rh->status & RSL_RECORD_EXISTS)) )
+  {
+    
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "GNS_PHASE_REC-%llu: Not expired and exists!\n",
+              rh->id);
     check_dht = GNUNET_NO;
+  }
   
-  if (0 != GNUNET_CRYPTO_short_hash_cmp(&rh->authority_chain_head->zone,
+  if (0 == GNUNET_CRYPTO_short_hash_cmp(&rh->authority_chain_head->zone,
                                         &rh->private_local_zone))
+  {
+
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "GNS_PHASE_REC-%llu: Our zone!\n",
+              rh->id);
     check_dht = GNUNET_NO;
+  }
   
   if ((0 != strcmp (rh->name, "+")) && (GNUNET_YES == is_srv (rh->name)))
       check_dht = GNUNET_NO;
@@ -2677,7 +2643,7 @@ handle_record_ns (void* cls, struct ResolverHandle *rh,
     return;
   }
   /* give up, cannot resolve */
-  finish_lookup(rh, rlh, 0, NULL);
+  finish_lookup (rh, rlh, 0, NULL);
 }
 
 
@@ -2808,21 +2774,12 @@ static void
 resolve_delegation_dht(struct ResolverHandle *rh)
 {
   uint32_t xquery;
-  struct GNUNET_CRYPTO_ShortHashCode name_hash;
-  struct GNUNET_HashCode name_hash_double;
-  struct GNUNET_HashCode zone_hash_double;
   struct GNUNET_HashCode lookup_key;
   struct ResolverHandle *rh_heap_root;
   
   pop_tld(rh->name, rh->authority_name);
 
-  //FIXME handle return values here
-  GNUNET_CRYPTO_short_hash(rh->authority_name,
-                     strlen(rh->authority_name),
-                     &name_hash);
-  GNUNET_CRYPTO_short_hash_double(&name_hash, &name_hash_double);
-  GNUNET_CRYPTO_short_hash_double(&rh->authority, &zone_hash_double);
-  GNUNET_CRYPTO_hash_xor(&name_hash_double, &zone_hash_double, &lookup_key);
+  GNUNET_GNS_get_key_for_record (rh->authority_name, &rh->authority, &lookup_key);
   
   rh->dht_heap_node = NULL;
 
@@ -2862,7 +2819,7 @@ resolve_delegation_dht(struct ResolverHandle *rh)
                        GNUNET_BLOCK_TYPE_GNS_NAMERECORD,
                        &lookup_key,
                        DHT_GNS_REPLICATION_LEVEL,
-                       GNUNET_DHT_RO_NONE,
+                       GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE,
                        &xquery,
                        sizeof(xquery),
                        &process_delegation_result_dht,
@@ -3640,7 +3597,7 @@ process_zone_to_name_shorten_shorten (void *cls,
                                         nsh->shorten_zone) == 0)
   {
     /**
-     * This is our zone append .gnunet unless name is empty
+     * This is our zone append .gads unless name is empty
      * (it shouldn't be, usually FIXME what happens if we
      * shorten to our zone to a "" record??)
      */
@@ -3672,8 +3629,11 @@ process_zone_to_name_shorten_shorten (void *cls,
   }
   next_authority = rh->authority_chain_head;
   
-  GNUNET_snprintf(tmp_name, MAX_DNS_NAME_LENGTH,
-                  "%s.%s", rh->name, next_authority->name);
+  if (0 == strcmp (rh->name, ""))
+    strcpy (tmp_name, next_authority->name);
+  else
+    GNUNET_snprintf(tmp_name, MAX_DNS_NAME_LENGTH,
+                    "%s.%s", rh->name, next_authority->name);
   
   strcpy(rh->name, tmp_name);
   GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
@@ -3747,7 +3707,7 @@ process_zone_to_name_shorten_private (void *cls,
                                         nsh->private_zone) == 0)
   {
     /**
-     * This is our zone append .gnunet unless name is empty
+     * This is our zone append .gads unless name is empty
      * (it shouldn't be, usually FIXME what happens if we
      * shorten to our zone to a "" record??)
      */
@@ -3782,8 +3742,11 @@ process_zone_to_name_shorten_private (void *cls,
     }
     next_authority = rh->authority_chain_head;
     
-    GNUNET_snprintf(tmp_name, MAX_DNS_NAME_LENGTH,
-                    "%s.%s", rh->name, next_authority->name);
+    if (0 == strcmp (rh->name, ""))
+      strcpy (tmp_name, next_authority->name);
+    else
+      GNUNET_snprintf(tmp_name, MAX_DNS_NAME_LENGTH,
+                      "%s.%s", rh->name, next_authority->name);
     
     strcpy(rh->name, tmp_name);
     GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
@@ -3858,7 +3821,7 @@ process_zone_to_name_shorten_root (void *cls,
                                         nsh->root_zone) == 0)
   {
     /**
-     * This is our zone append .gnunet unless name is empty
+     * This is our zone append .gads unless name is empty
      * (it shouldn't be, usually FIXME what happens if we
      * shorten to our zone to a "" record??)
      */
@@ -3901,8 +3864,11 @@ process_zone_to_name_shorten_root (void *cls,
     }
     next_authority = rh->authority_chain_head;
     
-    GNUNET_snprintf(tmp_name, MAX_DNS_NAME_LENGTH,
-                    "%s.%s", rh->name, next_authority->name);
+    if (0 == strcmp (rh->name, ""))
+      strcpy (tmp_name, next_authority->name);
+    else
+      GNUNET_snprintf(tmp_name, MAX_DNS_NAME_LENGTH,
+                      "%s.%s", rh->name, next_authority->name);
     
     strcpy(rh->name, tmp_name);
     GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
@@ -3943,7 +3909,7 @@ handle_delegation_ns_shorten (void* cls,
   char result[MAX_DNS_NAME_LENGTH];
 
   nsh = (struct NameShortenHandle *)cls;
-  
+  rh->namestore_task = NULL;
   /**
    * At this point rh->name contains the part of the name
    * that we do not have a PKEY in our namestore to resolve.
@@ -3955,11 +3921,11 @@ handle_delegation_ns_shorten (void* cls,
              "PKEY resolved as far as possible in ns up to %s!\n", rh->name);
   memset(result, 0, sizeof (result));
 
-  if (GNUNET_CRYPTO_short_hash_cmp(&rh->authority_chain_head->zone,
-                                   nsh->root_zone) == 0)
+  if (0 == GNUNET_CRYPTO_short_hash_cmp(&rh->authority_chain_head->zone,
+                                   nsh->root_zone))
   {
     /**
-     * This is our zone append .gnunet unless name is empty
+     * This is our zone append .gads unless name is empty
      * (it shouldn't be, usually FIXME what happens if we
      * shorten to our zone to a "" record??)
      */
@@ -3975,7 +3941,7 @@ handle_delegation_ns_shorten (void* cls,
   else if (NULL != nsh->private_zone)
   {
     /**
-     * This is our zone append .gnunet unless name is empty
+     * This is our zone append .gads unless name is empty
      * (it shouldn't be, usually FIXME what happens if we
      * shorten to our zone to a "" record??)
      */
@@ -3996,7 +3962,7 @@ handle_delegation_ns_shorten (void* cls,
   else if (NULL != nsh->shorten_zone)
   {
     /**
-     * This is our zone append .gnunet unless name is empty
+     * This is our zone append .gads unless name is empty
      * (it shouldn't be, usually FIXME what happens if we
      * shorten to our zone to a "" record??)
      */
@@ -4048,9 +4014,10 @@ process_zone_to_name_zkey(void *cls,
 {
   struct ResolverHandle *rh = cls;
   struct NameShortenHandle *nsh = rh->proc_cls;
-  struct GNUNET_CRYPTO_ShortHashAsciiEncoded enc;
   char new_name[MAX_DNS_NAME_LENGTH];
 
+  rh->namestore_task = NULL;
+
   /* zkey not in our zone */
   if (name == NULL)
   {
@@ -4061,18 +4028,16 @@ process_zone_to_name_zkey(void *cls,
      * because PKEY import will happen if the user follows the zkey
      * link.
      */
-    GNUNET_CRYPTO_short_hash_to_enc ((struct GNUNET_CRYPTO_ShortHashCode*)rd,
-                                     &enc);
     GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
-               "No name found for zkey %s returning verbatim!\n", enc);
-    if (strcmp(rh->name, "") != 0)
+               "No name found for zkey %s returning verbatim!\n", nsh->result);
+    /*if (strcmp(rh->name, "") != 0)
       GNUNET_snprintf(new_name, MAX_DNS_NAME_LENGTH, "%s.%s.%s",
                       rh->name, enc, GNUNET_GNS_TLD_ZKEY);
     else
       GNUNET_snprintf(new_name, MAX_DNS_NAME_LENGTH, "%s.%s",
                       enc, GNUNET_GNS_TLD_ZKEY);
 
-    strcpy (nsh->result, new_name);
+    strcpy (nsh->result, new_name);*/
 
     finish_shorten (rh, nsh);
     return;
@@ -4191,9 +4156,9 @@ gns_resolver_shorten_name (struct GNUNET_CRYPTO_ShortHashCode *zone,
     {
       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
                   "Cannot convert ZKEY %s to hash!\n", nzkey);
+      GNUNET_CONTAINER_DLL_remove (nsh_head, nsh_tail, rh);
       GNUNET_free (rh);
       GNUNET_free (nsh);
-      GNUNET_CONTAINER_DLL_remove (nsh_head, nsh_tail, rh);
       proc (proc_cls, name);
       return;
     }
@@ -4221,9 +4186,9 @@ gns_resolver_shorten_name (struct GNUNET_CRYPTO_ShortHashCode *zone,
   else
   {
     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Unknown TLD in %s\n", name);
+    GNUNET_CONTAINER_DLL_remove (nsh_head, nsh_tail, rh);
     GNUNET_free (rh);
     GNUNET_free (nsh);
-    GNUNET_CONTAINER_DLL_remove (nsh_head, nsh_tail, rh);
     proc (proc_cls, name);
     return;
   }
@@ -4252,10 +4217,10 @@ finish_get_auth (struct ResolverHandle *rh,
   GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
              "Got authority result %s\n", nah->result);
   
-  nah->proc(nah->proc_cls, nah->result);
+  nah->proc (nah->proc_cls, nah->result);
   GNUNET_CONTAINER_DLL_remove (nah_head, nah_tail, rh);
-  GNUNET_free(nah);
-  free_resolver_handle(rh);
+  GNUNET_free (nah);
+  free_resolver_handle (rh);
 }
 
 /**
@@ -4308,7 +4273,10 @@ handle_delegation_result_ns_get_auth(void* cls,
     answer_len = strlen(nah->name) - strlen(rh->name)
       + strlen(GNUNET_GNS_TLD) + 1;
     memset(nah->result, 0, answer_len);
-    strcpy(nah->result, nah->name + strlen(rh->name) + 1);
+    if (0 != strcmp (rh->name, ""))
+      strcpy(nah->result, nah->name + strlen(rh->name) + 1);
+    else
+      strcpy(nah->result, nah->name);
 
     finish_get_auth (rh, nah);
   }