From 14b3c75ab523830f5c1744d5a0faa4168b4172a7 Mon Sep 17 00:00:00 2001 From: Martin Schanzenbach Date: Mon, 7 Feb 2022 15:59:04 +0100 Subject: GNS: LSD0001 improvements NAMESTORE: Better error handling. Fixed private record feature. GNSRECORD: Record inconsistency check for delegation and redirection records --- src/gnsrecord/gnsrecord_misc.c | 137 ++++++++++++++++++--- src/include/gnunet_gns_service.h | 6 - src/include/gnunet_gnsrecord_lib.h | 61 +++++++-- src/namestore/gnunet-service-namestore.c | 103 +++++++++------- src/namestore/namestore.h | 14 +++ src/namestore/namestore_api.c | 46 ++++++- src/zonemaster/gnunet-service-zonemaster-monitor.c | 20 ++- src/zonemaster/gnunet-service-zonemaster.c | 20 ++- 8 files changed, 317 insertions(+), 90 deletions(-) diff --git a/src/gnsrecord/gnsrecord_misc.c b/src/gnsrecord/gnsrecord_misc.c index 5c20dbedc..5bf4aa371 100644 --- a/src/gnsrecord/gnsrecord_misc.c +++ b/src/gnsrecord/gnsrecord_misc.c @@ -300,7 +300,8 @@ GNUNET_GNSRECORD_data_from_identity (const struct return GNUNET_SYSERR; tmp = GNUNET_malloc (*data_size); if (GNUNET_IDENTITY_write_key_to_buffer (key, tmp, *data_size) - != *data_size) { + != *data_size) + { GNUNET_free (tmp); *data_size = 0; return GNUNET_SYSERR; @@ -399,44 +400,148 @@ GNUNET_GNSRECORD_record_to_identity_key (const struct GNUNET_GNSRECORD_Data *rd, } -unsigned int -GNUNET_GNSRECORD_convert_records_for_export (const struct GNUNET_GNSRECORD_Data *rd, - unsigned int rd_count, - struct GNUNET_GNSRECORD_Data *rd_public, - struct GNUNET_TIME_Absolute *expiry) +enum GNUNET_GenericReturnValue +GNUNET_GNSRECORD_normalize_record_set (const char *label, + const struct + GNUNET_GNSRECORD_Data *rd, + unsigned int rd_count, + struct GNUNET_GNSRECORD_Data * + rd_public, + unsigned int *rd_count_public, + struct GNUNET_TIME_Absolute *expiry, + int include_private, + char **emsg) { struct GNUNET_TIME_Absolute expiry_tombstone; struct GNUNET_TIME_Absolute now; struct GNUNET_TIME_Absolute minimum_expiration; - unsigned int rd_public_count; + int have_zone_delegation = GNUNET_NO; + int have_gns2dns = GNUNET_NO; + int have_other = GNUNET_NO; + int have_redirect = GNUNET_NO; + int have_empty_label = (0 == strcmp (GNUNET_GNS_EMPTY_LABEL_AT, label)); + unsigned int rd_count_tmp; - rd_public_count = 0; minimum_expiration = GNUNET_TIME_UNIT_FOREVER_ABS; now = GNUNET_TIME_absolute_get (); + rd_count_tmp = 0; for (unsigned int i = 0; i < rd_count; i++) { + /* Ignore the tombstone. For maintenance only. Remember expiration time. */ if (GNUNET_GNSRECORD_TYPE_TOMBSTONE == rd[i].record_type) { minimum_expiration.abs_value_us = rd[i].expiration_time; continue; } - if (0 != (rd[i].flags & GNUNET_GNSRECORD_RF_PRIVATE)) + /* No NICK records unless empty label */ + if (have_empty_label && + (GNUNET_GNSRECORD_TYPE_NICK == rd[i].record_type)) + continue; + + /** + * Check for delegation and redirect consistency. + * Note that we check for consistency BEFORE we filter for + * private records ON PURPOSE. + * We also want consistent record sets in our local zone(s). + * The only exception is the tombstone (above) which we ignore + * for the consistency check(s). + */ + if (GNUNET_YES == GNUNET_GNSRECORD_is_zonekey_type (rd[i].record_type)) + { + have_zone_delegation = GNUNET_YES; + /* No delegation records under empty label*/ + if (have_empty_label) + { + *emsg = GNUNET_strdup (_ ( + "Record set inconsistent: Multiple delegation records.")); + return GNUNET_SYSERR; + } + } + else if (GNUNET_GNSRECORD_TYPE_REDIRECT == rd[i].record_type) + { + if (GNUNET_YES == have_redirect) + { + *emsg = GNUNET_strdup (_ ( + "Record set inconsistent: Multiple REDIRECT records.")); + return GNUNET_SYSERR; + } + have_redirect = GNUNET_YES; + /* No redirection records under empty label*/ + if (have_empty_label) + { + *emsg = GNUNET_strdup (_ ( + "Record set inconsistent: REDIRECT record under apex label.")); + return GNUNET_SYSERR; + } + } + else if (GNUNET_GNSRECORD_TYPE_GNS2DNS == rd[i].record_type) + { + have_gns2dns = GNUNET_YES; + /* No gns2dns records under empty label*/ + if (have_empty_label) + { + *emsg = GNUNET_strdup (_ ( + "Record set inconsistent: GNS2DNS record under apex label.\n")); + return GNUNET_SYSERR; + } + } + else + { + /* Some other record. + * Not allowed for zone delegations or redirections */ + if ((GNUNET_YES == have_zone_delegation) || + (GNUNET_YES == have_redirect) || + (GNUNET_YES == have_gns2dns)) + { + *emsg = GNUNET_strdup (_("Record set inconsistent: Mutually exclusive records.\n")); + return GNUNET_SYSERR; + have_other = GNUNET_YES; + } + } + + /* Ignore private records for public record set */ + + if ((GNUNET_NO != include_private) && + (0 != (rd[i].flags & GNUNET_GNSRECORD_RF_PRIVATE))) continue; + /* Skip expired records */ if ((0 == (rd[i].flags & GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION)) && (rd[i].expiration_time < now.abs_value_us)) - continue; /* record already expired, skip it */ - rd_public[rd_public_count] = rd[i]; - /* Make sure critical record types are published as such */ + continue; /* record already expired, skip it */ + rd_public[rd_count_tmp] = rd[i]; + /* Make sure critical record types are marked as such */ if (GNUNET_YES == GNUNET_GNSRECORD_is_critical (rd[i].record_type)) - rd_public[rd_public_count].flags |= GNUNET_GNSRECORD_RF_CRITICAL; - rd_public_count++; + rd_public[rd_count_tmp].flags |= GNUNET_GNSRECORD_RF_CRITICAL; + rd_count_tmp++; } - *expiry = GNUNET_GNSRECORD_record_get_expiration_time (rd_public_count, + *expiry = GNUNET_GNSRECORD_record_get_expiration_time (rd_count_tmp, rd_public, minimum_expiration); + *rd_count_public = rd_count_tmp; + return GNUNET_OK; +} + +enum GNUNET_GenericReturnValue +GNUNET_GNSRECORD_convert_records_for_export (const char *label, + const struct + GNUNET_GNSRECORD_Data *rd, + unsigned int rd_count, + struct GNUNET_GNSRECORD_Data * + rd_public, + unsigned int *rd_count_public, + struct GNUNET_TIME_Absolute *expiry, + char **emsg) +{ + return GNUNET_GNSRECORD_normalize_record_set (label, + rd, + rd_count, + rd_public, + rd_count_public, + expiry, + GNUNET_NO, + emsg); - return rd_public_count; } diff --git a/src/include/gnunet_gns_service.h b/src/include/gnunet_gns_service.h index 3f6c9b9aa..5c06f8045 100644 --- a/src/include/gnunet_gns_service.h +++ b/src/include/gnunet_gns_service.h @@ -47,12 +47,6 @@ extern "C" { #endif -/** - * String we use to indicate an empty label (top-level - * entry in the zone). DNS uses "@", so do we. - */ -#define GNUNET_GNS_EMPTY_LABEL_AT "@" - /** * Connection to the GNS service. */ diff --git a/src/include/gnunet_gnsrecord_lib.h b/src/include/gnunet_gnsrecord_lib.h index c376b1d1f..cbf7ee15c 100644 --- a/src/include/gnunet_gnsrecord_lib.h +++ b/src/include/gnunet_gnsrecord_lib.h @@ -43,6 +43,12 @@ extern "C" { #endif #endif +/** + * String we use to indicate an empty label (top-level + * entry in the zone). DNS uses "@", so do we. + */ +#define GNUNET_GNS_EMPTY_LABEL_AT "@" + /** * Maximum size of a value that can be stored in a GNS block. */ @@ -619,7 +625,8 @@ GNUNET_GNSRECORD_records_cmp (const struct GNUNET_GNSRECORD_Data *a, */ struct GNUNET_TIME_Absolute GNUNET_GNSRECORD_record_get_expiration_time (unsigned int rd_count, - const struct GNUNET_GNSRECORD_Data *rd, + const struct + GNUNET_GNSRECORD_Data *rd, struct GNUNET_TIME_Absolute min); @@ -709,22 +716,58 @@ GNUNET_GNSRECORD_is_zonekey_type (uint32_t type); enum GNUNET_GenericReturnValue GNUNET_GNSRECORD_is_critical (uint32_t type); +/** + * Normalize namestore records: Check for consistency and + * expirations. Purge expired records. Returns a "clean" record set. + * Also returns the minimum expiration time this block should be + * published under. + * Also checks rules with respect to labels (e.g. no delegations under + * the empty label) + * + * @param label the label under which this set (supposed to be) stored. + * @param rd input records + * @param rd_count size of the @a rd and @a rd_public arrays + * @param rd_public where to write the converted records + * @param rd_public_count number of records written to @a rd_public + * @param min_expiry the minimum expiration of this set + * @param include_private GNUNET_YES if private records should be included. + * @param emsg the error message if something went wrong + * @return GNUNET_OK if set could be normalized and is consistent + */ +enum GNUNET_GenericReturnValue +GNUNET_GNSRECORD_normalize_record_set (const char *label, + const struct GNUNET_GNSRECORD_Data *rd, + unsigned int rd_count, + struct GNUNET_GNSRECORD_Data *rd_public, + unsigned int *rd_count_public, + struct GNUNET_TIME_Absolute *min_expiry, + int include_private, + char **emsg); + + /** * Convert namestore records from the internal format to that - * suitable for publication (removes private records, converts - * to absolute expiration time). + * suitable for publication (removes private records). * + * @param label the label under which this set is (supposed to be) published. * @param rd input records * @param rd_count size of the @a rd and @a rd_public arrays * @param rd_public where to write the converted records + * @param rd_public_count number of records written to @a rd_public * @param expiry the expiration of the block - * @return number of records written to @a rd_public + * @param emsg the error message if something went wrong + * @return GNUNET_OK if set is consistent and can be exported */ -unsigned int -GNUNET_GNSRECORD_convert_records_for_export (const struct GNUNET_GNSRECORD_Data *rd, - unsigned int rd_count, - struct GNUNET_GNSRECORD_Data *rd_public, - struct GNUNET_TIME_Absolute *expiry); +enum GNUNET_GenericReturnValue +GNUNET_GNSRECORD_convert_records_for_export (const char *label, + const struct + GNUNET_GNSRECORD_Data *rd, + unsigned int rd_count, + struct GNUNET_GNSRECORD_Data * + rd_public, + unsigned int *rd_count_public, + struct GNUNET_TIME_Absolute *expiry, + char **emsg); #if 0 /* keep Emacsens' auto-indent happy */ { diff --git a/src/namestore/gnunet-service-namestore.c b/src/namestore/gnunet-service-namestore.c index acf49de9e..51f9b9168 100644 --- a/src/namestore/gnunet-service-namestore.c +++ b/src/namestore/gnunet-service-namestore.c @@ -808,7 +808,8 @@ send_lookup_response (struct NamestoreClient *nc, * @param rid client's request ID */ static void -send_store_response (struct NamestoreClient *nc, int res, uint32_t rid) +send_store_response (struct NamestoreClient *nc, int res, const char*emsg, + uint32_t rid) { struct GNUNET_MQ_Envelope *env; struct RecordStoreResponseMessage *rcr_msg; @@ -820,10 +821,17 @@ send_store_response (struct NamestoreClient *nc, int res, uint32_t rid) "Store requests completed", 1, GNUNET_NO); - env = GNUNET_MQ_msg (rcr_msg, - GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_STORE_RESPONSE); + env = GNUNET_MQ_msg_extra (rcr_msg, + (NULL != emsg) ? strlen (emsg) + 1 : 0, + GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_STORE_RESPONSE); rcr_msg->gns_header.r_id = htonl (rid); rcr_msg->op_result = htonl (res); + rcr_msg->reserved = htons (0); + if (NULL != emsg) + { + rcr_msg->emsg_len = htons (strlen (emsg) + 1); + memcpy (&rcr_msg[1], emsg, strlen (emsg) + 1); + } GNUNET_MQ_send (nc->mq, env); } @@ -874,7 +882,7 @@ finish_cache_operation (void *cls, int32_t success, const char *emsg) GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "CACHE operation completed\n"); GNUNET_CONTAINER_DLL_remove (cop_head, cop_tail, cop); if (NULL != cop->nc) - send_store_response (cop->nc, success, cop->rid); + send_store_response (cop->nc, success, emsg, cop->rid); if (NULL != (zi = cop->zi)) { zi->cache_ops--; @@ -931,7 +939,7 @@ refresh_block (struct NamestoreClient *nc, if (0 == res_count) { if (NULL != nc) - send_store_response (nc, GNUNET_OK, rid); + send_store_response (nc, GNUNET_OK, NULL, rid); if (rd != res) GNUNET_free (res); return; /* no data, no need to update cache */ @@ -943,7 +951,7 @@ refresh_block (struct NamestoreClient *nc, 1, GNUNET_NO); if (NULL != nc) - send_store_response (nc, GNUNET_OK, rid); + send_store_response (nc, GNUNET_OK, NULL, rid); if (rd != res) GNUNET_free (res); return; @@ -1472,11 +1480,21 @@ get_block_exp_existing (void *cls, { struct GNUNET_TIME_Absolute *exp = cls; struct GNUNET_GNSRECORD_Data rd_pub[rd_count]; + unsigned int rd_pub_count; + char *emsg; - GNUNET_GNSRECORD_convert_records_for_export (rd, + if (GNUNET_OK != GNUNET_GNSRECORD_convert_records_for_export (label, + rd, rd_count, rd_pub, - exp); + &rd_pub_count, + exp, + &emsg)) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "%s\n", emsg); + GNUNET_free (emsg); + } } @@ -1501,12 +1519,10 @@ handle_record_store (void *cls, const struct RecordStoreMessage *rp_msg) struct StoreActivity *sa; struct GNUNET_TIME_Absolute existing_block_exp; struct GNUNET_TIME_Absolute new_block_exp; - struct GNUNET_GNSRECORD_Data *tombstone_record; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received NAMESTORE_RECORD_STORE message\n"); existing_block_exp.abs_value_us = 0; - tombstone_record = NULL; rid = ntohl (rp_msg->gns_header.r_id); name_len = ntohs (rp_msg->name_len); rd_count = ntohs (rp_msg->rd_count); @@ -1560,21 +1576,23 @@ handle_record_store (void *cls, const struct RecordStoreMessage *rp_msg) /* remove "NICK" records, unless this is for the #GNUNET_GNS_EMPTY_LABEL_AT label We may need one additional record later for tombstone. + FIXME: Since we must normalize the record set (check for + consistency etc) we have to iterate the set twice. + May be inefficient. + We cannot really move the nick caching into GNSRECORD. */ - struct GNUNET_GNSRECORD_Data rd_clean[GNUNET_NZL (rd_count) + 1]; + struct GNUNET_GNSRECORD_Data rd_clean[GNUNET_NZL (rd_count)]; + struct GNUNET_GNSRECORD_Data rd_nf[GNUNET_NZL (rd_count) + 1]; unsigned int rd_clean_off; + unsigned int rd_nf_count; + char *emsg; int have_nick; rd_clean_off = 0; have_nick = GNUNET_NO; for (unsigned int i = 0; i < rd_count; i++) { - /* Do not allow to set tombstone records unless zonemaster */ rd_clean[rd_clean_off] = rd[i]; - if (GNUNET_GNSRECORD_TYPE_TOMBSTONE == rd[i].record_type) - tombstone_record = &rd_clean[rd_clean_off]; - if (GNUNET_YES == GNUNET_GNSRECORD_is_critical (rd[i].record_type)) - rd_clean[rd_clean_off].flags |= GNUNET_GNSRECORD_RF_CRITICAL; if ((0 == strcmp (GNUNET_GNS_EMPTY_LABEL_AT, conv_name)) || (GNUNET_GNSRECORD_TYPE_NICK != rd[i].record_type)) @@ -1587,10 +1605,21 @@ handle_record_store (void *cls, const struct RecordStoreMessage *rp_msg) have_nick = GNUNET_YES; } } - GNUNET_GNSRECORD_convert_records_for_export (rd, - rd_clean_off, - rd_clean, - &new_block_exp); + if (GNUNET_OK != GNUNET_GNSRECORD_normalize_record_set (conv_name, + rd_clean, + rd_clean_off, + rd_nf, + &rd_nf_count, + &new_block_exp, + GNUNET_YES, + &emsg)) + { + send_store_response (nc, res, emsg, rid); + GNUNET_free (emsg); + GNUNET_SERVICE_client_continue (nc->client); + GNUNET_free (conv_name); + return; + } /* * If existing_block_exp is 0, then there was not record set * and no tombstone. @@ -1598,27 +1627,15 @@ handle_record_store (void *cls, const struct RecordStoreMessage *rp_msg) * new block expiration would be, we need to add a tombstone * or update it. */ - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "New exp: %s\n", - GNUNET_STRINGS_absolute_time_to_string (new_block_exp)); - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Old exp: %s\n", - GNUNET_STRINGS_absolute_time_to_string (existing_block_exp)); if (GNUNET_TIME_absolute_cmp (new_block_exp, <=, existing_block_exp)) { - /* There was already a TS record in the set given */ - if (NULL != tombstone_record) - { - tombstone_record->expiration_time = existing_block_exp.abs_value_us; - } - else { - rd_clean[rd_clean_off].record_type = GNUNET_GNSRECORD_TYPE_TOMBSTONE; - rd_clean[rd_clean_off].expiration_time = existing_block_exp.abs_value_us; - rd_clean[rd_clean_off].data = NULL; - rd_clean[rd_clean_off].data_size = 0; - rd_clean[rd_clean_off].flags |= GNUNET_GNSRECORD_RF_PRIVATE; - rd_clean_off++; - } + rd_nf[rd_nf_count].record_type = GNUNET_GNSRECORD_TYPE_TOMBSTONE; + rd_nf[rd_nf_count].expiration_time = + existing_block_exp.abs_value_us; + rd_nf[rd_nf_count].data = NULL; + rd_nf[rd_nf_count].data_size = 0; + rd_nf[rd_nf_count].flags |= GNUNET_GNSRECORD_RF_PRIVATE; + rd_nf_count++; } if ((0 == strcmp (GNUNET_GNS_EMPTY_LABEL_AT, conv_name)) && (GNUNET_NO == have_nick)) @@ -1629,17 +1646,13 @@ handle_record_store (void *cls, const struct RecordStoreMessage *rp_msg) res = GSN_database->store_records (GSN_database->cls, &rp_msg->private_key, conv_name, - rd_clean_off, - rd_clean); + rd_nf_count, + rd_nf); } if (GNUNET_OK != res) { /* store not successful or zonemaster, not need to tell monitors */ - send_store_response (nc, res, rid); - GNUNET_SERVICE_client_continue (nc->client); - GNUNET_free (conv_name); - return; } sa = GNUNET_malloc (sizeof(struct StoreActivity) diff --git a/src/namestore/namestore.h b/src/namestore/namestore.h index 05a1d97ad..8391d9d74 100644 --- a/src/namestore/namestore.h +++ b/src/namestore/namestore.h @@ -113,6 +113,20 @@ struct RecordStoreResponseMessage * #GNUNET_SYSERR on failure, #GNUNET_OK on success */ int32_t op_result GNUNET_PACKED; + + /** + * Error message length + */ + uint16_t emsg_len GNUNET_PACKED; + + /** + * Reserved for alignment. + */ + uint16_t reserved GNUNET_PACKED; + + /** + * Followed by error message + */ }; diff --git a/src/namestore/namestore_api.c b/src/namestore/namestore_api.c index d4d06bab9..bb2f7465f 100644 --- a/src/namestore/namestore_api.c +++ b/src/namestore/namestore_api.c @@ -346,6 +346,44 @@ check_rd (size_t rd_len, const void *rd_buf, unsigned int rd_count) return GNUNET_OK; } +/** + * Handle an incoming message of type + * #GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_STORE_RESPONSE + * + * @param cls + * @param msg the message we received + * @return #GNUNET_OK on success, #GNUNET_SYSERR on error + */ +static int +check_record_store_response (void *cls, + const struct RecordStoreResponseMessage *msg) +{ + const char *emsg; + size_t msg_len; + size_t emsg_len; + + (void) cls; + msg_len = ntohs (msg->gns_header.header.size); + emsg_len = ntohs (msg->emsg_len); + if (0 != ntohs (msg->reserved)) + { + GNUNET_break (0); + return GNUNET_SYSERR; + } + if (msg_len != sizeof(struct RecordStoreResponseMessage) + emsg_len) + { + GNUNET_break (0); + return GNUNET_SYSERR; + } + emsg = (const char *) &msg[1]; + if ((0 != emsg_len) && ('\0' != emsg[emsg_len - 1])) + { + GNUNET_break (0); + return GNUNET_SYSERR; + } + return GNUNET_OK; +} + /** * Handle an incoming message of type @@ -364,15 +402,11 @@ handle_record_store_response (void *cls, const char *emsg; qe = find_qe (h, ntohl (msg->gns_header.r_id)); + emsg = (const char *) &msg[1]; res = ntohl (msg->op_result); LOG (GNUNET_ERROR_TYPE_DEBUG, "Received RECORD_STORE_RESPONSE with result %d\n", res); - /* TODO: add actual error message from namestore to response... */ - if (GNUNET_SYSERR == res) - emsg = _ ("Namestore failed to store record\n"); - else - emsg = NULL; if (NULL == qe) return; if (NULL != qe->cont) @@ -775,7 +809,7 @@ static void reconnect (struct GNUNET_NAMESTORE_Handle *h) { struct GNUNET_MQ_MessageHandler handlers[] = - { GNUNET_MQ_hd_fixed_size (record_store_response, + { GNUNET_MQ_hd_var_size (record_store_response, GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_STORE_RESPONSE, struct RecordStoreResponseMessage, h), diff --git a/src/zonemaster/gnunet-service-zonemaster-monitor.c b/src/zonemaster/gnunet-service-zonemaster-monitor.c index fef9e6b82..6474228f4 100644 --- a/src/zonemaster/gnunet-service-zonemaster-monitor.c +++ b/src/zonemaster/gnunet-service-zonemaster-monitor.c @@ -288,6 +288,7 @@ handle_monitor_event (void *cls, unsigned int rd_fresh_count; struct DhtPutActivity *ma; struct GNUNET_TIME_Absolute expire; + char *emsg; (void) cls; GNUNET_STATISTICS_update (statistics, @@ -300,10 +301,21 @@ handle_monitor_event (void *cls, label); /* filter out records that are not public, and convert to absolute expiration time. */ - rd_public_count = GNUNET_GNSRECORD_convert_records_for_export (rd, - rd_count, - rd_public, - &expire); + if (GNUNET_OK != GNUNET_GNSRECORD_convert_records_for_export (label, + rd, + rd_count, + rd_public, + &rd_public_count, + &expire, + &emsg)) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Zonemaster-monitor failed: %s\n", emsg); + GNUNET_free (emsg); + GNUNET_NAMESTORE_zone_monitor_next (zmon, + 1); + return; /* nothing to do */ + } if (0 == rd_public_count) { GNUNET_NAMESTORE_zone_monitor_next (zmon, diff --git a/src/zonemaster/gnunet-service-zonemaster.c b/src/zonemaster/gnunet-service-zonemaster.c index 9eb3432ee..c5dd3348d 100644 --- a/src/zonemaster/gnunet-service-zonemaster.c +++ b/src/zonemaster/gnunet-service-zonemaster.c @@ -692,13 +692,25 @@ put_gns_record (void *cls, unsigned int rd_fresh_count = 0; struct DhtPutActivity *ma; struct GNUNET_TIME_Absolute expire; + char *emsg; (void) cls; ns_iteration_left--; - rd_public_count = GNUNET_GNSRECORD_convert_records_for_export (rd, - rd_count, - rd_public, - &expire); + if (GNUNET_OK != GNUNET_GNSRECORD_convert_records_for_export (label, + rd, + rd_count, + rd_public, + &rd_public_count, + &expire, + &emsg)) + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Record set inconsistent, moving to next record set: %s\n", + emsg); + GNUNET_free (emsg); + check_zone_namestore_next (); + return; + } if (0 == rd_public_count) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, -- cgit v1.2.3