gnunet

Main GNUnet Logic
Log | Files | Refs | Submodules | README | LICENSE

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:
Msrc/cli/gns/gnunet-dns2gns-absorb.c | 394++++++++++++++++++++++++++++++++++++++++++++++++-------------------------------
Msrc/cli/gns/meson.build | 30+++++++++++++++---------------
Msrc/cli/namestore/gnunet-zoneimport.c | 211+++++++++++++++++++++++++++++++++++++++++++++++++++++--------------------------
Msrc/plugin/gns/plugin_gnsrecord_gns.c | 48+++++++++++-------------------------------------
Msrc/service/gns/gnunet-service-gns_resolver.c | 24++++--------------------
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)