* @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"
/**
* Use only cache
*/
- int only_cached;
+ enum GNUNET_GNS_LocalOptions options;
/**
* Desired type for the resolution.
/**
* 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
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 */
rp = dot + 1;
rh->name_resolution_pos = dot - rh->name;
}
+ /* merge labels starting with underscore with label on the right (SRV/DANE case) */
+ while ( (NULL != (dot = memrchr (rh->name,
+ (int) '.',
+ rh->name_resolution_pos))) &&
+ ('_' == dot[1]) )
+ {
+ len += rh->name_resolution_pos - (dot - rh->name) - 1;
+ rp = dot + 1;
+ rh->name_resolution_pos = dot - rh->name;
+ }
return GNUNET_strndup (rp, len);
}
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,
rd[i].data_size,
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);
/**
- * Process a records that were decrypted from a block that we
- * got from the namecache. If the desired record type is not
- * included, we should query the DHT. Otherwise, we should
- * simply call #handle_gns_resolution_result().
+ * 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
const struct GNUNET_GNSRECORD_Data *rd)
{
struct GNS_ResolverHandle *rh = cls;
- unsigned int i;
- int found;
-
- found = GNUNET_NO;
- for (i=0;i<rd_count;i++)
- {
- if (rd[i].record_type == rh->record_type)
- {
- found = GNUNET_YES;
- break;
- }
- switch (rd[i].record_type)
- {
- case GNUNET_GNSRECORD_TYPE_VPN:
- if ( (GNUNET_DNSPARSER_TYPE_A == rh->record_type) ||
- (GNUNET_DNSPARSER_TYPE_AAAA == rh->record_type) )
- {
- found = GNUNET_YES;
- break;
- }
- break;
- case GNUNET_DNSPARSER_TYPE_CNAME:
- case GNUNET_GNSRECORD_TYPE_PKEY:
- case GNUNET_GNSRECORD_TYPE_GNS2DNS:
- /* delegations always count as 'found' */
- found = GNUNET_YES;
- break;
- default:
- break;
- }
- }
- if (GNUNET_YES == found)
- {
- handle_gns_resolution_result (rh,
- rd_count,
- rd);
- }
- else
- {
- /* try DHT */
- 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_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);
- }
+ handle_gns_resolution_result (rh,
+ rd_count,
+ rd);
}
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) ) )
{
&query);
if (GNUNET_YES == use_cache)
{
- rh->namecache_qe = GNUNET_NAMECACHE_lookup_block (namecache_handle,
- &query,
- &handle_namecache_block_response,
- rh);
+ rh->namecache_qe
+ = GNUNET_NAMECACHE_lookup_block (namecache_handle,
+ &query,
+ &handle_namecache_block_response,
+ rh);
GNUNET_assert (NULL != rh->namecache_qe);
}
else
* @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
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;
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);