-/**
- * Namestore resolution for delegation finished. Processing result.
- *
- * @param cls the closure
- * @param rh resolver handle
- * @param rd_count number of results (always 0)
- * @param rd record data (always NULL)
- */
-static void
-handle_delegation_ns (void* cls, struct ResolverHandle *rh,
- unsigned int rd_count,
- const struct GNUNET_NAMESTORE_RecordData *rd)
-{
- struct RecordLookupHandle* rlh = cls;
- int check_dht;
- size_t s_len;
-
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "GNS_PHASE_DELEGATE_NS-%llu: Resolution status: %d.\n",
- rh->id, rh->status);
-
- if (rh->status & RSL_PKEY_REVOKED)
- {
- finish_lookup (rh, rlh, 0, NULL);
- return;
- }
-
- if (0 == strcmp(rh->name, ""))
- {
-
- /* We resolved full name for delegation. resolving record */
- GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
- "GNS_PHASE_DELEGATE_NS-%llu: Resolved full name for delegation.\n",
- rh->id);
- if (rh->status & RSL_CNAME_FOUND)
- {
- if (GNUNET_DNSPARSER_TYPE_CNAME == rlh->record_type)
- {
- GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
- "GNS_PHASE_DELEGATE_NS-%llu: Resolved queried CNAME in NS.\n",
- rh->id);
- strcpy (rh->name, rh->authority_name);
- finish_lookup (rh, rlh, rd_count, rd);
- return;
- }
-
- /* A .+ CNAME */
- if (GNUNET_YES == is_tld ((char*)rd->data, GNUNET_GNS_TLD_PLUS))
- {
- s_len = strlen (rd->data) - 2;
- memcpy (rh->name, rd->data, s_len);
- rh->name[s_len] = '\0';
- resolve_delegation_ns (rh);
- return;
- }
- else if (GNUNET_YES == is_tld ((char*)rd->data, GNUNET_GNS_TLD_ZKEY))
- {
- gns_resolver_lookup_record (rh->authority,
- rh->private_local_zone,
- rlh->record_type,
- (char*)rd->data,
- rh->priv_key,
- rh->timeout,
- rh->only_cached,
- rlh->proc,
- rlh->proc_cls);
- GNUNET_free (rlh);
- GNUNET_CONTAINER_DLL_remove (rlh_head, rlh_tail, rh);
- free_resolver_handle (rh);
- return;
- }
- else
- {
- //Try DNS resolver
- strcpy (rh->dns_name, (char*)rd->data);
- resolve_dns_name (rh);
- return;
- }
-
- }
- else if (rh->status & RSL_DELEGATE_VPN)
- {
- if (GNUNET_NAMESTORE_TYPE_VPN == rlh->record_type)
- {
- GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
- "GNS_PHASE_DELEGATE_NS-%llu: Resolved queried VPNRR in NS.\n",
- rh->id);
- finish_lookup(rh, rlh, rd_count, rd);
- return;
- }
- GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
- "GNS_PHASE_DELEGATE_NS-%llu: VPN delegation starting.\n",
- rh->id);
- GNUNET_assert (NULL != rd);
- rh->proc = &handle_record_vpn;
- resolve_record_vpn (rh, rd_count, rd);
- return;
- }
- else if (rh->status & RSL_DELEGATE_NS)
- {
- if (GNUNET_DNSPARSER_TYPE_NS == rlh->record_type)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "GNS_PHASE_DELEGATE_NS-%llu: Resolved queried NSRR in NS.\n",
- rh->id);
- finish_lookup (rh, rlh, rd_count, rd);
- return;
- }
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "GNS_PHASE_DELEGATE_NS-%llu: NS delegation starting.\n",
- rh->id);
- GNUNET_assert (NULL != rd);
- rh->proc = &handle_record_ns;
- resolve_record_dns (rh, rd_count, rd);
- return;
- }
- else if (rh->status & RSL_DELEGATE_PKEY)
- {
- if (rh->status & RSL_PKEY_REVOKED)
- {
- GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
- "GNS_PHASE_DELEGATE_NS-%llu: Resolved PKEY is revoked.\n",
- rh->id);
- finish_lookup (rh, rlh, 0, NULL);
- return;
- }
- else if (GNUNET_NAMESTORE_TYPE_PKEY == rlh->record_type)
- {
- GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
- "GNS_PHASE_DELEGATE_NS-%llu: Resolved queried PKEY in NS.\n",
- rh->id);
- finish_lookup(rh, rlh, rd_count, rd);
- return;
- }
- }
- GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
- "GNS_PHASE_DELEGATE_NS-%llu: Resolving record +\n",
- rh->id);
- strcpy(rh->name, "+\0");
- rh->proc = &handle_record_ns;
- resolve_record_ns(rh);
- return;
- }
-
- if (rh->status & RSL_DELEGATE_NS)
- {
- if (GNUNET_DNSPARSER_TYPE_NS == rlh->record_type)
- {
- GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
- "GNS_PHASE_DELEGATE_NS-%llu: Resolved queried NSRR in NS.\n",
- rh->id);
- finish_lookup(rh, rlh, rd_count, rd);
- return;
- }
-
- GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
- "GNS_PHASE_DELEGATE_NS-%llu: NS delegation starting.\n",
- rh->id);
- GNUNET_assert (NULL != rd);
- rh->proc = &handle_record_ns;
- resolve_record_dns (rh, rd_count, rd);
- return;
- }
-
- /**
- * we still have some left
- * check if authority in ns is fresh
- * and exists
- * or we are authority
- **/
-
- check_dht = GNUNET_YES;
- if ((rh->status & RSL_RECORD_EXISTS) &&
- !(rh->status & RSL_RECORD_EXPIRED))
- check_dht = GNUNET_NO;
-
- if (0 == GNUNET_CRYPTO_short_hash_cmp(&rh->authority_chain_head->zone,
- &rh->private_local_zone))
- check_dht = GNUNET_NO;
-
- if (GNUNET_YES == rh->only_cached)
- check_dht = GNUNET_NO;
-
- if (GNUNET_YES == check_dht)
- {
-
- GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
- "GNS_PHASE_DELEGATE_NS-%llu: Trying to resolve delegation for %s via DHT\n",
- rh->id, rh->name);
- rh->proc = &handle_delegation_dht;
- resolve_delegation_dht(rh);
- return;
- }
-
- if (GNUNET_NO == is_canonical (rh->name))
- {
- /* give up, cannot resolve */
- GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
- "GNS_PHASE_DELEGATE_NS-%llu: Cannot fully resolve delegation for %s!\n",
- rh->id,
- rh->name);
- finish_lookup(rh, rlh, rd_count, rd);
- return;
- }
- GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
- "GNS_PHASE_DELEGATE_NS-%llu: Resolving canonical record %s\n",
- rh->id,
- rh->name);
- rh->proc = &handle_record_ns;
- resolve_record_ns(rh);
-}
-
-
-/**
- * This is a callback function that should give us only PKEY
- * records. Used to query the namestore for the authority (PKEY)
- * for 'name'. It will recursively try to resolve the
- * authority for a given name from the namestore.
- *
- * @param cls the pending query
- * @param key the key of the zone we did the lookup
- * @param expiration expiration date of the record data set in the namestore
- * @param name the name for which we need an authority
- * @param rd_count the number of records with 'name'
- * @param rd the record data
- * @param signature the signature of the authority for the record data
- */
-static void
-process_delegation_result_ns (void* cls,
- const struct GNUNET_CRYPTO_EccPublicKey *key,
- struct GNUNET_TIME_Absolute expiration,
- const char *name,
- unsigned int rd_count,
- const struct GNUNET_NAMESTORE_RecordData *rd,
- const struct GNUNET_CRYPTO_EccSignature *signature)
-{
- struct ResolverHandle *rh = cls;
- struct GNUNET_TIME_Relative remaining_time;
- struct GNUNET_CRYPTO_ShortHashCode zone;
- char new_name[GNUNET_DNSPARSER_MAX_NAME_LENGTH];
- unsigned int i;
- struct GNUNET_TIME_Absolute et;
- struct AuthorityChain *auth;
-
- rh->namestore_task = NULL;
- GNUNET_CRYPTO_short_hash (key,
- sizeof (struct GNUNET_CRYPTO_EccPublicKey),
- &zone);
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "GNS_PHASE_DELEGATE_NS-%llu: Got %d records from authority lookup for `%s' in zone %s\n",
- rh->id, rd_count,
- name,
- GNUNET_short_h2s (&zone));
-
- remaining_time = GNUNET_TIME_absolute_get_remaining (expiration);
-
- rh->status = 0;
-
- if (NULL != name)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "GNS_PHASE_DELEGATE_NS-%llu: Records with name `%s' exist in zone %s.\n",
- rh->id, name,
- GNUNET_short_h2s (&zone));
- rh->status |= RSL_RECORD_EXISTS;
-
- if (0 == remaining_time.rel_value_us)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "GNS_PHASE_DELEGATE_NS-%llu: Record set %s expired.\n",
- rh->id, name);
- rh->status |= RSL_RECORD_EXPIRED;
- }
- }
-
- /**
- * No authority found in namestore.
- */
- if (0 == rd_count)
- {
- /**
- * We did not find an authority in the namestore
- */
-
- /**
- * No PKEY in zone.
- * Promote this authority back to a name maybe it is
- * our record.
- */
- if (strcmp (rh->name, "") == 0)
- {
- /* simply promote back */
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "GNS_PHASE_DELEGATE_NS-%llu: Promoting %s back to name\n",
- rh->id, rh->authority_name);
- strcpy (rh->name, rh->authority_name);
- }
- else
- {
- /* add back to existing name */
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "GNS_PHASE_DELEGATE_NS-%llu: Adding %s back to %s\n",
- rh->id, rh->authority_name, rh->name);
- GNUNET_snprintf (new_name, GNUNET_DNSPARSER_MAX_NAME_LENGTH, "%s.%s",
- rh->name, rh->authority_name);
- strcpy (rh->name, new_name);
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "GNS_PHASE_DELEGATE_NS-%llu: %s restored\n",
- rh->id, rh->name);
- }
-
- rh->proc (rh->proc_cls, rh, 0, NULL);
- return;
- }
-
- /**
- * We found an authority that may be able to help us
- * move on with query
- * Note only 1 pkey should have been returned.. anything else would be strange
- */
- for (i=0; i < rd_count;i++)
- {
- switch (rd[i].record_type)
- {
- case GNUNET_DNSPARSER_TYPE_CNAME:
- /* Like in regular DNS this should mean that there is no other
- * record for this name. */
-
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "GNS_PHASE_DELEGATE_NS-%llu: CNAME `%.*s' found.\n",
- rh->id,
- (int) rd[i].data_size,
- rd[i].data);
- rh->status |= RSL_CNAME_FOUND;
- rh->proc (rh->proc_cls, rh, rd_count, rd);
- return;
- case GNUNET_NAMESTORE_TYPE_VPN:
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "GNS_PHASE_DELEGATE_NS-%llu: VPN found.\n",
- rh->id);
- rh->status |= RSL_DELEGATE_VPN;
- rh->proc (rh->proc_cls, rh, rd_count, rd);
- return;
- case GNUNET_DNSPARSER_TYPE_NS:
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "GNS_PHASE_DELEGATE_NS-%llu: NS `%.*s' found.\n",
- rh->id,
- (int) rd[i].data_size,
- rd[i].data);
- rh->status |= RSL_DELEGATE_NS;
- rh->proc (rh->proc_cls, rh, rd_count, rd);
- return;
- case GNUNET_NAMESTORE_TYPE_PKEY:
- rh->status |= RSL_DELEGATE_PKEY;
- if ((ignore_pending_records != 0) &&
- (rd[i].flags & GNUNET_NAMESTORE_RF_PENDING))
- {
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "GNS_PHASE_DELEGATE_NS-%llu: PKEY for %s is pending user confirmation.\n",
- rh->id,
- name);
- continue;
- }
- GNUNET_break (0 == (rd[i].flags & GNUNET_NAMESTORE_RF_RELATIVE_EXPIRATION));
- et.abs_value_us = rd[i].expiration_time;
- if (0 == (GNUNET_TIME_absolute_get_remaining (et)).rel_value_us)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "GNS_PHASE_DELEGATE_NS-%llu: This pkey is expired.\n",
- rh->id);
- if (remaining_time.rel_value_us == 0)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "GNS_PHASE_DELEGATE_NS-%llu: This dht entry is expired.\n",
- rh->id);
- rh->authority_chain_head->fresh = 0;
- rh->proc (rh->proc_cls, rh, 0, NULL);
- return;
- }
- continue;
- }
- /* Resolve rest of query with new authority */
- memcpy (&rh->authority, rd[i].data,
- sizeof (struct GNUNET_CRYPTO_ShortHashCode));
- auth = GNUNET_malloc(sizeof (struct AuthorityChain));
- auth->zone = rh->authority;
- memset (auth->name, 0, strlen (rh->authority_name)+1);
- strcpy (auth->name, rh->authority_name);
- GNUNET_CONTAINER_DLL_insert (rh->authority_chain_head,
- rh->authority_chain_tail,
- auth);
- if (NULL != rh->rd.data)
- GNUNET_free ((void*)(rh->rd.data));
- memcpy (&rh->rd, &rd[i], sizeof (struct GNUNET_NAMESTORE_RecordData));
- rh->rd.data = GNUNET_malloc (rd[i].data_size);
- memcpy ((void*)rh->rd.data, rd[i].data, rd[i].data_size);
- rh->rd_count = 1;
- /* Check for key revocation and delegate */
- rh->namestore_task = GNUNET_NAMESTORE_lookup_record (namestore_handle,
- &rh->authority,
- GNUNET_GNS_MASTERZONE_STR,
- GNUNET_NAMESTORE_TYPE_REV,
- &process_pkey_revocation_result_ns,
- rh);
- return;
- default:
- /* ignore, move to next result */
- break;
- }
- }
-
- /* no answers that would cause delegation were found */
- GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
- "GNS_PHASE_DELEGATE_NS-%llu: Authority lookup failed (no PKEY record)\n",
- rh->id);
- /**
- * If we have found some records for the LAST label
- * we return the results. Else NULL.
- */
- if (0 == strcmp (rh->name, ""))
- {
- /* Start shortening */
- if ((rh->priv_key != NULL) &&
- (is_canonical (rh->name) == GNUNET_YES))
- {
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "GNS_PHASE_DELEGATE_NS-%llu: Trying to shorten authority chain\n",
- rh->id);
- start_shorten (rh->authority_chain_head,
- rh->priv_key);
- }
- /* simply promote back */
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "GNS_PHASE_DELEGATE_NS-%llu: Promoting %s back to name\n",
- rh->id, rh->authority_name);
- strcpy (rh->name, rh->authority_name);
- rh->proc (rh->proc_cls, rh, rd_count, rd);
- }
- else
- {
- GNUNET_snprintf (new_name, GNUNET_DNSPARSER_MAX_NAME_LENGTH,
- "%s.%s", rh->name, rh->authority_name);
- strcpy (rh->name, new_name);
- rh->proc (rh->proc_cls, rh, 0, NULL);
- }
-}
-
-
-/**
- * Resolve the delegation chain for the request in our namestore
- * (as in, find the respective authority for the leftmost label).
- *
- * @param rh the resolver handle
- */
-static void
-resolve_delegation_ns (struct ResolverHandle *rh)
-{
- pop_tld (rh->name, rh->authority_name);
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "GNS_PHASE_DELEGATE_NS-%llu: Finding authority for `%s' by looking up `%s' in GADS zone `%s'\n",
- rh->id,
- rh->name,
- rh->authority_name,
- GNUNET_short_h2s (&rh->authority));
- rh->namestore_task = GNUNET_NAMESTORE_lookup_record (namestore_handle,
- &rh->authority,
- rh->authority_name,
- GNUNET_DNSPARSER_TYPE_ANY,
- &process_delegation_result_ns,
- rh);
-}
-
-
-/**
- * Lookup of a record in a specific zone
- * calls lookup result processor on result
- *
- * @param zone the root zone
- * @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 proc the processor to call on result
- * @param proc_cls the closure to pass to @a proc
- */
-void
-GNS_resolver_lookup (const struct GNUNET_CRYPTO_EccPublicKey * zone,
- uint32_t record_type,
- const char* name,
- struct GNUNET_CRYPTO_EccPrivateKey *shorten_key,
- int only_cached,
- RecordLookupProcessor proc,
- void *proc_cls)
-{
- struct ResolverHandle *rh;
- struct RecordLookupHandle* rlh;
- char string_hash[GNUNET_DNSPARSER_MAX_LABEL_LENGTH];
- char nzkey[GNUNET_DNSPARSER_MAX_LABEL_LENGTH];
- char* nzkey_ptr = nzkey;
-
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Starting resolution for `%s' (type=%d) with timeout %s!\n",
- name, record_type,
- GNUNET_STRINGS_relative_time_to_string (timeout, GNUNET_YES));
-
- if ((is_canonical ((char*)name) == GNUNET_YES) &&
- (strcmp(GNUNET_GNS_TLD, name) != 0))
- {
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "%s is canonical and not gnunet -> cannot resolve!\n", name);
- proc(cls, 0, NULL);
- return;
- }
-
- rlh = GNUNET_malloc (sizeof(struct RecordLookupHandle));
- rh = GNUNET_malloc (sizeof (struct ResolverHandle));
- rh->authority = zone;
- rh->id = rid_gen++;
- rh->proc_cls = rlh;
- rh->priv_key = key;
- rh->timeout = timeout;
- rh->private_local_zone = pzone;
- rh->only_cached = only_cached;
-
- GNUNET_CONTAINER_DLL_insert (rlh_head, rlh_tail, rh);
-
- if (NULL == key)
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "No shorten key for resolution\n");
-
- if (timeout.rel_value_us != GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us)
- {
- /*
- * Set timeout for authority lookup phase to 1/2
- */
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Timeout for lookup set to %s/2\n",
- GNUNET_STRINGS_relative_time_to_string (rh->timeout, GNUNET_YES));
- rh->timeout_task = GNUNET_SCHEDULER_add_delayed (
- GNUNET_TIME_relative_divide(timeout, 2),
- &handle_lookup_timeout,
- rh);
- rh->timeout_cont = &dht_authority_lookup_timeout;
- rh->timeout_cont_cls = rh;
- }
- else
- {
- GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "No timeout for query!\n");
- rh->timeout_task = GNUNET_SCHEDULER_NO_TASK;
- }
-
- if (strcmp(GNUNET_GNS_TLD, name) == 0)
- {
- /**
- * Only '.gads' given
- */
- strcpy (rh->name, "\0");
- }
- else
- {
- if (is_zkey_tld(name) == GNUNET_YES)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "TLD is zkey\n");
- /**
- * This is a zkey tld
- * build hash and use as initial authority
- */
- memset(rh->name, 0,
- strlen(name)-strlen(GNUNET_GNS_TLD_ZKEY));
- memcpy(rh->name, name,
- strlen(name)-strlen(GNUNET_GNS_TLD_ZKEY) - 1);
- pop_tld (rh->name, string_hash);
-
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "ZKEY is %s!\n", string_hash);
-
- GNUNET_STRINGS_utf8_toupper(string_hash, &nzkey_ptr);
-
- if (GNUNET_OK != GNUNET_CRYPTO_short_hash_from_string(nzkey,
- &rh->authority))
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Cannot convert ZKEY `%s' to hash!\n", string_hash);
-
- if (GNUNET_SCHEDULER_NO_TASK != rh->timeout_task)
- GNUNET_SCHEDULER_cancel (rh->timeout_task);
- GNUNET_CONTAINER_DLL_remove (rlh_head, rlh_tail, rh);
- GNUNET_free (rh);
- GNUNET_free (rlh);
- proc (cls, 0, NULL);
- return;
- }
-
- }
- else if (is_gads_tld (name) == GNUNET_YES)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "TLD is gads\n");
- /**
- * Presumably GADS tld
- */
- memcpy (rh->name, name,
- strlen (name) - strlen(GNUNET_GNS_TLD) - 1);
- rh->name[strlen (name) - strlen(GNUNET_GNS_TLD) - 1] = '\0';
- }
- else
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- _("Not a GADS TLD: `%s'\n"),
- name);
- if (GNUNET_SCHEDULER_NO_TASK != rh->timeout_task)
- GNUNET_SCHEDULER_cancel (rh->timeout_task);
- GNUNET_CONTAINER_DLL_remove (rlh_head, rlh_tail, rh);
- GNUNET_free (rh);
- GNUNET_free (rlh);
- proc (cls, 0, NULL);
- return;
- }
- }
-
- /**
- * Initialize authority chain
- */
- rh->authority_chain_head = GNUNET_malloc (sizeof(struct AuthorityChain));
- rh->authority_chain_tail = rh->authority_chain_head;
- rh->authority_chain_head->zone = rh->authority;
- strcpy (rh->authority_chain_head->name, "");
-
- /**
- * Copy original query into lookup handle
- */
- rlh->record_type = record_type;
- memset(rlh->name, 0, strlen(name) + 1);
- strcpy(rlh->name, name);
- rlh->proc = proc;
- rlh->proc_cls = cls;
-
- rh->proc = &handle_delegation_ns;
- resolve_delegation_ns (rh);
-}
-
-