X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;ds=sidebyside;f=src%2Fgns%2Fgnunet-service-gns_resolver.c;h=c881b6b83cbee2ba9c930d41e65913d305b7d3b1;hb=f416ed5cff91ff66dadfb4797562ec5c5a0adc21;hp=f91e9b2adb936bfbc4e19265fd556da03480a309;hpb=d75c27e6acf301f6be72bcc57d3cd6b1096820c1;p=oweals%2Fgnunet.git diff --git a/src/gns/gnunet-service-gns_resolver.c b/src/gns/gnunet-service-gns_resolver.c index f91e9b2ad..c881b6b83 100644 --- a/src/gns/gnunet-service-gns_resolver.c +++ b/src/gns/gnunet-service-gns_resolver.c @@ -20,38 +20,26 @@ /** * @file gns/gnunet-service-gns_resolver.c - * @brief GNUnet GNS resolver logic + * @brief GNU Name System resolver logic * @author Martin Schanzenbach * @author Christian Grothoff * - * URGENT: - * - shortening triggers - * - We currently go to the DHT simply if we find no local reply; this - * is incorrect; the correct rules for going to DHT are: - * - * 1. The entry in the DHT is RSL_RECORD_EXPIRED OR - * 2. No entry in the NS existed AND - * 3. The zone queried is not the local resolver's zone AND - * 4. The name that was looked up is '+' - * because if it was any other canonical name we either already queried - * the DHT for the authority in the authority lookup phase (and thus - * would already have an entry in the NS for the record) - * 5. We are not in cache only mode - * - * * TODO: * - GNS: handle special SRV names --- no delegation, direct lookup; * can likely be done in 'resolver_lookup_get_next_label'. (#3003) - * - revocation checks (make optional: privacy!), (#3004) + * - revocation checks (use REVOCATION service!), (#3004) * - DNAME support (#3005) */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_dnsstub_lib.h" #include "gnunet_dht_service.h" +#include "gnunet_gnsrecord_lib.h" +#include "gnunet_namecache_service.h" #include "gnunet_namestore_service.h" #include "gnunet_dns_service.h" #include "gnunet_resolver_service.h" +#include "gnunet_revocation_service.h" #include "gnunet_dnsparser_lib.h" #include "gnunet_gns_service.h" #include "gns.h" @@ -108,10 +96,10 @@ struct AuthorityChain struct GNS_ResolverHandle *rh; /** - * label/name corresponding to the authority + * label/name corresponding to the authority */ char *label; - + /** * #GNUNET_YES if the authority was a GNS authority, * #GNUNET_NO if the authority was a DNS authority. @@ -125,9 +113,9 @@ struct AuthorityChain { /** - * The zone of the GNS authority + * The zone of the GNS authority */ - struct GNUNET_CRYPTO_EccPublicKey gns_authority; + struct GNUNET_CRYPTO_EcdsaPublicKey gns_authority; struct { @@ -148,7 +136,7 @@ struct AuthorityChain } dns_authority; } authority_info; - + }; @@ -180,7 +168,7 @@ struct DnsResult uint64_t expiration_time; /** - * Number of bytes in 'data'. + * Number of bytes in @e data. */ size_t data_size; @@ -195,10 +183,10 @@ struct DnsResult /** * Closure for #vpn_allocation_cb. */ -struct VpnContext +struct VpnContext { - /** + /** * Which resolution process are we processing. */ struct GNS_ResolverHandle *rh; @@ -209,17 +197,17 @@ struct VpnContext struct GNUNET_VPN_RedirectionRequest *vpn_request; /** - * Number of records serialized in 'rd_data'. + * Number of records serialized in @e rd_data. */ unsigned int rd_count; - + /** * Serialized records. */ char *rd_data; - + /** - * Number of bytes in 'rd_data'. + * Number of bytes in @e rd_data. */ size_t rd_data_size; }; @@ -227,38 +215,38 @@ struct VpnContext /** * Handle to a currenty pending resolution. On result (positive or - * negative) the #GNS_ResultProcessor is called. + * negative) the #GNS_ResultProcessor is called. */ struct GNS_ResolverHandle { /** - * DLL + * DLL */ struct GNS_ResolverHandle *next; /** - * DLL + * DLL */ struct GNS_ResolverHandle *prev; /** - * The top-level GNS authoritative zone to query + * The top-level GNS authoritative zone to query */ - struct GNUNET_CRYPTO_EccPublicKey authority_zone; + struct GNUNET_CRYPTO_EcdsaPublicKey authority_zone; /** - * called when resolution phase finishes + * called when resolution phase finishes */ GNS_ResultProcessor proc; - + /** - * closure passed to proc + * closure passed to proc */ void* proc_cls; /** - * Handle for DHT lookups. should be NULL if no lookups are in progress + * Handle for DHT lookups. should be NULL if no lookups are in progress */ struct GNUNET_DHT_GetHandle *get_handle; @@ -278,9 +266,14 @@ struct GNS_ResolverHandle struct GNUNET_RESOLVER_RequestHandle *std_resolve; /** - * Pending Namestore task + * Pending Namecache lookup task + */ + struct GNUNET_NAMECACHE_QueueEntry *namecache_qe; + + /** + * Pending revocation check. */ - struct GNUNET_NAMESTORE_QueueEntry *namestore_qe; + struct GNUNET_REVOCATION_Query *rev_check; /** * Heap node associated with this lookup. Used to limit number of @@ -289,19 +282,19 @@ struct GNS_ResolverHandle struct GNUNET_CONTAINER_HeapNode *dht_heap_node; /** - * DLL to store the authority chain + * DLL to store the authority chain */ struct AuthorityChain *ac_head; /** - * DLL to store the authority chain + * DLL to store the authority chain */ struct AuthorityChain *ac_tail; /** * Private key of the shorten zone, NULL to not shorten. */ - struct GNUNET_CRYPTO_EccPrivateKey *shorten_key; + struct GNUNET_CRYPTO_EcdsaPrivateKey *shorten_key; /** * ID of a task associated with the resolution process. @@ -309,7 +302,7 @@ struct GNS_ResolverHandle GNUNET_SCHEDULER_TaskIdentifier task_id; /** - * The name to resolve + * The name to resolve */ char *name; @@ -329,7 +322,7 @@ struct GNS_ResolverHandle size_t name_resolution_pos; /** - * Use only cache + * Use only cache */ int only_cached; @@ -340,7 +333,7 @@ struct GNS_ResolverHandle /** * We increment the loop limiter for each step in a recursive - * resolution. If it passes our threshold (i.e. due to + * resolution. If it passes our threshold (i.e. due to * self-recursion in the resolution, i.e CNAME fun), we stop. */ unsigned int loop_limiter; @@ -349,9 +342,33 @@ struct GNS_ResolverHandle /** - * Our handle to the namestore service + * Active namestore caching operations. + */ +struct CacheOps +{ + + /** + * Organized in a DLL. + */ + struct CacheOps *next; + + /** + * Organized in a DLL. + */ + struct CacheOps *prev; + + /** + * Pending Namestore caching task. + */ + struct GNUNET_NAMECACHE_QueueEntry *namecache_qe_cache; + +}; + + +/** + * Our handle to the namecache service */ -static struct GNUNET_NAMESTORE_Handle *namestore_handle; +static struct GNUNET_NAMECACHE_Handle *namecache_handle; /** * Our handle to the vpn service @@ -388,13 +405,23 @@ static struct GNS_ResolverHandle *rlh_head; */ static struct GNS_ResolverHandle *rlh_tail; +/** + * Organized in a DLL. + */ +static struct CacheOps *co_head; + +/** + * Organized in a DLL. + */ +static struct CacheOps *co_tail; + /** * Global configuration. */ static const struct GNUNET_CONFIGURATION_Handle *cfg; - +#if 0 /** * Check if name is in srv format (_x._y.xxx) * @@ -423,6 +450,7 @@ is_srv (const char *name) GNUNET_free (ndup); return ret; } +#endif /** @@ -451,7 +479,7 @@ is_canonical (const char *name) if ('_' != name[0]) return GNUNET_NO; pos = &name[1]; - while (NULL != (dot = strchr (pos, '.'))) + while (NULL != (dot = strchr (pos, '.'))) if ('_' != dot[1]) return GNUNET_NO; else @@ -462,7 +490,7 @@ is_canonical (const char *name) /* ************************** Resolution **************************** */ /** - * Exands a name ending in .+ with the zone of origin. + * Expands a name ending in .+ with the zone of origin. * * @param rh resolution context * @param name name to modify (to be free'd or returned) @@ -483,7 +511,7 @@ translate_dot_plus (struct GNS_ResolverHandle *rh, "%.*s.%s", (int) (s_len - 2), name, - GNUNET_NAMESTORE_pkey_to_zkey (&rh->ac_tail->authority_info.gns_authority)); + GNUNET_GNSRECORD_pkey_to_zkey (&rh->ac_tail->authority_info.gns_authority)); GNUNET_free (name); return ret; } @@ -506,22 +534,26 @@ fail_resolution (void *cls, GNS_resolver_lookup_cancel (rh); } + #if (defined WINDOWS) || (defined DARWIN) /* Don't have this on W32, here's a naive implementation * Was somehow removed on OS X ... */ void * -memrchr (const void *s, int c, size_t n) +memrchr (const void *s, + int c, + size_t n) { - size_t i; - unsigned char *ucs = (unsigned char *) s; + const unsigned char *ucs = s; + ssize_t i; for (i = n - 1; i >= 0; i--) - if (ucs[i] == c) + 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. @@ -544,7 +576,7 @@ resolver_lookup_get_next_label (struct GNS_ResolverHandle *rh) /* done, this was the last one */ len = rh->name_resolution_pos; rp = rh->name; - rh->name_resolution_pos = 0; + rh->name_resolution_pos = 0; } else { @@ -552,8 +584,8 @@ resolver_lookup_get_next_label (struct GNS_ResolverHandle *rh) len = rh->name_resolution_pos - (dot - rh->name) - 1; rp = dot + 1; rh->name_resolution_pos = dot - rh->name; - } - return GNUNET_strndup (rp, len); + } + return GNUNET_strndup (rp, len); } @@ -573,7 +605,7 @@ transmit_lookup_dns_result (struct GNS_ResolverHandle *rh) for (pos = rh->dns_result_head; NULL != pos; pos = pos->next) n++; { - struct GNUNET_NAMESTORE_RecordData rd[n]; + struct GNUNET_GNSRECORD_Data rd[n]; i = 0; for (pos = rh->dns_result_head; NULL != pos; pos = pos->next) @@ -583,15 +615,20 @@ transmit_lookup_dns_result (struct GNS_ResolverHandle *rh) rd[i].record_type = pos->record_type; if (0 == pos->expiration_time) { - rd[i].flags = GNUNET_NAMESTORE_RF_RELATIVE_EXPIRATION; + rd[i].flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION; rd[i].expiration_time = 0; } else { - rd[i].flags = GNUNET_NAMESTORE_RF_NONE; + rd[i].flags = GNUNET_GNSRECORD_RF_NONE; rd[i].expiration_time = pos->expiration_time; } - } + i++; + } + GNUNET_assert (i == n); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Transmitting standard DNS result with %u records\n", + n); rh->proc (rh->proc_cls, n, rd); @@ -634,7 +671,7 @@ add_dns_result (struct GNS_ResolverHandle *rh, * We had to do a DNS lookup. Convert the result (if any) and return * it. * - * @param cls closure with the 'struct GNS_ResolverHandle' + * @param cls closure with the `struct GNS_ResolverHandle` * @param addr one of the addresses of the host, NULL for the last address * @param addrlen length of the address */ @@ -647,9 +684,12 @@ handle_dns_result (void *cls, const struct sockaddr_in *sa4; const struct sockaddr_in6 *sa6; - rh->std_resolve = NULL; + 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; } @@ -706,7 +746,7 @@ start_resolver_lookup (struct GNS_ResolverHandle *rh); * we were attempting to make * @param rs socket that received the response * @param dns dns response, never NULL - * @param dns_len number of bytes in 'dns' + * @param dns_len number of bytes in @a dns */ static void dns_result_parser (void *cls, @@ -723,7 +763,7 @@ dns_result_parser (void *cls, rh->dns_request = NULL; GNUNET_SCHEDULER_cancel (rh->task_id); rh->task_id = GNUNET_SCHEDULER_NO_TASK; - p = GNUNET_DNSPARSER_parse ((const char *) dns, + p = GNUNET_DNSPARSER_parse ((const char *) dns, dns_len); if (NULL == p) { @@ -733,7 +773,10 @@ dns_result_parser (void *cls, GNS_resolver_lookup_cancel (rh); return; } - + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Received DNS response for `%s' with %u answers\n", + rh->ac_tail->label, + (unsigned int) p->num_answers); if ( (p->num_answers > 0) && (GNUNET_DNSPARSER_TYPE_CNAME == p->answers[0].type) && (GNUNET_DNSPARSER_TYPE_CNAME != rh->record_type) ) @@ -741,17 +784,19 @@ dns_result_parser (void *cls, GNUNET_free (rh->name); rh->name = GNUNET_strdup (p->answers[0].data.hostname); start_resolver_lookup (rh); - return; + 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; { - struct GNUNET_NAMESTORE_RecordData rd[rd_count]; + struct GNUNET_GNSRECORD_Data rd[rd_count]; unsigned int skip; char buf[UINT16_MAX]; size_t buf_off; + size_t buf_start; buf_off = 0; skip = 0; @@ -762,7 +807,7 @@ dns_result_parser (void *cls, rec = &p->answers[i]; else if (i < p->num_answers + p->num_authority_records) rec = &p->authority_records[i - p->num_answers]; - else + else rec = &p->authority_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 @@ -804,6 +849,7 @@ dns_result_parser (void *cls, case GNUNET_DNSPARSER_TYPE_CNAME: case GNUNET_DNSPARSER_TYPE_PTR: case GNUNET_DNSPARSER_TYPE_NS: + buf_start = buf_off; if (GNUNET_OK != GNUNET_DNSPARSER_builder_add_name (buf, sizeof (buf), @@ -814,8 +860,11 @@ dns_result_parser (void *cls, skip++; continue; } + rd[i - skip].data_size = buf_off - buf_start; + rd[i - skip].data = &buf[buf_start]; break; case GNUNET_DNSPARSER_TYPE_SOA: + buf_start = buf_off; if (GNUNET_OK != GNUNET_DNSPARSER_builder_add_soa (buf, sizeof (buf), @@ -826,8 +875,11 @@ dns_result_parser (void *cls, skip++; continue; } + rd[i - skip].data_size = buf_off - buf_start; + rd[i - skip].data = &buf[buf_start]; break; case GNUNET_DNSPARSER_TYPE_MX: + buf_start = buf_off; if (GNUNET_OK != GNUNET_DNSPARSER_builder_add_mx (buf, sizeof (buf), @@ -838,8 +890,11 @@ dns_result_parser (void *cls, skip++; continue; } + rd[i - skip].data_size = buf_off - buf_start; + rd[i - skip].data = &buf[buf_start]; break; case GNUNET_DNSPARSER_TYPE_SRV: + buf_start = buf_off; if (GNUNET_OK != GNUNET_DNSPARSER_builder_add_srv (buf, sizeof (buf), @@ -850,6 +905,8 @@ dns_result_parser (void *cls, skip++; continue; } + rd[i - skip].data_size = buf_off - buf_start; + rd[i - skip].data = &buf[buf_start]; break; default: GNUNET_log (GNUNET_ERROR_TYPE_INFO, @@ -859,9 +916,13 @@ dns_result_parser (void *cls, continue; } } + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Returning DNS response for `%s' with %u answers\n", + rh->ac_tail->label, + (unsigned int) p->num_answers); rh->proc (rh->proc_cls, rd_count - skip, rd); GNS_resolver_lookup_cancel (rh); - } + } GNUNET_DNSPARSER_free_packet (p); } @@ -886,6 +947,9 @@ recursive_dns_resolution (struct GNS_ResolverHandle *rh) ac = rh->ac_tail; GNUNET_assert (NULL != ac); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Starting DNS lookup for `%s'\n", + ac->label); GNUNET_assert (GNUNET_NO == ac->gns_authority); switch (((const struct sockaddr *) &ac->authority_info.dns_authority.dns_ip)->sa_family) { @@ -904,7 +968,7 @@ recursive_dns_resolution (struct GNS_ResolverHandle *rh) query = GNUNET_new (struct GNUNET_DNSPARSER_Query); query->name = GNUNET_strdup (ac->label); query->type = rh->record_type; - query->class = GNUNET_TUN_DNS_CLASS_INTERNET; + query->dns_traffic_class = GNUNET_TUN_DNS_CLASS_INTERNET; p = GNUNET_new (struct GNUNET_DNSPARSER_Packet); p->queries = query; p->num_queries = 1; @@ -912,7 +976,7 @@ recursive_dns_resolution (struct GNS_ResolverHandle *rh) UINT16_MAX); p->flags.opcode = GNUNET_TUN_DNS_OPCODE_QUERY; p->flags.recursion_desired = 1; - if (GNUNET_OK != + if (GNUNET_OK != GNUNET_DNSPARSER_pack (p, 1024, &dns_request, &dns_request_length)) { GNUNET_break (0); @@ -942,7 +1006,7 @@ recursive_dns_resolution (struct GNS_ResolverHandle *rh) * Merge it into our chain. * * @param rh resolution we are performing - * @param cname value of the cname record we got for the current + * @param cname value of the cname record we got for the current * authority chain tail */ static void @@ -951,6 +1015,7 @@ handle_gns_cname_result (struct GNS_ResolverHandle *rh, { size_t nlen; char *res; + struct AuthorityChain *ac; nlen = strlen (cname); if ( (nlen > 2) && @@ -975,6 +1040,20 @@ handle_gns_cname_result (struct GNS_ResolverHandle *rh, } GNUNET_free (rh->name); rh->name = res; + ac = GNUNET_new (struct AuthorityChain); + ac->rh = rh; + 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); + /* tigger shortening */ + if (NULL != rh->shorten_key) + GNS_shorten_start (rh->ac_tail->label, + &ac->authority_info.gns_authority, + rh->shorten_key); + /* add AC to tail */ + GNUNET_CONTAINER_DLL_insert_tail (rh->ac_head, + rh->ac_tail, + ac); rh->task_id = GNUNET_SCHEDULER_add_now (&recursive_resolution, rh); return; @@ -996,7 +1075,7 @@ handle_gns_cname_result (struct GNS_ResolverHandle *rh, static void handle_gns_resolution_result (void *cls, unsigned int rd_count, - const struct GNUNET_NAMESTORE_RecordData *rd); + const struct GNUNET_GNSRECORD_Data *rd); /** @@ -1010,7 +1089,7 @@ handle_gns_resolution_result (void *cls, * will match 'result_af' from the request * @param address IP address (struct in_addr or struct in_addr6, depending on 'af') * that the VPN allocated for the redirection; - * traffic to this IP will now be redirected to the + * traffic to this IP will now be redirected to the * specified target peer; NULL on error */ static void @@ -1020,23 +1099,23 @@ vpn_allocation_cb (void *cls, { struct VpnContext *vpn_ctx = cls; struct GNS_ResolverHandle *rh = vpn_ctx->rh; - struct GNUNET_NAMESTORE_RecordData rd[vpn_ctx->rd_count]; + struct GNUNET_GNSRECORD_Data rd[vpn_ctx->rd_count]; unsigned int i; vpn_ctx->vpn_request = NULL; rh->vpn_ctx = NULL; GNUNET_assert (GNUNET_OK == - GNUNET_NAMESTORE_records_deserialize (vpn_ctx->rd_data_size, + GNUNET_GNSRECORD_records_deserialize (vpn_ctx->rd_data_size, vpn_ctx->rd_data, vpn_ctx->rd_count, rd)); for (i=0;ird_count;i++) { - if (GNUNET_NAMESTORE_TYPE_VPN == rd[i].record_type) + if (GNUNET_GNSRECORD_TYPE_VPN == rd[i].record_type) { switch (af) { - case AF_INET: + case AF_INET: rd[i].record_type = GNUNET_DNSPARSER_TYPE_A; rd[i].data_size = sizeof (struct in_addr); rd[i].expiration_time = GNUNET_TIME_relative_to_absolute (VPN_TIMEOUT).abs_value_us; @@ -1052,12 +1131,12 @@ vpn_allocation_cb (void *cls, break; default: GNUNET_assert (0); - } + } break; } } GNUNET_assert (i < vpn_ctx->rd_count); - handle_gns_resolution_result (rh, + handle_gns_resolution_result (rh, vpn_ctx->rd_count, rd); GNUNET_free (vpn_ctx->rd_data); @@ -1068,14 +1147,14 @@ vpn_allocation_cb (void *cls, /** * Process a records that were decrypted from a block. * - * @param cls closure with the 'struct GNS_ResolverHandle' + * @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_resolution_result (void *cls, unsigned int rd_count, - const struct GNUNET_NAMESTORE_RecordData *rd) + const struct GNUNET_GNSRECORD_Data *rd) { struct GNS_ResolverHandle *rh = cls; struct AuthorityChain *ac; @@ -1095,9 +1174,14 @@ handle_gns_resolution_result (void *cls, size_t scratch_off; size_t scratch_start; size_t off; - struct GNUNET_NAMESTORE_RecordData rd_new[rd_count]; + struct GNUNET_GNSRECORD_Data rd_new[rd_count]; unsigned int rd_off; - + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Resolution succeeded for `%s' in zone %s, got %u records\n", + rh->ac_tail->label, + GNUNET_GNSRECORD_z2s (&rh->ac_tail->authority_info.gns_authority), + rd_count); if (0 == rh->name_resolution_pos) { /* top-level match, are we done yet? */ @@ -1105,12 +1189,23 @@ handle_gns_resolution_result (void *cls, (GNUNET_DNSPARSER_TYPE_CNAME == rd[0].record_type) && (GNUNET_DNSPARSER_TYPE_CNAME != rh->record_type) ) { - cname = GNUNET_strndup (rd[0].data, - rd[0].data_size); - handle_gns_cname_result (rh, + off = 0; + cname = GNUNET_DNSPARSER_parse_name (rd[0].data, + rd[0].data_size, + &off); + if ( (NULL == cname) || + (off != rd[0].data_size) ) + { + GNUNET_break_op (0); + rh->proc (rh->proc_cls, 0, NULL); + GNS_resolver_lookup_cancel (rh); + GNUNET_free_non_null (cname); + return; + } + handle_gns_cname_result (rh, cname); GNUNET_free (cname); - return; + return; } /* If A/AAAA was requested, but we got a VPN record, we convert it to A/AAAA using GNUnet VPN */ @@ -1119,49 +1214,60 @@ handle_gns_resolution_result (void *cls, { for (i=0;irecord_type) ? AF_INET : AF_INET6; - if (sizeof (struct GNUNET_TUN_GnsVpnRecord) < - rd[i].data_size) + case GNUNET_GNSRECORD_TYPE_VPN: { - GNUNET_break_op (0); - rh->proc (rh->proc_cls, 0, NULL); - GNS_resolver_lookup_cancel (rh); - return; + af = (GNUNET_DNSPARSER_TYPE_A == rh->record_type) ? AF_INET : AF_INET6; + if (sizeof (struct GNUNET_TUN_GnsVpnRecord) < + rd[i].data_size) + { + GNUNET_break_op (0); + rh->proc (rh->proc_cls, 0, NULL); + GNS_resolver_lookup_cancel (rh); + return; + } + vpn = (const struct GNUNET_TUN_GnsVpnRecord *) rd[i].data; + vname = (const char *) &vpn[1]; + if ('\0' != vname[rd[i].data_size - 1 - sizeof (struct GNUNET_TUN_GnsVpnRecord)]) + { + GNUNET_break_op (0); + rh->proc (rh->proc_cls, 0, NULL); + GNS_resolver_lookup_cancel (rh); + return; + } + GNUNET_CRYPTO_hash (vname, + strlen (vname), // FIXME: +1? + &vhash); + 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->vpn_request = GNUNET_VPN_redirect_to_peer (vpn_handle, + af, + ntohs (vpn->proto), + &vpn->peer, + &vhash, + GNUNET_TIME_relative_to_absolute (VPN_TIMEOUT), + &vpn_allocation_cb, + rh); + return; } - vpn = (const struct GNUNET_TUN_GnsVpnRecord *) rd[i].data; - vname = (const char *) &vpn[1]; - if ('\0' != vname[rd[i].data_size - 1 - sizeof (struct GNUNET_TUN_GnsVpnRecord)]) + case GNUNET_GNSRECORD_TYPE_GNS2DNS: { - GNUNET_break_op (0); - rh->proc (rh->proc_cls, 0, NULL); - GNS_resolver_lookup_cancel (rh); - return; + /* delegation to DNS */ + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Found GNS2DNS record, delegating to DNS!\n"); + goto do_recurse; } - GNUNET_CRYPTO_hash (vname, - strlen (vname), // FIXME: +1? - &vhash); - vpn_ctx = GNUNET_new (struct VpnContext); - rh->vpn_ctx = vpn_ctx; - vpn_ctx->rh = rh; - vpn_ctx->rd_data_size = GNUNET_NAMESTORE_records_get_size (rd_count, - rd); - vpn_ctx->rd_data = GNUNET_malloc (vpn_ctx->rd_data_size); - (void) GNUNET_NAMESTORE_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), - &vpn->peer, - &vhash, - GNUNET_NO, - GNUNET_TIME_relative_to_absolute (VPN_TIMEOUT), - &vpn_allocation_cb, - rh); - return; + default: + break; } } } @@ -1194,6 +1300,7 @@ handle_gns_resolution_result (void *cls, else { cname = translate_dot_plus (rh, cname); + GNUNET_break (NULL != cname); scratch_start = scratch_off; if (GNUNET_OK != GNUNET_DNSPARSER_builder_add_name (scratch, @@ -1209,8 +1316,8 @@ handle_gns_resolution_result (void *cls, rd_new[rd_off].data_size = scratch_off - scratch_start; rd_off++; } - GNUNET_free (cname); } + GNUNET_free_non_null (cname); } break; case GNUNET_DNSPARSER_TYPE_SOA: @@ -1245,8 +1352,9 @@ handle_gns_resolution_result (void *cls, rd_new[rd_off].data_size = scratch_off - scratch_start; rd_off++; } - GNUNET_DNSPARSER_free_soa (soa); } + if (NULL != soa) + GNUNET_DNSPARSER_free_soa (soa); } break; case GNUNET_DNSPARSER_TYPE_MX: @@ -1280,16 +1388,17 @@ handle_gns_resolution_result (void *cls, rd_new[rd_off].data_size = scratch_off - scratch_start; rd_off++; } - GNUNET_DNSPARSER_free_mx (mx); } - } + if (NULL != mx) + GNUNET_DNSPARSER_free_mx (mx); + } break; case GNUNET_DNSPARSER_TYPE_SRV: { struct GNUNET_DNSPARSER_SrvRecord *srv; off = 0; - /* FIXME: passing rh->name here is is not necessarily what we want + /* 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, @@ -1319,34 +1428,86 @@ handle_gns_resolution_result (void *cls, rd_new[rd_off].data_size = scratch_off - scratch_start; rd_off++; } - GNUNET_DNSPARSER_free_srv (srv); } + if (NULL != srv) + GNUNET_DNSPARSER_free_srv (srv); } break; + case GNUNET_GNSRECORD_TYPE_PKEY: + { + struct GNUNET_CRYPTO_EcdsaPublicKey pub; + + if (rd[i].data_size != sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)) + { + GNUNET_break_op (0); + break; + } + memcpy (&pub, rd[i].data, rd[i].data_size); + + /* tigger shortening */ + if (NULL != rh->shorten_key) + { + GNS_shorten_start (rh->ac_tail->label, + &pub, + rh->shorten_key); + } + rd_off++; + if (GNUNET_GNSRECORD_TYPE_PKEY != rh->record_type) + { + /* try to resolve "+" */ + struct AuthorityChain *ac; + + ac = GNUNET_new (struct AuthorityChain); + ac->rh = rh; + ac->gns_authority = GNUNET_YES; + ac->authority_info.gns_authority = pub; + ac->label = GNUNET_strdup (GNUNET_GNS_MASTERZONE_STR); + GNUNET_CONTAINER_DLL_insert_tail (rh->ac_head, + rh->ac_tail, + ac); + rh->task_id = GNUNET_SCHEDULER_add_now (&recursive_resolution, + rh); + return; + } + } + break; + case GNUNET_GNSRECORD_TYPE_GNS2DNS: + { + /* delegation to DNS */ + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Found GNS2DNS record, delegating to DNS!\n"); + goto do_recurse; + } default: + rd_off++; break; } } - + /* yes, we are done, return result */ + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Returning GNS response for `%s' with %u answers\n", + rh->ac_tail->label, + rd_off); rh->proc (rh->proc_cls, rd_off, rd_new); GNS_resolver_lookup_cancel (rh); - return; + return; } + do_recurse: /* need to recurse, check if we can */ for (i=0;iproc (rh->proc_cls, 0, NULL); GNS_resolver_lookup_cancel (rh); - return; + return; } /* expand authority chain */ ac = GNUNET_new (struct AuthorityChain); @@ -1354,119 +1515,167 @@ handle_gns_resolution_result (void *cls, ac->gns_authority = GNUNET_YES; memcpy (&ac->authority_info.gns_authority, rd[i].data, - sizeof (struct GNUNET_CRYPTO_EccPublicKey)); + sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)); ac->label = resolver_lookup_get_next_label (rh); + /* tigger shortening */ + if (NULL != rh->shorten_key) + GNS_shorten_start (rh->ac_tail->label, + &ac->authority_info.gns_authority, + rh->shorten_key); + /* add AC to tail */ GNUNET_CONTAINER_DLL_insert_tail (rh->ac_head, rh->ac_tail, ac); /* recurse */ rh->task_id = GNUNET_SCHEDULER_add_now (&recursive_resolution, rh); - break; - case GNUNET_DNSPARSER_TYPE_NS: - /* resolution continues within DNS */ - if (GNUNET_DNSPARSER_MAX_NAME_LENGTH < rd[i].data_size) - { - GNUNET_break_op (0); - rh->proc (rh->proc_cls, 0, NULL); - GNS_resolver_lookup_cancel (rh); - return; - } - /* find associated A/AAAA record */ - sa = NULL; - for (j=0;jproc (rh->proc_cls, 0, NULL); - GNS_resolver_lookup_cancel (rh); - return; - } - /* FIXME: might want to check if we support IPv4 here, - and otherwise skip this one and hope we find another */ - memset (&v4, 0, sizeof (v4)); - sa_len = sizeof (v4); - v4.sin_family = AF_INET; - v4.sin_port = htons (53); + GNUNET_break_op (0); + rh->proc (rh->proc_cls, 0, NULL); + GNS_resolver_lookup_cancel (rh); + return; + } + /* find associated A/AAAA record */ + sa = NULL; + sa_len = 0; + for (j=0;jproc (rh->proc_cls, 0, NULL); + GNS_resolver_lookup_cancel (rh); + return; + } + /* FIXME: might want to check if we support IPv4 here, + and otherwise skip this one and hope we find another */ + memset (&v4, 0, sizeof (v4)); + sa_len = sizeof (v4); + v4.sin_family = AF_INET; + v4.sin_port = htons (53); #if HAVE_SOCKADDR_IN_SIN_LEN - v4.sin_len = (u_char) sa_len; + v4.sin_len = (u_char) sa_len; #endif - memcpy (&v4.sin_addr, - rd[j].data, - sizeof (struct in_addr)); - sa = (struct sockaddr *) &v4; - break; - case GNUNET_DNSPARSER_TYPE_AAAA: - if (sizeof (struct in6_addr) != rd[i].data_size) - { - GNUNET_break_op (0); - rh->proc (rh->proc_cls, 0, NULL); - GNS_resolver_lookup_cancel (rh); - return; - } - /* FIXME: might want to check if we support IPv6 here, - and otherwise skip this one and hope we find another */ - memset (&v6, 0, sizeof (v6)); - sa_len = sizeof (v6); - v6.sin6_family = AF_INET6; - v6.sin6_port = htons (53); + memcpy (&v4.sin_addr, + rd[j].data, + sizeof (struct in_addr)); + sa = (struct sockaddr *) &v4; + break; + case GNUNET_DNSPARSER_TYPE_AAAA: + if (sizeof (struct in6_addr) != rd[j].data_size) + { + GNUNET_break_op (0); + rh->proc (rh->proc_cls, 0, NULL); + GNS_resolver_lookup_cancel (rh); + return; + } + /* FIXME: might want to check if we support IPv6 here, + and otherwise skip this one and hope we find another */ + memset (&v6, 0, sizeof (v6)); + sa_len = sizeof (v6); + v6.sin6_family = AF_INET6; + v6.sin6_port = htons (53); #if HAVE_SOCKADDR_IN_SIN_LEN - v6.sin6_len = (u_char) sa_len; + v6.sin6_len = (u_char) sa_len; #endif - memcpy (&v6.sin6_addr, - rd[j].data, - sizeof (struct in6_addr)); - sa = (struct sockaddr *) &v6; - break; + memcpy (&v6.sin6_addr, + rd[j].data, + sizeof (struct in6_addr)); + sa = (struct sockaddr *) &v6; + break; + default: + break; + } + if (NULL != sa) + break; } - if (NULL != sa) - break; + if (NULL == sa) + { + /* we cannot continue; NS without A/AAAA */ + rh->proc (rh->proc_cls, 0, NULL); + GNS_resolver_lookup_cancel (rh); + return; + } + /* expand authority chain */ + ac = GNUNET_new (struct AuthorityChain); + ac->rh = rh; + off = 0; + ns = GNUNET_DNSPARSER_parse_name (rd[i].data, + rd[i].data_size, + &off); + if ( (NULL == ns) || + (off != rd[i].data_size) ) + { + GNUNET_break_op (0); /* record not well-formed */ + rh->proc (rh->proc_cls, 0, NULL); + GNS_resolver_lookup_cancel (rh); + GNUNET_free_non_null (ns); + GNUNET_free (ac); + return; + } + strcpy (ac->authority_info.dns_authority.name, + ns); + memcpy (&ac->authority_info.dns_authority.dns_ip, + sa, + sa_len); + /* for DNS recursion, the label is the full DNS name, + created from the remainder of the GNS name and the + name in the NS record */ + GNUNET_asprintf (&ac->label, + "%.*s%s%s", + (int) rh->name_resolution_pos, + rh->name, + (0 != rh->name_resolution_pos) ? "." : "", + ns); + GNUNET_free (ns); + GNUNET_CONTAINER_DLL_insert_tail (rh->ac_head, + rh->ac_tail, + ac); + if (strlen (ac->label) > GNUNET_DNSPARSER_MAX_NAME_LENGTH) + { + GNUNET_log (GNUNET_ERROR_TYPE_WARNING, + _("GNS lookup resulted in DNS name that is too long (`%s')\n"), + ac->label); + rh->proc (rh->proc_cls, 0, NULL); + GNS_resolver_lookup_cancel (rh); + return; + } + /* recurse */ + rh->task_id = GNUNET_SCHEDULER_add_now (&recursive_resolution, + rh); + return; } - /* expand authority chain */ - ac = GNUNET_new (struct AuthorityChain); - ac->rh = rh; - strncpy (ac->authority_info.dns_authority.name, - rd[i].data, - rd[i].data_size); - ac->authority_info.dns_authority.name[rd[i].data_size] = '\0'; - memcpy (&ac->authority_info.dns_authority.dns_ip, - sa, - sa_len); - /* for DNS recursion, the label is the full DNS name, - created from the remainder of the GNS name and the - name in the NS record */ - GNUNET_asprintf (&ac->label, - "%.*s%s", - (int) rh->name_resolution_pos, - rh->name, - ac->authority_info.dns_authority.name); - GNUNET_CONTAINER_DLL_insert_tail (rh->ac_head, - rh->ac_tail, - ac); - if (strlen (ac->label) > GNUNET_DNSPARSER_MAX_NAME_LENGTH) + case GNUNET_DNSPARSER_TYPE_CNAME: { - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - _("GNS lookup resulted in DNS name that is too long (`%s')\n"), - ac->label); - rh->proc (rh->proc_cls, 0, NULL); - GNS_resolver_lookup_cancel (rh); + char *cname; + + off = 0; + cname = GNUNET_DNSPARSER_parse_name (rd[i].data, + rd[i].data_size, + &off); + if ( (NULL == cname) || + (off != rd[i].data_size) ) + { + GNUNET_break_op (0); /* record not well-formed */ + rh->proc (rh->proc_cls, 0, NULL); + GNS_resolver_lookup_cancel (rh); + GNUNET_free_non_null (cname); + return; + } + handle_gns_cname_result (rh, + cname); + GNUNET_free (cname); return; } - /* recurse */ - rh->task_id = GNUNET_SCHEDULER_add_now (&recursive_resolution, - rh); - return; - case GNUNET_DNSPARSER_TYPE_CNAME: - cname = GNUNET_strndup (rd[i].data, - rd[i].data_size); - handle_gns_cname_result (rh, - cname); - GNUNET_free (cname); - return; /* FIXME: handle DNAME */ default: /* skip */ @@ -1484,22 +1693,26 @@ handle_gns_resolution_result (void *cls, * Function called once the namestore has completed the request for * caching a block. * - * @param cls closure with the 'struct GNS_ResolverHandle' + * @param cls closure with the `struct CacheOps` * @param success #GNUNET_OK on success * @param emsg error message */ static void -namestore_cache_continuation (void *cls, +namecache_cache_continuation (void *cls, int32_t success, const char *emsg) { - struct GNS_ResolverHandle *rh = cls; + struct CacheOps *co = cls; - rh->namestore_qe = NULL; + co->namecache_qe_cache = NULL; if (NULL != emsg) GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _("Failed to cache GNS resolution: %s\n"), emsg); + GNUNET_CONTAINER_DLL_remove (co_head, + co_tail, + co); + GNUNET_free (co); } @@ -1507,15 +1720,15 @@ namestore_cache_continuation (void *cls, * Iterator called on each result obtained for a DHT * operation that expects a reply * - * @param cls closure with the 'struct GNS_ResolverHandle' + * @param cls closure with the `struct GNS_ResolverHandle` * @param exp when will this value expire * @param key key of the result * @param get_path peers on reply path (or NULL if not recorded) * [0] = datastore's first neighbor, [length - 1] = local peer - * @param get_path_length number of entries in get_path + * @param get_path_length number of entries in @a get_path * @param put_path peers on the PUT path (or NULL if not recorded) * [0] = origin, [length - 1] = datastore - * @param put_path_length number of entries in get_path + * @param put_path_length number of entries in @a put_path * @param type type of the result * @param size number of bytes in data * @param data pointer to the result data @@ -1523,44 +1736,47 @@ namestore_cache_continuation (void *cls, static void handle_dht_response (void *cls, struct GNUNET_TIME_Absolute exp, - const struct GNUNET_HashCode * key, + const struct GNUNET_HashCode *key, const struct GNUNET_PeerIdentity *get_path, unsigned int get_path_length, - const struct GNUNET_PeerIdentity *put_path, + const struct GNUNET_PeerIdentity *put_path, unsigned int put_path_length, enum GNUNET_BLOCK_Type type, size_t size, const void *data) { struct GNS_ResolverHandle *rh = cls; struct AuthorityChain *ac = rh->ac_tail; - const struct GNUNET_NAMESTORE_Block *block; - + const struct GNUNET_GNSRECORD_Block *block; + struct CacheOps *co; + GNUNET_DHT_get_stop (rh->get_handle); rh->get_handle = NULL; GNUNET_CONTAINER_heap_remove_node (rh->dht_heap_node); - rh->dht_heap_node = NULL; - if (size < sizeof (struct GNUNET_NAMESTORE_Block)) + rh->dht_heap_node = NULL; + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Handling response from the DHT\n"); + if (size < sizeof (struct GNUNET_GNSRECORD_Block)) { /* how did this pass DHT block validation!? */ GNUNET_break (0); rh->proc (rh->proc_cls, 0, NULL); GNS_resolver_lookup_cancel (rh); - return; + return; } - block = data; + block = data; if (size != - ntohs (block->purpose.size) + - sizeof (struct GNUNET_CRYPTO_EccPublicKey) + - sizeof (struct GNUNET_CRYPTO_EccSignature)) + ntohl (block->purpose.size) + + sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey) + + sizeof (struct GNUNET_CRYPTO_EcdsaSignature)) { /* how did this pass DHT block validation!? */ GNUNET_break (0); rh->proc (rh->proc_cls, 0, NULL); GNS_resolver_lookup_cancel (rh); - return; + return; } if (GNUNET_OK != - GNUNET_NAMESTORE_block_decrypt (block, + GNUNET_GNSRECORD_block_decrypt (block, &ac->authority_info.gns_authority, ac->label, &handle_gns_resolution_result, @@ -1571,11 +1787,23 @@ handle_dht_response (void *cls, GNS_resolver_lookup_cancel (rh); return; } + if (0 == GNUNET_TIME_absolute_get_remaining (GNUNET_TIME_absolute_ntoh (block->expiration_time)).rel_value_us) + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Received expired block from the DHT, will not cache it.\n"); + return; + } /* Cache well-formed blocks */ - rh->namestore_qe = GNUNET_NAMESTORE_block_cache (namestore_handle, - block, - &namestore_cache_continuation, - rh); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Caching response from the DHT in namestore\n"); + co = GNUNET_new (struct CacheOps); + co->namecache_qe_cache = GNUNET_NAMECACHE_block_cache (namecache_handle, + block, + &namecache_cache_continuation, + co); + GNUNET_CONTAINER_DLL_insert (co_head, + co_tail, + co); } @@ -1585,24 +1813,32 @@ handle_dht_response (void *cls, * @param cls closure with the `struct GNS_ResolverHandle` * @param block block that was stored in the namestore */ -static void +static void handle_namestore_block_response (void *cls, - const struct GNUNET_NAMESTORE_Block *block) + 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_EccPublicKey *auth = &ac->authority_info.gns_authority; + const struct GNUNET_CRYPTO_EcdsaPublicKey *auth = &ac->authority_info.gns_authority; struct GNUNET_HashCode query; - GNUNET_NAMESTORE_query_from_public_key (auth, + GNUNET_GNSRECORD_query_from_public_key (auth, label, &query); - rh->namestore_qe = NULL; - if (NULL == block) + GNUNET_assert (NULL != rh->namecache_qe); + rh->namecache_qe = NULL; + if ( (GNUNET_NO == rh->only_cached) && + ( (NULL == block) || + (0 == GNUNET_TIME_absolute_get_remaining (GNUNET_TIME_absolute_ntoh (block->expiration_time)).rel_value_us) ) ) { /* Namestore knows nothing; try DHT lookup */ + 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, @@ -1617,13 +1853,26 @@ handle_namestore_block_response (void *cls, { /* 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); } return; } + if ( (NULL == block) || + (0 == GNUNET_TIME_absolute_get_remaining (GNUNET_TIME_absolute_ntoh (block->expiration_time)).rel_value_us) ) + { + /* DHT not permitted and no local result, fail */ + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Resolution failed for `%s' in zone %s (DHT lookup not permitted by configuration)\n", + ac->label, + GNUNET_GNSRECORD_z2s (&ac->authority_info.gns_authority)); + rh->proc (rh->proc_cls, 0, NULL); + GNS_resolver_lookup_cancel (rh); + return; + } if (GNUNET_OK != - GNUNET_NAMESTORE_block_decrypt (block, + GNUNET_GNSRECORD_block_decrypt (block, auth, label, &handle_gns_resolution_result, @@ -1648,13 +1897,66 @@ recursive_gns_resolution_namestore (struct GNS_ResolverHandle *rh) struct AuthorityChain *ac = rh->ac_tail; struct GNUNET_HashCode query; - GNUNET_NAMESTORE_query_from_public_key (&ac->authority_info.gns_authority, + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Starting GNS resolution for `%s' in zone %s\n", + ac->label, + GNUNET_GNSRECORD_z2s (&ac->authority_info.gns_authority)); + GNUNET_GNSRECORD_query_from_public_key (&ac->authority_info.gns_authority, ac->label, &query); - rh->namestore_qe = GNUNET_NAMESTORE_lookup_block (namestore_handle, + rh->namecache_qe = GNUNET_NAMECACHE_lookup_block (namecache_handle, &query, &handle_namestore_block_response, rh); + GNUNET_assert (NULL != rh->namecache_qe); +} + + +/** + * Function called with the result from a revocation check. + * + * @param cls the `struct GNS_ResovlerHandle` + * @param is_valid #GNUNET_YES if the zone was not yet revoked + */ +static void +handle_revocation_result (void *cls, + int is_valid) +{ + struct GNS_ResolverHandle *rh = cls; + struct AuthorityChain *ac = rh->ac_tail; + + rh->rev_check = NULL; + if (GNUNET_YES != is_valid) + { + GNUNET_log (GNUNET_ERROR_TYPE_WARNING, + _("Zone %s was revoked, resolution fails\n"), + GNUNET_GNSRECORD_z2s (&ac->authority_info.gns_authority)); + rh->proc (rh->proc_cls, 0, NULL); + GNS_resolver_lookup_cancel (rh); + return; + } + recursive_gns_resolution_namestore (rh); +} + + +/** + * Perform revocation check on tail of our authority chain. + * + * @param rh query we are processing + */ +static void +recursive_gns_resolution_revocation (struct GNS_ResolverHandle *rh) +{ + struct AuthorityChain *ac = rh->ac_tail; + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Starting revocation check for zone %s\n", + GNUNET_GNSRECORD_z2s (&ac->authority_info.gns_authority)); + rh->rev_check = GNUNET_REVOCATION_query (cfg, + &ac->authority_info.gns_authority, + &handle_revocation_result, + rh); + GNUNET_assert (NULL != rh->rev_check); } @@ -1681,7 +1983,7 @@ recursive_resolution (void *cls, return; } if (GNUNET_YES == rh->ac_tail->gns_authority) - recursive_gns_resolution_namestore (rh); + recursive_gns_resolution_revocation (rh); else recursive_dns_resolution (rh); } @@ -1697,9 +1999,7 @@ static void start_resolver_lookup (struct GNS_ResolverHandle *rh) { struct AuthorityChain *ac; - char *x; char *y; - char *pkey; if ( ( (GNUNET_YES == is_canonical (rh->name)) && (0 != strcmp (GNUNET_GNS_TLD, rh->name)) ) || @@ -1721,7 +2021,10 @@ start_resolver_lookup (struct GNS_ResolverHandle *rh) af = AF_UNSPEC; break; } - rh->std_resolve = GNUNET_RESOLVER_ip_get (rh->name, + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Doing standard DNS lookup for `%s'\n", + rh->name); + rh->std_resolve = GNUNET_RESOLVER_ip_get (rh->name, af, DNS_LOOKUP_TIMEOUT, &handle_dns_result, @@ -1733,26 +2036,19 @@ start_resolver_lookup (struct GNS_ResolverHandle *rh) /* Name ends with ".zkey", try to replace authority zone with zkey authority */ GNUNET_free (resolver_lookup_get_next_label (rh)); /* will return "zkey" */ - x = resolver_lookup_get_next_label (rh); /* will return 'x' coordinate */ y = resolver_lookup_get_next_label (rh); /* will return 'y' coordinate */ - GNUNET_asprintf (&pkey, - "%s%s", - x, y); - if ( (NULL == x) || - (NULL == y) || + if ( (NULL == y) || (GNUNET_OK != - GNUNET_CRYPTO_ecc_public_key_from_string (pkey, - strlen (pkey), - &rh->authority_zone)) ) + GNUNET_CRYPTO_ecdsa_public_key_from_string (y, + strlen (y), + &rh->authority_zone)) ) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _("Hostname `%s' is not well-formed, resolution fails\n"), rh->name); rh->task_id = GNUNET_SCHEDULER_add_now (&fail_resolution, rh); } - GNUNET_free_non_null (x); GNUNET_free_non_null (y); - GNUNET_free (pkey); } else { @@ -1789,15 +2085,20 @@ start_resolver_lookup (struct GNS_ResolverHandle *rh) * @return handle to cancel operation */ struct GNS_ResolverHandle * -GNS_resolver_lookup (const struct GNUNET_CRYPTO_EccPublicKey *zone, +GNS_resolver_lookup (const struct GNUNET_CRYPTO_EcdsaPublicKey *zone, uint32_t record_type, const char *name, - const struct GNUNET_CRYPTO_EccPrivateKey *shorten_key, + const struct GNUNET_CRYPTO_EcdsaPrivateKey *shorten_key, int only_cached, GNS_ResultProcessor proc, void *proc_cls) { struct GNS_ResolverHandle *rh; + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + (NULL == shorten_key) + ? "Starting lookup for `%s' with shortening disabled\n" + : "Starting lookup for `%s' with shortening enabled\n", + name); rh = GNUNET_new (struct GNS_ResolverHandle); GNUNET_CONTAINER_DLL_insert (rlh_head, rlh_tail, @@ -1811,7 +2112,7 @@ GNS_resolver_lookup (const struct GNUNET_CRYPTO_EccPublicKey *zone, rh->name_resolution_pos = strlen (name); if (NULL != shorten_key) { - rh->shorten_key = GNUNET_new (struct GNUNET_CRYPTO_EccPrivateKey); + rh->shorten_key = GNUNET_new (struct GNUNET_CRYPTO_EcdsaPrivateKey); *rh->shorten_key = *shorten_key; } start_resolver_lookup (rh); @@ -1868,13 +2169,20 @@ GNS_resolver_lookup_cancel (struct GNS_ResolverHandle *rh) GNUNET_DNSSTUB_resolve_cancel (rh->dns_request); rh->dns_request = NULL; } - if (NULL != rh->namestore_qe) + if (NULL != rh->namecache_qe) + { + GNUNET_NAMECACHE_cancel (rh->namecache_qe); + rh->namecache_qe = NULL; + } + if (NULL != rh->rev_check) { - GNUNET_NAMESTORE_cancel (rh->namestore_qe); - rh->namestore_qe = NULL; + GNUNET_REVOCATION_query_cancel (rh->rev_check); + rh->rev_check = NULL; } if (NULL != rh->std_resolve) { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Canceling standard DNS resolution\n"); GNUNET_RESOLVER_request_cancel (rh->std_resolve); rh->std_resolve = NULL; } @@ -1897,13 +2205,13 @@ GNS_resolver_lookup_cancel (struct GNS_ResolverHandle *rh) /** * Initialize the resolver * - * @param nh the namestore handle + * @param nc the namecache handle * @param dht the dht handle * @param c configuration handle * @param max_bg_queries maximum number of parallel background queries in dht */ void -GNS_resolver_init (struct GNUNET_NAMESTORE_Handle *nh, +GNS_resolver_init (struct GNUNET_NAMECACHE_Handle *nc, struct GNUNET_DHT_Handle *dht, const struct GNUNET_CONFIGURATION_Handle *c, unsigned long long max_bg_queries) @@ -1911,7 +2219,7 @@ GNS_resolver_init (struct GNUNET_NAMESTORE_Handle *nh, char *dns_ip; cfg = c; - namestore_handle = nh; + namecache_handle = nc; dht_handle = dht; dht_lookup_heap = GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN); @@ -1938,12 +2246,21 @@ void GNS_resolver_done () { struct GNS_ResolverHandle *rh; + struct CacheOps *co; /* abort active resolutions */ while (NULL != (rh = rlh_head)) { rh->proc (rh->proc_cls, 0, NULL); - GNS_resolver_lookup_cancel (rh); + GNS_resolver_lookup_cancel (rh); + } + while (NULL != (co = co_head)) + { + GNUNET_CONTAINER_DLL_remove (co_head, + co_tail, + co); + GNUNET_NAMECACHE_cancel (co->namecache_qe_cache); + GNUNET_free (co); } GNUNET_CONTAINER_heap_destroy (dht_lookup_heap); dht_lookup_heap = NULL; @@ -1952,7 +2269,7 @@ GNS_resolver_done () GNUNET_VPN_disconnect (vpn_handle); vpn_handle = NULL; dht_handle = NULL; - namestore_handle = NULL; + namecache_handle = NULL; }