GNUnet 0.22.2
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_resolver_service.h"
#include "gnunet_revocation_service.h"
#include "gnunet_gns_service.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

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:486

Default DHT timeout for lookups.

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

◆ DNS_LOOKUP_TIMEOUT

#define DNS_LOOKUP_TIMEOUT
Value:

Default timeout for DNS lookups.

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

◆ DHT_GNS_REPLICATION_LEVEL

#define DHT_GNS_REPLICATION_LEVEL   10

DHT replication level.

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

Function Documentation

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

484{
485 char *ret;
486 size_t s_len = strlen (name);
487
488 if (0 != strcmp (&name[s_len - 2],
489 ".+"))
490 return name; /* did not end in ".+" */
493 "%.*s.%s",
494 (int) (s_len - 2),
495 name,
499 return ret;
500}
static int ret
Final status code.
Definition: gnunet-arm.c:93
static char * name
Name (label) of the records to list.
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.
@ GNUNET_YES
#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 510 of file gnunet-service-gns_resolver.c.

511{
512 struct GNS_ResolverHandle *rh = cls;
513
514 rh->task_id = NULL;
516}
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 525 of file gnunet-service-gns_resolver.c.

526{
527 rh->proc (rh->proc_cls,
528 0,
529 NULL);
530 GNUNET_assert (NULL == rh->task_id);
532 rh);
533}
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:1304
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 542 of file gnunet-service-gns_resolver.c.

543{
544 struct GNS_ResolverHandle *rh = cls;
545
546 rh->task_id = NULL;
547 fail_resolution (rh);
548}
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 557 of file gnunet-service-gns_resolver.c.

558{
559 struct protoent *pe = getprotobyname (name);
560 if (pe == NULL)
561 {
563 }
564 return pe->p_proto;
565}
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 575 of file gnunet-service-gns_resolver.c.

576{
577 struct servent *se = getservbyname (name, proto);
578 if (se == NULL)
579 {
581 }
582 return se->s_port;
583}
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 605 of file gnunet-service-gns_resolver.c.

606{
607 const char *rp;
608 const char *dot;
609 size_t len;
610 char *ret;
611 char *srv_name;
612 char *proto_name;
613 int protocol;
614 int service;
615
616 if (0 == rh->name_resolution_pos)
617 return NULL;
618 dot = memrchr (rh->name,
619 (int) '.',
621 if (NULL == dot)
622 {
623 /* done, this was the last one */
624 len = rh->name_resolution_pos;
625 rp = rh->name;
626 rh->name_resolution_pos = 0;
627 }
628 else if ('_' == dot[1])
629 {
638 len = strlen (GNUNET_GNS_EMPTY_LABEL_AT);
639 }
640 else
641 {
642 /* advance by one label */
643 len = rh->name_resolution_pos - (dot - rh->name) - 1;
644 rp = dot + 1;
645 rh->name_resolution_pos = dot - rh->name;
646 }
647 rh->protocol = 0;
648 rh->service = 0;
649 rh->prefix = NULL;
650 ret = GNUNET_strndup (rp, len);
655 if (('_' == rh->name[0]) &&
656 (NULL != (dot = memrchr (rh->name,
657 (int) '.',
658 rh->name_resolution_pos))) &&
659 ('_' == dot[1]) &&
660 (NULL == memrchr (rh->name,
661 (int) '.',
662 dot - rh->name)))
663 {
664 srv_name = GNUNET_strndup (&rh->name[1],
665 (dot - rh->name) - 1);
666 proto_name = GNUNET_strndup (&dot[2],
667 rh->name_resolution_pos - (dot - rh->name)
668 - 2);
669 protocol = resolver_getprotobyname (proto_name);
670 if (0 == protocol)
671 {
673 _ (
674 "Protocol `%s' unknown, skipping labels as BOX retain as SBOX.\n"),
675 proto_name);
676 GNUNET_free (proto_name);
677 GNUNET_free (srv_name);
679 rh->name_resolution_pos = 0;
680 return ret;
681 }
683 proto_name);
684 if (0 == service)
685 {
687 _ (
688 "Service `%s' unknown for protocol `%s', trying as number.\n"),
689 srv_name,
690 proto_name);
691 if (1 != sscanf (srv_name, "%u", &rh->service))
692 {
694 _ (
695 "Service `%s' not a port, skipping service labels as BOX retain as SBOX.\n"),
696 srv_name);
697 GNUNET_free (proto_name);
698 GNUNET_free (srv_name);
700 rh->name_resolution_pos = 0;
701 return ret;
702 }
703 }
704 else
705 {
706 rh->service = ntohs (service);
707 }
708 rh->protocol = protocol;
709 GNUNET_free (proto_name);
710 GNUNET_free (srv_name);
711 }
718 if ((NULL != (dot = memrchr (rh->name,
719 (int) '.',
720 rh->name_resolution_pos)) && '_' == dot[1]) ||
721 ((NULL == memrchr (rh->name,
722 (int) '.',
723 rh->name_resolution_pos)) && '_' == rh->name[0]))
724 {
726 rh->name_resolution_pos = 0;
727 }
728 return ret;
729}
#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 738 of file gnunet-service-gns_resolver.c.

739{
740 struct DnsResult *pos;
741 unsigned int n;
742 unsigned int i;
743
744 n = 0;
745 for (pos = rh->dns_result_head; NULL != pos; pos = pos->next)
746 n++;
747 {
748 struct GNUNET_GNSRECORD_Data rd[n];
749
750 i = 0;
751 for (pos = rh->dns_result_head; NULL != pos; pos = pos->next)
752 {
753 rd[i].data = pos->data;
754 rd[i].data_size = pos->data_size;
755 rd[i].record_type = pos->record_type;
763 if (0 == pos->expiration_time)
764 {
766 rd[i].expiration_time = 0;
767 }
768 else
769 {
771 }
772 i++;
773 }
774 GNUNET_assert (i == n);
776 "Transmitting standard DNS result with %u records\n",
777 n);
778 rh->proc (rh->proc_cls,
779 n,
780 rd);
781 }
783}
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 796 of file gnunet-service-gns_resolver.c.

801{
802 struct DnsResult *res;
803
804 res = GNUNET_malloc (sizeof(struct DnsResult) + data_size);
805 res->expiration_time = expiration_time;
806 res->data_size = data_size;
807 res->record_type = record_type;
808 res->data = &res[1];
809 GNUNET_memcpy (&res[1],
810 data,
811 data_size);
813 rh->dns_result_tail,
814 res);
815}
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 827 of file gnunet-service-gns_resolver.c.

830{
831 struct GNS_ResolverHandle *rh = cls;
832 const struct sockaddr_in *sa4;
833 const struct sockaddr_in6 *sa6;
834
835 if (NULL == addr)
836 {
837 rh->std_resolve = NULL;
839 return;
840 }
842 "Received %u bytes of DNS IP data\n",
843 addrlen);
844 switch (addr->sa_family)
845 {
846 case AF_INET:
847 sa4 = (const struct sockaddr_in *) addr;
848 add_dns_result (rh,
849 0 /* expiration time is unknown */,
851 sizeof(struct in_addr),
852 &sa4->sin_addr);
853 break;
854
855 case AF_INET6:
856 sa6 = (const struct sockaddr_in6 *) addr;
857 add_dns_result (rh,
858 0 /* expiration time is unknown */,
860 sizeof(struct in6_addr),
861 &sa6->sin6_addr);
862 break;
863
864 default:
865 GNUNET_break (0);
866 break;
867 }
868}
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 2829 of file gnunet-service-gns_resolver.c.

2830{
2831 struct GNS_ResolverHandle *rh = cls;
2832
2833 rh->task_id = NULL;
2834 if (rh->loop_threshold < rh->loop_limiter++)
2835 {
2837 "Encountered unbounded recursion resolving `%s'\n",
2838 rh->name);
2839 fail_resolution (rh);
2840 return;
2841 }
2842 if (GNUNET_YES == rh->ac_tail->gns_authority)
2844 else
2846}
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 2850 of file gnunet-service-gns_resolver.c.

2851{
2852 struct GNS_ResolverHandle *rh = cls;
2853 struct AuthorityChain *ac;
2854 struct in_addr v4;
2855 struct in6_addr v6;
2856
2857 rh->task_id = NULL;
2858 if (1 == inet_pton (AF_INET,
2859 rh->name,
2860 &v4))
2861 {
2862 /* name is IPv4 address, pretend it's an A record */
2864
2865 rd.data = &v4;
2866 rd.data_size = sizeof(v4);
2867 rd.expiration_time = UINT64_MAX;
2869 rd.flags = 0;
2870 rh->proc (rh->proc_cls,
2871 1,
2872 &rd);
2873 GNUNET_assert (NULL == rh->task_id);
2875 rh);
2876 return;
2877 }
2878 if (1 == inet_pton (AF_INET6,
2879 rh->name,
2880 &v6))
2881 {
2882 /* name is IPv6 address, pretend it's an AAAA record */
2884
2885 rd.data = &v6;
2886 rd.data_size = sizeof(v6);
2887 rd.expiration_time = UINT64_MAX;
2889 rd.flags = 0;
2890 rh->proc (rh->proc_cls,
2891 1,
2892 &rd);
2893 GNUNET_assert (NULL == rh->task_id);
2895 rh);
2896 return;
2897 }
2898
2899 ac = GNUNET_new (struct AuthorityChain);
2900 ac->rh = rh;
2902 if (NULL == ac->label)
2903 /* name was just the "TLD", so we default to label
2904 #GNUNET_GNS_EMPTY_LABEL_AT */
2909 rh->ac_tail,
2910 ac);
2912 rh);
2913}
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 899 of file gnunet-service-gns_resolver.c.

902{
903 struct GNS_ResolverHandle *rh = cls;
905 const struct GNUNET_DNSPARSER_Record *rec;
906 unsigned int rd_count;
907
908 if (NULL == dns)
909 {
910 rh->dns_request = NULL;
912 rh->task_id = NULL;
913 fail_resolution (rh);
914 return;
915 }
916 if (rh->original_dns_id != dns->id)
917 {
918 /* DNS answer, but for another query */
919 return;
920 }
921 p = GNUNET_DNSPARSER_parse ((const char *) dns,
922 dns_len);
923 if (NULL == p)
924 {
926 _ ("Failed to parse DNS response\n"));
927 return;
928 }
929
930 /* We got a result from DNS */
932 "Received DNS response for `%s' with %u answers\n",
933 rh->ac_tail->label,
934 (unsigned int) p->num_answers);
935 if ((p->num_answers > 0) &&
936 (GNUNET_DNSPARSER_TYPE_CNAME == p->answers[0].type) &&
938 {
939 int af;
940
942 "Got CNAME `%s' from DNS for `%s'\n",
943 p->answers[0].data.hostname,
944 rh->name);
945 if (NULL != rh->std_resolve)
946 {
948 "Multiple CNAME results from DNS resolving `%s'! Not really allowed...\n",
949 rh->name);
951 }
952 GNUNET_free (rh->name);
953 rh->name = GNUNET_strdup (p->answers[0].data.hostname);
954 rh->name_resolution_pos = strlen (rh->name);
955 switch (rh->record_type)
956 {
958 af = AF_INET;
959 break;
960
962 af = AF_INET6;
963 break;
964
965 default:
966 af = AF_UNSPEC;
967 break;
968 }
969 if (NULL != rh->leho)
970 add_dns_result (rh,
971 GNUNET_TIME_UNIT_HOURS.rel_value_us,
973 strlen (rh->leho),
974 rh->leho);
976 af,
979 rh);
982 rh->dns_request = NULL;
983 return;
984 }
985
986 /* convert from (parsed) DNS to (binary) GNS format! */
987 rd_count = p->num_answers + p->num_authority_records
988 + p->num_additional_records;
989 {
990 struct GNUNET_GNSRECORD_Data rd[rd_count + 1]; /* +1 for LEHO */
991 int skip;
992 char buf[UINT16_MAX];
993 size_t buf_off;
994 size_t buf_start;
995
996 buf_off = 0;
997 skip = 0;
998 memset (rd,
999 0,
1000 sizeof(rd));
1001 for (unsigned int i = 0; i < rd_count; i++)
1002 {
1003 if (i < p->num_answers)
1004 rec = &p->answers[i];
1005 else if (i < p->num_answers + p->num_authority_records)
1006 rec = &p->authority_records[i - p->num_answers];
1007 else
1008 rec = &p->additional_records[i - p->num_answers
1009 - p->num_authority_records];
1010 /* As we copied the full DNS name to 'rh->ac_tail->label', this
1011 should be the correct check to see if this record is actually
1012 a record for our label... */
1013 if (0 != strcmp (rec->name,
1014 rh->ac_tail->label))
1015 {
1017 "Dropping record `%s', does not match desired name `%s'\n",
1018 rec->name,
1019 rh->ac_tail->label);
1020 skip++;
1021 continue;
1022 }
1023 rd[i - skip].record_type = rec->type;
1025 switch (rec->type)
1026 {
1028 if (rec->data.raw.data_len != sizeof(struct in_addr))
1029 {
1030 GNUNET_break_op (0);
1031 skip++;
1032 continue;
1033 }
1034 rd[i - skip].data_size = rec->data.raw.data_len;
1035 rd[i - skip].data = rec->data.raw.data;
1036 break;
1037
1039 if (rec->data.raw.data_len != sizeof(struct in6_addr))
1040 {
1041 GNUNET_break_op (0);
1042 skip++;
1043 continue;
1044 }
1045 rd[i - skip].data_size = rec->data.raw.data_len;
1046 rd[i - skip].data = rec->data.raw.data;
1047 break;
1048
1052 buf_start = buf_off;
1053 if (GNUNET_OK !=
1055 sizeof(buf),
1056 &buf_off,
1057 rec->data.hostname))
1058 {
1059 GNUNET_break (0);
1060 skip++;
1061 continue;
1062 }
1063 rd[i - skip].data_size = buf_off - buf_start;
1064 rd[i - skip].data = &buf[buf_start];
1065 break;
1066
1068 buf_start = buf_off;
1069 if (GNUNET_OK !=
1071 sizeof(buf),
1072 &buf_off,
1073 rec->data.soa))
1074 {
1075 GNUNET_break (0);
1076 skip++;
1077 continue;
1078 }
1079 rd[i - skip].data_size = buf_off - buf_start;
1080 rd[i - skip].data = &buf[buf_start];
1081 break;
1082
1084 buf_start = buf_off;
1085 if (GNUNET_OK !=
1087 sizeof(buf),
1088 &buf_off,
1089 rec->data.mx))
1090 {
1091 GNUNET_break (0);
1092 skip++;
1093 continue;
1094 }
1095 rd[i - skip].data_size = buf_off - buf_start;
1096 rd[i - skip].data = &buf[buf_start];
1097 break;
1098
1100 buf_start = buf_off;
1101 if (GNUNET_OK !=
1103 sizeof(buf),
1104 &buf_off,
1105 rec->data.srv))
1106 {
1107 GNUNET_break (0);
1108 skip++;
1109 continue;
1110 }
1111 rd[i - skip].data_size = buf_off - buf_start;
1112 rd[i - skip].data = &buf[buf_start];
1113 break;
1114
1116 buf_start = buf_off;
1117 if (GNUNET_OK !=
1119 sizeof(buf),
1120 &buf_off,
1121 rec->data.uri))
1122 {
1123 GNUNET_break (0);
1124 skip++;
1125 continue;
1126 }
1127 rd[i - skip].data_size = buf_off - buf_start;
1128 rd[i - skip].data = &buf[buf_start];
1129 break;
1130
1131 default:
1133 _ ("Skipping record of unsupported type %d\n"),
1134 rec->type);
1135 skip++;
1136 continue;
1137 }
1138 } /* end of for all records in answer */
1139 if (NULL != rh->leho)
1140 {
1144 rd[rd_count - skip].expiration_time = GNUNET_TIME_UNIT_HOURS.rel_value_us;
1145 rd[rd_count - skip].data = rh->leho;
1146 rd[rd_count - skip].data_size = strlen (rh->leho);
1147 skip--; /* skip one LESS */
1149 "Adding LEHO %s\n",
1150 rh->leho);
1151 }
1153 "Returning DNS response for `%s' with %u answers\n",
1154 rh->ac_tail->label,
1155 (unsigned int) (rd_count - skip));
1156 rh->proc (rh->proc_cls,
1157 rd_count - skip,
1158 rd);
1160 rh->dns_request = NULL;
1161 }
1163 if (NULL != rh->task_id)
1164 GNUNET_SCHEDULER_cancel (rh->task_id); /* should be timeout task */
1166 rh);
1167}
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:985
void GNUNET_DNSPARSER_free_packet(struct GNUNET_DNSPARSER_Packet *p)
Free memory taken by a packet.
Definition: dnsparser.c:950
#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:1177
#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:1099
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:1218
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:1255
#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:729
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:980
#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 1179 of file gnunet-service-gns_resolver.c.

1180{
1181 struct AuthorityChain *ac;
1182 struct GNUNET_DNSPARSER_Query *query;
1183 struct GNUNET_DNSPARSER_Packet *p;
1184 char *dns_request;
1185 size_t dns_request_length;
1186 int ret;
1187
1188 ac = rh->ac_tail;
1189 GNUNET_assert (NULL != ac);
1191 "Starting DNS lookup for `%s'\n",
1192 ac->label);
1194 query = GNUNET_new (struct GNUNET_DNSPARSER_Query);
1195 query->name = GNUNET_strdup (ac->label);
1196 query->type = rh->record_type;
1199 p->queries = query;
1200 p->num_queries = 1;
1202 UINT16_MAX);
1203 p->flags.opcode = GNUNET_TUN_DNS_OPCODE_QUERY;
1204 p->flags.recursion_desired = 1;
1206 1024,
1207 &dns_request,
1208 &dns_request_length);
1209 if (GNUNET_OK != ret)
1210 {
1211 GNUNET_break (0);
1212 rh->proc (rh->proc_cls,
1213 0,
1214 NULL);
1215 GNUNET_assert (NULL == rh->task_id);
1217 rh);
1218 }
1219 else
1220 {
1221 rh->original_dns_id = p->id;
1223 GNUNET_assert (NULL == rh->dns_request);
1224 rh->leho = GNUNET_strdup (ac->label);
1227 dns_request,
1228 dns_request_length,
1230 rh);
1233 rh);
1234 }
1235 if (GNUNET_SYSERR != ret)
1236 GNUNET_free (dns_request);
1238}
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:1400
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_NO
@ 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:1277
#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 1250 of file gnunet-service-gns_resolver.c.

1252{
1253 size_t nlen;
1254 char *res;
1255 const char *tld;
1256 struct AuthorityChain *ac;
1257 int af;
1258 struct GNUNET_CRYPTO_PublicKey zone;
1259
1261 "Handling GNS REDIRECT result `%s'\n",
1262 rname);
1263 nlen = strlen (rname);
1264 tld = GNS_get_tld (rname);
1265 if (0 == strcmp ("+", tld))
1266 {
1267 /* REDIRECT resolution continues relative to current domain */
1268 if (0 == rh->name_resolution_pos)
1269 {
1270 res = GNUNET_strndup (rname, nlen - 2);
1271 rh->name_resolution_pos = nlen - 2;
1272 }
1273 else
1274 {
1276 "%.*s.%.*s",
1277 (int) rh->name_resolution_pos,
1278 rh->name,
1279 (int) (nlen - 2),
1280 rname);
1281 rh->name_resolution_pos = strlen (res);
1282 }
1283 GNUNET_free (rh->name);
1284 rh->name = res;
1285 ac = GNUNET_new (struct AuthorityChain);
1286 ac->rh = rh;
1291 /* add AC to tail */
1293 rh->ac_tail,
1294 ac);
1296 rh);
1297 return;
1298 }
1299 if (GNUNET_OK == GNUNET_GNSRECORD_zkey_to_pkey (tld, &zone))
1300 {
1301 /* REDIRECT resolution continues relative to current domain */
1302 if (0 == rh->name_resolution_pos)
1303 {
1305 "%.*s",
1306 (int) (strlen (rname) - (strlen (tld) + 1)),
1307 rname);
1308 }
1309 else
1310 {
1312 "%.*s.%.*s",
1313 (int) rh->name_resolution_pos,
1314 rh->name,
1315 (int) (strlen (rname) - (strlen (tld) + 1)),
1316 rname);
1317 }
1318 rh->name_resolution_pos = strlen (res);
1319 GNUNET_free (rh->name);
1320 rh->name = res;
1321 ac = GNUNET_new (struct AuthorityChain);
1322 ac->rh = rh;
1324 ac->authority_info.gns_authority = zone;
1326 /* add AC to tail */
1328 rh->ac_tail,
1329 ac);
1331 rh);
1332 return;
1333 }
1334
1336 "Got REDIRECT `%s' from GNS for `%s'\n",
1337 rname,
1338 rh->name);
1339 if (NULL != rh->std_resolve)
1340 {
1342 "Multiple REDIRECT results from GNS resolving `%s'! Not really allowed...\n",
1343 rh->name);
1345 }
1346 /* name is absolute, go to DNS */
1347 GNUNET_free (rh->name);
1348 rh->name = GNUNET_strdup (rname);
1349 rh->name_resolution_pos = strlen (rh->name);
1350 switch (rh->record_type)
1351 {
1353 af = AF_INET;
1354 break;
1355
1357 af = AF_INET6;
1358 break;
1359
1360 default:
1361 af = AF_UNSPEC;
1362 break;
1363 }
1365 "Doing standard DNS lookup for `%s'\n",
1366 rh->name);
1367
1369 af,
1372 rh);
1373}
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 1385 of file gnunet-service-gns_resolver.c.

1387{
1388 int af;
1389
1390 GNUNET_free (rh->name);
1391 rh->name = GNUNET_strdup (cname);
1392 rh->name_resolution_pos = strlen (rh->name);
1393 switch (rh->record_type)
1394 {
1396 af = AF_INET;
1397 break;
1398
1400 af = AF_INET6;
1401 break;
1402
1403 default:
1404 af = AF_UNSPEC;
1405 break;
1406 }
1408 "Doing standard DNS lookup for `%s'\n",
1409 rh->name);
1410
1412 af,
1415 rh);
1416}

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

1939{
1940 struct GNS_ResolverHandle *rh = cls;
1941 char *cname;
1942 char scratch[UINT16_MAX];
1943 size_t scratch_off;
1944 size_t scratch_start;
1945 size_t off;
1946 struct GNUNET_GNSRECORD_Data rd_new[rd_count];
1947 unsigned int rd_off;
1948
1950 "Resolution succeeded for `%s' in zone %s, got %u records\n",
1951 rh->ac_tail->label,
1953 rd_count);
1954 if (0 == rd_count)
1955 {
1957 _ ("GNS lookup failed (zero records found for `%s')\n"),
1958 rh->name);
1959 fail_resolution (rh);
1960 return;
1961 }
1962
1963 if (0 == rh->name_resolution_pos)
1964 {
1965 /* top-level match, are we done yet? */
1966 if ((rd_count > 0) &&
1969 {
1970 off = 0;
1972 rd[0].data_size,
1973 &off);
1974 if ((NULL == cname) ||
1975 (off != rd[0].data_size))
1976 {
1977 GNUNET_break_op (0);
1978 GNUNET_free (cname);
1979 fail_resolution (rh);
1980 return;
1981 }
1983 cname);
1984 GNUNET_free (cname);
1985 return;
1986 }
1987 if ((rd_count > 0) &&
1990 {
1992 rd[0].data);
1993 return;
1994 }
1995
1996
1997 /* If A/AAAA was requested,
1998 * but we got a GNS2DNS record */
1999 if ((GNUNET_DNSPARSER_TYPE_A == rh->record_type) ||
2001 {
2002 for (unsigned int i = 0; i < rd_count; i++)
2003 {
2004 switch (rd[i].record_type)
2005 {
2007 {
2008 /* delegation to DNS */
2010 "Found GNS2DNS record, delegating to DNS!\n");
2011 if (GNUNET_OK ==
2013 rd_count,
2014 rd))
2015 return;
2016 else
2017 goto fail;
2018 }
2019
2020 default:
2021 break;
2022 } /* end: switch */
2023 } /* end: for rd */
2024 } /* end: name_resolution_pos */
2025 /* convert relative names in record values to absolute names,
2026 using 'scratch' array for memory allocations */
2027 scratch_off = 0;
2028 rd_off = 0;
2029 for (unsigned int i = 0; i < rd_count; i++)
2030 {
2031 GNUNET_assert (rd_off <= i);
2032 if ((((0 != rh->protocol) &&
2033 (0 != rh->service)) || (NULL != rh->prefix)) &&
2038 continue;
2039 /* we _only_ care about boxed records */
2040
2041 GNUNET_assert (rd_off < rd_count);
2042 rd_new[rd_off] = rd[i];
2043 /* Check if the embedded name(s) end in "+", and if so,
2044 replace the "+" with the zone at "ac_tail", changing the name
2045 to a ".ZONEKEY". The name is allocated on the 'scratch' array,
2046 so we can free it afterwards. */
2047 switch (rd[i].record_type)
2048 {
2050 {
2051 char *rname;
2052 rname = GNUNET_strndup (rd[i].data, rd[i].data_size);
2053 rname = translate_dot_plus (rh, rname);
2054 GNUNET_break (NULL != rname);
2055 scratch_start = scratch_off;
2056 memcpy (&scratch[scratch_start], rname, strlen (rname) + 1);
2057 scratch_off += strlen (rname) + 1;
2058 GNUNET_assert (rd_off < rd_count);
2059 rd_new[rd_off].data = &scratch[scratch_start];
2060 rd_new[rd_off].data_size = scratch_off - scratch_start;
2061 rd_off++;
2062 GNUNET_free (rname);
2063 }
2064 break;
2065
2067 {
2068 char *cname_tmp;
2069
2070 off = 0;
2071 cname_tmp = GNUNET_DNSPARSER_parse_name (rd[i].data,
2072 rd[i].data_size,
2073 &off);
2074 if ((NULL == cname_tmp) ||
2075 (off != rd[i].data_size))
2076 {
2077 GNUNET_break_op (0); /* record not well-formed */
2078 }
2079 else
2080 {
2081 cname_tmp = translate_dot_plus (rh, cname_tmp);
2082 GNUNET_break (NULL != cname_tmp);
2083 scratch_start = scratch_off;
2084 if (GNUNET_OK !=
2086 sizeof(scratch),
2087 &scratch_off,
2088 cname_tmp))
2089 {
2090 GNUNET_break (0);
2091 }
2092 else
2093 {
2094 GNUNET_assert (rd_off < rd_count);
2095 rd_new[rd_off].data = &scratch[scratch_start];
2096 rd_new[rd_off].data_size = scratch_off - scratch_start;
2097 rd_off++;
2098 }
2099 }
2100 GNUNET_free (cname_tmp);
2101 }
2102 break;
2103
2105 {
2106 struct GNUNET_DNSPARSER_SoaRecord *soa;
2107
2108 off = 0;
2110 rd[i].data_size,
2111 &off);
2112 if ((NULL == soa) ||
2113 (off != rd[i].data_size))
2114 {
2115 GNUNET_break_op (0); /* record not well-formed */
2116 }
2117 else
2118 {
2119 soa->mname = translate_dot_plus (rh, soa->mname);
2120 soa->rname = translate_dot_plus (rh, soa->rname);
2121 scratch_start = scratch_off;
2122 if (GNUNET_OK !=
2124 sizeof(scratch),
2125 &scratch_off,
2126 soa))
2127 {
2128 GNUNET_break (0);
2129 }
2130 else
2131 {
2132 GNUNET_assert (rd_off < rd_count);
2133 rd_new[rd_off].data = &scratch[scratch_start];
2134 rd_new[rd_off].data_size = scratch_off - scratch_start;
2135 rd_off++;
2136 }
2137 }
2138 if (NULL != soa)
2140 }
2141 break;
2142
2144 {
2145 struct GNUNET_DNSPARSER_MxRecord *mx;
2146
2147 off = 0;
2149 rd[i].data_size,
2150 &off);
2151 if ((NULL == mx) ||
2152 (off != rd[i].data_size))
2153 {
2154 GNUNET_break_op (0); /* record not well-formed */
2155 }
2156 else
2157 {
2158 mx->mxhost = translate_dot_plus (rh, mx->mxhost);
2159 scratch_start = scratch_off;
2160 if (GNUNET_OK !=
2162 sizeof(scratch),
2163 &scratch_off,
2164 mx))
2165 {
2166 GNUNET_break (0);
2167 }
2168 else
2169 {
2170 GNUNET_assert (rd_off < rd_count);
2171 rd_new[rd_off].data = &scratch[scratch_start];
2172 rd_new[rd_off].data_size = scratch_off - scratch_start;
2173 rd_off++;
2174 }
2175 }
2176 if (NULL != mx)
2178 }
2179 break;
2180
2182 {
2183 struct GNUNET_DNSPARSER_SrvRecord *srv;
2184
2185 off = 0;
2187 rd[i].data_size,
2188 &off);
2189 if ((NULL == srv) ||
2190 (off != rd[i].data_size))
2191 {
2192 GNUNET_break_op (0); /* record not well-formed */
2193 }
2194 else
2195 {
2196 srv->target = translate_dot_plus (rh, srv->target);
2197 scratch_start = scratch_off;
2198 if (GNUNET_OK !=
2200 sizeof(scratch),
2201 &scratch_off,
2202 srv))
2203 {
2204 GNUNET_break (0);
2205 }
2206 else
2207 {
2208 GNUNET_assert (rd_off < rd_count);
2209 rd_new[rd_off].data = &scratch[scratch_start];
2210 rd_new[rd_off].data_size = scratch_off - scratch_start;
2211 rd_off++;
2212 }
2213 }
2214 if (NULL != srv)
2216 }
2217 break;
2218
2220 {
2222
2223 off = 0;
2225 rd[i].data_size,
2226 &off);
2227 if ((NULL == uri) ||
2228 (off != rd[i].data_size))
2229 {
2231 _ ("Failed to deserialize URI record with target\n"));
2232 GNUNET_break_op (0); /* record not well-formed */
2233 }
2234 else
2235 {
2236 scratch_start = scratch_off;
2237 if (GNUNET_OK !=
2239 sizeof(scratch),
2240 &scratch_off,
2241 uri))
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 != uri)
2255 }
2256 break;
2257
2260 {
2262 if (rd[i].data_size < sizeof(uint32_t))
2263 {
2264 GNUNET_break_op (0);
2265 break;
2266 }
2267 if (GNUNET_OK !=
2269 rd[i].data_size,
2270 rd[i].record_type,
2271 &pubkey))
2272 {
2273 GNUNET_break_op (0);
2274 break;
2275 }
2276 rd_off++;
2277 if (rd[i].record_type != rh->record_type)
2278 {
2279 /* try to resolve "@" */
2280 struct AuthorityChain *ac;
2281
2282 ac = GNUNET_new (struct AuthorityChain);
2283 ac->rh = rh;
2288 rh->ac_tail,
2289 ac);
2291 rh);
2292 return;
2293 }
2294 }
2295 break;
2296
2298 {
2299 /* delegation to DNS */
2301 {
2302 rd_off++;
2303 break; /* do not follow to DNS, we wanted the GNS2DNS record! */
2304 }
2306 "Found GNS2DNS record, delegating to DNS!\n");
2307 if (GNUNET_OK ==
2309 rd_count,
2310 rd))
2311 return;
2312 else
2313 goto fail;
2314 }
2315
2317 {
2318 /* unbox SRV/TLSA records if a specific one was requested */
2319 if ((0 != rh->protocol) &&
2320 (0 != rh->service) &&
2321 (rd[i].data_size >= sizeof(struct GNUNET_GNSRECORD_BoxRecord)))
2322 {
2323 const struct GNUNET_GNSRECORD_BoxRecord *box;
2324
2325 box = rd[i].data;
2327 "Got BOX record, checking if parameters match... %u/%u vs %u/%u\n",
2328 ntohs (box->protocol), ntohs (box->service),
2329 rh->protocol, rh->service);
2330 if ((ntohs (box->protocol) == rh->protocol) &&
2331 (ntohs (box->service) == rh->service))
2332 {
2333 /* Box matches, unbox! */
2334 GNUNET_assert (rd_off < rd_count);
2335 rd_new[rd_off].record_type = ntohl (box->record_type);
2336 rd_new[rd_off].data_size -= sizeof(struct
2338 rd_new[rd_off].data = &box[1];
2339 rd_off++;
2340 }
2341 }
2342 else
2343 {
2344 /* no specific protocol/service specified, preserve all BOX
2345 records (for modern, GNS-enabled applications) */
2346 rd_off++;
2347 }
2348 break;
2349 }
2351 {
2352 /* unbox SBOX records if a specific one was requested */
2353 if ((rh->prefix != NULL) &&
2354 (rd[i].data_size >= sizeof(struct GNUNET_GNSRECORD_SBoxRecord)))
2355 {
2356 const struct GNUNET_GNSRECORD_SBoxRecord *box;
2357 const char *prefix;
2358 size_t prefix_len;
2359
2360 box = rd[i].data;
2361 prefix = rd[i].data + sizeof(struct GNUNET_GNSRECORD_SBoxRecord);
2362 prefix_len = strnlen (
2363 prefix,
2364 rd[i].data_size - sizeof(struct GNUNET_GNSRECORD_SBoxRecord)) + 1;
2365 if (prefix_len - 1 >= rd[i].data_size - sizeof(struct
2367 {
2369 "SBOX record with invalid prefix length, maybe not null-terminated\n");
2370 continue;
2371 }
2373 "Got SBOX record, checking if prefixes match... %s vs %s\n",
2374 prefix, rh->prefix);
2375 if (strcmp (rh->prefix, prefix) == 0)
2376 {
2377 /* Box matches, unbox! */
2378 GNUNET_assert (rd_off < rd_count);
2379 rd_new[rd_off].record_type = ntohl (box->record_type);
2380 rd_new[rd_off].data_size -= sizeof(struct
2382 + prefix_len;
2383 rd_new[rd_off].data = rd[i].data
2384 + sizeof(struct GNUNET_GNSRECORD_SBoxRecord)
2385 + prefix_len;
2386 rd_off++;
2387 }
2388 }
2389 else
2390 {
2392 _ (
2393 "GNS no specific protocol/service specified, preserve all SBOX `%s')\n"),
2394 rh->name);
2395 /* no specific protocol/service specified, preserve all SBOX
2396 records (for modern, GNS-enabled applications) */
2397 rd_off++;
2398 }
2399 break;
2400 }
2401 default:
2402 rd_off++;
2403 break;
2404 } /* end: switch */
2405 } /* end: for rd_count */
2406
2407 GNUNET_free (rh->prefix);
2408 rh->prefix = NULL;
2409
2410 /* yes, we are done, return result */
2412 "Returning GNS response for `%s' with %u answers\n",
2413 rh->ac_tail->label,
2414 rd_off);
2415 rh->proc (rh->proc_cls,
2416 rd_off,
2417 rd_new);
2419 rh);
2420 return;
2421 }
2422
2423 switch (rd[0].record_type)
2424 {
2426 GNUNET_break_op (1 == rd_count); /* REDIRECT should be unique */
2428 &rd[0]);
2429 return;
2430
2432 GNUNET_break_op (1 == rd_count); /* CNAME should be unique */
2434 &rd[0]);
2435 return;
2436
2439 GNUNET_break_op (1 == rd_count); /* PKEY should be unique */
2441 &rd[0]);
2442 return;
2443
2445 if (GNUNET_OK ==
2447 rd_count,
2448 rd))
2449 return;
2450 break;
2451 default:
2453 return;
2455 _ ("Unable to process critical delegation record\n"));
2456 break;
2457 }
2458fail:
2460 _ ("GNS lookup recursion failed (no delegation record found)\n"));
2461 fail_resolution (rh);
2462}
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:65
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:239
@ 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 1440 of file gnunet-service-gns_resolver.c.

1441{
1442 struct GNS_ResolverHandle *rh = ac->rh;
1443
1444 if ((NULL != ac->authority_info.dns_authority.gp_head) &&
1446 return; /* more pending and none found yet */
1448 {
1450 "Failed to resolve DNS server for `%s' in GNS2DNS resolution\n",
1452 fail_resolution (rh);
1453 return;
1454 }
1456 return; /* already running, do not launch again! */
1457 /* recurse */
1460 "Will continue resolution using DNS to resolve `%s'\n",
1461 ac->label);
1462 GNUNET_assert (NULL == rh->task_id);
1464 rh);
1465}
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 1477 of file gnunet-service-gns_resolver.c.

1480{
1481 struct Gns2DnsPending *gp = cls;
1482 struct AuthorityChain *ac = gp->ac;
1483
1486 gp);
1487 /* enable cleanup of 'rh' handle that automatically comes after we return,
1488 and which expects 'rh' to be in the #rlh_head DLL. */
1489 if (NULL != gp->rh)
1490 {
1492 rlh_tail,
1493 gp->rh);
1494 gp->rh = NULL;
1495 }
1496 GNUNET_free (gp);
1498 "Received %u results for IP address of DNS server for GNS2DNS transition\n",
1499 rd_count);
1500 /* find suitable A/AAAA record */
1501 for (unsigned int j = 0; j < rd_count; j++)
1502 {
1503 switch (rd[j].record_type)
1504 {
1506 {
1507 struct sockaddr_in v4;
1508
1509 if (sizeof(struct in_addr) != rd[j].data_size)
1510 {
1511 GNUNET_break_op (0);
1512 continue;
1513 }
1514 memset (&v4,
1515 0,
1516 sizeof(v4));
1517 v4.sin_family = AF_INET;
1518 v4.sin_port = htons (53);
1519#if HAVE_SOCKADDR_IN_SIN_LEN
1520 v4.sin_len = (u_char) sizeof(v4);
1521#endif
1522 GNUNET_memcpy (&v4.sin_addr,
1523 rd[j].data,
1524 sizeof(struct in_addr));
1525 if (GNUNET_OK ==
1528 (const struct sockaddr *) &v4))
1530 break;
1531 }
1532
1534 {
1535 struct sockaddr_in6 v6;
1536
1537 if (sizeof(struct in6_addr) != rd[j].data_size)
1538 {
1539 GNUNET_break_op (0);
1540 continue;
1541 }
1542 /* FIXME: might want to check if we support IPv6 here,
1543 and otherwise skip this one and hope we find another */
1544 memset (&v6,
1545 0,
1546 sizeof(v6));
1547 v6.sin6_family = AF_INET6;
1548 v6.sin6_port = htons (53);
1549#if HAVE_SOCKADDR_IN_SIN_LEN
1550 v6.sin6_len = (u_char) sizeof(v6);
1551#endif
1552 GNUNET_memcpy (&v6.sin6_addr,
1553 rd[j].data,
1554 sizeof(struct in6_addr));
1555 if (GNUNET_OK ==
1558 (const struct sockaddr *) &v6))
1560 break;
1561 }
1562
1563 default:
1564 break;
1565 }
1566 }
1568}
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 1579 of file gnunet-service-gns_resolver.c.

1582{
1583 struct Gns2DnsPending *gp = cls;
1584 struct AuthorityChain *ac = gp->ac;
1585 struct sockaddr_storage ss;
1586 struct sockaddr_in *v4;
1587 struct sockaddr_in6 *v6;
1588
1589 if (NULL == addr)
1590 {
1591 /* DNS resolution finished */
1592 if (0 == gp->num_results)
1594 "Failed to use DNS to resolve name of DNS resolver\n");
1597 gp);
1598 GNUNET_free (gp);
1600 return;
1601 }
1602 GNUNET_memcpy (&ss,
1603 addr,
1604 addrlen);
1605 switch (ss.ss_family)
1606 {
1607 case AF_INET:
1608 v4 = (struct sockaddr_in *) &ss;
1609 v4->sin_port = htons (53);
1610 gp->num_results++;
1611 break;
1612
1613 case AF_INET6:
1614 v6 = (struct sockaddr_in6 *) &ss;
1615 v6->sin6_port = htons (53);
1616 gp->num_results++;
1617 break;
1618
1619 default:
1621 "Unsupported AF %d\n",
1622 ss.ss_family);
1623 return;
1624 }
1625 if (GNUNET_OK ==
1627 (struct sockaddr *) &ss))
1629}
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 1639 of file gnunet-service-gns_resolver.c.

1641{
1643 rd->data);
1644}

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

1656{
1657 char *cname;
1658 size_t off;
1659
1660 off = 0;
1662 rd->data_size,
1663 &off);
1664 if ((NULL == cname) ||
1665 (off != rd->data_size))
1666 {
1667 GNUNET_break_op (0); /* record not well-formed */
1668 GNUNET_free (cname);
1669 fail_resolution (rh);
1670 return;
1671 }
1673 cname);
1674 GNUNET_free (cname);
1675}

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

1687{
1688 struct AuthorityChain *ac;
1689 struct GNUNET_CRYPTO_PublicKey auth;
1690
1691 /* delegation to another zone */
1693 rd->data_size,
1694 rd->record_type,
1695 &auth))
1696 {
1697 GNUNET_break_op (0);
1698 fail_resolution (rh);
1699 return;
1700 }
1701 /* expand authority chain */
1702 ac = GNUNET_new (struct AuthorityChain);
1703 ac->rh = rh;
1705 ac->authority_info.gns_authority = auth;
1707 /* add AC to tail */
1709 rh->ac_tail,
1710 ac);
1711 /* recurse */
1713 rh);
1714}

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

1731{
1732 struct AuthorityChain *ac;
1733 const char *tld;
1734 char *ns;
1735
1736 ns = NULL;
1737 /* expand authority chain */
1738 ac = GNUNET_new (struct AuthorityChain);
1739 ac->rh = rh;
1741
1742 for (unsigned int i = 0; i < rd_count; i++)
1743 {
1744 char *ip;
1745 char *n;
1746 size_t off;
1747 struct Gns2DnsPending *gp;
1748 struct GNUNET_CRYPTO_PublicKey zone;
1749 struct sockaddr_in v4;
1750 struct sockaddr_in6 v6;
1751
1752 if (GNUNET_GNSRECORD_TYPE_GNS2DNS != rd[i].record_type)
1753 {
1757 GNUNET_free (ns);
1758 GNUNET_free (ac);
1759 return GNUNET_SYSERR;
1760 }
1761 off = 0;
1763 rd[i].data_size,
1764 &off);
1765 ip = GNUNET_strdup (&((const char *) rd[i].data)[off]);
1766 if ((NULL == n) ||
1767 (NULL == ip))
1768 {
1769 GNUNET_break_op (0);
1770 GNUNET_free (n);
1771 GNUNET_free (ip);
1772 continue;
1773 }
1774
1775 off += strlen (ip) + 1;
1776
1777 if (off != rd[i].data_size)
1778 {
1779 GNUNET_break_op (0);
1780 GNUNET_free (n);
1781 GNUNET_free (ip);
1782 continue;
1783 }
1784 /* resolve 'ip' to determine the IP(s) of the DNS
1785 resolver to use for lookup of 'ns' */
1786 if (NULL != ns)
1787 {
1788 if (0 != strcasecmp (ns,
1789 n))
1790 {
1791 /* NS values must all be the same for all GNS2DNS records,
1792 anything else leads to insanity */
1793 GNUNET_break_op (0);
1794 GNUNET_free (n);
1795 GNUNET_free (ip);
1796 continue;
1797 }
1798 GNUNET_free (n);
1799 }
1800 else
1801 {
1802 ns = n;
1803 }
1804
1805 /* check if 'ip' is already an IPv4/IPv6 address */
1806 if ((1 == inet_pton (AF_INET,
1807 ip,
1808 &v4)) ||
1809 (1 == inet_pton (AF_INET6,
1810 ip,
1811 &v6)))
1812 {
1816 ip));
1818 GNUNET_free (ip);
1819 continue;
1820 }
1821 tld = GNS_get_tld (ip);
1822 if ((0 != strcmp (tld, "+")) &&
1823 (GNUNET_OK != GNUNET_GNSRECORD_zkey_to_pkey (tld, &zone)))
1824 {
1825 /* 'ip' is a DNS name */
1826 gp = GNUNET_new (struct Gns2DnsPending);
1827 gp->ac = ac;
1830 gp);
1832 AF_UNSPEC,
1835 gp);
1836 GNUNET_free (ip);
1837 continue;
1838 }
1839 /* 'ip' should be a GNS name */
1840 gp = GNUNET_new (struct Gns2DnsPending);
1841 gp->ac = ac;
1844 gp);
1845 gp->rh = GNUNET_new (struct GNS_ResolverHandle);
1846 if (0 == strcmp (tld, "+"))
1847 {
1848 ip = translate_dot_plus (rh,
1849 ip);
1850 tld = GNS_get_tld (ip);
1851 if (GNUNET_OK !=
1853 &zone))
1854 {
1855 GNUNET_break_op (0);
1856 GNUNET_free (ip);
1857 continue;
1858 }
1859 }
1860 gp->rh->authority_zone = zone;
1862 "Resolving `%s' to determine IP address of DNS server for GNS2DNS transition for `%s'\n",
1863 ip,
1864 ns);
1865 gp->rh->name = ip;
1866 gp->rh->name_resolution_pos = strlen (ip) - strlen (tld) - 1;
1868 gp->rh->proc_cls = gp;
1871 gp->rh->loop_limiter = rh->loop_limiter + 1;
1872 gp->rh->loop_threshold = rh->loop_threshold;
1873 gp->rh->task_id
1875 gp->rh);
1876 } /* end 'for all records' */
1877
1878 if (NULL == ns)
1879 {
1880 /* not a single GNS2DNS record found */
1881 GNUNET_free (ac);
1882 return GNUNET_SYSERR;
1883 }
1885 strcpy (ac->authority_info.dns_authority.name,
1886 ns);
1887 /* for DNS recursion, the label is the full DNS name,
1888 created from the remainder of the GNS name and the
1889 name in the NS record */
1890 GNUNET_asprintf (&ac->label,
1891 "%.*s%s%s",
1892 (int) rh->name_resolution_pos,
1893 rh->name,
1894 (0 != rh->name_resolution_pos) ? "." : "",
1895 ns);
1896 GNUNET_free (ns);
1897
1898 {
1899 /* the GNS name is UTF-8 and may include multibyte chars.
1900 * We have to convert the combined name to a DNS-compatible IDNA.
1901 */
1902 char *tmp = ac->label;
1903
1904 if (IDNA_SUCCESS != idna_to_ascii_8z (tmp,
1905 &ac->label,
1906 IDNA_ALLOW_UNASSIGNED))
1907 {
1909 _ ("Name `%s' cannot be converted to IDNA."),
1910 tmp);
1911 GNUNET_free (tmp);
1912 GNUNET_free (ac);
1913 return GNUNET_SYSERR;
1914 }
1915 GNUNET_free (tmp);
1916 }
1917
1919 rh->ac_tail,
1920 ac);
1921 if (strlen (ac->label) > GNUNET_DNSPARSER_MAX_NAME_LENGTH)
1922 {
1924 _ ("GNS lookup resulted in DNS name that is too long (`%s')\n"),
1925 ac->label);
1926 GNUNET_free (ac->label);
1927 GNUNET_free (ac);
1928 return GNUNET_SYSERR;
1929 }
1931 return GNUNET_OK;
1932}
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 2474 of file gnunet-service-gns_resolver.c.

2477{
2478 struct CacheOps *co = cls;
2479
2480 co->namecache_qe_cache = NULL;
2481 if (GNUNET_OK != success)
2483 _ ("Failed to cache GNS resolution: %s\n"),
2484 emsg);
2486 co_tail,
2487 co);
2488 GNUNET_free (co);
2489}
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 2511 of file gnunet-service-gns_resolver.c.

2522{
2523 struct GNS_ResolverHandle *rh = cls;
2524 struct AuthorityChain *ac = rh->ac_tail;
2525 const struct GNUNET_GNSRECORD_Block *block;
2526 struct CacheOps *co;
2527
2528 (void) exp;
2529 (void) key;
2530 (void) get_path;
2531 (void) get_path_length;
2532 (void) put_path;
2533 (void) put_path_length;
2534 (void) type;
2536 rh->get_handle = NULL;
2538 rh->dht_heap_node = NULL;
2540 "Handling response from the DHT\n");
2541 if (size < sizeof(struct GNUNET_GNSRECORD_Block))
2542 {
2543 /* how did this pass DHT block validation!? */
2544 GNUNET_break (0);
2545 fail_resolution (rh);
2546 return;
2547 }
2548 block = data;
2550 {
2551 /* how did this pass DHT block validation!? */
2552 GNUNET_break (0);
2553 fail_resolution (rh);
2554 return;
2555 }
2557 "Decrypting DHT block of size %llu for `%s', expires %s\n",
2558 (unsigned long long) GNUNET_GNSRECORD_block_get_size (block),
2559 rh->name,
2561 if (GNUNET_OK !=
2564 ac->label,
2566 rh))
2567 {
2568 GNUNET_break_op (0); /* block was ill-formed */
2569 fail_resolution (rh);
2570 return;
2571 }
2574 rel_value_us)
2575 {
2577 "Received expired block from the DHT, will not cache it.\n");
2578 return;
2579 }
2581 return;
2582 /* Cache well-formed blocks */
2584 "Caching response from the DHT in namecache\n");
2585 co = GNUNET_new (struct CacheOps);
2587 block,
2588 &
2590 co);
2592 co_tail,
2593 co);
2594}
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:1233
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:406
const char * GNUNET_STRINGS_absolute_time_to_string(struct GNUNET_TIME_Absolute t)
Like asctime, except for GNUnet time.
Definition: strings.c:640
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 2604 of file gnunet-service-gns_resolver.c.

2606{
2607 struct GNS_ResolverHandle *rx;
2608
2609 GNUNET_assert (NULL == rh->get_handle);
2612 query,
2615 NULL, 0,
2616 &handle_dht_response, rh);
2618 rh,
2620 abs_value_us);
2623 {
2624 /* fail longest-standing DHT request */
2626 rx->dht_heap_node = NULL;
2627 GNUNET_assert (NULL != rx);
2628 fail_resolution (rx);
2629 }
2630}
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:1160
@ 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 2642 of file gnunet-service-gns_resolver.c.

2645{
2646 struct GNS_ResolverHandle *rh = cls;
2647
2648 if (0 == rd_count)
2650 _ ("GNS namecache returned empty result for `%s'\n"),
2651 rh->name);
2653 rd_count,
2654 rd);
2655}

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

2667{
2668 struct GNS_ResolverHandle *rh = cls;
2669 struct AuthorityChain *ac = rh->ac_tail;
2670 const char *label = ac->label;
2671 const struct GNUNET_CRYPTO_PublicKey *auth =
2673 struct GNUNET_HashCode query;
2674
2675 GNUNET_assert (NULL != rh->namecache_qe);
2676 rh->namecache_qe = NULL;
2677 if (NULL == block)
2679 "No block found\n");
2680 else
2682 "Got block with expiration %s\n",
2685 if (((GNUNET_GNS_LO_DEFAULT == rh->options) ||
2687 (ac != rh->ac_head))) &&
2688 ((NULL == block) ||
2691 rel_value_us)))
2692 {
2693 /* namecache knows nothing; try DHT lookup */
2695 label,
2696 &query);
2698 "Starting DHT lookup for `%s' in zone `%s' under key `%s'\n",
2699 ac->label,
2701 GNUNET_h2s (&query));
2702 start_dht_request (rh, &query);
2703 return;
2704 }
2705
2706 if ((NULL == block) ||
2709 rel_value_us))
2710 {
2711 /* DHT not permitted and no local result, fail */
2713 "Resolution failed for `%s' in zone %s (DHT lookup not permitted by configuration)\n",
2714 ac->label,
2716 fail_resolution (rh);
2717 return;
2718 }
2720 "Received result from namecache for label `%s'\n",
2721 ac->label);
2722
2723 if (GNUNET_OK !=
2725 auth,
2726 label,
2728 rh))
2729 {
2730 GNUNET_break_op (0); /* block was ill-formed */
2731 /* try DHT instead */
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}
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 2752 of file gnunet-service-gns_resolver.c.

2753{
2754 struct AuthorityChain *ac = rh->ac_tail;
2755 struct GNUNET_HashCode query;
2756
2758 "Starting GNS resolution for `%s' in zone %s\n",
2759 ac->label,
2762 ac->label,
2763 &query);
2765 {
2766 rh->namecache_qe
2768 &query,
2770 rh);
2771 GNUNET_assert (NULL != rh->namecache_qe);
2772 }
2773 else
2774 {
2776 &query);
2777 }
2778}
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 2788 of file gnunet-service-gns_resolver.c.

2790{
2791 struct GNS_ResolverHandle *rh = cls;
2792 struct AuthorityChain *ac = rh->ac_tail;
2793
2794 rh->rev_check = NULL;
2795 if (GNUNET_YES != is_valid)
2796 {
2798 _ ("Zone %s was revoked, resolution fails\n"),
2801 return;
2802 }
2804}
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 2813 of file gnunet-service-gns_resolver.c.

2814{
2815 struct AuthorityChain *ac = rh->ac_tail;
2816
2818 "Starting revocation check for zone %s\n",
2823 rh);
2824 GNUNET_assert (NULL != rh->rev_check);
2825}
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 2931 of file gnunet-service-gns_resolver.c.

2938{
2939 struct GNS_ResolverHandle *rh;
2940
2942 "Starting lookup for `%s'\n",
2943 name);
2944 rh = GNUNET_new (struct GNS_ResolverHandle);
2946 rlh_tail,
2947 rh);
2948 rh->authority_zone = *zone;
2949 rh->proc = proc;
2950 rh->proc_cls = proc_cls;
2951 rh->options = options;
2953 rh->name = GNUNET_strdup (name);
2954 rh->name_resolution_pos = strlen (name);
2955 rh->loop_threshold = recursion_depth_limit;
2957 rh);
2958 return rh;
2959}
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 2968 of file gnunet-service-gns_resolver.c.

2969{
2970 struct DnsResult *dr;
2971 struct AuthorityChain *ac;
2972
2974 rlh_tail,
2975 rh);
2976 if (NULL != rh->dns_request)
2977 {
2979 rh->dns_request = NULL;
2980 }
2981 while (NULL != (ac = rh->ac_head))
2982 {
2984 rh->ac_tail,
2985 ac);
2986 if (GNUNET_NO == ac->gns_authority)
2987 {
2988 struct Gns2DnsPending *gp;
2989
2990 while (NULL != (gp = ac->authority_info.dns_authority.gp_head))
2991 {
2994 gp);
2995 if (NULL != gp->rh)
2996 {
2997 /* rh->g2dc->rh is NOT in the DLL yet, so to enable us
2998 using GNS_resolver_lookup_cancel here, we need to
2999 add it first... */
3001 rlh_tail,
3002 gp->rh);
3003 GNUNET_assert (NULL == gp->rh->task_id);
3006 gp->rh);
3007 gp->rh = NULL;
3008 }
3009 if (NULL != gp->dns_rh)
3010 {
3012 gp->dns_rh = NULL;
3013 }
3014 GNUNET_free (gp);
3015 }
3017 }
3018 GNUNET_free (ac->label);
3019 GNUNET_free (ac);
3020 }
3021 if (NULL != rh->task_id)
3022 {
3024 rh->task_id = NULL;
3025 }
3026 if (NULL != rh->get_handle)
3027 {
3029 rh->get_handle = NULL;
3030 }
3031 if (NULL != rh->dht_heap_node)
3032 {
3034 rh->dht_heap_node = NULL;
3035 }
3036 if (NULL != rh->namecache_qe)
3037 {
3039 rh->namecache_qe = NULL;
3040 }
3041 if (NULL != rh->rev_check)
3042 {
3044 rh->rev_check = NULL;
3045 }
3046 if (NULL != rh->std_resolve)
3047 {
3049 "Canceling standard DNS resolution\n");
3051 rh->std_resolve = NULL;
3052 }
3053 while (NULL != (dr = rh->dns_result_head))
3054 {
3057 dr);
3058 GNUNET_free (dr);
3059 }
3060 if (NULL != rh->prefix)
3061 {
3063 rh->prefix = NULL;
3064 }
3065 GNUNET_free (rh->leho);
3066 GNUNET_free (rh->name);
3067 GNUNET_free (rh);
3068}
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 3083 of file gnunet-service-gns_resolver.c.

3087{
3088 cfg = c;
3090 dht_handle = dht;
3093 max_allowed_background_queries = max_bg_queries;
3095 "namecache",
3096 "DISABLE");
3099 "Namecache disabled\n");
3100}
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 3107 of file gnunet-service-gns_resolver.c.

3108{
3109 struct GNS_ResolverHandle *rh;
3110 struct CacheOps *co;
3111
3112 /* abort active resolutions */
3113 while (NULL != (rh = rlh_head))
3114 {
3115 rh->proc (rh->proc_cls,
3116 0,
3117 NULL);
3119 }
3120 while (NULL != (co = co_head))
3121 {
3123 co_tail,
3124 co);
3126 GNUNET_free (co);
3127 }
3129 dht_lookup_heap = NULL;
3130 dht_handle = NULL;
3131 namecache_handle = NULL;
3132}
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 424 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 429 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 434 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 439 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 444 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 449 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 454 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 459 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 469 of file gnunet-service-gns_resolver.c.

Referenced by GNS_resolver_init(), and recursive_gns_resolution_revocation().