This file is part of GNUnet.
Copyright (C) 2011-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 free software: you can redistribute it and/or modify it
+ under the terms of the GNU Affero General Public License as published
+ by the Free Software Foundation, either version 3 of the License,
+ 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.
+ Affero 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.
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+ SPDX-License-Identifier: AGPL3.0-or-later
*/
/**
/**
* DHT replication level
*/
-#define DHT_GNS_REPLICATION_LEVEL 5
+#define DHT_GNS_REPLICATION_LEVEL 10
/**
* How deep do we allow recursions to go before we abort?
*/
char *label;
- /**
- * label/name suggested for shortening to the authority
- */
- char *suggested_shortening_label;
-
- /**
- * Do we already try to shorten this authority?
- */
- int shortening_started;
-
/**
* #GNUNET_YES if the authority was a GNS authority,
* #GNUNET_NO if the authority was a DNS authority.
/**
* Number of bytes in @e rd_data.
*/
- size_t rd_data_size;
+ ssize_t rd_data_size;
};
*/
char *name;
+ /**
+ * Legacy Hostname to use if we encountered GNS2DNS record
+ * and thus can deduct the LEHO from that transition.
+ */
+ char *leho;
+
/**
* DLL of results we got from DNS.
*/
}
-#if (defined WINDOWS) || (defined DARWIN)
-/* Don't have this on W32, here's a naive implementation
- * Was somehow removed on OS X ... */
-static void *
-memrchr (const void *s,
- int c,
- size_t n)
-{
- const unsigned char *ucs = s;
- ssize_t i;
-
- for (i = n - 1; i >= 0; i--)
- if (c == (int) ucs[i])
- return (void *) &ucs[i];
- return NULL;
-}
-#endif
-
-
/**
* Get the next, rightmost label from the name that we are trying to resolve,
* and update the resolution position accordingly. Labels usually consist
if ( (p->num_answers > 0) &&
(GNUNET_DNSPARSER_TYPE_CNAME == p->answers[0].type) &&
(GNUNET_DNSPARSER_TYPE_CNAME != rh->record_type) )
- {
- int af;
+ {
+ int af;
- GNUNET_free (rh->name);
- rh->name = GNUNET_strdup (p->answers[0].data.hostname);
- rh->name_resolution_pos = strlen (rh->name);
- switch (rh->record_type)
- {
- case GNUNET_DNSPARSER_TYPE_A:
- af = AF_INET;
- break;
- case GNUNET_DNSPARSER_TYPE_AAAA:
- af = AF_INET6;
- break;
- default:
- af = AF_UNSPEC;
- break;
- }
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Doing standard DNS lookup for `%s'\n",
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "Got CNAME `%s' from DNS for `%s'\n",
+ p->answers[0].data.hostname,
+ rh->name);
+ if (NULL != rh->std_resolve)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ "Multiple CNAME results from DNS resolving `%s'! Not really allowed...\n",
rh->name);
- rh->std_resolve = GNUNET_RESOLVER_ip_get (rh->name,
- af,
- DNS_LOOKUP_TIMEOUT,
- &handle_dns_result,
- rh);
- GNUNET_DNSPARSER_free_packet (p);
- return;
+ GNUNET_RESOLVER_request_cancel (rh->std_resolve);
+ }
+ GNUNET_free (rh->name);
+ rh->name = GNUNET_strdup (p->answers[0].data.hostname);
+ rh->name_resolution_pos = strlen (rh->name);
+ switch (rh->record_type)
+ {
+ case GNUNET_DNSPARSER_TYPE_A:
+ af = AF_INET;
+ break;
+ case GNUNET_DNSPARSER_TYPE_AAAA:
+ af = AF_INET6;
+ break;
+ default:
+ af = AF_UNSPEC;
+ break;
}
+ if (NULL != rh->leho)
+ add_dns_result (rh,
+ GNUNET_TIME_UNIT_HOURS.rel_value_us,
+ GNUNET_GNSRECORD_TYPE_LEHO,
+ strlen (rh->leho),
+ rh->leho);
+ rh->std_resolve = GNUNET_RESOLVER_ip_get (rh->name,
+ af,
+ DNS_LOOKUP_TIMEOUT,
+ &handle_dns_result,
+ rh);
+ GNUNET_DNSPARSER_free_packet (p);
+ GNUNET_DNSSTUB_resolve_cancel (rh->dns_request);
+ rh->dns_request = NULL;
+ return;
+ }
/* convert from (parsed) DNS to (binary) GNS format! */
rd_count = p->num_answers + p->num_authority_records + p->num_additional_records;
{
- struct GNUNET_GNSRECORD_Data rd[rd_count];
- unsigned int skip;
+ struct GNUNET_GNSRECORD_Data rd[rd_count + 1]; /* +1 for LEHO */
+ int skip;
char buf[UINT16_MAX];
size_t buf_off;
size_t buf_start;
skip++;
continue;
}
+ } /* end of for all records in answer */
+ if (NULL != rh->leho)
+ {
+ rd[rd_count - skip].record_type = GNUNET_GNSRECORD_TYPE_LEHO;
+ rd[rd_count - skip].flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION;
+ rd[rd_count - skip].expiration_time = GNUNET_TIME_UNIT_HOURS.rel_value_us;
+ rd[rd_count - skip].data = rh->leho;
+ rd[rd_count - skip].data_size = strlen (rh->leho);
+ skip--; /* skip one LESS */
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Adding LEHO %s\n",
+ rh->leho);
}
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Returning DNS response for `%s' with %u answers\n",
rh->ac_tail->label,
- (unsigned int) p->num_answers);
+ (unsigned int) (rd_count - skip));
rh->proc (rh->proc_cls,
rd_count - skip,
rd);
+ GNUNET_DNSSTUB_resolve_cancel (rh->dns_request);
+ rh->dns_request = NULL;
}
GNUNET_DNSPARSER_free_packet (p);
if (NULL != rh->task_id)
rh->original_dns_id = p->id;
GNUNET_assert (NULL != ac->authority_info.dns_authority.dns_handle);
GNUNET_assert (NULL == rh->dns_request);
+ rh->leho = GNUNET_strdup (ac->label);
rh->dns_request = GNUNET_DNSSTUB_resolve (ac->authority_info.dns_authority.dns_handle,
dns_request,
dns_request_length,
ac->gns_authority = GNUNET_YES;
ac->authority_info.gns_authority = rh->ac_tail->authority_info.gns_authority;
ac->label = resolver_lookup_get_next_label (rh);
- ac->suggested_shortening_label = NULL;
- ac->shortening_started = GNUNET_NO;
/* add AC to tail */
GNUNET_CONTAINER_DLL_insert_tail (rh->ac_head,
rh->ac_tail,
rh);
return;
}
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "Got CNAME `%s' from GNS for `%s'\n",
+ cname,
+ rh->name);
+ if (NULL != rh->std_resolve)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ "Multiple CNAME results from GNS resolving `%s'! Not really allowed...\n",
+ rh->name);
+ GNUNET_RESOLVER_request_cancel (rh->std_resolve);
+ }
/* name is absolute, go to DNS */
GNUNET_free (rh->name);
rh->name = GNUNET_strdup (cname);
vpn_ctx->vpn_request = NULL;
rh->vpn_ctx = NULL;
GNUNET_assert (GNUNET_OK ==
- GNUNET_GNSRECORD_records_deserialize (vpn_ctx->rd_data_size,
+ GNUNET_GNSRECORD_records_deserialize ((size_t) vpn_ctx->rd_data_size,
vpn_ctx->rd_data,
vpn_ctx->rd_count,
rd));
}
}
GNUNET_assert (i < vpn_ctx->rd_count);
+ if (0 == vpn_ctx->rd_count)
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ _("VPN returned empty result for `%s'\n"),
+ rh->name);
handle_gns_resolution_result (rh,
vpn_ctx->rd_count,
rd);
ac = GNUNET_new (struct AuthorityChain);
ac->rh = rh;
ac->gns_authority = GNUNET_YES;
- ac->suggested_shortening_label = NULL;
- ac->shortening_started = GNUNET_NO;
GNUNET_memcpy (&ac->authority_info.gns_authority,
rd->data,
sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
size_t off;
struct Gns2DnsPending *gp;
struct GNUNET_CRYPTO_EcdsaPublicKey zone;
+ struct sockaddr_in v4;
+ struct sockaddr_in6 v6;
if (GNUNET_GNSRECORD_TYPE_GNS2DNS != rd[i].record_type)
continue;
}
/* check if 'ip' is already an IPv4/IPv6 address */
- if (GNUNET_OK ==
- GNUNET_DNSSTUB_add_dns_ip (ac->authority_info.dns_authority.dns_handle,
- ip))
+ if ( (1 == inet_pton (AF_INET,
+ ip,
+ &v4)) ||
+ (1 == inet_pton (AF_INET6,
+ ip,
+ &v6)) )
{
+ GNUNET_break (GNUNET_OK ==
+ GNUNET_DNSSTUB_add_dns_ip (ac->authority_info.dns_authority.dns_handle,
+ ip));
ac->authority_info.dns_authority.found = GNUNET_YES;
GNUNET_free (ip);
continue;
const struct GNUNET_GNSRECORD_Data *rd)
{
struct GNS_ResolverHandle *rh = cls;
- struct AuthorityChain *shorten_ac;
char *cname;
struct VpnContext *vpn_ctx;
const struct GNUNET_TUN_GnsVpnRecord *vpn;
if (0 == rd_count)
{
GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
- _("GNS lookup failed (zero records found)\n"));
+ _("GNS lookup failed (zero records found for `%s')\n"),
+ rh->name);
fail_resolution (rh);
return;
}
vpn_ctx->rh = rh;
vpn_ctx->rd_data_size = GNUNET_GNSRECORD_records_get_size (rd_count,
rd);
- vpn_ctx->rd_data = GNUNET_malloc (vpn_ctx->rd_data_size);
+ if (vpn_ctx->rd_data_size < 0)
+ {
+ GNUNET_break_op (0);
+ GNUNET_free (vpn_ctx);
+ fail_resolution (rh);
+ return;
+ }
+ vpn_ctx->rd_data = GNUNET_malloc ((size_t) vpn_ctx->rd_data_size);
vpn_ctx->rd_count = rd_count;
GNUNET_assert (vpn_ctx->rd_data_size ==
- (size_t) GNUNET_GNSRECORD_records_serialize (rd_count,
- rd,
- vpn_ctx->rd_data_size,
- vpn_ctx->rd_data));
+ GNUNET_GNSRECORD_records_serialize (rd_count,
+ rd,
+ (size_t) vpn_ctx->rd_data_size,
+ vpn_ctx->rd_data));
vpn_ctx->vpn_request = GNUNET_VPN_redirect_to_peer (vpn_handle,
af,
ntohs (vpn->proto),
using 'scratch' array for memory allocations */
scratch_off = 0;
rd_off = 0;
- shorten_ac = rh->ac_tail;
for (unsigned int i=0;i<rd_count;i++)
{
GNUNET_assert (rd_off <= i);
GNUNET_break_op (0);
break;
}
- if (NULL == shorten_ac->suggested_shortening_label)
- shorten_ac->suggested_shortening_label = GNUNET_strdup (nick);
break;
}
case GNUNET_GNSRECORD_TYPE_PKEY:
ac->gns_authority = GNUNET_YES;
ac->authority_info.gns_authority = pub;
ac->label = GNUNET_strdup (GNUNET_GNS_EMPTY_LABEL_AT);
- ac->suggested_shortening_label = NULL;
- ac->shortening_started = GNUNET_NO;
GNUNET_CONTAINER_DLL_insert_tail (rh->ac_head,
rh->ac_tail,
ac);
fail_resolution (rh);
return;
}
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Decrypting DHT block of size %u for `%s', expires %s\n",
+ ntohl (block->purpose.size),
+ rh->name,
+ GNUNET_STRINGS_absolute_time_to_string (exp));
if (GNUNET_OK !=
GNUNET_GNSRECORD_block_decrypt (block,
&ac->authority_info.gns_authority,
"Received expired block from the DHT, will not cache it.\n");
return;
}
+ if (GNUNET_YES == disable_cache)
+ return;
/* Cache well-formed blocks */
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Caching response from the DHT in namecache\n");
if (GNUNET_CONTAINER_heap_get_size (dht_lookup_heap) > max_allowed_background_queries)
{
/* fail longest-standing DHT request */
- rx = GNUNET_CONTAINER_heap_peek (dht_lookup_heap);
+ rx = GNUNET_CONTAINER_heap_remove_root (dht_lookup_heap);
+ rx->dht_heap_node = NULL;
GNUNET_assert (NULL != rx);
fail_resolution (rx);
}
{
struct GNS_ResolverHandle *rh = cls;
+ if (0 == rd_count)
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ _("GNS namecache returned empty result for `%s'\n"),
+ rh->name);
handle_gns_resolution_result (rh,
rd_count,
rd);
ac = GNUNET_new (struct AuthorityChain);
ac->rh = rh;
ac->label = resolver_lookup_get_next_label (rh);
- ac->suggested_shortening_label = NULL;
if (NULL == ac->label)
/* name was just the "TLD", so we default to label
#GNUNET_GNS_EMPTY_LABEL_AT */
GNUNET_DNSSTUB_stop (ac->authority_info.dns_authority.dns_handle);
}
GNUNET_free (ac->label);
- GNUNET_free_non_null (ac->suggested_shortening_label);
GNUNET_free (ac);
}
if (NULL != rh->task_id)
dr);
GNUNET_free (dr);
}
+ GNUNET_free_non_null (rh->leho);
GNUNET_free (rh->name);
GNUNET_free (rh);
}