X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;ds=sidebyside;f=src%2Fgns%2Fgnunet-service-gns_resolver.c;h=daae46ab7caa3291bc56acf203d0e44817baac2f;hb=29e6158507a0758192075ac6ece7ba8e75ddc49a;hp=71af82d01a4ae3f8f10eab6db1f708953584ac94;hpb=52a5e73ced4c456e5d6951158844f047048bd4e0;p=oweals%2Fgnunet.git diff --git a/src/gns/gnunet-service-gns_resolver.c b/src/gns/gnunet-service-gns_resolver.c index 71af82d01..daae46ab7 100644 --- a/src/gns/gnunet-service-gns_resolver.c +++ b/src/gns/gnunet-service-gns_resolver.c @@ -1,6 +1,6 @@ /* This file is part of GNUnet. - (C) 2011-2013 Christian Grothoff (and other contributing authors) + 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 @@ -14,8 +14,8 @@ 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., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. + Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. */ /** @@ -23,12 +23,6 @@ * @brief GNU Name System resolver logic * @author Martin Schanzenbach * @author Christian Grothoff - * - * TODO: - * - GNS: handle special SRV names --- no delegation, direct lookup; - * can likely be done in 'resolver_lookup_get_next_label'. (#3003) - * - revocation checks (use REVOCATION service!), (#3004) - * - DNAME support (#3005) */ #include "platform.h" #include "gnunet_util_lib.h" @@ -41,6 +35,7 @@ #include "gnunet_resolver_service.h" #include "gnunet_revocation_service.h" #include "gnunet_dnsparser_lib.h" +#include "gnunet_tun_lib.h" #include "gnunet_gns_service.h" #include "gns.h" #include "gnunet-service-gns_resolver.h" @@ -56,7 +51,7 @@ /** * Default timeout for DNS lookups. */ -#define DNS_LOOKUP_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5) +#define DNS_LOOKUP_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 15) /** * Default timeout for VPN redirections. @@ -173,7 +168,7 @@ struct DnsResult /** * Expiration time for the DNS record, 0 if we didn't - * get anything useful (i.e. 'gethostbyname' was used). + * get anything useful (i.e. 'gethostbyname()' was used). */ uint64_t expiration_time; @@ -339,7 +334,7 @@ struct GNS_ResolverHandle /** * ID of a task associated with the resolution process. */ - GNUNET_SCHEDULER_TaskIdentifier task_id; + struct GNUNET_SCHEDULER_Task * task_id; /** * The name to resolve @@ -364,7 +359,19 @@ struct GNS_ResolverHandle /** * Use only cache */ - int only_cached; + enum GNUNET_GNS_LocalOptions options; + + /** + * For SRV and TLSA records, the number of the + * protocol specified in the name. 0 if no protocol was given. + */ + int protocol; + + /** + * For SRV and TLSA records, the number of the + * service specified in the name. 0 if no service was given. + */ + int service; /** * Desired type for the resolution. @@ -455,42 +462,15 @@ static struct CacheOps *co_head; */ static struct CacheOps *co_tail; - /** - * Global configuration. + * Use namecache */ -static const struct GNUNET_CONFIGURATION_Handle *cfg; +static int use_cache; -#if 0 /** - * Check if name is in srv format (_x._y.xxx) - * - * @param name - * @return #GNUNET_YES if true + * Global configuration. */ -static int -is_srv (const char *name) -{ - char *ndup; - int ret; - - if (*name != '_') - return GNUNET_NO; - if (NULL == strstr (name, "._")) - return GNUNET_NO; - ret = GNUNET_YES; - ndup = GNUNET_strdup (name); - strtok (ndup, "."); - if (NULL == strtok (NULL, ".")) - ret = GNUNET_NO; - if (NULL == strtok (NULL, ".")) - ret = GNUNET_NO; - if (NULL != strtok (NULL, ".")) - ret = GNUNET_NO; - GNUNET_free (ndup); - return ret; -} -#endif +static const struct GNUNET_CONFIGURATION_Handle *cfg; /** @@ -561,15 +541,13 @@ translate_dot_plus (struct GNS_ResolverHandle *rh, * Task scheduled to asynchronously fail a resolution. * * @param cls the 'struct GNS_ResolverHandle' of the resolution to fail - * @param tc task context */ static void -fail_resolution (void *cls, - const struct GNUNET_SCHEDULER_TaskContext *tc) +fail_resolution (void *cls) { struct GNS_ResolverHandle *rh = cls; - rh->task_id = GNUNET_SCHEDULER_NO_TASK; + rh->task_id = NULL; rh->proc (rh->proc_cls, 0, NULL); GNS_resolver_lookup_cancel (rh); } @@ -578,7 +556,7 @@ fail_resolution (void *cls, #if (defined WINDOWS) || (defined DARWIN) /* Don't have this on W32, here's a naive implementation * Was somehow removed on OS X ... */ -void * +static void * memrchr (const void *s, int c, size_t n) @@ -596,7 +574,17 @@ memrchr (const void *s, /** * Get the next, rightmost label from the name that we are trying to resolve, - * and update the resolution position accordingly. + * and update the resolution position accordingly. Labels usually consist + * of up to 63 characters without a period ("."); however, we use a special + * convention to support SRV and TLSA records where the domain name + * includes an encoding for a service and protocol in the name. The + * syntax (see RFC 2782) here is "_Service._Proto.Name" and in this + * special case we include the "_Service._Proto" in the rightmost label. + * Thus, for "_443._tcp.foo.bar" we first return the label "bar" and then + * the label "_443._tcp.foo". The special case is detected by the + * presence of labels beginning with an underscore. Whenever a label + * begins with an underscore, it is combined with the label to its right + * (and the "." is preserved). * * @param rh handle to the resolution operation to get the next label from * @return NULL if there are no more labels @@ -607,10 +595,17 @@ resolver_lookup_get_next_label (struct GNS_ResolverHandle *rh) const char *rp; const char *dot; size_t len; + char *ret; + char *srv_name; + char *proto_name; + struct protoent *pe; + struct servent *se; if (0 == rh->name_resolution_pos) return NULL; - dot = memrchr (rh->name, (int) '.', rh->name_resolution_pos); + dot = memrchr (rh->name, + (int) '.', + rh->name_resolution_pos); if (NULL == dot) { /* done, this was the last one */ @@ -625,7 +620,53 @@ resolver_lookup_get_next_label (struct GNS_ResolverHandle *rh) rp = dot + 1; rh->name_resolution_pos = dot - rh->name; } - return GNUNET_strndup (rp, len); + rh->protocol = 0; + rh->service = 0; + ret = GNUNET_strndup (rp, len); + /* If we have labels starting with underscore with label on + * the right (SRV/DANE/BOX case), determine port/protocol; + * The format of `rh->name` must be "_PORT._PROTOCOL". + */ + if ( ('_' == rh->name[0]) && + (NULL != (dot = memrchr (rh->name, + (int) '.', + rh->name_resolution_pos))) && + ('_' == dot[1]) && + (NULL == memrchr (rh->name, + (int) '.', + dot - rh->name)) ) + { + srv_name = GNUNET_strndup (&rh->name[1], + (dot - rh->name) - 1); + proto_name = GNUNET_strndup (&dot[2], + rh->name_resolution_pos - (dot - rh->name) - 1); + rh->name_resolution_pos = 0; + pe = getprotobyname (proto_name); + if (NULL == pe) + { + GNUNET_log (GNUNET_ERROR_TYPE_WARNING, + _("Protocol `%s' unknown, skipping labels.\n"), + proto_name); + GNUNET_free (proto_name); + GNUNET_free (srv_name); + return ret; + } + se = getservbyname (srv_name, + proto_name); + if (NULL == se) + { + GNUNET_log (GNUNET_ERROR_TYPE_WARNING, + _("Service `%s' unknown for protocol `%s', skipping labels.\n"), + srv_name, + proto_name); + GNUNET_free (proto_name); + GNUNET_free (srv_name); + return ret; + } + rh->protocol = pe->p_proto; + rh->service = se->s_port; + } + return ret; } @@ -724,15 +765,15 @@ handle_dns_result (void *cls, const struct sockaddr_in *sa4; const struct sockaddr_in6 *sa6; - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Received %u bytes of DNS IP data\n", - addrlen); if (NULL == addr) { rh->std_resolve = NULL; transmit_lookup_dns_result (rh); return; } + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Received %u bytes of DNS IP data\n", + addrlen); switch (addr->sa_family) { case AF_INET: @@ -765,8 +806,7 @@ handle_dns_result (void *cls, * @param tc task context */ static void -recursive_resolution (void *cls, - const struct GNUNET_SCHEDULER_TaskContext *tc); +recursive_resolution (void *cls); /** @@ -802,7 +842,7 @@ dns_result_parser (void *cls, rh->dns_request = NULL; GNUNET_SCHEDULER_cancel (rh->task_id); - rh->task_id = GNUNET_SCHEDULER_NO_TASK; + rh->task_id = NULL; p = GNUNET_DNSPARSER_parse ((const char *) dns, dns_len); if (NULL == p) @@ -823,11 +863,11 @@ dns_result_parser (void *cls, { GNUNET_free (rh->name); rh->name = GNUNET_strdup (p->answers[0].data.hostname); + rh->name_resolution_pos = strlen (rh->name); start_resolver_lookup (rh); GNUNET_DNSPARSER_free_packet (p); return; } - /* FIXME: add DNAME support */ /* convert from (parsed) DNS to (binary) GNS format! */ rd_count = p->num_answers + p->num_authority_records + p->num_additional_records; @@ -848,7 +888,7 @@ dns_result_parser (void *cls, else if (i < p->num_answers + p->num_authority_records) rec = &p->authority_records[i - p->num_answers]; else - rec = &p->authority_records[i - p->num_answers - p->num_authority_records]; + rec = &p->additional_records[i - p->num_answers - p->num_authority_records]; /* As we copied the full DNS name to 'rh->ac_tail->label', this should be the correct check to see if this record is actually a record for our label... */ @@ -1098,6 +1138,7 @@ handle_gns_cname_result (struct GNS_ResolverHandle *rh, /* name is absolute, start from the beginning */ GNUNET_free (rh->name); rh->name = GNUNET_strdup (cname); + rh->name_resolution_pos = strlen (rh->name); start_resolver_lookup (rh); } @@ -1355,10 +1396,6 @@ handle_gns_resolution_result (void *cls, rh->ac_tail->label, GNUNET_GNSRECORD_z2s (&rh->ac_tail->authority_info.gns_authority), rd_count); - - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "%u \n\n", - rh->name_resolution_pos); if (0 == rh->name_resolution_pos) { /* top-level match, are we done yet? */ @@ -1396,7 +1433,7 @@ handle_gns_resolution_result (void *cls, case GNUNET_GNSRECORD_TYPE_VPN: { af = (GNUNET_DNSPARSER_TYPE_A == rh->record_type) ? AF_INET : AF_INET6; - if (sizeof (struct GNUNET_TUN_GnsVpnRecord) < + if (sizeof (struct GNUNET_TUN_GnsVpnRecord) > rd[i].data_size) { GNUNET_break_op (0); @@ -1413,19 +1450,26 @@ handle_gns_resolution_result (void *cls, GNS_resolver_lookup_cancel (rh); return; } - GNUNET_CRYPTO_hash (vname, - strlen (vname), // FIXME: +1? - &vhash); + GNUNET_TUN_service_name_to_hash (vname, + &vhash); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Attempting VPN allocation for %s-%s (AF: %d, proto %d)\n", + GNUNET_i2s (&vpn->peer), + vname, + (int) af, + (int) ntohs (vpn->proto)); vpn_ctx = GNUNET_new (struct VpnContext); rh->vpn_ctx = vpn_ctx; 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); - (void) GNUNET_GNSRECORD_records_serialize (rd_count, - rd, - vpn_ctx->rd_data_size, - vpn_ctx->rd_data); + vpn_ctx->rd_count = rd_count; + GNUNET_assert (vpn_ctx->rd_data_size == + GNUNET_GNSRECORD_records_serialize (rd_count, + rd, + vpn_ctx->rd_data_size, + vpn_ctx->rd_data)); vpn_ctx->vpn_request = GNUNET_VPN_redirect_to_peer (vpn_handle, af, ntohs (vpn->proto), @@ -1433,7 +1477,7 @@ handle_gns_resolution_result (void *cls, &vhash, GNUNET_TIME_relative_to_absolute (VPN_TIMEOUT), &vpn_allocation_cb, - rh); + vpn_ctx); return; } case GNUNET_GNSRECORD_TYPE_GNS2DNS: @@ -1455,6 +1499,11 @@ handle_gns_resolution_result (void *cls, shorten_ac = rh->ac_tail; for (i=0;iprotocol) && + (0 != rh->service) && + (GNUNET_GNSRECORD_TYPE_BOX != rd[i].record_type) ) + continue; /* we _only_ care about boxed records */ + rd_new[rd_off] = rd[i]; /* Check if the embedded name(s) end in "+", and if so, replace the "+" with the zone at "ac_tail", changing the name @@ -1576,10 +1625,7 @@ handle_gns_resolution_result (void *cls, struct GNUNET_DNSPARSER_SrvRecord *srv; off = 0; - /* FIXME: passing rh->name here is is not necessarily what we want - (SRV support not finished) */ - srv = GNUNET_DNSPARSER_parse_srv (rh->name, - rd[i].data, + srv = GNUNET_DNSPARSER_parse_srv (rd[i].data, rd[i].data_size, &off); if ( (NULL == srv) || @@ -1589,7 +1635,6 @@ handle_gns_resolution_result (void *cls, } else { - srv->domain_name = translate_dot_plus (rh, srv->domain_name); srv->target = translate_dot_plus (rh, srv->target); scratch_start = scratch_off; if (GNUNET_OK != @@ -1615,10 +1660,10 @@ handle_gns_resolution_result (void *cls, case GNUNET_GNSRECORD_TYPE_NICK: { const char *nick; + nick = rd[i].data; - if ((GNUNET_GNSRECORD_TYPE_NICK ==rd[i].record_type) && - (rd[i].data_size > 0) && - (nick[rd[i].data_size -1] == '\0')) + if ((rd[i].data_size > 0) && + (nick[rd[i].data_size -1] != '\0')) { GNUNET_break_op (0); break; @@ -1662,10 +1707,42 @@ handle_gns_resolution_result (void *cls, case GNUNET_GNSRECORD_TYPE_GNS2DNS: { /* delegation to DNS */ + if (GNUNET_GNSRECORD_TYPE_GNS2DNS == rh->record_type) + { + rd_off++; + break; /* do not follow to DNS, we wanted the GNS2DNS record! */ + } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Found GNS2DNS record, delegating to DNS!\n"); goto do_recurse; } + case GNUNET_GNSRECORD_TYPE_BOX: + { + /* unbox SRV/TLSA records if a specific one was requested */ + if ( (0 != rh->protocol) && + (0 != rh->service) && + (rd[i].data_size >= sizeof (struct GNUNET_GNSRECORD_BoxRecord)) ) + { + const struct GNUNET_GNSRECORD_BoxRecord *box; + + box = rd[i].data; + if ( (ntohs (box->protocol) == rh->protocol) && + (ntohs (box->service) == rh->service) ) + { + /* Box matches, unbox! */ + rd_new[rd_off].record_type = ntohl (box->record_type); + rd_new[rd_off].data_size -= sizeof (struct GNUNET_GNSRECORD_BoxRecord); + rd_new[rd_off].data = &box[1]; + rd_off++; + } + } + else + { + /* no specific protocol/service specified, preserve all BOX + records (for modern, GNS-enabled applications) */ + rd_off++; + } + } default: rd_off++; break; @@ -1764,6 +1841,7 @@ handle_gns_resolution_result (void *cls, resolver to use */ g2dc = GNUNET_new (struct Gns2DnsContext); g2dc->ns = ns; + g2dc->rh = GNUNET_new (struct GNS_ResolverHandle); g2dc->rh->authority_zone = rh->ac_tail->authority_info.gns_authority; ip = translate_dot_plus (rh, ip); @@ -1772,7 +1850,7 @@ handle_gns_resolution_result (void *cls, g2dc->rh->proc = &handle_gns2dns_result; g2dc->rh->proc_cls = rh; g2dc->rh->record_type = GNUNET_GNSRECORD_TYPE_ANY; - g2dc->rh->only_cached = GNUNET_NO; + g2dc->rh->options = GNUNET_GNS_LO_DEFAULT; g2dc->rh->loop_limiter = rh->loop_limiter + 1; rh->g2dc = g2dc; start_resolver_lookup (g2dc->rh); @@ -1919,7 +1997,7 @@ handle_dht_response (void *cls, } /* Cache well-formed blocks */ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Caching response from the DHT in namestore\n"); + "Caching response from the DHT in namecache\n"); co = GNUNET_new (struct CacheOps); co->namecache_qe_cache = GNUNET_NAMECACHE_block_cache (namecache_handle, block, @@ -1931,6 +2009,61 @@ handle_dht_response (void *cls, } +/** + * Initiate a DHT query for a set of GNS records. + * + * @param rh resolution handle + * @param query key to use in the DHT lookup + */ +static void +start_dht_request (struct GNS_ResolverHandle *rh, + const struct GNUNET_HashCode *query) +{ + struct GNS_ResolverHandle *rx; + + GNUNET_assert (NULL == rh->get_handle); + rh->get_handle = GNUNET_DHT_get_start (dht_handle, + GNUNET_BLOCK_TYPE_GNS_NAMERECORD, + query, + DHT_GNS_REPLICATION_LEVEL, + GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE, + NULL, 0, + &handle_dht_response, rh); + rh->dht_heap_node = GNUNET_CONTAINER_heap_insert (dht_lookup_heap, + rh, + GNUNET_TIME_absolute_get ().abs_value_us); + 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); + GNUNET_assert (NULL != rx); + rx->proc (rx->proc_cls, 0, NULL); + GNS_resolver_lookup_cancel (rx); + } +} + + +/** + * Process a records that were decrypted from a block that we got from + * the namecache. Simply calls #handle_gns_resolution_result(). + * + * @param cls closure with the `struct GNS_ResolverHandle` + * @param rd_count number of entries in @a rd array + * @param rd array of records with data to store + */ +static void +handle_gns_namecache_resolution_result (void *cls, + unsigned int rd_count, + const struct GNUNET_GNSRECORD_Data *rd) +{ + struct GNS_ResolverHandle *rh = cls; + + handle_gns_resolution_result (rh, + rd_count, + rd); +} + + /** * Process a record that was stored in the namecache. * @@ -1938,51 +2071,40 @@ handle_dht_response (void *cls, * @param block block that was stored in the namecache */ static void -handle_namestore_block_response (void *cls, +handle_namecache_block_response (void *cls, const struct GNUNET_GNSRECORD_Block *block) { struct GNS_ResolverHandle *rh = cls; - struct GNS_ResolverHandle *rx; struct AuthorityChain *ac = rh->ac_tail; const char *label = ac->label; const struct GNUNET_CRYPTO_EcdsaPublicKey *auth = &ac->authority_info.gns_authority; struct GNUNET_HashCode query; - GNUNET_GNSRECORD_query_from_public_key (auth, - label, - &query); GNUNET_assert (NULL != rh->namecache_qe); rh->namecache_qe = NULL; - if ( (GNUNET_NO == rh->only_cached) && + if ( ( (GNUNET_GNS_LO_DEFAULT == rh->options) || + ( (GNUNET_GNS_LO_LOCAL_MASTER == rh->options) && + (ac != rh->ac_head) ) ) && ( (NULL == block) || (0 == GNUNET_TIME_absolute_get_remaining (GNUNET_TIME_absolute_ntoh (block->expiration_time)).rel_value_us) ) ) { /* namecache knows nothing; try DHT lookup */ + GNUNET_GNSRECORD_query_from_public_key (auth, + label, + &query); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Starting DHT lookup for `%s' in zone %s\n", - ac->label, - GNUNET_GNSRECORD_z2s (&ac->authority_info.gns_authority)); - GNUNET_assert (NULL == rh->get_handle); - rh->get_handle = GNUNET_DHT_get_start (dht_handle, - GNUNET_BLOCK_TYPE_GNS_NAMERECORD, - &query, - DHT_GNS_REPLICATION_LEVEL, - GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE, - NULL, 0, - &handle_dht_response, rh); - rh->dht_heap_node = GNUNET_CONTAINER_heap_insert (dht_lookup_heap, - rh, - GNUNET_TIME_absolute_get ().abs_value_us); - 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); - GNUNET_assert (NULL != rx); - rx->proc (rx->proc_cls, 0, NULL); - GNS_resolver_lookup_cancel (rx); - } + "Starting DHT lookup for `%s' in zone `%s' under key `%s'\n", + ac->label, + GNUNET_GNSRECORD_z2s (&ac->authority_info.gns_authority), + GNUNET_h2s (&query)); + start_dht_request (rh, &query); return; } + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Received result from namecache for label `%s'\n", + ac->label); + if ( (NULL == block) || (0 == GNUNET_TIME_absolute_get_remaining (GNUNET_TIME_absolute_ntoh (block->expiration_time)).rel_value_us) ) { @@ -1999,24 +2121,32 @@ handle_namestore_block_response (void *cls, GNUNET_GNSRECORD_block_decrypt (block, auth, label, - &handle_gns_resolution_result, + &handle_gns_namecache_resolution_result, rh)) { GNUNET_break_op (0); /* block was ill-formed */ - rh->proc (rh->proc_cls, 0, NULL); - GNS_resolver_lookup_cancel (rh); + /* try DHT instead */ + GNUNET_GNSRECORD_query_from_public_key (auth, + label, + &query); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Starting DHT lookup for `%s' in zone `%s' under key `%s'\n", + ac->label, + GNUNET_GNSRECORD_z2s (&ac->authority_info.gns_authority), + GNUNET_h2s (&query)); + start_dht_request (rh, &query); return; } } /** - * Lookup tail of our authority chain in the namestore. + * Lookup tail of our authority chain in the namecache. * * @param rh query we are processing */ static void -recursive_gns_resolution_namestore (struct GNS_ResolverHandle *rh) +recursive_gns_resolution_namecache (struct GNS_ResolverHandle *rh) { struct AuthorityChain *ac = rh->ac_tail; struct GNUNET_HashCode query; @@ -2028,11 +2158,19 @@ recursive_gns_resolution_namestore (struct GNS_ResolverHandle *rh) GNUNET_GNSRECORD_query_from_public_key (&ac->authority_info.gns_authority, ac->label, &query); - rh->namecache_qe = GNUNET_NAMECACHE_lookup_block (namecache_handle, - &query, - &handle_namestore_block_response, - rh); - GNUNET_assert (NULL != rh->namecache_qe); + if (GNUNET_YES == use_cache) + { + rh->namecache_qe + = GNUNET_NAMECACHE_lookup_block (namecache_handle, + &query, + &handle_namecache_block_response, + rh); + GNUNET_assert (NULL != rh->namecache_qe); + } + else + { + start_dht_request (rh, &query); + } } @@ -2059,7 +2197,7 @@ handle_revocation_result (void *cls, GNS_resolver_lookup_cancel (rh); return; } - recursive_gns_resolution_namestore (rh); + recursive_gns_resolution_namecache (rh); } @@ -2088,15 +2226,13 @@ recursive_gns_resolution_revocation (struct GNS_ResolverHandle *rh) * Task scheduled to continue with the resolution process. * * @param cls the `struct GNS_ResolverHandle` of the resolution - * @param tc task context */ static void -recursive_resolution (void *cls, - const struct GNUNET_SCHEDULER_TaskContext *tc) +recursive_resolution (void *cls) { struct GNS_ResolverHandle *rh = cls; - rh->task_id = GNUNET_SCHEDULER_NO_TASK; + rh->task_id = NULL; if (MAX_RECURSION < rh->loop_limiter++) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, @@ -2238,7 +2374,7 @@ start_resolver_lookup (struct GNS_ResolverHandle *rh) * @param record_type the record type to look up * @param name the name to look up * @param shorten_key a private key for use with PSEU import (can be NULL) - * @param only_cached #GNUNET_NO to only check locally not DHT for performance + * @param options local options to control local lookup * @param proc the processor to call on result * @param proc_cls the closure to pass to @a proc * @return handle to cancel operation @@ -2248,7 +2384,7 @@ GNS_resolver_lookup (const struct GNUNET_CRYPTO_EcdsaPublicKey *zone, uint32_t record_type, const char *name, const struct GNUNET_CRYPTO_EcdsaPrivateKey *shorten_key, - int only_cached, + enum GNUNET_GNS_LocalOptions options, GNS_ResultProcessor proc, void *proc_cls) { struct GNS_ResolverHandle *rh; @@ -2265,7 +2401,7 @@ GNS_resolver_lookup (const struct GNUNET_CRYPTO_EcdsaPublicKey *zone, rh->authority_zone = *zone; rh->proc = proc; rh->proc_cls = proc_cls; - rh->only_cached = only_cached; + rh->options = options; rh->record_type = record_type; rh->name = GNUNET_strdup (name); rh->name_resolution_pos = strlen (name); @@ -2320,10 +2456,10 @@ GNS_resolver_lookup_cancel (struct GNS_ResolverHandle *rh) GNUNET_free (rh->g2dc); rh->g2dc = NULL; } - if (GNUNET_SCHEDULER_NO_TASK != rh->task_id) + if (NULL != rh->task_id) { GNUNET_SCHEDULER_cancel (rh->task_id); - rh->task_id = GNUNET_SCHEDULER_NO_TASK; + rh->task_id = NULL; } if (NULL != rh->get_handle) { @@ -2401,6 +2537,13 @@ GNS_resolver_init (struct GNUNET_NAMECACHE_Handle *nc, dht_lookup_heap = GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN); max_allowed_background_queries = max_bg_queries; + if (GNUNET_SYSERR == (use_cache = GNUNET_CONFIGURATION_get_value_yesno (c, + "gns", + "USE_CACHE"))) + use_cache = GNUNET_YES; + if (GNUNET_NO == use_cache) + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Namecache disabled\n"); + if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string (c, "gns",