GNUnet 0.21.1
gnunet-service-gns_resolver.c File Reference

GNU Name System resolver logic. More...

#include "platform.h"
#include "gnunet_util_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_gns_service.h"
#include "gns.h"
#include "gnunet-service-gns.h"
#include "gnunet-service-gns_resolver.h"
#include "gnu_name_system_protocols.h"
#include "gnu_name_system_service_ports.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 int resolver_getprotobyname (const char *name)
 Function called to receive the protocol number for a service. More...
 
static int resolver_getservbyname (const char *name, const char *proto)
 Function called to receive the port number for a service. More...
 
static char * resolver_lookup_get_next_label (struct GNS_ResolverHandle *rh)
 Get the next, rightmost label from the name that we are trying to resolve, and update the resolution position accordingly. More...
 
static void transmit_lookup_dns_result (struct GNS_ResolverHandle *rh)
 Gives the cumulative result obtained to the callback and clean up the request. More...
 
static void add_dns_result (struct GNS_ResolverHandle *rh, uint64_t expiration_time, uint32_t record_type, size_t data_size, const void *data)
 Add a result from DNS to the records to be returned to the application. More...
 
static void handle_dns_result (void *cls, const struct sockaddr *addr, socklen_t addrlen)
 We had to do a DNS lookup. More...
 
static void recursive_resolution (void *cls)
 Task scheduled to continue with the resolution process. More...
 
static void start_resolver_lookup (void *cls)
 Begin the resolution process from 'name', starting with the identification of the zone specified by 'name'. More...
 
static void dns_result_parser (void *cls, const struct GNUNET_TUN_DnsHeader *dns, size_t dns_len)
 Function called with the result of a DNS resolution. More...
 
static void recursive_dns_resolution (struct GNS_ResolverHandle *rh)
 Perform recursive DNS resolution. More...
 
static void handle_gns_redirect_result (struct GNS_ResolverHandle *rh, const char *rname)
 We encountered a REDIRECT record during our resolution. More...
 
static void handle_gns_cname_result (struct GNS_ResolverHandle *rh, const char *cname)
 We encountered a CNAME record during our resolution. More...
 
static void handle_gns_resolution_result (void *cls, unsigned int rd_count, const struct GNUNET_GNSRECORD_Data *rd)
 Process records that were decrypted from a block. More...
 
static void continue_with_gns2dns (struct AuthorityChain *ac)
 We have resolved one or more of the nameservers for a GNS2DNS lookup. More...
 
static void handle_gns2dns_result (void *cls, unsigned int rd_count, const struct GNUNET_GNSRECORD_Data *rd)
 We've resolved the IP address for the DNS resolver to use after encountering a GNS2DNS record. More...
 
static void handle_gns2dns_ip (void *cls, const struct sockaddr *addr, socklen_t addrlen)
 Function called by the resolver for each address obtained from DNS. More...
 
static void recursive_redirect_resolution (struct GNS_ResolverHandle *rh, const struct GNUNET_GNSRECORD_Data *rd)
 We found a REDIRECT record, perform recursive resolution on it. More...
 
static void recursive_cname_resolution (struct GNS_ResolverHandle *rh, const struct GNUNET_GNSRECORD_Data *rd)
 We found a CNAME record, perform recursive resolution on it. More...
 
static void recursive_pkey_resolution (struct GNS_ResolverHandle *rh, const struct GNUNET_GNSRECORD_Data *rd)
 We found a PKEY record, perform recursive resolution on it. More...
 
static int recursive_gns2dns_resolution (struct GNS_ResolverHandle *rh, unsigned int rd_count, const struct GNUNET_GNSRECORD_Data *rd)
 We found one or more GNS2DNS records, perform recursive resolution on it. More...
 
static void namecache_cache_continuation (void *cls, int32_t success, const char *emsg)
 Function called once the namestore has completed the request for caching a block. More...
 
static void handle_dht_response (void *cls, struct GNUNET_TIME_Absolute exp, const struct GNUNET_HashCode *key, const struct GNUNET_PeerIdentity *trunc_peer, const struct GNUNET_DHT_PathElement *get_path, unsigned int get_path_length, const struct GNUNET_DHT_PathElement *put_path, unsigned int put_path_length, enum GNUNET_BLOCK_Type type, size_t size, const void *data)
 Iterator called on each result obtained for a DHT operation that expects a reply. More...
 
static void start_dht_request (struct GNS_ResolverHandle *rh, const struct GNUNET_HashCode *query)
 Initiate a DHT query for a set of GNS records. More...
 
static void handle_gns_namecache_resolution_result (void *cls, unsigned int rd_count, const struct GNUNET_GNSRECORD_Data *rd)
 Process a records that were decrypted from a block that we got from the namecache. More...
 
static void handle_namecache_block_response (void *cls, const struct GNUNET_GNSRECORD_Block *block)
 Process a record that was stored in the namecache. More...
 
static void recursive_gns_resolution_namecache (struct GNS_ResolverHandle *rh)
 Lookup tail of our authority chain in the namecache. More...
 
static void handle_revocation_result (void *cls, int is_valid)
 Function called with the result from a revocation check. More...
 
static void recursive_gns_resolution_revocation (struct GNS_ResolverHandle *rh)
 Perform revocation check on tail of our authority chain. More...
 
struct GNS_ResolverHandleGNS_resolver_lookup (const struct GNUNET_CRYPTO_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:484

Default DHT timeout for lookups.

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

◆ DNS_LOOKUP_TIMEOUT

#define DNS_LOOKUP_TIMEOUT
Value:

Default timeout for DNS lookups.

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

◆ DHT_GNS_REPLICATION_LEVEL

#define DHT_GNS_REPLICATION_LEVEL   10

DHT replication level.

Definition at line 71 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 490 of file gnunet-service-gns_resolver.c.

491{
492 const char *pos;
493 const char *dot;
494
495 if (NULL == strchr (name,
496 (unsigned char) '.'))
497 return GNUNET_YES;
498 if ('_' != name[0])
499 return GNUNET_NO;
500 pos = &name[1];
501 while (NULL != (dot = strchr (pos,
502 (unsigned char) '.')))
503 if ('_' != dot[1])
504 return GNUNET_NO;
505 else
506 pos = dot + 1;
507 return GNUNET_YES;
508}
static char * name
Name (label) of the records to list.
@ GNUNET_YES
@ GNUNET_NO

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

523{
524 char *ret;
525 size_t s_len = strlen (name);
526
527 if (0 != strcmp (&name[s_len - 2],
528 ".+"))
529 return name; /* did not end in ".+" */
532 "%.*s.%s",
533 (int) (s_len - 2),
534 name,
538 return ret;
539}
static int ret
Final status code.
Definition: gnunet-arm.c:94
const char * GNUNET_GNSRECORD_pkey_to_zkey(const struct GNUNET_CRYPTO_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.
union AuthorityChain::@55 authority_info
Information about the resolver authority for this label.
int gns_authority
GNUNET_YES if the authority was a GNS authority, GNUNET_NO if the authority was a DNS authority.
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 549 of file gnunet-service-gns_resolver.c.

550{
551 struct GNS_ResolverHandle *rh = cls;
552
553 rh->task_id = NULL;
555}
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 564 of file gnunet-service-gns_resolver.c.

565{
566 rh->proc (rh->proc_cls,
567 0,
568 NULL);
569 GNUNET_assert (NULL == rh->task_id);
571 rh);
572}
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:1305
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 581 of file gnunet-service-gns_resolver.c.

582{
583 struct GNS_ResolverHandle *rh = cls;
584
585 rh->task_id = NULL;
586 fail_resolution (rh);
587}
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_getprotobyname()

static int resolver_getprotobyname ( const char *  name)
static

Function called to receive the protocol number for a service.

Parameters
namename of the protocol

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

597{
598 struct protoent *pe = getprotobyname (name);
599 if (pe == NULL)
600 {
602 }
603 return pe->p_proto;
604}
uint16_t GNUNET_GNS_protocol_name_to_number(const char *name)

References GNUNET_GNS_protocol_name_to_number(), and name.

Referenced by resolver_lookup_get_next_label().

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

◆ resolver_getservbyname()

static int resolver_getservbyname ( const char *  name,
const char *  proto 
)
static

Function called to receive the port number for a service.

Parameters
namename of the service
protoname of the protocol

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

615{
616 struct servent *se = getservbyname (name, proto);
617 if (se == NULL)
618 {
620 }
621 return se->s_port;
622}
static uint8_t proto
Protocol to use.
uint16_t GNUNET_GNS_service_port_name_to_number(const char *name)

References GNUNET_GNS_service_port_name_to_number(), name, and proto.

Referenced by resolver_lookup_get_next_label().

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 resource records where the domain name includes a label starting with '_'. The syntax (see RFC 8552) here is "someLabel._Label.Name" and in this special case we include the "someLabel._Label" 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 one label beginning with an underscore. The rightmost label beginning with an underscore, is combined with the label to its right (and the "." is preserved). If the label is in the syntax of "_PORT._PROTOCOL" (e.g. "_443._tcp") we also extract the port and protocol. In this implementation, the more specific case is handled first.

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 prefix. Indicating a BOX record (_443,_tcp) Or some version of an SBOX record (HEX,_smimeacert) Which means, it is a BOX/SBOX under the empty label. leaving name_resolution_pos as is and returning empty label.

If we have labels starting with underscore with label on the right (SRV/DANE/BOX case), determine port/protocol; The format of rh->name must be "_PORT._PROTOCOL".

If we have labels starting with underscore with label on the right, copy prefix to rh->prefix; The format of rh->name must be "*._label" or "_label", where label is a string without '.'

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

645{
646 const char *rp;
647 const char *dot;
648 size_t len;
649 char *ret;
650 char *srv_name;
651 char *proto_name;
652 int protocol;
653 int service;
654
655 if (0 == rh->name_resolution_pos)
656 return NULL;
657 dot = memrchr (rh->name,
658 (int) '.',
660 if (NULL == dot)
661 {
662 /* done, this was the last one */
663 len = rh->name_resolution_pos;
664 rp = rh->name;
665 rh->name_resolution_pos = 0;
666 }
667 else if ('_' == dot[1])
668 {
677 len = strlen (GNUNET_GNS_EMPTY_LABEL_AT);
678 }
679 else
680 {
681 /* advance by one label */
682 len = rh->name_resolution_pos - (dot - rh->name) - 1;
683 rp = dot + 1;
684 rh->name_resolution_pos = dot - rh->name;
685 }
686 rh->protocol = 0;
687 rh->service = 0;
688 rh->prefix = NULL;
689 ret = GNUNET_strndup (rp, len);
694 if (('_' == rh->name[0]) &&
695 (NULL != (dot = memrchr (rh->name,
696 (int) '.',
697 rh->name_resolution_pos))) &&
698 ('_' == dot[1]) &&
699 (NULL == memrchr (rh->name,
700 (int) '.',
701 dot - rh->name)))
702 {
703 srv_name = GNUNET_strndup (&rh->name[1],
704 (dot - rh->name) - 1);
705 proto_name = GNUNET_strndup (&dot[2],
706 rh->name_resolution_pos - (dot - rh->name)
707 - 2);
708 protocol = resolver_getprotobyname (proto_name);
709 if (0 == protocol)
710 {
712 _ (
713 "Protocol `%s' unknown, skipping labels as BOX retain as SBOX.\n"),
714 proto_name);
715 GNUNET_free (proto_name);
716 GNUNET_free (srv_name);
718 rh->name_resolution_pos = 0;
719 return ret;
720 }
722 proto_name);
723 if (0 == service)
724 {
726 _ (
727 "Service `%s' unknown for protocol `%s', trying as number.\n"),
728 srv_name,
729 proto_name);
730 if (1 != sscanf (srv_name, "%u", &rh->service))
731 {
733 _ (
734 "Service `%s' not a port, skipping service labels as BOX retain as SBOX.\n"),
735 srv_name);
736 GNUNET_free (proto_name);
737 GNUNET_free (srv_name);
739 rh->name_resolution_pos = 0;
740 return ret;
741 }
742 }
743 else
744 {
745 rh->service = ntohs (service);
746 }
747 rh->protocol = protocol;
748 GNUNET_free (proto_name);
749 GNUNET_free (srv_name);
750 }
757 if ((NULL != (dot = memrchr (rh->name,
758 (int) '.',
759 rh->name_resolution_pos)) && '_' == dot[1]) ||
760 ((NULL == memrchr (rh->name,
761 (int) '.',
762 rh->name_resolution_pos)) && '_' == rh->name[0]))
763 {
765 rh->name_resolution_pos = 0;
766 }
767 return ret;
768}
#define memrchr(s, c, n)
Definition: compat.h:49
static char * rp
Relying party.
static struct GNUNET_SERVICE_Handle * service
Handle to our service instance.
static int resolver_getprotobyname(const char *name)
Function called to receive the protocol number for a service.
static int resolver_getservbyname(const char *name, const char *proto)
Function called to receive the port number for a service.
#define GNUNET_GNS_EMPTY_LABEL_AT
String we use to indicate an empty label (top-level entry in the zone).
#define GNUNET_log(kind,...)
@ GNUNET_ERROR_TYPE_WARNING
#define GNUNET_strndup(a, length)
Wrapper around GNUNET_xstrndup_.
#define _(String)
GNU gettext support macro.
Definition: platform.h:178
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.
char * prefix
For SMIMEA,OPENPGPKEY... records.
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, memrchr, GNS_ResolverHandle::name, GNS_ResolverHandle::name_resolution_pos, GNS_ResolverHandle::prefix, GNS_ResolverHandle::protocol, resolver_getprotobyname(), resolver_getservbyname(), ret, rp, service, and GNS_ResolverHandle::service.

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

Here is the call graph for this function:
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 777 of file gnunet-service-gns_resolver.c.

778{
779 struct DnsResult *pos;
780 unsigned int n;
781 unsigned int i;
782
783 n = 0;
784 for (pos = rh->dns_result_head; NULL != pos; pos = pos->next)
785 n++;
786 {
787 struct GNUNET_GNSRECORD_Data rd[n];
788
789 i = 0;
790 for (pos = rh->dns_result_head; NULL != pos; pos = pos->next)
791 {
792 rd[i].data = pos->data;
793 rd[i].data_size = pos->data_size;
794 rd[i].record_type = pos->record_type;
802 if (0 == pos->expiration_time)
803 {
805 rd[i].expiration_time = 0;
806 }
807 else
808 {
810 }
811 i++;
812 }
813 GNUNET_assert (i == n);
815 "Transmitting standard DNS result with %u records\n",
816 n);
817 rh->proc (rh->proc_cls,
818 n,
819 rd);
820 }
822}
static struct GNUNET_GNSRECORD_Data rd[50]
The record data under a single label.
@ 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
Entry for no flags / cleared flags.
@ GNUNET_ERROR_TYPE_DEBUG
#define GNUNET_GNSRECORD_TYPE_LEHO
GNS legacy hostname.
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.
size_t data_size
Number of bytes in data.
enum GNUNET_GNSRECORD_Flags flags
Flags for the record.
uint64_t expiration_time
Expiration time for the DNS record.

References GNUNET_GNSRECORD_Data::data, DnsResult::data, GNUNET_GNSRECORD_Data::data_size, DnsResult::data_size, GNS_ResolverHandle::dns_result_head, GNUNET_GNSRECORD_Data::expiration_time, DnsResult::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, rd, GNUNET_GNSRECORD_Data::record_type, and DnsResult::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 835 of file gnunet-service-gns_resolver.c.

840{
841 struct DnsResult *res;
842
843 res = GNUNET_malloc (sizeof(struct DnsResult) + data_size);
844 res->expiration_time = expiration_time;
845 res->data_size = data_size;
846 res->record_type = record_type;
847 res->data = &res[1];
848 GNUNET_memcpy (&res[1],
849 data,
850 data_size);
852 rh->dns_result_tail,
853 res);
854}
static char * data
The data to insert into the dht.
static char * res
Currently read line or NULL on EOF.
static size_t data_size
Number of bytes in data.
#define GNUNET_CONTAINER_DLL_insert(head, tail, element)
Insert an element at the head of a DLL.
#define GNUNET_memcpy(dst, src, n)
Call memcpy() but check for n being 0 first.
#define GNUNET_malloc(size)
Wrapper around malloc.
struct DnsResult * dns_result_tail
DLL of results we got from DNS.

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

Referenced by dns_result_parser(), and handle_dns_result().

Here is the caller graph for this function:

◆ handle_dns_result()

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

We had to do a DNS lookup.

Convert the result (if any) and return it.

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

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

869{
870 struct GNS_ResolverHandle *rh = cls;
871 const struct sockaddr_in *sa4;
872 const struct sockaddr_in6 *sa6;
873
874 if (NULL == addr)
875 {
876 rh->std_resolve = NULL;
878 return;
879 }
881 "Received %u bytes of DNS IP data\n",
882 addrlen);
883 switch (addr->sa_family)
884 {
885 case AF_INET:
886 sa4 = (const struct sockaddr_in *) addr;
887 add_dns_result (rh,
888 0 /* expiration time is unknown */,
890 sizeof(struct in_addr),
891 &sa4->sin_addr);
892 break;
893
894 case AF_INET6:
895 sa6 = (const struct sockaddr_in6 *) addr;
896 add_dns_result (rh,
897 0 /* expiration time is unknown */,
899 sizeof(struct in6_addr),
900 &sa6->sin6_addr);
901 break;
902
903 default:
904 GNUNET_break (0);
905 break;
906 }
907}
static void transmit_lookup_dns_result(struct GNS_ResolverHandle *rh)
Gives the cumulative result obtained to the callback and clean up the request.
static void add_dns_result(struct GNS_ResolverHandle *rh, uint64_t expiration_time, uint32_t record_type, size_t data_size, const void *data)
Add a result from DNS to the records to be returned to the application.
#define GNUNET_DNSPARSER_TYPE_A
#define GNUNET_DNSPARSER_TYPE_AAAA
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur.
struct GNUNET_RESOLVER_RequestHandle * std_resolve
Handle for standard DNS resolution, NULL if none is active.

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

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

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

◆ recursive_resolution()

static void recursive_resolution ( void *  cls)
static

Task scheduled to continue with the resolution process.

Parameters
clsthe 'struct GNS_ResolverHandle' of the resolution

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

2868{
2869 struct GNS_ResolverHandle *rh = cls;
2870
2871 rh->task_id = NULL;
2872 if (rh->loop_threshold < rh->loop_limiter++)
2873 {
2875 "Encountered unbounded recursion resolving `%s'\n",
2876 rh->name);
2877 fail_resolution (rh);
2878 return;
2879 }
2880 if (GNUNET_YES == rh->ac_tail->gns_authority)
2882 else
2884}
static void recursive_gns_resolution_revocation(struct GNS_ResolverHandle *rh)
Perform revocation check on tail of our authority chain.
static void recursive_dns_resolution(struct GNS_ResolverHandle *rh)
Perform recursive DNS resolution.
unsigned int loop_limiter
We increment the loop limiter for each step in a recursive resolution.
unsigned int loop_threshold
Maximum value of loop_limiter allowed by client.

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

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

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

◆ start_resolver_lookup()

static void start_resolver_lookup ( void *  cls)
static

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

Parameters
clsclosure with struct GNS_ResolverHandle *rh

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

2889{
2890 struct GNS_ResolverHandle *rh = cls;
2891 struct AuthorityChain *ac;
2892 struct in_addr v4;
2893 struct in6_addr v6;
2894
2895 rh->task_id = NULL;
2896 if (1 == inet_pton (AF_INET,
2897 rh->name,
2898 &v4))
2899 {
2900 /* name is IPv4 address, pretend it's an A record */
2902
2903 rd.data = &v4;
2904 rd.data_size = sizeof(v4);
2905 rd.expiration_time = UINT64_MAX;
2907 rd.flags = 0;
2908 rh->proc (rh->proc_cls,
2909 1,
2910 &rd);
2911 GNUNET_assert (NULL == rh->task_id);
2913 rh);
2914 return;
2915 }
2916 if (1 == inet_pton (AF_INET6,
2917 rh->name,
2918 &v6))
2919 {
2920 /* name is IPv6 address, pretend it's an AAAA record */
2922
2923 rd.data = &v6;
2924 rd.data_size = sizeof(v6);
2925 rd.expiration_time = UINT64_MAX;
2927 rd.flags = 0;
2928 rh->proc (rh->proc_cls,
2929 1,
2930 &rd);
2931 GNUNET_assert (NULL == rh->task_id);
2933 rh);
2934 return;
2935 }
2936
2937 ac = GNUNET_new (struct AuthorityChain);
2938 ac->rh = rh;
2940 if (NULL == ac->label)
2941 /* name was just the "TLD", so we default to label
2942 #GNUNET_GNS_EMPTY_LABEL_AT */
2947 rh->ac_tail,
2948 ac);
2950 rh);
2951}
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.
char * label
label/name corresponding to the authority
struct GNS_ResolverHandle * rh
Resolver handle this entry in the chain belongs to.
struct GNUNET_CRYPTO_PublicKey authority_zone
The top-level GNS authoritative zone to query.
struct AuthorityChain * ac_head
DLL to store the authority chain.

References GNS_ResolverHandle::ac_head, GNS_ResolverHandle::ac_tail, AuthorityChain::authority_info, GNS_ResolverHandle::authority_zone, GNUNET_GNSRECORD_Data::data, GNUNET_GNSRECORD_Data::data_size, GNUNET_GNSRECORD_Data::expiration_time, GNUNET_GNSRECORD_Data::flags, AuthorityChain::gns_authority, 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, AuthorityChain::label, GNS_ResolverHandle::name, GNS_ResolverHandle::proc, GNS_ResolverHandle::proc_cls, rd, GNUNET_GNSRECORD_Data::record_type, recursive_resolution(), resolver_lookup_get_next_label(), AuthorityChain::rh, 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 938 of file gnunet-service-gns_resolver.c.

941{
942 struct GNS_ResolverHandle *rh = cls;
944 const struct GNUNET_DNSPARSER_Record *rec;
945 unsigned int rd_count;
946
947 if (NULL == dns)
948 {
949 rh->dns_request = NULL;
951 rh->task_id = NULL;
952 fail_resolution (rh);
953 return;
954 }
955 if (rh->original_dns_id != dns->id)
956 {
957 /* DNS answer, but for another query */
958 return;
959 }
960 p = GNUNET_DNSPARSER_parse ((const char *) dns,
961 dns_len);
962 if (NULL == p)
963 {
965 _ ("Failed to parse DNS response\n"));
966 return;
967 }
968
969 /* We got a result from DNS */
971 "Received DNS response for `%s' with %u answers\n",
972 rh->ac_tail->label,
973 (unsigned int) p->num_answers);
974 if ((p->num_answers > 0) &&
975 (GNUNET_DNSPARSER_TYPE_CNAME == p->answers[0].type) &&
977 {
978 int af;
979
981 "Got CNAME `%s' from DNS for `%s'\n",
982 p->answers[0].data.hostname,
983 rh->name);
984 if (NULL != rh->std_resolve)
985 {
987 "Multiple CNAME results from DNS resolving `%s'! Not really allowed...\n",
988 rh->name);
990 }
991 GNUNET_free (rh->name);
992 rh->name = GNUNET_strdup (p->answers[0].data.hostname);
993 rh->name_resolution_pos = strlen (rh->name);
994 switch (rh->record_type)
995 {
997 af = AF_INET;
998 break;
999
1001 af = AF_INET6;
1002 break;
1003
1004 default:
1005 af = AF_UNSPEC;
1006 break;
1007 }
1008 if (NULL != rh->leho)
1009 add_dns_result (rh,
1010 GNUNET_TIME_UNIT_HOURS.rel_value_us,
1012 strlen (rh->leho),
1013 rh->leho);
1015 af,
1018 rh);
1021 rh->dns_request = NULL;
1022 return;
1023 }
1024
1025 /* convert from (parsed) DNS to (binary) GNS format! */
1026 rd_count = p->num_answers + p->num_authority_records
1027 + p->num_additional_records;
1028 {
1029 struct GNUNET_GNSRECORD_Data rd[rd_count + 1]; /* +1 for LEHO */
1030 int skip;
1031 char buf[UINT16_MAX];
1032 size_t buf_off;
1033 size_t buf_start;
1034
1035 buf_off = 0;
1036 skip = 0;
1037 memset (rd,
1038 0,
1039 sizeof(rd));
1040 for (unsigned int i = 0; i < rd_count; i++)
1041 {
1042 if (i < p->num_answers)
1043 rec = &p->answers[i];
1044 else if (i < p->num_answers + p->num_authority_records)
1045 rec = &p->authority_records[i - p->num_answers];
1046 else
1047 rec = &p->additional_records[i - p->num_answers
1048 - p->num_authority_records];
1049 /* As we copied the full DNS name to 'rh->ac_tail->label', this
1050 should be the correct check to see if this record is actually
1051 a record for our label... */
1052 if (0 != strcmp (rec->name,
1053 rh->ac_tail->label))
1054 {
1056 "Dropping record `%s', does not match desired name `%s'\n",
1057 rec->name,
1058 rh->ac_tail->label);
1059 skip++;
1060 continue;
1061 }
1062 rd[i - skip].record_type = rec->type;
1064 switch (rec->type)
1065 {
1067 if (rec->data.raw.data_len != sizeof(struct in_addr))
1068 {
1069 GNUNET_break_op (0);
1070 skip++;
1071 continue;
1072 }
1073 rd[i - skip].data_size = rec->data.raw.data_len;
1074 rd[i - skip].data = rec->data.raw.data;
1075 break;
1076
1078 if (rec->data.raw.data_len != sizeof(struct in6_addr))
1079 {
1080 GNUNET_break_op (0);
1081 skip++;
1082 continue;
1083 }
1084 rd[i - skip].data_size = rec->data.raw.data_len;
1085 rd[i - skip].data = rec->data.raw.data;
1086 break;
1087
1091 buf_start = buf_off;
1092 if (GNUNET_OK !=
1094 sizeof(buf),
1095 &buf_off,
1096 rec->data.hostname))
1097 {
1098 GNUNET_break (0);
1099 skip++;
1100 continue;
1101 }
1102 rd[i - skip].data_size = buf_off - buf_start;
1103 rd[i - skip].data = &buf[buf_start];
1104 break;
1105
1107 buf_start = buf_off;
1108 if (GNUNET_OK !=
1110 sizeof(buf),
1111 &buf_off,
1112 rec->data.soa))
1113 {
1114 GNUNET_break (0);
1115 skip++;
1116 continue;
1117 }
1118 rd[i - skip].data_size = buf_off - buf_start;
1119 rd[i - skip].data = &buf[buf_start];
1120 break;
1121
1123 buf_start = buf_off;
1124 if (GNUNET_OK !=
1126 sizeof(buf),
1127 &buf_off,
1128 rec->data.mx))
1129 {
1130 GNUNET_break (0);
1131 skip++;
1132 continue;
1133 }
1134 rd[i - skip].data_size = buf_off - buf_start;
1135 rd[i - skip].data = &buf[buf_start];
1136 break;
1137
1139 buf_start = buf_off;
1140 if (GNUNET_OK !=
1142 sizeof(buf),
1143 &buf_off,
1144 rec->data.srv))
1145 {
1146 GNUNET_break (0);
1147 skip++;
1148 continue;
1149 }
1150 rd[i - skip].data_size = buf_off - buf_start;
1151 rd[i - skip].data = &buf[buf_start];
1152 break;
1153
1155 buf_start = buf_off;
1156 if (GNUNET_OK !=
1158 sizeof(buf),
1159 &buf_off,
1160 rec->data.uri))
1161 {
1162 GNUNET_break (0);
1163 skip++;
1164 continue;
1165 }
1166 rd[i - skip].data_size = buf_off - buf_start;
1167 rd[i - skip].data = &buf[buf_start];
1168 break;
1169
1170 default:
1172 _ ("Skipping record of unsupported type %d\n"),
1173 rec->type);
1174 skip++;
1175 continue;
1176 }
1177 } /* end of for all records in answer */
1178 if (NULL != rh->leho)
1179 {
1183 rd[rd_count - skip].expiration_time = GNUNET_TIME_UNIT_HOURS.rel_value_us;
1184 rd[rd_count - skip].data = rh->leho;
1185 rd[rd_count - skip].data_size = strlen (rh->leho);
1186 skip--; /* skip one LESS */
1188 "Adding LEHO %s\n",
1189 rh->leho);
1190 }
1192 "Returning DNS response for `%s' with %u answers\n",
1193 rh->ac_tail->label,
1194 (unsigned int) (rd_count - skip));
1195 rh->proc (rh->proc_cls,
1196 rd_count - skip,
1197 rd);
1199 rh->dns_request = NULL;
1200 }
1202 if (NULL != rh->task_id)
1203 GNUNET_SCHEDULER_cancel (rh->task_id); /* should be timeout task */
1205 rh);
1206}
static unsigned int rd_count
Number of records for currently parsed set.
#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 struct GNUNET_OS_Process * p
Helper process we started.
Definition: gnunet-uri.c:38
#define GNUNET_DNSPARSER_TYPE_URI
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:982
void GNUNET_DNSPARSER_free_packet(struct GNUNET_DNSPARSER_Packet *p)
Free memory taken by a packet.
Definition: dnsparser.c:947
#define GNUNET_DNSPARSER_TYPE_SRV
#define GNUNET_DNSPARSER_TYPE_SOA
#define GNUNET_DNSPARSER_TYPE_PTR
#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:1172
#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:1096
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:1213
int GNUNET_DNSPARSER_builder_add_uri(char *dst, size_t dst_len, size_t *off, const struct GNUNET_DNSPARSER_UriRecord *uri)
Add an URI record to the UDP packet at the given location.
Definition: dnsparser.c:1249
#define GNUNET_DNSPARSER_TYPE_MX
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:727
void GNUNET_DNSSTUB_resolve_cancel(struct GNUNET_DNSSTUB_RequestSocket *rs)
Cancel DNS resolution.
Definition: dnsstub.c:562
@ GNUNET_OK
#define GNUNET_break_op(cond)
Use this for assertion violations caused by other peers (i.e.
@ GNUNET_ERROR_TYPE_INFO
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:940
void GNUNET_RESOLVER_request_cancel(struct GNUNET_RESOLVER_RequestHandle *rh)
Cancel a request that is still pending with the resolver.
void * GNUNET_SCHEDULER_cancel(struct GNUNET_SCHEDULER_Task *task)
Cancel the task with the specified identifier.
Definition: scheduler.c:981
#define GNUNET_TIME_UNIT_HOURS
One hour.
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?
char * name
Name of the record that the query is for (0-terminated).
struct GNUNET_DNSPARSER_RawRecord raw
Raw data for all other types.
union GNUNET_DNSPARSER_Record::@20 data
Payload of the record (which one of these is valid depends on the 'type').
struct GNUNET_DNSPARSER_UriRecord * uri
URI data for URI records.
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(), 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_builder_add_uri(), 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_DNSPARSER_TYPE_URI, 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, GNUNET_DNSPARSER_Record::name, GNS_ResolverHandle::name, GNS_ResolverHandle::name_resolution_pos, GNS_ResolverHandle::original_dns_id, p, GNS_ResolverHandle::proc, GNS_ResolverHandle::proc_cls, GNUNET_DNSPARSER_Record::raw, rd, rd_count, GNUNET_GNSRECORD_Data::record_type, GNS_ResolverHandle::record_type, GNUNET_DNSPARSER_Record::soa, GNUNET_DNSPARSER_Record::srv, GNS_ResolverHandle::std_resolve, GNS_ResolverHandle::task_id, GNUNET_DNSPARSER_Record::type, and GNUNET_DNSPARSER_Record::uri.

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

1219{
1220 struct AuthorityChain *ac;
1221 struct GNUNET_DNSPARSER_Query *query;
1222 struct GNUNET_DNSPARSER_Packet *p;
1223 char *dns_request;
1224 size_t dns_request_length;
1225 int ret;
1226
1227 ac = rh->ac_tail;
1228 GNUNET_assert (NULL != ac);
1230 "Starting DNS lookup for `%s'\n",
1231 ac->label);
1233 query = GNUNET_new (struct GNUNET_DNSPARSER_Query);
1234 query->name = GNUNET_strdup (ac->label);
1235 query->type = rh->record_type;
1238 p->queries = query;
1239 p->num_queries = 1;
1241 UINT16_MAX);
1242 p->flags.opcode = GNUNET_TUN_DNS_OPCODE_QUERY;
1243 p->flags.recursion_desired = 1;
1245 1024,
1246 &dns_request,
1247 &dns_request_length);
1248 if (GNUNET_OK != ret)
1249 {
1250 GNUNET_break (0);
1251 rh->proc (rh->proc_cls,
1252 0,
1253 NULL);
1254 GNUNET_assert (NULL == rh->task_id);
1256 rh);
1257 }
1258 else
1259 {
1260 rh->original_dns_id = p->id;
1262 GNUNET_assert (NULL == rh->dns_request);
1263 rh->leho = GNUNET_strdup (ac->label);
1266 dns_request,
1267 dns_request_length,
1269 rh);
1272 rh);
1273 }
1274 if (GNUNET_SYSERR != ret)
1275 GNUNET_free (dns_request);
1277}
static void dns_result_parser(void *cls, const struct GNUNET_TUN_DnsHeader *dns, size_t dns_len)
Function called with the result of a DNS resolution.
static void timeout_resolution(void *cls)
Function called when a resolution times out.
uint32_t GNUNET_CRYPTO_random_u32(enum GNUNET_CRYPTO_Quality mode, uint32_t i)
Produce a random value.
@ GNUNET_CRYPTO_QUALITY_NONCE
Randomness for IVs etc.
int GNUNET_DNSPARSER_pack(const struct GNUNET_DNSPARSER_Packet *p, uint16_t max, char **buf, size_t *buf_length)
Given a DNS packet p, generate the corresponding UDP payload.
Definition: dnsparser.c:1392
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:526
@ GNUNET_SYSERR
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:1278
#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
struct GNUNET_DNSSTUB_Context * dns_handle
Handle to perform DNS lookups with this authority (in GNS2DNS handling).
struct AuthorityChain::@55::@56 dns_authority
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 GNS_ResolverHandle::ac_tail, AuthorityChain::authority_info, AuthorityChain::dns_authority, AuthorityChain::dns_handle, DNS_LOOKUP_TIMEOUT, GNS_ResolverHandle::dns_request, dns_result_parser(), GNUNET_DNSPARSER_Query::dns_traffic_class, AuthorityChain::gns_authority, 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, AuthorityChain::label, 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 1289 of file gnunet-service-gns_resolver.c.

1291{
1292 size_t nlen;
1293 char *res;
1294 const char *tld;
1295 struct AuthorityChain *ac;
1296 int af;
1297 struct GNUNET_CRYPTO_PublicKey zone;
1298
1300 "Handling GNS REDIRECT result `%s'\n",
1301 rname);
1302 nlen = strlen (rname);
1303 tld = GNS_get_tld (rname);
1304 if (0 == strcmp ("+", tld))
1305 {
1306 /* REDIRECT resolution continues relative to current domain */
1307 if (0 == rh->name_resolution_pos)
1308 {
1309 res = GNUNET_strndup (rname, nlen - 2);
1310 rh->name_resolution_pos = nlen - 2;
1311 }
1312 else
1313 {
1315 "%.*s.%.*s",
1316 (int) rh->name_resolution_pos,
1317 rh->name,
1318 (int) (nlen - 2),
1319 rname);
1320 rh->name_resolution_pos = strlen (res);
1321 }
1322 GNUNET_free (rh->name);
1323 rh->name = res;
1324 ac = GNUNET_new (struct AuthorityChain);
1325 ac->rh = rh;
1330 /* add AC to tail */
1332 rh->ac_tail,
1333 ac);
1335 rh);
1336 return;
1337 }
1338 if (GNUNET_OK == GNUNET_GNSRECORD_zkey_to_pkey (tld, &zone))
1339 {
1340 /* REDIRECT resolution continues relative to current domain */
1341 if (0 == rh->name_resolution_pos)
1342 {
1344 "%.*s",
1345 (int) (strlen (rname) - (strlen (tld) + 1)),
1346 rname);
1347 }
1348 else
1349 {
1351 "%.*s.%.*s",
1352 (int) rh->name_resolution_pos,
1353 rh->name,
1354 (int) (strlen (rname) - (strlen (tld) + 1)),
1355 rname);
1356 }
1357 rh->name_resolution_pos = strlen (res);
1358 GNUNET_free (rh->name);
1359 rh->name = res;
1360 ac = GNUNET_new (struct AuthorityChain);
1361 ac->rh = rh;
1363 ac->authority_info.gns_authority = zone;
1365 /* add AC to tail */
1367 rh->ac_tail,
1368 ac);
1370 rh);
1371 return;
1372 }
1373
1375 "Got REDIRECT `%s' from GNS for `%s'\n",
1376 rname,
1377 rh->name);
1378 if (NULL != rh->std_resolve)
1379 {
1381 "Multiple REDIRECT results from GNS resolving `%s'! Not really allowed...\n",
1382 rh->name);
1384 }
1385 /* name is absolute, go to DNS */
1386 GNUNET_free (rh->name);
1387 rh->name = GNUNET_strdup (rname);
1388 rh->name_resolution_pos = strlen (rh->name);
1389 switch (rh->record_type)
1390 {
1392 af = AF_INET;
1393 break;
1394
1396 af = AF_INET6;
1397 break;
1398
1399 default:
1400 af = AF_UNSPEC;
1401 break;
1402 }
1404 "Doing standard DNS lookup for `%s'\n",
1405 rh->name);
1406
1408 af,
1411 rh);
1412}
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_CRYPTO_PublicKey *pkey)
Convert an absolute domain name to the respective public key.
An identity key as per LSD0001.

References 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(), AuthorityChain::label, GNS_ResolverHandle::name, GNS_ResolverHandle::name_resolution_pos, GNS_ResolverHandle::record_type, recursive_resolution(), res, resolver_lookup_get_next_label(), AuthorityChain::rh, GNS_ResolverHandle::std_resolve, and GNS_ResolverHandle::task_id.

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

1426{
1427 int af;
1428
1429 GNUNET_free (rh->name);
1430 rh->name = GNUNET_strdup (cname);
1431 rh->name_resolution_pos = strlen (rh->name);
1432 switch (rh->record_type)
1433 {
1435 af = AF_INET;
1436 break;
1437
1439 af = AF_INET6;
1440 break;
1441
1442 default:
1443 af = AF_UNSPEC;
1444 break;
1445 }
1447 "Doing standard DNS lookup for `%s'\n",
1448 rh->name);
1449
1451 af,
1454 rh);
1455}

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

Referenced by handle_gns_resolution_result(), and recursive_cname_resolution().

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

◆ handle_gns_resolution_result()

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

Process records that were decrypted from a block.

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

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

1978{
1979 struct GNS_ResolverHandle *rh = cls;
1980 char *cname;
1981 char scratch[UINT16_MAX];
1982 size_t scratch_off;
1983 size_t scratch_start;
1984 size_t off;
1985 struct GNUNET_GNSRECORD_Data rd_new[rd_count];
1986 unsigned int rd_off;
1987
1989 "Resolution succeeded for `%s' in zone %s, got %u records\n",
1990 rh->ac_tail->label,
1992 rd_count);
1993 if (0 == rd_count)
1994 {
1996 _ ("GNS lookup failed (zero records found for `%s')\n"),
1997 rh->name);
1998 fail_resolution (rh);
1999 return;
2000 }
2001
2002 if (0 == rh->name_resolution_pos)
2003 {
2004 /* top-level match, are we done yet? */
2005 if ((rd_count > 0) &&
2008 {
2009 off = 0;
2011 rd[0].data_size,
2012 &off);
2013 if ((NULL == cname) ||
2014 (off != rd[0].data_size))
2015 {
2016 GNUNET_break_op (0);
2017 GNUNET_free (cname);
2018 fail_resolution (rh);
2019 return;
2020 }
2022 cname);
2023 GNUNET_free (cname);
2024 return;
2025 }
2026 if ((rd_count > 0) &&
2029 {
2031 rd[0].data);
2032 return;
2033 }
2034
2035
2036 /* If A/AAAA was requested,
2037 * but we got a GNS2DNS record */
2038 if ((GNUNET_DNSPARSER_TYPE_A == rh->record_type) ||
2040 {
2041 for (unsigned int i = 0; i < rd_count; i++)
2042 {
2043 switch (rd[i].record_type)
2044 {
2046 {
2047 /* delegation to DNS */
2049 "Found GNS2DNS record, delegating to DNS!\n");
2050 if (GNUNET_OK ==
2052 rd_count,
2053 rd))
2054 return;
2055 else
2056 goto fail;
2057 }
2058
2059 default:
2060 break;
2061 } /* end: switch */
2062 } /* end: for rd */
2063 } /* end: name_resolution_pos */
2064 /* convert relative names in record values to absolute names,
2065 using 'scratch' array for memory allocations */
2066 scratch_off = 0;
2067 rd_off = 0;
2068 for (unsigned int i = 0; i < rd_count; i++)
2069 {
2070 GNUNET_assert (rd_off <= i);
2071 if ((((0 != rh->protocol) &&
2072 (0 != rh->service)) || (NULL != rh->prefix)) &&
2077 continue;
2078 /* we _only_ care about boxed records */
2079
2080 GNUNET_assert (rd_off < rd_count);
2081 rd_new[rd_off] = rd[i];
2082 /* Check if the embedded name(s) end in "+", and if so,
2083 replace the "+" with the zone at "ac_tail", changing the name
2084 to a ".ZONEKEY". The name is allocated on the 'scratch' array,
2085 so we can free it afterwards. */
2086 switch (rd[i].record_type)
2087 {
2089 {
2090 char *rname;
2091 rname = GNUNET_strndup (rd[i].data, rd[i].data_size);
2092 rname = translate_dot_plus (rh, rname);
2093 GNUNET_break (NULL != rname);
2094 scratch_start = scratch_off;
2095 memcpy (&scratch[scratch_start], rname, strlen (rname) + 1);
2096 scratch_off += strlen (rname) + 1;
2097 GNUNET_assert (rd_off < rd_count);
2098 rd_new[rd_off].data = &scratch[scratch_start];
2099 rd_new[rd_off].data_size = scratch_off - scratch_start;
2100 rd_off++;
2101 GNUNET_free (rname);
2102 }
2103 break;
2104
2106 {
2107 char *cname;
2108
2109 off = 0;
2111 rd[i].data_size,
2112 &off);
2113 if ((NULL == cname) ||
2114 (off != rd[i].data_size))
2115 {
2116 GNUNET_break_op (0); /* record not well-formed */
2117 }
2118 else
2119 {
2120 cname = translate_dot_plus (rh, cname);
2121 GNUNET_break (NULL != cname);
2122 scratch_start = scratch_off;
2123 if (GNUNET_OK !=
2125 sizeof(scratch),
2126 &scratch_off,
2127 cname))
2128 {
2129 GNUNET_break (0);
2130 }
2131 else
2132 {
2133 GNUNET_assert (rd_off < rd_count);
2134 rd_new[rd_off].data = &scratch[scratch_start];
2135 rd_new[rd_off].data_size = scratch_off - scratch_start;
2136 rd_off++;
2137 }
2138 }
2139 GNUNET_free (cname);
2140 }
2141 break;
2142
2144 {
2145 struct GNUNET_DNSPARSER_SoaRecord *soa;
2146
2147 off = 0;
2149 rd[i].data_size,
2150 &off);
2151 if ((NULL == soa) ||
2152 (off != rd[i].data_size))
2153 {
2154 GNUNET_break_op (0); /* record not well-formed */
2155 }
2156 else
2157 {
2158 soa->mname = translate_dot_plus (rh, soa->mname);
2159 soa->rname = translate_dot_plus (rh, soa->rname);
2160 scratch_start = scratch_off;
2161 if (GNUNET_OK !=
2163 sizeof(scratch),
2164 &scratch_off,
2165 soa))
2166 {
2167 GNUNET_break (0);
2168 }
2169 else
2170 {
2171 GNUNET_assert (rd_off < rd_count);
2172 rd_new[rd_off].data = &scratch[scratch_start];
2173 rd_new[rd_off].data_size = scratch_off - scratch_start;
2174 rd_off++;
2175 }
2176 }
2177 if (NULL != soa)
2179 }
2180 break;
2181
2183 {
2184 struct GNUNET_DNSPARSER_MxRecord *mx;
2185
2186 off = 0;
2188 rd[i].data_size,
2189 &off);
2190 if ((NULL == mx) ||
2191 (off != rd[i].data_size))
2192 {
2193 GNUNET_break_op (0); /* record not well-formed */
2194 }
2195 else
2196 {
2197 mx->mxhost = translate_dot_plus (rh, mx->mxhost);
2198 scratch_start = scratch_off;
2199 if (GNUNET_OK !=
2201 sizeof(scratch),
2202 &scratch_off,
2203 mx))
2204 {
2205 GNUNET_break (0);
2206 }
2207 else
2208 {
2209 GNUNET_assert (rd_off < rd_count);
2210 rd_new[rd_off].data = &scratch[scratch_start];
2211 rd_new[rd_off].data_size = scratch_off - scratch_start;
2212 rd_off++;
2213 }
2214 }
2215 if (NULL != mx)
2217 }
2218 break;
2219
2221 {
2222 struct GNUNET_DNSPARSER_SrvRecord *srv;
2223
2224 off = 0;
2226 rd[i].data_size,
2227 &off);
2228 if ((NULL == srv) ||
2229 (off != rd[i].data_size))
2230 {
2231 GNUNET_break_op (0); /* record not well-formed */
2232 }
2233 else
2234 {
2235 srv->target = translate_dot_plus (rh, srv->target);
2236 scratch_start = scratch_off;
2237 if (GNUNET_OK !=
2239 sizeof(scratch),
2240 &scratch_off,
2241 srv))
2242 {
2243 GNUNET_break (0);
2244 }
2245 else
2246 {
2247 GNUNET_assert (rd_off < rd_count);
2248 rd_new[rd_off].data = &scratch[scratch_start];
2249 rd_new[rd_off].data_size = scratch_off - scratch_start;
2250 rd_off++;
2251 }
2252 }
2253 if (NULL != srv)
2255 }
2256 break;
2257
2259 {
2261
2262 off = 0;
2264 rd[i].data_size,
2265 &off);
2266 if ((NULL == uri) ||
2267 (off != rd[i].data_size))
2268 {
2270 _ ("Failed to deserialize URI record with target\n"));
2271 GNUNET_break_op (0); /* record not well-formed */
2272 }
2273 else
2274 {
2275 scratch_start = scratch_off;
2276 if (GNUNET_OK !=
2278 sizeof(scratch),
2279 &scratch_off,
2280 uri))
2281 {
2282 GNUNET_break (0);
2283 }
2284 else
2285 {
2286 GNUNET_assert (rd_off < rd_count);
2287 rd_new[rd_off].data = &scratch[scratch_start];
2288 rd_new[rd_off].data_size = scratch_off - scratch_start;
2289 rd_off++;
2290 }
2291 }
2292 if (NULL != uri)
2294 }
2295 break;
2296
2299 {
2301 if (rd[i].data_size < sizeof(uint32_t))
2302 {
2303 GNUNET_break_op (0);
2304 break;
2305 }
2306 if (GNUNET_OK !=
2308 rd[i].data_size,
2309 rd[i].record_type,
2310 &pubkey))
2311 {
2312 GNUNET_break_op (0);
2313 break;
2314 }
2315 rd_off++;
2316 if (rd[i].record_type != rh->record_type)
2317 {
2318 /* try to resolve "@" */
2319 struct AuthorityChain *ac;
2320
2321 ac = GNUNET_new (struct AuthorityChain);
2322 ac->rh = rh;
2327 rh->ac_tail,
2328 ac);
2330 rh);
2331 return;
2332 }
2333 }
2334 break;
2335
2337 {
2338 /* delegation to DNS */
2340 {
2341 rd_off++;
2342 break; /* do not follow to DNS, we wanted the GNS2DNS record! */
2343 }
2345 "Found GNS2DNS record, delegating to DNS!\n");
2346 if (GNUNET_OK ==
2348 rd_count,
2349 rd))
2350 return;
2351 else
2352 goto fail;
2353 }
2354
2356 {
2357 /* unbox SRV/TLSA records if a specific one was requested */
2358 if ((0 != rh->protocol) &&
2359 (0 != rh->service) &&
2360 (rd[i].data_size >= sizeof(struct GNUNET_GNSRECORD_BoxRecord)))
2361 {
2362 const struct GNUNET_GNSRECORD_BoxRecord *box;
2363
2364 box = rd[i].data;
2366 "Got BOX record, checking if parameters match... %u/%u vs %u/%u\n",
2367 ntohs (box->protocol), ntohs (box->service),
2368 rh->protocol, rh->service);
2369 if ((ntohs (box->protocol) == rh->protocol) &&
2370 (ntohs (box->service) == rh->service))
2371 {
2372 /* Box matches, unbox! */
2373 GNUNET_assert (rd_off < rd_count);
2374 rd_new[rd_off].record_type = ntohl (box->record_type);
2375 rd_new[rd_off].data_size -= sizeof(struct
2377 rd_new[rd_off].data = &box[1];
2378 rd_off++;
2379 }
2380 }
2381 else
2382 {
2383 /* no specific protocol/service specified, preserve all BOX
2384 records (for modern, GNS-enabled applications) */
2385 rd_off++;
2386 }
2387 break;
2388 }
2390 {
2391 /* unbox SBOX records if a specific one was requested */
2392 if ((rh->prefix != NULL) &&
2393 (rd[i].data_size >= sizeof(struct GNUNET_GNSRECORD_SBoxRecord)))
2394 {
2395 const struct GNUNET_GNSRECORD_SBoxRecord *box;
2396
2397 box = rd[i].data;
2398 const char *prefix = rd[i].data + sizeof(struct
2400 size_t prefix_len = strnlen (prefix, rd[i].data_size - sizeof(struct
2402 + 1;
2403 if (prefix_len - 1 >= rd[i].data_size - sizeof(struct
2405 {
2407 "SBOX record with invalid prefix length, maybe not null-terminated\n");
2408 continue;
2409 }
2411 "Got SBOX record, checking if prefixes match... %s vs %s\n",
2412 prefix, rh->prefix);
2413 if (strcmp (rh->prefix, prefix) == 0)
2414 {
2415 /* Box matches, unbox! */
2416 GNUNET_assert (rd_off < rd_count);
2417 rd_new[rd_off].record_type = ntohl (box->record_type);
2418 rd_new[rd_off].data_size -= sizeof(struct
2420 + prefix_len;
2421 rd_new[rd_off].data = rd[i].data
2422 + sizeof(struct GNUNET_GNSRECORD_SBoxRecord)
2423 + prefix_len;
2424 rd_off++;
2425 }
2426 }
2427 else
2428 {
2430 _ (
2431 "GNS no specific protocol/service specified, preserve all SBOX `%s')\n"),
2432 rh->name);
2433 /* no specific protocol/service specified, preserve all SBOX
2434 records (for modern, GNS-enabled applications) */
2435 rd_off++;
2436 }
2437 break;
2438 }
2439 default:
2440 rd_off++;
2441 break;
2442 } /* end: switch */
2443 } /* end: for rd_count */
2444
2445 GNUNET_free (rh->prefix);
2446 rh->prefix = NULL;
2447
2448 /* yes, we are done, return result */
2450 "Returning GNS response for `%s' with %u answers\n",
2451 rh->ac_tail->label,
2452 rd_off);
2453 rh->proc (rh->proc_cls,
2454 rd_off,
2455 rd_new);
2457 rh);
2458 return;
2459 }
2460
2461 switch (rd[0].record_type)
2462 {
2464 GNUNET_break_op (1 == rd_count); /* REDIRECT should be unique */
2466 &rd[0]);
2467 return;
2468
2470 GNUNET_break_op (1 == rd_count); /* CNAME should be unique */
2472 &rd[0]);
2473 return;
2474
2477 GNUNET_break_op (1 == rd_count); /* PKEY should be unique */
2479 &rd[0]);
2480 return;
2481
2483 if (GNUNET_OK ==
2485 rd_count,
2486 rd))
2487 return;
2488 break;
2489 default:
2491 return;
2493 _ ("Unable to process critical delegation record\n"));
2494 break;
2495 }
2496fail:
2498 _ ("GNS lookup recursion failed (no delegation record found)\n"));
2499 fail_resolution (rh);
2500}
static size_t strnlen(const char *s, size_t n)
static int prefix
If printing the value of PREFIX has been requested.
Definition: gnunet-config.c:59
static struct GNUNET_CRYPTO_PublicKey pubkey
Public key of the zone to look in.
static struct GNUNET_FS_Uri * uri
Value of URI provided on command-line (when not publishing a file but just creating UBlocks to refer ...
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 char * translate_dot_plus(struct GNS_ResolverHandle *rh, char *name)
Expands a name ending in .
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 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_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:455
void GNUNET_DNSPARSER_free_srv(struct GNUNET_DNSPARSER_SrvRecord *srv)
Free SRV information record.
Definition: dnsparser.c:139
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:410
void GNUNET_DNSPARSER_free_uri(struct GNUNET_DNSPARSER_UriRecord *uri)
Free URI information record.
Definition: dnsparser.c:154
struct GNUNET_DNSPARSER_UriRecord * GNUNET_DNSPARSER_parse_uri(const char *udp_payload, size_t udp_payload_length, size_t *off)
Parse a DNS URI record.
Definition: dnsparser.c:537
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:496
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:353
void GNUNET_DNSPARSER_free_soa(struct GNUNET_DNSPARSER_SoaRecord *soa)
Free SOA information record.
Definition: dnsparser.c:108
void GNUNET_DNSPARSER_free_mx(struct GNUNET_DNSPARSER_MxRecord *mx)
Free MX information record.
Definition: dnsparser.c:169
const char * GNUNET_GNSRECORD_z2s(const struct GNUNET_CRYPTO_PublicKey *z)
Convert a zone to a string (for printing debug messages).
enum GNUNET_GenericReturnValue GNUNET_GNSRECORD_identity_from_data(const char *data, size_t data_size, uint32_t type, struct GNUNET_CRYPTO_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:247
@ GNUNET_ERROR_TYPE_ERROR
#define GNUNET_GNSRECORD_TYPE_BOX
Box record.
#define GNUNET_GNSRECORD_TYPE_GNS2DNS
Delegation to DNS.
#define GNUNET_GNSRECORD_TYPE_REDIRECT
Redirection record.
#define GNUNET_GNSRECORD_TYPE_SBOX
SBox record.
#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
GNS zone delegation (EDKEY)
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.
Information from URI records (RFC 7553).
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.).
Record type used to box up SMIMEA records.
uint32_t record_type
GNS record type of the boxed record.

References _, GNS_ResolverHandle::ac_head, GNS_ResolverHandle::ac_tail, AuthorityChain::authority_info, data, GNUNET_GNSRECORD_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_builder_add_uri(), GNUNET_DNSPARSER_free_mx(), GNUNET_DNSPARSER_free_soa(), GNUNET_DNSPARSER_free_srv(), GNUNET_DNSPARSER_free_uri(), GNUNET_DNSPARSER_parse_mx(), GNUNET_DNSPARSER_parse_name(), GNUNET_DNSPARSER_parse_soa(), GNUNET_DNSPARSER_parse_srv(), GNUNET_DNSPARSER_parse_uri(), 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_DNSPARSER_TYPE_URI, GNUNET_ERROR_TYPE_DEBUG, GNUNET_ERROR_TYPE_ERROR, 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_TYPE_SBOX, 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, prefix, GNS_ResolverHandle::prefix, GNS_ResolverHandle::proc, GNS_ResolverHandle::proc_cls, GNUNET_GNSRECORD_BoxRecord::protocol, GNS_ResolverHandle::protocol, pubkey, rd, rd_count, GNUNET_GNSRECORD_Data::record_type, GNUNET_GNSRECORD_BoxRecord::record_type, GNUNET_GNSRECORD_SBoxRecord::record_type, GNS_ResolverHandle::record_type, recursive_cname_resolution(), recursive_gns2dns_resolution(), recursive_pkey_resolution(), recursive_redirect_resolution(), recursive_resolution(), AuthorityChain::rh, GNUNET_DNSPARSER_SoaRecord::rname, GNUNET_GNSRECORD_BoxRecord::service, GNS_ResolverHandle::service, strnlen(), GNUNET_DNSPARSER_SrvRecord::target, GNS_ResolverHandle::task_id, translate_dot_plus(), and uri.

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

1480{
1481 struct GNS_ResolverHandle *rh = ac->rh;
1482
1483 if ((NULL != ac->authority_info.dns_authority.gp_head) &&
1485 return; /* more pending and none found yet */
1487 {
1489 "Failed to resolve DNS server for `%s' in GNS2DNS resolution\n",
1491 fail_resolution (rh);
1492 return;
1493 }
1495 return; /* already running, do not launch again! */
1496 /* recurse */
1499 "Will continue resolution using DNS to resolve `%s'\n",
1500 ac->label);
1501 GNUNET_assert (NULL == rh->task_id);
1503 rh);
1504}
int found
Did we succeed in getting an IP address for any of the DNS servers listed? Once we do,...
char name[GNUNET_DNSPARSER_MAX_NAME_LENGTH+1]
Domain of the DNS resolver that is the authority.
int launched
Did we start the recursive resolution via DNS?
struct Gns2DnsPending * gp_head
List of resolutions of the 'ip' of the name server that are still pending.

References AuthorityChain::authority_info, AuthorityChain::dns_authority, fail_resolution(), AuthorityChain::found, GNUNET_assert, GNUNET_ERROR_TYPE_DEBUG, GNUNET_ERROR_TYPE_INFO, GNUNET_log, GNUNET_NO, GNUNET_SCHEDULER_add_now(), GNUNET_YES, AuthorityChain::gp_head, AuthorityChain::label, AuthorityChain::launched, AuthorityChain::name, recursive_resolution(), AuthorityChain::rh, 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 1516 of file gnunet-service-gns_resolver.c.

1519{
1520 struct Gns2DnsPending *gp = cls;
1521 struct AuthorityChain *ac = gp->ac;
1522
1525 gp);
1526 /* enable cleanup of 'rh' handle that automatically comes after we return,
1527 and which expects 'rh' to be in the #rlh_head DLL. */
1528 if (NULL != gp->rh)
1529 {
1531 rlh_tail,
1532 gp->rh);
1533 gp->rh = NULL;
1534 }
1535 GNUNET_free (gp);
1537 "Received %u results for IP address of DNS server for GNS2DNS transition\n",
1538 rd_count);
1539 /* find suitable A/AAAA record */
1540 for (unsigned int j = 0; j < rd_count; j++)
1541 {
1542 switch (rd[j].record_type)
1543 {
1545 {
1546 struct sockaddr_in v4;
1547
1548 if (sizeof(struct in_addr) != rd[j].data_size)
1549 {
1550 GNUNET_break_op (0);
1551 continue;
1552 }
1553 memset (&v4,
1554 0,
1555 sizeof(v4));
1556 v4.sin_family = AF_INET;
1557 v4.sin_port = htons (53);
1558#if HAVE_SOCKADDR_IN_SIN_LEN
1559 v4.sin_len = (u_char) sizeof(v4);
1560#endif
1561 GNUNET_memcpy (&v4.sin_addr,
1562 rd[j].data,
1563 sizeof(struct in_addr));
1564 if (GNUNET_OK ==
1567 (const struct sockaddr *) &v4))
1569 break;
1570 }
1571
1573 {
1574 struct sockaddr_in6 v6;
1575
1576 if (sizeof(struct in6_addr) != rd[j].data_size)
1577 {
1578 GNUNET_break_op (0);
1579 continue;
1580 }
1581 /* FIXME: might want to check if we support IPv6 here,
1582 and otherwise skip this one and hope we find another */
1583 memset (&v6,
1584 0,
1585 sizeof(v6));
1586 v6.sin6_family = AF_INET6;
1587 v6.sin6_port = htons (53);
1588#if HAVE_SOCKADDR_IN_SIN_LEN
1589 v6.sin6_len = (u_char) sizeof(v6);
1590#endif
1591 GNUNET_memcpy (&v6.sin6_addr,
1592 rd[j].data,
1593 sizeof(struct in6_addr));
1594 if (GNUNET_OK ==
1597 (const struct sockaddr *) &v6))
1599 break;
1600 }
1601
1602 default:
1603 break;
1604 }
1605 }
1607}
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:665
struct Gns2DnsPending * gp_tail
Tail of list of resolutions of the 'ip' of the name server that are still pending.
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, AuthorityChain::authority_info, continue_with_gns2dns(), GNUNET_GNSRECORD_Data::data, data_size, AuthorityChain::dns_authority, AuthorityChain::dns_handle, AuthorityChain::found, 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, AuthorityChain::gp_head, AuthorityChain::gp_tail, rd, rd_count, 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 1618 of file gnunet-service-gns_resolver.c.

1621{
1622 struct Gns2DnsPending *gp = cls;
1623 struct AuthorityChain *ac = gp->ac;
1624 struct sockaddr_storage ss;
1625 struct sockaddr_in *v4;
1626 struct sockaddr_in6 *v6;
1627
1628 if (NULL == addr)
1629 {
1630 /* DNS resolution finished */
1631 if (0 == gp->num_results)
1633 "Failed to use DNS to resolve name of DNS resolver\n");
1636 gp);
1637 GNUNET_free (gp);
1639 return;
1640 }
1641 GNUNET_memcpy (&ss,
1642 addr,
1643 addrlen);
1644 switch (ss.ss_family)
1645 {
1646 case AF_INET:
1647 v4 = (struct sockaddr_in *) &ss;
1648 v4->sin_port = htons (53);
1649 gp->num_results++;
1650 break;
1651
1652 case AF_INET6:
1653 v6 = (struct sockaddr_in6 *) &ss;
1654 v6->sin6_port = htons (53);
1655 gp->num_results++;
1656 break;
1657
1658 default:
1660 "Unsupported AF %d\n",
1661 ss.ss_family);
1662 return;
1663 }
1664 if (GNUNET_OK ==
1666 (struct sockaddr *) &ss))
1668}
unsigned int num_results
How many results did we get?

References Gns2DnsPending::ac, AuthorityChain::authority_info, continue_with_gns2dns(), AuthorityChain::dns_authority, AuthorityChain::dns_handle, AuthorityChain::found, 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, AuthorityChain::gp_head, AuthorityChain::gp_tail, 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 1678 of file gnunet-service-gns_resolver.c.

1680{
1682 rd->data);
1683}

References GNUNET_GNSRECORD_Data::data, handle_gns_redirect_result(), and rd.

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

1695{
1696 char *cname;
1697 size_t off;
1698
1699 off = 0;
1701 rd->data_size,
1702 &off);
1703 if ((NULL == cname) ||
1704 (off != rd->data_size))
1705 {
1706 GNUNET_break_op (0); /* record not well-formed */
1707 GNUNET_free (cname);
1708 fail_resolution (rh);
1709 return;
1710 }
1712 cname);
1713 GNUNET_free (cname);
1714}

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

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

1726{
1727 struct AuthorityChain *ac;
1728 struct GNUNET_CRYPTO_PublicKey auth;
1729
1730 /* delegation to another zone */
1732 rd->data_size,
1733 rd->record_type,
1734 &auth))
1735 {
1736 GNUNET_break_op (0);
1737 fail_resolution (rh);
1738 return;
1739 }
1740 /* expand authority chain */
1741 ac = GNUNET_new (struct AuthorityChain);
1742 ac->rh = rh;
1744 ac->authority_info.gns_authority = auth;
1746 /* add AC to tail */
1748 rh->ac_tail,
1749 ac);
1750 /* recurse */
1752 rh);
1753}

References GNS_ResolverHandle::ac_head, GNS_ResolverHandle::ac_tail, AuthorityChain::authority_info, GNUNET_GNSRECORD_Data::data, GNUNET_GNSRECORD_Data::data_size, fail_resolution(), AuthorityChain::gns_authority, GNUNET_break_op, GNUNET_CONTAINER_DLL_insert_tail, GNUNET_GNSRECORD_identity_from_data(), GNUNET_new, GNUNET_OK, GNUNET_SCHEDULER_add_now(), GNUNET_YES, AuthorityChain::label, rd, GNUNET_GNSRECORD_Data::record_type, recursive_resolution(), resolver_lookup_get_next_label(), AuthorityChain::rh, 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 1767 of file gnunet-service-gns_resolver.c.

1770{
1771 struct AuthorityChain *ac;
1772 const char *tld;
1773 char *ns;
1774
1775 ns = NULL;
1776 /* expand authority chain */
1777 ac = GNUNET_new (struct AuthorityChain);
1778 ac->rh = rh;
1780
1781 for (unsigned int i = 0; i < rd_count; i++)
1782 {
1783 char *ip;
1784 char *n;
1785 size_t off;
1786 struct Gns2DnsPending *gp;
1787 struct GNUNET_CRYPTO_PublicKey zone;
1788 struct sockaddr_in v4;
1789 struct sockaddr_in6 v6;
1790
1791 if (GNUNET_GNSRECORD_TYPE_GNS2DNS != rd[i].record_type)
1792 {
1796 GNUNET_free (ns);
1797 GNUNET_free (ac);
1798 return GNUNET_SYSERR;
1799 }
1800 off = 0;
1802 rd[i].data_size,
1803 &off);
1804 ip = GNUNET_strdup (&((const char *) rd[i].data)[off]);
1805 if ((NULL == n) ||
1806 (NULL == ip))
1807 {
1808 GNUNET_break_op (0);
1809 GNUNET_free (n);
1810 GNUNET_free (ip);
1811 continue;
1812 }
1813
1814 off += strlen (ip) + 1;
1815
1816 if (off != rd[i].data_size)
1817 {
1818 GNUNET_break_op (0);
1819 GNUNET_free (n);
1820 GNUNET_free (ip);
1821 continue;
1822 }
1823 /* resolve 'ip' to determine the IP(s) of the DNS
1824 resolver to use for lookup of 'ns' */
1825 if (NULL != ns)
1826 {
1827 if (0 != strcasecmp (ns,
1828 n))
1829 {
1830 /* NS values must all be the same for all GNS2DNS records,
1831 anything else leads to insanity */
1832 GNUNET_break_op (0);
1833 GNUNET_free (n);
1834 GNUNET_free (ip);
1835 continue;
1836 }
1837 GNUNET_free (n);
1838 }
1839 else
1840 {
1841 ns = n;
1842 }
1843
1844 /* check if 'ip' is already an IPv4/IPv6 address */
1845 if ((1 == inet_pton (AF_INET,
1846 ip,
1847 &v4)) ||
1848 (1 == inet_pton (AF_INET6,
1849 ip,
1850 &v6)))
1851 {
1855 ip));
1857 GNUNET_free (ip);
1858 continue;
1859 }
1860 tld = GNS_get_tld (ip);
1861 if ((0 != strcmp (tld, "+")) &&
1862 (GNUNET_OK != GNUNET_GNSRECORD_zkey_to_pkey (tld, &zone)))
1863 {
1864 /* 'ip' is a DNS name */
1865 gp = GNUNET_new (struct Gns2DnsPending);
1866 gp->ac = ac;
1869 gp);
1871 AF_UNSPEC,
1874 gp);
1875 GNUNET_free (ip);
1876 continue;
1877 }
1878 /* 'ip' should be a GNS name */
1879 gp = GNUNET_new (struct Gns2DnsPending);
1880 gp->ac = ac;
1883 gp);
1884 gp->rh = GNUNET_new (struct GNS_ResolverHandle);
1885 if (0 == strcmp (tld, "+"))
1886 {
1887 ip = translate_dot_plus (rh,
1888 ip);
1889 tld = GNS_get_tld (ip);
1890 if (GNUNET_OK !=
1892 &zone))
1893 {
1894 GNUNET_break_op (0);
1895 GNUNET_free (ip);
1896 continue;
1897 }
1898 }
1899 gp->rh->authority_zone = zone;
1901 "Resolving `%s' to determine IP address of DNS server for GNS2DNS transition for `%s'\n",
1902 ip,
1903 ns);
1904 gp->rh->name = ip;
1905 gp->rh->name_resolution_pos = strlen (ip) - strlen (tld) - 1;
1907 gp->rh->proc_cls = gp;
1910 gp->rh->loop_limiter = rh->loop_limiter + 1;
1911 gp->rh->loop_threshold = rh->loop_threshold;
1912 gp->rh->task_id
1914 gp->rh);
1915 } /* end 'for all records' */
1916
1917 if (NULL == ns)
1918 {
1919 /* not a single GNS2DNS record found */
1920 GNUNET_free (ac);
1921 return GNUNET_SYSERR;
1922 }
1924 strcpy (ac->authority_info.dns_authority.name,
1925 ns);
1926 /* for DNS recursion, the label is the full DNS name,
1927 created from the remainder of the GNS name and the
1928 name in the NS record */
1929 GNUNET_asprintf (&ac->label,
1930 "%.*s%s%s",
1931 (int) rh->name_resolution_pos,
1932 rh->name,
1933 (0 != rh->name_resolution_pos) ? "." : "",
1934 ns);
1935 GNUNET_free (ns);
1936
1937 {
1938 /* the GNS name is UTF-8 and may include multibyte chars.
1939 * We have to convert the combined name to a DNS-compatible IDNA.
1940 */
1941 char *tmp = ac->label;
1942
1943 if (IDNA_SUCCESS != idna_to_ascii_8z (tmp,
1944 &ac->label,
1945 IDNA_ALLOW_UNASSIGNED))
1946 {
1948 _ ("Name `%s' cannot be converted to IDNA."),
1949 tmp);
1950 GNUNET_free (tmp);
1951 GNUNET_free (ac);
1952 return GNUNET_SYSERR;
1953 }
1954 GNUNET_free (tmp);
1955 }
1956
1958 rh->ac_tail,
1959 ac);
1960 if (strlen (ac->label) > GNUNET_DNSPARSER_MAX_NAME_LENGTH)
1961 {
1963 _ ("GNS lookup resulted in DNS name that is too long (`%s')\n"),
1964 ac->label);
1965 GNUNET_free (ac->label);
1966 GNUNET_free (ac);
1967 return GNUNET_SYSERR;
1968 }
1970 return GNUNET_OK;
1971}
static struct GNUNET_NAMECACHE_Handle * ns
Handle to the namecache.
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.
struct GNUNET_DNSSTUB_Context * GNUNET_DNSSTUB_start(unsigned int num_sockets)
Start a DNS stub resolver.
Definition: dnsstub.c:586
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:613
@ 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, GNS_ResolverHandle::ac_head, GNS_ResolverHandle::ac_tail, AuthorityChain::authority_info, GNS_ResolverHandle::authority_zone, continue_with_gns2dns(), data, data_size, AuthorityChain::dns_authority, AuthorityChain::dns_handle, Gns2DnsPending::dns_rh, AuthorityChain::found, 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, AuthorityChain::gp_head, AuthorityChain::gp_tail, handle_gns2dns_ip(), handle_gns2dns_result(), AuthorityChain::label, GNS_ResolverHandle::loop_limiter, GNS_ResolverHandle::loop_threshold, AuthorityChain::name, GNS_ResolverHandle::name, GNS_ResolverHandle::name_resolution_pos, ns, GNS_ResolverHandle::options, GNS_ResolverHandle::proc, GNS_ResolverHandle::proc_cls, rd, rd_count, GNS_ResolverHandle::record_type, Gns2DnsPending::rh, AuthorityChain::rh, start_resolver_lookup(), GNS_ResolverHandle::task_id, and translate_dot_plus().

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

2515{
2516 struct CacheOps *co = cls;
2517
2518 co->namecache_qe_cache = NULL;
2519 if (GNUNET_OK != success)
2521 _ ("Failed to cache GNS resolution: %s\n"),
2522 emsg);
2524 co_tail,
2525 co);
2526 GNUNET_free (co);
2527}
static struct CacheOps * co_head
Organized in a DLL.
static struct CacheOps * co_tail
Organized in a DLL.
Active namestore caching operations.
struct GNUNET_NAMECACHE_QueueEntry * namecache_qe_cache
Pending Namestore caching task.

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

Referenced by handle_dht_response().

Here is the caller graph for this function:

◆ handle_dht_response()

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

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

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

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

2560{
2561 struct GNS_ResolverHandle *rh = cls;
2562 struct AuthorityChain *ac = rh->ac_tail;
2563 const struct GNUNET_GNSRECORD_Block *block;
2564 struct CacheOps *co;
2565
2566 (void) exp;
2567 (void) key;
2568 (void) get_path;
2569 (void) get_path_length;
2570 (void) put_path;
2571 (void) put_path_length;
2572 (void) type;
2574 rh->get_handle = NULL;
2576 rh->dht_heap_node = NULL;
2578 "Handling response from the DHT\n");
2579 if (size < sizeof(struct GNUNET_GNSRECORD_Block))
2580 {
2581 /* how did this pass DHT block validation!? */
2582 GNUNET_break (0);
2583 fail_resolution (rh);
2584 return;
2585 }
2586 block = data;
2588 {
2589 /* how did this pass DHT block validation!? */
2590 GNUNET_break (0);
2591 fail_resolution (rh);
2592 return;
2593 }
2595 "Decrypting DHT block of size %llu for `%s', expires %s\n",
2596 (unsigned long long) GNUNET_GNSRECORD_block_get_size (block),
2597 rh->name,
2599 if (GNUNET_OK !=
2602 ac->label,
2604 rh))
2605 {
2606 GNUNET_break_op (0); /* block was ill-formed */
2607 fail_resolution (rh);
2608 return;
2609 }
2612 rel_value_us)
2613 {
2615 "Received expired block from the DHT, will not cache it.\n");
2616 return;
2617 }
2619 return;
2620 /* Cache well-formed blocks */
2622 "Caching response from the DHT in namecache\n");
2623 co = GNUNET_new (struct CacheOps);
2625 block,
2626 &
2628 co);
2630 co_tail,
2631 co);
2632}
struct GNUNET_HashCode key
The key used in the DHT.
static uint32_t type
Type string converted to DNS type value.
static int disable_cache
Use namecache.
static void namecache_cache_continuation(void *cls, int32_t success, const char *emsg)
Function called once the namestore has completed the request for caching a block.
static void handle_gns_resolution_result(void *cls, unsigned int rd_count, const struct GNUNET_GNSRECORD_Data *rd)
Process records that were decrypted from a block.
static struct GNUNET_NAMECACHE_Handle * namecache_handle
Our handle to the namecache service.
void GNUNET_DHT_get_stop(struct GNUNET_DHT_GetHandle *get_handle)
Stop async DHT-get.
Definition: dht_api.c:1235
enum GNUNET_GenericReturnValue GNUNET_GNSRECORD_block_decrypt(const struct GNUNET_GNSRECORD_Block *block, const struct GNUNET_CRYPTO_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:405
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:68
struct GNUNET_CONTAINER_HeapNode * dht_heap_node
Heap node associated with this lookup.
struct GNUNET_DHT_GetHandle * get_handle
Handle for DHT lookups.

References GNS_ResolverHandle::ac_tail, AuthorityChain::authority_info, co_head, co_tail, data, GNS_ResolverHandle::dht_heap_node, disable_cache, fail_resolution(), GNS_ResolverHandle::get_handle, AuthorityChain::gns_authority, 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, AuthorityChain::label, 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 2642 of file gnunet-service-gns_resolver.c.

2644{
2645 struct GNS_ResolverHandle *rx;
2646
2647 GNUNET_assert (NULL == rh->get_handle);
2650 query,
2653 NULL, 0,
2654 &handle_dht_response, rh);
2656 rh,
2658 abs_value_us);
2661 {
2662 /* fail longest-standing DHT request */
2664 rx->dht_heap_node = NULL;
2665 GNUNET_assert (NULL != rx);
2666 fail_resolution (rx);
2667 }
2668}
static unsigned long long max_allowed_background_queries
Maximum amount of parallel queries to the DHT.
static struct GNUNET_DHT_Handle * dht_handle
Resolver handle to the dht.
static void handle_dht_response(void *cls, struct GNUNET_TIME_Absolute exp, const struct GNUNET_HashCode *key, const struct GNUNET_PeerIdentity *trunc_peer, const struct GNUNET_DHT_PathElement *get_path, unsigned int get_path_length, const struct GNUNET_DHT_PathElement *put_path, unsigned int put_path_length, enum GNUNET_BLOCK_Type type, size_t size, const void *data)
Iterator called on each result obtained for a DHT operation that expects a reply.
#define DHT_GNS_REPLICATION_LEVEL
DHT replication level.
static struct GNUNET_CONTAINER_Heap * dht_lookup_heap
Heap for limiting parallel DHT lookups.
struct GNUNET_DHT_GetHandle * GNUNET_DHT_get_start(struct GNUNET_DHT_Handle *handle, enum GNUNET_BLOCK_Type type, const struct GNUNET_HashCode *key, uint32_t desired_replication_level, enum GNUNET_DHT_RouteOption options, const void *xquery, size_t xquery_size, GNUNET_DHT_GetIterator iter, void *iter_cls)
Perform an asynchronous GET operation on the DHT identified.
Definition: dht_api.c:1162
@ 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:111
@ GNUNET_BLOCK_TYPE_GNS_NAMERECORD
Block for storing GNS record data.

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

2683{
2684 struct GNS_ResolverHandle *rh = cls;
2685
2686 if (0 == rd_count)
2688 _ ("GNS namecache returned empty result for `%s'\n"),
2689 rh->name);
2691 rd_count,
2692 rd);
2693}

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

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

2705{
2706 struct GNS_ResolverHandle *rh = cls;
2707 struct AuthorityChain *ac = rh->ac_tail;
2708 const char *label = ac->label;
2709 const struct GNUNET_CRYPTO_PublicKey *auth =
2711 struct GNUNET_HashCode query;
2712
2713 GNUNET_assert (NULL != rh->namecache_qe);
2714 rh->namecache_qe = NULL;
2715 if (NULL == block)
2717 "No block found\n");
2718 else
2720 "Got block with expiration %s\n",
2723 if (((GNUNET_GNS_LO_DEFAULT == rh->options) ||
2725 (ac != rh->ac_head))) &&
2726 ((NULL == block) ||
2729 rel_value_us)))
2730 {
2731 /* namecache knows nothing; try DHT lookup */
2733 label,
2734 &query);
2736 "Starting DHT lookup for `%s' in zone `%s' under key `%s'\n",
2737 ac->label,
2739 GNUNET_h2s (&query));
2740 start_dht_request (rh, &query);
2741 return;
2742 }
2743
2744 if ((NULL == block) ||
2747 rel_value_us))
2748 {
2749 /* DHT not permitted and no local result, fail */
2751 "Resolution failed for `%s' in zone %s (DHT lookup not permitted by configuration)\n",
2752 ac->label,
2754 fail_resolution (rh);
2755 return;
2756 }
2758 "Received result from namecache for label `%s'\n",
2759 ac->label);
2760
2761 if (GNUNET_OK !=
2763 auth,
2764 label,
2766 rh))
2767 {
2768 GNUNET_break_op (0); /* block was ill-formed */
2769 /* try DHT instead */
2771 label,
2772 &query);
2774 "Starting DHT lookup for `%s' in zone `%s' under key `%s'\n",
2775 ac->label,
2777 GNUNET_h2s (&query));
2778 start_dht_request (rh, &query);
2779 return;
2780 }
2781}
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_CRYPTO_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 GNS_ResolverHandle::ac_head, GNS_ResolverHandle::ac_tail, AuthorityChain::authority_info, fail_resolution(), AuthorityChain::gns_authority, 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 2790 of file gnunet-service-gns_resolver.c.

2791{
2792 struct AuthorityChain *ac = rh->ac_tail;
2793 struct GNUNET_HashCode query;
2794
2796 "Starting GNS resolution for `%s' in zone %s\n",
2797 ac->label,
2800 ac->label,
2801 &query);
2803 {
2804 rh->namecache_qe
2806 &query,
2808 rh);
2809 GNUNET_assert (NULL != rh->namecache_qe);
2810 }
2811 else
2812 {
2814 &query);
2815 }
2816}
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 GNS_ResolverHandle::ac_tail, AuthorityChain::authority_info, disable_cache, AuthorityChain::gns_authority, 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(), AuthorityChain::label, 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 2826 of file gnunet-service-gns_resolver.c.

2828{
2829 struct GNS_ResolverHandle *rh = cls;
2830 struct AuthorityChain *ac = rh->ac_tail;
2831
2832 rh->rev_check = NULL;
2833 if (GNUNET_YES != is_valid)
2834 {
2836 _ ("Zone %s was revoked, resolution fails\n"),
2839 return;
2840 }
2842}
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 _, GNS_ResolverHandle::ac_tail, AuthorityChain::authority_info, fail_resolution(), AuthorityChain::gns_authority, 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 2851 of file gnunet-service-gns_resolver.c.

2852{
2853 struct AuthorityChain *ac = rh->ac_tail;
2854
2856 "Starting revocation check for zone %s\n",
2861 rh);
2862 GNUNET_assert (NULL != rh->rev_check);
2863}
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_CRYPTO_PublicKey *key, GNUNET_REVOCATION_Callback func, void *func_cls)
Check if a key was revoked.

References GNS_ResolverHandle::ac_tail, AuthorityChain::authority_info, cfg, AuthorityChain::gns_authority, 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_CRYPTO_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 2969 of file gnunet-service-gns_resolver.c.

2976{
2977 struct GNS_ResolverHandle *rh;
2978
2980 "Starting lookup for `%s'\n",
2981 name);
2982 rh = GNUNET_new (struct GNS_ResolverHandle);
2984 rlh_tail,
2985 rh);
2986 rh->authority_zone = *zone;
2987 rh->proc = proc;
2988 rh->proc_cls = proc_cls;
2989 rh->options = options;
2991 rh->name = GNUNET_strdup (name);
2992 rh->name_resolution_pos = strlen (name);
2993 rh->loop_threshold = recursion_depth_limit;
2995 rh);
2996 return rh;
2997}
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(), and GNS_ResolverHandle::task_id.

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

3007{
3008 struct DnsResult *dr;
3009 struct AuthorityChain *ac;
3010
3012 rlh_tail,
3013 rh);
3014 if (NULL != rh->dns_request)
3015 {
3017 rh->dns_request = NULL;
3018 }
3019 while (NULL != (ac = rh->ac_head))
3020 {
3022 rh->ac_tail,
3023 ac);
3024 if (GNUNET_NO == ac->gns_authority)
3025 {
3026 struct Gns2DnsPending *gp;
3027
3028 while (NULL != (gp = ac->authority_info.dns_authority.gp_head))
3029 {
3032 gp);
3033 if (NULL != gp->rh)
3034 {
3035 /* rh->g2dc->rh is NOT in the DLL yet, so to enable us
3036 using GNS_resolver_lookup_cancel here, we need to
3037 add it first... */
3039 rlh_tail,
3040 gp->rh);
3041 GNUNET_assert (NULL == gp->rh->task_id);
3044 gp->rh);
3045 gp->rh = NULL;
3046 }
3047 if (NULL != gp->dns_rh)
3048 {
3050 gp->dns_rh = NULL;
3051 }
3052 GNUNET_free (gp);
3053 }
3055 }
3056 GNUNET_free (ac->label);
3057 GNUNET_free (ac);
3058 }
3059 if (NULL != rh->task_id)
3060 {
3062 rh->task_id = NULL;
3063 }
3064 if (NULL != rh->get_handle)
3065 {
3067 rh->get_handle = NULL;
3068 }
3069 if (NULL != rh->dht_heap_node)
3070 {
3072 rh->dht_heap_node = NULL;
3073 }
3074 if (NULL != rh->namecache_qe)
3075 {
3077 rh->namecache_qe = NULL;
3078 }
3079 if (NULL != rh->rev_check)
3080 {
3082 rh->rev_check = NULL;
3083 }
3084 if (NULL != rh->std_resolve)
3085 {
3087 "Canceling standard DNS resolution\n");
3089 rh->std_resolve = NULL;
3090 }
3091 while (NULL != (dr = rh->dns_result_head))
3092 {
3095 dr);
3096 GNUNET_free (dr);
3097 }
3098 if (NULL != rh->prefix)
3099 {
3101 rh->prefix = NULL;
3102 }
3103 GNUNET_free (rh->leho);
3104 GNUNET_free (rh->name);
3105 GNUNET_free (rh);
3106}
void GNUNET_DNSSTUB_stop(struct GNUNET_DNSSTUB_Context *ctx)
Cleanup DNSSTUB resolver.
Definition: dnsstub.c:705
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 Gns2DnsPending::ac, GNS_ResolverHandle::ac_head, GNS_ResolverHandle::ac_tail, AuthorityChain::authority_info, GNS_ResolverHandle::dht_heap_node, AuthorityChain::dns_authority, AuthorityChain::dns_handle, GNS_ResolverHandle::dns_request, GNS_ResolverHandle::dns_result_head, GNS_ResolverHandle::dns_result_tail, Gns2DnsPending::dns_rh, GNS_ResolverHandle::get_handle, AuthorityChain::gns_authority, 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(), AuthorityChain::gp_head, AuthorityChain::gp_tail, AuthorityChain::label, GNS_ResolverHandle::leho, GNS_ResolverHandle::name, GNS_ResolverHandle::namecache_qe, GNS_ResolverHandle::prefix, 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 3121 of file gnunet-service-gns_resolver.c.

3125{
3126 cfg = c;
3128 dht_handle = dht;
3131 max_allowed_background_queries = max_bg_queries;
3133 "namecache",
3134 "DISABLE");
3137 "Namecache disabled\n");
3138}
static struct GNUNET_DHT_Handle * dht
Handle to the DHT.
static struct GNUNET_NotificationContext * nc
Notification context for broadcasting to monitors.
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 3145 of file gnunet-service-gns_resolver.c.

3146{
3147 struct GNS_ResolverHandle *rh;
3148 struct CacheOps *co;
3149
3150 /* abort active resolutions */
3151 while (NULL != (rh = rlh_head))
3152 {
3153 rh->proc (rh->proc_cls,
3154 0,
3155 NULL);
3157 }
3158 while (NULL != (co = co_head))
3159 {
3161 co_tail,
3162 co);
3164 GNUNET_free (co);
3165 }
3167 dht_lookup_heap = NULL;
3168 dht_handle = NULL;
3169 namecache_handle = NULL;
3170}
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 426 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 431 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 436 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 441 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 446 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 451 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 456 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 461 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 471 of file gnunet-service-gns_resolver.c.

Referenced by GNS_resolver_init(), and recursive_gns_resolution_revocation().