commit 05ba852edfb7588d8363b67b9293afa3e43b74fa
parent 04a771418d1467eb43ceb622eccbbfa075ccc5eb
Author: Martin Schanzenbach <schanzen@gnunet.org>
Date: Mon, 1 Sep 2025 14:06:47 +0200
namestore/gns: start merging zoneimport and absorb. this also fixes handling of GNS2DNS according to the spec RFC9498 which we probably forgot to change in the code
Diffstat:
5 files changed, 410 insertions(+), 297 deletions(-)
diff --git a/src/cli/gns/gnunet-dns2gns-absorb.c b/src/cli/gns/gnunet-dns2gns-absorb.c
@@ -26,6 +26,7 @@
#include "platform.h"
#include <gnunet_util_lib.h>
#include <gnunet_gnsrecord_lib.h>
+#include <gnunet_namestore_service.h>
/**
* Request we should make.
@@ -113,12 +114,23 @@ static struct GNUNET_SCHEDULER_Task *t;
static char*dnsserver;
-static char*name;
+static char *name;
+
+static char ego_to_use_name[GNUNET_DNSPARSER_MAX_NAME_LENGTH];
+
+static char current_hostname[GNUNET_DNSPARSER_MAX_NAME_LENGTH];
static struct GNUNET_IDENTITY_Handle *identity;
+static struct GNUNET_NAMESTORE_Handle *namestore;
+
+static struct GNUNET_NAMESTORE_QueueEntry *ns_op;
+
static struct GNUNET_IDENTITY_Ego *ego_to_use;
+static struct GNUNET_CRYPTO_PrivateKey ego_to_use_sk;
+
+static struct GNUNET_IDENTITY_Operation *id_op;
/**
* Maximum number of queries pending at the same time.
@@ -214,7 +226,9 @@ process_record (struct Request *req,
struct NsDelegation *ns_deleg;
ns_deleg = GNUNET_new (struct NsDelegation);
sprintf (ns_deleg->name, "%s", rec->data.hostname);
- printf ("New ns_deleg %s\n", ns_deleg->name);
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "New ns_deleg %s\n",
+ ns_deleg->name);
GNUNET_CONTAINER_DLL_insert (ns_delegs_head,
ns_delegs_tail,
ns_deleg);
@@ -257,7 +271,59 @@ submit_req (struct Request *req, GNUNET_DNSSTUB_ResultCallback rc)
* @param hostname name to resolve
*/
static void
-resolve_ip (const struct NsDelegation *ns_deleg, int type);
+resolve (const char *hostname, int type, GNUNET_DNSSTUB_ResultCallback rc)
+{
+ struct GNUNET_DNSPARSER_Packet p;
+ struct GNUNET_DNSPARSER_Query q;
+ struct Request *req;
+ char *raw;
+ size_t raw_size;
+ int ret;
+
+ if (GNUNET_OK !=
+ GNUNET_DNSPARSER_check_name (hostname))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Refusing invalid hostname `%s'\n",
+ hostname);
+ return;
+ }
+ q.name = (char *) hostname;
+ q.type = type;
+ q.dns_traffic_class = GNUNET_TUN_DNS_CLASS_INTERNET;
+
+ memset (&p,
+ 0,
+ sizeof(p));
+ p.num_queries = 1;
+ p.queries = &q;
+ p.id = (uint16_t) GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_NONCE,
+ UINT16_MAX);
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Resolving hostname `%s'\n",
+ hostname);
+ ret = GNUNET_DNSPARSER_pack (&p,
+ UINT16_MAX,
+ &raw,
+ &raw_size);
+ if (GNUNET_OK != ret)
+ {
+ if (GNUNET_NO == ret)
+ GNUNET_free (raw);
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Failed to pack query for hostname `%s'\n",
+ hostname);
+ return;
+ }
+
+ req = GNUNET_new (struct Request);
+ req->hostname = strdup (hostname);
+ req->raw = raw;
+ req->raw_len = raw_size;
+ req->id = p.id;
+ submit_req (req, rc);
+}
+
/**
* Function called with the result of a DNS resolution.
@@ -341,131 +407,163 @@ process_result_ip (void *cls,
{
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"No IPv4s.\n");
- resolve_ip (ns_deleg,
- GNUNET_DNSPARSER_TYPE_AAAA);
+ resolve (ns_deleg->name,
+ GNUNET_DNSPARSER_TYPE_AAAA,
+ &process_result_ip);
GNUNET_free (req);
return;
}
GNUNET_assert (req->type == GNUNET_DNSPARSER_TYPE_AAAA);
if (NULL != ns_deleg->next)
{
- resolve_ip (ns_deleg->next, GNUNET_DNSPARSER_TYPE_A);
+ resolve (ns_deleg->next->name,
+ GNUNET_DNSPARSER_TYPE_A,
+ &process_result_ip);
GNUNET_free (req);
return;
}
GNUNET_free (req);
- for (ns_deleg = ns_delegs_head;
- NULL != ns_deleg;
- ns_deleg = ns_deleg->next)
{
- printf (
- "Got delegating DNS server `%s' with %d IPv4 and %d IPv6 addresses\n",
- ns_deleg->name,
- ns_deleg->ip_num,
- ns_deleg->ip6_num);
- for (int i = 0; i < ns_deleg->ip_num; i++)
+ int rd_count = 0;
+ for (ns_deleg = ns_delegs_head;
+ NULL != ns_deleg;
+ ns_deleg = ns_deleg->next)
{
- printf ("%s\n",
- inet_ntoa (*(struct in_addr*) &ns_deleg->ip_addrs[i]));
+ rd_count += ns_deleg->ip_num + ns_deleg->ip6_num;
}
- for (int i = 0; i < ns_deleg->ip6_num; i++)
+
+ struct GNUNET_GNSRECORD_Data rd[rd_count];
+ int rd_idx = 0;
+ char ip_str[INET6_ADDRSTRLEN];
+ char nsbuf[514];
+ size_t off;
+
+ GNUNET_assert (GNUNET_OK ==
+ GNUNET_DNSPARSER_builder_add_name (nsbuf,
+ sizeof(nsbuf),
+ &off,
+ name));
+ for (ns_deleg = ns_delegs_head;
+ NULL != ns_deleg;
+ ns_deleg = ns_deleg->next)
{
- char ip_str[INET6_ADDRSTRLEN];
- inet_ntop (AF_INET6, &ns_deleg->ip6_addrs[i * 2], ip_str, INET6_ADDRSTRLEN
- );
- printf ("%s\n",
- ip_str);
+ GNUNET_log (
+ GNUNET_ERROR_TYPE_DEBUG,
+ "Got delegating DNS server `%s' with %d IPv4 and %d IPv6 addresses\n",
+ ns_deleg->name,
+ ns_deleg->ip_num,
+ ns_deleg->ip6_num);
+ for (int i = 0; i < ns_deleg->ip_num; i++)
+ {
+ inet_ntop (AF_INET,
+ &ns_deleg->ip_addrs[i],
+ ip_str,
+ INET_ADDRSTRLEN);
+ printf ("%s\n",
+ ip_str);
+ rd[rd_idx].record_type = GNUNET_GNSRECORD_TYPE_GNS2DNS;
+ rd[rd_idx].expiration_time = GNUNET_TIME_UNIT_DAYS.rel_value_us;
+ rd[rd_idx].flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION;
+ GNUNET_memcpy (&nsbuf[off],
+ ip_str,
+ INET_ADDRSTRLEN + 1);
+ off += INET_ADDRSTRLEN + 1;
+ rd[rd_idx].data = GNUNET_malloc (off);
+ GNUNET_memcpy ((void*) rd[i].data, nsbuf, off);
+ rd[rd_idx].data_size = off;
+ rd_idx++;
+ }
+ for (int i = 0; i < ns_deleg->ip6_num; i++)
+ {
+ inet_ntop (AF_INET6,
+ &ns_deleg->ip6_addrs[i * 2],
+ ip_str,
+ INET6_ADDRSTRLEN);
+ printf ("%s\n",
+ ip_str);
+ rd[rd_idx].record_type = GNUNET_GNSRECORD_TYPE_GNS2DNS;
+ rd[rd_idx].expiration_time = GNUNET_TIME_UNIT_DAYS.rel_value_us;
+ rd[rd_idx].flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION;
+ GNUNET_memcpy (&nsbuf[off],
+ ip_str,
+ INET6_ADDRSTRLEN + 1);
+ off += INET6_ADDRSTRLEN + 1;
+ rd[rd_idx].data = GNUNET_malloc (off);
+ GNUNET_memcpy ((void*) rd[i].data, nsbuf, off);
+ rd[rd_idx].data_size = off;
+ rd_idx++;
+ }
}
}
GNUNET_SCHEDULER_shutdown ();
}
-/**
- * Add @a hostname to the list of requests to be made.
- *
- * @param hostname name to resolve
- */
-static void
-resolve_ip (const struct NsDelegation *ns_deleg, int type)
-{
- struct GNUNET_DNSPARSER_Packet p;
- struct GNUNET_DNSPARSER_Query q;
- struct Request *req;
- char *raw;
- size_t raw_size;
- int ret;
- const char *hostname = ns_deleg->name;
-
- if (GNUNET_OK !=
- GNUNET_DNSPARSER_check_name (hostname))
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Refusing invalid hostname `%s'\n",
- hostname);
- return;
- }
- q.name = (char *) hostname;
- q.type = type;
- q.dns_traffic_class = GNUNET_TUN_DNS_CLASS_INTERNET;
-
- memset (&p,
- 0,
- sizeof(p));
- p.num_queries = 1;
- p.queries = &q;
- p.id = (uint16_t) GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_NONCE,
- UINT16_MAX);
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Resolving hostname `%s'\n",
- hostname);
- ret = GNUNET_DNSPARSER_pack (&p,
- UINT16_MAX,
- &raw,
- &raw_size);
- if (GNUNET_OK != ret)
- {
- if (GNUNET_NO == ret)
- GNUNET_free (raw);
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Failed to pack query for hostname `%s'\n",
- hostname);
- return;
- }
-
- req = GNUNET_new (struct Request);
- req->hostname = strdup (hostname);
- req->raw = raw;
- req->type = type;
- req->raw_len = raw_size;
- req->id = p.id;
- submit_req (req, &process_result_ip);
-}
-
-
static const char*
-get_next_label ()
+pop_next_label ()
{
char *next_lbl;
- printf ("%s\n", name);
next_lbl = strrchr (name, '.');
if (NULL != next_lbl)
{
*next_lbl = 0;
return next_lbl + 1;
}
- printf ("%s\n", name);
return NULL;
}
-/**
- * Add @a hostname to the list of requests to be made.
- *
- * @param hostname name to resolve
- */
static void
-resolve (const char *hostname);
+ego_create_cb (
+ void *cls,
+ const struct GNUNET_CRYPTO_PrivateKey *pk,
+ enum GNUNET_ErrorCode ec)
+{
+ id_op = NULL;
+ GNUNET_assert (GNUNET_EC_NONE == ec);
+}
+
+
+static void
+ns_lookup_error_cb (void *cls)
+{
+ GNUNET_assert (0);
+}
+
+
+static void
+ns_lookup_result_cb (void *cls,
+ const struct
+ GNUNET_CRYPTO_PrivateKey *zone,
+ const char *label,
+ unsigned int rd_count,
+ const struct GNUNET_GNSRECORD_Data *rd)
+{
+ ns_op = NULL;
+ if (0 == rd_count)
+ {
+ id_op = GNUNET_IDENTITY_create (identity,
+ current_hostname,
+ NULL,
+ GNUNET_PUBLIC_KEY_TYPE_EDDSA,
+ &ego_create_cb,
+ NULL);
+ return;
+ }
+ for (int i = 0; i < rd_count; i++)
+ {
+ if (GNUNET_GNSRECORD_is_zonekey_type (rd[i].record_type))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "We have an ego for `%s', using that\n",
+ label);
+ GNUNET_memcpy (&ego_to_use_sk,
+ rd[i].data,
+ rd[i].data_size);
+ }
+ }
+}
+
/**
* Function called with the result of a DNS resolution.
@@ -540,7 +638,24 @@ process_result_ns (void *cls,
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"No NS records found.\n");
char *next_hostname;
- const char *next_lbl = get_next_label ();
+ const char *next_lbl;
+
+ // We have found no NS records.
+ // We need to use or create a new Ego
+ // to continue with the current label.
+ if (NULL != strrchr (name, '.'))
+ {
+ ns_op =
+ GNUNET_NAMESTORE_records_lookup (namestore,
+ &ego_to_use_sk,
+ next_lbl,
+ &ns_lookup_error_cb,
+ NULL,
+ &ns_lookup_result_cb,
+ NULL);
+ return;
+ }
+ next_lbl = pop_next_label ();
if (NULL == next_lbl)
{
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
@@ -552,13 +667,19 @@ process_result_ns (void *cls,
return;
}
GNUNET_asprintf (&next_hostname, "%s.%s", next_lbl, req->hostname);
- resolve (next_hostname);
+ resolve (next_hostname,
+ GNUNET_DNSPARSER_TYPE_A,
+ &process_result_ip);
return;
}
+ // next_lbl now contains the name under which to publish
+ // any GNS2DNS records
GNUNET_free (req->hostname);
GNUNET_free (req->raw);
GNUNET_free (req);
- resolve_ip (ns_delegs_head, GNUNET_DNSPARSER_TYPE_A);
+ resolve (ns_delegs_head->name,
+ GNUNET_DNSPARSER_TYPE_A,
+ &process_result_ip);
}
@@ -579,70 +700,24 @@ do_shutdown (void *cls)
}
GNUNET_DNSSTUB_stop (ctx);
ctx = NULL;
+ if (NULL != id_op)
+ {
+ GNUNET_IDENTITY_cancel (id_op);
+ id_op = NULL;
+ }
if (NULL != identity)
{
GNUNET_IDENTITY_disconnect (identity);
}
-}
-
-
-/**
- * Add @a hostname to the list of requests to be made.
- *
- * @param hostname name to resolve
- */
-static void
-resolve (const char *hostname)
-{
- struct GNUNET_DNSPARSER_Packet p;
- struct GNUNET_DNSPARSER_Query q;
- struct Request *req;
- char *raw;
- size_t raw_size;
- int ret;
-
- if (GNUNET_OK !=
- GNUNET_DNSPARSER_check_name (hostname))
+ if (NULL != ns_op)
{
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Refusing invalid hostname `%s'\n",
- hostname);
- return;
+ GNUNET_NAMESTORE_cancel (ns_op);
+ ns_op = NULL;
}
- q.name = (char *) hostname;
- q.type = GNUNET_DNSPARSER_TYPE_NS;
- q.dns_traffic_class = GNUNET_TUN_DNS_CLASS_INTERNET;
-
- memset (&p,
- 0,
- sizeof(p));
- p.num_queries = 1;
- p.queries = &q;
- p.id = (uint16_t) GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_NONCE,
- UINT16_MAX);
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Resolving hostname `%s'\n",
- hostname);
- ret = GNUNET_DNSPARSER_pack (&p,
- UINT16_MAX,
- &raw,
- &raw_size);
- if (GNUNET_OK != ret)
+ if (NULL != namestore)
{
- if (GNUNET_NO == ret)
- GNUNET_free (raw);
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Failed to pack query for hostname `%s'\n",
- hostname);
- return;
+ GNUNET_NAMESTORE_disconnect (namestore);
}
-
- req = GNUNET_new (struct Request);
- req->hostname = strdup (hostname);
- req->raw = raw;
- req->raw_len = raw_size;
- req->id = p.id;
- submit_req (req, &process_result_ns);
}
@@ -664,9 +739,13 @@ id_cb (void *cls,
GNUNET_SCHEDULER_shutdown ();
return;
}
+ ego_to_use_sk = *GNUNET_IDENTITY_ego_get_private_key (ego_to_use);
+ GNUNET_memcpy (ego_to_use_name,
+ GNUNET_IDENTITY_ego_get_name (ego_to_use),
+ strlen (GNUNET_IDENTITY_ego_get_name (ego_to_use) + 1));
sprintf (suffix,
".%s.",
- GNUNET_IDENTITY_ego_get_name (ego_to_use));
+ ego_to_use_name);
// Find pointer to first label before suffix.
printf ("Absorbing `%s' into `%s'\n",
name,
@@ -676,11 +755,13 @@ id_cb (void *cls,
suffix));
name[strlen (name) - strlen (suffix)] = '\0';
printf ("%s\n", name);
- const char *next_lbl = get_next_label ();
+ const char *next_lbl = pop_next_label ();
GNUNET_assert (NULL != next_lbl);
char *next_hostname;
GNUNET_asprintf (&next_hostname, "%s%s", next_lbl, suffix);
- resolve (next_hostname);
+ resolve (next_hostname,
+ GNUNET_DNSPARSER_TYPE_NS,
+ &process_result_ns);
return;
}
if ((NULL == ego) || (NULL == ego_name))
@@ -753,6 +834,7 @@ run (void *cls,
}
// Find longest prefix identity
identity = GNUNET_IDENTITY_connect (c, &id_cb, NULL);
+ namestore = GNUNET_NAMESTORE_connect (c);
}
diff --git a/src/cli/gns/meson.build b/src/cli/gns/meson.build
@@ -28,21 +28,21 @@ executable(
install_dir: get_option('bindir'),
)
-executable(
- 'gnunet-dns2gns-absorb',
- 'gnunet-dns2gns-absorb.c',
- install_rpath: rpath_option,
- dependencies: [
- libgnunetidentity_dep,
- libgnunetgns_dep,
- libgnunetgnsrecord_dep,
- idn_dep,
- libgnunetutil_dep,
- ],
- include_directories: [incdir, configuration_inc],
- install: true,
- install_dir: get_option('bindir'),
-)
+#executable(
+# 'gnunet-dns2gns-absorb',
+# 'gnunet-dns2gns-absorb.c',
+# install_rpath: rpath_option,
+# dependencies: [
+# libgnunetidentity_dep,
+# libgnunetgns_dep,
+# libgnunetgnsrecord_dep,
+# idn_dep,
+# libgnunetutil_dep,
+# ],
+# include_directories: [incdir, configuration_inc],
+# install: true,
+# install_dir: get_option('bindir'),
+#)
testgns = [
'test_dns2gns',
diff --git a/src/cli/namestore/gnunet-zoneimport.c b/src/cli/namestore/gnunet-zoneimport.c
@@ -202,6 +202,29 @@ struct Request
uint16_t id;
};
+/**
+ * Missing identity creation context
+ */
+struct MissingZoneCreationCtx
+{
+ // DLL
+ struct MissingZoneCreationCtx *next;
+
+ // DLL
+ struct MissingZoneCreationCtx *prev;
+
+ // Operation
+ struct GNUNET_IDENTITY_Operation *id_op;
+
+ // Request
+ struct Request *req;
+};
+
+// Missing zones list
+static struct MissingZoneCreationCtx *missing_zones_head;
+
+// Missing zones list
+static struct MissingZoneCreationCtx *missing_zones_tail;
/**
* Command-line argument specifying desired size of the hash map with
@@ -605,8 +628,7 @@ check_for_glue (void *cls, const struct GNUNET_DNSPARSER_Record *rec)
{
struct GlueClosure *gc = cls;
char dst[65536];
- size_t dst_len;
- size_t off;
+ size_t rd_len;
char ip[INET6_ADDRSTRLEN + 1];
socklen_t ip_size = (socklen_t) sizeof(ip);
struct GNUNET_TIME_Absolute expiration_time;
@@ -622,8 +644,7 @@ check_for_glue (void *cls, const struct GNUNET_DNSPARSER_Record *rec)
if (left.rel_value_us < minimum_expiration_time.rel_value_us)
expiration_time =
GNUNET_TIME_relative_to_absolute (minimum_expiration_time);
- dst_len = sizeof(dst);
- off = 0;
+ rd_len = 0;
switch (rec->type)
{
case GNUNET_DNSPARSER_TYPE_A:
@@ -637,20 +658,22 @@ check_for_glue (void *cls, const struct GNUNET_DNSPARSER_Record *rec)
GNUNET_break (0);
return;
}
- if ((GNUNET_OK == GNUNET_DNSPARSER_builder_add_name (dst,
- dst_len,
- &off,
- gc->req->hostname)) &&
- (GNUNET_OK ==
- GNUNET_DNSPARSER_builder_add_name (dst, dst_len, &off, ip)))
- {
- add_record (gc->req,
- GNUNET_GNSRECORD_TYPE_GNS2DNS,
- expiration_time,
- dst,
- off);
- gc->found = GNUNET_YES;
- }
+ // NAME
+ GNUNET_memcpy (dst,
+ gc->req->hostname,
+ strlen (gc->req->hostname) + 1);
+ rd_len += strlen (gc->req->hostname) + 1;
+ // DNS SERVER NAME
+ GNUNET_memcpy (dst + strlen (gc->req->hostname) + 1,
+ ip,
+ strlen (ip) + 1);
+ rd_len += strlen (ip) + 1;
+ add_record (gc->req,
+ GNUNET_GNSRECORD_TYPE_GNS2DNS,
+ expiration_time,
+ dst,
+ rd_len);
+ gc->found = GNUNET_YES;
break;
case GNUNET_DNSPARSER_TYPE_AAAA:
@@ -664,39 +687,41 @@ check_for_glue (void *cls, const struct GNUNET_DNSPARSER_Record *rec)
GNUNET_break (0);
return;
}
- if ((GNUNET_OK == GNUNET_DNSPARSER_builder_add_name (dst,
- dst_len,
- &off,
- gc->req->hostname)) &&
- (GNUNET_OK ==
- GNUNET_DNSPARSER_builder_add_name (dst, dst_len, &off, ip)))
- {
- add_record (gc->req,
- GNUNET_GNSRECORD_TYPE_GNS2DNS,
- expiration_time,
- dst,
- off);
- gc->found = GNUNET_YES;
- }
+ // NAME
+ GNUNET_memcpy (dst,
+ gc->req->hostname,
+ strlen (gc->req->hostname) + 1);
+ rd_len += strlen (gc->req->hostname) + 1;
+ // DNS SERVER NAME
+ GNUNET_memcpy (dst + strlen (gc->req->hostname) + 1,
+ ip,
+ strlen (ip) + 1);
+ rd_len += strlen (ip) + 1;
+ add_record (gc->req,
+ GNUNET_GNSRECORD_TYPE_GNS2DNS,
+ expiration_time,
+ dst,
+ rd_len);
+ gc->found = GNUNET_YES;
break;
case GNUNET_DNSPARSER_TYPE_CNAME:
- if ((GNUNET_OK == GNUNET_DNSPARSER_builder_add_name (dst,
- dst_len,
- &off,
- gc->req->hostname)) &&
- (GNUNET_OK == GNUNET_DNSPARSER_builder_add_name (dst,
- dst_len,
- &off,
- rec->data.hostname)))
- {
- add_record (gc->req,
- GNUNET_GNSRECORD_TYPE_GNS2DNS,
- expiration_time,
- dst,
- off);
- gc->found = GNUNET_YES;
- }
+ // NAME
+ GNUNET_memcpy (dst,
+ gc->req->hostname,
+ strlen (gc->req->hostname) + 1);
+ rd_len += strlen (gc->req->hostname) + 1;
+ // DNS SERVER NAME
+ GNUNET_memcpy (dst + strlen (gc->req->hostname) + 1,
+ rec->data.hostname,
+ strlen (rec->data.hostname) + 1);
+ rd_len += strlen (ip) + 1;
+ add_record (gc->req,
+ GNUNET_GNSRECORD_TYPE_GNS2DNS,
+ expiration_time,
+ dst,
+ rd_len);
+ gc->found = GNUNET_YES;
break;
default:
@@ -787,16 +812,18 @@ process_record (void *cls, const struct GNUNET_DNSPARSER_Record *rec)
gc.ns = rec->data.hostname;
gc.found = GNUNET_NO;
for_all_records (prc->p, &check_for_glue, &gc);
- if ((GNUNET_NO == gc.found) &&
- (GNUNET_OK == GNUNET_DNSPARSER_builder_add_name (dst,
- dst_len,
- &off,
- req->hostname)) &&
- (GNUNET_OK == GNUNET_DNSPARSER_builder_add_name (dst,
- dst_len,
- &off,
- rec->data.hostname)))
+ if (GNUNET_NO == gc.found)
{
+ // NAME
+ GNUNET_memcpy (dst,
+ req->hostname,
+ strlen (req->hostname) + 1);
+ off += strlen (req->hostname) + 1;
+ // DNS SERVER NAME
+ GNUNET_memcpy (dst + strlen (req->hostname) + 1,
+ rec->data.hostname,
+ strlen (rec->data.hostname) + 1);
+ off += strlen (rec->data.hostname) + 1;
/* FIXME: actually check if this is out-of-bailiwick,
and if not request explicit resolution... */
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
@@ -1497,6 +1524,36 @@ ns_lookup_result_cb (void *cls,
}
+static void
+missing_zone_creation_cont (
+ void *cls,
+ const struct GNUNET_CRYPTO_PrivateKey *pk,
+ enum GNUNET_ErrorCode ec)
+{
+ struct MissingZoneCreationCtx *mzctx = cls;
+ struct Zone *zone;
+ const char*dot;
+
+ dot = strchr (mzctx->req->hostname, (unsigned char) '.');
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Created missing ego `%s'\n",
+ dot + 1);
+ zone = GNUNET_new (struct Zone);
+ zone->key = *pk;
+ zone->domain = GNUNET_strdup (dot + 1);
+ mzctx->req->zone = zone;
+ GNUNET_CONTAINER_DLL_insert (zone_head, zone_tail, zone);
+ GNUNET_CONTAINER_DLL_remove (missing_zones_head,
+ missing_zones_tail,
+ mzctx);
+ GNUNET_free (mzctx);
+ if (NULL == missing_zones_head)
+ {
+ iterate_zones (NULL);
+ }
+}
+
+
/**
* Add @a hostname to the list of requests to be made.
*
@@ -1531,18 +1588,31 @@ queue (const char *hostname)
for (zone = zone_head; NULL != zone; zone = zone->next)
if (0 == strcmp (zone->domain, dot + 1))
break;
+ hlen = strlen (hostname) + 1;
+ req = GNUNET_malloc (sizeof(struct Request) + hlen);
if (NULL == zone)
{
- rejects++;
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Domain name `%s' not in ego list!\n",
dot + 1);
- return;
+ struct MissingZoneCreationCtx *mzctx;
+ mzctx = GNUNET_new (struct MissingZoneCreationCtx);
+ mzctx->id_op = GNUNET_IDENTITY_create (id,
+ dot + 1,
+ NULL,
+ GNUNET_PUBLIC_KEY_TYPE_EDDSA,
+ &missing_zone_creation_cont,
+ mzctx);
+ mzctx->req = req;
+ GNUNET_CONTAINER_DLL_insert (missing_zones_head,
+ missing_zones_tail,
+ mzctx);
+ }
+ else
+ {
+ req->zone = zone;
}
- hlen = strlen (hostname) + 1;
- req = GNUNET_malloc (sizeof(struct Request) + hlen);
- req->zone = zone;
req->hostname = (char *) &req[1];
GNUNET_memcpy (req->hostname, hostname, hlen);
req->id = (uint16_t) GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_NONCE,
@@ -1669,11 +1739,6 @@ process_stdin (void *cls)
(void) cls;
t = NULL;
- if (NULL != id)
- {
- GNUNET_IDENTITY_disconnect (id);
- id = NULL;
- }
while (NULL != fgets (hn, sizeof(hn), stdin))
{
if (strlen (hn) > 0)
@@ -1698,7 +1763,11 @@ process_stdin (void *cls)
"Done reading %llu domain names\n",
(unsigned long long) idot);
GNUNET_STATISTICS_set (stats, "# domain names provided", idot, GNUNET_NO);
- iterate_zones (NULL);
+ // Only start iteration immediately if no zones are missing.
+ if (NULL == missing_zones_head)
+ {
+ iterate_zones (NULL);
+ }
}
@@ -1743,7 +1812,10 @@ identity_cb (void *cls,
{
(void) cls;
(void) ctx;
+ static int initial_iteration = GNUNET_YES;
+ if (GNUNET_NO == initial_iteration)
+ return;
if (NULL == ego)
{
/* end of iteration */
@@ -1753,6 +1825,7 @@ identity_cb (void *cls,
GNUNET_SCHEDULER_shutdown ();
return;
}
+ initial_iteration = GNUNET_NO;
/* zone_head non-null, process hostnames from stdin */
t = GNUNET_SCHEDULER_add_now (&process_stdin, NULL);
return;
diff --git a/src/plugin/gns/plugin_gnsrecord_gns.c b/src/plugin/gns/plugin_gnsrecord_gns.c
@@ -68,25 +68,16 @@ gns_value_to_string (void *cls,
case GNUNET_GNSRECORD_TYPE_LEHO:
return GNUNET_strndup (data, data_size);
+ // See https://www.rfc-editor.org/rfc/rfc9498.html#name-gns2dns
case GNUNET_GNSRECORD_TYPE_GNS2DNS: {
- char *ns;
- char *ip;
- size_t off;
+ const char *name;
+ const char *dns_server_name;
char *nstr;
- off = 0;
- ns = GNUNET_DNSPARSER_parse_name (data, data_size, &off);
- if (NULL == ns)
- {
- GNUNET_break_op (0);
- GNUNET_free (ns);
- return NULL;
- }
+ name = (const char *) data;
/* DNS server IP/name must be UTF-8 */
- ip = GNUNET_strdup (&((const char*) data)[off]);
- GNUNET_asprintf (&nstr, "%s@%s", ns, ip);
- GNUNET_free (ns);
- GNUNET_free (ip);
+ dns_server_name = name + strlen (name) + 1;
+ GNUNET_asprintf (&nstr, "%s@%s", name, dns_server_name);
return nstr;
}
@@ -229,11 +220,10 @@ gns_string_to_value (void *cls,
*data_size = strlen (s);
return GNUNET_OK;
+ // See https://www.rfc-editor.org/rfc/rfc9498.html#name-gns2dns
case GNUNET_GNSRECORD_TYPE_GNS2DNS: {
- char nsbuf[514];
char *cpy;
char *at;
- size_t off;
cpy = GNUNET_strdup (s);
at = strchr (cpy, '@');
@@ -248,27 +238,9 @@ gns_string_to_value (void *cls,
*at = '\0';
at++;
- off = 0;
- if (GNUNET_OK !=
- GNUNET_DNSPARSER_builder_add_name (nsbuf,
- sizeof(nsbuf),
- &off,
- cpy))
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- _ (
- "Failed to serialize GNS2DNS record with value `%s': Not a DNS name.\n"),
- s);
- GNUNET_free (cpy);
- return GNUNET_SYSERR;
- }
/* The DNS server location/name is in UTF-8 */
- GNUNET_memcpy (&nsbuf[off], at, strlen (at) + 1);
- off += strlen (at) + 1;
- GNUNET_free (cpy);
- *data_size = off;
- *data = GNUNET_malloc (off);
- GNUNET_memcpy (*data, nsbuf, off);
+ *data_size = strlen (s) + 1;
+ *data = cpy;
return GNUNET_OK;
}
@@ -483,6 +455,7 @@ gns_is_critical (void *cls, uint32_t type)
GNUNET_YES : GNUNET_NO);
}
+
void *
libgnunet_plugin_gnsrecord_gns_init (void *cls);
@@ -506,6 +479,7 @@ libgnunet_plugin_gnsrecord_gns_init (void *cls)
return api;
}
+
void *
libgnunet_plugin_gnsrecord_gns_done (void *cls);
diff --git a/src/service/gns/gnunet-service-gns_resolver.c b/src/service/gns/gnunet-service-gns_resolver.c
@@ -1743,7 +1743,6 @@ recursive_gns2dns_resolution (struct GNS_ResolverHandle *rh,
{
char *ip;
char *n;
- size_t off;
struct Gns2DnsPending *gp;
struct GNUNET_CRYPTO_PublicKey zone;
struct sockaddr_in v4;
@@ -1753,34 +1752,19 @@ recursive_gns2dns_resolution (struct GNS_ResolverHandle *rh,
{
/**
* Records other than GNS2DNS not allowed
+ * FIXME: According to RFC 9498, they are...
*/
GNUNET_free (ns);
GNUNET_free (ac);
return GNUNET_SYSERR;
}
- off = 0;
- n = GNUNET_DNSPARSER_parse_name (rd[i].data,
- rd[i].data_size,
- &off);
- ip = GNUNET_strdup (&((const char *) rd[i].data)[off]);
- if ((NULL == n) ||
- (NULL == ip))
+ n = GNUNET_strdup ((const char*) rd[i].data);
+ if (strlen (n) + 1 >= rd[i].data_size)
{
GNUNET_break_op (0);
- GNUNET_free (n);
- GNUNET_free (ip);
- continue;
- }
-
- off += strlen (ip) + 1;
-
- if (off != rd[i].data_size)
- {
- GNUNET_break_op (0);
- GNUNET_free (n);
- GNUNET_free (ip);
continue;
}
+ ip = GNUNET_strdup (rd[i].data + strlen (n) + 1);
/* resolve 'ip' to determine the IP(s) of the DNS
resolver to use for lookup of 'ns' */
if (NULL != ns)