GNUnet  0.16.x
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 a 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_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
Definition: gnunet_common.h:97
@ GNUNET_NO
Definition: gnunet_common.h:94
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_log(kind,...)
#define GNUNET_GNS_EMPTY_LABEL_AT
String we use to indicate an empty label (top-level entry in the zone).
@ 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_memcpy(dst, src, n)
Call memcpy() but check for n being 0 first.
#define GNUNET_CONTAINER_DLL_insert(head, tail, element)
Insert an element at the head of a DLL.
#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
tctask context
clsthe struct GNS_ResolverHandle of the resolution

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

2706 {
2707  struct GNS_ResolverHandle *rh = cls;
2708 
2709  rh->task_id = NULL;
2710  if (rh->loop_threshold < rh->loop_limiter++)
2711  {
2713  "Encountered unbounded recursion resolving `%s'\n",
2714  rh->name);
2715  fail_resolution (rh);
2716  return;
2717  }
2718  if (GNUNET_YES == rh->ac_tail->gns_authority)
2720  else
2722 }
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
clsthe struct GNS_ResolverHandle

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

2733 {
2734  struct GNS_ResolverHandle *rh = cls;
2735  struct AuthorityChain *ac;
2736  struct in_addr v4;
2737  struct in6_addr v6;
2738 
2739  rh->task_id = NULL;
2740  if (1 == inet_pton (AF_INET,
2741  rh->name,
2742  &v4))
2743  {
2744  /* name is IPv4 address, pretend it's an A record */
2745  struct GNUNET_GNSRECORD_Data rd;
2746 
2747  rd.data = &v4;
2748  rd.data_size = sizeof(v4);
2749  rd.expiration_time = UINT64_MAX;
2750  rd.record_type = GNUNET_DNSPARSER_TYPE_A;
2751  rd.flags = 0;
2752  rh->proc (rh->proc_cls,
2753  1,
2754  &rd);
2755  GNUNET_assert (NULL == rh->task_id);
2757  rh);
2758  return;
2759  }
2760  if (1 == inet_pton (AF_INET6,
2761  rh->name,
2762  &v6))
2763  {
2764  /* name is IPv6 address, pretend it's an AAAA record */
2765  struct GNUNET_GNSRECORD_Data rd;
2766 
2767  rd.data = &v6;
2768  rd.data_size = sizeof(v6);
2769  rd.expiration_time = UINT64_MAX;
2770  rd.record_type = GNUNET_DNSPARSER_TYPE_AAAA;
2771  rd.flags = 0;
2772  rh->proc (rh->proc_cls,
2773  1,
2774  &rd);
2775  GNUNET_assert (NULL == rh->task_id);
2777  rh);
2778  return;
2779  }
2780 
2781  ac = GNUNET_new (struct AuthorityChain);
2782  ac->rh = rh;
2783  ac->label = resolver_lookup_get_next_label (rh);
2784  if (NULL == ac->label)
2785  /* name was just the "TLD", so we default to label
2786  #GNUNET_GNS_EMPTY_LABEL_AT */
2788  ac->gns_authority = GNUNET_YES;
2789  ac->authority_info.gns_authority = rh->authority_zone;
2791  rh->ac_tail,
2792  ac);
2794  rh);
2795 }
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 877 of file gnunet-service-gns_resolver.c.

880 {
881  struct GNS_ResolverHandle *rh = cls;
882  struct GNUNET_DNSPARSER_Packet *p;
883  const struct GNUNET_DNSPARSER_Record *rec;
884  unsigned int rd_count;
885 
886  if (NULL == dns)
887  {
888  rh->dns_request = NULL;
890  rh->task_id = NULL;
891  fail_resolution (rh);
892  return;
893  }
894  if (rh->original_dns_id != dns->id)
895  {
896  /* DNS answer, but for another query */
897  return;
898  }
899  p = GNUNET_DNSPARSER_parse ((const char *) dns,
900  dns_len);
901  if (NULL == p)
902  {
904  _ ("Failed to parse DNS response\n"));
905  return;
906  }
907 
908  /* We got a result from DNS */
910  "Received DNS response for `%s' with %u answers\n",
911  rh->ac_tail->label,
912  (unsigned int) p->num_answers);
913  if ((p->num_answers > 0) &&
914  (GNUNET_DNSPARSER_TYPE_CNAME == p->answers[0].type) &&
916  {
917  int af;
918 
920  "Got CNAME `%s' from DNS for `%s'\n",
921  p->answers[0].data.hostname,
922  rh->name);
923  if (NULL != rh->std_resolve)
924  {
926  "Multiple CNAME results from DNS resolving `%s'! Not really allowed...\n",
927  rh->name);
929  }
930  GNUNET_free (rh->name);
931  rh->name = GNUNET_strdup (p->answers[0].data.hostname);
932  rh->name_resolution_pos = strlen (rh->name);
933  switch (rh->record_type)
934  {
936  af = AF_INET;
937  break;
938 
940  af = AF_INET6;
941  break;
942 
943  default:
944  af = AF_UNSPEC;
945  break;
946  }
947  if (NULL != rh->leho)
948  add_dns_result (rh,
949  GNUNET_TIME_UNIT_HOURS.rel_value_us,
951  strlen (rh->leho),
952  rh->leho);
954  af,
957  rh);
960  rh->dns_request = NULL;
961  return;
962  }
963 
964  /* convert from (parsed) DNS to (binary) GNS format! */
965  rd_count = p->num_answers + p->num_authority_records
966  + p->num_additional_records;
967  {
968  struct GNUNET_GNSRECORD_Data rd[rd_count + 1]; /* +1 for LEHO */
969  int skip;
970  char buf[UINT16_MAX];
971  size_t buf_off;
972  size_t buf_start;
973 
974  buf_off = 0;
975  skip = 0;
976  memset (rd,
977  0,
978  sizeof(rd));
979  for (unsigned int i = 0; i < rd_count; i++)
980  {
981  if (i < p->num_answers)
982  rec = &p->answers[i];
983  else if (i < p->num_answers + p->num_authority_records)
984  rec = &p->authority_records[i - p->num_answers];
985  else
986  rec = &p->additional_records[i - p->num_answers
987  - p->num_authority_records];
988  /* As we copied the full DNS name to 'rh->ac_tail->label', this
989  should be the correct check to see if this record is actually
990  a record for our label... */
991  if (0 != strcmp (rec->name,
992  rh->ac_tail->label))
993  {
995  "Dropping record `%s', does not match desired name `%s'\n",
996  rec->name,
997  rh->ac_tail->label);
998  skip++;
999  continue;
1000  }
1001  rd[i - skip].record_type = rec->type;
1002  rd[i - skip].expiration_time = rec->expiration_time.abs_value_us;
1003  switch (rec->type)
1004  {
1006  if (rec->data.raw.data_len != sizeof(struct in_addr))
1007  {
1008  GNUNET_break_op (0);
1009  skip++;
1010  continue;
1011  }
1012  rd[i - skip].data_size = rec->data.raw.data_len;
1013  rd[i - skip].data = rec->data.raw.data;
1014  break;
1015 
1017  if (rec->data.raw.data_len != sizeof(struct in6_addr))
1018  {
1019  GNUNET_break_op (0);
1020  skip++;
1021  continue;
1022  }
1023  rd[i - skip].data_size = rec->data.raw.data_len;
1024  rd[i - skip].data = rec->data.raw.data;
1025  break;
1026 
1030  buf_start = buf_off;
1031  if (GNUNET_OK !=
1033  sizeof(buf),
1034  &buf_off,
1035  rec->data.hostname))
1036  {
1037  GNUNET_break (0);
1038  skip++;
1039  continue;
1040  }
1041  rd[i - skip].data_size = buf_off - buf_start;
1042  rd[i - skip].data = &buf[buf_start];
1043  break;
1044 
1046  buf_start = buf_off;
1047  if (GNUNET_OK !=
1049  sizeof(buf),
1050  &buf_off,
1051  rec->data.soa))
1052  {
1053  GNUNET_break (0);
1054  skip++;
1055  continue;
1056  }
1057  rd[i - skip].data_size = buf_off - buf_start;
1058  rd[i - skip].data = &buf[buf_start];
1059  break;
1060 
1062  buf_start = buf_off;
1063  if (GNUNET_OK !=
1065  sizeof(buf),
1066  &buf_off,
1067  rec->data.mx))
1068  {
1069  GNUNET_break (0);
1070  skip++;
1071  continue;
1072  }
1073  rd[i - skip].data_size = buf_off - buf_start;
1074  rd[i - skip].data = &buf[buf_start];
1075  break;
1076 
1078  buf_start = buf_off;
1079  if (GNUNET_OK !=
1081  sizeof(buf),
1082  &buf_off,
1083  rec->data.srv))
1084  {
1085  GNUNET_break (0);
1086  skip++;
1087  continue;
1088  }
1089  rd[i - skip].data_size = buf_off - buf_start;
1090  rd[i - skip].data = &buf[buf_start];
1091  break;
1092 
1093  default:
1095  _ ("Skipping record of unsupported type %d\n"),
1096  rec->type);
1097  skip++;
1098  continue;
1099  }
1100  } /* end of for all records in answer */
1101  if (NULL != rh->leho)
1102  {
1103  rd[rd_count - skip].record_type = GNUNET_GNSRECORD_TYPE_LEHO;
1104  rd[rd_count - skip].flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION;
1105  rd[rd_count - skip].flags |= GNUNET_GNSRECORD_RF_SUPPLEMENTAL;
1106  rd[rd_count - skip].expiration_time = GNUNET_TIME_UNIT_HOURS.rel_value_us;
1107  rd[rd_count - skip].data = rh->leho;
1108  rd[rd_count - skip].data_size = strlen (rh->leho);
1109  skip--; /* skip one LESS */
1111  "Adding LEHO %s\n",
1112  rh->leho);
1113  }
1115  "Returning DNS response for `%s' with %u answers\n",
1116  rh->ac_tail->label,
1117  (unsigned int) (rd_count - skip));
1118  rh->proc (rh->proc_cls,
1119  rd_count - skip,
1120  rd);
1122  rh->dns_request = NULL;
1123  }
1125  if (NULL != rh->task_id)
1126  GNUNET_SCHEDULER_cancel (rh->task_id); /* should be timeout task */
1128  rh);
1129 }
#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
@ GNUNET_OK
Definition: gnunet_common.h:95
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
#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 1141 of file gnunet-service-gns_resolver.c.

1142 {
1143  struct AuthorityChain *ac;
1144  struct GNUNET_DNSPARSER_Query *query;
1145  struct GNUNET_DNSPARSER_Packet *p;
1146  char *dns_request;
1147  size_t dns_request_length;
1148  int ret;
1149 
1150  ac = rh->ac_tail;
1151  GNUNET_assert (NULL != ac);
1153  "Starting DNS lookup for `%s'\n",
1154  ac->label);
1155  GNUNET_assert (GNUNET_NO == ac->gns_authority);
1156  query = GNUNET_new (struct GNUNET_DNSPARSER_Query);
1157  query->name = GNUNET_strdup (ac->label);
1158  query->type = rh->record_type;
1161  p->queries = query;
1162  p->num_queries = 1;
1164  UINT16_MAX);
1165  p->flags.opcode = GNUNET_TUN_DNS_OPCODE_QUERY;
1166  p->flags.recursion_desired = 1;
1168  1024,
1169  &dns_request,
1170  &dns_request_length);
1171  if (GNUNET_OK != ret)
1172  {
1173  GNUNET_break (0);
1174  rh->proc (rh->proc_cls,
1175  0,
1176  NULL);
1177  GNUNET_assert (NULL == rh->task_id);
1179  rh);
1180  }
1181  else
1182  {
1183  rh->original_dns_id = p->id;
1184  GNUNET_assert (NULL != ac->authority_info.dns_authority.dns_handle);
1185  GNUNET_assert (NULL == rh->dns_request);
1186  rh->leho = GNUNET_strdup (ac->label);
1188  ac->authority_info.dns_authority.dns_handle,
1189  dns_request,
1190  dns_request_length,
1192  rh);
1195  rh);
1196  }
1197  if (GNUNET_SYSERR != ret)
1198  GNUNET_free (dns_request);
1200 }
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.
@ GNUNET_SYSERR
Definition: gnunet_common.h:93
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
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 1212 of file gnunet-service-gns_resolver.c.

1214 {
1215  size_t nlen;
1216  char *res;
1217  const char *tld;
1218  struct AuthorityChain *ac;
1219  int af;
1221 
1223  "Handling GNS REDIRECT result `%s'\n",
1224  rname);
1225  nlen = strlen (rname);
1226  tld = GNS_get_tld (rname);
1227  if (0 == strcmp ("+", tld))
1228  {
1229  /* REDIRECT resolution continues relative to current domain */
1230  if (0 == rh->name_resolution_pos)
1231  {
1232  res = GNUNET_strndup (rname, nlen - 2);
1233  rh->name_resolution_pos = nlen - 2;
1234  }
1235  else
1236  {
1237  GNUNET_asprintf (&res,
1238  "%.*s.%.*s",
1239  (int) rh->name_resolution_pos,
1240  rh->name,
1241  (int) (nlen - 2),
1242  rname);
1243  rh->name_resolution_pos = strlen (res);
1244  }
1245  GNUNET_free (rh->name);
1246  rh->name = res;
1247  ac = GNUNET_new (struct AuthorityChain);
1248  ac->rh = rh;
1249  ac->gns_authority = GNUNET_YES;
1250  ac->authority_info.gns_authority =
1252  ac->label = resolver_lookup_get_next_label (rh);
1253  /* add AC to tail */
1255  rh->ac_tail,
1256  ac);
1258  rh);
1259  return;
1260  }
1262  {
1263  /* REDIRECT resolution continues relative to current domain */
1264  if (0 == rh->name_resolution_pos)
1265  {
1266  GNUNET_asprintf (&res,
1267  "%.*s",
1268  (int) (strlen (rname) - (strlen (tld) + 1)),
1269  rname);
1270  }
1271  else
1272  {
1273  GNUNET_asprintf (&res,
1274  "%.*s.%.*s",
1275  (int) rh->name_resolution_pos,
1276  rh->name,
1277  (int) (strlen (rname) - (strlen (tld) + 1)),
1278  rname);
1279  }
1280  rh->name_resolution_pos = strlen (res);
1281  GNUNET_free (rh->name);
1282  rh->name = res;
1283  ac = GNUNET_new (struct AuthorityChain);
1284  ac->rh = rh;
1285  ac->gns_authority = GNUNET_YES;
1286  ac->authority_info.gns_authority = zone;
1287  ac->label = resolver_lookup_get_next_label (rh);
1288  /* add AC to tail */
1290  rh->ac_tail,
1291  ac);
1293  rh);
1294  return;
1295  }
1296 
1298  "Got REDIRECT `%s' from GNS for `%s'\n",
1299  rname,
1300  rh->name);
1301  if (NULL != rh->std_resolve)
1302  {
1304  "Multiple REDIRECT results from GNS resolving `%s'! Not really allowed...\n",
1305  rh->name);
1307  }
1308  /* name is absolute, go to DNS */
1309  GNUNET_free (rh->name);
1310  rh->name = GNUNET_strdup (rname);
1311  rh->name_resolution_pos = strlen (rh->name);
1312  switch (rh->record_type)
1313  {
1315  af = AF_INET;
1316  break;
1317 
1319  af = AF_INET6;
1320  break;
1321 
1322  default:
1323  af = AF_UNSPEC;
1324  break;
1325  }
1327  "Doing standard DNS lookup for `%s'\n",
1328  rh->name);
1329 
1331  af,
1334  rh);
1335 }
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 1348 of file gnunet-service-gns_resolver.c.

1350 {
1351  int af;
1352 
1353  GNUNET_free (rh->name);
1354  rh->name = GNUNET_strdup (cname);
1355  rh->name_resolution_pos = strlen (rh->name);
1356  switch (rh->record_type)
1357  {
1359  af = AF_INET;
1360  break;
1361 
1363  af = AF_INET6;
1364  break;
1365 
1366  default:
1367  af = AF_UNSPEC;
1368  break;
1369  }
1371  "Doing standard DNS lookup for `%s'\n",
1372  rh->name);
1373 
1375  af,
1378  rh);
1379 }

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 a 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
clsclosure with the struct GNS_ResolverHandle
rd_countnumber of entries in rd array
rdarray of records with data to store

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

1909 {
1910  struct GNS_ResolverHandle *rh = cls;
1911  char *cname;
1912  char scratch[UINT16_MAX];
1913  size_t scratch_off;
1914  size_t scratch_start;
1915  size_t off;
1916  struct GNUNET_GNSRECORD_Data rd_new[rd_count];
1917  unsigned int rd_off;
1918 
1920  "Resolution succeeded for `%s' in zone %s, got %u records\n",
1921  rh->ac_tail->label,
1923  rd_count);
1924  if (0 == rd_count)
1925  {
1927  _ ("GNS lookup failed (zero records found for `%s')\n"),
1928  rh->name);
1929  fail_resolution (rh);
1930  return;
1931  }
1932 
1933  if (0 == rh->name_resolution_pos)
1934  {
1935  /* top-level match, are we done yet? */
1936  if ((rd_count > 0) &&
1939  {
1940  off = 0;
1941  cname = GNUNET_DNSPARSER_parse_name (rd[0].data,
1942  rd[0].data_size,
1943  &off);
1944  if ((NULL == cname) ||
1945  (off != rd[0].data_size))
1946  {
1947  GNUNET_break_op (0);
1948  GNUNET_free (cname);
1949  fail_resolution (rh);
1950  return;
1951  }
1953  cname);
1954  GNUNET_free (cname);
1955  return;
1956  }
1957  if ((rd_count > 0) &&
1960  {
1962  rd[0].data);
1963  return;
1964  }
1965 
1966 
1967  /* If A/AAAA was requested,
1968  * but we got a GNS2DNS record */
1969  if ((GNUNET_DNSPARSER_TYPE_A == rh->record_type) ||
1971  {
1972  for (unsigned int i = 0; i < rd_count; i++)
1973  {
1974  switch (rd[i].record_type)
1975  {
1977  {
1978  /* delegation to DNS */
1980  "Found GNS2DNS record, delegating to DNS!\n");
1981  if (GNUNET_OK ==
1983  rd_count,
1984  rd))
1985  return;
1986  else
1987  goto fail;
1988  }
1989 
1990  default:
1991  break;
1992  } /* end: switch */
1993  } /* end: for rd */
1994  } /* end: name_resolution_pos */
1995  /* convert relative names in record values to absolute names,
1996  using 'scratch' array for memory allocations */
1997  scratch_off = 0;
1998  rd_off = 0;
1999  for (unsigned int i = 0; i < rd_count; i++)
2000  {
2001  GNUNET_assert (rd_off <= i);
2002  if ((0 != rh->protocol) &&
2003  (0 != rh->service) &&
2004  (GNUNET_GNSRECORD_TYPE_BOX != rd[i].record_type))
2005  continue; /* we _only_ care about boxed records */
2006 
2007  GNUNET_assert (rd_off < rd_count);
2008  rd_new[rd_off] = rd[i];
2009  /* Check if the embedded name(s) end in "+", and if so,
2010  replace the "+" with the zone at "ac_tail", changing the name
2011  to a ".ZONEKEY". The name is allocated on the 'scratch' array,
2012  so we can free it afterwards. */
2013  switch (rd[i].record_type)
2014  {
2016  {
2017  char *rname;
2018  rname = GNUNET_strndup (rd[i].data, rd[i].data_size);
2019  rname = translate_dot_plus (rh, rname);
2020  GNUNET_break (NULL != rname);
2021  scratch_start = scratch_off;
2022  memcpy (&scratch[scratch_start], rname, strlen (rname) + 1);
2023  scratch_off += strlen (rname) + 1;
2024  GNUNET_assert (rd_off < rd_count);
2025  rd_new[rd_off].data = &scratch[scratch_start];
2026  rd_new[rd_off].data_size = scratch_off - scratch_start;
2027  rd_off++;
2028  GNUNET_free (rname);
2029  }
2030  break;
2031 
2033  {
2034  char *cname;
2035 
2036  off = 0;
2037  cname = GNUNET_DNSPARSER_parse_name (rd[i].data,
2038  rd[i].data_size,
2039  &off);
2040  if ((NULL == cname) ||
2041  (off != rd[i].data_size))
2042  {
2043  GNUNET_break_op (0); /* record not well-formed */
2044  }
2045  else
2046  {
2047  cname = translate_dot_plus (rh, cname);
2048  GNUNET_break (NULL != cname);
2049  scratch_start = scratch_off;
2050  if (GNUNET_OK !=
2052  sizeof(scratch),
2053  &scratch_off,
2054  cname))
2055  {
2056  GNUNET_break (0);
2057  }
2058  else
2059  {
2060  GNUNET_assert (rd_off < rd_count);
2061  rd_new[rd_off].data = &scratch[scratch_start];
2062  rd_new[rd_off].data_size = scratch_off - scratch_start;
2063  rd_off++;
2064  }
2065  }
2066  GNUNET_free (cname);
2067  }
2068  break;
2069 
2071  {
2072  struct GNUNET_DNSPARSER_SoaRecord *soa;
2073 
2074  off = 0;
2075  soa = GNUNET_DNSPARSER_parse_soa (rd[i].data,
2076  rd[i].data_size,
2077  &off);
2078  if ((NULL == soa) ||
2079  (off != rd[i].data_size))
2080  {
2081  GNUNET_break_op (0); /* record not well-formed */
2082  }
2083  else
2084  {
2085  soa->mname = translate_dot_plus (rh, soa->mname);
2086  soa->rname = translate_dot_plus (rh, soa->rname);
2087  scratch_start = scratch_off;
2088  if (GNUNET_OK !=
2090  sizeof(scratch),
2091  &scratch_off,
2092  soa))
2093  {
2094  GNUNET_break (0);
2095  }
2096  else
2097  {
2098  GNUNET_assert (rd_off < rd_count);
2099  rd_new[rd_off].data = &scratch[scratch_start];
2100  rd_new[rd_off].data_size = scratch_off - scratch_start;
2101  rd_off++;
2102  }
2103  }
2104  if (NULL != soa)
2106  }
2107  break;
2108 
2110  {
2111  struct GNUNET_DNSPARSER_MxRecord *mx;
2112 
2113  off = 0;
2114  mx = GNUNET_DNSPARSER_parse_mx (rd[i].data,
2115  rd[i].data_size,
2116  &off);
2117  if ((NULL == mx) ||
2118  (off != rd[i].data_size))
2119  {
2120  GNUNET_break_op (0); /* record not well-formed */
2121  }
2122  else
2123  {
2124  mx->mxhost = translate_dot_plus (rh, mx->mxhost);
2125  scratch_start = scratch_off;
2126  if (GNUNET_OK !=
2128  sizeof(scratch),
2129  &scratch_off,
2130  mx))
2131  {
2132  GNUNET_break (0);
2133  }
2134  else
2135  {
2136  GNUNET_assert (rd_off < rd_count);
2137  rd_new[rd_off].data = &scratch[scratch_start];
2138  rd_new[rd_off].data_size = scratch_off - scratch_start;
2139  rd_off++;
2140  }
2141  }
2142  if (NULL != mx)
2144  }
2145  break;
2146 
2148  {
2149  struct GNUNET_DNSPARSER_SrvRecord *srv;
2150 
2151  off = 0;
2152  srv = GNUNET_DNSPARSER_parse_srv (rd[i].data,
2153  rd[i].data_size,
2154  &off);
2155  if ((NULL == srv) ||
2156  (off != rd[i].data_size))
2157  {
2158  GNUNET_break_op (0); /* record not well-formed */
2159  }
2160  else
2161  {
2162  srv->target = translate_dot_plus (rh, srv->target);
2163  scratch_start = scratch_off;
2164  if (GNUNET_OK !=
2166  sizeof(scratch),
2167  &scratch_off,
2168  srv))
2169  {
2170  GNUNET_break (0);
2171  }
2172  else
2173  {
2174  GNUNET_assert (rd_off < rd_count);
2175  rd_new[rd_off].data = &scratch[scratch_start];
2176  rd_new[rd_off].data_size = scratch_off - scratch_start;
2177  rd_off++;
2178  }
2179  }
2180  if (NULL != srv)
2182  }
2183  break;
2184 
2187  {
2189  if (rd[i].data_size < sizeof(uint32_t))
2190  {
2191  GNUNET_break_op (0);
2192  break;
2193  }
2194  if (GNUNET_OK !=
2196  rd[i].data_size,
2197  rd[i].record_type,
2198  &pubkey))
2199  {
2200  GNUNET_break_op (0);
2201  break;
2202  }
2203  rd_off++;
2204  if (rd[i].record_type != rh->record_type)
2205  {
2206  /* try to resolve "@" */
2207  struct AuthorityChain *ac;
2208 
2209  ac = GNUNET_new (struct AuthorityChain);
2210  ac->rh = rh;
2211  ac->gns_authority = GNUNET_YES;
2212  ac->authority_info.gns_authority = pubkey;
2215  rh->ac_tail,
2216  ac);
2218  rh);
2219  return;
2220  }
2221  }
2222  break;
2223 
2225  {
2226  /* delegation to DNS */
2228  {
2229  rd_off++;
2230  break; /* do not follow to DNS, we wanted the GNS2DNS record! */
2231  }
2233  "Found GNS2DNS record, delegating to DNS!\n");
2234  if (GNUNET_OK ==
2236  rd_count,
2237  rd))
2238  return;
2239  else
2240  goto fail;
2241  }
2242 
2244  {
2245  /* unbox SRV/TLSA records if a specific one was requested */
2246  if ((0 != rh->protocol) &&
2247  (0 != rh->service) &&
2248  (rd[i].data_size >= sizeof(struct GNUNET_GNSRECORD_BoxRecord)))
2249  {
2250  const struct GNUNET_GNSRECORD_BoxRecord *box;
2251 
2252  box = rd[i].data;
2254  "Got BOX record, checking if parameters match... %u/%u vs %u/%u\n",
2255  ntohs (box->protocol), ntohs (box->service),
2256  rh->protocol, rh->service);
2257  if ((ntohs (box->protocol) == rh->protocol) &&
2258  (ntohs (box->service) == rh->service))
2259  {
2260  /* Box matches, unbox! */
2261  GNUNET_assert (rd_off < rd_count);
2262  rd_new[rd_off].record_type = ntohl (box->record_type);
2263  rd_new[rd_off].data_size -= sizeof(struct
2265  rd_new[rd_off].data = &box[1];
2266  rd_off++;
2267  }
2268  }
2269  else
2270  {
2271  /* no specific protocol/service specified, preserve all BOX
2272  records (for modern, GNS-enabled applications) */
2273  rd_off++;
2274  }
2275  break;
2276  }
2277 
2278  default:
2279  rd_off++;
2280  break;
2281  } /* end: switch */
2282  } /* end: for rd_count */
2283 
2284  /* yes, we are done, return result */
2286  "Returning GNS response for `%s' with %u answers\n",
2287  rh->ac_tail->label,
2288  rd_off);
2289  rh->proc (rh->proc_cls,
2290  rd_off,
2291  rd_new);
2293  rh);
2294  return;
2295  }
2296 
2297  switch (rd[0].record_type)
2298  {
2300  GNUNET_break_op (1 == rd_count); /* REDIRECT should be unique */
2302  &rd[0]);
2303  return;
2304 
2306  GNUNET_break_op (1 == rd_count); /* CNAME should be unique */
2308  &rd[0]);
2309  return;
2310 
2313  GNUNET_break_op (1 == rd_count); /* PKEY should be unique */
2315  &rd[0]);
2316  return;
2317 
2319  if (GNUNET_OK ==
2321  rd_count,
2322  rd))
2323  return;
2324  break;
2325  default:
2327  return;
2329  _ ("Unable to process critical delegation record\n"));
2330  break;
2331  }
2332  fail:
2334  _ ("GNS lookup recursion failed (no delegation record found)\n"));
2335  fail_resolution (rh);
2336 }
#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 1404 of file gnunet-service-gns_resolver.c.

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

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 1441 of file gnunet-service-gns_resolver.c.

1444 {
1445  struct Gns2DnsPending *gp = cls;
1446  struct AuthorityChain *ac = gp->ac;
1447 
1448  GNUNET_CONTAINER_DLL_remove (ac->authority_info.dns_authority.gp_head,
1449  ac->authority_info.dns_authority.gp_tail,
1450  gp);
1451  /* enable cleanup of 'rh' handle that automatically comes after we return,
1452  and which expects 'rh' to be in the #rlh_head DLL. */
1453  if (NULL != gp->rh)
1454  {
1456  rlh_tail,
1457  gp->rh);
1458  gp->rh = NULL;
1459  }
1460  GNUNET_free (gp);
1462  "Received %u results for IP address of DNS server for GNS2DNS transition\n",
1463  rd_count);
1464  /* find suitable A/AAAA record */
1465  for (unsigned int j = 0; j < rd_count; j++)
1466  {
1467  switch (rd[j].record_type)
1468  {
1470  {
1471  struct sockaddr_in v4;
1472 
1473  if (sizeof(struct in_addr) != rd[j].data_size)
1474  {
1475  GNUNET_break_op (0);
1476  continue;
1477  }
1478  memset (&v4,
1479  0,
1480  sizeof(v4));
1481  v4.sin_family = AF_INET;
1482  v4.sin_port = htons (53);
1483 #if HAVE_SOCKADDR_IN_SIN_LEN
1484  v4.sin_len = (u_char) sizeof(v4);
1485 #endif
1486  GNUNET_memcpy (&v4.sin_addr,
1487  rd[j].data,
1488  sizeof(struct in_addr));
1489  if (GNUNET_OK ==
1491  ac->authority_info.dns_authority.dns_handle,
1492  (const struct sockaddr *) &v4))
1493  ac->authority_info.dns_authority.found = GNUNET_YES;
1494  break;
1495  }
1496 
1498  {
1499  struct sockaddr_in6 v6;
1500 
1501  if (sizeof(struct in6_addr) != rd[j].data_size)
1502  {
1503  GNUNET_break_op (0);
1504  continue;
1505  }
1506  /* FIXME: might want to check if we support IPv6 here,
1507  and otherwise skip this one and hope we find another */
1508  memset (&v6,
1509  0,
1510  sizeof(v6));
1511  v6.sin6_family = AF_INET6;
1512  v6.sin6_port = htons (53);
1513 #if HAVE_SOCKADDR_IN_SIN_LEN
1514  v6.sin6_len = (u_char) sizeof(v6);
1515 #endif
1516  GNUNET_memcpy (&v6.sin6_addr,
1517  rd[j].data,
1518  sizeof(struct in6_addr));
1519  if (GNUNET_OK ==
1521  ac->authority_info.dns_authority.dns_handle,
1522  (const struct sockaddr *) &v6))
1523  ac->authority_info.dns_authority.found = GNUNET_YES;
1524  break;
1525  }
1526 
1527  default:
1528  break;
1529  }
1530  }
1532 }
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 1543 of file gnunet-service-gns_resolver.c.

1546 {
1547  struct Gns2DnsPending *gp = cls;
1548  struct AuthorityChain *ac = gp->ac;
1549  struct sockaddr_storage ss;
1550  struct sockaddr_in *v4;
1551  struct sockaddr_in6 *v6;
1552 
1553  if (NULL == addr)
1554  {
1555  /* DNS resolution finished */
1556  if (0 == gp->num_results)
1558  "Failed to use DNS to resolve name of DNS resolver\n");
1559  GNUNET_CONTAINER_DLL_remove (ac->authority_info.dns_authority.gp_head,
1560  ac->authority_info.dns_authority.gp_tail,
1561  gp);
1562  GNUNET_free (gp);
1564  return;
1565  }
1566  GNUNET_memcpy (&ss,
1567  addr,
1568  addrlen);
1569  switch (ss.ss_family)
1570  {
1571  case AF_INET:
1572  v4 = (struct sockaddr_in *) &ss;
1573  v4->sin_port = htons (53);
1574  gp->num_results++;
1575  break;
1576 
1577  case AF_INET6:
1578  v6 = (struct sockaddr_in6 *) &ss;
1579  v6->sin6_port = htons (53);
1580  gp->num_results++;
1581  break;
1582 
1583  default:
1585  "Unsupported AF %d\n",
1586  ss.ss_family);
1587  return;
1588  }
1589  if (GNUNET_OK ==
1590  GNUNET_DNSSTUB_add_dns_sa (ac->authority_info.dns_authority.dns_handle,
1591  (struct sockaddr *) &ss))
1592  ac->authority_info.dns_authority.found = GNUNET_YES;
1593 }
@ 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 1602 of file gnunet-service-gns_resolver.c.

1604 {
1606  rd->data);
1607 }

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 1617 of file gnunet-service-gns_resolver.c.

1619 {
1620  char *cname;
1621  size_t off;
1622 
1623  off = 0;
1624  cname = GNUNET_DNSPARSER_parse_name (rd->data,
1625  rd->data_size,
1626  &off);
1627  if ((NULL == cname) ||
1628  (off != rd->data_size))
1629  {
1630  GNUNET_break_op (0); /* record not well-formed */
1631  GNUNET_free (cname);
1632  fail_resolution (rh);
1633  return;
1634  }
1636  cname);
1637  GNUNET_free (cname);
1638 }
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 1648 of file gnunet-service-gns_resolver.c.

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

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 1691 of file gnunet-service-gns_resolver.c.

1694 {
1695  struct AuthorityChain *ac;
1696  const char *tld;
1697  char *ns;
1698 
1699  ns = NULL;
1700  /* expand authority chain */
1701  ac = GNUNET_new (struct AuthorityChain);
1702  ac->rh = rh;
1703  ac->authority_info.dns_authority.dns_handle = GNUNET_DNSSTUB_start (4);
1704 
1705  for (unsigned int i = 0; i < rd_count; i++)
1706  {
1707  char *ip;
1708  char *n;
1709  size_t off;
1710  struct Gns2DnsPending *gp;
1712  struct sockaddr_in v4;
1713  struct sockaddr_in6 v6;
1714 
1715  if (GNUNET_GNSRECORD_TYPE_GNS2DNS != rd[i].record_type)
1716  {
1720  GNUNET_free (ns);
1721  GNUNET_free (ac);
1722  return GNUNET_SYSERR;
1723  }
1724  off = 0;
1725  n = GNUNET_DNSPARSER_parse_name (rd[i].data,
1726  rd[i].data_size,
1727  &off);
1728  ip = GNUNET_strdup (&((const char *) rd[i].data)[off]);
1729  if ((NULL == n) ||
1730  (NULL == ip))
1731  {
1732  GNUNET_break_op (0);
1733  GNUNET_free (n);
1734  GNUNET_free (ip);
1735  continue;
1736  }
1737 
1738  off += strlen (ip) + 1;
1739 
1740  if (off != rd[i].data_size)
1741  {
1742  GNUNET_break_op (0);
1743  GNUNET_free (n);
1744  GNUNET_free (ip);
1745  continue;
1746  }
1747  /* resolve 'ip' to determine the IP(s) of the DNS
1748  resolver to use for lookup of 'ns' */
1749  if (NULL != ns)
1750  {
1751  if (0 != strcasecmp (ns,
1752  n))
1753  {
1754  /* NS values must all be the same for all GNS2DNS records,
1755  anything else leads to insanity */
1756  GNUNET_break_op (0);
1757  GNUNET_free (n);
1758  GNUNET_free (ip);
1759  continue;
1760  }
1761  GNUNET_free (n);
1762  }
1763  else
1764  {
1765  ns = n;
1766  }
1767 
1768  /* check if 'ip' is already an IPv4/IPv6 address */
1769  if ((1 == inet_pton (AF_INET,
1770  ip,
1771  &v4)) ||
1772  (1 == inet_pton (AF_INET6,
1773  ip,
1774  &v6)))
1775  {
1778  ac->authority_info.dns_authority.dns_handle,
1779  ip));
1780  ac->authority_info.dns_authority.found = GNUNET_YES;
1781  GNUNET_free (ip);
1782  continue;
1783  }
1784  tld = GNS_get_tld (ip);
1785  if ((0 != strcmp (tld, "+")) &&
1787  {
1788  /* 'ip' is a DNS name */
1789  gp = GNUNET_new (struct Gns2DnsPending);
1790  gp->ac = ac;
1791  GNUNET_CONTAINER_DLL_insert (ac->authority_info.dns_authority.gp_head,
1792  ac->authority_info.dns_authority.gp_tail,
1793  gp);
1794  gp->dns_rh = GNUNET_RESOLVER_ip_get (ip,
1795  AF_UNSPEC,
1798  gp);
1799  GNUNET_free (ip);
1800  continue;
1801  }
1802  /* 'ip' should be a GNS name */
1803  gp = GNUNET_new (struct Gns2DnsPending);
1804  gp->ac = ac;
1805  GNUNET_CONTAINER_DLL_insert (ac->authority_info.dns_authority.gp_head,
1806  ac->authority_info.dns_authority.gp_tail,
1807  gp);
1808  gp->rh = GNUNET_new (struct GNS_ResolverHandle);
1809  if (0 == strcmp (tld, "+"))
1810  {
1811  ip = translate_dot_plus (rh,
1812  ip);
1813  tld = GNS_get_tld (ip);
1814  if (GNUNET_OK !=
1816  &zone))
1817  {
1818  GNUNET_break_op (0);
1819  GNUNET_free (ip);
1820  continue;
1821  }
1822  }
1823  gp->rh->authority_zone = zone;
1825  "Resolving `%s' to determine IP address of DNS server for GNS2DNS transition for `%s'\n",
1826  ip,
1827  ns);
1828  gp->rh->name = ip;
1829  gp->rh->name_resolution_pos = strlen (ip) - strlen (tld) - 1;
1830  gp->rh->proc = &handle_gns2dns_result;
1831  gp->rh->proc_cls = gp;
1834  gp->rh->loop_limiter = rh->loop_limiter + 1;
1835  gp->rh->loop_threshold = rh->loop_threshold;
1836  gp->rh->task_id
1838  gp->rh);
1839  } /* end 'for all records' */
1840 
1841  if (NULL == ns)
1842  {
1843  /* not a single GNS2DNS record found */
1844  GNUNET_free (ac);
1845  return GNUNET_SYSERR;
1846  }
1848  strcpy (ac->authority_info.dns_authority.name,
1849  ns);
1850  /* for DNS recursion, the label is the full DNS name,
1851  created from the remainder of the GNS name and the
1852  name in the NS record */
1853  GNUNET_asprintf (&ac->label,
1854  "%.*s%s%s",
1855  (int) rh->name_resolution_pos,
1856  rh->name,
1857  (0 != rh->name_resolution_pos) ? "." : "",
1858  ns);
1859  GNUNET_free (ns);
1860 
1861  {
1862  /* the GNS name is UTF-8 and may include multibyte chars.
1863  * We have to convert the combined name to a DNS-compatible IDNA.
1864  */
1865  char *tmp = ac->label;
1866 
1867  if (IDNA_SUCCESS != idna_to_ascii_8z (tmp,
1868  &ac->label,
1869  IDNA_ALLOW_UNASSIGNED))
1870  {
1872  _ ("Name `%s' cannot be converted to IDNA."),
1873  tmp);
1874  GNUNET_free (tmp);
1875  GNUNET_free (ac);
1876  return GNUNET_SYSERR;
1877  }
1878  GNUNET_free (tmp);
1879  }
1880 
1882  rh->ac_tail,
1883  ac);
1884  if (strlen (ac->label) > GNUNET_DNSPARSER_MAX_NAME_LENGTH)
1885  {
1887  _ ("GNS lookup resulted in DNS name that is too long (`%s')\n"),
1888  ac->label);
1889  GNUNET_free (ac->label);
1890  GNUNET_free (ac);
1891  return GNUNET_SYSERR;
1892  }
1894  return GNUNET_OK;
1895 }
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 2348 of file gnunet-service-gns_resolver.c.

2351 {
2352  struct CacheOps *co = cls;
2353 
2354  co->namecache_qe_cache = NULL;
2355  if (GNUNET_OK != success)
2357  _ ("Failed to cache GNS resolution: %s\n"),
2358  emsg);
2360  co_tail,
2361  co);
2362  GNUNET_free (co);
2363 }
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_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
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 2384 of file gnunet-service-gns_resolver.c.

2394 {
2395  struct GNS_ResolverHandle *rh = cls;
2396  struct AuthorityChain *ac = rh->ac_tail;
2397  const struct GNUNET_GNSRECORD_Block *block;
2398  struct CacheOps *co;
2399 
2400  (void) exp;
2401  (void) key;
2402  (void) get_path;
2403  (void) get_path_length;
2404  (void) put_path;
2405  (void) put_path_length;
2406  (void) type;
2408  rh->get_handle = NULL;
2410  rh->dht_heap_node = NULL;
2412  "Handling response from the DHT\n");
2413  if (size < sizeof(struct GNUNET_GNSRECORD_Block))
2414  {
2415  /* how did this pass DHT block validation!? */
2416  GNUNET_break (0);
2417  fail_resolution (rh);
2418  return;
2419  }
2420  block = data;
2421  if (size != GNUNET_GNSRECORD_block_get_size (block))
2422  {
2423  /* how did this pass DHT block validation!? */
2424  GNUNET_break (0);
2425  fail_resolution (rh);
2426  return;
2427  }
2429  "Decrypting DHT block of size %lu for `%s', expires %s\n",
2431  rh->name,
2433  if (GNUNET_OK !=
2435  &ac->authority_info.gns_authority,
2436  ac->label,
2438  rh))
2439  {
2440  GNUNET_break_op (0); /* block was ill-formed */
2441  fail_resolution (rh);
2442  return;
2443  }
2446  rel_value_us)
2447  {
2449  "Received expired block from the DHT, will not cache it.\n");
2450  return;
2451  }
2452  if (GNUNET_YES == disable_cache)
2453  return;
2454  /* Cache well-formed blocks */
2456  "Caching response from the DHT in namecache\n");
2457  co = GNUNET_new (struct CacheOps);
2459  block,
2460  &
2462  co);
2464  co_tail,
2465  co);
2466 }
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 a 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:1187
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 2476 of file gnunet-service-gns_resolver.c.

2478 {
2479  struct GNS_ResolverHandle *rx;
2480 
2481  GNUNET_assert (NULL == rh->get_handle);
2484  query,
2487  NULL, 0,
2488  &handle_dht_response, rh);
2490  rh,
2492  abs_value_us);
2495  {
2496  /* fail longest-standing DHT request */
2498  rx->dht_heap_node = NULL;
2499  GNUNET_assert (NULL != rx);
2500  fail_resolution (rx);
2501  }
2502 }
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_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.
@ GNUNET_BLOCK_TYPE_GNS_NAMERECORD
Block for storing GNS record data.
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:1114
@ 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 2514 of file gnunet-service-gns_resolver.c.

2517 {
2518  struct GNS_ResolverHandle *rh = cls;
2519 
2520  if (0 == rd_count)
2522  _ ("GNS namecache returned empty result for `%s'\n"),
2523  rh->name);
2525  rd_count,
2526  rd);
2527 }

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 2537 of file gnunet-service-gns_resolver.c.

2539 {
2540  struct GNS_ResolverHandle *rh = cls;
2541  struct AuthorityChain *ac = rh->ac_tail;
2542  const char *label = ac->label;
2543  const struct GNUNET_IDENTITY_PublicKey *auth =
2544  &ac->authority_info.gns_authority;
2545  struct GNUNET_HashCode query;
2546 
2547  GNUNET_assert (NULL != rh->namecache_qe);
2548  rh->namecache_qe = NULL;
2549  if (NULL == block)
2551  "No block found\n");
2552  else
2554  "Got block with expiration %s\n",
2556  if (((GNUNET_GNS_LO_DEFAULT == rh->options) ||
2557  ((GNUNET_GNS_LO_LOCAL_MASTER == rh->options) &&
2558  (ac != rh->ac_head))) &&
2559  ((NULL == block) ||
2562  rel_value_us)))
2563  {
2564  /* namecache knows nothing; try DHT lookup */
2566  label,
2567  &query);
2569  "Starting DHT lookup for `%s' in zone `%s' under key `%s'\n",
2570  ac->label,
2571  GNUNET_GNSRECORD_z2s (&ac->authority_info.gns_authority),
2572  GNUNET_h2s (&query));
2573  start_dht_request (rh, &query);
2574  return;
2575  }
2576 
2577  if ((NULL == block) ||
2580  rel_value_us))
2581  {
2582  /* DHT not permitted and no local result, fail */
2584  "Resolution failed for `%s' in zone %s (DHT lookup not permitted by configuration)\n",
2585  ac->label,
2586  GNUNET_GNSRECORD_z2s (&ac->authority_info.gns_authority));
2587  fail_resolution (rh);
2588  return;
2589  }
2591  "Received result from namecache for label `%s'\n",
2592  ac->label);
2593 
2594  if (GNUNET_OK !=
2596  auth,
2597  label,
2599  rh))
2600  {
2601  GNUNET_break_op (0); /* block was ill-formed */
2602  /* try DHT instead */
2604  label,
2605  &query);
2607  "Starting DHT lookup for `%s' in zone `%s' under key `%s'\n",
2608  ac->label,
2609  GNUNET_GNSRECORD_z2s (&ac->authority_info.gns_authority),
2610  GNUNET_h2s (&query));
2611  start_dht_request (rh, &query);
2612  return;
2613  }
2614 }
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 2623 of file gnunet-service-gns_resolver.c.

2624 {
2625  struct AuthorityChain *ac = rh->ac_tail;
2626  struct GNUNET_HashCode query;
2627 
2629  "Starting GNS resolution for `%s' in zone %s\n",
2630  ac->label,
2631  GNUNET_GNSRECORD_z2s (&ac->authority_info.gns_authority));
2632  GNUNET_GNSRECORD_query_from_public_key (&ac->authority_info.gns_authority,
2633  ac->label,
2634  &query);
2635  if (GNUNET_YES != disable_cache)
2636  {
2637  rh->namecache_qe
2639  &query,
2641  rh);
2642  GNUNET_assert (NULL != rh->namecache_qe);
2643  }
2644  else
2645  {
2646  start_dht_request (rh,
2647  &query);
2648  }
2649 }
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 2659 of file gnunet-service-gns_resolver.c.

2661 {
2662  struct GNS_ResolverHandle *rh = cls;
2663  struct AuthorityChain *ac = rh->ac_tail;
2664 
2665  rh->rev_check = NULL;
2666  if (GNUNET_YES != is_valid)
2667  {
2669  _ ("Zone %s was revoked, resolution fails\n"),
2670  GNUNET_GNSRECORD_z2s (&ac->authority_info.gns_authority));
2671  fail_resolution (rh);
2672  return;
2673  }
2675 }
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 2684 of file gnunet-service-gns_resolver.c.

2685 {
2686  struct AuthorityChain *ac = rh->ac_tail;
2687 
2689  "Starting revocation check for zone %s\n",
2690  GNUNET_GNSRECORD_z2s (&ac->authority_info.gns_authority));
2692  &ac->authority_info.gns_authority,
2694  rh);
2695  GNUNET_assert (NULL != rh->rev_check);
2696 }
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 2813 of file gnunet-service-gns_resolver.c.

2820 {
2821  struct GNS_ResolverHandle *rh;
2822 
2824  "Starting lookup for `%s'\n",
2825  name);
2826  rh = GNUNET_new (struct GNS_ResolverHandle);
2828  rlh_tail,
2829  rh);
2830  rh->authority_zone = *zone;
2831  rh->proc = proc;
2832  rh->proc_cls = proc_cls;
2833  rh->options = options;
2834  rh->record_type = record_type;
2835  rh->name = GNUNET_strdup (name);
2836  rh->name_resolution_pos = strlen (name);
2837  rh->loop_threshold = recursion_depth_limit;
2839  rh);
2840  return rh;
2841 }
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 2850 of file gnunet-service-gns_resolver.c.

2851 {
2852  struct DnsResult *dr;
2853  struct AuthorityChain *ac;
2854 
2856  rlh_tail,
2857  rh);
2858  if (NULL != rh->dns_request)
2859  {
2861  rh->dns_request = NULL;
2862  }
2863  while (NULL != (ac = rh->ac_head))
2864  {
2866  rh->ac_tail,
2867  ac);
2868  if (GNUNET_NO == ac->gns_authority)
2869  {
2870  struct Gns2DnsPending *gp;
2871 
2872  while (NULL != (gp = ac->authority_info.dns_authority.gp_head))
2873  {
2874  GNUNET_CONTAINER_DLL_remove (ac->authority_info.dns_authority.gp_head,
2875  ac->authority_info.dns_authority.gp_tail,
2876  gp);
2877  if (NULL != gp->rh)
2878  {
2879  /* rh->g2dc->rh is NOT in the DLL yet, so to enable us
2880  using GNS_resolver_lookup_cancel here, we need to
2881  add it first... */
2883  rlh_tail,
2884  gp->rh);
2885  GNUNET_assert (NULL == gp->rh->task_id);
2888  gp->rh);
2889  gp->rh = NULL;
2890  }
2891  if (NULL != gp->dns_rh)
2892  {
2894  gp->dns_rh = NULL;
2895  }
2896  GNUNET_free (gp);
2897  }
2898  GNUNET_DNSSTUB_stop (ac->authority_info.dns_authority.dns_handle);
2899  }
2900  GNUNET_free (ac->label);
2901  GNUNET_free (ac);
2902  }
2903  if (NULL != rh->task_id)
2904  {
2906  rh->task_id = NULL;
2907  }
2908  if (NULL != rh->get_handle)
2909  {
2911  rh->get_handle = NULL;
2912  }
2913  if (NULL != rh->dht_heap_node)
2914  {
2916  rh->dht_heap_node = NULL;
2917  }
2918  if (NULL != rh->namecache_qe)
2919  {
2921  rh->namecache_qe = NULL;
2922  }
2923  if (NULL != rh->rev_check)
2924  {
2926  rh->rev_check = NULL;
2927  }
2928  if (NULL != rh->std_resolve)
2929  {
2931  "Canceling standard DNS resolution\n");
2933  rh->std_resolve = NULL;
2934  }
2935  while (NULL != (dr = rh->dns_result_head))
2936  {
2939  dr);
2940  GNUNET_free (dr);
2941  }
2942  GNUNET_free (rh->leho);
2943  GNUNET_free (rh->name);
2944  GNUNET_free (rh);
2945 }
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 2960 of file gnunet-service-gns_resolver.c.

2964 {
2965  cfg = c;
2966  namecache_handle = nc;
2967  dht_handle = dht;
2968  dht_lookup_heap =
2970  max_allowed_background_queries = max_bg_queries;
2972  "namecache",
2973  "DISABLE");
2974  if (GNUNET_YES == disable_cache)
2976  "Namecache disabled\n");
2977 }
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 2984 of file gnunet-service-gns_resolver.c.

2985 {
2986  struct GNS_ResolverHandle *rh;
2987  struct CacheOps *co;
2988 
2989  /* abort active resolutions */
2990  while (NULL != (rh = rlh_head))
2991  {
2992  rh->proc (rh->proc_cls,
2993  0,
2994  NULL);
2996  }
2997  while (NULL != (co = co_head))
2998  {
3000  co_tail,
3001  co);
3003  GNUNET_free (co);
3004  }
3006  dht_lookup_heap = NULL;
3007  dht_handle = NULL;
3008  namecache_handle = NULL;
3009 }
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().