- Add reverse resolution with limited functionality
authorMartin Schanzenbach <mschanzenbach@posteo.de>
Thu, 6 Oct 2016 15:54:30 +0000 (15:54 +0000)
committerMartin Schanzenbach <mschanzenbach@posteo.de>
Thu, 6 Oct 2016 15:54:30 +0000 (15:54 +0000)
src/gns/Makefile.am
src/gns/gns.h
src/gns/gns_api.c
src/gns/gnunet-gns.c
src/gns/gnunet-service-gns.c
src/gns/gnunet-service-gns_reverser.c [new file with mode: 0644]
src/gns/gnunet-service-gns_reverser.h [new file with mode: 0644]
src/gns/plugin_gnsrecord_gns.c
src/include/gnunet_gns_service.h
src/include/gnunet_gnsrecord_lib.h
src/include/gnunet_protocols.h

index 33fd96d9db737e762f54eda45af184dbe1ac1a77..0b65a3d174a784b847eca16368e1cd50d9df0d72 100644 (file)
@@ -184,6 +184,7 @@ w32nsp_resolve_LDADD = -lws2_32
 gnunet_service_gns_SOURCES = \
  gnunet-service-gns.c \
  gnunet-service-gns_resolver.c gnunet-service-gns_resolver.h \
+ gnunet-service-gns_reverser.c gnunet-service-gns_reverser.h \
  gnunet-service-gns_shorten.c gnunet-service-gns_shorten.h \
  gnunet-service-gns_interceptor.c gnunet-service-gns_interceptor.h
 gnunet_service_gns_LDADD = \
@@ -258,7 +259,8 @@ check_SCRIPTS = \
   test_gns_rel_expiration.sh\
   test_gns_soa_lookup.sh\
   test_gns_revocation.sh\
-  test_gns_cname_lookup.sh
+  test_gns_cname_lookup.sh \
+       test_gns_reverse_lookup.sh
 
 if ENABLE_TEST_RUN
 if HAVE_SQLITE
index 476cb0fd219fe96caad58e807a6d1747d8c3d4c1..ca5525f801895ec07891252e70668da48668ea1c 100644 (file)
@@ -90,6 +90,32 @@ struct LookupMessage
 };
 
 
+/**
+ * Message from client to GNS service to lookup records.
+ */
+struct ReverseLookupMessage
+{
+  /**
+   * Header of type #GNUNET_MESSAGE_TYPE_GNS_REVERSE_LOOKUP
+   */
+  struct GNUNET_MessageHeader header;
+
+  /**
+   * Unique identifier for this request (for key collisions).
+   */
+  uint32_t id GNUNET_PACKED;
+
+  /**
+   * Zone that is target for reverse lookup
+   */
+  struct GNUNET_CRYPTO_EcdsaPublicKey zone_pkey;
+  
+  /**
+   * Root zone
+   */
+  struct GNUNET_CRYPTO_EcdsaPublicKey root_pkey;
+};
+
 /**
  * Message from GNS service to client: new results.
  */
@@ -114,6 +140,24 @@ struct LookupResultMessage
 
 };
 
+/**
+ * Message from GNS service to client: new results.
+ */
+struct ReverseLookupResultMessage
+{
+  /**
+    * Header of type #GNUNET_MESSAGE_TYPE_GNS_REVERSE_LOOKUP_RESULT
+   */
+  struct GNUNET_MessageHeader header;
+
+  /**
+   * Unique identifier for this request (for key collisions).
+   */
+  uint32_t id GNUNET_PACKED;
+
+  /* followed by the resulting name of the reverse lookup */
+};
+
 
 GNUNET_NETWORK_STRUCT_END
 
index b9b95b7c20fd5cc24e92e9e11ae162d036d6b090..3f6425b42a2195af3a789f719c546d7f649f3766 100644 (file)
@@ -79,6 +79,49 @@ struct GNUNET_GNS_LookupRequest
 
 };
 
+/**
+ * Handle to a lookup request
+ */
+struct GNUNET_GNS_ReverseLookupRequest
+{
+
+  /**
+   * DLL
+   */
+  struct GNUNET_GNS_ReverseLookupRequest *next;
+
+  /**
+   * DLL
+   */
+  struct GNUNET_GNS_ReverseLookupRequest *prev;
+
+  /**
+   * handle to gns
+   */
+  struct GNUNET_GNS_Handle *gns_handle;
+
+  /**
+   * processor to call on lookup result
+   */
+  GNUNET_GNS_ReverseLookupResultProcessor lookup_proc;
+
+  /**
+   * @e lookup_proc closure
+   */
+  void *proc_cls;
+
+  /**
+   * Envelope with the message for this queue entry.
+   */
+  struct GNUNET_MQ_Envelope *env;
+
+  /**
+   * request id
+   */
+  uint32_t r_id;
+
+};
+
 
 /**
  * Connection to the GNS service.
@@ -106,6 +149,15 @@ struct GNUNET_GNS_Handle
    */
   struct GNUNET_GNS_LookupRequest *lookup_tail;
 
+  /**
+   * Head of linked list of active reverse lookup requests.
+   */
+  struct GNUNET_GNS_ReverseLookupRequest *rev_lookup_head;
+
+  /**
+   * Tail of linked list of active reverse lookup requests.
+   */
+  struct GNUNET_GNS_ReverseLookupRequest *rev_lookup_tail;
   /**
    * Reconnect task
    */
@@ -180,10 +232,71 @@ mq_error_handler (void *cls,
                   enum GNUNET_MQ_Error error)
 {
   struct GNUNET_GNS_Handle *handle = cls;
-
+  LOG (GNUNET_ERROR_TYPE_WARNING, "Problem with message queue. error: %i\n",
+       error);
   force_reconnect (handle);
 }
 
+/**
+ * Check validity of message received from the GNS service
+ *
+ * @param cls the `struct GNUNET_GNS_Handle *`
+ * @param loookup_msg the incoming message
+ */
+static int
+check_rev_result (void *cls,
+              const struct ReverseLookupResultMessage *lookup_msg)
+{
+  size_t mlen = ntohs (lookup_msg->header.size) - sizeof (*lookup_msg);
+  char *name;
+  
+  name = (char*) &lookup_msg[1];
+  if ('\0' != name[mlen-1])
+  {
+    GNUNET_break (0);
+    return GNUNET_SYSERR;
+  }
+  return GNUNET_OK;
+}
+
+
+/**
+ * Handler for messages received from the GNS service
+ *
+ * @param cls the `struct GNUNET_GNS_Handle *`
+ * @param loookup_msg the incoming message
+ */
+static void
+handle_rev_result (void *cls,
+                   const struct ReverseLookupResultMessage *lookup_msg)
+{
+  struct GNUNET_GNS_Handle *handle = cls;
+  char *name;
+  uint32_t r_id = ntohl (lookup_msg->id);
+  struct GNUNET_GNS_ReverseLookupRequest *rlr;
+  GNUNET_GNS_ReverseLookupResultProcessor proc;
+  void *proc_cls;
+
+  name = (char*)&lookup_msg[1];
+  LOG (GNUNET_ERROR_TYPE_DEBUG,
+       "Received reverse lookup reply from GNS service (%s)\n",
+       name);
+  for (rlr = handle->rev_lookup_head; NULL != rlr; rlr = rlr->next)
+    if (rlr->r_id == r_id)
+      break;
+  if (NULL == rlr)
+    return;
+  proc = rlr->lookup_proc;
+  proc_cls = rlr->proc_cls;
+  GNUNET_CONTAINER_DLL_remove (handle->rev_lookup_head,
+                               handle->rev_lookup_tail,
+                               rlr);
+  GNUNET_free (rlr);
+  proc (proc_cls,
+        name);
+}
+
+
 
 /**
  * Check validity of message received from the GNS service
@@ -269,9 +382,14 @@ reconnect (struct GNUNET_GNS_Handle *handle)
                            GNUNET_MESSAGE_TYPE_GNS_LOOKUP_RESULT,
                            struct LookupResultMessage,
                            handle),
+    GNUNET_MQ_hd_var_size (rev_result,
+                           GNUNET_MESSAGE_TYPE_GNS_REVERSE_LOOKUP_RESULT,
+                           struct ReverseLookupResultMessage,
+                           handle),
     GNUNET_MQ_handler_end ()
   };
   struct GNUNET_GNS_LookupRequest *lh;
+  struct GNUNET_GNS_ReverseLookupRequest *rlh;
 
   GNUNET_assert (NULL == handle->mq);
   LOG (GNUNET_ERROR_TYPE_DEBUG,
@@ -286,6 +404,9 @@ reconnect (struct GNUNET_GNS_Handle *handle)
   for (lh = handle->lookup_head; NULL != lh; lh = lh->next)
     GNUNET_MQ_send_copy (handle->mq,
                          lh->env);
+  for (rlh = handle->rev_lookup_head; NULL != rlh; rlh = rlh->next)
+    GNUNET_MQ_send_copy (handle->mq,
+                         rlh->env);
 }
 
 
@@ -331,6 +452,7 @@ GNUNET_GNS_disconnect (struct GNUNET_GNS_Handle *handle)
     handle->reconnect_task = NULL;
   }
   GNUNET_assert (NULL == handle->lookup_head);
+  GNUNET_assert (NULL == handle->rev_lookup_head);
   GNUNET_free (handle);
 }
 
@@ -352,6 +474,22 @@ GNUNET_GNS_lookup_cancel (struct GNUNET_GNS_LookupRequest *lr)
   GNUNET_free (lr);
 }
 
+/**
+ * Cancel pending reverse lookup request
+ *
+ * @param lr the lookup request to cancel
+ */
+void
+GNUNET_GNS_reverse_lookup_cancel (struct GNUNET_GNS_ReverseLookupRequest *lr)
+{
+  struct GNUNET_GNS_Handle *handle = lr->gns_handle;
+
+  GNUNET_CONTAINER_DLL_remove (handle->rev_lookup_head,
+                               handle->rev_lookup_tail,
+                               lr);
+  GNUNET_MQ_discard (lr->env);
+  GNUNET_free (lr);
+}
 
 /**
  * Perform an asynchronous lookup operation on the GNS.
@@ -368,13 +506,13 @@ GNUNET_GNS_lookup_cancel (struct GNUNET_GNS_LookupRequest *lr)
  */
 struct GNUNET_GNS_LookupRequest*
 GNUNET_GNS_lookup (struct GNUNET_GNS_Handle *handle,
-                  const char *name,
-                  const struct GNUNET_CRYPTO_EcdsaPublicKey *zone,
-                  uint32_t type,
-                  enum GNUNET_GNS_LocalOptions options,
-                  const struct GNUNET_CRYPTO_EcdsaPrivateKey *shorten_zone_key,
-                  GNUNET_GNS_LookupResultProcessor proc,
-                  void *proc_cls)
+                   const char *name,
+                   const struct GNUNET_CRYPTO_EcdsaPublicKey *zone,
+                   uint32_t type,
+                   enum GNUNET_GNS_LocalOptions options,
+                   const struct GNUNET_CRYPTO_EcdsaPrivateKey *shorten_zone_key,
+                   GNUNET_GNS_LookupResultProcessor proc,
+                   void *proc_cls)
 {
   /* IPC to shorten gns names, return shorten_handle */
   struct LookupMessage *lookup_msg;
@@ -413,8 +551,8 @@ GNUNET_GNS_lookup (struct GNUNET_GNS_Handle *handle,
     lookup_msg->shorten_key = *shorten_zone_key;
   }
   GNUNET_memcpy (&lookup_msg[1],
-          name,
-          nlen);
+                 name,
+                 nlen);
   GNUNET_CONTAINER_DLL_insert (handle->lookup_head,
                                handle->lookup_tail,
                                lr);
@@ -424,5 +562,50 @@ GNUNET_GNS_lookup (struct GNUNET_GNS_Handle *handle,
   return lr;
 }
 
+/**
+ * Perform an asynchronous reverse lookup operation on the GNS.
+ *
+ * @param handle handle to the GNS service
+ * @param zone_key zone to find a name for
+ * @param root_key our zone
+ * @param proc processor to call on result
+ * @param proc_cls closure for @a proc
+ * @return handle to the request
+ */
+struct GNUNET_GNS_ReverseLookupRequest*
+GNUNET_GNS_reverse_lookup (struct GNUNET_GNS_Handle *handle,
+                           const struct GNUNET_CRYPTO_EcdsaPublicKey *zone_key,
+                           const struct GNUNET_CRYPTO_EcdsaPublicKey *root_key,
+                           GNUNET_GNS_ReverseLookupResultProcessor proc,
+                           void *proc_cls)
+{
+  /* IPC to shorten gns names, return shorten_handle */
+  struct ReverseLookupMessage *rev_lookup_msg;
+  struct GNUNET_GNS_ReverseLookupRequest *lr;
 
+  if ((NULL == zone_key) || (NULL == root_key))
+  {
+    GNUNET_break (0);
+    return NULL;
+  }
+  LOG (GNUNET_ERROR_TYPE_DEBUG,
+       "Trying to reverse lookup in GNS\n");
+  lr = GNUNET_new (struct GNUNET_GNS_ReverseLookupRequest);
+  lr->gns_handle = handle;
+  lr->lookup_proc = proc;
+  lr->proc_cls = proc_cls;
+  lr->r_id = handle->r_id_gen++;
+  lr->env = GNUNET_MQ_msg (rev_lookup_msg,
+                           GNUNET_MESSAGE_TYPE_GNS_REVERSE_LOOKUP);
+  rev_lookup_msg->id = htonl (lr->r_id);
+  rev_lookup_msg->zone_pkey = *zone_key;
+  rev_lookup_msg->root_pkey = *root_key;
+  GNUNET_CONTAINER_DLL_insert (handle->rev_lookup_head,
+                               handle->rev_lookup_tail,
+                               lr);
+  if (NULL != handle->mq)
+    GNUNET_MQ_send_copy (handle->mq,
+                         lr->env);
+  return lr;
+}
 /* end of gns_api.c */
index 62cec54cb1065534c0b332337ebd420b52870cc6..17fe4cbdae425b2ac6335df5bf7f6800c4ba6d15 100644 (file)
@@ -65,6 +65,16 @@ static char *zone_ego_name;
  */
 static char *public_key;
 
+/**
+ * Reverse key
+ */
+static char *reverse_key;
+
+/**
+ * Reverse key
+ */
+static struct GNUNET_CRYPTO_EcdsaPublicKey rkey;
+
 /**
  * Set to GNUNET_GNS_LO_LOCAL_MASTER if we are looking up in the master zone.
  */
@@ -85,6 +95,11 @@ static int rtype;
  */
 static struct GNUNET_GNS_LookupRequest *lookup_request;
 
+/**
+ * Handle to reverse lookup request
+ */
+static struct GNUNET_GNS_ReverseLookupRequest *rev_lookup_request;
+
 /**
  * Lookup an ego with the identity service.
  */
@@ -159,6 +174,24 @@ do_timeout (void *cls)
   GNUNET_SCHEDULER_shutdown ();
 }
 
+static void
+process_reverse_result (void *cls,
+                        const char *name)
+{
+  rev_lookup_request = NULL;
+  if (NULL == name)
+  {
+    printf ("No name found.\n");
+    return;
+  }
+  if (raw)
+    printf ("%s\n", name);
+  else
+    printf ("%s is known as %s\n",
+            reverse_key,
+            name);
+  GNUNET_SCHEDULER_shutdown ();
+}
 
 /**
  * Function called with the result of a GNS lookup.
@@ -248,6 +281,14 @@ lookup_with_keys (const struct GNUNET_CRYPTO_EcdsaPublicKey *pkey,
                                        &process_lookup_result,
                                        lookup_name);
   }
+  else if (NULL != reverse_key)
+  {
+    rev_lookup_request = GNUNET_GNS_reverse_lookup (gns,
+                                                &rkey,
+                                                pkey,
+                                                &process_reverse_result,
+                                                NULL);
+  }
   else
   {
     fprintf (stderr,
@@ -416,49 +457,77 @@ run (void *cls,
     return;
   }
   tt = GNUNET_SCHEDULER_add_delayed (timeout,
-                                    &do_timeout, NULL);
+                                     &do_timeout, NULL);
   GNUNET_SCHEDULER_add_shutdown (&do_shutdown, NULL);
+  if (NULL != reverse_key)
+  {
+    if (GNUNET_OK !=
+        GNUNET_CRYPTO_ecdsa_public_key_from_string (reverse_key,
+                                                    strlen (reverse_key),
+                                                    &rkey))
+    {
+      fprintf (stderr,
+               _("Reverse key `%s' is not well-formed\n"),
+               reverse_key);
+      GNUNET_SCHEDULER_shutdown ();
+      return;
+    }
+  }
   if (NULL != public_key)
   {
     if (GNUNET_OK !=
-       GNUNET_CRYPTO_ecdsa_public_key_from_string (public_key,
-                                                 strlen (public_key),
-                                                 &pkey))
+        GNUNET_CRYPTO_ecdsa_public_key_from_string (public_key,
+                                                    strlen (public_key),
+                                                    &pkey))
     {
       fprintf (stderr,
-              _("Public key `%s' is not well-formed\n"),
-              public_key);
+               _("Public key `%s' is not well-formed\n"),
+               public_key);
       GNUNET_SCHEDULER_shutdown ();
       return;
     }
     lookup_with_public_key (&pkey);
     return;
   }
+  if (NULL != reverse_key)
+  {
+    if (GNUNET_OK !=
+        GNUNET_CRYPTO_ecdsa_public_key_from_string (reverse_key,
+                                                    strlen (reverse_key),
+                                                    &rkey))
+    {
+      fprintf (stderr,
+               _("Reverse key `%s' is not well-formed\n"),
+               reverse_key);
+      GNUNET_SCHEDULER_shutdown ();
+      return;
+    }
+  }
   if (NULL != zone_ego_name)
   {
     el = GNUNET_IDENTITY_ego_lookup (cfg,
-                                    zone_ego_name,
-                                    &identity_zone_cb,
-                                    NULL);
+                                     zone_ego_name,
+                                     &identity_zone_cb,
+                                     NULL);
     return;
   }
   if ( (NULL != lookup_name) &&
        (strlen (lookup_name) > 4) &&
        (0 == strcmp (".zkey",
-                    &lookup_name[strlen (lookup_name) - 4])) )
+                     &lookup_name[strlen (lookup_name) - 4])) )
   {
     /* no zone required, use 'anonymous' zone */
     GNUNET_CRYPTO_ecdsa_key_get_public (GNUNET_CRYPTO_ecdsa_key_get_anonymous (),
-                                     &pkey);
+                                        &pkey);
     lookup_with_public_key (&pkey);
   }
   else
   {
     GNUNET_break (NULL == id_op);
     id_op = GNUNET_IDENTITY_get (identity,
-                                "gns-master",
-                                &identity_master_cb,
-                                NULL);
+                                 "gns-master",
+                                 &identity_master_cb,
+                                 NULL);
     GNUNET_assert (NULL != id_op);
   }
 }
@@ -493,6 +562,9 @@ main (int argc, char *const *argv)
     {'z', "zone", "NAME",
       gettext_noop ("Specify the name of the ego of the zone to lookup the record in"), 1,
       &GNUNET_GETOPT_set_string, &zone_ego_name},
+    {'R', "reverse", "PKEY",
+      gettext_noop ("Specify the public key of the zone to reverse lookup a name for"), 1,
+      &GNUNET_GETOPT_set_string, &reverse_key},
     GNUNET_GETOPT_OPTION_END
   };
   int ret;
@@ -503,11 +575,11 @@ main (int argc, char *const *argv)
 
   GNUNET_log_setup ("gnunet-gns", "WARNING", NULL);
   ret =
-      (GNUNET_OK ==
-       GNUNET_PROGRAM_run (argc, argv, "gnunet-gns",
-                           _("GNUnet GNS resolver tool"),
-                          options,
-                           &run, NULL)) ? 0 : 1;
+    (GNUNET_OK ==
+     GNUNET_PROGRAM_run (argc, argv, "gnunet-gns",
+                         _("GNUnet GNS resolver tool"),
+                         options,
+                         &run, NULL)) ? 0 : 1;
   GNUNET_free ((void*) argv);
   return ret;
 }
index 386e6d7449e7e3cddeebf84e4f5df1e00809f36e..221d75bbab6f19c70d77775b64a1ee83897e9667 100644 (file)
@@ -35,6 +35,7 @@
 #include "gnunet_statistics_service.h"
 #include "gns.h"
 #include "gnunet-service-gns_resolver.h"
+#include "gnunet-service-gns_reverser.h"
 #include "gnunet-service-gns_shorten.h"
 #include "gnunet-service-gns_interceptor.h"
 #include "gnunet_protocols.h"
@@ -108,6 +109,11 @@ struct ClientLookupHandle
    */
   struct GNS_ResolverHandle *lookup;
 
+  /**
+   * Active handle for a reverse lookup
+   */
+  struct GNS_ReverserHandle *rev_lookup;
+
   /**
    * request id
    */
@@ -367,7 +373,10 @@ client_disconnect_cb (void *cls,
               client);
   while (NULL != (clh = gc->clh_head))
   {
-    GNS_resolver_lookup_cancel (clh->lookup);
+    if (NULL != clh->lookup)
+      GNS_resolver_lookup_cancel (clh->lookup);
+    if (NULL != clh->rev_lookup)
+      GNS_reverse_lookup_cancel (clh->rev_lookup);
     GNUNET_CONTAINER_DLL_remove (gc->clh_head,
                                  gc->clh_tail,
                                  clh);
@@ -846,6 +855,47 @@ send_lookup_response (void* cls,
                             GNUNET_NO);
 }
 
+/**
+ * Reply to client with the result from our reverse lookup.
+ *
+ * @param cls the closure (our client lookup handle)
+ * @param rd_count the number of records in @a rd
+ * @param rd the record data
+ */
+static void
+send_reverse_lookup_response (void* cls,
+                              const char *name)
+{
+  struct ClientLookupHandle *clh = cls;
+  struct GNUNET_MQ_Envelope *env;
+  struct ReverseLookupResultMessage *rmsg;
+  size_t len;
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Sending LOOKUP_RESULT message with %s\n",
+              name);
+
+  if (NULL == name)
+    len = 1;
+  else
+    len = strlen (name) + 1;
+  env = GNUNET_MQ_msg_extra (rmsg,
+                             len,
+                             GNUNET_MESSAGE_TYPE_GNS_REVERSE_LOOKUP_RESULT);
+  rmsg->id = clh->request_id;
+  if (1 < len)
+    GNUNET_memcpy ((char*) &rmsg[1],
+                   name,
+                   strlen (name));
+  GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq(clh->gc->client),
+                  env);
+  GNUNET_CONTAINER_DLL_remove (clh->gc->clh_head, clh->gc->clh_tail, clh);
+  GNUNET_free (clh);
+  GNUNET_STATISTICS_update (statistics,
+                            "Completed reverse lookups", 1,
+                            GNUNET_NO);
+}
+
 
 /**
  * Checks a #GNUNET_MESSAGE_TYPE_GNS_LOOKUP message
@@ -856,7 +906,7 @@ send_lookup_response (void* cls,
  */
 static int
 check_lookup (void *cls,
-                   const struct LookupMessage *l_msg)
+              const struct LookupMessage *l_msg)
 {
   size_t msg_size;
   const char* name;
@@ -936,6 +986,37 @@ handle_lookup (void *cls,
                             1, GNUNET_NO);
 }
 
+/**
+ * Handle reverse lookup requests from client
+ *
+ * @param cls the closure
+ * @param client the client
+ * @param message the message
+ */
+static void
+handle_rev_lookup (void *cls,
+                   const struct ReverseLookupMessage *sh_msg)
+{
+  struct GnsClient *gc = cls;
+  struct ClientLookupHandle *clh;
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Received REVERSE_LOOKUP message\n");
+  GNUNET_SERVICE_client_continue (gc->client);
+
+  clh = GNUNET_new (struct ClientLookupHandle);
+  GNUNET_CONTAINER_DLL_insert (gc->clh_head, gc->clh_tail, clh);
+  clh->gc = gc;
+  clh->request_id = sh_msg->id;
+  clh->rev_lookup = GNS_reverse_lookup (&sh_msg->zone_pkey,
+                                        &sh_msg->root_pkey,
+                                        &send_reverse_lookup_response,
+                                        clh);
+  GNUNET_STATISTICS_update (statistics,
+                            "Reverse lookup attempts",
+                            1, GNUNET_NO);
+}
+
 
 /**
  * The zone monitor is now in SYNC with the current state of the
@@ -1149,6 +1230,10 @@ GNUNET_SERVICE_MAIN
                         GNUNET_MESSAGE_TYPE_GNS_LOOKUP,
                         struct LookupMessage,
                         NULL),
+ GNUNET_MQ_hd_fixed_size (rev_lookup,
+                          GNUNET_MESSAGE_TYPE_GNS_REVERSE_LOOKUP,
+                          struct ReverseLookupMessage,
+                          NULL),
  GNUNET_MQ_handler_end());
 
 
diff --git a/src/gns/gnunet-service-gns_reverser.c b/src/gns/gnunet-service-gns_reverser.c
new file mode 100644 (file)
index 0000000..6bae20b
--- /dev/null
@@ -0,0 +1,244 @@
+/*
+     This file is part of GNUnet.
+     Copyright (C) 2009-2013 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
+     by the Free Software Foundation; either version 3, or (at your
+     option) any later version.
+
+     GNUnet is distributed in the hope that it will be useful, but
+     WITHOUT ANY WARRANTY; without even the implied warranty of
+     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+     General Public License for more details.
+
+     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., 51 Franklin Street, Fifth Floor,
+     Boston, MA 02110-1301, USA.
+*/
+/**
+ * @file gns/gnunet-service-gns_reverser.c
+ * @brief GNUnet GNS service
+ * @author Martin Schanzenbach
+ */
+
+
+#include "platform.h"
+#include "gnunet_gns_service.h"
+#include "gnunet-service-gns_resolver.h"
+#include "gnunet-service-gns_reverser.h"
+
+struct ReverseTreeNode
+{
+  /**
+   * DLL
+   */
+  struct ReverseTreeNode *next;
+
+  /**
+   * DLL
+   */
+  struct ReverseTreeNode *prev;
+
+  /**
+   * Resolved name until now
+   */
+  char *name;
+
+  /**
+   * Depth of the resolution at this node
+   */
+  uint8_t depth;
+
+  /**
+   * The pkey of the namespace
+   */
+  struct GNUNET_CRYPTO_EcdsaPublicKey pkey;
+
+};
+
+
+struct GNS_ReverserHandle
+{
+  /**
+   * GNS resolver handle
+   */
+  struct GNS_ResolverHandle *rh;
+
+  /**
+   * The authority to look for
+   */
+  struct GNUNET_CRYPTO_EcdsaPublicKey authority;
+  
+  /**
+   * Resolution candidate queue
+   */
+  struct ReverseTreeNode *node_queue_head;
+
+  /**
+   * Resolution candidate queue
+   */
+  struct ReverseTreeNode *node_queue_tail;
+
+  /**
+   * Max depth for the resolution
+   */
+  uint8_t max_depth;
+
+  /**
+   * Result callback
+   */
+  GNS_ReverseResultProcessor proc;
+
+  /**
+   * Callback closure
+   */
+  void *proc_cls;
+};
+
+void
+cleanup_handle (struct GNS_ReverserHandle *rh)
+{
+  struct ReverseTreeNode *rtn;
+
+  for (rtn = rh->node_queue_head; NULL != rtn; rtn = rh->node_queue_head)
+  {
+    if (NULL != rtn->name)
+      GNUNET_free (rtn->name);
+    GNUNET_CONTAINER_DLL_remove (rh->node_queue_head,
+                                 rh->node_queue_tail,
+                                 rtn);
+    GNUNET_free (rtn);
+  }
+}
+
+void
+handle_gns_result (void *cls,
+                   uint32_t rd_count,
+                   const struct GNUNET_GNSRECORD_Data *rd)
+{
+  struct GNS_ReverserHandle *rh = cls;
+  const struct GNUNET_GNSRECORD_ReverseRecord *rr;
+  struct ReverseTreeNode *rtn;
+  char *result;
+  const char *name;
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Got result (%d)\n", rd_count);
+
+  for (int i = 0; i < rd_count; i++)
+  {
+    /**
+     * Check if we are in the delegation set
+     */
+    if (GNUNET_GNSRECORD_TYPE_REVERSE != rd[i].record_type)
+      continue;
+    rr = rd[i].data;
+    name = (const char*) &rr[1];
+    if (0 == memcmp (&rh->authority,
+                     &rr->pkey,
+                     sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)))
+    {
+      //Found!
+      GNUNET_asprintf (&result,
+                       "%s.%s.gnu",
+                       rh->node_queue_head->name,
+                       name);
+      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                  "Found path from %s\n", result);
+
+      rh->proc (rh->proc_cls, result);
+      cleanup_handle (rh);
+      GNUNET_free (result);
+      return;
+    } else {
+      if (rh->node_queue_head->depth >= rh->max_depth)
+        break;
+      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                  "Found REVERSE from %s\n", name);
+
+      rtn = GNUNET_new (struct ReverseTreeNode);
+      if (NULL == rh->node_queue_head->name)
+        rtn->name = GNUNET_strdup (name);
+      else
+        GNUNET_asprintf (&rtn->name,
+                         "%s.%s",
+                         rh->node_queue_head->name,
+                         name);
+      rtn->depth = rh->node_queue_head->depth + 1;
+      rtn->pkey = rr->pkey;
+      GNUNET_CONTAINER_DLL_insert_tail (rh->node_queue_head,
+                                        rh->node_queue_tail,
+                                        rtn);
+    }
+  }
+
+  /**
+   * Done here remove node from queue
+   */
+  rtn = rh->node_queue_head;
+  GNUNET_CONTAINER_DLL_remove (rh->node_queue_head,
+                               rh->node_queue_tail,
+                               rtn);
+  if (NULL == rh->node_queue_head)
+  {
+    //No luck
+    rh->proc (rh->proc_cls, NULL);
+    cleanup_handle (rh);
+    return;
+  }
+  rh->rh = GNS_resolver_lookup (&rh->node_queue_head->pkey,
+                                GNUNET_GNSRECORD_TYPE_REVERSE,
+                                "+.gnu",
+                                NULL,
+                                GNUNET_GNS_LO_DEFAULT,
+                                &handle_gns_result,
+                                rh);
+}
+
+struct GNS_ReverserHandle *
+GNS_reverse_lookup (const struct GNUNET_CRYPTO_EcdsaPublicKey *target,
+                    const struct GNUNET_CRYPTO_EcdsaPublicKey *authority,
+                    GNS_ReverseResultProcessor proc,
+                    void *proc_cls)
+{
+  struct GNS_ReverserHandle *rh;
+  struct ReverseTreeNode *rtn;
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Starting reverse resolution\n");
+  rh = GNUNET_new (struct GNS_ReverserHandle);
+  rh->proc = proc;
+  rh->proc_cls = proc_cls;
+  rtn = GNUNET_new (struct ReverseTreeNode);
+  rtn->name = NULL;
+  rtn->pkey = *target;
+  rtn->depth = 0;
+  GNUNET_CONTAINER_DLL_insert (rh->node_queue_head,
+                               rh->node_queue_tail,
+                               rtn);
+  rh->authority = *authority;
+  rh->max_depth = 3; //TODO make argument
+  rh->rh = GNS_resolver_lookup (target,
+                                GNUNET_GNSRECORD_TYPE_REVERSE,
+                                "+.gnu",
+                                NULL,
+                                GNUNET_GNS_LO_DEFAULT,
+                                &handle_gns_result,
+                                rh);
+  return rh;
+}
+
+/**
+ * Cancel active resolution (i.e. client disconnected).
+ *
+ * @param rh resolution to abort
+ */
+void
+GNS_reverse_lookup_cancel (struct GNS_ReverserHandle *rh)
+{
+  cleanup_handle (rh);
+  return;
+}
+
+
diff --git a/src/gns/gnunet-service-gns_reverser.h b/src/gns/gnunet-service-gns_reverser.h
new file mode 100644 (file)
index 0000000..ecec7d7
--- /dev/null
@@ -0,0 +1,72 @@
+/*
+     This file is part of GNUnet.
+     Copyright (C) 2009-2013 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
+     by the Free Software Foundation; either version 3, or (at your
+     option) any later version.
+
+     GNUnet is distributed in the hope that it will be useful, but
+     WITHOUT ANY WARRANTY; without even the implied warranty of
+     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+     General Public License for more details.
+
+     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., 51 Franklin Street, Fifth Floor,
+     Boston, MA 02110-1301, USA.
+*/
+/**
+ * @file gns/gnunet-service-gns_reverser.h
+ * @brief GNUnet GNS service
+ * @author Martin Schanzenbach
+ */
+#ifndef GNS_REVERSER_H
+#define GNS_REVERSER_H
+#include "gns.h"
+#include "gnunet_gns_service.h"
+
+/**
+ * Handle for an active request.
+ */
+struct GNS_ReverserHandle;
+
+
+/**
+ * Function called with results for a GNS resolution.
+ *
+ * @param cls closure
+ * @param rd_count number of records in @a rd
+ * @param rd records returned for the lookup
+ */
+typedef void (*GNS_ReverseResultProcessor)(void *cls,
+                                           const char *name);
+
+
+/**
+ * Reverse lookup of a specific zone
+ * calls RecordLookupProcessor on result or timeout
+ *
+ * @param target the zone to perform the lookup in
+ * @param authority the authority
+ * @param proc the processor to call
+ * @param proc_cls the closure to pass to @a proc
+ * @return handle to cancel operation
+ */
+struct GNS_ReverserHandle *
+GNS_reverse_lookup (const struct GNUNET_CRYPTO_EcdsaPublicKey *target,
+                    const struct GNUNET_CRYPTO_EcdsaPublicKey *authority,
+                    GNS_ReverseResultProcessor proc,
+                    void *proc_cls);
+
+
+/**
+ * Cancel active resolution (i.e. client disconnected).
+ *
+ * @param rh resolution to abort
+ */
+void
+GNS_reverse_lookup_cancel (struct GNS_ReverserHandle *rh);
+
+#endif
index 360500af767c357f83fde9d23a1fd7118579c1b4..5faca4578accc258c2cc90d890542fab1c241f66 100644 (file)
@@ -31,6 +31,7 @@
 #include "gnunet_gnsrecord_lib.h"
 #include "gnunet_dnsparser_lib.h"
 #include "gnunet_gnsrecord_plugin.h"
+#include <inttypes.h>
 
 
 /**
@@ -139,6 +140,30 @@ gns_value_to_string (void *cls,
       GNUNET_free (ival);
       return box_str;
     }
+  case GNUNET_GNSRECORD_TYPE_REVERSE:
+    {
+      struct GNUNET_GNSRECORD_ReverseRecord rev;
+      char *rev_str;
+      char *pkey_str;
+
+      if (data_size < sizeof (struct GNUNET_GNSRECORD_ReverseRecord))
+        return NULL; /* malformed */
+
+      memcpy (&rev,
+              data,
+              sizeof (rev));
+      cdata = data;
+      pkey_str = GNUNET_CRYPTO_ecdsa_public_key_to_string (&rev.pkey);
+
+      GNUNET_asprintf (&rev_str,
+                       "%s %s %"SCNu64,
+                       &cdata[sizeof (rev)],
+                       pkey_str,
+                       rev.expiration.abs_value_us);
+      GNUNET_free (pkey_str);
+      return rev_str;
+
+    }
   default:
     return NULL;
   }
@@ -170,147 +195,184 @@ gns_string_to_value (void *cls,
   switch (type)
   {
 
-  case GNUNET_GNSRECORD_TYPE_PKEY:
-    if (GNUNET_OK !=
-       GNUNET_CRYPTO_ecdsa_public_key_from_string (s, strlen (s), &pkey))
-    {
-      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-           _("Unable to parse PKEY record `%s'\n"),
-           s);
-      return GNUNET_SYSERR;
-    }
-    *data = GNUNET_new (struct GNUNET_CRYPTO_EcdsaPublicKey);
-    GNUNET_memcpy (*data, &pkey, sizeof (pkey));
-    *data_size = sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey);
-    return GNUNET_OK;
-
-  case GNUNET_GNSRECORD_TYPE_NICK:
-    *data = GNUNET_strdup (s);
-    *data_size = strlen (s);
-    return GNUNET_OK;
-  case GNUNET_GNSRECORD_TYPE_LEHO:
-    *data = GNUNET_strdup (s);
-    *data_size = strlen (s);
-    return GNUNET_OK;
-  case GNUNET_GNSRECORD_TYPE_GNS2DNS:
-    {
-      char nsbuf[514];
-      char *cpy;
-      char *at;
-      size_t off;
-
-      cpy = GNUNET_strdup (s);
-      at = strchr (cpy, '@');
-      if (NULL == at)
+    case GNUNET_GNSRECORD_TYPE_PKEY:
+      if (GNUNET_OK !=
+          GNUNET_CRYPTO_ecdsa_public_key_from_string (s, strlen (s), &pkey))
       {
         GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                    _("Unable to parse GNS2DNS record `%s'\n"),
+                    _("Unable to parse PKEY record `%s'\n"),
                     s);
-        GNUNET_free (cpy);
         return GNUNET_SYSERR;
       }
-      *at = '\0';
-      at++;
+      *data = GNUNET_new (struct GNUNET_CRYPTO_EcdsaPublicKey);
+      GNUNET_memcpy (*data, &pkey, sizeof (pkey));
+      *data_size = sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey);
+      return GNUNET_OK;
 
-      off = 0;
-      if ( (GNUNET_OK !=
-            GNUNET_DNSPARSER_builder_add_name (nsbuf,
-                                               sizeof (nsbuf),
-                                               &off,
-                                               cpy)) ||
-           (GNUNET_OK !=
-            GNUNET_DNSPARSER_builder_add_name (nsbuf,
-                                               sizeof (nsbuf),
-                                               &off,
-                                               at)) )
+    case GNUNET_GNSRECORD_TYPE_NICK:
+      *data = GNUNET_strdup (s);
+      *data_size = strlen (s);
+      return GNUNET_OK;
+    case GNUNET_GNSRECORD_TYPE_LEHO:
+      *data = GNUNET_strdup (s);
+      *data_size = strlen (s);
+      return GNUNET_OK;
+    case GNUNET_GNSRECORD_TYPE_GNS2DNS:
       {
-       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                    _("Failed to serialize GNS2DNS record with value `%s'\n"),
-                    s);
+        char nsbuf[514];
+        char *cpy;
+        char *at;
+        size_t off;
+
+        cpy = GNUNET_strdup (s);
+        at = strchr (cpy, '@');
+        if (NULL == at)
+        {
+          GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                      _("Unable to parse GNS2DNS record `%s'\n"),
+                      s);
+          GNUNET_free (cpy);
+          return GNUNET_SYSERR;
+        }
+        *at = '\0';
+        at++;
+
+        off = 0;
+        if ( (GNUNET_OK !=
+              GNUNET_DNSPARSER_builder_add_name (nsbuf,
+                                                 sizeof (nsbuf),
+                                                 &off,
+                                                 cpy)) ||
+             (GNUNET_OK !=
+              GNUNET_DNSPARSER_builder_add_name (nsbuf,
+                                                 sizeof (nsbuf),
+                                                 &off,
+                                                 at)) )
+        {
+          GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                      _("Failed to serialize GNS2DNS record with value `%s'\n"),
+                      s);
+          GNUNET_free (cpy);
+          return GNUNET_SYSERR;
+        }
         GNUNET_free (cpy);
-       return GNUNET_SYSERR;
+        *data_size = off;
+        *data = GNUNET_malloc (off);
+        GNUNET_memcpy (*data, nsbuf, off);
+        return GNUNET_OK;
       }
-      GNUNET_free (cpy);
-      *data_size = off;
-      *data = GNUNET_malloc (off);
-      GNUNET_memcpy (*data, nsbuf, off);
-      return GNUNET_OK;
-    }
-  case GNUNET_GNSRECORD_TYPE_VPN:
-    {
-      struct GNUNET_TUN_GnsVpnRecord *vpn;
-      char s_peer[103 + 1];
-      char s_serv[253 + 1];
-      unsigned int proto;
-
-      if (3 != SSCANF (s,
-                       "%u %103s %253s",
-                       &proto, s_peer, s_serv))
+    case GNUNET_GNSRECORD_TYPE_VPN:
       {
-        GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                    _("Unable to parse VPN record string `%s'\n"),
-                    s);
-        return GNUNET_SYSERR;
+        struct GNUNET_TUN_GnsVpnRecord *vpn;
+        char s_peer[103 + 1];
+        char s_serv[253 + 1];
+        unsigned int proto;
+
+        if (3 != SSCANF (s,
+                         "%u %103s %253s",
+                         &proto, s_peer, s_serv))
+        {
+          GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                      _("Unable to parse VPN record string `%s'\n"),
+                      s);
+          return GNUNET_SYSERR;
+        }
+        *data_size = sizeof (struct GNUNET_TUN_GnsVpnRecord) + strlen (s_serv) + 1;
+        *data = vpn = GNUNET_malloc (*data_size);
+        if (GNUNET_OK != GNUNET_CRYPTO_eddsa_public_key_from_string ((char*) s_peer,
+                                                                     strlen (s_peer),
+                                                                     &vpn->peer.public_key))
+        {
+          GNUNET_free (vpn);
+          *data_size = 0;
+          return GNUNET_SYSERR;
+        }
+        vpn->proto = htons ((uint16_t) proto);
+        strcpy ((char*)&vpn[1], s_serv);
+        return GNUNET_OK;
       }
-      *data_size = sizeof (struct GNUNET_TUN_GnsVpnRecord) + strlen (s_serv) + 1;
-      *data = vpn = GNUNET_malloc (*data_size);
-      if (GNUNET_OK != GNUNET_CRYPTO_eddsa_public_key_from_string ((char*) s_peer,
-                                                                   strlen (s_peer),
-                                                                   &vpn->peer.public_key))
+    case GNUNET_GNSRECORD_TYPE_BOX:
       {
-        GNUNET_free (vpn);
-        *data_size = 0;
-        return GNUNET_SYSERR;
+        struct GNUNET_GNSRECORD_BoxRecord *box;
+        size_t rest;
+        unsigned int protocol;
+        unsigned int service;
+        unsigned int record_type;
+        void *bval;
+        size_t bval_size;
+
+        if (3 != SSCANF (s,
+                         "%u %u %u ",
+                         &protocol,
+                         &service,
+                         &record_type))
+        {
+          GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                      _("Unable to parse BOX record string `%s'\n"),
+                      s);
+          return GNUNET_SYSERR;
+        }
+        rest = snprintf (NULL, 0,
+                         "%u %u %u ",
+                         protocol,
+                         service,
+                         record_type);
+        if (GNUNET_OK !=
+            GNUNET_GNSRECORD_string_to_value (record_type,
+                                              &s[rest],
+                                              &bval,
+                                              &bval_size))
+          return GNUNET_SYSERR;
+        *data_size = sizeof (struct GNUNET_GNSRECORD_BoxRecord) + bval_size;
+        *data = box = GNUNET_malloc (*data_size);
+        box->protocol = htons (protocol);
+        box->service = htons (service);
+        box->record_type = htonl (record_type);
+        GNUNET_memcpy (&box[1],
+                       bval,
+                       bval_size);
+        GNUNET_free (bval);
+        return GNUNET_OK;
       }
-      vpn->proto = htons ((uint16_t) proto);
-      strcpy ((char*)&vpn[1], s_serv);
-      return GNUNET_OK;
-    }
-  case GNUNET_GNSRECORD_TYPE_BOX:
-    {
-      struct GNUNET_GNSRECORD_BoxRecord *box;
-      size_t rest;
-      unsigned int protocol;
-      unsigned int service;
-      unsigned int record_type;
-      void *bval;
-      size_t bval_size;
-
-      if (3 != SSCANF (s,
-                       "%u %u %u ",
-                       &protocol,
-                       &service,
-                       &record_type))
+    case GNUNET_GNSRECORD_TYPE_REVERSE:
       {
-        GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                    _("Unable to parse BOX record string `%s'\n"),
-                    s);
-        return GNUNET_SYSERR;
+        struct GNUNET_GNSRECORD_ReverseRecord *rev;
+        char known_by[253 + 1];
+        struct GNUNET_TIME_Absolute expiration;
+
+        /* TODO: From crypto_ecc.c
+         * Why is this not a constant???
+         */
+        size_t enclen = (sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)) * 8;
+        if (enclen % 5 > 0)
+          enclen += 5 - enclen % 5;
+        enclen /= 5; /* 260/5 = 52 */
+        char pkey_str[enclen + 1];
+
+        if (3 != SSCANF (s,
+                         "%253s %52s %"SCNu64,
+                         known_by,
+                         pkey_str,
+                         &expiration.abs_value_us))
+        {
+          GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                      _("Unable to parse REVERSE record string `%s'\n"),
+                      s);
+          return GNUNET_SYSERR;
+        }
+        *data_size = sizeof (struct GNUNET_GNSRECORD_ReverseRecord) + strlen (known_by) + 1;
+        *data = rev = GNUNET_malloc (*data_size);
+        GNUNET_CRYPTO_ecdsa_public_key_from_string (pkey_str,
+                                                    strlen (pkey_str),
+                                                    &rev->pkey);
+        rev->expiration = expiration;
+        GNUNET_memcpy (&rev[1],
+                       known_by,
+                       strlen (known_by));
+        return GNUNET_OK;
       }
-      rest = snprintf (NULL, 0,
-                       "%u %u %u ",
-                       protocol,
-                       service,
-                       record_type);
-      if (GNUNET_OK !=
-          GNUNET_GNSRECORD_string_to_value (record_type,
-                                            &s[rest],
-                                            &bval,
-                                            &bval_size))
-        return GNUNET_SYSERR;
-      *data_size = sizeof (struct GNUNET_GNSRECORD_BoxRecord) + bval_size;
-      *data = box = GNUNET_malloc (*data_size);
-      box->protocol = htons (protocol);
-      box->service = htons (service);
-      box->record_type = htonl (record_type);
-      GNUNET_memcpy (&box[1],
-              bval,
-              bval_size);
-      GNUNET_free (bval);
-      return GNUNET_OK;
-    }
-  default:
-    return GNUNET_SYSERR;
+    default:
+      return GNUNET_SYSERR;
   }
 }
 
@@ -329,6 +391,7 @@ static struct {
   { "VPN", GNUNET_GNSRECORD_TYPE_VPN },
   { "GNS2DNS", GNUNET_GNSRECORD_TYPE_GNS2DNS },
   { "BOX", GNUNET_GNSRECORD_TYPE_BOX },
+  { "REVERSE", GNUNET_GNSRECORD_TYPE_REVERSE },
   { NULL, UINT32_MAX }
 };
 
@@ -348,7 +411,7 @@ gns_typename_to_number (void *cls,
 
   i=0;
   while ( (NULL != gns_name_map[i].name) &&
-         (0 != strcasecmp (gns_typename,
+          (0 != strcasecmp (gns_typename,
                             gns_name_map[i].name)) )
     i++;
   return gns_name_map[i].number;
@@ -370,7 +433,7 @@ gns_number_to_typename (void *cls,
 
   i=0;
   while ( (NULL != gns_name_map[i].name) &&
-         (type != gns_name_map[i].number) )
+          (type != gns_name_map[i].number) )
     i++;
   return gns_name_map[i].name;
 }
index 1d74408fc4e1a27d5f9ea413f45b49b79233bba1..8a1099444075b367477cd605605a0361eaa19136 100644 (file)
@@ -94,6 +94,16 @@ typedef void (*GNUNET_GNS_LookupResultProcessor) (void *cls,
                                                  uint32_t rd_count,
                                                  const struct GNUNET_GNSRECORD_Data *rd);
 
+/**
+ * Iterator called on obtained result for a GNS lookup.
+ *
+ * @param cls closure
+ * @param rd_count number of records in @a rd
+ * @param rd the records in reply
+ */
+typedef void (*GNUNET_GNS_ReverseLookupResultProcessor) (void *cls,
+                                                 const char* name);
+
 
 /**
  * Options for the GNS lookup.
@@ -146,6 +156,23 @@ GNUNET_GNS_lookup (struct GNUNET_GNS_Handle *handle,
                   GNUNET_GNS_LookupResultProcessor proc,
                   void *proc_cls);
 
+/**
+ * Perform an asynchronous reverse lookup operation on the GNS.
+ *
+ * @param handle handle to the GNS service
+ * @param zone_key zone to find a name for
+ * @param root_key our zone
+ * @param proc processor to call on result
+ * @param proc_cls closure for @a proc
+ * @return handle to the request
+ */
+struct GNUNET_GNS_ReverseLookupRequest*
+GNUNET_GNS_reverse_lookup (struct GNUNET_GNS_Handle *handle,
+                           const struct GNUNET_CRYPTO_EcdsaPublicKey *zone_key,
+                           const struct GNUNET_CRYPTO_EcdsaPublicKey *root_key,
+                           GNUNET_GNS_ReverseLookupResultProcessor proc,
+                           void *proc_cls);
+
 
 /**
  * Cancel pending lookup request
index b7920cbb844295ed4ac1079ee7a6997c65a1d2c6..985ae1f7ab0d5489d6ffbc3b00644787bf119990 100644 (file)
@@ -108,6 +108,10 @@ extern "C"
  */
 #define GNUNET_GNSRECORD_TYPE_ID_TOKEN_METADATA 65546
 
+/**
+ * Record type for reverse lookups
+ */
+#define GNUNET_GNSRECORD_TYPE_REVERSE 65548
 
 /**
  * Flags that can be set for a record.
@@ -286,6 +290,27 @@ struct GNUNET_GNSRECORD_BoxRecord
 
 };
 
+/**
+ * Record type used internally to keep track of reverse mappings into a
+ * namespace.
+ * The record contains data related to PKEY delegations from other namespaces to
+ * the namespace the record belongs to.
+ * It is exclusively found under the label ``+''.
+ */
+struct GNUNET_GNSRECORD_ReverseRecord
+{
+  /**
+   * The public key of the namespace the is delegating to our namespace
+   */
+  struct GNUNET_CRYPTO_EcdsaPublicKey pkey;
+
+  /**
+   * The expiration time of the delegation
+   */
+  struct GNUNET_TIME_Absolute expiration;
+
+  /* followed by the name the delegator uses to refer to our namespace */
+};
 
 GNUNET_NETWORK_STRUCT_END
 
index f9f6cbd9c4f2eee7812988b8d6018942ba3cc059..0da6780cbe0309e53ee40fdd7759f8e337aca14c 100644 (file)
@@ -1529,6 +1529,16 @@ extern "C"
  */
 #define GNUNET_MESSAGE_TYPE_GNS_LOOKUP_RESULT 501
 
+/**
+ * Reverse lookup
+ */
+#define GNUNET_MESSAGE_TYPE_GNS_REVERSE_LOOKUP 503
+
+/**
+ * Response to reverse lookup
+ */
+#define GNUNET_MESSAGE_TYPE_GNS_REVERSE_LOOKUP_RESULT 504
+
 
 /*******************************************************************************
  * CONSENSUS message types