-add reverse autoadd; with test
authorMartin Schanzenbach <mschanzenbach@posteo.de>
Fri, 7 Oct 2016 09:43:32 +0000 (09:43 +0000)
committerMartin Schanzenbach <mschanzenbach@posteo.de>
Fri, 7 Oct 2016 09:43:32 +0000 (09:43 +0000)
src/gns/gnunet-service-gns.c
src/gns/gnunet-service-gns_reverser.c
src/gns/gnunet-service-gns_reverser.h
src/gns/test_gns_reverse_lookup.sh

index 221d75bbab6f19c70d77775b64a1ee83897e9667..3e718dac851831fced2178b0e9ef4040020319d1 100644 (file)
@@ -301,6 +301,7 @@ shutdown_task (void *cls)
     identity_handle = NULL;
   }
   GNS_resolver_done ();
+  GNS_reverse_done ();
   GNS_shorten_done ();
   while (NULL != (ma = ma_head))
   {
@@ -1061,6 +1062,51 @@ handle_monitor_error (void *cls)
                                                 NULL);
 }
 
+/**
+ * Method called to inform about the ego to be used for the master zone
+ * for DNS interceptions.
+ *
+ * This function is only called ONCE, and 'NULL' being passed in
+ * @a ego does indicate that interception is not configured.
+ * If @a ego is non-NULL, we should start to intercept DNS queries
+ * and resolve ".gnu" queries using the given ego as the master zone.
+ *
+ * @param cls closure, our `const struct GNUNET_CONFIGURATION_Handle *c`
+ * @param ego ego handle
+ * @param ctx context for application to store data for this ego
+ *                 (during the lifetime of this process, initially NULL)
+ * @param name name assigned by the user for this ego,
+ *                   NULL if the user just deleted the ego and it
+ *                   must thus no longer be used
+ */
+static void
+identity_reverse_cb (void *cls,
+                       struct GNUNET_IDENTITY_Ego *ego,
+                       void **ctx,
+                       const char *name)
+{
+  identity_op = NULL;
+
+  if (NULL == ego)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+                _("No ego configured for `%s`\n"),
+                "gns-master");
+
+    return;
+  }
+  if (GNUNET_SYSERR ==
+      GNS_reverse_init (namestore_handle,
+                        GNUNET_IDENTITY_ego_get_private_key (ego),
+                        name))
+  {
+    GNUNET_break (0);
+    GNUNET_SCHEDULER_add_now (&shutdown_task, NULL);
+    return;
+  }
+}
+
+
 
 /**
  * Method called to inform about the ego to be used for the master zone
@@ -1087,13 +1133,22 @@ identity_intercept_cb (void *cls,
 {
   const struct GNUNET_CONFIGURATION_Handle *cfg = cls;
   struct GNUNET_CRYPTO_EcdsaPublicKey dns_root;
-
   identity_op = NULL;
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Looking for gns-intercept ego\n");
+  identity_op = GNUNET_IDENTITY_get (identity_handle,
+                                     "gns-reverse",
+                                     &identity_reverse_cb,
+                                     (void*)cfg);
+
+
   if (NULL == ego)
   {
     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
                 _("No ego configured for `%s`\n"),
                 "gns-intercept");
+
     return;
   }
   GNUNET_IDENTITY_ego_get_public_key (ego,
index 2e66e7fa64058b71dcaca76433296b98b2286aab..28c4f4e4d412de7597df1febfec46c78610ac1aa 100644 (file)
@@ -46,6 +46,11 @@ struct ReverseRecordEntry
    */
   struct GNUNET_GNSRECORD_ReverseRecord *record;
 
+  /**
+   * Record length
+   */
+  size_t record_len;
+
 };
 
 struct IteratorHandle
@@ -61,19 +66,19 @@ struct IteratorHandle
   struct ReverseRecordEntry *records_tail;
 
   /**
-   * Current delegation to expect
+   * Record count
    */
-  struct GNUNET_CRYPTO_EcdsaPublicKey target;
+  uint64_t record_count;
 
   /**
-   * The zone target for reverse record resolution
+   * Current delegation to expect
    */
-  struct GNUNET_CRYPTO_EcdsaPublicKey myzone;
+  struct GNUNET_CRYPTO_EcdsaPublicKey target;
 
   /**
-   * The nick of our zone
+   * Queue entry
    */
-  char *mynick;
+  struct GNUNET_NAMESTORE_QueueEntry *ns_qe;
 
 };
 
@@ -150,6 +155,11 @@ struct GNS_ReverserHandle
  */
 static struct GNUNET_SCHEDULER_Task *reverse_record_check_task;
 
+/**
+ * NS iterator task
+ */
+static struct GNUNET_SCHEDULER_Task *it_task;
+
 /**
  * GNS lookup handle
  */
@@ -165,7 +175,23 @@ static struct GNUNET_NAMESTORE_Handle *ns;
  */
 static struct GNUNET_NAMESTORE_ZoneIterator *namestore_iter;
 
-void
+/**
+ * The zone target for reverse record resolution
+ */
+static struct GNUNET_CRYPTO_EcdsaPublicKey myzone;
+
+/**
+ * The zone target for reverse record resolution
+ */
+static struct GNUNET_CRYPTO_EcdsaPrivateKey pzone;
+
+/**
+ * The nick of our zone
+ */
+static char *mynick;
+
+
+static void
 cleanup_handle (struct GNS_ReverserHandle *rh)
 {
   struct ReverseTreeNode *rtn;
@@ -174,14 +200,15 @@ cleanup_handle (struct GNS_ReverserHandle *rh)
   {
     if (NULL != rtn->name)
       GNUNET_free (rtn->name);
-    GNUNET_CONTAINER_DLL_remove (rh->node_queue_head,
+        GNUNET_CONTAINER_DLL_remove (rh->node_queue_head,
                                  rh->node_queue_tail,
                                  rtn);
-    GNUNET_free (rtn);
+        GNUNET_free (rtn);
   }
+  GNUNET_free (rh);
 }
 
-void
+static void
 handle_gns_result (void *cls,
                    uint32_t rd_count,
                    const struct GNUNET_GNSRECORD_Data *rd)
@@ -245,9 +272,10 @@ handle_gns_result (void *cls,
    * 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 != rtn)
+    GNUNET_CONTAINER_DLL_remove (rh->node_queue_head,
+                                 rh->node_queue_tail,
+                                 rtn);
   if (NULL == rh->node_queue_head)
   {
     //No luck
@@ -264,6 +292,16 @@ handle_gns_result (void *cls,
                                 rh);
 }
 
+/**
+ * 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,
@@ -309,47 +347,62 @@ GNS_reverse_lookup_cancel (struct GNS_ReverserHandle *rh)
   return;
 }
 
-void
+/********************************************
+ * Reverse iterator
+ * ******************************************/
+
+
+static void
 next_it (void *cls);
 
-void
+static void
 handle_gns_result_iter (void *cls,
                         uint32_t rd_count,
                         const struct GNUNET_GNSRECORD_Data *rd)
 {
   struct IteratorHandle *ith = cls;
   struct ReverseRecordEntry *rr;
+  gns_lookup_reverse = NULL;
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "GNS for REVERSE (%s)\n", mynick);
+
+
   if ((rd_count != 1) ||
       (GNUNET_GNSRECORD_TYPE_PKEY != rd->record_type))
   {
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "GNS invalid REVERSE (%s)\n", mynick);
     gns_lookup_reverse = NULL;
-    GNUNET_SCHEDULER_add_now (&next_it, NULL);
+    it_task = GNUNET_SCHEDULER_add_now (&next_it, ith);
     return;
   }
 
 
   rr = GNUNET_new (struct ReverseRecordEntry);
-  rr->record = GNUNET_malloc (sizeof (struct GNUNET_GNSRECORD_ReverseRecord)
-                              + strlen (ith->mynick) + 1);
+  rr->record_len = sizeof (struct GNUNET_GNSRECORD_ReverseRecord)
+    + strlen (mynick) + 1;
+  rr->record = GNUNET_malloc (rr->record_len);
   rr->record->pkey = ith->target;
   rr->record->expiration.abs_value_us = rd->expiration_time;
   GNUNET_memcpy ((char*)&rr->record[1],
-                 ith->mynick,
-                 strlen (ith->mynick));
+                 mynick,
+                 strlen (mynick));
   GNUNET_CONTAINER_DLL_insert (ith->records_head,
                                ith->records_tail,
                                rr);
-  GNUNET_SCHEDULER_add_now (&next_it, NULL);
+  ith->record_count++;
+  it_task = GNUNET_SCHEDULER_add_now (&next_it, ith);
 }
 
-void
+static void
 next_it (void *cls)
 {
+  it_task = NULL;
   GNUNET_assert (NULL != namestore_iter);
   GNUNET_NAMESTORE_zone_iterator_next (namestore_iter);
 }
 
-void
+static void
 iterator_cb (void *cls,
              const struct GNUNET_CRYPTO_EcdsaPrivateKey *key,
              const char *label,
@@ -357,42 +410,68 @@ iterator_cb (void *cls,
              const struct GNUNET_GNSRECORD_Data *rd)
 {
   struct IteratorHandle *ith = cls;
-  struct GNUNET_CRYPTO_EcdsaPublicKey *target;
   struct GNUNET_CRYPTO_EcdsaPublicKey zone;
+  char *name;
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "iterating for REVERSE (%s / %s)\n",
+              label,
+              mynick);
+
 
   if ((rd_count != 1) ||
       (GNUNET_GNSRECORD_TYPE_PKEY != rd->record_type))
   {
-    GNUNET_SCHEDULER_add_now (&next_it, NULL);
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "wrong format (%s)\n", mynick);
+
+
+    it_task = GNUNET_SCHEDULER_add_now (&next_it, ith);
     return;
   }
   GNUNET_CRYPTO_ecdsa_key_get_public (key,
                                       &zone);
-  if (0 != memcmp (&zone, &ith->myzone,
+  if (0 != memcmp (&zone, &myzone,
                    sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)))
   {
-    GNUNET_SCHEDULER_add_now (&next_it, NULL);
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "wrong zone (%s)\n", mynick);
+
+
+    it_task = GNUNET_SCHEDULER_add_now (&next_it, ith);
     return;
   }
-  target = (struct GNUNET_CRYPTO_EcdsaPublicKey *) rd->data;
-  gns_lookup_reverse = GNS_resolver_lookup (target,
+  ith->target = *((struct GNUNET_CRYPTO_EcdsaPublicKey *) rd->data);
+  GNUNET_asprintf (&name,
+                  "%s.gnu",
+                  mynick);
+  gns_lookup_reverse = GNS_resolver_lookup (&ith->target,
                                             GNUNET_GNSRECORD_TYPE_PKEY,
-                                            ith->mynick,
+                                            name,
                                             NULL,
                                             GNUNET_GNS_LO_DEFAULT,
                                             &handle_gns_result_iter,
                                             ith);
+  GNUNET_free (name);
 }
 
-void check_reverse_records (void *cls);
+static void check_reverse_records (void *cls);
 
-void
-finished_cb (void *cls)
+static void
+store_reverse (void *cls,
+               int32_t success,
+               const char *emsg)
 {
   struct IteratorHandle *ith = cls;
   struct ReverseRecordEntry *rr;
 
-  //TODO add results to namestore!
+  if (GNUNET_SYSERR == success)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                emsg);
+  }
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Stored records (%s)\n", mynick);
+
   for (rr = ith->records_head; NULL != rr; rr = ith->records_head)
   {
     GNUNET_CONTAINER_DLL_remove (ith->records_head,
@@ -404,19 +483,60 @@ finished_cb (void *cls)
   reverse_record_check_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_DAYS,
                                                             &check_reverse_records,
                                                             NULL);
+  GNUNET_free (ith);
+}
+
+static void
+finished_cb (void *cls)
+{
+  struct IteratorHandle *ith = cls;
+  struct ReverseRecordEntry *rr;
+  struct GNUNET_GNSRECORD_Data rd[ith->record_count];
+
+  memset (rd, 0, sizeof (struct GNUNET_GNSRECORD_Data) * ith->record_count);
+
+  rr = ith->records_head;
+  for (int i = 0; i < ith->record_count; i++)
+  {
+    rd[i].data_size = rr->record_len;
+    rd[i].data = GNUNET_malloc (rr->record_len);
+    rd[i].record_type = GNUNET_GNSRECORD_TYPE_REVERSE;
+    rd[i].expiration_time = rr->record->expiration.abs_value_us;
+    GNUNET_memcpy ((char*) rd[i].data,
+                   rr->record,
+                   rr->record_len);
+    rr = rr->next;
+  }
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Finished iterating for REVERSE\n");
+
+  ith->ns_qe = GNUNET_NAMESTORE_records_store (ns,
+                                               &pzone,
+                                               "+",
+                                               ith->record_count,
+                                               rd,
+                                               &store_reverse,
+                                               ith);
+  namestore_iter = NULL;
 
 }
 
-void
+static void
 it_error (void *cls)
 {
-  finished_cb (cls);
+  GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+              "Error iterating for REVERSE\n");
 }
 
-void
+static void
 check_reverse_records (void *cls)
 {
-  struct IteratorHandle *ith = cls;
+  struct IteratorHandle *ith;
+  ith = GNUNET_new (struct IteratorHandle);
+  ith->record_count = 0;
+  reverse_record_check_task = NULL;
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Start iterating for REVERSE (%s)\n", mynick);
   namestore_iter = GNUNET_NAMESTORE_zone_iteration_start (ns,
                                                           NULL,
                                                           &it_error,
@@ -427,20 +547,48 @@ check_reverse_records (void *cls)
                                                           ith);
 }
 
-void
-GNS_reverse_init (const struct GNUNET_CONFIGURATION_Handle *c,
-                  const struct GNUNET_NAMESTORE_Handle *nh,
-                  const struct GNUNET_CRYPTO_EcdsaPublicKey *myzone,
-                  const char *mynick)
+
+/**
+ * Initialize reverser
+ *
+ * @param nh handle to a namestore
+ * @param key the private key of the gns-reverse zone
+ * @param name the name of the gns-reverse zone
+ * @return GNUNET_OK
+ */
+int
+GNS_reverse_init (struct GNUNET_NAMESTORE_Handle *nh,
+                  const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
+                  const char *nick)
 {
-  struct IteratorHandle *ith;
+  GNUNET_asprintf (&mynick,
+                   "%s",
+                   nick);
+  GNUNET_CRYPTO_ecdsa_key_get_public (zone,
+                                      &myzone);
+  GNUNET_memcpy (&pzone,
+                 zone,
+                 sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey));
+  ns = nh;
+  reverse_record_check_task = GNUNET_SCHEDULER_add_now (&check_reverse_records,
+                                                        NULL);
+  return GNUNET_OK;
+}
 
-  ns = ns;
-  ith = GNUNET_new (struct IteratorHandle);
-  ith->mynick = GNUNET_strdup (mynick);
-  ith->myzone = *myzone;
-  reverse_record_check_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_DAYS,
-                                                            &check_reverse_records,
-                                                            NULL);
+/**
+ * Cleanup reverser
+ */
+void
+GNS_reverse_done ()
+{
+  GNUNET_free (mynick);
+  if (NULL != it_task)
+    GNUNET_SCHEDULER_cancel (it_task);
+  if (NULL != reverse_record_check_task)
+    GNUNET_SCHEDULER_cancel (reverse_record_check_task);
+  if (NULL != gns_lookup_reverse)
+    GNS_resolver_lookup_cancel (gns_lookup_reverse);
+  if (NULL != namestore_iter)
+    GNUNET_NAMESTORE_zone_iteration_stop (namestore_iter);
 }
 
index ecec7d74385be72df7021e864f77d3f71729d6d5..fc9680a29e832fe7015ee194381865a1eb18105c 100644 (file)
@@ -69,4 +69,23 @@ GNS_reverse_lookup (const struct GNUNET_CRYPTO_EcdsaPublicKey *target,
 void
 GNS_reverse_lookup_cancel (struct GNS_ReverserHandle *rh);
 
+/**
+ * Initialize reverser
+ *
+ * @param nh handle to a namestore
+ * @param key the private key of the gns-reverse zone
+ * @param name the name of the gns-reverse zone
+ * @return GNUNET_OK
+ */
+int
+GNS_reverse_init (struct GNUNET_NAMESTORE_Handle *nh,
+                  const struct GNUNET_CRYPTO_EcdsaPrivateKey *key,
+                  const char *name);
+
+/**
+ * Cleanup reverser
+ */
+void
+GNS_reverse_done ();
+
 #endif
index 73b829e07374a522380a322d36cdd2d1da532155..bff1c0662870003019411ab296b71ceb5b3fb092 100755 (executable)
@@ -16,7 +16,7 @@ fi
 
 TEST_NAME="dave.bob.alice.gnu"
 gnunet-arm -s -c test_gns_lookup.conf
-gnunet-identity -C bobego -c test_gns_lookup.conf
+gnunet-identity -C bob -c test_gns_lookup.conf
 BOB_PKEY=$(gnunet-identity -d -c test_gns_lookup.conf | grep bob | awk '{print $3}')
 gnunet-identity -C daveego -c test_gns_lookup.conf
 DAVE_PKEY=$(gnunet-identity -d -c test_gns_lookup.conf | grep dave | awk '{print $3}')
@@ -24,14 +24,22 @@ gnunet-identity -C aliceego -c test_gns_lookup.conf
 ALICE_PKEY=$(gnunet-identity -d -c test_gns_lookup.conf | grep alice | awk '{print $3}')
 gnunet-identity -C testego -c test_gns_lookup.conf
 ROOT_PKEY=$(gnunet-identity -d -c test_gns_lookup.conf | grep testego | awk '{print $3}')
+
+gnunet-identity -s gns-reverse -e bob -c test_gns_lookup.conf
+
 gnunet-namestore -p -z testego -a -n alice -t PKEY -V $ALICE_PKEY -e never -c test_gns_lookup.conf
 gnunet-namestore -p -z aliceego -a -n bob -t PKEY -V $BOB_PKEY -e never -c test_gns_lookup.conf
 gnunet-namestore -p -z aliceego -a -n + -t REVERSE -V "alice $ROOT_PKEY 0" -e never -c test_gns_lookup.conf
-gnunet-namestore -p -z bobego -a -n dave -t PKEY -V $DAVE_PKEY -e never -c test_gns_lookup.conf
-gnunet-namestore -p -z bobego -a -n + -t REVERSE -V "bob $ALICE_PKEY 0" -e never -c test_gns_lookup.conf
+gnunet-namestore -p -z bob -a -n dave -t PKEY -V $DAVE_PKEY -e never -c test_gns_lookup.conf
+gnunet-namestore -p -z bob -a -n alice -t PKEY -V $ALICE_PKEY -e never -c test_gns_lookup.conf
+#gnunet-namestore -p -z bob -a -n + -t REVERSE -V "bob $ALICE_PKEY 0" -e never -c test_gns_lookup.conf
 gnunet-namestore -p -z daveego -a -n + -t REVERSE -V "dave $BOB_PKEY 0" -e never -c test_gns_lookup.conf
+gnunet-namestore -p -z daveego -a -n bob -t PKEY -V $BOB_PKEY -e never -c test_gns_lookup.conf
 gnunet-arm -i gns -c test_gns_lookup.conf
-sleep 0.5
+$DO_TIMEOUT gnunet-gns --raw -z aliceego -u bob.gnu -t PKEY -c test_gns_lookup.conf
+sleep 10
+gnunet-namestore -z bob -D -c test_gns_lookup.conf
+gnunet-namestore -z daveego -D -c test_gns_lookup.conf
 RES_NAME=`$DO_TIMEOUT gnunet-gns --raw -z testego -R $DAVE_PKEY -c test_gns_lookup.conf`
 gnunet-arm -e -c test_gns_lookup.conf
 rm -rf /tmp/test-gnunet-gns-peer-1/