GNUnet  0.17.6
Data Structures | Macros | Functions | Variables
gnunet-service-gns_resolver.c File Reference

GNU Name System resolver logic. More...

#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_dns_service.h"
#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.h"
#include "gnunet-service-gns_resolver.h"
Include dependency graph for gnunet-service-gns_resolver.c:

Go to the source code of this file.

Data Structures

struct  Gns2DnsPending
 Element of a resolution process for looking up the responsible DNS server hostname in a GNS2DNS recursive resolution. More...
 
struct  AuthorityChain
 DLL to hold the authority chain we had to pass in the resolution process. More...
 
struct  DnsResult
 A result we got from DNS. More...
 
struct  GNS_ResolverHandle
 Handle to a currently pending resolution. More...
 
struct  CacheOps
 Active namestore caching operations. More...
 

Macros

#define DHT_LOOKUP_TIMEOUT
 Default DHT timeout for lookups. More...
 
#define DNS_LOOKUP_TIMEOUT
 Default timeout for DNS lookups. More...
 
#define DHT_GNS_REPLICATION_LEVEL   10
 DHT replication level. More...
 

Functions

int is_canonical (const char *name)
 Determine if this name is canonical (is a legal name in a zone, without delegation); note that we do not test that the name does not contain illegal characters, we only test for delegation. More...
 
static char * translate_dot_plus (struct GNS_ResolverHandle *rh, char *name)
 Expands a name ending in . More...
 
static void GNS_resolver_lookup_cancel_ (void *cls)
 Wrapper around GNS_resolver_lookup_cancel() as a task. More...
 
static void fail_resolution (struct GNS_ResolverHandle *rh)
 Function called to asynchronously fail a resolution. More...
 
static void timeout_resolution (void *cls)
 Function called when a resolution times out. More...
 
static char * resolver_lookup_get_next_label (struct GNS_ResolverHandle *rh)
 Get the next, rightmost label from the name that we are trying to resolve, and update the resolution position accordingly. More...
 
static void transmit_lookup_dns_result (struct GNS_ResolverHandle *rh)
 Gives the cumulative result obtained to the callback and clean up the request. More...
 
static void add_dns_result (struct GNS_ResolverHandle *rh, uint64_t expiration_time, uint32_t record_type, size_t data_size, const void *data)
 Add a result from DNS to the records to be returned to the application. More...
 
static void handle_dns_result (void *cls, const struct sockaddr *addr, socklen_t addrlen)
 We had to do a DNS lookup. More...
 
static void recursive_resolution (void *cls)
 Task scheduled to continue with the resolution process. More...
 
static void start_resolver_lookup (void *cls)
 Begin the resolution process from 'name', starting with the identification of the zone specified by 'name'. More...
 
static void dns_result_parser (void *cls, const struct GNUNET_TUN_DnsHeader *dns, size_t dns_len)
 Function called with the result of a DNS resolution. More...
 
static void recursive_dns_resolution (struct GNS_ResolverHandle *rh)
 Perform recursive DNS resolution. More...
 
static void handle_gns_redirect_result (struct GNS_ResolverHandle *rh, const char *rname)
 We encountered a REDIRECT record during our resolution. More...
 
static void handle_gns_cname_result (struct GNS_ResolverHandle *rh, const char *cname)
 We encountered a CNAME record during our resolution. More...
 
static void handle_gns_resolution_result (void *cls, unsigned int rd_count, const struct GNUNET_GNSRECORD_Data *rd)
 Process records that were decrypted from a block. More...
 
static void continue_with_gns2dns (struct AuthorityChain *ac)
 We have resolved one or more of the nameservers for a GNS2DNS lookup. More...
 
static void handle_gns2dns_result (void *cls, unsigned int rd_count, const struct GNUNET_GNSRECORD_Data *rd)
 We've resolved the IP address for the DNS resolver to use after encountering a GNS2DNS record. More...
 
static void handle_gns2dns_ip (void *cls, const struct sockaddr *addr, socklen_t addrlen)
 Function called by the resolver for each address obtained from DNS. More...
 
static void recursive_redirect_resolution (struct GNS_ResolverHandle *rh, const struct GNUNET_GNSRECORD_Data *rd)
 We found a REDIRECT record, perform recursive resolution on it. More...
 
static void recursive_cname_resolution (struct GNS_ResolverHandle *rh, const struct GNUNET_GNSRECORD_Data *rd)
 We found a CNAME record, perform recursive resolution on it. More...
 
static void recursive_pkey_resolution (struct GNS_ResolverHandle *rh, const struct GNUNET_GNSRECORD_Data *rd)
 We found a PKEY record, perform recursive resolution on it. More...
 
static int recursive_gns2dns_resolution (struct GNS_ResolverHandle *rh, unsigned int rd_count, const struct GNUNET_GNSRECORD_Data *rd)
 We found one or more GNS2DNS records, perform recursive resolution on it. More...
 
static void namecache_cache_continuation (void *cls, int32_t success, const char *emsg)
 Function called once the namestore has completed the request for caching a block. More...
 
static void handle_dht_response (void *cls, struct GNUNET_TIME_Absolute exp, const struct GNUNET_HashCode *key, const struct GNUNET_PeerIdentity *trunc_peer, const struct GNUNET_DHT_PathElement *get_path, unsigned int get_path_length, const struct GNUNET_DHT_PathElement *put_path, unsigned int put_path_length, enum GNUNET_BLOCK_Type type, size_t size, const void *data)
 Iterator called on each result obtained for a DHT operation that expects a reply. More...
 
static void start_dht_request (struct GNS_ResolverHandle *rh, const struct GNUNET_HashCode *query)
 Initiate a DHT query for a set of GNS records. More...
 
static void handle_gns_namecache_resolution_result (void *cls, unsigned int rd_count, const struct GNUNET_GNSRECORD_Data *rd)
 Process a records that were decrypted from a block that we got from the namecache. More...
 
static void handle_namecache_block_response (void *cls, const struct GNUNET_GNSRECORD_Block *block)
 Process a record that was stored in the namecache. More...
 
static void recursive_gns_resolution_namecache (struct GNS_ResolverHandle *rh)
 Lookup tail of our authority chain in the namecache. More...
 
static void handle_revocation_result (void *cls, int is_valid)
 Function called with the result from a revocation check. More...
 
static void recursive_gns_resolution_revocation (struct GNS_ResolverHandle *rh)
 Perform revocation check on tail of our authority chain. More...
 
struct GNS_ResolverHandleGNS_resolver_lookup (const struct GNUNET_IDENTITY_PublicKey *zone, uint32_t record_type, const char *name, enum GNUNET_GNS_LocalOptions options, uint16_t recursion_depth_limit, GNS_ResultProcessor proc, void *proc_cls)
 Lookup of a record in a specific zone calls lookup result processor on result. More...
 
void GNS_resolver_lookup_cancel (struct GNS_ResolverHandle *rh)
 Cancel active resolution (i.e. More...
 
void 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)
 Initialize the resolver. More...
 
void GNS_resolver_done ()
 Shutdown resolver. More...
 

Variables

static struct GNUNET_NAMECACHE_Handlenamecache_handle
 Our handle to the namecache service. More...
 
static struct GNUNET_DHT_Handledht_handle
 Resolver handle to the dht. More...
 
static struct GNUNET_CONTAINER_Heapdht_lookup_heap
 Heap for limiting parallel DHT lookups. More...
 
static unsigned long long max_allowed_background_queries
 Maximum amount of parallel queries to the DHT. More...
 
static struct GNS_ResolverHandlerlh_head
 Head of resolver lookup list. More...
 
static struct GNS_ResolverHandlerlh_tail
 Tail of resolver lookup list. More...
 
static struct CacheOpsco_head
 Organized in a DLL. More...
 
static struct CacheOpsco_tail
 Organized in a DLL. More...
 
static int disable_cache
 Use namecache. More...
 
static const struct GNUNET_CONFIGURATION_Handlecfg
 Global configuration. More...
 

Detailed Description

GNU Name System resolver logic.

Author
Martin Schanzenbach
Christian Grothoff

Definition in file gnunet-service-gns_resolver.c.

Macro Definition Documentation

◆ DHT_LOOKUP_TIMEOUT

#define DHT_LOOKUP_TIMEOUT
Value:
#define GNUNET_TIME_UNIT_SECONDS
One second.
struct GNUNET_TIME_Relative GNUNET_TIME_relative_multiply(struct GNUNET_TIME_Relative rel, unsigned long long factor)
Multiply relative time by a given factor.
Definition: time.c:483

Default DHT timeout for lookups.

Definition at line 60 of file gnunet-service-gns_resolver.c.

◆ DNS_LOOKUP_TIMEOUT

#define DNS_LOOKUP_TIMEOUT
Value:

Default timeout for DNS lookups.

Definition at line 66 of file gnunet-service-gns_resolver.c.

◆ DHT_GNS_REPLICATION_LEVEL

#define DHT_GNS_REPLICATION_LEVEL   10

DHT replication level.

Definition at line 72 of file gnunet-service-gns_resolver.c.

Function Documentation

◆ is_canonical()

int is_canonical ( const char *  name)

Determine if this name is canonical (is a legal name in a zone, without delegation); note that we do not test that the name does not contain illegal characters, we only test for delegation.

Note that service records (like _foo._srv) are canonical names even though they consist of multiple labels.

Examples: a.b.gnu = not canonical a = canonical _foo._srv = canonical _f.bar = not canonical

Parameters
namethe name to test
Returns
GNUNET_YES if canonical

Definition at line 485 of file gnunet-service-gns_resolver.c.

486 {
487  const char *pos;
488  const char *dot;
489 
490  if (NULL == strchr (name,
491  (unsigned char) '.'))
492  return GNUNET_YES;
493  if ('_' != name[0])
494  return GNUNET_NO;
495  pos = &name[1];
496  while (NULL != (dot = strchr (pos,
497  (unsigned char) '.')))
498  if ('_' != dot[1])
499  return GNUNET_NO;
500  else
501  pos = dot + 1;
502  return GNUNET_YES;
503 }
@ GNUNET_YES
@ GNUNET_NO
Definition: gnunet_common.h:98
const char * name

References GNUNET_NO, GNUNET_YES, and name.

◆ translate_dot_plus()

static char* translate_dot_plus ( struct GNS_ResolverHandle rh,
char *  name 
)
static

Expands a name ending in .

  • with the zone of origin.
Parameters
rhresolution context
namename to modify (to be free'd or returned)
Returns
updated name

Definition at line 516 of file gnunet-service-gns_resolver.c.

518 {
519  char *ret;
520  size_t s_len = strlen (name);
521 
522  if (0 != strcmp (&name[s_len - 2],
523  ".+"))
524  return name; /* did not end in ".+" */
527  "%.*s.%s",
528  (int) (s_len - 2),
529  name,
532  GNUNET_free (name);
533  return ret;
534 }
static int ret
Return value of the commandline.
Definition: gnunet-abd.c:81
const char * GNUNET_GNSRECORD_pkey_to_zkey(const struct GNUNET_IDENTITY_PublicKey *pkey)
Convert public key to the respective absolute domain name in the ".zkey" pTLD.
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
int int GNUNET_asprintf(char **buf, const char *format,...) __attribute__((format(printf
Like asprintf, just portable.
#define GNUNET_free(ptr)
Wrapper around free.
int gns_authority
GNUNET_YES if the authority was a GNS authority, GNUNET_NO if the authority was a DNS authority.
union AuthorityChain::@19 authority_info
Information about the resolver authority for this label.
struct AuthorityChain * ac_tail
DLL to store the authority chain.

References GNS_ResolverHandle::ac_tail, AuthorityChain::authority_info, AuthorityChain::gns_authority, GNUNET_asprintf(), GNUNET_assert, GNUNET_free, GNUNET_GNSRECORD_pkey_to_zkey(), GNUNET_YES, name, and ret.

Referenced by handle_gns_resolution_result(), and recursive_gns2dns_resolution().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ GNS_resolver_lookup_cancel_()

static void GNS_resolver_lookup_cancel_ ( void *  cls)
static

Wrapper around GNS_resolver_lookup_cancel() as a task.

Used for delayed cleanup so we can unwind the stack first.

Parameters
clsthe struct GNS_ResolverHandle

Definition at line 544 of file gnunet-service-gns_resolver.c.

545 {
546  struct GNS_ResolverHandle *rh = cls;
547 
548  rh->task_id = NULL;
550 }
void GNS_resolver_lookup_cancel(struct GNS_ResolverHandle *rh)
Cancel active resolution (i.e.
Handle to a currently pending resolution.
struct GNUNET_SCHEDULER_Task * task_id
ID of a task associated with the resolution process.

References GNS_resolver_lookup_cancel(), and GNS_ResolverHandle::task_id.

Referenced by dns_result_parser(), fail_resolution(), GNS_resolver_lookup_cancel(), handle_gns_resolution_result(), recursive_dns_resolution(), and start_resolver_lookup().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ fail_resolution()

static void fail_resolution ( struct GNS_ResolverHandle rh)
static

Function called to asynchronously fail a resolution.

Parameters
rhthe resolution to fail

Definition at line 559 of file gnunet-service-gns_resolver.c.

560 {
561  rh->proc (rh->proc_cls,
562  0,
563  NULL);
564  GNUNET_assert (NULL == rh->task_id);
566  rh);
567 }
static void GNS_resolver_lookup_cancel_(void *cls)
Wrapper around GNS_resolver_lookup_cancel() as a task.
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_now(GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run as soon as possible.
Definition: scheduler.c:1281
void * proc_cls
closure passed to proc
GNS_ResultProcessor proc
called when resolution phase finishes

References GNS_resolver_lookup_cancel_(), GNUNET_assert, GNUNET_SCHEDULER_add_now(), GNS_ResolverHandle::proc, GNS_ResolverHandle::proc_cls, and GNS_ResolverHandle::task_id.

Referenced by continue_with_gns2dns(), dns_result_parser(), handle_dht_response(), handle_gns_resolution_result(), handle_namecache_block_response(), handle_revocation_result(), recursive_cname_resolution(), recursive_pkey_resolution(), recursive_resolution(), start_dht_request(), and timeout_resolution().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ timeout_resolution()

static void timeout_resolution ( void *  cls)
static

Function called when a resolution times out.

Parameters
clsthe struct GNS_ResolverHandle

Definition at line 576 of file gnunet-service-gns_resolver.c.

577 {
578  struct GNS_ResolverHandle *rh = cls;
579 
580  rh->task_id = NULL;
581  fail_resolution (rh);
582 }
static void fail_resolution(struct GNS_ResolverHandle *rh)
Function called to asynchronously fail a resolution.

References fail_resolution(), and GNS_ResolverHandle::task_id.

Referenced by recursive_dns_resolution().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ resolver_lookup_get_next_label()

static char* resolver_lookup_get_next_label ( struct GNS_ResolverHandle rh)
static

Get the next, rightmost label from the name that we are trying to resolve, 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).

Parameters
rhhandle to the resolution operation to get the next label from
Returns
NULL if there are no more labels

Do not advance a label. This seems to be a name only consisting of a BOX indicator (_443,_tcp). Which means, it is a BOX under the empty label. leaving name_resolution_pos as is and returning empty label.

Definition at line 603 of file gnunet-service-gns_resolver.c.

604 {
605  const char *rp;
606  const char *dot;
607  size_t len;
608  char *ret;
609  char *srv_name;
610  char *proto_name;
611  struct protoent *pe;
612  struct servent *se;
613 
614  if (0 == rh->name_resolution_pos)
615  return NULL;
616  dot = memrchr (rh->name,
617  (int) '.',
618  rh->name_resolution_pos);
619  if (NULL == dot)
620  {
621  /* done, this was the last one */
622  len = rh->name_resolution_pos;
623  rp = rh->name;
624  rh->name_resolution_pos = 0;
625  }
626  else if (('_' == dot[1]) &&
627  ('_' == rh->name[0]) &&
628  (dot == memchr (rh->name, (int) '.', rh->name_resolution_pos)))
629  {
637  len = strlen (GNUNET_GNS_EMPTY_LABEL_AT);
638  }
639  else
640  {
641  /* advance by one label */
642  len = rh->name_resolution_pos - (dot - rh->name) - 1;
643  rp = dot + 1;
644  rh->name_resolution_pos = dot - rh->name;
645  }
646  rh->protocol = 0;
647  rh->service = 0;
648  ret = GNUNET_strndup (rp, len);
649  /* If we have labels starting with underscore with label on
650  * the right (SRV/DANE/BOX case), determine port/protocol;
651  * The format of `rh->name` must be "_PORT._PROTOCOL".
652  */
653  if (('_' == rh->name[0]) &&
654  (NULL != (dot = memrchr (rh->name,
655  (int) '.',
656  rh->name_resolution_pos))) &&
657  ('_' == dot[1]) &&
658  (NULL == memrchr (rh->name,
659  (int) '.',
660  dot - rh->name)))
661  {
662  srv_name = GNUNET_strndup (&rh->name[1],
663  (dot - rh->name) - 1);
664  proto_name = GNUNET_strndup (&dot[2],
665  rh->name_resolution_pos - (dot - rh->name)
666  - 2);
667  rh->name_resolution_pos = 0;
668  pe = getprotobyname (proto_name);
669  if (NULL == pe)
670  {
672  _ ("Protocol `%s' unknown, skipping labels.\n"),
673  proto_name);
674  GNUNET_free (proto_name);
675  GNUNET_free (srv_name);
676  return ret;
677  }
678  se = getservbyname (srv_name,
679  proto_name);
680  if (NULL == se)
681  {
683  _ (
684  "Service `%s' unknown for protocol `%s', trying as number.\n"),
685  srv_name,
686  proto_name);
687  if (1 != sscanf (srv_name, "%u", &rh->service))
688  {
690  _ ("Service `%s' not a port, skipping service labels.\n"),
691  srv_name);
692  GNUNET_free (proto_name);
693  GNUNET_free (srv_name);
694  return ret;
695  }
696  }
697  else
698  {
699  rh->service = ntohs (se->s_port);
700  }
701  rh->protocol = pe->p_proto;
702  GNUNET_free (proto_name);
703  GNUNET_free (srv_name);
704  }
705  return ret;
706 }
#define memrchr(s, c, n)
Definition: compat.h:49
uint16_t len
length of data (which is always a uint32_t, but presumably this can be used to specify that fewer byt...
static char * rp
Relying party.
#define GNUNET_GNS_EMPTY_LABEL_AT
String we use to indicate an empty label (top-level entry in the zone).
#define GNUNET_log(kind,...)
@ GNUNET_ERROR_TYPE_WARNING
#define GNUNET_strndup(a, length)
Wrapper around GNUNET_xstrndup_.
#define _(String)
GNU gettext support macro.
Definition: platform.h:177
size_t name_resolution_pos
Current offset in name where we are resolving.
int service
For SRV and TLSA records, the number of the service specified in the name.
char * name
The name to resolve.
int protocol
For SRV and TLSA records, the number of the protocol specified in the name.

References _, GNUNET_ERROR_TYPE_WARNING, GNUNET_free, GNUNET_GNS_EMPTY_LABEL_AT, GNUNET_log, GNUNET_strndup, len, memrchr, GNS_ResolverHandle::name, GNS_ResolverHandle::name_resolution_pos, GNS_ResolverHandle::protocol, ret, rp, and GNS_ResolverHandle::service.

Referenced by handle_gns_redirect_result(), recursive_pkey_resolution(), and start_resolver_lookup().

Here is the caller graph for this function:

◆ transmit_lookup_dns_result()

static void transmit_lookup_dns_result ( struct GNS_ResolverHandle rh)
static

Gives the cumulative result obtained to the callback and clean up the request.

Parameters
rhresolution process that has culminated in a result

If this is a LEHO, we added this before. It must be a supplemental record #LSD0001

Definition at line 715 of file gnunet-service-gns_resolver.c.

716 {
717  struct DnsResult *pos;
718  unsigned int n;
719  unsigned int i;
720 
721  n = 0;
722  for (pos = rh->dns_result_head; NULL != pos; pos = pos->next)
723  n++;
724  {
725  struct GNUNET_GNSRECORD_Data rd[n];
726 
727  i = 0;
728  for (pos = rh->dns_result_head; NULL != pos; pos = pos->next)
729  {
730  rd[i].data = pos->data;
731  rd[i].data_size = pos->data_size;
732  rd[i].record_type = pos->record_type;
733  rd[i].flags = GNUNET_GNSRECORD_RF_NONE;
739  rd[i].flags |= GNUNET_GNSRECORD_RF_SUPPLEMENTAL;
740  if (0 == pos->expiration_time)
741  {
743  rd[i].expiration_time = 0;
744  }
745  else
746  {
747  rd[i].expiration_time = pos->expiration_time;
748  }
749  i++;
750  }
751  GNUNET_assert (i == n);
753  "Transmitting standard DNS result with %u records\n",
754  n);
755  rh->proc (rh->proc_cls,
756  n,
757  rd);
758  }
760 }
#define GNUNET_GNSRECORD_TYPE_LEHO
legacy hostnames
@ GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION
This expiration time of the record is a relative time (not an absolute time).
@ GNUNET_GNSRECORD_RF_SUPPLEMENTAL
This is a supplemental record.
@ GNUNET_GNSRECORD_RF_NONE
No special options.
@ GNUNET_ERROR_TYPE_DEBUG
A result we got from DNS.
struct DnsResult * next
Kept in DLL.
size_t data_size
Number of bytes in data.
uint32_t record_type
Type of the GNS/DNS record.
uint64_t expiration_time
Expiration time for the DNS record, 0 if we didn't get anything useful (i.e.
const void * data
Binary value stored in the DNS record (appended to this struct)
struct DnsResult * dns_result_head
DLL of results we got from DNS.
uint32_t record_type
Type of the GNS/DNS record.
const void * data
Binary value stored in the DNS record.

References DnsResult::data, GNUNET_GNSRECORD_Data::data, DnsResult::data_size, GNUNET_GNSRECORD_Data::data_size, GNS_ResolverHandle::dns_result_head, DnsResult::expiration_time, GNUNET_GNSRECORD_Data::expiration_time, GNUNET_GNSRECORD_Data::flags, GNS_resolver_lookup_cancel(), GNUNET_assert, GNUNET_ERROR_TYPE_DEBUG, GNUNET_GNSRECORD_RF_NONE, GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION, GNUNET_GNSRECORD_RF_SUPPLEMENTAL, GNUNET_GNSRECORD_TYPE_LEHO, GNUNET_log, DnsResult::next, GNS_ResolverHandle::proc, GNS_ResolverHandle::proc_cls, DnsResult::record_type, and GNUNET_GNSRECORD_Data::record_type.

Referenced by handle_dns_result().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ add_dns_result()

static void add_dns_result ( struct GNS_ResolverHandle rh,
uint64_t  expiration_time,
uint32_t  record_type,
size_t  data_size,
const void *  data 
)
static

Add a result from DNS to the records to be returned to the application.

Parameters
rhresolution request to extend with a result
expiration_timeexpiration time for the answer
record_typeDNS record type of the answer
data_sizenumber of bytes in data
databinary data to return in DNS record

Definition at line 773 of file gnunet-service-gns_resolver.c.

778 {
779  struct DnsResult *res;
780 
781  res = GNUNET_malloc (sizeof(struct DnsResult) + data_size);
782  res->expiration_time = expiration_time;
783  res->data_size = data_size;
784  res->record_type = record_type;
785  res->data = &res[1];
786  GNUNET_memcpy (&res[1],
787  data,
788  data_size);
790  rh->dns_result_tail,
791  res);
792 }
static size_t data_size
Number of bytes in data.
Definition: gnunet-abd.c:187
static int res
uint32_t data
The data value.
#define GNUNET_CONTAINER_DLL_insert(head, tail, element)
Insert an element at the head of a DLL.
#define GNUNET_memcpy(dst, src, n)
Call memcpy() but check for n being 0 first.
#define GNUNET_malloc(size)
Wrapper around malloc.
struct DnsResult * dns_result_tail
DLL of results we got from DNS.

References data, data_size, GNS_ResolverHandle::dns_result_head, GNS_ResolverHandle::dns_result_tail, DnsResult::expiration_time, GNUNET_CONTAINER_DLL_insert, GNUNET_malloc, GNUNET_memcpy, DnsResult::record_type, and res.

Referenced by dns_result_parser(), and handle_dns_result().

Here is the caller graph for this function:

◆ handle_dns_result()

static void handle_dns_result ( void *  cls,
const struct sockaddr *  addr,
socklen_t  addrlen 
)
static

We had to do a DNS lookup.

Convert the result (if any) and return it.

Parameters
clsclosure with the struct GNS_ResolverHandle
addrone of the addresses of the host, NULL for the last address
addrlenlength of the address

Definition at line 804 of file gnunet-service-gns_resolver.c.

807 {
808  struct GNS_ResolverHandle *rh = cls;
809  const struct sockaddr_in *sa4;
810  const struct sockaddr_in6 *sa6;
811 
812  if (NULL == addr)
813  {
814  rh->std_resolve = NULL;
816  return;
817  }
819  "Received %u bytes of DNS IP data\n",
820  addrlen);
821  switch (addr->sa_family)
822  {
823  case AF_INET:
824  sa4 = (const struct sockaddr_in *) addr;
825  add_dns_result (rh,
826  0 /* expiration time is unknown */,
828  sizeof(struct in_addr),
829  &sa4->sin_addr);
830  break;
831 
832  case AF_INET6:
833  sa6 = (const struct sockaddr_in6 *) addr;
834  add_dns_result (rh,
835  0 /* expiration time is unknown */,
837  sizeof(struct in6_addr),
838  &sa6->sin6_addr);
839  break;
840 
841  default:
842  GNUNET_break (0);
843  break;
844  }
845 }
static void transmit_lookup_dns_result(struct GNS_ResolverHandle *rh)
Gives the cumulative result obtained to the callback and clean up the request.
static void add_dns_result(struct GNS_ResolverHandle *rh, uint64_t expiration_time, uint32_t record_type, size_t data_size, const void *data)
Add a result from DNS to the records to be returned to the application.
#define GNUNET_DNSPARSER_TYPE_A
#define GNUNET_DNSPARSER_TYPE_AAAA
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur.
struct GNUNET_RESOLVER_RequestHandle * std_resolve
Handle for standard DNS resolution, NULL if none is active.

References add_dns_result(), GNUNET_break, GNUNET_DNSPARSER_TYPE_A, GNUNET_DNSPARSER_TYPE_AAAA, GNUNET_ERROR_TYPE_DEBUG, GNUNET_log, GNS_ResolverHandle::std_resolve, and transmit_lookup_dns_result().

Referenced by dns_result_parser(), handle_gns_cname_result(), and handle_gns_redirect_result().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ recursive_resolution()

static void recursive_resolution ( void *  cls)
static

Task scheduled to continue with the resolution process.

Parameters
clsthe 'struct GNS_ResolverHandle' of the resolution

Definition at line 2694 of file gnunet-service-gns_resolver.c.

2695 {
2696  struct GNS_ResolverHandle *rh = cls;
2697 
2698  rh->task_id = NULL;
2699  if (rh->loop_threshold < rh->loop_limiter++)
2700  {
2702  "Encountered unbounded recursion resolving `%s'\n",
2703  rh->name);
2704  fail_resolution (rh);
2705  return;
2706  }
2707  if (GNUNET_YES == rh->ac_tail->gns_authority)
2709  else
2711 }
static void recursive_gns_resolution_revocation(struct GNS_ResolverHandle *rh)
Perform revocation check on tail of our authority chain.
static void recursive_dns_resolution(struct GNS_ResolverHandle *rh)
Perform recursive DNS resolution.
unsigned int loop_limiter
We increment the loop limiter for each step in a recursive resolution.
unsigned int loop_threshold
Maximum value of loop_limiter allowed by client.

References GNS_ResolverHandle::ac_tail, fail_resolution(), AuthorityChain::gns_authority, GNUNET_ERROR_TYPE_WARNING, GNUNET_log, GNUNET_YES, GNS_ResolverHandle::loop_limiter, GNS_ResolverHandle::loop_threshold, GNS_ResolverHandle::name, recursive_dns_resolution(), recursive_gns_resolution_revocation(), and GNS_ResolverHandle::task_id.

Referenced by continue_with_gns2dns(), handle_gns_redirect_result(), handle_gns_resolution_result(), recursive_pkey_resolution(), and start_resolver_lookup().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ start_resolver_lookup()

static void start_resolver_lookup ( void *  cls)
static

Begin the resolution process from 'name', starting with the identification of the zone specified by 'name'.

Parameters
clsclosure with struct GNS_ResolverHandle *rh

Definition at line 2715 of file gnunet-service-gns_resolver.c.

2716 {
2717  struct GNS_ResolverHandle *rh = cls;
2718  struct AuthorityChain *ac;
2719  struct in_addr v4;
2720  struct in6_addr v6;
2721 
2722  rh->task_id = NULL;
2723  if (1 == inet_pton (AF_INET,
2724  rh->name,
2725  &v4))
2726  {
2727  /* name is IPv4 address, pretend it's an A record */
2728  struct GNUNET_GNSRECORD_Data rd;
2729 
2730  rd.data = &v4;
2731  rd.data_size = sizeof(v4);
2732  rd.expiration_time = UINT64_MAX;
2733  rd.record_type = GNUNET_DNSPARSER_TYPE_A;
2734  rd.flags = 0;
2735  rh->proc (rh->proc_cls,
2736  1,
2737  &rd);
2738  GNUNET_assert (NULL == rh->task_id);
2740  rh);
2741  return;
2742  }
2743  if (1 == inet_pton (AF_INET6,
2744  rh->name,
2745  &v6))
2746  {
2747  /* name is IPv6 address, pretend it's an AAAA record */
2748  struct GNUNET_GNSRECORD_Data rd;
2749 
2750  rd.data = &v6;
2751  rd.data_size = sizeof(v6);
2752  rd.expiration_time = UINT64_MAX;
2753  rd.record_type = GNUNET_DNSPARSER_TYPE_AAAA;
2754  rd.flags = 0;
2755  rh->proc (rh->proc_cls,
2756  1,
2757  &rd);
2758  GNUNET_assert (NULL == rh->task_id);
2760  rh);
2761  return;
2762  }
2763 
2764  ac = GNUNET_new (struct AuthorityChain);
2765  ac->rh = rh;
2766  ac->label = resolver_lookup_get_next_label (rh);
2767  if (NULL == ac->label)
2768  /* name was just the "TLD", so we default to label
2769  #GNUNET_GNS_EMPTY_LABEL_AT */
2771  ac->gns_authority = GNUNET_YES;
2772  ac->authority_info.gns_authority = rh->authority_zone;
2774  rh->ac_tail,
2775  ac);
2777  rh);
2778 }
static struct GNUNET_MQ_Envelope * ac
Handle to current GNUNET_PEERINFO_add_peer() operation.
static void recursive_resolution(void *cls)
Task scheduled to continue with the resolution process.
static char * resolver_lookup_get_next_label(struct GNS_ResolverHandle *rh)
Get the next, rightmost label from the name that we are trying to resolve, and update the resolution ...
#define GNUNET_CONTAINER_DLL_insert_tail(head, tail, element)
Insert an element at the tail of a DLL.
#define GNUNET_strdup(a)
Wrapper around GNUNET_xstrdup_.
#define GNUNET_new(type)
Allocate a struct or union of the given type.
DLL to hold the authority chain we had to pass in the resolution process.
struct AuthorityChain * ac_head
DLL to store the authority chain.
struct GNUNET_IDENTITY_PublicKey authority_zone
The top-level GNS authoritative zone to query.

References ac, GNS_ResolverHandle::ac_head, GNS_ResolverHandle::ac_tail, GNS_ResolverHandle::authority_zone, GNUNET_GNSRECORD_Data::data, GNUNET_GNSRECORD_Data::data_size, GNUNET_GNSRECORD_Data::expiration_time, GNUNET_GNSRECORD_Data::flags, GNS_resolver_lookup_cancel_(), GNUNET_assert, GNUNET_CONTAINER_DLL_insert_tail, GNUNET_DNSPARSER_TYPE_A, GNUNET_DNSPARSER_TYPE_AAAA, GNUNET_GNS_EMPTY_LABEL_AT, GNUNET_new, GNUNET_SCHEDULER_add_now(), GNUNET_strdup, GNUNET_YES, GNS_ResolverHandle::name, GNS_ResolverHandle::proc, GNS_ResolverHandle::proc_cls, GNUNET_GNSRECORD_Data::record_type, recursive_resolution(), resolver_lookup_get_next_label(), and GNS_ResolverHandle::task_id.

Referenced by GNS_resolver_lookup(), and recursive_gns2dns_resolution().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ dns_result_parser()

static void dns_result_parser ( void *  cls,
const struct GNUNET_TUN_DnsHeader dns,
size_t  dns_len 
)
static

Function called with the result of a DNS resolution.

Parameters
clsthe request handle of the resolution that we were attempting to make
dnsdns response, never NULL
dns_lennumber of bytes in dns

Definition at line 876 of file gnunet-service-gns_resolver.c.

879 {
880  struct GNS_ResolverHandle *rh = cls;
881  struct GNUNET_DNSPARSER_Packet *p;
882  const struct GNUNET_DNSPARSER_Record *rec;
883  unsigned int rd_count;
884 
885  if (NULL == dns)
886  {
887  rh->dns_request = NULL;
889  rh->task_id = NULL;
890  fail_resolution (rh);
891  return;
892  }
893  if (rh->original_dns_id != dns->id)
894  {
895  /* DNS answer, but for another query */
896  return;
897  }
898  p = GNUNET_DNSPARSER_parse ((const char *) dns,
899  dns_len);
900  if (NULL == p)
901  {
903  _ ("Failed to parse DNS response\n"));
904  return;
905  }
906 
907  /* We got a result from DNS */
909  "Received DNS response for `%s' with %u answers\n",
910  rh->ac_tail->label,
911  (unsigned int) p->num_answers);
912  if ((p->num_answers > 0) &&
913  (GNUNET_DNSPARSER_TYPE_CNAME == p->answers[0].type) &&
915  {
916  int af;
917 
919  "Got CNAME `%s' from DNS for `%s'\n",
920  p->answers[0].data.hostname,
921  rh->name);
922  if (NULL != rh->std_resolve)
923  {
925  "Multiple CNAME results from DNS resolving `%s'! Not really allowed...\n",
926  rh->name);
928  }
929  GNUNET_free (rh->name);
930  rh->name = GNUNET_strdup (p->answers[0].data.hostname);
931  rh->name_resolution_pos = strlen (rh->name);
932  switch (rh->record_type)
933  {
935  af = AF_INET;
936  break;
937 
939  af = AF_INET6;
940  break;
941 
942  default:
943  af = AF_UNSPEC;
944  break;
945  }
946  if (NULL != rh->leho)
947  add_dns_result (rh,
948  GNUNET_TIME_UNIT_HOURS.rel_value_us,
950  strlen (rh->leho),
951  rh->leho);
953  af,
956  rh);
959  rh->dns_request = NULL;
960  return;
961  }
962 
963  /* convert from (parsed) DNS to (binary) GNS format! */
964  rd_count = p->num_answers + p->num_authority_records
965  + p->num_additional_records;
966  {
967  struct GNUNET_GNSRECORD_Data rd[rd_count + 1]; /* +1 for LEHO */
968  int skip;
969  char buf[UINT16_MAX];
970  size_t buf_off;
971  size_t buf_start;
972 
973  buf_off = 0;
974  skip = 0;
975  memset (rd,
976  0,
977  sizeof(rd));
978  for (unsigned int i = 0; i < rd_count; i++)
979  {
980  if (i < p->num_answers)
981  rec = &p->answers[i];
982  else if (i < p->num_answers + p->num_authority_records)
983  rec = &p->authority_records[i - p->num_answers];
984  else
985  rec = &p->additional_records[i - p->num_answers
986  - p->num_authority_records];
987  /* As we copied the full DNS name to 'rh->ac_tail->label', this
988  should be the correct check to see if this record is actually
989  a record for our label... */
990  if (0 != strcmp (rec->name,
991  rh->ac_tail->label))
992  {
994  "Dropping record `%s', does not match desired name `%s'\n",
995  rec->name,
996  rh->ac_tail->label);
997  skip++;
998  continue;
999  }
1000  rd[i - skip].record_type = rec->type;
1001  rd[i - skip].expiration_time = rec->expiration_time.abs_value_us;
1002  switch (rec->type)
1003  {
1005  if (rec->data.raw.data_len != sizeof(struct in_addr))
1006  {
1007  GNUNET_break_op (0);
1008  skip++;
1009  continue;
1010  }
1011  rd[i - skip].data_size = rec->data.raw.data_len;
1012  rd[i - skip].data = rec->data.raw.data;
1013  break;
1014 
1016  if (rec->data.raw.data_len != sizeof(struct in6_addr))
1017  {
1018  GNUNET_break_op (0);
1019  skip++;
1020  continue;
1021  }
1022  rd[i - skip].data_size = rec->data.raw.data_len;
1023  rd[i - skip].data = rec->data.raw.data;
1024  break;
1025 
1029  buf_start = buf_off;
1030  if (GNUNET_OK !=
1032  sizeof(buf),
1033  &buf_off,
1034  rec->data.hostname))
1035  {
1036  GNUNET_break (0);
1037  skip++;
1038  continue;
1039  }
1040  rd[i - skip].data_size = buf_off - buf_start;
1041  rd[i - skip].data = &buf[buf_start];
1042  break;
1043 
1045  buf_start = buf_off;
1046  if (GNUNET_OK !=
1048  sizeof(buf),
1049  &buf_off,
1050  rec->data.soa))
1051  {
1052  GNUNET_break (0);
1053  skip++;
1054  continue;
1055  }
1056  rd[i - skip].data_size = buf_off - buf_start;
1057  rd[i - skip].data = &buf[buf_start];
1058  break;
1059 
1061  buf_start = buf_off;
1062  if (GNUNET_OK !=
1064  sizeof(buf),
1065  &buf_off,
1066  rec->data.mx))
1067  {
1068  GNUNET_break (0);
1069  skip++;
1070  continue;
1071  }
1072  rd[i - skip].data_size = buf_off - buf_start;
1073  rd[i - skip].data = &buf[buf_start];
1074  break;
1075 
1077  buf_start = buf_off;
1078  if (GNUNET_OK !=
1080  sizeof(buf),
1081  &buf_off,
1082  rec->data.srv))
1083  {
1084  GNUNET_break (0);
1085  skip++;
1086  continue;
1087  }
1088  rd[i - skip].data_size = buf_off - buf_start;
1089  rd[i - skip].data = &buf[buf_start];
1090  break;
1091 
1092  default:
1094  _ ("Skipping record of unsupported type %d\n"),
1095  rec->type);
1096  skip++;
1097  continue;
1098  }
1099  } /* end of for all records in answer */
1100  if (NULL != rh->leho)
1101  {
1102  rd[rd_count - skip].record_type = GNUNET_GNSRECORD_TYPE_LEHO;
1103  rd[rd_count - skip].flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION;
1104  rd[rd_count - skip].flags |= GNUNET_GNSRECORD_RF_SUPPLEMENTAL;
1105  rd[rd_count - skip].expiration_time = GNUNET_TIME_UNIT_HOURS.rel_value_us;
1106  rd[rd_count - skip].data = rh->leho;
1107  rd[rd_count - skip].data_size = strlen (rh->leho);
1108  skip--; /* skip one LESS */
1110  "Adding LEHO %s\n",
1111  rh->leho);
1112  }
1114  "Returning DNS response for `%s' with %u answers\n",
1115  rh->ac_tail->label,
1116  (unsigned int) (rd_count - skip));
1117  rh->proc (rh->proc_cls,
1118  rd_count - skip,
1119  rd);
1121  rh->dns_request = NULL;
1122  }
1124  if (NULL != rh->task_id)
1125  GNUNET_SCHEDULER_cancel (rh->task_id); /* should be timeout task */
1127  rh);
1128 }
#define DNS_LOOKUP_TIMEOUT
Default timeout for DNS lookups.
static void handle_dns_result(void *cls, const struct sockaddr *addr, socklen_t addrlen)
We had to do a DNS lookup.
static char buf[2048]
static struct GNUNET_OS_Process * p
Helper process we started.
Definition: gnunet-uri.c:37
int GNUNET_DNSPARSER_builder_add_name(char *dst, size_t dst_len, size_t *off, const char *name)
Add a DNS name to the UDP packet at the given location, converting the name to IDNA notation as neces...
Definition: dnsparser.c:889
void GNUNET_DNSPARSER_free_packet(struct GNUNET_DNSPARSER_Packet *p)
Free memory taken by a packet.
Definition: dnsparser.c:854
#define GNUNET_DNSPARSER_TYPE_SRV
#define GNUNET_DNSPARSER_TYPE_SOA
#define GNUNET_DNSPARSER_TYPE_PTR
struct GNUNET_DNSPARSER_Packet * GNUNET_DNSPARSER_parse(const char *udp_payload, size_t udp_payload_length)
Parse a UDP payload of a DNS packet in to a nice struct for further processing and manipulation.
Definition: dnsparser.c:656
#define GNUNET_DNSPARSER_TYPE_NS
int GNUNET_DNSPARSER_builder_add_soa(char *dst, size_t dst_len, size_t *off, const struct GNUNET_DNSPARSER_SoaRecord *soa)
Add an SOA record to the UDP packet at the given location.
Definition: dnsparser.c:1077
#define GNUNET_DNSPARSER_TYPE_CNAME
int GNUNET_DNSPARSER_builder_add_mx(char *dst, size_t dst_len, size_t *off, const struct GNUNET_DNSPARSER_MxRecord *mx)
Add an MX record to the UDP packet at the given location.
Definition: dnsparser.c:1001
int GNUNET_DNSPARSER_builder_add_srv(char *dst, size_t dst_len, size_t *off, const struct GNUNET_DNSPARSER_SrvRecord *srv)
Add an SRV record to the UDP packet at the given location.
Definition: dnsparser.c:1118
#define GNUNET_DNSPARSER_TYPE_MX
void GNUNET_DNSSTUB_resolve_cancel(struct GNUNET_DNSSTUB_RequestSocket *rs)
Cancel DNS resolution.
Definition: dnsstub.c:566
@ GNUNET_OK
Definition: gnunet_common.h:99
#define GNUNET_break_op(cond)
Use this for assertion violations caused by other peers (i.e.
@ GNUNET_ERROR_TYPE_INFO
void GNUNET_RESOLVER_request_cancel(struct GNUNET_RESOLVER_RequestHandle *rh)
Cancel a request that is still pending with the resolver.
struct GNUNET_RESOLVER_RequestHandle * GNUNET_RESOLVER_ip_get(const char *hostname, int af, struct GNUNET_TIME_Relative timeout, GNUNET_RESOLVER_AddressCallback callback, void *callback_cls)
Convert a string to one or more IP addresses.
Definition: resolver_api.c:939
void * GNUNET_SCHEDULER_cancel(struct GNUNET_SCHEDULER_Task *task)
Cancel the task with the specified identifier.
Definition: scheduler.c:957
#define GNUNET_TIME_UNIT_HOURS
One hour.
char * label
label/name corresponding to the authority
char * leho
Legacy Hostname to use if we encountered GNS2DNS record and thus can deduct the LEHO from that transi...
int record_type
Desired type for the resolution.
uint16_t original_dns_id
16 bit random ID we used in the dns_request.
struct GNUNET_DNSSTUB_RequestSocket * dns_request
Socket for a DNS request, NULL if none is active.
Easy-to-process, parsed version of a DNS packet.
void * data
Binary record data.
size_t data_len
Number of bytes in data.
A DNS response record.
struct GNUNET_DNSPARSER_SoaRecord * soa
SOA data for SOA records.
struct GNUNET_DNSPARSER_SrvRecord * srv
SRV data for SRV records.
struct GNUNET_DNSPARSER_MxRecord * mx
MX data for MX records.
char * hostname
For NS, CNAME and PTR records, this is the uncompressed 0-terminated hostname.
uint16_t type
See GNUNET_DNSPARSER_TYPE_*.
struct GNUNET_TIME_Absolute expiration_time
When does the record expire?
union GNUNET_DNSPARSER_Record::@24 data
Payload of the record (which one of these is valid depends on the 'type').
char * name
Name of the record that the query is for (0-terminated).
struct GNUNET_DNSPARSER_RawRecord raw
Raw data for all other types.
uint64_t abs_value_us
The actual value.
uint16_t id
Unique identifier for the request/response.

References _, GNUNET_TIME_Absolute::abs_value_us, GNS_ResolverHandle::ac_tail, add_dns_result(), buf, GNUNET_DNSPARSER_RawRecord::data, GNUNET_DNSPARSER_Record::data, GNUNET_GNSRECORD_Data::data, GNUNET_DNSPARSER_RawRecord::data_len, GNUNET_GNSRECORD_Data::data_size, DNS_LOOKUP_TIMEOUT, GNS_ResolverHandle::dns_request, GNUNET_DNSPARSER_Record::expiration_time, GNUNET_GNSRECORD_Data::expiration_time, fail_resolution(), GNUNET_GNSRECORD_Data::flags, GNS_resolver_lookup_cancel_(), GNUNET_break, GNUNET_break_op, GNUNET_DNSPARSER_builder_add_mx(), GNUNET_DNSPARSER_builder_add_name(), GNUNET_DNSPARSER_builder_add_soa(), GNUNET_DNSPARSER_builder_add_srv(), GNUNET_DNSPARSER_free_packet(), GNUNET_DNSPARSER_parse(), GNUNET_DNSPARSER_TYPE_A, GNUNET_DNSPARSER_TYPE_AAAA, GNUNET_DNSPARSER_TYPE_CNAME, GNUNET_DNSPARSER_TYPE_MX, GNUNET_DNSPARSER_TYPE_NS, GNUNET_DNSPARSER_TYPE_PTR, GNUNET_DNSPARSER_TYPE_SOA, GNUNET_DNSPARSER_TYPE_SRV, GNUNET_DNSSTUB_resolve_cancel(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_ERROR_TYPE_INFO, GNUNET_ERROR_TYPE_WARNING, GNUNET_free, GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION, GNUNET_GNSRECORD_RF_SUPPLEMENTAL, GNUNET_GNSRECORD_TYPE_LEHO, GNUNET_log, GNUNET_OK, GNUNET_RESOLVER_ip_get(), GNUNET_RESOLVER_request_cancel(), GNUNET_SCHEDULER_add_now(), GNUNET_SCHEDULER_cancel(), GNUNET_strdup, GNUNET_TIME_UNIT_HOURS, handle_dns_result(), GNUNET_DNSPARSER_Record::hostname, GNUNET_TUN_DnsHeader::id, AuthorityChain::label, GNS_ResolverHandle::leho, GNUNET_DNSPARSER_Record::mx, GNS_ResolverHandle::name, GNUNET_DNSPARSER_Record::name, GNS_ResolverHandle::name_resolution_pos, GNS_ResolverHandle::original_dns_id, p, GNS_ResolverHandle::proc, GNS_ResolverHandle::proc_cls, GNUNET_DNSPARSER_Record::raw, GNS_ResolverHandle::record_type, GNUNET_GNSRECORD_Data::record_type, GNUNET_DNSPARSER_Record::soa, GNUNET_DNSPARSER_Record::srv, GNS_ResolverHandle::std_resolve, GNS_ResolverHandle::task_id, and GNUNET_DNSPARSER_Record::type.

Referenced by recursive_dns_resolution().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ recursive_dns_resolution()

static void recursive_dns_resolution ( struct GNS_ResolverHandle rh)
static

Perform recursive DNS resolution.

Asks the given DNS resolver to resolve "rh->dns_name", possibly recursively proceeding following NS delegations, CNAMES, etc., until 'rh->loop_limiter' bounds us or we find the answer.

Parameters
rhresolution information

Definition at line 1140 of file gnunet-service-gns_resolver.c.

1141 {
1142  struct AuthorityChain *ac;
1143  struct GNUNET_DNSPARSER_Query *query;
1144  struct GNUNET_DNSPARSER_Packet *p;
1145  char *dns_request;
1146  size_t dns_request_length;
1147  int ret;
1148 
1149  ac = rh->ac_tail;
1150  GNUNET_assert (NULL != ac);
1152  "Starting DNS lookup for `%s'\n",
1153  ac->label);
1154  GNUNET_assert (GNUNET_NO == ac->gns_authority);
1155  query = GNUNET_new (struct GNUNET_DNSPARSER_Query);
1156  query->name = GNUNET_strdup (ac->label);
1157  query->type = rh->record_type;
1160  p->queries = query;
1161  p->num_queries = 1;
1163  UINT16_MAX);
1164  p->flags.opcode = GNUNET_TUN_DNS_OPCODE_QUERY;
1165  p->flags.recursion_desired = 1;
1167  1024,
1168  &dns_request,
1169  &dns_request_length);
1170  if (GNUNET_OK != ret)
1171  {
1172  GNUNET_break (0);
1173  rh->proc (rh->proc_cls,
1174  0,
1175  NULL);
1176  GNUNET_assert (NULL == rh->task_id);
1178  rh);
1179  }
1180  else
1181  {
1182  rh->original_dns_id = p->id;
1183  GNUNET_assert (NULL != ac->authority_info.dns_authority.dns_handle);
1184  GNUNET_assert (NULL == rh->dns_request);
1185  rh->leho = GNUNET_strdup (ac->label);
1187  ac->authority_info.dns_authority.dns_handle,
1188  dns_request,
1189  dns_request_length,
1191  rh);
1194  rh);
1195  }
1196  if (GNUNET_SYSERR != ret)
1197  GNUNET_free (dns_request);
1199 }
static void dns_result_parser(void *cls, const struct GNUNET_TUN_DnsHeader *dns, size_t dns_len)
Function called with the result of a DNS resolution.
static void timeout_resolution(void *cls)
Function called when a resolution times out.
uint32_t GNUNET_CRYPTO_random_u32(enum GNUNET_CRYPTO_Quality mode, uint32_t i)
Produce a random value.
@ GNUNET_CRYPTO_QUALITY_NONCE
Randomness for IVs etc.
int GNUNET_DNSPARSER_pack(const struct GNUNET_DNSPARSER_Packet *p, uint16_t max, char **buf, size_t *buf_length)
Given a DNS packet p, generate the corresponding UDP payload.
Definition: dnsparser.c:1257
struct GNUNET_DNSSTUB_RequestSocket * GNUNET_DNSSTUB_resolve(struct GNUNET_DNSSTUB_Context *ctx, const void *request, size_t request_len, GNUNET_DNSSTUB_ResultCallback rc, void *rc_cls)
Perform DNS resolution using our default IP from init.
Definition: dnsstub.c:530
@ GNUNET_SYSERR
Definition: gnunet_common.h:97
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_delayed(struct GNUNET_TIME_Relative delay, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run with a specified delay.
Definition: scheduler.c:1254
#define GNUNET_TUN_DNS_CLASS_INTERNET
A few common DNS classes (ok, only one is common, but I list a couple more to make it clear what we'r...
#define GNUNET_TUN_DNS_OPCODE_QUERY
uint16_t dns_traffic_class
See GNUNET_TUN_DNS_CLASS_*.
uint16_t type
See GNUNET_DNSPARSER_TYPE_*.
char * name
Name of the record that the query is for (0-terminated).

References ac, GNS_ResolverHandle::ac_tail, DNS_LOOKUP_TIMEOUT, GNS_ResolverHandle::dns_request, dns_result_parser(), GNUNET_DNSPARSER_Query::dns_traffic_class, GNS_resolver_lookup_cancel_(), GNUNET_assert, GNUNET_break, GNUNET_CRYPTO_QUALITY_NONCE, GNUNET_CRYPTO_random_u32(), GNUNET_DNSPARSER_free_packet(), GNUNET_DNSPARSER_pack(), GNUNET_DNSSTUB_resolve(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_free, GNUNET_log, GNUNET_new, GNUNET_NO, GNUNET_OK, GNUNET_SCHEDULER_add_delayed(), GNUNET_SCHEDULER_add_now(), GNUNET_strdup, GNUNET_SYSERR, GNUNET_TUN_DNS_CLASS_INTERNET, GNUNET_TUN_DNS_OPCODE_QUERY, GNS_ResolverHandle::leho, GNUNET_DNSPARSER_Query::name, GNS_ResolverHandle::original_dns_id, p, GNS_ResolverHandle::proc, GNS_ResolverHandle::proc_cls, GNS_ResolverHandle::record_type, ret, GNS_ResolverHandle::task_id, timeout_resolution(), and GNUNET_DNSPARSER_Query::type.

Referenced by recursive_resolution().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ handle_gns_redirect_result()

static void handle_gns_redirect_result ( struct GNS_ResolverHandle rh,
const char *  rname 
)
static

We encountered a REDIRECT record during our resolution.

Merge it into our chain.

Parameters
rhresolution we are performing
rnamevalue of the redirect record we got for the current authority chain tail

Definition at line 1211 of file gnunet-service-gns_resolver.c.

1213 {
1214  size_t nlen;
1215  char *res;
1216  const char *tld;
1217  struct AuthorityChain *ac;
1218  int af;
1220 
1222  "Handling GNS REDIRECT result `%s'\n",
1223  rname);
1224  nlen = strlen (rname);
1225  tld = GNS_get_tld (rname);
1226  if (0 == strcmp ("+", tld))
1227  {
1228  /* REDIRECT resolution continues relative to current domain */
1229  if (0 == rh->name_resolution_pos)
1230  {
1231  res = GNUNET_strndup (rname, nlen - 2);
1232  rh->name_resolution_pos = nlen - 2;
1233  }
1234  else
1235  {
1236  GNUNET_asprintf (&res,
1237  "%.*s.%.*s",
1238  (int) rh->name_resolution_pos,
1239  rh->name,
1240  (int) (nlen - 2),
1241  rname);
1242  rh->name_resolution_pos = strlen (res);
1243  }
1244  GNUNET_free (rh->name);
1245  rh->name = res;
1246  ac = GNUNET_new (struct AuthorityChain);
1247  ac->rh = rh;
1248  ac->gns_authority = GNUNET_YES;
1249  ac->authority_info.gns_authority =
1251  ac->label = resolver_lookup_get_next_label (rh);
1252  /* add AC to tail */
1254  rh->ac_tail,
1255  ac);
1257  rh);
1258  return;
1259  }
1261  {
1262  /* REDIRECT resolution continues relative to current domain */
1263  if (0 == rh->name_resolution_pos)
1264  {
1265  GNUNET_asprintf (&res,
1266  "%.*s",
1267  (int) (strlen (rname) - (strlen (tld) + 1)),
1268  rname);
1269  }
1270  else
1271  {
1272  GNUNET_asprintf (&res,
1273  "%.*s.%.*s",
1274  (int) rh->name_resolution_pos,
1275  rh->name,
1276  (int) (strlen (rname) - (strlen (tld) + 1)),
1277  rname);
1278  }
1279  rh->name_resolution_pos = strlen (res);
1280  GNUNET_free (rh->name);
1281  rh->name = res;
1282  ac = GNUNET_new (struct AuthorityChain);
1283  ac->rh = rh;
1284  ac->gns_authority = GNUNET_YES;
1285  ac->authority_info.gns_authority = zone;
1286  ac->label = resolver_lookup_get_next_label (rh);
1287  /* add AC to tail */
1289  rh->ac_tail,
1290  ac);
1292  rh);
1293  return;
1294  }
1295 
1297  "Got REDIRECT `%s' from GNS for `%s'\n",
1298  rname,
1299  rh->name);
1300  if (NULL != rh->std_resolve)
1301  {
1303  "Multiple REDIRECT results from GNS resolving `%s'! Not really allowed...\n",
1304  rh->name);
1306  }
1307  /* name is absolute, go to DNS */
1308  GNUNET_free (rh->name);
1309  rh->name = GNUNET_strdup (rname);
1310  rh->name_resolution_pos = strlen (rh->name);
1311  switch (rh->record_type)
1312  {
1314  af = AF_INET;
1315  break;
1316 
1318  af = AF_INET6;
1319  break;
1320 
1321  default:
1322  af = AF_UNSPEC;
1323  break;
1324  }
1326  "Doing standard DNS lookup for `%s'\n",
1327  rh->name);
1328 
1330  af,
1333  rh);
1334 }
static char * zone
Name of the zone being managed.
const char * GNS_get_tld(const char *name)
Obtain the TLD of the given name.
int GNUNET_GNSRECORD_zkey_to_pkey(const char *zkey, struct GNUNET_IDENTITY_PublicKey *pkey)
Convert an absolute domain name to the respective public key.
An identity key as per LSD0001.

References ac, GNS_ResolverHandle::ac_head, GNS_ResolverHandle::ac_tail, AuthorityChain::authority_info, DNS_LOOKUP_TIMEOUT, AuthorityChain::gns_authority, GNS_get_tld(), GNUNET_asprintf(), GNUNET_CONTAINER_DLL_insert_tail, GNUNET_DNSPARSER_TYPE_A, GNUNET_DNSPARSER_TYPE_AAAA, GNUNET_ERROR_TYPE_DEBUG, GNUNET_ERROR_TYPE_INFO, GNUNET_ERROR_TYPE_WARNING, GNUNET_free, GNUNET_GNSRECORD_zkey_to_pkey(), GNUNET_log, GNUNET_new, GNUNET_OK, GNUNET_RESOLVER_ip_get(), GNUNET_RESOLVER_request_cancel(), GNUNET_SCHEDULER_add_now(), GNUNET_strdup, GNUNET_strndup, GNUNET_YES, handle_dns_result(), GNS_ResolverHandle::name, GNS_ResolverHandle::name_resolution_pos, GNS_ResolverHandle::record_type, recursive_resolution(), res, resolver_lookup_get_next_label(), GNS_ResolverHandle::std_resolve, GNS_ResolverHandle::task_id, and zone.

Referenced by handle_gns_resolution_result(), and recursive_redirect_resolution().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ handle_gns_cname_result()

static void handle_gns_cname_result ( struct GNS_ResolverHandle rh,
const char *  cname 
)
static

We encountered a CNAME record during our resolution.

Merge it into our chain.

Parameters
rhresolution we are performing
cnamevalue of the cname record we got for the current authority chain tail

Definition at line 1346 of file gnunet-service-gns_resolver.c.

1348 {
1349  int af;
1350 
1351  GNUNET_free (rh->name);
1352  rh->name = GNUNET_strdup (cname);
1353  rh->name_resolution_pos = strlen (rh->name);
1354  switch (rh->record_type)
1355  {
1357  af = AF_INET;
1358  break;
1359 
1361  af = AF_INET6;
1362  break;
1363 
1364  default:
1365  af = AF_UNSPEC;
1366  break;
1367  }
1369  "Doing standard DNS lookup for `%s'\n",
1370  rh->name);
1371 
1373  af,
1376  rh);
1377 }

References DNS_LOOKUP_TIMEOUT, GNUNET_DNSPARSER_TYPE_A, GNUNET_DNSPARSER_TYPE_AAAA, GNUNET_ERROR_TYPE_DEBUG, GNUNET_free, GNUNET_log, GNUNET_RESOLVER_ip_get(), GNUNET_strdup, handle_dns_result(), GNS_ResolverHandle::name, GNS_ResolverHandle::name_resolution_pos, GNS_ResolverHandle::record_type, and GNS_ResolverHandle::std_resolve.

Referenced by handle_gns_resolution_result(), and recursive_cname_resolution().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ handle_gns_resolution_result()

static void handle_gns_resolution_result ( void *  cls,
unsigned int  rd_count,
const struct GNUNET_GNSRECORD_Data rd 
)
static

Process records that were decrypted from a block.

Parameters
clsclosure with the 'struct GNS_ResolverHandle'
rd_countnumber of entries in rd array
rdarray of records with data to store

Definition at line 1897 of file gnunet-service-gns_resolver.c.

1900 {
1901  struct GNS_ResolverHandle *rh = cls;
1902  char *cname;
1903  char scratch[UINT16_MAX];
1904  size_t scratch_off;
1905  size_t scratch_start;
1906  size_t off;
1907  struct GNUNET_GNSRECORD_Data rd_new[rd_count];
1908  unsigned int rd_off;
1909 
1911  "Resolution succeeded for `%s' in zone %s, got %u records\n",
1912  rh->ac_tail->label,
1914  rd_count);
1915  if (0 == rd_count)
1916  {
1918  _ ("GNS lookup failed (zero records found for `%s')\n"),
1919  rh->name);
1920  fail_resolution (rh);
1921  return;
1922  }
1923 
1924  if (0 == rh->name_resolution_pos)
1925  {
1926  /* top-level match, are we done yet? */
1927  if ((rd_count > 0) &&
1930  {
1931  off = 0;
1932  cname = GNUNET_DNSPARSER_parse_name (rd[0].data,
1933  rd[0].data_size,
1934  &off);
1935  if ((NULL == cname) ||
1936  (off != rd[0].data_size))
1937  {
1938  GNUNET_break_op (0);
1939  GNUNET_free (cname);
1940  fail_resolution (rh);
1941  return;
1942  }
1944  cname);
1945  GNUNET_free (cname);
1946  return;
1947  }
1948  if ((rd_count > 0) &&
1951  {
1953  rd[0].data);
1954  return;
1955  }
1956 
1957 
1958  /* If A/AAAA was requested,
1959  * but we got a GNS2DNS record */
1960  if ((GNUNET_DNSPARSER_TYPE_A == rh->record_type) ||
1962  {
1963  for (unsigned int i = 0; i < rd_count; i++)
1964  {
1965  switch (rd[i].record_type)
1966  {
1968  {
1969  /* delegation to DNS */
1971  "Found GNS2DNS record, delegating to DNS!\n");
1972  if (GNUNET_OK ==
1974  rd_count,
1975  rd))
1976  return;
1977  else
1978  goto fail;
1979  }
1980 
1981  default:
1982  break;
1983  } /* end: switch */
1984  } /* end: for rd */
1985  } /* end: name_resolution_pos */
1986  /* convert relative names in record values to absolute names,
1987  using 'scratch' array for memory allocations */
1988  scratch_off = 0;
1989  rd_off = 0;
1990  for (unsigned int i = 0; i < rd_count; i++)
1991  {
1992  GNUNET_assert (rd_off <= i);
1993  if ((0 != rh->protocol) &&
1994  (0 != rh->service) &&
1995  (GNUNET_GNSRECORD_TYPE_BOX != rd[i].record_type))
1996  continue; /* we _only_ care about boxed records */
1997 
1998  GNUNET_assert (rd_off < rd_count);
1999  rd_new[rd_off] = rd[i];
2000  /* Check if the embedded name(s) end in "+", and if so,
2001  replace the "+" with the zone at "ac_tail", changing the name
2002  to a ".ZONEKEY". The name is allocated on the 'scratch' array,
2003  so we can free it afterwards. */
2004  switch (rd[i].record_type)
2005  {
2007  {
2008  char *rname;
2009  rname = GNUNET_strndup (rd[i].data, rd[i].data_size);
2010  rname = translate_dot_plus (rh, rname);
2011  GNUNET_break (NULL != rname);
2012  scratch_start = scratch_off;
2013  memcpy (&scratch[scratch_start], rname, strlen (rname) + 1);
2014  scratch_off += strlen (rname) + 1;
2015  GNUNET_assert (rd_off < rd_count);
2016  rd_new[rd_off].data = &scratch[scratch_start];
2017  rd_new[rd_off].data_size = scratch_off - scratch_start;
2018  rd_off++;
2019  GNUNET_free (rname);
2020  }
2021  break;
2022 
2024  {
2025  char *cname;
2026 
2027  off = 0;
2028  cname = GNUNET_DNSPARSER_parse_name (rd[i].data,
2029  rd[i].data_size,
2030  &off);
2031  if ((NULL == cname) ||
2032  (off != rd[i].data_size))
2033  {
2034  GNUNET_break_op (0); /* record not well-formed */
2035  }
2036  else
2037  {
2038  cname = translate_dot_plus (rh, cname);
2039  GNUNET_break (NULL != cname);
2040  scratch_start = scratch_off;
2041  if (GNUNET_OK !=
2043  sizeof(scratch),
2044  &scratch_off,
2045  cname))
2046  {
2047  GNUNET_break (0);
2048  }
2049  else
2050  {
2051  GNUNET_assert (rd_off < rd_count);
2052  rd_new[rd_off].data = &scratch[scratch_start];
2053  rd_new[rd_off].data_size = scratch_off - scratch_start;
2054  rd_off++;
2055  }
2056  }
2057  GNUNET_free (cname);
2058  }
2059  break;
2060 
2062  {
2063  struct GNUNET_DNSPARSER_SoaRecord *soa;
2064 
2065  off = 0;
2066  soa = GNUNET_DNSPARSER_parse_soa (rd[i].data,
2067  rd[i].data_size,
2068  &off);
2069  if ((NULL == soa) ||
2070  (off != rd[i].data_size))
2071  {
2072  GNUNET_break_op (0); /* record not well-formed */
2073  }
2074  else
2075  {
2076  soa->mname = translate_dot_plus (rh, soa->mname);
2077  soa->rname = translate_dot_plus (rh, soa->rname);
2078  scratch_start = scratch_off;
2079  if (GNUNET_OK !=
2081  sizeof(scratch),
2082  &scratch_off,
2083  soa))
2084  {
2085  GNUNET_break (0);
2086  }
2087  else
2088  {
2089  GNUNET_assert (rd_off < rd_count);
2090  rd_new[rd_off].data = &scratch[scratch_start];
2091  rd_new[rd_off].data_size = scratch_off - scratch_start;
2092  rd_off++;
2093  }
2094  }
2095  if (NULL != soa)
2097  }
2098  break;
2099 
2101  {
2102  struct GNUNET_DNSPARSER_MxRecord *mx;
2103 
2104  off = 0;
2105  mx = GNUNET_DNSPARSER_parse_mx (rd[i].data,
2106  rd[i].data_size,
2107  &off);
2108  if ((NULL == mx) ||
2109  (off != rd[i].data_size))
2110  {
2111  GNUNET_break_op (0); /* record not well-formed */
2112  }
2113  else
2114  {
2115  mx->mxhost = translate_dot_plus (rh, mx->mxhost);
2116  scratch_start = scratch_off;
2117  if (GNUNET_OK !=
2119  sizeof(scratch),
2120  &scratch_off,
2121  mx))
2122  {
2123  GNUNET_break (0);
2124  }
2125  else
2126  {
2127  GNUNET_assert (rd_off < rd_count);
2128  rd_new[rd_off].data = &scratch[scratch_start];
2129  rd_new[rd_off].data_size = scratch_off - scratch_start;
2130  rd_off++;
2131  }
2132  }
2133  if (NULL != mx)
2135  }
2136  break;
2137 
2139  {
2140  struct GNUNET_DNSPARSER_SrvRecord *srv;
2141 
2142  off = 0;
2143  srv = GNUNET_DNSPARSER_parse_srv (rd[i].data,
2144  rd[i].data_size,
2145  &off);
2146  if ((NULL == srv) ||
2147  (off != rd[i].data_size))
2148  {
2149  GNUNET_break_op (0); /* record not well-formed */
2150  }
2151  else
2152  {
2153  srv->target = translate_dot_plus (rh, srv->target);
2154  scratch_start = scratch_off;
2155  if (GNUNET_OK !=
2157  sizeof(scratch),
2158  &scratch_off,
2159  srv))
2160  {
2161  GNUNET_break (0);
2162  }
2163  else
2164  {
2165  GNUNET_assert (rd_off < rd_count);
2166  rd_new[rd_off].data = &scratch[scratch_start];
2167  rd_new[rd_off].data_size = scratch_off - scratch_start;
2168  rd_off++;
2169  }
2170  }
2171  if (NULL != srv)
2173  }
2174  break;
2175 
2178  {
2180  if (rd[i].data_size < sizeof(uint32_t))
2181  {
2182  GNUNET_break_op (0);
2183  break;
2184  }
2185  if (GNUNET_OK !=
2187  rd[i].data_size,
2188  rd[i].record_type,
2189  &pubkey))
2190  {
2191  GNUNET_break_op (0);
2192  break;
2193  }
2194  rd_off++;
2195  if (rd[i].record_type != rh->record_type)
2196  {
2197  /* try to resolve "@" */
2198  struct AuthorityChain *ac;
2199 
2200  ac = GNUNET_new (struct AuthorityChain);
2201  ac->rh = rh;
2202  ac->gns_authority = GNUNET_YES;
2203  ac->authority_info.gns_authority = pubkey;
2206  rh->ac_tail,
2207  ac);
2209  rh);
2210  return;
2211  }
2212  }
2213  break;
2214 
2216  {
2217  /* delegation to DNS */
2219  {
2220  rd_off++;
2221  break; /* do not follow to DNS, we wanted the GNS2DNS record! */
2222  }
2224  "Found GNS2DNS record, delegating to DNS!\n");
2225  if (GNUNET_OK ==
2227  rd_count,
2228  rd))
2229  return;
2230  else
2231  goto fail;
2232  }
2233 
2235  {
2236  /* unbox SRV/TLSA records if a specific one was requested */
2237  if ((0 != rh->protocol) &&
2238  (0 != rh->service) &&
2239  (rd[i].data_size >= sizeof(struct GNUNET_GNSRECORD_BoxRecord)))
2240  {
2241  const struct GNUNET_GNSRECORD_BoxRecord *box;
2242 
2243  box = rd[i].data;
2245  "Got BOX record, checking if parameters match... %u/%u vs %u/%u\n",
2246  ntohs (box->protocol), ntohs (box->service),
2247  rh->protocol, rh->service);
2248  if ((ntohs (box->protocol) == rh->protocol) &&
2249  (ntohs (box->service) == rh->service))
2250  {
2251  /* Box matches, unbox! */
2252  GNUNET_assert (rd_off < rd_count);
2253  rd_new[rd_off].record_type = ntohl (box->record_type);
2254  rd_new[rd_off].data_size -= sizeof(struct
2256  rd_new[rd_off].data = &box[1];
2257  rd_off++;
2258  }
2259  }
2260  else
2261  {
2262  /* no specific protocol/service specified, preserve all BOX
2263  records (for modern, GNS-enabled applications) */
2264  rd_off++;
2265  }
2266  break;
2267  }
2268 
2269  default:
2270  rd_off++;
2271  break;
2272  } /* end: switch */
2273  } /* end: for rd_count */
2274 
2275  /* yes, we are done, return result */
2277  "Returning GNS response for `%s' with %u answers\n",
2278  rh->ac_tail->label,
2279  rd_off);
2280  rh->proc (rh->proc_cls,
2281  rd_off,
2282  rd_new);
2284  rh);
2285  return;
2286  }
2287 
2288  switch (rd[0].record_type)
2289  {
2291  GNUNET_break_op (1 == rd_count); /* REDIRECT should be unique */
2293  &rd[0]);
2294  return;
2295 
2297  GNUNET_break_op (1 == rd_count); /* CNAME should be unique */
2299  &rd[0]);
2300  return;
2301 
2304  GNUNET_break_op (1 == rd_count); /* PKEY should be unique */
2306  &rd[0]);
2307  return;
2308 
2310  if (GNUNET_OK ==
2312  rd_count,
2313  rd))
2314  return;
2315  break;
2316  default:
2318  return;
2320  _ ("Unable to process critical delegation record\n"));
2321  break;
2322  }
2323 fail:
2325  _ ("GNS lookup recursion failed (no delegation record found)\n"));
2326  fail_resolution (rh);
2327 }
#define GNUNET_GNSRECORD_TYPE_BOX
Boxed records (see TLSA/SRV handling in GNS)
#define GNUNET_GNSRECORD_TYPE_GNS2DNS
Delegation to DNS.
#define GNUNET_GNSRECORD_TYPE_REDIRECT
Resolver redirects.
#define GNUNET_GNSRECORD_TYPE_PKEY
WARNING: This header is generated! In order to add GNS record types, you must register them in GANA,...
#define GNUNET_GNSRECORD_TYPE_EDKEY
Record type for EDKEY zone delegations.
static struct GNUNET_IDENTITY_PublicKey pubkey
Public key of the zone to look in.
static void recursive_pkey_resolution(struct GNS_ResolverHandle *rh, const struct GNUNET_GNSRECORD_Data *rd)
We found a PKEY record, perform recursive resolution on it.
static void recursive_cname_resolution(struct GNS_ResolverHandle *rh, const struct GNUNET_GNSRECORD_Data *rd)
We found a CNAME record, perform recursive resolution on it.
static void handle_gns_redirect_result(struct GNS_ResolverHandle *rh, const char *rname)
We encountered a REDIRECT record during our resolution.
static char * translate_dot_plus(struct GNS_ResolverHandle *rh, char *name)
Expands a name ending in .
static void recursive_redirect_resolution(struct GNS_ResolverHandle *rh, const struct GNUNET_GNSRECORD_Data *rd)
We found a REDIRECT record, perform recursive resolution on it.
static void handle_gns_cname_result(struct GNS_ResolverHandle *rh, const char *cname)
We encountered a CNAME record during our resolution.
static int recursive_gns2dns_resolution(struct GNS_ResolverHandle *rh, unsigned int rd_count, const struct GNUNET_GNSRECORD_Data *rd)
We found one or more GNS2DNS records, perform recursive resolution on it.
struct GNUNET_DNSPARSER_SoaRecord * GNUNET_DNSPARSER_parse_soa(const char *udp_payload, size_t udp_payload_length, size_t *off)
Parse a DNS SOA record.
Definition: dnsparser.c:391
void GNUNET_DNSPARSER_free_srv(struct GNUNET_DNSPARSER_SrvRecord *srv)
Free SRV information record.
Definition: dnsparser.c:139
struct GNUNET_DNSPARSER_MxRecord * GNUNET_DNSPARSER_parse_mx(const char *udp_payload, size_t udp_payload_length, size_t *off)
Parse a DNS MX record.
Definition: dnsparser.c:436
void GNUNET_DNSPARSER_free_soa(struct GNUNET_DNSPARSER_SoaRecord *soa)
Free SOA information record.
Definition: dnsparser.c:108
struct GNUNET_DNSPARSER_SrvRecord * GNUNET_DNSPARSER_parse_srv(const char *udp_payload, size_t udp_payload_length, size_t *off)
Parse a DNS SRV record.
Definition: dnsparser.c:477
void GNUNET_DNSPARSER_free_mx(struct GNUNET_DNSPARSER_MxRecord *mx)
Free MX information record.
Definition: dnsparser.c:154
char * GNUNET_DNSPARSER_parse_name(const char *udp_payload, size_t udp_payload_length, size_t *off)
Parse name inside of a DNS query or record.
Definition: dnsparser.c:334
enum GNUNET_GenericReturnValue GNUNET_GNSRECORD_identity_from_data(const char *data, size_t data_size, uint32_t type, struct GNUNET_IDENTITY_PublicKey *key)
Build a #GNUNET_GNSRECORD_PublicKey from zone delegation resource record data.
enum GNUNET_GenericReturnValue GNUNET_GNSRECORD_is_critical(uint32_t type)
Check if this type is a critical record.
Definition: gnsrecord.c:264
const char * GNUNET_GNSRECORD_z2s(const struct GNUNET_IDENTITY_PublicKey *z)
Convert a zone key to a string (for printing debug messages).
struct GNS_ResolverHandle * rh
Resolver handle this entry in the chain belongs to.
Information from MX records (RFC 1035).
char * mxhost
Name of the mail server.
Information from SOA records (RFC 1035).
char * mname
The domainname of the name server that was the original or primary source of data for this zone.
char * rname
A domainname which specifies the mailbox of the person responsible for this zone.
Information from SRV records (RFC 2782).
char * target
Hostname offering the service.
Record type used to box up SRV and TLSA records.
uint32_t record_type
GNS record type of the boxed record.
uint16_t service
Service of the boxed record (aka port number), in NBO.
uint16_t protocol
Protocol of the boxed record (6 = TCP, 17 = UDP, etc.).

References _, ac, GNS_ResolverHandle::ac_head, GNS_ResolverHandle::ac_tail, AuthorityChain::authority_info, GNUNET_GNSRECORD_Data::data, data, data_size, GNUNET_GNSRECORD_Data::data_size, fail_resolution(), AuthorityChain::gns_authority, GNS_resolver_lookup_cancel_(), GNUNET_assert, GNUNET_break, GNUNET_break_op, GNUNET_CONTAINER_DLL_insert_tail, GNUNET_DNSPARSER_builder_add_mx(), GNUNET_DNSPARSER_builder_add_name(), GNUNET_DNSPARSER_builder_add_soa(), GNUNET_DNSPARSER_builder_add_srv(), GNUNET_DNSPARSER_free_mx(), GNUNET_DNSPARSER_free_soa(), GNUNET_DNSPARSER_free_srv(), GNUNET_DNSPARSER_parse_mx(), GNUNET_DNSPARSER_parse_name(), GNUNET_DNSPARSER_parse_soa(), GNUNET_DNSPARSER_parse_srv(), GNUNET_DNSPARSER_TYPE_A, GNUNET_DNSPARSER_TYPE_AAAA, GNUNET_DNSPARSER_TYPE_CNAME, GNUNET_DNSPARSER_TYPE_MX, GNUNET_DNSPARSER_TYPE_SOA, GNUNET_DNSPARSER_TYPE_SRV, GNUNET_ERROR_TYPE_DEBUG, GNUNET_ERROR_TYPE_INFO, GNUNET_ERROR_TYPE_WARNING, GNUNET_free, GNUNET_GNS_EMPTY_LABEL_AT, GNUNET_GNSRECORD_identity_from_data(), GNUNET_GNSRECORD_is_critical(), GNUNET_GNSRECORD_TYPE_BOX, GNUNET_GNSRECORD_TYPE_EDKEY, GNUNET_GNSRECORD_TYPE_GNS2DNS, GNUNET_GNSRECORD_TYPE_PKEY, GNUNET_GNSRECORD_TYPE_REDIRECT, GNUNET_GNSRECORD_z2s(), GNUNET_log, GNUNET_new, GNUNET_OK, GNUNET_SCHEDULER_add_now(), GNUNET_strdup, GNUNET_strndup, GNUNET_YES, handle_gns_cname_result(), handle_gns_redirect_result(), AuthorityChain::label, GNUNET_DNSPARSER_SoaRecord::mname, GNUNET_DNSPARSER_MxRecord::mxhost, GNS_ResolverHandle::name, GNS_ResolverHandle::name_resolution_pos, GNS_ResolverHandle::proc, GNS_ResolverHandle::proc_cls, GNS_ResolverHandle::protocol, GNUNET_GNSRECORD_BoxRecord::protocol, pubkey, GNS_ResolverHandle::record_type, GNUNET_GNSRECORD_Data::record_type, GNUNET_GNSRECORD_BoxRecord::record_type, recursive_cname_resolution(), recursive_gns2dns_resolution(), recursive_pkey_resolution(), recursive_redirect_resolution(), recursive_resolution(), AuthorityChain::rh, GNUNET_DNSPARSER_SoaRecord::rname, GNS_ResolverHandle::service, GNUNET_GNSRECORD_BoxRecord::service, GNUNET_DNSPARSER_SrvRecord::target, GNS_ResolverHandle::task_id, and translate_dot_plus().

Referenced by handle_dht_response(), and handle_gns_namecache_resolution_result().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ continue_with_gns2dns()

static void continue_with_gns2dns ( struct AuthorityChain ac)
static

We have resolved one or more of the nameservers for a GNS2DNS lookup.

Once we have some of them, begin using the DNSSTUB resolver.

Parameters
accontext for GNS2DNS resolution

Definition at line 1401 of file gnunet-service-gns_resolver.c.

1402 {
1403  struct GNS_ResolverHandle *rh = ac->rh;
1404 
1405  if ((NULL != ac->authority_info.dns_authority.gp_head) &&
1406  (GNUNET_NO == ac->authority_info.dns_authority.found))
1407  return; /* more pending and none found yet */
1408  if (GNUNET_NO == ac->authority_info.dns_authority.found)
1409  {
1411  "Failed to resolve DNS server for `%s' in GNS2DNS resolution\n",
1412  ac->authority_info.dns_authority.name);
1413  fail_resolution (rh);
1414  return;
1415  }
1416  if (GNUNET_NO != ac->authority_info.dns_authority.launched)
1417  return; /* already running, do not launch again! */
1418  /* recurse */
1419  ac->authority_info.dns_authority.launched = GNUNET_YES;
1421  "Will continue resolution using DNS to resolve `%s'\n",
1422  ac->label);
1423  GNUNET_assert (NULL == rh->task_id);
1425  rh);
1426 }

References ac, fail_resolution(), GNUNET_assert, GNUNET_ERROR_TYPE_DEBUG, GNUNET_ERROR_TYPE_INFO, GNUNET_log, GNUNET_NO, GNUNET_SCHEDULER_add_now(), GNUNET_YES, recursive_resolution(), and GNS_ResolverHandle::task_id.

Referenced by handle_gns2dns_ip(), handle_gns2dns_result(), and recursive_gns2dns_resolution().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ handle_gns2dns_result()

static void handle_gns2dns_result ( void *  cls,
unsigned int  rd_count,
const struct GNUNET_GNSRECORD_Data rd 
)
static

We've resolved the IP address for the DNS resolver to use after encountering a GNS2DNS record.

Parameters
clsthe struct Gns2DnsPending used for this request
rd_countnumber of records in rd
rdaddresses for the DNS resolver (presumably)

Definition at line 1438 of file gnunet-service-gns_resolver.c.

1441 {
1442  struct Gns2DnsPending *gp = cls;
1443  struct AuthorityChain *ac = gp->ac;
1444 
1445  GNUNET_CONTAINER_DLL_remove (ac->authority_info.dns_authority.gp_head,
1446  ac->authority_info.dns_authority.gp_tail,
1447  gp);
1448  /* enable cleanup of 'rh' handle that automatically comes after we return,
1449  and which expects 'rh' to be in the #rlh_head DLL. */
1450  if (NULL != gp->rh)
1451  {
1453  rlh_tail,
1454  gp->rh);
1455  gp->rh = NULL;
1456  }
1457  GNUNET_free (gp);
1459  "Received %u results for IP address of DNS server for GNS2DNS transition\n",
1460  rd_count);
1461  /* find suitable A/AAAA record */
1462  for (unsigned int j = 0; j < rd_count; j++)
1463  {
1464  switch (rd[j].record_type)
1465  {
1467  {
1468  struct sockaddr_in v4;
1469 
1470  if (sizeof(struct in_addr) != rd[j].data_size)
1471  {
1472  GNUNET_break_op (0);
1473  continue;
1474  }
1475  memset (&v4,
1476  0,
1477  sizeof(v4));
1478  v4.sin_family = AF_INET;
1479  v4.sin_port = htons (53);
1480 #if HAVE_SOCKADDR_IN_SIN_LEN
1481  v4.sin_len = (u_char) sizeof(v4);
1482 #endif
1483  GNUNET_memcpy (&v4.sin_addr,
1484  rd[j].data,
1485  sizeof(struct in_addr));
1486  if (GNUNET_OK ==
1488  ac->authority_info.dns_authority.dns_handle,
1489  (const struct sockaddr *) &v4))
1490  ac->authority_info.dns_authority.found = GNUNET_YES;
1491  break;
1492  }
1493 
1495  {
1496  struct sockaddr_in6 v6;
1497 
1498  if (sizeof(struct in6_addr) != rd[j].data_size)
1499  {
1500  GNUNET_break_op (0);
1501  continue;
1502  }
1503  /* FIXME: might want to check if we support IPv6 here,
1504  and otherwise skip this one and hope we find another */
1505  memset (&v6,
1506  0,
1507  sizeof(v6));
1508  v6.sin6_family = AF_INET6;
1509  v6.sin6_port = htons (53);
1510 #if HAVE_SOCKADDR_IN_SIN_LEN
1511  v6.sin6_len = (u_char) sizeof(v6);
1512 #endif
1513  GNUNET_memcpy (&v6.sin6_addr,
1514  rd[j].data,
1515  sizeof(struct in6_addr));
1516  if (GNUNET_OK ==
1518  ac->authority_info.dns_authority.dns_handle,
1519  (const struct sockaddr *) &v6))
1520  ac->authority_info.dns_authority.found = GNUNET_YES;
1521  break;
1522  }
1523 
1524  default:
1525  break;
1526  }
1527  }
1529 }
static struct GNS_ResolverHandle * rlh_tail
Tail of resolver lookup list.
static struct GNS_ResolverHandle * rlh_head
Head of resolver lookup list.
static void continue_with_gns2dns(struct AuthorityChain *ac)
We have resolved one or more of the nameservers for a GNS2DNS lookup.
#define GNUNET_CONTAINER_DLL_remove(head, tail, element)
Remove an element from a DLL.
int GNUNET_DNSSTUB_add_dns_sa(struct GNUNET_DNSSTUB_Context *ctx, const struct sockaddr *sa)
Add nameserver for use by the DNSSTUB.
Definition: dnsstub.c:669
Element of a resolution process for looking up the responsible DNS server hostname in a GNS2DNS recur...
struct GNS_ResolverHandle * rh
Handle for the resolution of the IP part of the GNS2DNS record.
struct AuthorityChain * ac
Context this activity belongs with.

References Gns2DnsPending::ac, ac, continue_with_gns2dns(), GNUNET_GNSRECORD_Data::data, data_size, GNUNET_break_op, GNUNET_CONTAINER_DLL_insert, GNUNET_CONTAINER_DLL_remove, GNUNET_DNSPARSER_TYPE_A, GNUNET_DNSPARSER_TYPE_AAAA, GNUNET_DNSSTUB_add_dns_sa(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_free, GNUNET_log, GNUNET_memcpy, GNUNET_OK, GNUNET_YES, Gns2DnsPending::rh, rlh_head, and rlh_tail.

Referenced by recursive_gns2dns_resolution().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ handle_gns2dns_ip()

static void handle_gns2dns_ip ( void *  cls,
const struct sockaddr *  addr,
socklen_t  addrlen 
)
static

Function called by the resolver for each address obtained from DNS.

Parameters
clsclosure, a struct Gns2DnsPending *
addrone of the addresses of the host, NULL for the last address
addrlenlength of addr

Definition at line 1540 of file gnunet-service-gns_resolver.c.

1543 {
1544  struct Gns2DnsPending *gp = cls;
1545  struct AuthorityChain *ac = gp->ac;
1546  struct sockaddr_storage ss;
1547  struct sockaddr_in *v4;
1548  struct sockaddr_in6 *v6;
1549 
1550  if (NULL == addr)
1551  {
1552  /* DNS resolution finished */
1553  if (0 == gp->num_results)
1555  "Failed to use DNS to resolve name of DNS resolver\n");
1556  GNUNET_CONTAINER_DLL_remove (ac->authority_info.dns_authority.gp_head,
1557  ac->authority_info.dns_authority.gp_tail,
1558  gp);
1559  GNUNET_free (gp);
1561  return;
1562  }
1563  GNUNET_memcpy (&ss,
1564  addr,
1565  addrlen);
1566  switch (ss.ss_family)
1567  {
1568  case AF_INET:
1569  v4 = (struct sockaddr_in *) &ss;
1570  v4->sin_port = htons (53);
1571  gp->num_results++;
1572  break;
1573 
1574  case AF_INET6:
1575  v6 = (struct sockaddr_in6 *) &ss;
1576  v6->sin6_port = htons (53);
1577  gp->num_results++;
1578  break;
1579 
1580  default:
1582  "Unsupported AF %d\n",
1583  ss.ss_family);
1584  return;
1585  }
1586  if (GNUNET_OK ==
1587  GNUNET_DNSSTUB_add_dns_sa (ac->authority_info.dns_authority.dns_handle,
1588  (struct sockaddr *) &ss))
1589  ac->authority_info.dns_authority.found = GNUNET_YES;
1590 }
@ GNUNET_ERROR_TYPE_ERROR
unsigned int num_results
How many results did we get?

References Gns2DnsPending::ac, ac, continue_with_gns2dns(), GNUNET_CONTAINER_DLL_remove, GNUNET_DNSSTUB_add_dns_sa(), GNUNET_ERROR_TYPE_ERROR, GNUNET_ERROR_TYPE_WARNING, GNUNET_free, GNUNET_log, GNUNET_memcpy, GNUNET_OK, GNUNET_YES, and Gns2DnsPending::num_results.

Referenced by recursive_gns2dns_resolution().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ recursive_redirect_resolution()

static void recursive_redirect_resolution ( struct GNS_ResolverHandle rh,
const struct GNUNET_GNSRECORD_Data rd 
)
static

We found a REDIRECT record, perform recursive resolution on it.

Parameters
rhresolution handle
rdrecord with CNAME to resolve recursively

Definition at line 1600 of file gnunet-service-gns_resolver.c.

1602 {
1604  rd->data);
1605 }

References GNUNET_GNSRECORD_Data::data, and handle_gns_redirect_result().

Referenced by handle_gns_resolution_result().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ recursive_cname_resolution()

static void recursive_cname_resolution ( struct GNS_ResolverHandle rh,
const struct GNUNET_GNSRECORD_Data rd 
)
static

We found a CNAME record, perform recursive resolution on it.

Parameters
rhresolution handle
rdrecord with CNAME to resolve recursively

Definition at line 1615 of file gnunet-service-gns_resolver.c.

1617 {
1618  char *cname;
1619  size_t off;
1620 
1621  off = 0;
1622  cname = GNUNET_DNSPARSER_parse_name (rd->data,
1623  rd->data_size,
1624  &off);
1625  if ((NULL == cname) ||
1626  (off != rd->data_size))
1627  {
1628  GNUNET_break_op (0); /* record not well-formed */
1629  GNUNET_free (cname);
1630  fail_resolution (rh);
1631  return;
1632  }
1634  cname);
1635  GNUNET_free (cname);
1636 }
size_t data_size
Number of bytes in data.

References GNUNET_GNSRECORD_Data::data, GNUNET_GNSRECORD_Data::data_size, fail_resolution(), GNUNET_break_op, GNUNET_DNSPARSER_parse_name(), GNUNET_free, and handle_gns_cname_result().

Referenced by handle_gns_resolution_result().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ recursive_pkey_resolution()

static void recursive_pkey_resolution ( struct GNS_ResolverHandle rh,
const struct GNUNET_GNSRECORD_Data rd 
)
static

We found a PKEY record, perform recursive resolution on it.

Parameters
rhresolution handle
rdrecord with PKEY to resolve recursively

Definition at line 1646 of file gnunet-service-gns_resolver.c.

1648 {
1649  struct AuthorityChain *ac;
1650  struct GNUNET_IDENTITY_PublicKey auth;
1651 
1652  /* delegation to another zone */
1654  rd->data_size,
1655  rd->record_type,
1656  &auth))
1657  {
1658  GNUNET_break_op (0);
1659  fail_resolution (rh);
1660  return;
1661  }
1662  /* expand authority chain */
1663  ac = GNUNET_new (struct AuthorityChain);
1664  ac->rh = rh;
1665  ac->gns_authority = GNUNET_YES;
1666  ac->authority_info.gns_authority = auth;
1667  ac->label = resolver_lookup_get_next_label (rh);
1668  /* add AC to tail */
1670  rh->ac_tail,
1671  ac);
1672  /* recurse */
1674  rh);
1675 }

References ac, GNS_ResolverHandle::ac_head, GNS_ResolverHandle::ac_tail, GNUNET_GNSRECORD_Data::data, GNUNET_GNSRECORD_Data::data_size, fail_resolution(), GNUNET_break_op, GNUNET_CONTAINER_DLL_insert_tail, GNUNET_GNSRECORD_identity_from_data(), GNUNET_new, GNUNET_OK, GNUNET_SCHEDULER_add_now(), GNUNET_YES, GNUNET_GNSRECORD_Data::record_type, recursive_resolution(), resolver_lookup_get_next_label(), and GNS_ResolverHandle::task_id.

Referenced by handle_gns_resolution_result().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ recursive_gns2dns_resolution()

static int recursive_gns2dns_resolution ( struct GNS_ResolverHandle rh,
unsigned int  rd_count,
const struct GNUNET_GNSRECORD_Data rd 
)
static

We found one or more GNS2DNS records, perform recursive resolution on it.

(to be precise, one or more records in rd is GNS2DNS, there may be others, so this function still needs to check which ones are GNS2DNS).

Parameters
rhresolution handle
rd_countlength of the rd array
rdrecord with PKEY to resolve recursively
Returns
GNUNET_OK if this worked, GNUNET_SYSERR if no GNS2DNS records were in rd

Records other than GNS2DNS not allowed

Definition at line 1689 of file gnunet-service-gns_resolver.c.

1692 {
1693  struct AuthorityChain *ac;
1694  const char *tld;
1695  char *ns;
1696 
1697  ns = NULL;
1698  /* expand authority chain */
1699  ac = GNUNET_new (struct AuthorityChain);
1700  ac->rh = rh;
1701  ac->authority_info.dns_authority.dns_handle = GNUNET_DNSSTUB_start (4);
1702 
1703  for (unsigned int i = 0; i < rd_count; i++)
1704  {
1705  char *ip;
1706  char *n;
1707  size_t off;
1708  struct Gns2DnsPending *gp;
1710  struct sockaddr_in v4;
1711  struct sockaddr_in6 v6;
1712 
1713  if (GNUNET_GNSRECORD_TYPE_GNS2DNS != rd[i].record_type)
1714  {
1718  GNUNET_free (ns);
1719  GNUNET_free (ac);
1720  return GNUNET_SYSERR;
1721  }
1722  off = 0;
1723  n = GNUNET_DNSPARSER_parse_name (rd[i].data,
1724  rd[i].data_size,
1725  &off);
1726  ip = GNUNET_strdup (&((const char *) rd[i].data)[off]);
1727  if ((NULL == n) ||
1728  (NULL == ip))
1729  {
1730  GNUNET_break_op (0);
1731  GNUNET_free (n);
1732  GNUNET_free (ip);
1733  continue;
1734  }
1735 
1736  off += strlen (ip) + 1;
1737 
1738  if (off != rd[i].data_size)
1739  {
1740  GNUNET_break_op (0);
1741  GNUNET_free (n);
1742  GNUNET_free (ip);
1743  continue;
1744  }
1745  /* resolve 'ip' to determine the IP(s) of the DNS
1746  resolver to use for lookup of 'ns' */
1747  if (NULL != ns)
1748  {
1749  if (0 != strcasecmp (ns,
1750  n))
1751  {
1752  /* NS values must all be the same for all GNS2DNS records,
1753  anything else leads to insanity */
1754  GNUNET_break_op (0);
1755  GNUNET_free (n);
1756  GNUNET_free (ip);
1757  continue;
1758  }
1759  GNUNET_free (n);
1760  }
1761  else
1762  {
1763  ns = n;
1764  }
1765 
1766  /* check if 'ip' is already an IPv4/IPv6 address */
1767  if ((1 == inet_pton (AF_INET,
1768  ip,
1769  &v4)) ||
1770  (1 == inet_pton (AF_INET6,
1771  ip,
1772  &v6)))
1773  {
1776  ac->authority_info.dns_authority.dns_handle,
1777  ip));
1778  ac->authority_info.dns_authority.found = GNUNET_YES;
1779  GNUNET_free (ip);
1780  continue;
1781  }
1782  tld = GNS_get_tld (ip);
1783  if ((0 != strcmp (tld, "+")) &&
1785  {
1786  /* 'ip' is a DNS name */
1787  gp = GNUNET_new (struct Gns2DnsPending);
1788  gp->ac = ac;
1789  GNUNET_CONTAINER_DLL_insert (ac->authority_info.dns_authority.gp_head,
1790  ac->authority_info.dns_authority.gp_tail,
1791  gp);
1792  gp->dns_rh = GNUNET_RESOLVER_ip_get (ip,
1793  AF_UNSPEC,
1796  gp);
1797  GNUNET_free (ip);
1798  continue;
1799  }
1800  /* 'ip' should be a GNS name */
1801  gp = GNUNET_new (struct Gns2DnsPending);
1802  gp->ac = ac;
1803  GNUNET_CONTAINER_DLL_insert (ac->authority_info.dns_authority.gp_head,
1804  ac->authority_info.dns_authority.gp_tail,
1805  gp);
1806  gp->rh = GNUNET_new (struct GNS_ResolverHandle);
1807  if (0 == strcmp (tld, "+"))
1808  {
1809  ip = translate_dot_plus (rh,
1810  ip);
1811  tld = GNS_get_tld (ip);
1812  if (GNUNET_OK !=
1814  &zone))
1815  {
1816  GNUNET_break_op (0);
1817  GNUNET_free (ip);
1818  continue;
1819  }
1820  }
1821  gp->rh->authority_zone = zone;
1823  "Resolving `%s' to determine IP address of DNS server for GNS2DNS transition for `%s'\n",
1824  ip,
1825  ns);
1826  gp->rh->name = ip;
1827  gp->rh->name_resolution_pos = strlen (ip) - strlen (tld) - 1;
1828  gp->rh->proc = &handle_gns2dns_result;
1829  gp->rh->proc_cls = gp;
1832  gp->rh->loop_limiter = rh->loop_limiter + 1;
1833  gp->rh->loop_threshold = rh->loop_threshold;
1834  gp->rh->task_id
1836  gp->rh);
1837  } /* end 'for all records' */
1838 
1839  if (NULL == ns)
1840  {
1841  /* not a single GNS2DNS record found */
1842  GNUNET_free (ac);
1843  return GNUNET_SYSERR;
1844  }
1846  strcpy (ac->authority_info.dns_authority.name,
1847  ns);
1848  /* for DNS recursion, the label is the full DNS name,
1849  created from the remainder of the GNS name and the
1850  name in the NS record */
1851  GNUNET_asprintf (&ac->label,
1852  "%.*s%s%s",
1853  (int) rh->name_resolution_pos,
1854  rh->name,
1855  (0 != rh->name_resolution_pos) ? "." : "",
1856  ns);
1857  GNUNET_free (ns);
1858 
1859  {
1860  /* the GNS name is UTF-8 and may include multibyte chars.
1861  * We have to convert the combined name to a DNS-compatible IDNA.
1862  */
1863  char *tmp = ac->label;
1864 
1865  if (IDNA_SUCCESS != idna_to_ascii_8z (tmp,
1866  &ac->label,
1867  IDNA_ALLOW_UNASSIGNED))
1868  {
1870  _ ("Name `%s' cannot be converted to IDNA."),
1871  tmp);
1872  GNUNET_free (tmp);
1873  GNUNET_free (ac);
1874  return GNUNET_SYSERR;
1875  }
1876  GNUNET_free (tmp);
1877  }
1878 
1880  rh->ac_tail,
1881  ac);
1882  if (strlen (ac->label) > GNUNET_DNSPARSER_MAX_NAME_LENGTH)
1883  {
1885  _ ("GNS lookup resulted in DNS name that is too long (`%s')\n"),
1886  ac->label);
1887  GNUNET_free (ac->label);
1888  GNUNET_free (ac);
1889  return GNUNET_SYSERR;
1890  }
1892  return GNUNET_OK;
1893 }
static struct GNUNET_NAMESTORE_Handle * ns
Handle to the namestore.
Definition: gnunet-abd.c:41
static void handle_gns2dns_ip(void *cls, const struct sockaddr *addr, socklen_t addrlen)
Function called by the resolver for each address obtained from DNS.
static void start_resolver_lookup(void *cls)
Begin the resolution process from 'name', starting with the identification of the zone specified by '...
static void handle_gns2dns_result(void *cls, unsigned int rd_count, const struct GNUNET_GNSRECORD_Data *rd)
We've resolved the IP address for the DNS resolver to use after encountering a GNS2DNS record.
#define GNUNET_DNSPARSER_MAX_NAME_LENGTH
Maximum length of a name in DNS.
int GNUNET_DNSSTUB_add_dns_ip(struct GNUNET_DNSSTUB_Context *ctx, const char *dns_ip)
Add nameserver for use by the DNSSTUB.
Definition: dnsstub.c:617
struct GNUNET_DNSSTUB_Context * GNUNET_DNSSTUB_start(unsigned int num_sockets)
Start a DNS stub resolver.
Definition: dnsstub.c:590
@ GNUNET_GNS_LO_DEFAULT
Defaults, look in cache, then in DHT.
#define GNUNET_GNSRECORD_TYPE_ANY
Record type indicating any record/'*'.
#define GNUNET_TIME_UNIT_FOREVER_REL
Constant used to specify "forever".
enum GNUNET_GNS_LocalOptions options
Use only cache.
struct GNUNET_RESOLVER_RequestHandle * dns_rh
Handle for DNS resolution of the DNS nameserver.

References _, Gns2DnsPending::ac, ac, GNS_ResolverHandle::ac_head, GNS_ResolverHandle::ac_tail, GNS_ResolverHandle::authority_zone, continue_with_gns2dns(), data, data_size, Gns2DnsPending::dns_rh, GNS_get_tld(), GNUNET_asprintf(), GNUNET_assert, GNUNET_break, GNUNET_break_op, GNUNET_CONTAINER_DLL_insert, GNUNET_CONTAINER_DLL_insert_tail, GNUNET_DNSPARSER_MAX_NAME_LENGTH, GNUNET_DNSPARSER_parse_name(), GNUNET_DNSSTUB_add_dns_ip(), GNUNET_DNSSTUB_start(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_ERROR_TYPE_WARNING, GNUNET_free, GNUNET_GNS_LO_DEFAULT, GNUNET_GNSRECORD_TYPE_ANY, GNUNET_GNSRECORD_TYPE_GNS2DNS, GNUNET_GNSRECORD_zkey_to_pkey(), GNUNET_log, GNUNET_new, GNUNET_OK, GNUNET_RESOLVER_ip_get(), GNUNET_SCHEDULER_add_now(), GNUNET_strdup, GNUNET_SYSERR, GNUNET_TIME_UNIT_FOREVER_REL, GNUNET_YES, handle_gns2dns_ip(), handle_gns2dns_result(), GNS_ResolverHandle::loop_limiter, GNS_ResolverHandle::loop_threshold, GNS_ResolverHandle::name, GNS_ResolverHandle::name_resolution_pos, ns, GNS_ResolverHandle::options, GNS_ResolverHandle::proc, GNS_ResolverHandle::proc_cls, GNS_ResolverHandle::record_type, Gns2DnsPending::rh, AuthorityChain::rh, start_resolver_lookup(), GNS_ResolverHandle::task_id, translate_dot_plus(), and zone.

Referenced by handle_gns_resolution_result().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ namecache_cache_continuation()

static void namecache_cache_continuation ( void *  cls,
int32_t  success,
const char *  emsg 
)
static

Function called once the namestore has completed the request for caching a block.

Parameters
clsclosure with the struct CacheOps
successGNUNET_OK on success
emsgerror message

Definition at line 2339 of file gnunet-service-gns_resolver.c.

2342 {
2343  struct CacheOps *co = cls;
2344 
2345  co->namecache_qe_cache = NULL;
2346  if (GNUNET_OK != success)
2348  _ ("Failed to cache GNS resolution: %s\n"),
2349  emsg);
2351  co_tail,
2352  co);
2353  GNUNET_free (co);
2354 }
static struct CacheOps * co_head
Organized in a DLL.
static struct CacheOps * co_tail
Organized in a DLL.
Active namestore caching operations.
struct GNUNET_NAMECACHE_QueueEntry * namecache_qe_cache
Pending Namestore caching task.

References _, co_head, co_tail, GNUNET_CONTAINER_DLL_remove, GNUNET_ERROR_TYPE_WARNING, GNUNET_free, GNUNET_log, GNUNET_OK, and CacheOps::namecache_qe_cache.

Referenced by handle_dht_response().

Here is the caller graph for this function:

◆ handle_dht_response()

static void handle_dht_response ( void *  cls,
struct GNUNET_TIME_Absolute  exp,
const struct GNUNET_HashCode key,
const struct GNUNET_PeerIdentity trunc_peer,
const struct GNUNET_DHT_PathElement get_path,
unsigned int  get_path_length,
const struct GNUNET_DHT_PathElement put_path,
unsigned int  put_path_length,
enum GNUNET_BLOCK_Type  type,
size_t  size,
const void *  data 
)
static

Iterator called on each result obtained for a DHT operation that expects a reply.

Parameters
clsclosure with the struct GNS_ResolverHandle
expwhen will this value expire
keykey of the result
trunc_peertruncated peer, NULL if not truncated
get_pathpeers on reply path (or NULL if not recorded) [0] = datastore's first neighbor, [length - 1] = local peer
get_path_lengthnumber of entries in get_path
put_pathpeers on the PUT path (or NULL if not recorded) [0] = origin, [length - 1] = datastore
put_path_lengthnumber of entries in put_path
typetype of the result
sizenumber of bytes in data
datapointer to the result data

Definition at line 2376 of file gnunet-service-gns_resolver.c.

2387 {
2388  struct GNS_ResolverHandle *rh = cls;
2389  struct AuthorityChain *ac = rh->ac_tail;
2390  const struct GNUNET_GNSRECORD_Block *block;
2391  struct CacheOps *co;
2392 
2393  (void) exp;
2394  (void) key;
2395  (void) get_path;
2396  (void) get_path_length;
2397  (void) put_path;
2398  (void) put_path_length;
2399  (void) type;
2401  rh->get_handle = NULL;
2403  rh->dht_heap_node = NULL;
2405  "Handling response from the DHT\n");
2406  if (size < sizeof(struct GNUNET_GNSRECORD_Block))
2407  {
2408  /* how did this pass DHT block validation!? */
2409  GNUNET_break (0);
2410  fail_resolution (rh);
2411  return;
2412  }
2413  block = data;
2414  if (size != GNUNET_GNSRECORD_block_get_size (block))
2415  {
2416  /* how did this pass DHT block validation!? */
2417  GNUNET_break (0);
2418  fail_resolution (rh);
2419  return;
2420  }
2422  "Decrypting DHT block of size %lu for `%s', expires %s\n",
2424  rh->name,
2426  if (GNUNET_OK !=
2428  &ac->authority_info.gns_authority,
2429  ac->label,
2431  rh))
2432  {
2433  GNUNET_break_op (0); /* block was ill-formed */
2434  fail_resolution (rh);
2435  return;
2436  }
2439  rel_value_us)
2440  {
2442  "Received expired block from the DHT, will not cache it.\n");
2443  return;
2444  }
2445  if (GNUNET_YES == disable_cache)
2446  return;
2447  /* Cache well-formed blocks */
2449  "Caching response from the DHT in namecache\n");
2450  co = GNUNET_new (struct CacheOps);
2452  block,
2453  &
2455  co);
2457  co_tail,
2458  co);
2459 }
struct GNUNET_HashCode key
The key used in the DHT.
static int disable_cache
Use namecache.
static void namecache_cache_continuation(void *cls, int32_t success, const char *emsg)
Function called once the namestore has completed the request for caching a block.
static void handle_gns_resolution_result(void *cls, unsigned int rd_count, const struct GNUNET_GNSRECORD_Data *rd)
Process records that were decrypted from a block.
static struct GNUNET_NAMECACHE_Handle * namecache_handle
Our handle to the namecache service.
void GNUNET_DHT_get_stop(struct GNUNET_DHT_GetHandle *get_handle)
Stop async DHT-get.
Definition: dht_api.c:1237
enum GNUNET_GenericReturnValue GNUNET_GNSRECORD_block_decrypt(const struct GNUNET_GNSRECORD_Block *block, const struct GNUNET_IDENTITY_PublicKey *zone_key, const char *label, GNUNET_GNSRECORD_RecordCallback proc, void *proc_cls)
Decrypt block.
size_t GNUNET_GNSRECORD_block_get_size(const struct GNUNET_GNSRECORD_Block *block)
Returns the length of this block in bytes.
struct GNUNET_TIME_Absolute GNUNET_GNSRECORD_block_get_expiration(const struct GNUNET_GNSRECORD_Block *block)
Returns the expiration of a block.
void * GNUNET_CONTAINER_heap_remove_node(struct GNUNET_CONTAINER_HeapNode *node)
Removes a node from the heap.
struct GNUNET_NAMECACHE_QueueEntry * GNUNET_NAMECACHE_block_cache(struct GNUNET_NAMECACHE_Handle *h, const struct GNUNET_GNSRECORD_Block *block, GNUNET_NAMECACHE_ContinuationWithStatus cont, void *cont_cls)
Store an item in the namecache.
struct GNUNET_TIME_Relative GNUNET_TIME_absolute_get_remaining(struct GNUNET_TIME_Absolute future)
Given a timestamp in the future, how much time remains until then?
Definition: time.c:404
const char * GNUNET_STRINGS_absolute_time_to_string(struct GNUNET_TIME_Absolute t)
Like asctime, except for GNUnet time.
Definition: strings.c:617
static unsigned int size
Size of the "table".
Definition: peer.c:67
struct GNUNET_CONTAINER_HeapNode * dht_heap_node
Heap node associated with this lookup.
struct GNUNET_DHT_GetHandle * get_handle
Handle for DHT lookups.
enum GNUNET_TESTBED_UnderlayLinkModelType type
the type of this model

References ac, GNS_ResolverHandle::ac_tail, co_head, co_tail, data, GNS_ResolverHandle::dht_heap_node, disable_cache, fail_resolution(), GNS_ResolverHandle::get_handle, GNUNET_break, GNUNET_break_op, GNUNET_CONTAINER_DLL_insert, GNUNET_CONTAINER_heap_remove_node(), GNUNET_DHT_get_stop(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_GNSRECORD_block_decrypt(), GNUNET_GNSRECORD_block_get_expiration(), GNUNET_GNSRECORD_block_get_size(), GNUNET_log, GNUNET_NAMECACHE_block_cache(), GNUNET_new, GNUNET_OK, GNUNET_STRINGS_absolute_time_to_string(), GNUNET_TIME_absolute_get_remaining(), GNUNET_YES, handle_gns_resolution_result(), key, GNS_ResolverHandle::name, namecache_cache_continuation(), namecache_handle, CacheOps::namecache_qe_cache, AuthorityChain::rh, size, and type.

Referenced by start_dht_request().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ start_dht_request()

static void start_dht_request ( struct GNS_ResolverHandle rh,
const struct GNUNET_HashCode query 
)
static

Initiate a DHT query for a set of GNS records.

Parameters
rhresolution handle
querykey to use in the DHT lookup

Definition at line 2469 of file gnunet-service-gns_resolver.c.

2471 {
2472  struct GNS_ResolverHandle *rx;
2473 
2474  GNUNET_assert (NULL == rh->get_handle);
2477  query,
2480  NULL, 0,
2481  &handle_dht_response, rh);
2483  rh,
2485  abs_value_us);
2488  {
2489  /* fail longest-standing DHT request */
2491  rx->dht_heap_node = NULL;
2492  GNUNET_assert (NULL != rx);
2493  fail_resolution (rx);
2494  }
2495 }
@ GNUNET_BLOCK_TYPE_GNS_NAMERECORD
Block for storing GNS record data.
static unsigned long long max_allowed_background_queries
Maximum amount of parallel queries to the DHT.
static struct GNUNET_DHT_Handle * dht_handle
Resolver handle to the dht.
static void handle_dht_response(void *cls, struct GNUNET_TIME_Absolute exp, const struct GNUNET_HashCode *key, const struct GNUNET_PeerIdentity *trunc_peer, const struct GNUNET_DHT_PathElement *get_path, unsigned int get_path_length, const struct GNUNET_DHT_PathElement *put_path, unsigned int put_path_length, enum GNUNET_BLOCK_Type type, size_t size, const void *data)
Iterator called on each result obtained for a DHT operation that expects a reply.
#define DHT_GNS_REPLICATION_LEVEL
DHT replication level.
static struct GNUNET_CONTAINER_Heap * dht_lookup_heap
Heap for limiting parallel DHT lookups.
struct GNUNET_DHT_GetHandle * GNUNET_DHT_get_start(struct GNUNET_DHT_Handle *handle, enum GNUNET_BLOCK_Type type, const struct GNUNET_HashCode *key, uint32_t desired_replication_level, enum GNUNET_DHT_RouteOption options, const void *xquery, size_t xquery_size, GNUNET_DHT_GetIterator iter, void *iter_cls)
Perform an asynchronous GET operation on the DHT identified.
Definition: dht_api.c:1164
@ GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE
Each peer along the way should process the request (otherwise only peers locally closest to the key w...
void * GNUNET_CONTAINER_heap_remove_root(struct GNUNET_CONTAINER_Heap *heap)
Remove root of the heap.
struct GNUNET_CONTAINER_HeapNode * GNUNET_CONTAINER_heap_insert(struct GNUNET_CONTAINER_Heap *heap, void *element, GNUNET_CONTAINER_HeapCostType cost)
Inserts a new element into the heap.
unsigned int GNUNET_CONTAINER_heap_get_size(const struct GNUNET_CONTAINER_Heap *heap)
Get the current size of the heap.
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_get(void)
Get the current time.
Definition: time.c:110

References DHT_GNS_REPLICATION_LEVEL, dht_handle, GNS_ResolverHandle::dht_heap_node, dht_lookup_heap, fail_resolution(), GNS_ResolverHandle::get_handle, GNUNET_assert, GNUNET_BLOCK_TYPE_GNS_NAMERECORD, GNUNET_CONTAINER_heap_get_size(), GNUNET_CONTAINER_heap_insert(), GNUNET_CONTAINER_heap_remove_root(), GNUNET_DHT_get_start(), GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE, GNUNET_TIME_absolute_get(), handle_dht_response(), and max_allowed_background_queries.

Referenced by handle_namecache_block_response(), and recursive_gns_resolution_namecache().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ handle_gns_namecache_resolution_result()

static void handle_gns_namecache_resolution_result ( void *  cls,
unsigned int  rd_count,
const struct GNUNET_GNSRECORD_Data rd 
)
static

Process a records that were decrypted from a block that we got from the namecache.

Simply calls handle_gns_resolution_result().

Parameters
clsclosure with the struct GNS_ResolverHandle
rd_countnumber of entries in rd array
rdarray of records with data to store

Definition at line 2507 of file gnunet-service-gns_resolver.c.

2510 {
2511  struct GNS_ResolverHandle *rh = cls;
2512 
2513  if (0 == rd_count)
2515  _ ("GNS namecache returned empty result for `%s'\n"),
2516  rh->name);
2518  rd_count,
2519  rd);
2520 }

References _, GNUNET_ERROR_TYPE_WARNING, GNUNET_log, handle_gns_resolution_result(), and GNS_ResolverHandle::name.

Referenced by handle_namecache_block_response().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ handle_namecache_block_response()

static void handle_namecache_block_response ( void *  cls,
const struct GNUNET_GNSRECORD_Block block 
)
static

Process a record that was stored in the namecache.

Parameters
clsclosure with the struct GNS_ResolverHandle
blockblock that was stored in the namecache

Definition at line 2530 of file gnunet-service-gns_resolver.c.

2532 {
2533  struct GNS_ResolverHandle *rh = cls;
2534  struct AuthorityChain *ac = rh->ac_tail;
2535  const char *label = ac->label;
2536  const struct GNUNET_IDENTITY_PublicKey *auth =
2537  &ac->authority_info.gns_authority;
2538  struct GNUNET_HashCode query;
2539 
2540  GNUNET_assert (NULL != rh->namecache_qe);
2541  rh->namecache_qe = NULL;
2542  if (NULL == block)
2544  "No block found\n");
2545  else
2547  "Got block with expiration %s\n",
2550  if (((GNUNET_GNS_LO_DEFAULT == rh->options) ||
2551  ((GNUNET_GNS_LO_LOCAL_MASTER == rh->options) &&
2552  (ac != rh->ac_head))) &&
2553  ((NULL == block) ||
2556  rel_value_us)))
2557  {
2558  /* namecache knows nothing; try DHT lookup */
2560  label,
2561  &query);
2563  "Starting DHT lookup for `%s' in zone `%s' under key `%s'\n",
2564  ac->label,
2565  GNUNET_GNSRECORD_z2s (&ac->authority_info.gns_authority),
2566  GNUNET_h2s (&query));
2567  start_dht_request (rh, &query);
2568  return;
2569  }
2570 
2571  if ((NULL == block) ||
2574  rel_value_us))
2575  {
2576  /* DHT not permitted and no local result, fail */
2578  "Resolution failed for `%s' in zone %s (DHT lookup not permitted by configuration)\n",
2579  ac->label,
2580  GNUNET_GNSRECORD_z2s (&ac->authority_info.gns_authority));
2581  fail_resolution (rh);
2582  return;
2583  }
2585  "Received result from namecache for label `%s'\n",
2586  ac->label);
2587 
2588  if (GNUNET_OK !=
2590  auth,
2591  label,
2593  rh))
2594  {
2595  GNUNET_break_op (0); /* block was ill-formed */
2596  /* try DHT instead */
2598  label,
2599  &query);
2601  "Starting DHT lookup for `%s' in zone `%s' under key `%s'\n",
2602  ac->label,
2603  GNUNET_GNSRECORD_z2s (&ac->authority_info.gns_authority),
2604  GNUNET_h2s (&query));
2605  start_dht_request (rh, &query);
2606  return;
2607  }
2608 }
static void start_dht_request(struct GNS_ResolverHandle *rh, const struct GNUNET_HashCode *query)
Initiate a DHT query for a set of GNS records.
static void handle_gns_namecache_resolution_result(void *cls, unsigned int rd_count, const struct GNUNET_GNSRECORD_Data *rd)
Process a records that were decrypted from a block that we got from the namecache.
@ GNUNET_GNS_LO_LOCAL_MASTER
For the rightmost label, only look in the cache (it is our local namestore), for the others,...
void GNUNET_GNSRECORD_query_from_public_key(const struct GNUNET_IDENTITY_PublicKey *pub, const char *label, struct GNUNET_HashCode *query)
Calculate the DHT query for a given label in a given zone.
const char * GNUNET_h2s(const struct GNUNET_HashCode *hc)
Convert a hash value to a string (for printing debug messages).
struct GNUNET_NAMECACHE_QueueEntry * namecache_qe
Pending Namecache lookup task.
A 512-bit hashcode.

References ac, GNS_ResolverHandle::ac_head, GNS_ResolverHandle::ac_tail, fail_resolution(), GNUNET_assert, GNUNET_break_op, GNUNET_ERROR_TYPE_DEBUG, GNUNET_GNS_LO_DEFAULT, GNUNET_GNS_LO_LOCAL_MASTER, GNUNET_GNSRECORD_block_decrypt(), GNUNET_GNSRECORD_block_get_expiration(), GNUNET_GNSRECORD_query_from_public_key(), GNUNET_GNSRECORD_z2s(), GNUNET_h2s(), GNUNET_log, GNUNET_OK, GNUNET_STRINGS_absolute_time_to_string(), GNUNET_TIME_absolute_get_remaining(), handle_gns_namecache_resolution_result(), AuthorityChain::label, GNS_ResolverHandle::namecache_qe, GNS_ResolverHandle::options, AuthorityChain::rh, and start_dht_request().

Referenced by recursive_gns_resolution_namecache().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ recursive_gns_resolution_namecache()

static void recursive_gns_resolution_namecache ( struct GNS_ResolverHandle rh)
static

Lookup tail of our authority chain in the namecache.

Parameters
rhquery we are processing

Definition at line 2617 of file gnunet-service-gns_resolver.c.

2618 {
2619  struct AuthorityChain *ac = rh->ac_tail;
2620  struct GNUNET_HashCode query;
2621 
2623  "Starting GNS resolution for `%s' in zone %s\n",
2624  ac->label,
2625  GNUNET_GNSRECORD_z2s (&ac->authority_info.gns_authority));
2626  GNUNET_GNSRECORD_query_from_public_key (&ac->authority_info.gns_authority,
2627  ac->label,
2628  &query);
2629  if (GNUNET_YES != disable_cache)
2630  {
2631  rh->namecache_qe
2633  &query,
2635  rh);
2636  GNUNET_assert (NULL != rh->namecache_qe);
2637  }
2638  else
2639  {
2640  start_dht_request (rh,
2641  &query);
2642  }
2643 }
static void handle_namecache_block_response(void *cls, const struct GNUNET_GNSRECORD_Block *block)
Process a record that was stored in the namecache.
struct GNUNET_NAMECACHE_QueueEntry * GNUNET_NAMECACHE_lookup_block(struct GNUNET_NAMECACHE_Handle *h, const struct GNUNET_HashCode *derived_hash, GNUNET_NAMECACHE_BlockProcessor proc, void *proc_cls)
Get a result for a particular key from the namecache.

References ac, GNS_ResolverHandle::ac_tail, disable_cache, GNUNET_assert, GNUNET_ERROR_TYPE_DEBUG, GNUNET_GNSRECORD_query_from_public_key(), GNUNET_GNSRECORD_z2s(), GNUNET_log, GNUNET_NAMECACHE_lookup_block(), GNUNET_YES, handle_namecache_block_response(), namecache_handle, GNS_ResolverHandle::namecache_qe, AuthorityChain::rh, and start_dht_request().

Referenced by handle_revocation_result().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ handle_revocation_result()

static void handle_revocation_result ( void *  cls,
int  is_valid 
)
static

Function called with the result from a revocation check.

Parameters
clsthe struct GNS_ResovlerHandle
is_validGNUNET_YES if the zone was not yet revoked

Definition at line 2653 of file gnunet-service-gns_resolver.c.

2655 {
2656  struct GNS_ResolverHandle *rh = cls;
2657  struct AuthorityChain *ac = rh->ac_tail;
2658 
2659  rh->rev_check = NULL;
2660  if (GNUNET_YES != is_valid)
2661  {
2663  _ ("Zone %s was revoked, resolution fails\n"),
2664  GNUNET_GNSRECORD_z2s (&ac->authority_info.gns_authority));
2665  fail_resolution (rh);
2666  return;
2667  }
2669 }
static void recursive_gns_resolution_namecache(struct GNS_ResolverHandle *rh)
Lookup tail of our authority chain in the namecache.
struct GNUNET_REVOCATION_Query * rev_check
Pending revocation check.

References _, ac, GNS_ResolverHandle::ac_tail, fail_resolution(), GNUNET_ERROR_TYPE_WARNING, GNUNET_GNSRECORD_z2s(), GNUNET_log, GNUNET_YES, recursive_gns_resolution_namecache(), GNS_ResolverHandle::rev_check, and AuthorityChain::rh.

Referenced by recursive_gns_resolution_revocation().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ recursive_gns_resolution_revocation()

static void recursive_gns_resolution_revocation ( struct GNS_ResolverHandle rh)
static

Perform revocation check on tail of our authority chain.

Parameters
rhquery we are processing

Definition at line 2678 of file gnunet-service-gns_resolver.c.

2679 {
2680  struct AuthorityChain *ac = rh->ac_tail;
2681 
2683  "Starting revocation check for zone %s\n",
2684  GNUNET_GNSRECORD_z2s (&ac->authority_info.gns_authority));
2686  &ac->authority_info.gns_authority,
2688  rh);
2689  GNUNET_assert (NULL != rh->rev_check);
2690 }
static void handle_revocation_result(void *cls, int is_valid)
Function called with the result from a revocation check.
static const struct GNUNET_CONFIGURATION_Handle * cfg
Global configuration.
struct GNUNET_REVOCATION_Query * GNUNET_REVOCATION_query(const struct GNUNET_CONFIGURATION_Handle *cfg, const struct GNUNET_IDENTITY_PublicKey *key, GNUNET_REVOCATION_Callback func, void *func_cls)
Check if a key was revoked.

References ac, GNS_ResolverHandle::ac_tail, cfg, GNUNET_assert, GNUNET_ERROR_TYPE_DEBUG, GNUNET_GNSRECORD_z2s(), GNUNET_log, GNUNET_REVOCATION_query(), handle_revocation_result(), GNS_ResolverHandle::rev_check, and AuthorityChain::rh.

Referenced by recursive_resolution().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ GNS_resolver_lookup()

struct GNS_ResolverHandle* GNS_resolver_lookup ( const struct GNUNET_IDENTITY_PublicKey zone,
uint32_t  record_type,
const char *  name,
enum GNUNET_GNS_LocalOptions  options,
uint16_t  recursion_depth_limit,
GNS_ResultProcessor  proc,
void *  proc_cls 
)

Lookup of a record in a specific zone calls lookup result processor on result.

Lookup of a record in a specific zone calls RecordLookupProcessor on result or timeout.

Parameters
zonethe zone to perform the lookup in
record_typethe record type to look up
namethe name to look up
optionslocal options to control local lookup
recursion_depth_limithow many zones to traverse at most
procthe processor to call on result
proc_clsthe closure to pass to proc
Returns
handle to cancel operation

Definition at line 2796 of file gnunet-service-gns_resolver.c.

2803 {
2804  struct GNS_ResolverHandle *rh;
2805 
2807  "Starting lookup for `%s'\n",
2808  name);
2809  rh = GNUNET_new (struct GNS_ResolverHandle);
2811  rlh_tail,
2812  rh);
2813  rh->authority_zone = *zone;
2814  rh->proc = proc;
2815  rh->proc_cls = proc_cls;
2816  rh->options = options;
2817  rh->record_type = record_type;
2818  rh->name = GNUNET_strdup (name);
2819  rh->name_resolution_pos = strlen (name);
2820  rh->loop_threshold = recursion_depth_limit;
2822  rh);
2823  return rh;
2824 }
struct GNUNET_GETOPT_CommandLineOption options[]
Definition: 002.c:5

References GNS_ResolverHandle::authority_zone, GNUNET_CONTAINER_DLL_insert, GNUNET_ERROR_TYPE_DEBUG, GNUNET_log, GNUNET_new, GNUNET_SCHEDULER_add_now(), GNUNET_strdup, GNS_ResolverHandle::loop_threshold, name, GNS_ResolverHandle::name, GNS_ResolverHandle::name_resolution_pos, options, GNS_ResolverHandle::options, GNS_ResolverHandle::proc, GNS_ResolverHandle::proc_cls, GNS_ResolverHandle::record_type, rlh_head, rlh_tail, start_resolver_lookup(), GNS_ResolverHandle::task_id, and zone.

Referenced by handle_dns_request(), and handle_lookup().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ GNS_resolver_lookup_cancel()

void GNS_resolver_lookup_cancel ( struct GNS_ResolverHandle rh)

Cancel active resolution (i.e.

client disconnected).

Parameters
rhresolution to abort

Definition at line 2833 of file gnunet-service-gns_resolver.c.

2834 {
2835  struct DnsResult *dr;
2836  struct AuthorityChain *ac;
2837 
2839  rlh_tail,
2840  rh);
2841  if (NULL != rh->dns_request)
2842  {
2844  rh->dns_request = NULL;
2845  }
2846  while (NULL != (ac = rh->ac_head))
2847  {
2849  rh->ac_tail,
2850  ac);
2851  if (GNUNET_NO == ac->gns_authority)
2852  {
2853  struct Gns2DnsPending *gp;
2854 
2855  while (NULL != (gp = ac->authority_info.dns_authority.gp_head))
2856  {
2857  GNUNET_CONTAINER_DLL_remove (ac->authority_info.dns_authority.gp_head,
2858  ac->authority_info.dns_authority.gp_tail,
2859  gp);
2860  if (NULL != gp->rh)
2861  {
2862  /* rh->g2dc->rh is NOT in the DLL yet, so to enable us
2863  using GNS_resolver_lookup_cancel here, we need to
2864  add it first... */
2866  rlh_tail,
2867  gp->rh);
2868  GNUNET_assert (NULL == gp->rh->task_id);
2871  gp->rh);
2872  gp->rh = NULL;
2873  }
2874  if (NULL != gp->dns_rh)
2875  {
2877  gp->dns_rh = NULL;
2878  }
2879  GNUNET_free (gp);
2880  }
2881  GNUNET_DNSSTUB_stop (ac->authority_info.dns_authority.dns_handle);
2882  }
2883  GNUNET_free (ac->label);
2884  GNUNET_free (ac);
2885  }
2886  if (NULL != rh->task_id)
2887  {
2889  rh->task_id = NULL;
2890  }
2891  if (NULL != rh->get_handle)
2892  {
2894  rh->get_handle = NULL;
2895  }
2896  if (NULL != rh->dht_heap_node)
2897  {
2899  rh->dht_heap_node = NULL;
2900  }
2901  if (NULL != rh->namecache_qe)
2902  {
2904  rh->namecache_qe = NULL;
2905  }
2906  if (NULL != rh->rev_check)
2907  {
2909  rh->rev_check = NULL;
2910  }
2911  if (NULL != rh->std_resolve)
2912  {
2914  "Canceling standard DNS resolution\n");
2916  rh->std_resolve = NULL;
2917  }
2918  while (NULL != (dr = rh->dns_result_head))
2919  {
2922  dr);
2923  GNUNET_free (dr);
2924  }
2925  GNUNET_free (rh->leho);
2926  GNUNET_free (rh->name);
2927  GNUNET_free (rh);
2928 }
void GNUNET_DNSSTUB_stop(struct GNUNET_DNSSTUB_Context *ctx)
Cleanup DNSSTUB resolver.
Definition: dnsstub.c:716
void GNUNET_NAMECACHE_cancel(struct GNUNET_NAMECACHE_QueueEntry *qe)
Cancel a namecache operation.
void GNUNET_REVOCATION_query_cancel(struct GNUNET_REVOCATION_Query *q)
Cancel key revocation check.

References ac, GNS_ResolverHandle::ac_head, GNS_ResolverHandle::ac_tail, GNS_ResolverHandle::dht_heap_node, GNS_ResolverHandle::dns_request, GNS_ResolverHandle::dns_result_head, GNS_ResolverHandle::dns_result_tail, Gns2DnsPending::dns_rh, GNS_ResolverHandle::get_handle, GNS_resolver_lookup_cancel_(), GNUNET_assert, GNUNET_CONTAINER_DLL_insert, GNUNET_CONTAINER_DLL_remove, GNUNET_CONTAINER_heap_remove_node(), GNUNET_DHT_get_stop(), GNUNET_DNSSTUB_resolve_cancel(), GNUNET_DNSSTUB_stop(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_free, GNUNET_log, GNUNET_NAMECACHE_cancel(), GNUNET_NO, GNUNET_RESOLVER_request_cancel(), GNUNET_REVOCATION_query_cancel(), GNUNET_SCHEDULER_add_now(), GNUNET_SCHEDULER_cancel(), GNS_ResolverHandle::leho, GNS_ResolverHandle::name, GNS_ResolverHandle::namecache_qe, GNS_ResolverHandle::rev_check, Gns2DnsPending::rh, AuthorityChain::rh, rlh_head, rlh_tail, GNS_ResolverHandle::std_resolve, and GNS_ResolverHandle::task_id.

Referenced by client_disconnect_cb(), GNS_interceptor_done(), GNS_resolver_done(), GNS_resolver_lookup_cancel_(), and transmit_lookup_dns_result().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ GNS_resolver_init()

void 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 
)

Initialize the resolver.

Initialize the resolver subsystem.

Parameters
ncthe namecache handle
dhtthe dht handle
cconfiguration handle
max_bg_queriesmaximum number of parallel background queries in dht

Definition at line 2943 of file gnunet-service-gns_resolver.c.

2947 {
2948  cfg = c;
2949  namecache_handle = nc;
2950  dht_handle = dht;
2951  dht_lookup_heap =
2953  max_allowed_background_queries = max_bg_queries;
2955  "namecache",
2956  "DISABLE");
2957  if (GNUNET_YES == disable_cache)
2959  "Namecache disabled\n");
2960 }
static struct GNUNET_DHT_Handle * dht
Handle to the DHT.
static struct GNUNET_PEERINFO_NotifyContext * nc
Iterator context.
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_get_value_yesno(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option)
Get a configuration value that should be in a set of "YES" or "NO".
struct GNUNET_CONTAINER_Heap * GNUNET_CONTAINER_heap_create(enum GNUNET_CONTAINER_HeapOrder order)
Create a new heap.
@ GNUNET_CONTAINER_HEAP_ORDER_MIN
Heap with the minimum cost at the root.

References cfg, dht, dht_handle, dht_lookup_heap, disable_cache, GNUNET_CONFIGURATION_get_value_yesno(), GNUNET_CONTAINER_heap_create(), GNUNET_CONTAINER_HEAP_ORDER_MIN, GNUNET_ERROR_TYPE_WARNING, GNUNET_log, GNUNET_YES, max_allowed_background_queries, namecache_handle, and nc.

Referenced by run().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ GNS_resolver_done()

void GNS_resolver_done ( void  )

Shutdown resolver.

Cleanup resolver: Terminate pending lookups.

Definition at line 2967 of file gnunet-service-gns_resolver.c.

2968 {
2969  struct GNS_ResolverHandle *rh;
2970  struct CacheOps *co;
2971 
2972  /* abort active resolutions */
2973  while (NULL != (rh = rlh_head))
2974  {
2975  rh->proc (rh->proc_cls,
2976  0,
2977  NULL);
2979  }
2980  while (NULL != (co = co_head))
2981  {
2983  co_tail,
2984  co);
2986  GNUNET_free (co);
2987  }
2989  dht_lookup_heap = NULL;
2990  dht_handle = NULL;
2991  namecache_handle = NULL;
2992 }
void GNUNET_CONTAINER_heap_destroy(struct GNUNET_CONTAINER_Heap *heap)
Destroys the heap.

References co_head, co_tail, dht_handle, dht_lookup_heap, GNS_resolver_lookup_cancel(), GNUNET_CONTAINER_DLL_remove, GNUNET_CONTAINER_heap_destroy(), GNUNET_free, GNUNET_NAMECACHE_cancel(), namecache_handle, CacheOps::namecache_qe_cache, GNS_ResolverHandle::proc, GNS_ResolverHandle::proc_cls, and rlh_head.

Referenced by shutdown_task().

Here is the call graph for this function:
Here is the caller graph for this function:

Variable Documentation

◆ namecache_handle

struct GNUNET_NAMECACHE_Handle* namecache_handle
static

Our handle to the namecache service.

Definition at line 421 of file gnunet-service-gns_resolver.c.

Referenced by GNS_resolver_done(), GNS_resolver_init(), handle_dht_response(), and recursive_gns_resolution_namecache().

◆ dht_handle

struct GNUNET_DHT_Handle* dht_handle
static

Resolver handle to the dht.

Definition at line 426 of file gnunet-service-gns_resolver.c.

Referenced by GNS_resolver_done(), GNS_resolver_init(), and start_dht_request().

◆ dht_lookup_heap

struct GNUNET_CONTAINER_Heap* dht_lookup_heap
static

Heap for limiting parallel DHT lookups.

Definition at line 431 of file gnunet-service-gns_resolver.c.

Referenced by GNS_resolver_done(), GNS_resolver_init(), and start_dht_request().

◆ max_allowed_background_queries

unsigned long long max_allowed_background_queries
static

Maximum amount of parallel queries to the DHT.

Definition at line 436 of file gnunet-service-gns_resolver.c.

Referenced by GNS_resolver_init(), and start_dht_request().

◆ rlh_head

struct GNS_ResolverHandle* rlh_head
static

Head of resolver lookup list.

Definition at line 441 of file gnunet-service-gns_resolver.c.

Referenced by GNS_resolver_done(), GNS_resolver_lookup(), GNS_resolver_lookup_cancel(), and handle_gns2dns_result().

◆ rlh_tail

struct GNS_ResolverHandle* rlh_tail
static

Tail of resolver lookup list.

Definition at line 446 of file gnunet-service-gns_resolver.c.

Referenced by GNS_resolver_lookup(), GNS_resolver_lookup_cancel(), and handle_gns2dns_result().

◆ co_head

struct CacheOps* co_head
static

Organized in a DLL.

Definition at line 451 of file gnunet-service-gns_resolver.c.

Referenced by GNS_resolver_done(), handle_dht_response(), and namecache_cache_continuation().

◆ co_tail

struct CacheOps* co_tail
static

Organized in a DLL.

Definition at line 456 of file gnunet-service-gns_resolver.c.

Referenced by GNS_resolver_done(), handle_dht_response(), and namecache_cache_continuation().

◆ disable_cache

int disable_cache
static

◆ cfg

const struct GNUNET_CONFIGURATION_Handle* cfg
static

Global configuration.

Definition at line 466 of file gnunet-service-gns_resolver.c.

Referenced by GNS_resolver_init(), and recursive_gns_resolution_revocation().