GNUnet 0.28.1-dev.4-47-g3e168ca2d
 
Loading...
Searching...
No Matches
gnunet-service-gns_resolver.c File Reference

GNU Name System resolver logic. More...

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...
 
struct  RefreshOps
 Background lookup for a fresher version of a block that is still in the namecache but about to expire. More...
 

Macros

#define DHT_LOOKUP_TIMEOUT
 Default DHT timeout for lookups.
 
#define DHT_LOOKUP_RETRIES   2
 How often do we restart a DHT lookup that stayed unanswered for DHT_LOOKUP_TIMEOUT before we give up on the name?
 
#define DNS_LOOKUP_TIMEOUT
 Default timeout for DNS lookups.
 
#define DHT_GNS_REPLICATION_LEVEL   10
 DHT replication level.
 
#define BLOCK_REFRESH_THRESHOLD
 If a block we found in the namecache expires within this time, look for a fresher version of it in the DHT while we answer from the cache.
 
#define BLOCK_REFRESH_TIMEOUT
 How long do we leave a background refresh GET running?
 

Functions

static char * translate_dot_plus (struct GNS_ResolverHandle *rh, char *name)
 Expands a name ending in .
 
static void GNS_resolver_lookup_cancel_ (void *cls)
 Wrapper around GNS_resolver_lookup_cancel() as a task.
 
static void fail_resolution (struct GNS_ResolverHandle *rh)
 Function called to asynchronously fail a resolution.
 
static void timeout_resolution (void *cls)
 Function called when a resolution times out.
 
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.
 
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.
 
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.
 
static void handle_dns_result (void *cls, const struct sockaddr *addr, socklen_t addrlen)
 We had to do a DNS lookup.
 
static void recursive_resolution (void *cls)
 Task scheduled to continue with the resolution process.
 
static void start_resolver_lookup (void *cls)
 Begin the resolution process from 'name', starting with the identification of the zone specified by 'name'.
 
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 recursive_dns_resolution (struct GNS_ResolverHandle *rh)
 Perform recursive DNS resolution.
 
static void handle_gns_redirect_result (struct GNS_ResolverHandle *rh, const char *rname)
 We encountered a REDIRECT record during our resolution.
 
static void handle_gns_cname_result (struct GNS_ResolverHandle *rh, const char *cname)
 We encountered a CNAME record during our resolution.
 
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 void continue_with_gns2dns (struct AuthorityChain *ac)
 We have resolved one or more of the nameservers for a GNS2DNS lookup.
 
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.
 
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 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 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 recursive_pkey_resolution (struct GNS_ResolverHandle *rh, const struct GNUNET_GNSRECORD_Data *rd)
 We found a PKEY record, perform recursive resolution on it.
 
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.
 
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_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.
 
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 dht_lookup_timeout (void *cls)
 The DHT did not answer within DHT_LOOKUP_TIMEOUT.
 
static void refresh_stop (struct RefreshOps *ro)
 End a background refresh.
 
static void refresh_timeout (void *cls)
 Nothing fresher showed up in time.
 
static void handle_refresh_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)
 A background refresh returned a block.
 
static void start_refresh (const struct GNUNET_HashCode *query, struct GNUNET_TIME_Absolute expiration)
 Ask the DHT for a fresher version of query while we answer from a namecache entry that is about to expire.
 
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.
 
static void handle_namecache_block_response (void *cls, const struct GNUNET_GNSRECORD_Block *block)
 Process a record that was stored in the namecache.
 
static void recursive_gns_resolution_namecache (struct GNS_ResolverHandle *rh)
 Lookup tail of our authority chain in the namecache.
 
static void handle_revocation_result (void *cls, int is_valid)
 Function called with the result from a revocation check.
 
static void recursive_gns_resolution_revocation (struct GNS_ResolverHandle *rh)
 Perform revocation check on tail of our authority chain.
 
struct GNS_ResolverHandleGNS_resolver_lookup (const struct GNUNET_CRYPTO_BlindablePublicKey *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.
 
void GNS_resolver_lookup_cancel (struct GNS_ResolverHandle *rh)
 Cancel active resolution (i.e.
 
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.
 
void GNS_resolver_done ()
 Shutdown resolver.
 

Variables

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

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.

105{
109 struct Gns2DnsPending *next;
110
114 struct Gns2DnsPending *prev;
115
119 struct AuthorityChain *ac;
120
126 struct GNS_ResolverHandle *rh;
127
131 struct GNUNET_RESOLVER_RequestHandle *dns_rh;
132
136 unsigned int num_results;
137};
138
139
144struct GNS_ResolverHandle;
145
146
151struct AuthorityChain
152{
156 struct AuthorityChain *prev;
157
161 struct AuthorityChain *next;
162
166 struct GNS_ResolverHandle *rh;
167
171 char *label;
172
177 int gns_authority;
178
182 union
183 {
188
189 struct
190 {
197
202 struct Gns2DnsPending *gp_head;
203
208 struct Gns2DnsPending *gp_tail;
209
214
219 int found;
220
224 int launched;
227};
228
229
233struct DnsResult
234{
238 struct DnsResult *next;
239
243 struct DnsResult *prev;
244
248 const void *data;
249
254 uint64_t expiration_time;
255
259 size_t data_size;
260
264 uint32_t record_type;
265};
266
267
273{
277 struct GNS_ResolverHandle *next;
278
282 struct GNS_ResolverHandle *prev;
283
288
293
297 void *proc_cls;
298
303
304
309
314
319
324
330
336
340 struct AuthorityChain *ac_head;
341
345 struct AuthorityChain *ac_tail;
346
351
355 char *name;
356
361 char *leho;
362
367
372
376 size_t name_resolution_pos;
377
382
387 int protocol;
388
393 int service;
394
398 char *prefix;
399
400
404 int record_type;
405
411 unsigned int loop_limiter;
412
416 unsigned int loop_threshold;
417
422 unsigned int dht_retries;
423
427 uint16_t original_dns_id;
428};
429
430
434struct CacheOps
435{
439 struct CacheOps *next;
440
444 struct CacheOps *prev;
445
450};
451
452
458struct RefreshOps
459{
463 struct RefreshOps *next;
464
468 struct RefreshOps *prev;
469
474
479
483 struct GNUNET_HashCode query;
484
489};
490
491
496
500static struct GNUNET_DHT_Handle *dht_handle;
501
506
510static unsigned long long max_allowed_background_queries;
511
515static struct GNS_ResolverHandle *rlh_head;
516
520static struct GNS_ResolverHandle *rlh_tail;
521
525static struct CacheOps *co_head;
526
530static struct CacheOps *co_tail;
531
535static struct RefreshOps *ro_head;
536
540static struct RefreshOps *ro_tail;
541
545static int disable_cache;
546
550static const struct GNUNET_CONFIGURATION_Handle *cfg;
551
552
553/* ************************** Resolution **************************** */
554
562static char *
564 char *name)
565{
566 char *ret;
567 size_t s_len = strlen (name);
568
569 if (0 != strcmp (&name[s_len - 2],
570 ".+"))
571 return name; /* did not end in ".+" */
574 "%.*s.%s",
575 (int) (s_len - 2),
576 name,
580 return ret;
581}
582
583
590static void
592{
593 struct GNS_ResolverHandle *rh = cls;
594
595 rh->task_id = NULL;
597}
598
599
605static void
607{
608 rh->proc (rh->proc_cls,
609 0,
610 NULL);
611 GNUNET_assert (NULL == rh->task_id);
613 rh);
614}
615
616
622static void
623timeout_resolution (void *cls)
624{
625 struct GNS_ResolverHandle *rh = cls;
626
627 rh->task_id = NULL;
628 fail_resolution (rh);
629}
630
631
637static int
638resolver_getprotobyname (const char *name)
639{
640 struct protoent *pe = getprotobyname (name);
641 if (pe == NULL)
642 {
644 }
645 return pe->p_proto;
646}
647
648
655static int
656resolver_getservbyname (const char *name, const char *proto)
657{
658 struct servent *se = getservbyname (name, proto);
659 if (se == NULL)
660 {
662 }
663 return se->s_port;
664}
665
666
685static char *
687{
688 const char *rp;
689 const char *dot;
690 size_t len;
691 char *ret;
692 char *srv_name;
693 char *proto_name;
694 int protocol;
695 int service;
696
697 if (0 == rh->name_resolution_pos)
698 return NULL;
699 dot = memrchr (rh->name,
700 (int) '.',
702 if (NULL == dot)
703 {
704 /* done, this was the last one */
705 len = rh->name_resolution_pos;
706 rp = rh->name;
707 rh->name_resolution_pos = 0;
708 }
709 else if ('_' == dot[1])
710 {
719 len = strlen (GNUNET_GNS_EMPTY_LABEL_AT);
720 }
721 else
722 {
723 /* advance by one label */
724 len = rh->name_resolution_pos - (dot - rh->name) - 1;
725 rp = dot + 1;
726 rh->name_resolution_pos = dot - rh->name;
727 }
728 rh->protocol = 0;
729 rh->service = 0;
730 rh->prefix = NULL;
731 ret = GNUNET_strndup (rp, len);
736 if (('_' == rh->name[0]) &&
737 (NULL != (dot = memrchr (rh->name,
738 (int) '.',
739 rh->name_resolution_pos))) &&
740 ('_' == dot[1]) &&
741 (NULL == memrchr (rh->name,
742 (int) '.',
743 dot - rh->name)))
744 {
745 srv_name = GNUNET_strndup (&rh->name[1],
746 (dot - rh->name) - 1);
747 proto_name = GNUNET_strndup (&dot[2],
748 rh->name_resolution_pos - (dot - rh->name)
749 - 2);
750 protocol = resolver_getprotobyname (proto_name);
751 if (0 == protocol)
752 {
754 _ (
755 "Protocol `%s' unknown, skipping labels as BOX retain as SBOX.\n"),
756 proto_name);
757 GNUNET_free (proto_name);
758 GNUNET_free (srv_name);
760 rh->name_resolution_pos = 0;
761 return ret;
762 }
764 proto_name);
765 if (0 == service)
766 {
768 _ (
769 "Service `%s' unknown for protocol `%s', trying as number.\n"),
770 srv_name,
771 proto_name);
772 if (1 != sscanf (srv_name, "%u", &rh->service))
773 {
775 _ (
776 "Service `%s' not a port, skipping service labels as BOX retain as SBOX.\n"),
777 srv_name);
778 GNUNET_free (proto_name);
779 GNUNET_free (srv_name);
781 rh->name_resolution_pos = 0;
782 return ret;
783 }
784 }
785 else
786 {
787 rh->service = ntohs (service);
788 }
789 rh->protocol = protocol;
790 GNUNET_free (proto_name);
791 GNUNET_free (srv_name);
792 }
799 if ((NULL != (dot = memrchr (rh->name,
800 (int) '.',
801 rh->name_resolution_pos)) && '_' == dot[1]) ||
802 ((NULL == memrchr (rh->name,
803 (int) '.',
804 rh->name_resolution_pos)) && '_' == rh->name[0]))
805 {
807 rh->name_resolution_pos = 0;
808 }
809 return ret;
810}
811
812
818static void
820{
821 struct DnsResult *pos;
822 unsigned int n;
823 unsigned int i;
824
825 n = 0;
826 for (pos = rh->dns_result_head; NULL != pos; pos = pos->next)
827 n++;
828 {
829 struct GNUNET_GNSRECORD_Data rd[n];
830
831 i = 0;
832 for (pos = rh->dns_result_head; NULL != pos; pos = pos->next)
833 {
834 rd[i].data = pos->data;
835 rd[i].data_size = pos->data_size;
836 rd[i].record_type = pos->record_type;
844 if (0 == pos->expiration_time)
845 {
847 rd[i].expiration_time = 0;
848 }
849 else
850 {
852 }
853 i++;
854 }
855 GNUNET_assert (i == n);
857 "Transmitting standard DNS result with %u records\n",
858 n);
859 rh->proc (rh->proc_cls,
860 n,
861 rd);
862 }
864}
865
866
876static void
878 uint64_t expiration_time,
879 uint32_t record_type,
880 size_t data_size,
881 const void *data)
882{
883 struct DnsResult *res;
884
885 res = GNUNET_malloc (sizeof(struct DnsResult) + data_size);
886 res->expiration_time = expiration_time;
887 res->data_size = data_size;
888 res->record_type = record_type;
889 res->data = &res[1];
890 GNUNET_memcpy (&res[1],
891 data,
892 data_size);
894 rh->dns_result_tail,
895 res);
896}
897
898
907static void
908handle_dns_result (void *cls,
909 const struct sockaddr *addr,
910 socklen_t addrlen)
911{
912 struct GNS_ResolverHandle *rh = cls;
913 const struct sockaddr_in *sa4;
914 const struct sockaddr_in6 *sa6;
915
916 if (NULL == addr)
917 {
918 rh->std_resolve = NULL;
920 return;
921 }
923 "Received %u bytes of DNS IP data\n",
924 addrlen);
925 switch (addr->sa_family)
926 {
927 case AF_INET:
928 sa4 = (const struct sockaddr_in *) addr;
929 add_dns_result (rh,
930 0 /* expiration time is unknown */,
932 sizeof(struct in_addr),
933 &sa4->sin_addr);
934 break;
935
936 case AF_INET6:
937 sa6 = (const struct sockaddr_in6 *) addr;
938 add_dns_result (rh,
939 0 /* expiration time is unknown */,
941 sizeof(struct in6_addr),
942 &sa6->sin6_addr);
943 break;
944
945 default:
946 GNUNET_break (0);
947 break;
948 }
949}
950
951
957static void
958recursive_resolution (void *cls);
959
960
967static void
968start_resolver_lookup (void *cls);
969
970
979static void
980dns_result_parser (void *cls,
981 const struct GNUNET_TUN_DnsHeader *dns,
982 size_t dns_len)
983{
984 struct GNS_ResolverHandle *rh = cls;
986 const struct GNUNET_DNSPARSER_Record *rec;
987 unsigned int rd_count;
988
989 if (NULL == dns)
990 {
991 rh->dns_request = NULL;
993 rh->task_id = NULL;
994 fail_resolution (rh);
995 return;
996 }
997 if (rh->original_dns_id != dns->id)
998 {
999 /* DNS answer, but for another query */
1000 return;
1001 }
1002 p = GNUNET_DNSPARSER_parse ((const char *) dns,
1003 dns_len);
1004 if (NULL == p)
1005 {
1007 _ ("Failed to parse DNS response\n"));
1008 return;
1009 }
1010
1011 /* We got a result from DNS */
1013 "Received DNS response for `%s' with %u answers\n",
1014 rh->ac_tail->label,
1015 (unsigned int) p->num_answers);
1016 if ((p->num_answers > 0) &&
1017 (GNUNET_DNSPARSER_TYPE_CNAME == p->answers[0].type) &&
1019 {
1020 int af;
1021
1023 "Got CNAME `%s' from DNS for `%s'\n",
1024 p->answers[0].data.hostname,
1025 rh->name);
1026 if (NULL != rh->std_resolve)
1027 {
1029 "Multiple CNAME results from DNS resolving `%s'! Not really allowed...\n",
1030 rh->name);
1032 }
1033 GNUNET_free (rh->name);
1034 rh->name = GNUNET_strdup (p->answers[0].data.hostname);
1035 rh->name_resolution_pos = strlen (rh->name);
1036 switch (rh->record_type)
1037 {
1039 af = AF_INET;
1040 break;
1041
1043 af = AF_INET6;
1044 break;
1045
1046 default:
1047 af = AF_UNSPEC;
1048 break;
1049 }
1050 if (NULL != rh->leho)
1051 add_dns_result (rh,
1052 GNUNET_TIME_UNIT_HOURS.rel_value_us,
1054 strlen (rh->leho),
1055 rh->leho);
1057 af,
1060 rh);
1063 rh->dns_request = NULL;
1064 return;
1065 }
1066
1067 /* convert from (parsed) DNS to (binary) GNS format! */
1068 rd_count = p->num_answers + p->num_authority_records
1069 + p->num_additional_records;
1070 {
1071 struct GNUNET_GNSRECORD_Data rd[rd_count + 1]; /* +1 for LEHO */
1072 int skip;
1073 char buf[UINT16_MAX];
1074 char *name_ace;
1075 size_t buf_off;
1076 size_t buf_start;
1077
1078 buf_off = 0;
1079 skip = 0;
1080 memset (rd,
1081 0,
1082 sizeof(rd));
1083 for (unsigned int i = 0; i < rd_count; i++)
1084 {
1085 if (i < p->num_answers)
1086 rec = &p->answers[i];
1087 else if (i < p->num_answers + p->num_authority_records)
1088 rec = &p->authority_records[i - p->num_answers];
1089 else
1090 rec = &p->additional_records[i - p->num_answers
1091 - p->num_authority_records];
1092 /* As we copied the full DNS name to 'rh->ac_tail->label', this
1093 should be the correct check to see if this record is actually
1094 a record for our label...
1095 However, DNSPARSER will convert the ACE name to UTF-8 so
1096 we must convert back.
1097 */
1098 if (IDNA_SUCCESS != idna_to_ascii_8z (rec->name,
1099 &name_ace,
1100 IDNA_ALLOW_UNASSIGNED))
1101 {
1103 _ ("Name `%s' cannot be converted to IDNA."),
1104 rec->name);
1105 continue;
1106 }
1107
1108 if (0 != strcmp (name_ace,
1109 rh->ac_tail->label))
1110 {
1112 "Dropping record `%s', does not match desired name `%s'\n",
1113 rec->name,
1114 rh->ac_tail->label);
1115 skip++;
1116 continue;
1117 }
1118 rd[i - skip].record_type = rec->type;
1120 switch (rec->type)
1121 {
1123 if (rec->data.raw.data_len != sizeof(struct in_addr))
1124 {
1125 GNUNET_break_op (0);
1126 skip++;
1127 continue;
1128 }
1129 rd[i - skip].data_size = rec->data.raw.data_len;
1130 rd[i - skip].data = rec->data.raw.data;
1131 break;
1132
1134 if (rec->data.raw.data_len != sizeof(struct in6_addr))
1135 {
1136 GNUNET_break_op (0);
1137 skip++;
1138 continue;
1139 }
1140 rd[i - skip].data_size = rec->data.raw.data_len;
1141 rd[i - skip].data = rec->data.raw.data;
1142 break;
1143
1147 buf_start = buf_off;
1148 if (GNUNET_OK !=
1150 sizeof(buf),
1151 &buf_off,
1152 rec->data.hostname))
1153 {
1154 GNUNET_break (0);
1155 skip++;
1156 continue;
1157 }
1158 rd[i - skip].data_size = buf_off - buf_start;
1159 rd[i - skip].data = &buf[buf_start];
1160 break;
1161
1163 buf_start = buf_off;
1164 if (GNUNET_OK !=
1166 sizeof(buf),
1167 &buf_off,
1168 rec->data.soa))
1169 {
1170 GNUNET_break (0);
1171 skip++;
1172 continue;
1173 }
1174 rd[i - skip].data_size = buf_off - buf_start;
1175 rd[i - skip].data = &buf[buf_start];
1176 break;
1177
1179 buf_start = buf_off;
1180 if (GNUNET_OK !=
1182 sizeof(buf),
1183 &buf_off,
1184 rec->data.mx))
1185 {
1186 GNUNET_break (0);
1187 skip++;
1188 continue;
1189 }
1190 rd[i - skip].data_size = buf_off - buf_start;
1191 rd[i - skip].data = &buf[buf_start];
1192 break;
1193
1195 buf_start = buf_off;
1196 if (GNUNET_OK !=
1198 sizeof(buf),
1199 &buf_off,
1200 rec->data.srv))
1201 {
1202 GNUNET_break (0);
1203 skip++;
1204 continue;
1205 }
1206 rd[i - skip].data_size = buf_off - buf_start;
1207 rd[i - skip].data = &buf[buf_start];
1208 break;
1209
1211 buf_start = buf_off;
1212 if (GNUNET_OK !=
1214 sizeof(buf),
1215 &buf_off,
1216 rec->data.uri))
1217 {
1218 GNUNET_break (0);
1219 skip++;
1220 continue;
1221 }
1222 rd[i - skip].data_size = buf_off - buf_start;
1223 rd[i - skip].data = &buf[buf_start];
1224 break;
1225
1226 default:
1228 _ ("Skipping record of unsupported type %d\n"),
1229 rec->type);
1230 skip++;
1231 continue;
1232 }
1233 } /* end of for all records in answer */
1234 if (NULL != rh->leho)
1235 {
1239 rd[rd_count - skip].expiration_time = GNUNET_TIME_UNIT_HOURS.rel_value_us;
1240 rd[rd_count - skip].data = rh->leho;
1241 rd[rd_count - skip].data_size = strlen (rh->leho);
1242 skip--; /* skip one LESS */
1244 "Adding LEHO %s\n",
1245 rh->leho);
1246 }
1248 "Returning DNS response for `%s' with %u answers\n",
1249 rh->ac_tail->label,
1250 (unsigned int) (rd_count - skip));
1251 rh->proc (rh->proc_cls,
1252 rd_count - skip,
1253 rd);
1255 rh->dns_request = NULL;
1256 }
1257
1258
1260 if (NULL != rh->task_id)
1261 GNUNET_SCHEDULER_cancel (rh->task_id); /* should be timeout task */
1263 rh);
1264}
1265
1266
1275static void
1277{
1278 struct AuthorityChain *ac;
1279 struct GNUNET_DNSPARSER_Query *query;
1280 struct GNUNET_DNSPARSER_Packet *p;
1281 char *dns_request;
1282 size_t dns_request_length;
1283 int ret;
1284
1285 ac = rh->ac_tail;
1286 GNUNET_assert (NULL != ac);
1288 "Starting DNS lookup for `%s'\n",
1289 ac->label);
1291 query = GNUNET_new (struct GNUNET_DNSPARSER_Query);
1292 query->name = GNUNET_strdup (ac->label);
1293 query->type = rh->record_type;
1296 p->queries = query;
1297 p->num_queries = 1;
1298 p->id = (uint16_t) GNUNET_CRYPTO_random_u32 (UINT16_MAX);
1299 p->flags.opcode = GNUNET_TUN_DNS_OPCODE_QUERY;
1300 p->flags.recursion_desired = 1;
1302 1024,
1303 &dns_request,
1304 &dns_request_length);
1305 if (GNUNET_OK != ret)
1306 {
1307 GNUNET_break (0);
1308 rh->proc (rh->proc_cls,
1309 0,
1310 NULL);
1311 GNUNET_assert (NULL == rh->task_id);
1313 rh);
1314 }
1315 else
1316 {
1317 rh->original_dns_id = p->id;
1319 GNUNET_assert (NULL == rh->dns_request);
1320 if (IDNA_SUCCESS != idna_to_unicode_8z8z (ac->label,
1321 &rh->leho,
1322 IDNA_ALLOW_UNASSIGNED))
1323 {
1324 GNUNET_break (0);
1325 rh->proc (rh->proc_cls,
1326 0,
1327 NULL);
1328 GNUNET_assert (NULL == rh->task_id);
1330 rh);
1331 }
1334 dns_request,
1335 dns_request_length,
1337 rh);
1340 rh);
1341 }
1342 if (GNUNET_SYSERR != ret)
1343 GNUNET_free (dns_request);
1345}
1346
1347
1356static void
1358 const char *rname)
1359{
1360 size_t nlen;
1361 char *res;
1362 const char *tld;
1363 struct AuthorityChain *ac;
1364 int af;
1366
1368 "Handling GNS REDIRECT result `%s'\n",
1369 rname);
1370 nlen = strlen (rname);
1371 tld = GNS_get_tld (rname);
1372 if (0 == strcmp ("+", tld))
1373 {
1374 /* REDIRECT resolution continues relative to current domain */
1375 if (0 == rh->name_resolution_pos)
1376 {
1377 res = GNUNET_strndup (rname, nlen - 2);
1378 rh->name_resolution_pos = nlen - 2;
1379 }
1380 else
1381 {
1383 "%.*s.%.*s",
1384 (int) rh->name_resolution_pos,
1385 rh->name,
1386 (int) (nlen - 2),
1387 rname);
1388 rh->name_resolution_pos = strlen (res);
1389 }
1390 GNUNET_free (rh->name);
1391 rh->name = res;
1392 ac = GNUNET_new (struct AuthorityChain);
1393 ac->rh = rh;
1398 /* add AC to tail */
1400 rh->ac_tail,
1401 ac);
1403 rh);
1404 return;
1405 }
1406 if (GNUNET_OK == GNUNET_GNSRECORD_zkey_to_pkey (tld, &zone))
1407 {
1408 /* REDIRECT resolution continues relative to current domain */
1409 if (0 == rh->name_resolution_pos)
1410 {
1412 "%.*s",
1413 (int) (strlen (rname) - (strlen (tld) + 1)),
1414 rname);
1415 }
1416 else
1417 {
1419 "%.*s.%.*s",
1420 (int) rh->name_resolution_pos,
1421 rh->name,
1422 (int) (strlen (rname) - (strlen (tld) + 1)),
1423 rname);
1424 }
1425 rh->name_resolution_pos = strlen (res);
1426 GNUNET_free (rh->name);
1427 rh->name = res;
1428 ac = GNUNET_new (struct AuthorityChain);
1429 ac->rh = rh;
1431 ac->authority_info.gns_authority = zone;
1433 /* add AC to tail */
1435 rh->ac_tail,
1436 ac);
1438 rh);
1439 return;
1440 }
1441
1443 "Got REDIRECT `%s' from GNS for `%s'\n",
1444 rname,
1445 rh->name);
1446 if (NULL != rh->std_resolve)
1447 {
1449 "Multiple REDIRECT results from GNS resolving `%s'! Not really allowed...\n",
1450 rh->name);
1452 }
1453 /* name is absolute, go to DNS */
1454 GNUNET_free (rh->name);
1455 rh->name = GNUNET_strdup (rname);
1456 rh->name_resolution_pos = strlen (rh->name);
1457 switch (rh->record_type)
1458 {
1460 af = AF_INET;
1461 break;
1462
1464 af = AF_INET6;
1465 break;
1466
1467 default:
1468 af = AF_UNSPEC;
1469 break;
1470 }
1472 "Doing standard DNS lookup for `%s'\n",
1473 rh->name);
1474
1476 af,
1479 rh);
1480}
1481
1482
1491static void
1493 const char *cname)
1494{
1495 int af;
1496
1497 GNUNET_free (rh->name);
1498 rh->name = GNUNET_strdup (cname);
1499 rh->name_resolution_pos = strlen (rh->name);
1500 switch (rh->record_type)
1501 {
1503 af = AF_INET;
1504 break;
1505
1507 af = AF_INET6;
1508 break;
1509
1510 default:
1511 af = AF_UNSPEC;
1512 break;
1513 }
1515 "Doing standard DNS lookup for `%s'\n",
1516 rh->name);
1517
1519 af,
1522 rh);
1523}
1524
1525
1533static void
1535 unsigned int rd_count,
1536 const struct GNUNET_GNSRECORD_Data *rd);
1537
1538
1546static void
1548{
1549 struct GNS_ResolverHandle *rh = ac->rh;
1550
1551 if ((NULL != ac->authority_info.dns_authority.gp_head) &&
1553 return; /* more pending and none found yet */
1555 {
1557 "Failed to resolve DNS server for `%s' in GNS2DNS resolution\n",
1559 fail_resolution (rh);
1560 return;
1561 }
1563 return; /* already running, do not launch again! */
1564 /* recurse */
1567 "Will continue resolution using DNS to resolve `%s'\n",
1568 ac->label);
1569 GNUNET_assert (NULL == rh->task_id);
1571 rh);
1572}
1573
1574
1583static void
1584handle_gns2dns_result (void *cls,
1585 unsigned int rd_count,
1586 const struct GNUNET_GNSRECORD_Data *rd)
1587{
1588 struct Gns2DnsPending *gp = cls;
1589 struct AuthorityChain *ac = gp->ac;
1590
1593 gp);
1594 /* enable cleanup of 'rh' handle that automatically comes after we return,
1595 and which expects 'rh' to be in the #rlh_head DLL. */
1596 if (NULL != gp->rh)
1597 {
1599 rlh_tail,
1600 gp->rh);
1601 gp->rh = NULL;
1602 }
1603 GNUNET_free (gp);
1605 "Received %u results for IP address of DNS server for GNS2DNS transition\n",
1606 rd_count);
1607 /* find suitable A/AAAA record */
1608 for (unsigned int j = 0; j < rd_count; j++)
1609 {
1610 switch (rd[j].record_type)
1611 {
1613 {
1614 struct sockaddr_in v4;
1615
1616 if (sizeof(struct in_addr) != rd[j].data_size)
1617 {
1618 GNUNET_break_op (0);
1619 continue;
1620 }
1621 memset (&v4,
1622 0,
1623 sizeof(v4));
1624 v4.sin_family = AF_INET;
1625 v4.sin_port = htons (53);
1626#if HAVE_SOCKADDR_IN_SIN_LEN
1627 v4.sin_len = (u_char) sizeof(v4);
1628#endif
1629 GNUNET_memcpy (&v4.sin_addr,
1630 rd[j].data,
1631 sizeof(struct in_addr));
1632 if (GNUNET_OK ==
1635 (const struct sockaddr *) &v4))
1637 break;
1638 }
1639
1641 {
1642 struct sockaddr_in6 v6;
1643
1644 if (sizeof(struct in6_addr) != rd[j].data_size)
1645 {
1646 GNUNET_break_op (0);
1647 continue;
1648 }
1649 /* FIXME: might want to check if we support IPv6 here,
1650 and otherwise skip this one and hope we find another */
1651 memset (&v6,
1652 0,
1653 sizeof(v6));
1654 v6.sin6_family = AF_INET6;
1655 v6.sin6_port = htons (53);
1656#if HAVE_SOCKADDR_IN_SIN_LEN
1657 v6.sin6_len = (u_char) sizeof(v6);
1658#endif
1659 GNUNET_memcpy (&v6.sin6_addr,
1660 rd[j].data,
1661 sizeof(struct in6_addr));
1662 if (GNUNET_OK ==
1665 (const struct sockaddr *) &v6))
1667 break;
1668 }
1669
1670 default:
1671 break;
1672 }
1673 }
1675}
1676
1677
1685static void
1686handle_gns2dns_ip (void *cls,
1687 const struct sockaddr *addr,
1688 socklen_t addrlen)
1689{
1690 struct Gns2DnsPending *gp = cls;
1691 struct AuthorityChain *ac = gp->ac;
1692 struct sockaddr_storage ss;
1693 struct sockaddr_in *v4;
1694 struct sockaddr_in6 *v6;
1695
1696 if (NULL == addr)
1697 {
1698 /* DNS resolution finished */
1699 if (0 == gp->num_results)
1701 "Failed to use DNS to resolve name of DNS resolver\n");
1704 gp);
1705 GNUNET_free (gp);
1707 return;
1708 }
1709 GNUNET_memcpy (&ss,
1710 addr,
1711 addrlen);
1712 switch (ss.ss_family)
1713 {
1714 case AF_INET:
1715 v4 = (struct sockaddr_in *) &ss;
1716 v4->sin_port = htons (53);
1717 gp->num_results++;
1718 break;
1719
1720 case AF_INET6:
1721 v6 = (struct sockaddr_in6 *) &ss;
1722 v6->sin6_port = htons (53);
1723 gp->num_results++;
1724 break;
1725
1726 default:
1728 "Unsupported AF %d\n",
1729 ss.ss_family);
1730 return;
1731 }
1732 if (GNUNET_OK ==
1734 (struct sockaddr *) &ss))
1736}
1737
1738
1745static void
1747 const struct GNUNET_GNSRECORD_Data *rd)
1748{
1750 rd->data);
1751}
1752
1753
1760static void
1762 const struct GNUNET_GNSRECORD_Data *rd)
1763{
1764 char *cname;
1765 size_t off;
1766
1767 off = 0;
1769 rd->data_size,
1770 &off);
1771 if ((NULL == cname) ||
1772 (off != rd->data_size))
1773 {
1774 GNUNET_break_op (0); /* record not well-formed */
1775 GNUNET_free (cname);
1776 fail_resolution (rh);
1777 return;
1778 }
1780 cname);
1781 GNUNET_free (cname);
1782}
1783
1784
1791static void
1793 const struct GNUNET_GNSRECORD_Data *rd)
1794{
1795 struct AuthorityChain *ac;
1797
1798 /* delegation to another zone */
1800 rd->data_size,
1801 rd->record_type,
1802 &auth))
1803 {
1804 GNUNET_break_op (0);
1805 fail_resolution (rh);
1806 return;
1807 }
1808 /* expand authority chain */
1809 ac = GNUNET_new (struct AuthorityChain);
1810 ac->rh = rh;
1812 ac->authority_info.gns_authority = auth;
1814 /* add AC to tail */
1816 rh->ac_tail,
1817 ac);
1818 /* recurse */
1820 rh);
1821}
1822
1823
1834static int
1836 unsigned int rd_count,
1837 const struct GNUNET_GNSRECORD_Data *rd)
1838{
1839 struct AuthorityChain *ac;
1840 const char *tld;
1841 char *ns;
1842
1843 ns = NULL;
1844 /* expand authority chain */
1845 ac = GNUNET_new (struct AuthorityChain);
1846 ac->rh = rh;
1848
1849 for (unsigned int i = 0; i < rd_count; i++)
1850 {
1851 char *ip;
1852 char *n;
1853 struct Gns2DnsPending *gp;
1855 struct sockaddr_in v4;
1856 struct sockaddr_in6 v6;
1857
1858 if (GNUNET_GNSRECORD_TYPE_GNS2DNS != rd[i].record_type)
1859 {
1864 GNUNET_free (ns);
1865 GNUNET_free (ac);
1866 return GNUNET_SYSERR;
1867 }
1868 n = GNUNET_strdup ((const char*) rd[i].data);
1869 if (strlen (n) + 1 >= rd[i].data_size)
1870 {
1871 GNUNET_break_op (0);
1872 continue;
1873 }
1874 ip = GNUNET_strdup (rd[i].data + strlen (n) + 1);
1875 /* resolve 'ip' to determine the IP(s) of the DNS
1876 resolver to use for lookup of 'ns' */
1877 if (NULL != ns)
1878 {
1879 if (0 != strcasecmp (ns,
1880 n))
1881 {
1882 /* NS values must all be the same for all GNS2DNS records,
1883 anything else leads to insanity */
1884 GNUNET_break_op (0);
1885 GNUNET_free (n);
1886 GNUNET_free (ip);
1887 continue;
1888 }
1889 GNUNET_free (n);
1890 }
1891 else
1892 {
1893 ns = n;
1894 }
1895
1896 /* check if 'ip' is already an IPv4/IPv6 address */
1897 if ((1 == inet_pton (AF_INET,
1898 ip,
1899 &v4)) ||
1900 (1 == inet_pton (AF_INET6,
1901 ip,
1902 &v6)))
1903 {
1907 ip));
1909 GNUNET_free (ip);
1910 continue;
1911 }
1912 tld = GNS_get_tld (ip);
1913 if ((0 != strcmp (tld, "+")) &&
1914 (GNUNET_OK != GNUNET_GNSRECORD_zkey_to_pkey (tld, &zone)))
1915 {
1916 /* 'ip' is a DNS name */
1917 gp = GNUNET_new (struct Gns2DnsPending);
1918 gp->ac = ac;
1921 gp);
1923 AF_UNSPEC,
1926 gp);
1927 GNUNET_free (ip);
1928 continue;
1929 }
1930 /* 'ip' should be a GNS name */
1931 gp = GNUNET_new (struct Gns2DnsPending);
1932 gp->ac = ac;
1935 gp);
1936 gp->rh = GNUNET_new (struct GNS_ResolverHandle);
1937 if (0 == strcmp (tld, "+"))
1938 {
1939 ip = translate_dot_plus (rh,
1940 ip);
1941 tld = GNS_get_tld (ip);
1942 if (GNUNET_OK !=
1944 &zone))
1945 {
1946 GNUNET_break_op (0);
1947 GNUNET_free (ip);
1948 continue;
1949 }
1950 }
1951 gp->rh->authority_zone = zone;
1953 "Resolving `%s' to determine IP address of DNS server for GNS2DNS transition for `%s'\n",
1954 ip,
1955 ns);
1956 gp->rh->name = ip;
1957 gp->rh->name_resolution_pos = strlen (ip) - strlen (tld) - 1;
1959 gp->rh->proc_cls = gp;
1962 gp->rh->loop_limiter = rh->loop_limiter + 1;
1963 gp->rh->loop_threshold = rh->loop_threshold;
1964 gp->rh->task_id
1966 gp->rh);
1967 } /* end 'for all records' */
1968
1969 if (NULL == ns)
1970 {
1971 /* not a single GNS2DNS record found */
1972 GNUNET_free (ac);
1973 return GNUNET_SYSERR;
1974 }
1976 strcpy (ac->authority_info.dns_authority.name,
1977 ns);
1978 /* for DNS recursion, the label is the full DNS name,
1979 created from the remainder of the GNS name and the
1980 name in the NS record */
1981 GNUNET_asprintf (&ac->label,
1982 "%.*s%s%s",
1983 (int) rh->name_resolution_pos,
1984 rh->name,
1985 (0 != rh->name_resolution_pos) ? "." : "",
1986 ns);
1987 GNUNET_free (ns);
1988
1989 {
1990 /* the GNS name is UTF-8 and may include multibyte chars.
1991 * We have to convert the combined name to a DNS-compatible IDNA.
1992 */
1993 char *tmp = ac->label;
1994
1995 if (IDNA_SUCCESS != idna_to_ascii_8z (tmp,
1996 &ac->label,
1997 IDNA_ALLOW_UNASSIGNED))
1998 {
2000 _ ("Name `%s' cannot be converted to IDNA."),
2001 tmp);
2002 GNUNET_free (tmp);
2003 GNUNET_free (ac);
2004 return GNUNET_SYSERR;
2005 }
2006 GNUNET_free (tmp);
2007 }
2008
2010 rh->ac_tail,
2011 ac);
2012 if (strlen (ac->label) > GNUNET_DNSPARSER_MAX_NAME_LENGTH)
2013 {
2015 _ ("GNS lookup resulted in DNS name that is too long (`%s')\n"),
2016 ac->label);
2017 GNUNET_free (ac->label);
2018 GNUNET_free (ac);
2019 return GNUNET_SYSERR;
2020 }
2022 return GNUNET_OK;
2023}
2024
2025
2026static void
2028 unsigned int rd_count,
2029 const struct GNUNET_GNSRECORD_Data *rd)
2030{
2031 struct GNS_ResolverHandle *rh = cls;
2032 char *cname;
2033 char scratch[UINT16_MAX];
2034 size_t scratch_off;
2035 size_t scratch_start;
2036 size_t off;
2037 struct GNUNET_GNSRECORD_Data rd_new[rd_count];
2038 unsigned int rd_off;
2039
2041 "Resolution succeeded for `%s' in zone %s, got %u records\n",
2042 rh->ac_tail->label,
2044 rd_count);
2045 if (0 == rd_count)
2046 {
2048 _ ("GNS lookup failed (zero records found for `%s')\n"),
2049 rh->name);
2050 fail_resolution (rh);
2051 return;
2052 }
2053
2054 if (0 == rh->name_resolution_pos)
2055 {
2056 /* top-level match, are we done yet? */
2057 if ((rd_count > 0) &&
2060 {
2061 off = 0;
2063 rd[0].data_size,
2064 &off);
2065 if ((NULL == cname) ||
2066 (off != rd[0].data_size))
2067 {
2068 GNUNET_break_op (0);
2069 GNUNET_free (cname);
2070 fail_resolution (rh);
2071 return;
2072 }
2074 cname);
2075 GNUNET_free (cname);
2076 return;
2077 }
2078 if ((rd_count > 0) &&
2081 {
2083 rd[0].data);
2084 return;
2085 }
2086
2087
2088 /* If A/AAAA was requested,
2089 * but we got a GNS2DNS record */
2090 if ((GNUNET_DNSPARSER_TYPE_A == rh->record_type) ||
2092 {
2093 for (unsigned int i = 0; i < rd_count; i++)
2094 {
2095 switch (rd[i].record_type)
2096 {
2098 {
2099 /* delegation to DNS */
2101 "Found GNS2DNS record, delegating to DNS!\n");
2102 if (GNUNET_OK ==
2104 rd_count,
2105 rd))
2106 return;
2107 else
2108 goto fail;
2109 }
2110
2111 default:
2112 break;
2113 } /* end: switch */
2114 } /* end: for rd */
2115 } /* end: name_resolution_pos */
2116 /* convert relative names in record values to absolute names,
2117 using 'scratch' array for memory allocations */
2118 scratch_off = 0;
2119 rd_off = 0;
2120 for (unsigned int i = 0; i < rd_count; i++)
2121 {
2122 GNUNET_assert (rd_off <= i);
2123 if ((((0 != rh->protocol) &&
2124 (0 != rh->service)) || (NULL != rh->prefix)) &&
2129 continue;
2130 /* we _only_ care about boxed records */
2131
2132 GNUNET_assert (rd_off < rd_count);
2133 rd_new[rd_off] = rd[i];
2134 /* Check if the embedded name(s) end in "+", and if so,
2135 replace the "+" with the zone at "ac_tail", changing the name
2136 to a ".ZONEKEY". The name is allocated on the 'scratch' array,
2137 so we can free it afterwards. */
2138 switch (rd[i].record_type)
2139 {
2141 {
2142 char *rname;
2143 rname = GNUNET_strndup (rd[i].data, rd[i].data_size);
2144 rname = translate_dot_plus (rh, rname);
2145 GNUNET_break (NULL != rname);
2146 scratch_start = scratch_off;
2147 memcpy (&scratch[scratch_start], rname, strlen (rname) + 1);
2148 scratch_off += strlen (rname) + 1;
2149 GNUNET_assert (rd_off < rd_count);
2150 rd_new[rd_off].data = &scratch[scratch_start];
2151 rd_new[rd_off].data_size = scratch_off - scratch_start;
2152 rd_off++;
2153 GNUNET_free (rname);
2154 }
2155 break;
2156
2158 {
2159 char *cname_tmp;
2160
2161 off = 0;
2162 cname_tmp = GNUNET_DNSPARSER_parse_name (rd[i].data,
2163 rd[i].data_size,
2164 &off);
2165 if ((NULL == cname_tmp) ||
2166 (off != rd[i].data_size))
2167 {
2168 GNUNET_break_op (0); /* record not well-formed */
2169 }
2170 else
2171 {
2172 cname_tmp = translate_dot_plus (rh, cname_tmp);
2173 GNUNET_break (NULL != cname_tmp);
2174 scratch_start = scratch_off;
2175 if (GNUNET_OK !=
2177 sizeof(scratch),
2178 &scratch_off,
2179 cname_tmp))
2180 {
2181 GNUNET_break (0);
2182 }
2183 else
2184 {
2185 GNUNET_assert (rd_off < rd_count);
2186 rd_new[rd_off].data = &scratch[scratch_start];
2187 rd_new[rd_off].data_size = scratch_off - scratch_start;
2188 rd_off++;
2189 }
2190 }
2191 GNUNET_free (cname_tmp);
2192 }
2193 break;
2194
2196 {
2197 struct GNUNET_DNSPARSER_SoaRecord *soa;
2198
2199 off = 0;
2201 rd[i].data_size,
2202 &off);
2203 if ((NULL == soa) ||
2204 (off != rd[i].data_size))
2205 {
2206 GNUNET_break_op (0); /* record not well-formed */
2207 }
2208 else
2209 {
2210 soa->mname = translate_dot_plus (rh, soa->mname);
2211 soa->rname = translate_dot_plus (rh, soa->rname);
2212 scratch_start = scratch_off;
2213 if (GNUNET_OK !=
2215 sizeof(scratch),
2216 &scratch_off,
2217 soa))
2218 {
2219 GNUNET_break (0);
2220 }
2221 else
2222 {
2223 GNUNET_assert (rd_off < rd_count);
2224 rd_new[rd_off].data = &scratch[scratch_start];
2225 rd_new[rd_off].data_size = scratch_off - scratch_start;
2226 rd_off++;
2227 }
2228 }
2229 if (NULL != soa)
2231 }
2232 break;
2233
2235 {
2236 struct GNUNET_DNSPARSER_MxRecord *mx;
2237
2238 off = 0;
2240 rd[i].data_size,
2241 &off);
2242 if ((NULL == mx) ||
2243 (off != rd[i].data_size))
2244 {
2245 GNUNET_break_op (0); /* record not well-formed */
2246 }
2247 else
2248 {
2249 mx->mxhost = translate_dot_plus (rh, mx->mxhost);
2250 scratch_start = scratch_off;
2251 if (GNUNET_OK !=
2253 sizeof(scratch),
2254 &scratch_off,
2255 mx))
2256 {
2257 GNUNET_break (0);
2258 }
2259 else
2260 {
2261 GNUNET_assert (rd_off < rd_count);
2262 rd_new[rd_off].data = &scratch[scratch_start];
2263 rd_new[rd_off].data_size = scratch_off - scratch_start;
2264 rd_off++;
2265 }
2266 }
2267 if (NULL != mx)
2269 }
2270 break;
2271
2273 {
2274 struct GNUNET_DNSPARSER_SrvRecord *srv;
2275
2276 off = 0;
2278 rd[i].data_size,
2279 &off);
2280 if ((NULL == srv) ||
2281 (off != rd[i].data_size))
2282 {
2283 GNUNET_break_op (0); /* record not well-formed */
2284 }
2285 else
2286 {
2287 srv->target = translate_dot_plus (rh, srv->target);
2288 scratch_start = scratch_off;
2289 if (GNUNET_OK !=
2291 sizeof(scratch),
2292 &scratch_off,
2293 srv))
2294 {
2295 GNUNET_break (0);
2296 }
2297 else
2298 {
2299 GNUNET_assert (rd_off < rd_count);
2300 rd_new[rd_off].data = &scratch[scratch_start];
2301 rd_new[rd_off].data_size = scratch_off - scratch_start;
2302 rd_off++;
2303 }
2304 }
2305 if (NULL != srv)
2307 }
2308 break;
2309
2311 {
2313
2314 off = 0;
2316 rd[i].data_size,
2317 &off);
2318 if ((NULL == uri) ||
2319 (off != rd[i].data_size))
2320 {
2322 _ ("Failed to deserialize URI record with target\n"));
2323 GNUNET_break_op (0); /* record not well-formed */
2324 }
2325 else
2326 {
2327 scratch_start = scratch_off;
2328 if (GNUNET_OK !=
2330 sizeof(scratch),
2331 &scratch_off,
2332 uri))
2333 {
2334 GNUNET_break (0);
2335 }
2336 else
2337 {
2338 GNUNET_assert (rd_off < rd_count);
2339 rd_new[rd_off].data = &scratch[scratch_start];
2340 rd_new[rd_off].data_size = scratch_off - scratch_start;
2341 rd_off++;
2342 }
2343 }
2344 if (NULL != uri)
2346 }
2347 break;
2348
2351 {
2353 if (rd[i].data_size < sizeof(uint32_t))
2354 {
2355 GNUNET_break_op (0);
2356 break;
2357 }
2358 if (GNUNET_OK !=
2360 rd[i].data_size,
2361 rd[i].record_type,
2362 &pubkey))
2363 {
2364 GNUNET_break_op (0);
2365 break;
2366 }
2367 rd_off++;
2368 if (rd[i].record_type != rh->record_type)
2369 {
2370 /* try to resolve "@" */
2371 struct AuthorityChain *ac;
2372
2373 ac = GNUNET_new (struct AuthorityChain);
2374 ac->rh = rh;
2379 rh->ac_tail,
2380 ac);
2382 rh);
2383 return;
2384 }
2385 }
2386 break;
2387
2389 {
2390 /* delegation to DNS */
2392 {
2393 rd_off++;
2394 break; /* do not follow to DNS, we wanted the GNS2DNS record! */
2395 }
2397 "Found GNS2DNS record, delegating to DNS!\n");
2398 if (GNUNET_OK ==
2400 rd_count,
2401 rd))
2402 return;
2403 else
2404 goto fail;
2405 }
2406
2408 {
2409 /* unbox SRV/TLSA records if a specific one was requested */
2410 if ((0 != rh->protocol) &&
2411 (0 != rh->service) &&
2412 (rd[i].data_size >= sizeof(struct GNUNET_GNSRECORD_BoxRecord)))
2413 {
2414 const struct GNUNET_GNSRECORD_BoxRecord *box;
2415
2416 box = rd[i].data;
2418 "Got BOX record, checking if parameters match... %u/%u vs %u/%u\n",
2419 ntohs (box->protocol), ntohs (box->service),
2420 rh->protocol, rh->service);
2421 if ((ntohs (box->protocol) == rh->protocol) &&
2422 (ntohs (box->service) == rh->service))
2423 {
2424 /* Box matches, unbox! */
2425 GNUNET_assert (rd_off < rd_count);
2426 rd_new[rd_off].record_type = ntohl (box->record_type);
2427 rd_new[rd_off].data_size -= sizeof(struct
2429 rd_new[rd_off].data = &box[1];
2430 rd_off++;
2431 }
2432 }
2433 else
2434 {
2435 /* no specific protocol/service specified, preserve all BOX
2436 records (for modern, GNS-enabled applications) */
2437 rd_off++;
2438 }
2439 break;
2440 }
2442 {
2443 /* unbox SBOX records if a specific one was requested */
2444 if ((rh->prefix != NULL) &&
2445 (rd[i].data_size >= sizeof(struct GNUNET_GNSRECORD_SBoxRecord)))
2446 {
2447 const struct GNUNET_GNSRECORD_SBoxRecord *box;
2448 const char *prefix;
2449 size_t prefix_len;
2450
2451 box = rd[i].data;
2452 prefix = rd[i].data + sizeof(struct GNUNET_GNSRECORD_SBoxRecord);
2453 prefix_len = strnlen (
2454 prefix,
2455 rd[i].data_size - sizeof(struct GNUNET_GNSRECORD_SBoxRecord)) + 1;
2456 if (prefix_len - 1 >= rd[i].data_size - sizeof(struct
2458 {
2460 "SBOX record with invalid prefix length, maybe not null-terminated\n");
2461 continue;
2462 }
2464 "Got SBOX record, checking if prefixes match... %s vs %s\n",
2465 prefix, rh->prefix);
2466 if (strcmp (rh->prefix, prefix) == 0)
2467 {
2468 /* Box matches, unbox! */
2469 GNUNET_assert (rd_off < rd_count);
2470 rd_new[rd_off].record_type = ntohl (box->record_type);
2471 rd_new[rd_off].data_size -= sizeof(struct
2473 + prefix_len;
2474 rd_new[rd_off].data = rd[i].data
2475 + sizeof(struct GNUNET_GNSRECORD_SBoxRecord)
2476 + prefix_len;
2477 rd_off++;
2478 }
2479 }
2480 else
2481 {
2483 _ (
2484 "GNS no specific protocol/service specified, preserve all SBOX `%s')\n"),
2485 rh->name);
2486 /* no specific protocol/service specified, preserve all SBOX
2487 records (for modern, GNS-enabled applications) */
2488 rd_off++;
2489 }
2490 break;
2491 }
2492 default:
2493 rd_off++;
2494 break;
2495 } /* end: switch */
2496 } /* end: for rd_count */
2497
2498 GNUNET_free (rh->prefix);
2499 rh->prefix = NULL;
2500
2501 /* yes, we are done, return result */
2503 "Returning GNS response for `%s' with %u answers\n",
2504 rh->ac_tail->label,
2505 rd_off);
2506 rh->proc (rh->proc_cls,
2507 rd_off,
2508 rd_new);
2510 rh);
2511 return;
2512 }
2513
2514 switch (rd[0].record_type)
2515 {
2517 GNUNET_break_op (1 == rd_count); /* REDIRECT should be unique */
2519 &rd[0]);
2520 return;
2521
2523 GNUNET_break_op (1 == rd_count); /* CNAME should be unique */
2525 &rd[0]);
2526 return;
2527
2530 GNUNET_break_op (1 == rd_count); /* PKEY should be unique */
2532 &rd[0]);
2533 return;
2534
2536 if (GNUNET_OK ==
2538 rd_count,
2539 rd))
2540 return;
2541 break;
2542 default:
2544 return;
2546 _ ("Unable to process critical delegation record\n"));
2547 break;
2548 }
2549fail:
2551 _ ("GNS lookup recursion failed (no delegation record found)\n"));
2552 fail_resolution (rh);
2553}
2554
2555
2564static void
2566 int32_t success,
2567 const char *emsg)
2568{
2569 struct CacheOps *co = cls;
2570
2571 co->namecache_qe_cache = NULL;
2572 if (GNUNET_OK != success)
2574 _ ("Failed to cache GNS resolution: %s\n"),
2575 emsg);
2577 co_tail,
2578 co);
2579 GNUNET_free (co);
2580}
2581
2582
2601static void
2602handle_dht_response (void *cls,
2603 struct GNUNET_TIME_Absolute exp,
2604 const struct GNUNET_HashCode *key,
2605 const struct GNUNET_PeerIdentity *trunc_peer,
2606 const struct GNUNET_DHT_PathElement *get_path,
2607 unsigned int get_path_length,
2608 const struct GNUNET_DHT_PathElement *put_path,
2609 unsigned int put_path_length,
2611 size_t size,
2612 const void *data)
2613{
2614 struct GNS_ResolverHandle *rh = cls;
2615 struct AuthorityChain *ac = rh->ac_tail;
2616 const struct GNUNET_GNSRECORD_Block *block;
2617 struct CacheOps *co;
2618
2619 (void) exp;
2620 (void) key;
2621 (void) get_path;
2622 (void) get_path_length;
2623 (void) put_path;
2624 (void) put_path_length;
2625 (void) type;
2627 rh->get_handle = NULL;
2629 rh->dht_heap_node = NULL;
2630 /* must be cleared before handle_gns_resolution_result() below gets
2631 to schedule the next step */
2632 if (NULL != rh->task_id)
2633 {
2635 rh->task_id = NULL;
2636 }
2638 "Handling response from the DHT\n");
2639 if (size < sizeof(struct GNUNET_GNSRECORD_Block))
2640 {
2641 /* how did this pass DHT block validation!? */
2642 GNUNET_break (0);
2643 fail_resolution (rh);
2644 return;
2645 }
2646 block = data;
2648 {
2649 /* how did this pass DHT block validation!? */
2650 GNUNET_break (0);
2651 fail_resolution (rh);
2652 return;
2653 }
2655 "Decrypting DHT block of size %llu for `%s', expires %s\n",
2656 (unsigned long long) GNUNET_GNSRECORD_block_get_size (block),
2657 rh->name,
2659 if (GNUNET_OK !=
2662 ac->label,
2664 rh))
2665 {
2666 GNUNET_break_op (0); /* block was ill-formed */
2667 fail_resolution (rh);
2668 return;
2669 }
2672 rel_value_us)
2673 {
2675 "Received expired block from the DHT, will not cache it.\n");
2676 return;
2677 }
2679 return;
2680 /* Cache well-formed blocks */
2682 "Caching response from the DHT in namecache\n");
2683 co = GNUNET_new (struct CacheOps);
2685 block,
2686 &
2688 co);
2690 co_tail,
2691 co);
2692}
2693
2694
2701static void
2703 const struct GNUNET_HashCode *query);
2704
2705
2713static void
2714dht_lookup_timeout (void *cls)
2715{
2716 struct GNS_ResolverHandle *rh = cls;
2717 struct GNUNET_HashCode query = rh->dht_query;
2718
2719 rh->task_id = NULL;
2721 rh->get_handle = NULL;
2723 rh->dht_heap_node = NULL;
2725 {
2727 _ ("DHT lookup for `%s' timed out\n"),
2728 rh->name);
2729 fail_resolution (rh);
2730 return;
2731 }
2732 rh->dht_retries++;
2734 "DHT lookup for `%s' under key %s timed out, retrying (%u/%u)\n",
2735 rh->name,
2736 GNUNET_h2s (&query),
2737 rh->dht_retries,
2738 (unsigned int) DHT_LOOKUP_RETRIES);
2740 &query);
2741}
2742
2743
2744static void
2746 const struct GNUNET_HashCode *query)
2747{
2748 struct GNS_ResolverHandle *rx;
2749
2750 GNUNET_assert (NULL == rh->get_handle);
2751 rh->dht_query = *query;
2754 query,
2757 NULL, 0,
2758 &handle_dht_response, rh);
2760 rh,
2762 abs_value_us);
2763 GNUNET_assert (NULL == rh->task_id);
2766 rh);
2769 {
2770 /* fail longest-standing DHT request */
2772 GNUNET_assert (NULL != rx);
2773 rx->dht_heap_node = NULL;
2774 if (NULL != rx->task_id)
2775 {
2777 rx->task_id = NULL;
2778 }
2779 fail_resolution (rx);
2780 }
2781}
2782
2783
2789static void
2790refresh_stop (struct RefreshOps *ro)
2791{
2793 ro_tail,
2794 ro);
2795 if (NULL != ro->timeout_task)
2798 GNUNET_free (ro);
2799}
2800
2801
2807static void
2808refresh_timeout (void *cls)
2809{
2810 struct RefreshOps *ro = cls;
2811
2812 ro->timeout_task = NULL;
2814 "No fresher block for %s found in the DHT\n",
2815 GNUNET_h2s (&ro->query));
2816 refresh_stop (ro);
2817}
2818
2819
2826static void
2827handle_refresh_response (void *cls,
2828 struct GNUNET_TIME_Absolute exp,
2829 const struct GNUNET_HashCode *key,
2830 const struct GNUNET_PeerIdentity *trunc_peer,
2831 const struct GNUNET_DHT_PathElement *get_path,
2832 unsigned int get_path_length,
2833 const struct GNUNET_DHT_PathElement *put_path,
2834 unsigned int put_path_length,
2836 size_t size,
2837 const void *data)
2838{
2839 struct RefreshOps *ro = cls;
2840 const struct GNUNET_GNSRECORD_Block *block = data;
2842 struct CacheOps *co;
2843
2844 (void) exp;
2845 (void) key;
2846 (void) trunc_peer;
2847 (void) get_path;
2848 (void) get_path_length;
2849 (void) put_path;
2850 (void) put_path_length;
2851 (void) type;
2852 if ( (size < sizeof (struct GNUNET_GNSRECORD_Block)) ||
2854 {
2855 /* how did this pass DHT block validation!? */
2856 GNUNET_break (0);
2857 return;
2858 }
2860 if (expiration.abs_value_us <= ro->expiration.abs_value_us)
2861 return; /* not an improvement, keep looking */
2863 "Refreshing cached block for %s, now expires %s\n",
2864 GNUNET_h2s (&ro->query),
2866 co = GNUNET_new (struct CacheOps);
2868 block,
2869 &
2871 co);
2873 co_tail,
2874 co);
2875 refresh_stop (ro);
2876}
2877
2878
2886static void
2887start_refresh (const struct GNUNET_HashCode *query,
2889{
2890 struct RefreshOps *ro;
2891
2892 for (ro = ro_head; NULL != ro; ro = ro->next)
2893 if (0 == GNUNET_memcmp (&ro->query,
2894 query))
2895 return; /* already refreshing this one */
2896 ro = GNUNET_new (struct RefreshOps);
2897 ro->query = *query;
2898 ro->expiration = expiration;
2901 query,
2904 NULL, 0,
2906 ro);
2907 if (NULL == ro->get_handle)
2908 {
2909 GNUNET_free (ro);
2910 return;
2911 }
2913 "Looking for a fresher block for %s in the DHT\n",
2914 GNUNET_h2s (query));
2917 ro);
2919 ro_tail,
2920 ro);
2921}
2922
2923
2932static void
2934 unsigned int rd_count,
2935 const struct GNUNET_GNSRECORD_Data *rd)
2936{
2937 struct GNS_ResolverHandle *rh = cls;
2938
2939 if (0 == rd_count)
2941 _ ("GNS namecache returned empty result for `%s'\n"),
2942 rh->name);
2944 rd_count,
2945 rd);
2946}
2947
2948
2955static void
2957 const struct GNUNET_GNSRECORD_Block *block)
2958{
2959 struct GNS_ResolverHandle *rh = cls;
2960 struct AuthorityChain *ac = rh->ac_tail;
2961 const char *label = ac->label;
2962 const struct GNUNET_CRYPTO_BlindablePublicKey *auth =
2964 struct GNUNET_HashCode query;
2965 bool dht_allowed;
2966
2967 GNUNET_assert (NULL != rh->namecache_qe);
2968 rh->namecache_qe = NULL;
2969 dht_allowed = ((GNUNET_GNS_LO_DEFAULT == rh->options) ||
2971 (ac != rh->ac_head)));
2972 if (NULL == block)
2974 "No block found\n");
2975 else
2977 "Got block with expiration %s\n",
2980 if (dht_allowed &&
2981 ((NULL == block) ||
2984 rel_value_us)))
2985 {
2986 /* namecache knows nothing; try DHT lookup */
2988 label,
2989 &query);
2991 "Starting DHT lookup for `%s' in zone `%s' under key `%s'\n",
2992 ac->label,
2994 GNUNET_h2s (&query));
2995 start_dht_request (rh, &query);
2996 return;
2997 }
2998
2999 if ((NULL == block) ||
3002 rel_value_us))
3003 {
3004 /* DHT not permitted and no local result, fail */
3006 "Resolution failed for `%s' in zone %s (DHT lookup not permitted by configuration)\n",
3007 ac->label,
3009 fail_resolution (rh);
3010 return;
3011 }
3013 "Received result from namecache for label `%s'\n",
3014 ac->label);
3015 /* The block is still valid, but a record set that is about to expire
3016 has almost certainly been republished by now; get that version
3017 into the cache before this one dies, instead of paying a cold DHT
3018 lookup then. */
3019 if (dht_allowed &&
3021 GNUNET_GNSRECORD_block_get_expiration (block)).rel_value_us <
3023 {
3025 label,
3026 &query);
3027 start_refresh (&query,
3029 }
3030
3031 if (GNUNET_OK !=
3033 auth,
3034 label,
3036 rh))
3037 {
3038 GNUNET_break_op (0); /* block was ill-formed */
3039 /* try DHT instead */
3041 label,
3042 &query);
3044 "Starting DHT lookup for `%s' in zone `%s' under key `%s'\n",
3045 ac->label,
3047 GNUNET_h2s (&query));
3048 start_dht_request (rh, &query);
3049 return;
3050 }
3051}
3052
3053
3059static void
3061{
3062 struct AuthorityChain *ac = rh->ac_tail;
3063 struct GNUNET_HashCode query;
3064
3066 "Starting GNS resolution for `%s' in zone %s\n",
3067 ac->label,
3070 ac->label,
3071 &query);
3073 {
3074 rh->namecache_qe
3076 &query,
3078 rh);
3079 GNUNET_assert (NULL != rh->namecache_qe);
3080 }
3081 else
3082 {
3084 &query);
3085 }
3086}
3087
3088
3095static void
3096handle_revocation_result (void *cls,
3097 int is_valid)
3098{
3099 struct GNS_ResolverHandle *rh = cls;
3100 struct AuthorityChain *ac = rh->ac_tail;
3101
3102 rh->rev_check = NULL;
3103 if (GNUNET_YES != is_valid)
3104 {
3106 _ ("Zone %s was revoked, resolution fails\n"),
3109 return;
3110 }
3112}
3113
3114
3120static void
3122{
3123 struct AuthorityChain *ac = rh->ac_tail;
3124
3126 "Starting revocation check for zone %s\n",
3131 rh);
3132 GNUNET_assert (NULL != rh->rev_check);
3133}
3134
3135
3136static void
3137recursive_resolution (void *cls)
3138{
3139 struct GNS_ResolverHandle *rh = cls;
3140
3141 rh->task_id = NULL;
3142 if (rh->loop_threshold < rh->loop_limiter++)
3143 {
3145 "Encountered unbounded recursion resolving `%s'\n",
3146 rh->name);
3147 fail_resolution (rh);
3148 return;
3149 }
3150 if (GNUNET_YES == rh->ac_tail->gns_authority)
3152 else
3154}
3155
3156
3157static void
3158start_resolver_lookup (void *cls)
3159{
3160 struct GNS_ResolverHandle *rh = cls;
3161 struct AuthorityChain *ac;
3162 struct in_addr v4;
3163 struct in6_addr v6;
3164
3165 rh->task_id = NULL;
3166 if (1 == inet_pton (AF_INET,
3167 rh->name,
3168 &v4))
3169 {
3170 /* name is IPv4 address, pretend it's an A record */
3172
3173 rd.data = &v4;
3174 rd.data_size = sizeof(v4);
3175 rd.expiration_time = UINT64_MAX;
3177 rd.flags = 0;
3178 rh->proc (rh->proc_cls,
3179 1,
3180 &rd);
3181 GNUNET_assert (NULL == rh->task_id);
3183 rh);
3184 return;
3185 }
3186 if (1 == inet_pton (AF_INET6,
3187 rh->name,
3188 &v6))
3189 {
3190 /* name is IPv6 address, pretend it's an AAAA record */
3192
3193 rd.data = &v6;
3194 rd.data_size = sizeof(v6);
3195 rd.expiration_time = UINT64_MAX;
3197 rd.flags = 0;
3198 rh->proc (rh->proc_cls,
3199 1,
3200 &rd);
3201 GNUNET_assert (NULL == rh->task_id);
3203 rh);
3204 return;
3205 }
3206
3207 ac = GNUNET_new (struct AuthorityChain);
3208 ac->rh = rh;
3210 if (NULL == ac->label)
3211 /* name was just the "TLD", so we default to label
3212 #GNUNET_GNS_EMPTY_LABEL_AT */
3217 rh->ac_tail,
3218 ac);
3220 rh);
3221}
3222
3223
3238struct GNS_ResolverHandle *
3240 uint32_t record_type,
3241 const char *name,
3243 uint16_t recursion_depth_limit,
3245 void *proc_cls)
3246{
3247 struct GNS_ResolverHandle *rh;
3248
3250 "Starting lookup for `%s'\n",
3251 name);
3252 rh = GNUNET_new (struct GNS_ResolverHandle);
3254 rlh_tail,
3255 rh);
3256 rh->authority_zone = *zone;
3257 rh->proc = proc;
3258 rh->proc_cls = proc_cls;
3259 rh->options = options;
3261 rh->name = GNUNET_strdup (name);
3262 rh->name_resolution_pos = strlen (name);
3263 rh->loop_threshold = recursion_depth_limit;
3265 rh);
3266 return rh;
3267}
3268
3269
3275void
3277{
3278 struct DnsResult *dr;
3279 struct AuthorityChain *ac;
3280
3282 rlh_tail,
3283 rh);
3284 if (NULL != rh->dns_request)
3285 {
3287 rh->dns_request = NULL;
3288 }
3289 while (NULL != (ac = rh->ac_head))
3290 {
3292 rh->ac_tail,
3293 ac);
3294 if (GNUNET_NO == ac->gns_authority)
3295 {
3296 struct Gns2DnsPending *gp;
3297
3298 while (NULL != (gp = ac->authority_info.dns_authority.gp_head))
3299 {
3302 gp);
3303 if (NULL != gp->rh)
3304 {
3305 /* rh->g2dc->rh is NOT in the DLL yet, so to enable us
3306 using GNS_resolver_lookup_cancel here, we need to
3307 add it first... */
3309 rlh_tail,
3310 gp->rh);
3311 GNUNET_assert (NULL == gp->rh->task_id);
3314 gp->rh);
3315 gp->rh = NULL;
3316 }
3317 if (NULL != gp->dns_rh)
3318 {
3320 gp->dns_rh = NULL;
3321 }
3322 GNUNET_free (gp);
3323 }
3325 }
3326 GNUNET_free (ac->label);
3327 GNUNET_free (ac);
3328 }
3329 if (NULL != rh->task_id)
3330 {
3332 rh->task_id = NULL;
3333 }
3334 if (NULL != rh->get_handle)
3335 {
3337 rh->get_handle = NULL;
3338 }
3339 if (NULL != rh->dht_heap_node)
3340 {
3342 rh->dht_heap_node = NULL;
3343 }
3344 if (NULL != rh->namecache_qe)
3345 {
3347 rh->namecache_qe = NULL;
3348 }
3349 if (NULL != rh->rev_check)
3350 {
3352 rh->rev_check = NULL;
3353 }
3354 if (NULL != rh->std_resolve)
3355 {
3357 "Canceling standard DNS resolution\n");
3359 rh->std_resolve = NULL;
3360 }
3361 while (NULL != (dr = rh->dns_result_head))
3362 {
3365 dr);
3366 GNUNET_free (dr);
3367 }
3368 if (NULL != rh->prefix)
3369 {
3371 rh->prefix = NULL;
3372 }
3373 GNUNET_free (rh->leho);
3374 GNUNET_free (rh->name);
3375 GNUNET_free (rh);
3376}
3377
3378
3379/* ***************** Resolver initialization ********************* */
3380
3381
3390void
3392 struct GNUNET_DHT_Handle *dht,
3393 const struct GNUNET_CONFIGURATION_Handle *c,
3394 unsigned long long max_bg_queries)
3395{
3396 cfg = c;
3398 dht_handle = dht;
3401 max_allowed_background_queries = max_bg_queries;
3403 "namecache",
3404 "DISABLE");
3407 "Namecache disabled\n");
3408}
3409
3410
3414void
3416{
3417 struct GNS_ResolverHandle *rh;
3418 struct CacheOps *co;
3419
3420 /* abort active resolutions */
3421 while (NULL != (rh = rlh_head))
3422 {
3423 rh->proc (rh->proc_cls,
3424 0,
3425 NULL);
3427 }
3428 while (NULL != ro_head)
3430 while (NULL != (co = co_head))
3431 {
3433 co_tail,
3434 co);
3436 GNUNET_free (co);
3437 }
3439 dht_lookup_heap = NULL;
3440 dht_handle = NULL;
3441 namecache_handle = NULL;
3442}
3443
3444
3445/* end of gnunet-service-gns_resolver.c */
struct GNUNET_GETOPT_CommandLineOption options[]
Definition 002.c:5
static size_t strnlen(const char *s, size_t n)
#define memrchr(s, c, n)
Definition compat.h:49
uint16_t GNUNET_GNS_protocol_name_to_number(const char *name)
#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_LEHO
GNS legacy hostname.
#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)
uint16_t GNUNET_GNS_service_port_name_to_number(const char *name)
static int ret
Final status code.
Definition gnunet-arm.c:93
static int prefix
If printing the value of PREFIX has been requested.
static struct GNUNET_DHT_Handle * dht
Handle to the DHT.
static char * data
The data to insert into the dht.
struct GNUNET_HashCode key
The key used in the DHT.
static struct GNUNET_TIME_Relative expiration
User supplied expiration value.
static struct GNUNET_CRYPTO_BlindablePublicKey pubkey
Public key of the zone to look in.
static char * name
Name (label) of the records to list.
static struct GNUNET_NAMECACHE_Handle * ns
Handle to the namecache.
static unsigned int rd_count
Number of records for currently parsed set.
static char * res
Currently read line or NULL on EOF.
static struct GNUNET_GNSRECORD_Data rd[50]
The record data under a single label.
static uint32_t type
Type string converted to DNS type value.
static size_t data_size
Number of bytes in data.
static uint8_t proto
Protocol to use.
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 char * rp
Relying party.
static struct GNUNET_SERVICE_Handle * service
Handle to our service instance.
static struct GNUNET_NotificationContext * nc
Notification context for broadcasting to monitors.
const char * GNS_get_tld(const char *name)
Obtain the TLD of the given name.
static void refresh_timeout(void *cls)
Nothing fresher showed up in time.
#define DHT_LOOKUP_TIMEOUT
Default DHT timeout for lookups.
#define DNS_LOOKUP_TIMEOUT
Default timeout for DNS lookups.
static int disable_cache
Use namecache.
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.
static unsigned long long max_allowed_background_queries
Maximum amount of parallel queries to the DHT.
static void start_dht_request(struct GNS_ResolverHandle *rh, const struct GNUNET_HashCode *query)
Initiate a DHT query for a set of GNS records.
#define BLOCK_REFRESH_THRESHOLD
If a block we found in the namecache expires within this time, look for a fresher version of it in th...
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 handle_revocation_result(void *cls, int is_valid)
Function called with the result from a revocation check.
static int resolver_getprotobyname(const char *name)
Function called to receive the protocol number for a service.
static void dht_lookup_timeout(void *cls)
The DHT did not answer within DHT_LOOKUP_TIMEOUT.
static void recursive_pkey_resolution(struct GNS_ResolverHandle *rh, const struct GNUNET_GNSRECORD_Data *rd)
We found a PKEY record, perform recursive resolution on it.
static void recursive_resolution(void *cls)
Task scheduled to continue with the resolution process.
#define BLOCK_REFRESH_TIMEOUT
How long do we leave a background refresh GET running?
static void start_resolver_lookup(void *cls)
Begin the resolution process from 'name', starting with the identification of the zone specified by '...
static struct GNS_ResolverHandle * rlh_tail
Tail of resolver lookup list.
static void transmit_lookup_dns_result(struct GNS_ResolverHandle *rh)
Gives the cumulative result obtained to the callback and clean up the request.
static char * translate_dot_plus(struct GNS_ResolverHandle *rh, char *name)
Expands a name ending in .
static void recursive_gns_resolution_namecache(struct GNS_ResolverHandle *rh)
Lookup tail of our authority chain in the namecache.
static const struct GNUNET_CONFIGURATION_Handle * cfg
Global configuration.
static void fail_resolution(struct GNS_ResolverHandle *rh)
Function called to asynchronously fail a resolution.
static struct RefreshOps * ro_head
Organized in a DLL.
static void handle_namecache_block_response(void *cls, const struct GNUNET_GNSRECORD_Block *block)
Process a record that was stored in the namecache.
static void start_refresh(const struct GNUNET_HashCode *query, struct GNUNET_TIME_Absolute expiration)
Ask the DHT for a fresher version of query while we answer from a namecache entry that is about to ex...
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 int resolver_getservbyname(const char *name, const char *proto)
Function called to receive the port number for a service.
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.
static void recursive_gns_resolution_revocation(struct GNS_ResolverHandle *rh)
Perform revocation check on tail of our authority chain.
static struct GNUNET_DHT_Handle * dht_handle
Resolver handle to the dht.
static struct GNS_ResolverHandle * rlh_head
Head of resolver lookup list.
void GNS_resolver_lookup_cancel(struct GNS_ResolverHandle *rh)
Cancel active resolution (i.e.
static void handle_refresh_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)
A background refresh returned a block.
static void refresh_stop(struct RefreshOps *ro)
End a background refresh.
static void handle_dns_result(void *cls, const struct sockaddr *addr, socklen_t addrlen)
We had to do a DNS lookup.
static struct CacheOps * co_head
Organized in a DLL.
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.
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 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 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_cname_result(struct GNS_ResolverHandle *rh, const char *cname)
We encountered a CNAME record during our resolution.
#define DHT_GNS_REPLICATION_LEVEL
DHT replication level.
static void GNS_resolver_lookup_cancel_(void *cls)
Wrapper around GNS_resolver_lookup_cancel() as a task.
static void recursive_dns_resolution(struct GNS_ResolverHandle *rh)
Perform recursive DNS resolution.
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 ...
static void timeout_resolution(void *cls)
Function called when a resolution times out.
static struct CacheOps * co_tail
Organized in a DLL.
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.
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.
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.
struct GNS_ResolverHandle * GNS_resolver_lookup(const struct GNUNET_CRYPTO_BlindablePublicKey *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.
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.
static void continue_with_gns2dns(struct AuthorityChain *ac)
We have resolved one or more of the nameservers for a GNS2DNS lookup.
void GNS_resolver_done()
Shutdown resolver.
#define DHT_LOOKUP_RETRIES
How often do we restart a DHT lookup that stayed unanswered for DHT_LOOKUP_TIMEOUT before we give up ...
static struct GNUNET_CONTAINER_Heap * dht_lookup_heap
Heap for limiting parallel DHT lookups.
static struct RefreshOps * ro_tail
Organized in a DLL.
static struct GNUNET_NAMECACHE_Handle * namecache_handle
Our handle to the namecache service.
void(* GNS_ResultProcessor)(void *cls, uint32_t rd_count, const struct GNUNET_GNSRECORD_Data *rd)
Function called with results for a GNS resolution.
static struct GNUNET_Process * p
Helper process we started.
Definition gnunet-uri.c:38
GNUNET_BLOCK_Type
WARNING: This header is generated! In order to add DHT block types, you must register them in GANA,...
@ GNUNET_BLOCK_TYPE_GNS_NAMERECORD
Block for storing GNS record data.
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".
uint32_t GNUNET_CRYPTO_random_u32(uint32_t i)
Produce a random value.
void GNUNET_DHT_get_stop(struct GNUNET_DHT_GetHandle *get_handle)
Stop async DHT-get.
Definition dht_api.c:1238
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:1165
@ GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE
Each peer along the way should process the request (otherwise only peers locally closest to the key w...
#define GNUNET_CONTAINER_DLL_remove(head, tail, element)
Remove an element from a DLL.
#define GNUNET_CONTAINER_DLL_insert_tail(head, tail, element)
Insert an element at the tail of a DLL.
#define GNUNET_CONTAINER_DLL_insert(head, tail, element)
Insert an element at the head of a DLL.
#define GNUNET_DNSPARSER_TYPE_URI
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:473
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:1013
void GNUNET_DNSPARSER_free_packet(struct GNUNET_DNSPARSER_Packet *p)
Free memory taken by a packet.
Definition dnsparser.c:978
#define GNUNET_DNSPARSER_TYPE_SRV
#define GNUNET_DNSPARSER_TYPE_SOA
#define GNUNET_DNSPARSER_TYPE_A
void GNUNET_DNSPARSER_free_srv(struct GNUNET_DNSPARSER_SrvRecord *srv)
Free SRV information record.
Definition dnsparser.c:156
#define GNUNET_DNSPARSER_TYPE_PTR
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:428
void GNUNET_DNSPARSER_free_uri(struct GNUNET_DNSPARSER_UriRecord *uri)
Free URI information record.
Definition dnsparser.c:171
#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:1205
#define GNUNET_DNSPARSER_TYPE_CNAME
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:555
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:514
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:371
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:1127
void GNUNET_DNSPARSER_free_soa(struct GNUNET_DNSPARSER_SoaRecord *soa)
Free SOA information record.
Definition dnsparser.c:125
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:1246
void GNUNET_DNSPARSER_free_mx(struct GNUNET_DNSPARSER_MxRecord *mx)
Free MX information record.
Definition dnsparser.c:186
#define GNUNET_DNSPARSER_TYPE_AAAA
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:1428
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:1283
#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:756
#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:585
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:612
void GNUNET_DNSSTUB_stop(struct GNUNET_DNSSTUB_Context *ctx)
Cleanup DNSSTUB resolver.
Definition dnsstub.c:704
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:525
void GNUNET_DNSSTUB_resolve_cancel(struct GNUNET_DNSSTUB_RequestSocket *rs)
Cancel DNS resolution.
Definition dnsstub.c:561
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:664
GNUNET_GNS_LocalOptions
Options for the GNS lookup.
@ GNUNET_GNS_LO_LOCAL_MASTER
For the rightmost label, only look in the cache (it is our local namestore), for the others,...
@ GNUNET_GNS_LO_DEFAULT
Defaults, look in cache, then in DHT.
int GNUNET_GNSRECORD_zkey_to_pkey(const char *zkey, struct GNUNET_CRYPTO_BlindablePublicKey *pkey)
Convert an absolute domain name to the respective public key.
const char * GNUNET_GNSRECORD_z2s(const struct GNUNET_CRYPTO_BlindablePublicKey *z)
Convert a zone to a string (for printing debug messages).
enum GNUNET_GenericReturnValue GNUNET_GNSRECORD_block_decrypt(const struct GNUNET_GNSRECORD_Block *block, const struct GNUNET_CRYPTO_BlindablePublicKey *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.
enum GNUNET_GenericReturnValue GNUNET_GNSRECORD_identity_from_data(const char *data, size_t data_size, uint32_t type, struct GNUNET_CRYPTO_BlindablePublicKey *key)
Build a #GNUNET_GNSRECORD_PublicKey from zone delegation resource record data.
const char * GNUNET_GNSRECORD_pkey_to_zkey(const struct GNUNET_CRYPTO_BlindablePublicKey *pkey)
Convert public key to the respective absolute domain name in the ".zkey" pTLD.
#define GNUNET_GNS_EMPTY_LABEL_AT
String we use to indicate an empty label (top-level entry in the zone).
enum GNUNET_GenericReturnValue GNUNET_GNSRECORD_is_critical(uint32_t type)
Check if this type is a critical record.
Definition gnsrecord.c:239
void GNUNET_GNSRECORD_query_from_public_key(const struct GNUNET_CRYPTO_BlindablePublicKey *pub, const char *label, struct GNUNET_HashCode *query)
Calculate the DHT query for a given label in a given zone.
#define GNUNET_GNSRECORD_TYPE_ANY
Record type indicating any record/'*'.
struct GNUNET_TIME_Absolute GNUNET_GNSRECORD_block_get_expiration(const struct GNUNET_GNSRECORD_Block *block)
Returns the expiration of a block.
@ 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.
void * GNUNET_CONTAINER_heap_remove_node(struct GNUNET_CONTAINER_HeapNode *node)
Removes a node from the heap.
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_CONTAINER_Heap * GNUNET_CONTAINER_heap_create(enum GNUNET_CONTAINER_HeapOrder order)
Create a new heap.
void GNUNET_CONTAINER_heap_destroy(struct GNUNET_CONTAINER_Heap *heap)
Destroys the heap.
@ GNUNET_CONTAINER_HEAP_ORDER_MIN
Heap with the minimum cost at the root.
#define GNUNET_log(kind,...)
#define GNUNET_memcmp(a, b)
Compare memory in a and b, where both must be of the same pointer type.
#define GNUNET_memcpy(dst, src, n)
Call memcpy() but check for n being 0 first.
@ GNUNET_OK
@ GNUNET_YES
@ GNUNET_NO
@ GNUNET_SYSERR
#define GNUNET_break_op(cond)
Use this for assertion violations caused by other peers (i.e.
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur.
const char * GNUNET_h2s(const struct GNUNET_HashCode *hc)
Convert a hash value to a string (for printing debug messages).
@ GNUNET_ERROR_TYPE_WARNING
@ GNUNET_ERROR_TYPE_ERROR
@ GNUNET_ERROR_TYPE_DEBUG
@ GNUNET_ERROR_TYPE_INFO
int int GNUNET_asprintf(char **buf, const char *format,...) __attribute__((format(printf
Like asprintf, just portable.
#define GNUNET_strdup(a)
Wrapper around GNUNET_xstrdup_.
#define GNUNET_strndup(a, length)
Wrapper around GNUNET_xstrndup_.
#define GNUNET_new(type)
Allocate a struct or union of the given type.
#define GNUNET_malloc(size)
Wrapper around malloc.
#define GNUNET_free(ptr)
Wrapper around free.
void GNUNET_NAMECACHE_cancel(struct GNUNET_NAMECACHE_QueueEntry *qe)
Cancel a namecache operation.
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.
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_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.
void GNUNET_RESOLVER_request_cancel(struct GNUNET_RESOLVER_RequestHandle *rh)
Cancel a request that is still pending with the resolver.
struct GNUNET_REVOCATION_Query * GNUNET_REVOCATION_query(const struct GNUNET_CONFIGURATION_Handle *cfg, const struct GNUNET_CRYPTO_BlindablePublicKey *key, GNUNET_REVOCATION_Callback func, void *func_cls)
Check if a key was revoked.
void GNUNET_REVOCATION_query_cancel(struct GNUNET_REVOCATION_Query *q)
Cancel key revocation check.
void * GNUNET_SCHEDULER_cancel(struct GNUNET_SCHEDULER_Task *task)
Cancel the task with the specified identifier.
Definition scheduler.c:986
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:1310
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:1283
#define GNUNET_TIME_UNIT_FOREVER_REL
Constant used to specify "forever".
#define GNUNET_TIME_UNIT_HOURS
One hour.
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
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_get(void)
Get the current time.
Definition time.c:111
const char * GNUNET_STRINGS_absolute_time_to_string(struct GNUNET_TIME_Absolute t)
Like asctime, except for GNUnet time.
Definition strings.c:671
#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
static unsigned int size
Size of the "table".
Definition peer.c:68
#define _(String)
GNU gettext support macro.
Definition platform.h:179
DLL to hold the authority chain we had to pass in the resolution process.
int found
Did we succeed in getting an IP address for any of the DNS servers listed? Once we do,...
char * label
label/name corresponding to the authority
struct AuthorityChain::@63::@64 dns_authority
struct AuthorityChain * next
This is a DLL.
int gns_authority
GNUNET_YES if the authority was a GNS authority, GNUNET_NO if the authority was a DNS authority.
struct GNUNET_DNSSTUB_Context * dns_handle
Handle to perform DNS lookups with this authority (in GNS2DNS handling).
char name[GNUNET_DNSPARSER_MAX_NAME_LENGTH+1]
Domain of the DNS resolver that is the authority.
struct AuthorityChain * prev
This is a DLL.
struct GNS_ResolverHandle * rh
Resolver handle this entry in the chain belongs to.
int launched
Did we start the recursive resolution via DNS?
union AuthorityChain::@63 authority_info
Information about the resolver authority for this label.
struct Gns2DnsPending * gp_head
List of resolutions of the 'ip' of the name server that are still pending.
struct Gns2DnsPending * gp_tail
Tail of list of resolutions of the 'ip' of the name server that are still pending.
Active namestore caching operations.
struct CacheOps * prev
Organized in a DLL.
struct GNUNET_NAMECACHE_QueueEntry * namecache_qe_cache
Pending Namestore caching task.
struct CacheOps * next
Organized in a DLL.
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.
struct DnsResult * prev
Kept in DLL.
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)
Handle to a currently pending resolution.
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 * leho
Legacy Hostname to use if we encountered GNS2DNS record and thus can deduct the LEHO from that transi...
struct GNUNET_CONTAINER_HeapNode * dht_heap_node
Heap node associated with this lookup.
void * proc_cls
closure passed to proc
struct GNS_ResolverHandle * next
DLL.
struct GNUNET_DHT_GetHandle * get_handle
Handle for DHT lookups.
struct DnsResult * dns_result_tail
DLL of results we got from DNS.
struct GNUNET_REVOCATION_Query * rev_check
Pending revocation check.
unsigned int loop_limiter
We increment the loop limiter for each step in a recursive resolution.
struct GNUNET_NAMECACHE_QueueEntry * namecache_qe
Pending Namecache lookup task.
struct GNUNET_RESOLVER_RequestHandle * std_resolve
Handle for standard DNS resolution, NULL if none is active.
int record_type
Desired type for the resolution.
struct GNUNET_CRYPTO_BlindablePublicKey authority_zone
The top-level GNS authoritative zone to query.
struct DnsResult * dns_result_head
DLL of results we got from DNS.
struct AuthorityChain * ac_head
DLL to store the authority chain.
unsigned int dht_retries
How many times did we already restart the DHT GET in get_handle because it did not answer within DHT_...
struct AuthorityChain * ac_tail
DLL to store the authority chain.
unsigned int loop_threshold
Maximum value of loop_limiter allowed by client.
struct GNUNET_SCHEDULER_Task * task_id
ID of a task associated with the resolution process.
GNS_ResultProcessor proc
called when resolution phase finishes
uint16_t original_dns_id
16 bit random ID we used in the dns_request.
struct GNS_ResolverHandle * prev
DLL.
struct GNUNET_HashCode dht_query
Key of the DHT GET in get_handle, so that we can re-issue it when it times out.
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.
enum GNUNET_GNS_LocalOptions options
Use only cache.
struct GNUNET_DNSSTUB_RequestSocket * dns_request
Socket for a DNS request, NULL if none is active.
Handle to a node in a heap.
An identity key as per LSD0001.
Handle to a GET request.
Definition dht_api.c:79
Connection to the DHT service.
Definition dht_api.c:235
A (signed) path tracking a block's flow through the DHT is represented by an array of path elements,...
Information from MX records (RFC 1035).
char * mxhost
Name of the mail server.
Easy-to-process, parsed version of a DNS packet.
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).
void * data
Binary record data.
size_t data_len
Number of bytes in data.
A DNS response record.
struct GNUNET_DNSPARSER_SoaRecord * soa
SOA data for SOA records.
struct GNUNET_DNSPARSER_SrvRecord * srv
SRV data for SRV records.
struct GNUNET_DNSPARSER_MxRecord * mx
MX data for MX records.
char * hostname
For NS, CNAME and PTR records, this is the uncompressed 0-terminated hostname.
uint16_t type
See GNUNET_DNSPARSER_TYPE_*.
struct GNUNET_TIME_Absolute expiration_time
When does the record expire?
union GNUNET_DNSPARSER_Record::@24 data
Payload of the record (which one of these is valid depends on the 'type').
char * name
Name of the record that the query is for (0-terminated).
struct GNUNET_DNSPARSER_RawRecord raw
Raw data for all other types.
struct GNUNET_DNSPARSER_UriRecord * uri
URI data for URI records.
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).
Handle to the stub resolver.
Definition dnsstub.c:125
UDP socket we are using for sending DNS requests to the Internet.
Definition dnsstub.c:46
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.).
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.
Record type used to box up SMIMEA records.
uint32_t record_type
GNS record type of the boxed record.
A 512-bit hashcode.
Connection to the NAMECACHE service.
An QueueEntry used to store information for a pending NAMECACHE record operation.
The identity of the host (wraps the signing key of the peer).
Handle to a request given to the resolver.
Handle for the key revocation query.
Entry in list of pending tasks.
Definition scheduler.c:141
Time for absolute times used by GNUnet, in microseconds.
uint64_t abs_value_us
The actual value.
uint64_t rel_value_us
The actual value.
uint16_t id
Unique identifier for the request/response.
Element of a resolution process for looking up the responsible DNS server hostname in a GNS2DNS recur...
struct GNUNET_RESOLVER_RequestHandle * dns_rh
Handle for DNS resolution of the DNS nameserver.
struct Gns2DnsPending * next
Kept in a DLL.
struct Gns2DnsPending * prev
Kept in a DLL.
struct GNS_ResolverHandle * rh
Handle for the resolution of the IP part of the GNS2DNS record.
struct AuthorityChain * ac
Context this activity belongs with.
unsigned int num_results
How many results did we get?
Background lookup for a fresher version of a block that is still in the namecache but about to expire...
struct GNUNET_HashCode query
Query we are refreshing.
struct GNUNET_DHT_GetHandle * get_handle
Our DHT GET.
struct RefreshOps * prev
Organized in a DLL.
struct RefreshOps * next
Organized in a DLL.
struct GNUNET_SCHEDULER_Task * timeout_task
Task that ends this refresh.
struct GNUNET_TIME_Absolute expiration
Expiration time of the best block we have seen so far.

◆ DHT_LOOKUP_RETRIES

#define DHT_LOOKUP_RETRIES   2

How often do we restart a DHT lookup that stayed unanswered for DHT_LOOKUP_TIMEOUT before we give up on the name?

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

◆ DNS_LOOKUP_TIMEOUT

#define DNS_LOOKUP_TIMEOUT
Value:

Default timeout for DNS lookups.

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

◆ DHT_GNS_REPLICATION_LEVEL

#define DHT_GNS_REPLICATION_LEVEL   10

DHT replication level.

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

◆ BLOCK_REFRESH_THRESHOLD

#define BLOCK_REFRESH_THRESHOLD
Value:
#define GNUNET_TIME_UNIT_MINUTES
One minute.

If a block we found in the namecache expires within this time, look for a fresher version of it in the DHT while we answer from the cache.

Without this, a resolver keeps serving the version it happened to fetch until it dies, and then pays a cold DHT lookup.

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

◆ BLOCK_REFRESH_TIMEOUT

#define BLOCK_REFRESH_TIMEOUT
Value:

How long do we leave a background refresh GET running?

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

566{
567 char *ret;
568 size_t s_len = strlen (name);
569
570 if (0 != strcmp (&name[s_len - 2],
571 ".+"))
572 return name; /* did not end in ".+" */
575 "%.*s.%s",
576 (int) (s_len - 2),
577 name,
581 return ret;
582}

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

593{
594 struct GNS_ResolverHandle *rh = cls;
595
596 rh->task_id = NULL;
598}

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

608{
609 rh->proc (rh->proc_cls,
610 0,
611 NULL);
612 GNUNET_assert (NULL == rh->task_id);
614 rh);
615}

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(), dht_lookup_timeout(), 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 624 of file gnunet-service-gns_resolver.c.

625{
626 struct GNS_ResolverHandle *rh = cls;
627
628 rh->task_id = NULL;
629 fail_resolution (rh);
630}

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

640{
641 struct protoent *pe = getprotobyname (name);
642 if (pe == NULL)
643 {
645 }
646 return pe->p_proto;
647}

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

658{
659 struct servent *se = getservbyname (name, proto);
660 if (se == NULL)
661 {
663 }
664 return se->s_port;
665}

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

688{
689 const char *rp;
690 const char *dot;
691 size_t len;
692 char *ret;
693 char *srv_name;
694 char *proto_name;
695 int protocol;
696 int service;
697
698 if (0 == rh->name_resolution_pos)
699 return NULL;
700 dot = memrchr (rh->name,
701 (int) '.',
703 if (NULL == dot)
704 {
705 /* done, this was the last one */
706 len = rh->name_resolution_pos;
707 rp = rh->name;
708 rh->name_resolution_pos = 0;
709 }
710 else if ('_' == dot[1])
711 {
720 len = strlen (GNUNET_GNS_EMPTY_LABEL_AT);
721 }
722 else
723 {
724 /* advance by one label */
725 len = rh->name_resolution_pos - (dot - rh->name) - 1;
726 rp = dot + 1;
727 rh->name_resolution_pos = dot - rh->name;
728 }
729 rh->protocol = 0;
730 rh->service = 0;
731 rh->prefix = NULL;
732 ret = GNUNET_strndup (rp, len);
737 if (('_' == rh->name[0]) &&
738 (NULL != (dot = memrchr (rh->name,
739 (int) '.',
740 rh->name_resolution_pos))) &&
741 ('_' == dot[1]) &&
742 (NULL == memrchr (rh->name,
743 (int) '.',
744 dot - rh->name)))
745 {
746 srv_name = GNUNET_strndup (&rh->name[1],
747 (dot - rh->name) - 1);
748 proto_name = GNUNET_strndup (&dot[2],
749 rh->name_resolution_pos - (dot - rh->name)
750 - 2);
751 protocol = resolver_getprotobyname (proto_name);
752 if (0 == protocol)
753 {
755 _ (
756 "Protocol `%s' unknown, skipping labels as BOX retain as SBOX.\n"),
757 proto_name);
758 GNUNET_free (proto_name);
759 GNUNET_free (srv_name);
761 rh->name_resolution_pos = 0;
762 return ret;
763 }
765 proto_name);
766 if (0 == service)
767 {
769 _ (
770 "Service `%s' unknown for protocol `%s', trying as number.\n"),
771 srv_name,
772 proto_name);
773 if (1 != sscanf (srv_name, "%u", &rh->service))
774 {
776 _ (
777 "Service `%s' not a port, skipping service labels as BOX retain as SBOX.\n"),
778 srv_name);
779 GNUNET_free (proto_name);
780 GNUNET_free (srv_name);
782 rh->name_resolution_pos = 0;
783 return ret;
784 }
785 }
786 else
787 {
788 rh->service = ntohs (service);
789 }
790 rh->protocol = protocol;
791 GNUNET_free (proto_name);
792 GNUNET_free (srv_name);
793 }
800 if ((NULL != (dot = memrchr (rh->name,
801 (int) '.',
802 rh->name_resolution_pos)) && '_' == dot[1]) ||
803 ((NULL == memrchr (rh->name,
804 (int) '.',
805 rh->name_resolution_pos)) && '_' == rh->name[0]))
806 {
808 rh->name_resolution_pos = 0;
809 }
810 return ret;
811}

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

821{
822 struct DnsResult *pos;
823 unsigned int n;
824 unsigned int i;
825
826 n = 0;
827 for (pos = rh->dns_result_head; NULL != pos; pos = pos->next)
828 n++;
829 {
830 struct GNUNET_GNSRECORD_Data rd[n];
831
832 i = 0;
833 for (pos = rh->dns_result_head; NULL != pos; pos = pos->next)
834 {
835 rd[i].data = pos->data;
836 rd[i].data_size = pos->data_size;
837 rd[i].record_type = pos->record_type;
845 if (0 == pos->expiration_time)
846 {
848 rd[i].expiration_time = 0;
849 }
850 else
851 {
853 }
854 i++;
855 }
856 GNUNET_assert (i == n);
858 "Transmitting standard DNS result with %u records\n",
859 n);
860 rh->proc (rh->proc_cls,
861 n,
862 rd);
863 }
865}

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

883{
884 struct DnsResult *res;
885
886 res = GNUNET_malloc (sizeof(struct DnsResult) + data_size);
887 res->expiration_time = expiration_time;
888 res->data_size = data_size;
889 res->record_type = record_type;
890 res->data = &res[1];
891 GNUNET_memcpy (&res[1],
892 data,
893 data_size);
895 rh->dns_result_tail,
896 res);
897}

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

912{
913 struct GNS_ResolverHandle *rh = cls;
914 const struct sockaddr_in *sa4;
915 const struct sockaddr_in6 *sa6;
916
917 if (NULL == addr)
918 {
919 rh->std_resolve = NULL;
921 return;
922 }
924 "Received %u bytes of DNS IP data\n",
925 addrlen);
926 switch (addr->sa_family)
927 {
928 case AF_INET:
929 sa4 = (const struct sockaddr_in *) addr;
930 add_dns_result (rh,
931 0 /* expiration time is unknown */,
933 sizeof(struct in_addr),
934 &sa4->sin_addr);
935 break;
936
937 case AF_INET6:
938 sa6 = (const struct sockaddr_in6 *) addr;
939 add_dns_result (rh,
940 0 /* expiration time is unknown */,
942 sizeof(struct in6_addr),
943 &sa6->sin6_addr);
944 break;
945
946 default:
947 GNUNET_break (0);
948 break;
949 }
950}

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

3139{
3140 struct GNS_ResolverHandle *rh = cls;
3141
3142 rh->task_id = NULL;
3143 if (rh->loop_threshold < rh->loop_limiter++)
3144 {
3146 "Encountered unbounded recursion resolving `%s'\n",
3147 rh->name);
3148 fail_resolution (rh);
3149 return;
3150 }
3151 if (GNUNET_YES == rh->ac_tail->gns_authority)
3153 else
3155}

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

3160{
3161 struct GNS_ResolverHandle *rh = cls;
3162 struct AuthorityChain *ac;
3163 struct in_addr v4;
3164 struct in6_addr v6;
3165
3166 rh->task_id = NULL;
3167 if (1 == inet_pton (AF_INET,
3168 rh->name,
3169 &v4))
3170 {
3171 /* name is IPv4 address, pretend it's an A record */
3173
3174 rd.data = &v4;
3175 rd.data_size = sizeof(v4);
3176 rd.expiration_time = UINT64_MAX;
3178 rd.flags = 0;
3179 rh->proc (rh->proc_cls,
3180 1,
3181 &rd);
3182 GNUNET_assert (NULL == rh->task_id);
3184 rh);
3185 return;
3186 }
3187 if (1 == inet_pton (AF_INET6,
3188 rh->name,
3189 &v6))
3190 {
3191 /* name is IPv6 address, pretend it's an AAAA record */
3193
3194 rd.data = &v6;
3195 rd.data_size = sizeof(v6);
3196 rd.expiration_time = UINT64_MAX;
3198 rd.flags = 0;
3199 rh->proc (rh->proc_cls,
3200 1,
3201 &rd);
3202 GNUNET_assert (NULL == rh->task_id);
3204 rh);
3205 return;
3206 }
3207
3208 ac = GNUNET_new (struct AuthorityChain);
3209 ac->rh = rh;
3211 if (NULL == ac->label)
3212 /* name was just the "TLD", so we default to label
3213 #GNUNET_GNS_EMPTY_LABEL_AT */
3218 rh->ac_tail,
3219 ac);
3221 rh);
3222}

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

984{
985 struct GNS_ResolverHandle *rh = cls;
987 const struct GNUNET_DNSPARSER_Record *rec;
988 unsigned int rd_count;
989
990 if (NULL == dns)
991 {
992 rh->dns_request = NULL;
994 rh->task_id = NULL;
995 fail_resolution (rh);
996 return;
997 }
998 if (rh->original_dns_id != dns->id)
999 {
1000 /* DNS answer, but for another query */
1001 return;
1002 }
1003 p = GNUNET_DNSPARSER_parse ((const char *) dns,
1004 dns_len);
1005 if (NULL == p)
1006 {
1008 _ ("Failed to parse DNS response\n"));
1009 return;
1010 }
1011
1012 /* We got a result from DNS */
1014 "Received DNS response for `%s' with %u answers\n",
1015 rh->ac_tail->label,
1016 (unsigned int) p->num_answers);
1017 if ((p->num_answers > 0) &&
1018 (GNUNET_DNSPARSER_TYPE_CNAME == p->answers[0].type) &&
1020 {
1021 int af;
1022
1024 "Got CNAME `%s' from DNS for `%s'\n",
1025 p->answers[0].data.hostname,
1026 rh->name);
1027 if (NULL != rh->std_resolve)
1028 {
1030 "Multiple CNAME results from DNS resolving `%s'! Not really allowed...\n",
1031 rh->name);
1033 }
1034 GNUNET_free (rh->name);
1035 rh->name = GNUNET_strdup (p->answers[0].data.hostname);
1036 rh->name_resolution_pos = strlen (rh->name);
1037 switch (rh->record_type)
1038 {
1040 af = AF_INET;
1041 break;
1042
1044 af = AF_INET6;
1045 break;
1046
1047 default:
1048 af = AF_UNSPEC;
1049 break;
1050 }
1051 if (NULL != rh->leho)
1052 add_dns_result (rh,
1053 GNUNET_TIME_UNIT_HOURS.rel_value_us,
1055 strlen (rh->leho),
1056 rh->leho);
1058 af,
1061 rh);
1064 rh->dns_request = NULL;
1065 return;
1066 }
1067
1068 /* convert from (parsed) DNS to (binary) GNS format! */
1069 rd_count = p->num_answers + p->num_authority_records
1070 + p->num_additional_records;
1071 {
1072 struct GNUNET_GNSRECORD_Data rd[rd_count + 1]; /* +1 for LEHO */
1073 int skip;
1074 char buf[UINT16_MAX];
1075 char *name_ace;
1076 size_t buf_off;
1077 size_t buf_start;
1078
1079 buf_off = 0;
1080 skip = 0;
1081 memset (rd,
1082 0,
1083 sizeof(rd));
1084 for (unsigned int i = 0; i < rd_count; i++)
1085 {
1086 if (i < p->num_answers)
1087 rec = &p->answers[i];
1088 else if (i < p->num_answers + p->num_authority_records)
1089 rec = &p->authority_records[i - p->num_answers];
1090 else
1091 rec = &p->additional_records[i - p->num_answers
1092 - p->num_authority_records];
1093 /* As we copied the full DNS name to 'rh->ac_tail->label', this
1094 should be the correct check to see if this record is actually
1095 a record for our label...
1096 However, DNSPARSER will convert the ACE name to UTF-8 so
1097 we must convert back.
1098 */
1099 if (IDNA_SUCCESS != idna_to_ascii_8z (rec->name,
1100 &name_ace,
1101 IDNA_ALLOW_UNASSIGNED))
1102 {
1104 _ ("Name `%s' cannot be converted to IDNA."),
1105 rec->name);
1106 continue;
1107 }
1108
1109 if (0 != strcmp (name_ace,
1110 rh->ac_tail->label))
1111 {
1113 "Dropping record `%s', does not match desired name `%s'\n",
1114 rec->name,
1115 rh->ac_tail->label);
1116 skip++;
1117 continue;
1118 }
1119 rd[i - skip].record_type = rec->type;
1121 switch (rec->type)
1122 {
1124 if (rec->data.raw.data_len != sizeof(struct in_addr))
1125 {
1126 GNUNET_break_op (0);
1127 skip++;
1128 continue;
1129 }
1130 rd[i - skip].data_size = rec->data.raw.data_len;
1131 rd[i - skip].data = rec->data.raw.data;
1132 break;
1133
1135 if (rec->data.raw.data_len != sizeof(struct in6_addr))
1136 {
1137 GNUNET_break_op (0);
1138 skip++;
1139 continue;
1140 }
1141 rd[i - skip].data_size = rec->data.raw.data_len;
1142 rd[i - skip].data = rec->data.raw.data;
1143 break;
1144
1148 buf_start = buf_off;
1149 if (GNUNET_OK !=
1151 sizeof(buf),
1152 &buf_off,
1153 rec->data.hostname))
1154 {
1155 GNUNET_break (0);
1156 skip++;
1157 continue;
1158 }
1159 rd[i - skip].data_size = buf_off - buf_start;
1160 rd[i - skip].data = &buf[buf_start];
1161 break;
1162
1164 buf_start = buf_off;
1165 if (GNUNET_OK !=
1167 sizeof(buf),
1168 &buf_off,
1169 rec->data.soa))
1170 {
1171 GNUNET_break (0);
1172 skip++;
1173 continue;
1174 }
1175 rd[i - skip].data_size = buf_off - buf_start;
1176 rd[i - skip].data = &buf[buf_start];
1177 break;
1178
1180 buf_start = buf_off;
1181 if (GNUNET_OK !=
1183 sizeof(buf),
1184 &buf_off,
1185 rec->data.mx))
1186 {
1187 GNUNET_break (0);
1188 skip++;
1189 continue;
1190 }
1191 rd[i - skip].data_size = buf_off - buf_start;
1192 rd[i - skip].data = &buf[buf_start];
1193 break;
1194
1196 buf_start = buf_off;
1197 if (GNUNET_OK !=
1199 sizeof(buf),
1200 &buf_off,
1201 rec->data.srv))
1202 {
1203 GNUNET_break (0);
1204 skip++;
1205 continue;
1206 }
1207 rd[i - skip].data_size = buf_off - buf_start;
1208 rd[i - skip].data = &buf[buf_start];
1209 break;
1210
1212 buf_start = buf_off;
1213 if (GNUNET_OK !=
1215 sizeof(buf),
1216 &buf_off,
1217 rec->data.uri))
1218 {
1219 GNUNET_break (0);
1220 skip++;
1221 continue;
1222 }
1223 rd[i - skip].data_size = buf_off - buf_start;
1224 rd[i - skip].data = &buf[buf_start];
1225 break;
1226
1227 default:
1229 _ ("Skipping record of unsupported type %d\n"),
1230 rec->type);
1231 skip++;
1232 continue;
1233 }
1234 } /* end of for all records in answer */
1235 if (NULL != rh->leho)
1236 {
1240 rd[rd_count - skip].expiration_time = GNUNET_TIME_UNIT_HOURS.rel_value_us;
1241 rd[rd_count - skip].data = rh->leho;
1242 rd[rd_count - skip].data_size = strlen (rh->leho);
1243 skip--; /* skip one LESS */
1245 "Adding LEHO %s\n",
1246 rh->leho);
1247 }
1249 "Returning DNS response for `%s' with %u answers\n",
1250 rh->ac_tail->label,
1251 (unsigned int) (rd_count - skip));
1252 rh->proc (rh->proc_cls,
1253 rd_count - skip,
1254 rd);
1256 rh->dns_request = NULL;
1257 }
1258
1259
1261 if (NULL != rh->task_id)
1262 GNUNET_SCHEDULER_cancel (rh->task_id); /* should be timeout task */
1264 rh);
1265}

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

1278{
1279 struct AuthorityChain *ac;
1280 struct GNUNET_DNSPARSER_Query *query;
1281 struct GNUNET_DNSPARSER_Packet *p;
1282 char *dns_request;
1283 size_t dns_request_length;
1284 int ret;
1285
1286 ac = rh->ac_tail;
1287 GNUNET_assert (NULL != ac);
1289 "Starting DNS lookup for `%s'\n",
1290 ac->label);
1292 query = GNUNET_new (struct GNUNET_DNSPARSER_Query);
1293 query->name = GNUNET_strdup (ac->label);
1294 query->type = rh->record_type;
1297 p->queries = query;
1298 p->num_queries = 1;
1299 p->id = (uint16_t) GNUNET_CRYPTO_random_u32 (UINT16_MAX);
1300 p->flags.opcode = GNUNET_TUN_DNS_OPCODE_QUERY;
1301 p->flags.recursion_desired = 1;
1303 1024,
1304 &dns_request,
1305 &dns_request_length);
1306 if (GNUNET_OK != ret)
1307 {
1308 GNUNET_break (0);
1309 rh->proc (rh->proc_cls,
1310 0,
1311 NULL);
1312 GNUNET_assert (NULL == rh->task_id);
1314 rh);
1315 }
1316 else
1317 {
1318 rh->original_dns_id = p->id;
1320 GNUNET_assert (NULL == rh->dns_request);
1321 if (IDNA_SUCCESS != idna_to_unicode_8z8z (ac->label,
1322 &rh->leho,
1323 IDNA_ALLOW_UNASSIGNED))
1324 {
1325 GNUNET_break (0);
1326 rh->proc (rh->proc_cls,
1327 0,
1328 NULL);
1329 GNUNET_assert (NULL == rh->task_id);
1331 rh);
1332 }
1335 dns_request,
1336 dns_request_length,
1338 rh);
1341 rh);
1342 }
1343 if (GNUNET_SYSERR != ret)
1344 GNUNET_free (dns_request);
1346}

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

1360{
1361 size_t nlen;
1362 char *res;
1363 const char *tld;
1364 struct AuthorityChain *ac;
1365 int af;
1367
1369 "Handling GNS REDIRECT result `%s'\n",
1370 rname);
1371 nlen = strlen (rname);
1372 tld = GNS_get_tld (rname);
1373 if (0 == strcmp ("+", tld))
1374 {
1375 /* REDIRECT resolution continues relative to current domain */
1376 if (0 == rh->name_resolution_pos)
1377 {
1378 res = GNUNET_strndup (rname, nlen - 2);
1379 rh->name_resolution_pos = nlen - 2;
1380 }
1381 else
1382 {
1384 "%.*s.%.*s",
1385 (int) rh->name_resolution_pos,
1386 rh->name,
1387 (int) (nlen - 2),
1388 rname);
1389 rh->name_resolution_pos = strlen (res);
1390 }
1391 GNUNET_free (rh->name);
1392 rh->name = res;
1393 ac = GNUNET_new (struct AuthorityChain);
1394 ac->rh = rh;
1399 /* add AC to tail */
1401 rh->ac_tail,
1402 ac);
1404 rh);
1405 return;
1406 }
1407 if (GNUNET_OK == GNUNET_GNSRECORD_zkey_to_pkey (tld, &zone))
1408 {
1409 /* REDIRECT resolution continues relative to current domain */
1410 if (0 == rh->name_resolution_pos)
1411 {
1413 "%.*s",
1414 (int) (strlen (rname) - (strlen (tld) + 1)),
1415 rname);
1416 }
1417 else
1418 {
1420 "%.*s.%.*s",
1421 (int) rh->name_resolution_pos,
1422 rh->name,
1423 (int) (strlen (rname) - (strlen (tld) + 1)),
1424 rname);
1425 }
1426 rh->name_resolution_pos = strlen (res);
1427 GNUNET_free (rh->name);
1428 rh->name = res;
1429 ac = GNUNET_new (struct AuthorityChain);
1430 ac->rh = rh;
1432 ac->authority_info.gns_authority = zone;
1434 /* add AC to tail */
1436 rh->ac_tail,
1437 ac);
1439 rh);
1440 return;
1441 }
1442
1444 "Got REDIRECT `%s' from GNS for `%s'\n",
1445 rname,
1446 rh->name);
1447 if (NULL != rh->std_resolve)
1448 {
1450 "Multiple REDIRECT results from GNS resolving `%s'! Not really allowed...\n",
1451 rh->name);
1453 }
1454 /* name is absolute, go to DNS */
1455 GNUNET_free (rh->name);
1456 rh->name = GNUNET_strdup (rname);
1457 rh->name_resolution_pos = strlen (rh->name);
1458 switch (rh->record_type)
1459 {
1461 af = AF_INET;
1462 break;
1463
1465 af = AF_INET6;
1466 break;
1467
1468 default:
1469 af = AF_UNSPEC;
1470 break;
1471 }
1473 "Doing standard DNS lookup for `%s'\n",
1474 rh->name);
1475
1477 af,
1480 rh);
1481}

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

1495{
1496 int af;
1497
1498 GNUNET_free (rh->name);
1499 rh->name = GNUNET_strdup (cname);
1500 rh->name_resolution_pos = strlen (rh->name);
1501 switch (rh->record_type)
1502 {
1504 af = AF_INET;
1505 break;
1506
1508 af = AF_INET6;
1509 break;
1510
1511 default:
1512 af = AF_UNSPEC;
1513 break;
1514 }
1516 "Doing standard DNS lookup for `%s'\n",
1517 rh->name);
1518
1520 af,
1523 rh);
1524}

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

2031{
2032 struct GNS_ResolverHandle *rh = cls;
2033 char *cname;
2034 char scratch[UINT16_MAX];
2035 size_t scratch_off;
2036 size_t scratch_start;
2037 size_t off;
2038 struct GNUNET_GNSRECORD_Data rd_new[rd_count];
2039 unsigned int rd_off;
2040
2042 "Resolution succeeded for `%s' in zone %s, got %u records\n",
2043 rh->ac_tail->label,
2045 rd_count);
2046 if (0 == rd_count)
2047 {
2049 _ ("GNS lookup failed (zero records found for `%s')\n"),
2050 rh->name);
2051 fail_resolution (rh);
2052 return;
2053 }
2054
2055 if (0 == rh->name_resolution_pos)
2056 {
2057 /* top-level match, are we done yet? */
2058 if ((rd_count > 0) &&
2061 {
2062 off = 0;
2064 rd[0].data_size,
2065 &off);
2066 if ((NULL == cname) ||
2067 (off != rd[0].data_size))
2068 {
2069 GNUNET_break_op (0);
2070 GNUNET_free (cname);
2071 fail_resolution (rh);
2072 return;
2073 }
2075 cname);
2076 GNUNET_free (cname);
2077 return;
2078 }
2079 if ((rd_count > 0) &&
2082 {
2084 rd[0].data);
2085 return;
2086 }
2087
2088
2089 /* If A/AAAA was requested,
2090 * but we got a GNS2DNS record */
2091 if ((GNUNET_DNSPARSER_TYPE_A == rh->record_type) ||
2093 {
2094 for (unsigned int i = 0; i < rd_count; i++)
2095 {
2096 switch (rd[i].record_type)
2097 {
2099 {
2100 /* delegation to DNS */
2102 "Found GNS2DNS record, delegating to DNS!\n");
2103 if (GNUNET_OK ==
2105 rd_count,
2106 rd))
2107 return;
2108 else
2109 goto fail;
2110 }
2111
2112 default:
2113 break;
2114 } /* end: switch */
2115 } /* end: for rd */
2116 } /* end: name_resolution_pos */
2117 /* convert relative names in record values to absolute names,
2118 using 'scratch' array for memory allocations */
2119 scratch_off = 0;
2120 rd_off = 0;
2121 for (unsigned int i = 0; i < rd_count; i++)
2122 {
2123 GNUNET_assert (rd_off <= i);
2124 if ((((0 != rh->protocol) &&
2125 (0 != rh->service)) || (NULL != rh->prefix)) &&
2130 continue;
2131 /* we _only_ care about boxed records */
2132
2133 GNUNET_assert (rd_off < rd_count);
2134 rd_new[rd_off] = rd[i];
2135 /* Check if the embedded name(s) end in "+", and if so,
2136 replace the "+" with the zone at "ac_tail", changing the name
2137 to a ".ZONEKEY". The name is allocated on the 'scratch' array,
2138 so we can free it afterwards. */
2139 switch (rd[i].record_type)
2140 {
2142 {
2143 char *rname;
2144 rname = GNUNET_strndup (rd[i].data, rd[i].data_size);
2145 rname = translate_dot_plus (rh, rname);
2146 GNUNET_break (NULL != rname);
2147 scratch_start = scratch_off;
2148 memcpy (&scratch[scratch_start], rname, strlen (rname) + 1);
2149 scratch_off += strlen (rname) + 1;
2150 GNUNET_assert (rd_off < rd_count);
2151 rd_new[rd_off].data = &scratch[scratch_start];
2152 rd_new[rd_off].data_size = scratch_off - scratch_start;
2153 rd_off++;
2154 GNUNET_free (rname);
2155 }
2156 break;
2157
2159 {
2160 char *cname_tmp;
2161
2162 off = 0;
2163 cname_tmp = GNUNET_DNSPARSER_parse_name (rd[i].data,
2164 rd[i].data_size,
2165 &off);
2166 if ((NULL == cname_tmp) ||
2167 (off != rd[i].data_size))
2168 {
2169 GNUNET_break_op (0); /* record not well-formed */
2170 }
2171 else
2172 {
2173 cname_tmp = translate_dot_plus (rh, cname_tmp);
2174 GNUNET_break (NULL != cname_tmp);
2175 scratch_start = scratch_off;
2176 if (GNUNET_OK !=
2178 sizeof(scratch),
2179 &scratch_off,
2180 cname_tmp))
2181 {
2182 GNUNET_break (0);
2183 }
2184 else
2185 {
2186 GNUNET_assert (rd_off < rd_count);
2187 rd_new[rd_off].data = &scratch[scratch_start];
2188 rd_new[rd_off].data_size = scratch_off - scratch_start;
2189 rd_off++;
2190 }
2191 }
2192 GNUNET_free (cname_tmp);
2193 }
2194 break;
2195
2197 {
2198 struct GNUNET_DNSPARSER_SoaRecord *soa;
2199
2200 off = 0;
2202 rd[i].data_size,
2203 &off);
2204 if ((NULL == soa) ||
2205 (off != rd[i].data_size))
2206 {
2207 GNUNET_break_op (0); /* record not well-formed */
2208 }
2209 else
2210 {
2211 soa->mname = translate_dot_plus (rh, soa->mname);
2212 soa->rname = translate_dot_plus (rh, soa->rname);
2213 scratch_start = scratch_off;
2214 if (GNUNET_OK !=
2216 sizeof(scratch),
2217 &scratch_off,
2218 soa))
2219 {
2220 GNUNET_break (0);
2221 }
2222 else
2223 {
2224 GNUNET_assert (rd_off < rd_count);
2225 rd_new[rd_off].data = &scratch[scratch_start];
2226 rd_new[rd_off].data_size = scratch_off - scratch_start;
2227 rd_off++;
2228 }
2229 }
2230 if (NULL != soa)
2232 }
2233 break;
2234
2236 {
2237 struct GNUNET_DNSPARSER_MxRecord *mx;
2238
2239 off = 0;
2241 rd[i].data_size,
2242 &off);
2243 if ((NULL == mx) ||
2244 (off != rd[i].data_size))
2245 {
2246 GNUNET_break_op (0); /* record not well-formed */
2247 }
2248 else
2249 {
2250 mx->mxhost = translate_dot_plus (rh, mx->mxhost);
2251 scratch_start = scratch_off;
2252 if (GNUNET_OK !=
2254 sizeof(scratch),
2255 &scratch_off,
2256 mx))
2257 {
2258 GNUNET_break (0);
2259 }
2260 else
2261 {
2262 GNUNET_assert (rd_off < rd_count);
2263 rd_new[rd_off].data = &scratch[scratch_start];
2264 rd_new[rd_off].data_size = scratch_off - scratch_start;
2265 rd_off++;
2266 }
2267 }
2268 if (NULL != mx)
2270 }
2271 break;
2272
2274 {
2275 struct GNUNET_DNSPARSER_SrvRecord *srv;
2276
2277 off = 0;
2279 rd[i].data_size,
2280 &off);
2281 if ((NULL == srv) ||
2282 (off != rd[i].data_size))
2283 {
2284 GNUNET_break_op (0); /* record not well-formed */
2285 }
2286 else
2287 {
2288 srv->target = translate_dot_plus (rh, srv->target);
2289 scratch_start = scratch_off;
2290 if (GNUNET_OK !=
2292 sizeof(scratch),
2293 &scratch_off,
2294 srv))
2295 {
2296 GNUNET_break (0);
2297 }
2298 else
2299 {
2300 GNUNET_assert (rd_off < rd_count);
2301 rd_new[rd_off].data = &scratch[scratch_start];
2302 rd_new[rd_off].data_size = scratch_off - scratch_start;
2303 rd_off++;
2304 }
2305 }
2306 if (NULL != srv)
2308 }
2309 break;
2310
2312 {
2314
2315 off = 0;
2317 rd[i].data_size,
2318 &off);
2319 if ((NULL == uri) ||
2320 (off != rd[i].data_size))
2321 {
2323 _ ("Failed to deserialize URI record with target\n"));
2324 GNUNET_break_op (0); /* record not well-formed */
2325 }
2326 else
2327 {
2328 scratch_start = scratch_off;
2329 if (GNUNET_OK !=
2331 sizeof(scratch),
2332 &scratch_off,
2333 uri))
2334 {
2335 GNUNET_break (0);
2336 }
2337 else
2338 {
2339 GNUNET_assert (rd_off < rd_count);
2340 rd_new[rd_off].data = &scratch[scratch_start];
2341 rd_new[rd_off].data_size = scratch_off - scratch_start;
2342 rd_off++;
2343 }
2344 }
2345 if (NULL != uri)
2347 }
2348 break;
2349
2352 {
2354 if (rd[i].data_size < sizeof(uint32_t))
2355 {
2356 GNUNET_break_op (0);
2357 break;
2358 }
2359 if (GNUNET_OK !=
2361 rd[i].data_size,
2362 rd[i].record_type,
2363 &pubkey))
2364 {
2365 GNUNET_break_op (0);
2366 break;
2367 }
2368 rd_off++;
2369 if (rd[i].record_type != rh->record_type)
2370 {
2371 /* try to resolve "@" */
2372 struct AuthorityChain *ac;
2373
2374 ac = GNUNET_new (struct AuthorityChain);
2375 ac->rh = rh;
2380 rh->ac_tail,
2381 ac);
2383 rh);
2384 return;
2385 }
2386 }
2387 break;
2388
2390 {
2391 /* delegation to DNS */
2393 {
2394 rd_off++;
2395 break; /* do not follow to DNS, we wanted the GNS2DNS record! */
2396 }
2398 "Found GNS2DNS record, delegating to DNS!\n");
2399 if (GNUNET_OK ==
2401 rd_count,
2402 rd))
2403 return;
2404 else
2405 goto fail;
2406 }
2407
2409 {
2410 /* unbox SRV/TLSA records if a specific one was requested */
2411 if ((0 != rh->protocol) &&
2412 (0 != rh->service) &&
2413 (rd[i].data_size >= sizeof(struct GNUNET_GNSRECORD_BoxRecord)))
2414 {
2415 const struct GNUNET_GNSRECORD_BoxRecord *box;
2416
2417 box = rd[i].data;
2419 "Got BOX record, checking if parameters match... %u/%u vs %u/%u\n",
2420 ntohs (box->protocol), ntohs (box->service),
2421 rh->protocol, rh->service);
2422 if ((ntohs (box->protocol) == rh->protocol) &&
2423 (ntohs (box->service) == rh->service))
2424 {
2425 /* Box matches, unbox! */
2426 GNUNET_assert (rd_off < rd_count);
2427 rd_new[rd_off].record_type = ntohl (box->record_type);
2428 rd_new[rd_off].data_size -= sizeof(struct
2430 rd_new[rd_off].data = &box[1];
2431 rd_off++;
2432 }
2433 }
2434 else
2435 {
2436 /* no specific protocol/service specified, preserve all BOX
2437 records (for modern, GNS-enabled applications) */
2438 rd_off++;
2439 }
2440 break;
2441 }
2443 {
2444 /* unbox SBOX records if a specific one was requested */
2445 if ((rh->prefix != NULL) &&
2446 (rd[i].data_size >= sizeof(struct GNUNET_GNSRECORD_SBoxRecord)))
2447 {
2448 const struct GNUNET_GNSRECORD_SBoxRecord *box;
2449 const char *prefix;
2450 size_t prefix_len;
2451
2452 box = rd[i].data;
2453 prefix = rd[i].data + sizeof(struct GNUNET_GNSRECORD_SBoxRecord);
2454 prefix_len = strnlen (
2455 prefix,
2456 rd[i].data_size - sizeof(struct GNUNET_GNSRECORD_SBoxRecord)) + 1;
2457 if (prefix_len - 1 >= rd[i].data_size - sizeof(struct
2459 {
2461 "SBOX record with invalid prefix length, maybe not null-terminated\n");
2462 continue;
2463 }
2465 "Got SBOX record, checking if prefixes match... %s vs %s\n",
2466 prefix, rh->prefix);
2467 if (strcmp (rh->prefix, prefix) == 0)
2468 {
2469 /* Box matches, unbox! */
2470 GNUNET_assert (rd_off < rd_count);
2471 rd_new[rd_off].record_type = ntohl (box->record_type);
2472 rd_new[rd_off].data_size -= sizeof(struct
2474 + prefix_len;
2475 rd_new[rd_off].data = rd[i].data
2476 + sizeof(struct GNUNET_GNSRECORD_SBoxRecord)
2477 + prefix_len;
2478 rd_off++;
2479 }
2480 }
2481 else
2482 {
2484 _ (
2485 "GNS no specific protocol/service specified, preserve all SBOX `%s')\n"),
2486 rh->name);
2487 /* no specific protocol/service specified, preserve all SBOX
2488 records (for modern, GNS-enabled applications) */
2489 rd_off++;
2490 }
2491 break;
2492 }
2493 default:
2494 rd_off++;
2495 break;
2496 } /* end: switch */
2497 } /* end: for rd_count */
2498
2499 GNUNET_free (rh->prefix);
2500 rh->prefix = NULL;
2501
2502 /* yes, we are done, return result */
2504 "Returning GNS response for `%s' with %u answers\n",
2505 rh->ac_tail->label,
2506 rd_off);
2507 rh->proc (rh->proc_cls,
2508 rd_off,
2509 rd_new);
2511 rh);
2512 return;
2513 }
2514
2515 switch (rd[0].record_type)
2516 {
2518 GNUNET_break_op (1 == rd_count); /* REDIRECT should be unique */
2520 &rd[0]);
2521 return;
2522
2524 GNUNET_break_op (1 == rd_count); /* CNAME should be unique */
2526 &rd[0]);
2527 return;
2528
2531 GNUNET_break_op (1 == rd_count); /* PKEY should be unique */
2533 &rd[0]);
2534 return;
2535
2537 if (GNUNET_OK ==
2539 rd_count,
2540 rd))
2541 return;
2542 break;
2543 default:
2545 return;
2547 _ ("Unable to process critical delegation record\n"));
2548 break;
2549 }
2550fail:
2552 _ ("GNS lookup recursion failed (no delegation record found)\n"));
2553 fail_resolution (rh);
2554}

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

1549{
1550 struct GNS_ResolverHandle *rh = ac->rh;
1551
1552 if ((NULL != ac->authority_info.dns_authority.gp_head) &&
1554 return; /* more pending and none found yet */
1556 {
1558 "Failed to resolve DNS server for `%s' in GNS2DNS resolution\n",
1560 fail_resolution (rh);
1561 return;
1562 }
1564 return; /* already running, do not launch again! */
1565 /* recurse */
1568 "Will continue resolution using DNS to resolve `%s'\n",
1569 ac->label);
1570 GNUNET_assert (NULL == rh->task_id);
1572 rh);
1573}

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

1588{
1589 struct Gns2DnsPending *gp = cls;
1590 struct AuthorityChain *ac = gp->ac;
1591
1594 gp);
1595 /* enable cleanup of 'rh' handle that automatically comes after we return,
1596 and which expects 'rh' to be in the #rlh_head DLL. */
1597 if (NULL != gp->rh)
1598 {
1600 rlh_tail,
1601 gp->rh);
1602 gp->rh = NULL;
1603 }
1604 GNUNET_free (gp);
1606 "Received %u results for IP address of DNS server for GNS2DNS transition\n",
1607 rd_count);
1608 /* find suitable A/AAAA record */
1609 for (unsigned int j = 0; j < rd_count; j++)
1610 {
1611 switch (rd[j].record_type)
1612 {
1614 {
1615 struct sockaddr_in v4;
1616
1617 if (sizeof(struct in_addr) != rd[j].data_size)
1618 {
1619 GNUNET_break_op (0);
1620 continue;
1621 }
1622 memset (&v4,
1623 0,
1624 sizeof(v4));
1625 v4.sin_family = AF_INET;
1626 v4.sin_port = htons (53);
1627#if HAVE_SOCKADDR_IN_SIN_LEN
1628 v4.sin_len = (u_char) sizeof(v4);
1629#endif
1630 GNUNET_memcpy (&v4.sin_addr,
1631 rd[j].data,
1632 sizeof(struct in_addr));
1633 if (GNUNET_OK ==
1636 (const struct sockaddr *) &v4))
1638 break;
1639 }
1640
1642 {
1643 struct sockaddr_in6 v6;
1644
1645 if (sizeof(struct in6_addr) != rd[j].data_size)
1646 {
1647 GNUNET_break_op (0);
1648 continue;
1649 }
1650 /* FIXME: might want to check if we support IPv6 here,
1651 and otherwise skip this one and hope we find another */
1652 memset (&v6,
1653 0,
1654 sizeof(v6));
1655 v6.sin6_family = AF_INET6;
1656 v6.sin6_port = htons (53);
1657#if HAVE_SOCKADDR_IN_SIN_LEN
1658 v6.sin6_len = (u_char) sizeof(v6);
1659#endif
1660 GNUNET_memcpy (&v6.sin6_addr,
1661 rd[j].data,
1662 sizeof(struct in6_addr));
1663 if (GNUNET_OK ==
1666 (const struct sockaddr *) &v6))
1668 break;
1669 }
1670
1671 default:
1672 break;
1673 }
1674 }
1676}

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

1690{
1691 struct Gns2DnsPending *gp = cls;
1692 struct AuthorityChain *ac = gp->ac;
1693 struct sockaddr_storage ss;
1694 struct sockaddr_in *v4;
1695 struct sockaddr_in6 *v6;
1696
1697 if (NULL == addr)
1698 {
1699 /* DNS resolution finished */
1700 if (0 == gp->num_results)
1702 "Failed to use DNS to resolve name of DNS resolver\n");
1705 gp);
1706 GNUNET_free (gp);
1708 return;
1709 }
1710 GNUNET_memcpy (&ss,
1711 addr,
1712 addrlen);
1713 switch (ss.ss_family)
1714 {
1715 case AF_INET:
1716 v4 = (struct sockaddr_in *) &ss;
1717 v4->sin_port = htons (53);
1718 gp->num_results++;
1719 break;
1720
1721 case AF_INET6:
1722 v6 = (struct sockaddr_in6 *) &ss;
1723 v6->sin6_port = htons (53);
1724 gp->num_results++;
1725 break;
1726
1727 default:
1729 "Unsupported AF %d\n",
1730 ss.ss_family);
1731 return;
1732 }
1733 if (GNUNET_OK ==
1735 (struct sockaddr *) &ss))
1737}

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

1749{
1751 rd->data);
1752}

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

1764{
1765 char *cname;
1766 size_t off;
1767
1768 off = 0;
1770 rd->data_size,
1771 &off);
1772 if ((NULL == cname) ||
1773 (off != rd->data_size))
1774 {
1775 GNUNET_break_op (0); /* record not well-formed */
1776 GNUNET_free (cname);
1777 fail_resolution (rh);
1778 return;
1779 }
1781 cname);
1782 GNUNET_free (cname);
1783}

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

1795{
1796 struct AuthorityChain *ac;
1798
1799 /* delegation to another zone */
1801 rd->data_size,
1802 rd->record_type,
1803 &auth))
1804 {
1805 GNUNET_break_op (0);
1806 fail_resolution (rh);
1807 return;
1808 }
1809 /* expand authority chain */
1810 ac = GNUNET_new (struct AuthorityChain);
1811 ac->rh = rh;
1813 ac->authority_info.gns_authority = auth;
1815 /* add AC to tail */
1817 rh->ac_tail,
1818 ac);
1819 /* recurse */
1821 rh);
1822}

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 FIXME: According to RFC 9498, they are...

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

1839{
1840 struct AuthorityChain *ac;
1841 const char *tld;
1842 char *ns;
1843
1844 ns = NULL;
1845 /* expand authority chain */
1846 ac = GNUNET_new (struct AuthorityChain);
1847 ac->rh = rh;
1849
1850 for (unsigned int i = 0; i < rd_count; i++)
1851 {
1852 char *ip;
1853 char *n;
1854 struct Gns2DnsPending *gp;
1856 struct sockaddr_in v4;
1857 struct sockaddr_in6 v6;
1858
1859 if (GNUNET_GNSRECORD_TYPE_GNS2DNS != rd[i].record_type)
1860 {
1865 GNUNET_free (ns);
1866 GNUNET_free (ac);
1867 return GNUNET_SYSERR;
1868 }
1869 n = GNUNET_strdup ((const char*) rd[i].data);
1870 if (strlen (n) + 1 >= rd[i].data_size)
1871 {
1872 GNUNET_break_op (0);
1873 continue;
1874 }
1875 ip = GNUNET_strdup (rd[i].data + strlen (n) + 1);
1876 /* resolve 'ip' to determine the IP(s) of the DNS
1877 resolver to use for lookup of 'ns' */
1878 if (NULL != ns)
1879 {
1880 if (0 != strcasecmp (ns,
1881 n))
1882 {
1883 /* NS values must all be the same for all GNS2DNS records,
1884 anything else leads to insanity */
1885 GNUNET_break_op (0);
1886 GNUNET_free (n);
1887 GNUNET_free (ip);
1888 continue;
1889 }
1890 GNUNET_free (n);
1891 }
1892 else
1893 {
1894 ns = n;
1895 }
1896
1897 /* check if 'ip' is already an IPv4/IPv6 address */
1898 if ((1 == inet_pton (AF_INET,
1899 ip,
1900 &v4)) ||
1901 (1 == inet_pton (AF_INET6,
1902 ip,
1903 &v6)))
1904 {
1908 ip));
1910 GNUNET_free (ip);
1911 continue;
1912 }
1913 tld = GNS_get_tld (ip);
1914 if ((0 != strcmp (tld, "+")) &&
1915 (GNUNET_OK != GNUNET_GNSRECORD_zkey_to_pkey (tld, &zone)))
1916 {
1917 /* 'ip' is a DNS name */
1918 gp = GNUNET_new (struct Gns2DnsPending);
1919 gp->ac = ac;
1922 gp);
1924 AF_UNSPEC,
1927 gp);
1928 GNUNET_free (ip);
1929 continue;
1930 }
1931 /* 'ip' should be a GNS name */
1932 gp = GNUNET_new (struct Gns2DnsPending);
1933 gp->ac = ac;
1936 gp);
1937 gp->rh = GNUNET_new (struct GNS_ResolverHandle);
1938 if (0 == strcmp (tld, "+"))
1939 {
1940 ip = translate_dot_plus (rh,
1941 ip);
1942 tld = GNS_get_tld (ip);
1943 if (GNUNET_OK !=
1945 &zone))
1946 {
1947 GNUNET_break_op (0);
1948 GNUNET_free (ip);
1949 continue;
1950 }
1951 }
1952 gp->rh->authority_zone = zone;
1954 "Resolving `%s' to determine IP address of DNS server for GNS2DNS transition for `%s'\n",
1955 ip,
1956 ns);
1957 gp->rh->name = ip;
1958 gp->rh->name_resolution_pos = strlen (ip) - strlen (tld) - 1;
1960 gp->rh->proc_cls = gp;
1963 gp->rh->loop_limiter = rh->loop_limiter + 1;
1964 gp->rh->loop_threshold = rh->loop_threshold;
1965 gp->rh->task_id
1967 gp->rh);
1968 } /* end 'for all records' */
1969
1970 if (NULL == ns)
1971 {
1972 /* not a single GNS2DNS record found */
1973 GNUNET_free (ac);
1974 return GNUNET_SYSERR;
1975 }
1977 strcpy (ac->authority_info.dns_authority.name,
1978 ns);
1979 /* for DNS recursion, the label is the full DNS name,
1980 created from the remainder of the GNS name and the
1981 name in the NS record */
1982 GNUNET_asprintf (&ac->label,
1983 "%.*s%s%s",
1984 (int) rh->name_resolution_pos,
1985 rh->name,
1986 (0 != rh->name_resolution_pos) ? "." : "",
1987 ns);
1988 GNUNET_free (ns);
1989
1990 {
1991 /* the GNS name is UTF-8 and may include multibyte chars.
1992 * We have to convert the combined name to a DNS-compatible IDNA.
1993 */
1994 char *tmp = ac->label;
1995
1996 if (IDNA_SUCCESS != idna_to_ascii_8z (tmp,
1997 &ac->label,
1998 IDNA_ALLOW_UNASSIGNED))
1999 {
2001 _ ("Name `%s' cannot be converted to IDNA."),
2002 tmp);
2003 GNUNET_free (tmp);
2004 GNUNET_free (ac);
2005 return GNUNET_SYSERR;
2006 }
2007 GNUNET_free (tmp);
2008 }
2009
2011 rh->ac_tail,
2012 ac);
2013 if (strlen (ac->label) > GNUNET_DNSPARSER_MAX_NAME_LENGTH)
2014 {
2016 _ ("GNS lookup resulted in DNS name that is too long (`%s')\n"),
2017 ac->label);
2018 GNUNET_free (ac->label);
2019 GNUNET_free (ac);
2020 return GNUNET_SYSERR;
2021 }
2023 return GNUNET_OK;
2024}

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

2569{
2570 struct CacheOps *co = cls;
2571
2572 co->namecache_qe_cache = NULL;
2573 if (GNUNET_OK != success)
2575 _ ("Failed to cache GNS resolution: %s\n"),
2576 emsg);
2578 co_tail,
2579 co);
2580 GNUNET_free (co);
2581}

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(), and handle_refresh_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 2603 of file gnunet-service-gns_resolver.c.

2614{
2615 struct GNS_ResolverHandle *rh = cls;
2616 struct AuthorityChain *ac = rh->ac_tail;
2617 const struct GNUNET_GNSRECORD_Block *block;
2618 struct CacheOps *co;
2619
2620 (void) exp;
2621 (void) key;
2622 (void) get_path;
2623 (void) get_path_length;
2624 (void) put_path;
2625 (void) put_path_length;
2626 (void) type;
2628 rh->get_handle = NULL;
2630 rh->dht_heap_node = NULL;
2631 /* must be cleared before handle_gns_resolution_result() below gets
2632 to schedule the next step */
2633 if (NULL != rh->task_id)
2634 {
2636 rh->task_id = NULL;
2637 }
2639 "Handling response from the DHT\n");
2640 if (size < sizeof(struct GNUNET_GNSRECORD_Block))
2641 {
2642 /* how did this pass DHT block validation!? */
2643 GNUNET_break (0);
2644 fail_resolution (rh);
2645 return;
2646 }
2647 block = data;
2649 {
2650 /* how did this pass DHT block validation!? */
2651 GNUNET_break (0);
2652 fail_resolution (rh);
2653 return;
2654 }
2656 "Decrypting DHT block of size %llu for `%s', expires %s\n",
2657 (unsigned long long) GNUNET_GNSRECORD_block_get_size (block),
2658 rh->name,
2660 if (GNUNET_OK !=
2663 ac->label,
2665 rh))
2666 {
2667 GNUNET_break_op (0); /* block was ill-formed */
2668 fail_resolution (rh);
2669 return;
2670 }
2673 rel_value_us)
2674 {
2676 "Received expired block from the DHT, will not cache it.\n");
2677 return;
2678 }
2680 return;
2681 /* Cache well-formed blocks */
2683 "Caching response from the DHT in namecache\n");
2684 co = GNUNET_new (struct CacheOps);
2686 block,
2687 &
2689 co);
2691 co_tail,
2692 co);
2693}

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_SCHEDULER_cancel(), 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, GNS_ResolverHandle::task_id, 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 2746 of file gnunet-service-gns_resolver.c.

2748{
2749 struct GNS_ResolverHandle *rx;
2750
2751 GNUNET_assert (NULL == rh->get_handle);
2752 rh->dht_query = *query;
2755 query,
2758 NULL, 0,
2759 &handle_dht_response, rh);
2761 rh,
2763 abs_value_us);
2764 GNUNET_assert (NULL == rh->task_id);
2767 rh);
2770 {
2771 /* fail longest-standing DHT request */
2773 GNUNET_assert (NULL != rx);
2774 rx->dht_heap_node = NULL;
2775 if (NULL != rx->task_id)
2776 {
2778 rx->task_id = NULL;
2779 }
2780 fail_resolution (rx);
2781 }
2782}

References DHT_GNS_REPLICATION_LEVEL, dht_handle, GNS_ResolverHandle::dht_heap_node, dht_lookup_heap, DHT_LOOKUP_TIMEOUT, dht_lookup_timeout(), GNS_ResolverHandle::dht_query, 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_SCHEDULER_add_delayed(), GNUNET_SCHEDULER_cancel(), GNUNET_TIME_absolute_get(), handle_dht_response(), max_allowed_background_queries, and GNS_ResolverHandle::task_id.

Referenced by dht_lookup_timeout(), 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:

◆ dht_lookup_timeout()

static void dht_lookup_timeout ( void *  cls)
static

The DHT did not answer within DHT_LOOKUP_TIMEOUT.

Restart the GET (which also restarts the DHT service's own retry back-off for it), or fail the resolution once we ran out of attempts.

Parameters
clsthe struct GNS_ResolverHandle

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

2716{
2717 struct GNS_ResolverHandle *rh = cls;
2718 struct GNUNET_HashCode query = rh->dht_query;
2719
2720 rh->task_id = NULL;
2722 rh->get_handle = NULL;
2724 rh->dht_heap_node = NULL;
2726 {
2728 _ ("DHT lookup for `%s' timed out\n"),
2729 rh->name);
2730 fail_resolution (rh);
2731 return;
2732 }
2733 rh->dht_retries++;
2735 "DHT lookup for `%s' under key %s timed out, retrying (%u/%u)\n",
2736 rh->name,
2737 GNUNET_h2s (&query),
2738 rh->dht_retries,
2739 (unsigned int) DHT_LOOKUP_RETRIES);
2741 &query);
2742}

References _, GNS_ResolverHandle::dht_heap_node, DHT_LOOKUP_RETRIES, GNS_ResolverHandle::dht_query, GNS_ResolverHandle::dht_retries, fail_resolution(), GNS_ResolverHandle::get_handle, GNUNET_CONTAINER_heap_remove_node(), GNUNET_DHT_get_stop(), GNUNET_ERROR_TYPE_INFO, GNUNET_ERROR_TYPE_WARNING, GNUNET_h2s(), GNUNET_log, GNS_ResolverHandle::name, start_dht_request(), and GNS_ResolverHandle::task_id.

Referenced by start_dht_request().

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

◆ refresh_stop()

static void refresh_stop ( struct RefreshOps ro)
static

End a background refresh.

Parameters
rorefresh to stop

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

2792{
2794 ro_tail,
2795 ro);
2796 if (NULL != ro->timeout_task)
2799 GNUNET_free (ro);
2800}

References RefreshOps::get_handle, GNUNET_CONTAINER_DLL_remove, GNUNET_DHT_get_stop(), GNUNET_free, GNUNET_SCHEDULER_cancel(), ro_head, ro_tail, and RefreshOps::timeout_task.

Referenced by GNS_resolver_done(), handle_refresh_response(), and refresh_timeout().

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

◆ refresh_timeout()

static void refresh_timeout ( void *  cls)
static

Nothing fresher showed up in time.

Parameters
clsthe struct RefreshOps

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

2810{
2811 struct RefreshOps *ro = cls;
2812
2813 ro->timeout_task = NULL;
2815 "No fresher block for %s found in the DHT\n",
2816 GNUNET_h2s (&ro->query));
2817 refresh_stop (ro);
2818}

References GNUNET_ERROR_TYPE_DEBUG, GNUNET_h2s(), GNUNET_log, RefreshOps::query, refresh_stop(), and RefreshOps::timeout_task.

Referenced by start_refresh().

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

◆ handle_refresh_response()

static void handle_refresh_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

A background refresh returned a block.

If it is fresher than the one we are serving, put it into the namecache and stop.

Parameters
clsthe struct RefreshOps

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

2839{
2840 struct RefreshOps *ro = cls;
2841 const struct GNUNET_GNSRECORD_Block *block = data;
2843 struct CacheOps *co;
2844
2845 (void) exp;
2846 (void) key;
2847 (void) trunc_peer;
2848 (void) get_path;
2849 (void) get_path_length;
2850 (void) put_path;
2851 (void) put_path_length;
2852 (void) type;
2853 if ( (size < sizeof (struct GNUNET_GNSRECORD_Block)) ||
2855 {
2856 /* how did this pass DHT block validation!? */
2857 GNUNET_break (0);
2858 return;
2859 }
2861 if (expiration.abs_value_us <= ro->expiration.abs_value_us)
2862 return; /* not an improvement, keep looking */
2864 "Refreshing cached block for %s, now expires %s\n",
2865 GNUNET_h2s (&ro->query),
2867 co = GNUNET_new (struct CacheOps);
2869 block,
2870 &
2872 co);
2874 co_tail,
2875 co);
2876 refresh_stop (ro);
2877}

References GNUNET_TIME_Absolute::abs_value_us, co_head, co_tail, data, expiration, RefreshOps::expiration, GNUNET_break, GNUNET_CONTAINER_DLL_insert, GNUNET_ERROR_TYPE_DEBUG, GNUNET_GNSRECORD_block_get_expiration(), GNUNET_GNSRECORD_block_get_size(), GNUNET_h2s(), GNUNET_log, GNUNET_NAMECACHE_block_cache(), GNUNET_new, GNUNET_STRINGS_absolute_time_to_string(), key, namecache_cache_continuation(), namecache_handle, CacheOps::namecache_qe_cache, RefreshOps::query, refresh_stop(), size, and type.

Referenced by start_refresh().

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

◆ start_refresh()

static void start_refresh ( const struct GNUNET_HashCode query,
struct GNUNET_TIME_Absolute  expiration 
)
static

Ask the DHT for a fresher version of query while we answer from a namecache entry that is about to expire.

Nobody waits for this.

Parameters
querykey of the block to refresh
expirationexpiration time of the block we have

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

2890{
2891 struct RefreshOps *ro;
2892
2893 for (ro = ro_head; NULL != ro; ro = ro->next)
2894 if (0 == GNUNET_memcmp (&ro->query,
2895 query))
2896 return; /* already refreshing this one */
2897 ro = GNUNET_new (struct RefreshOps);
2898 ro->query = *query;
2899 ro->expiration = expiration;
2902 query,
2905 NULL, 0,
2907 ro);
2908 if (NULL == ro->get_handle)
2909 {
2910 GNUNET_free (ro);
2911 return;
2912 }
2914 "Looking for a fresher block for %s in the DHT\n",
2915 GNUNET_h2s (query));
2918 ro);
2920 ro_tail,
2921 ro);
2922}

References BLOCK_REFRESH_TIMEOUT, DHT_GNS_REPLICATION_LEVEL, dht_handle, expiration, RefreshOps::expiration, RefreshOps::get_handle, GNUNET_BLOCK_TYPE_GNS_NAMERECORD, GNUNET_CONTAINER_DLL_insert, GNUNET_DHT_get_start(), GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE, GNUNET_ERROR_TYPE_DEBUG, GNUNET_free, GNUNET_h2s(), GNUNET_log, GNUNET_memcmp, GNUNET_new, GNUNET_SCHEDULER_add_delayed(), handle_refresh_response(), RefreshOps::next, RefreshOps::query, refresh_timeout(), ro_head, ro_tail, and RefreshOps::timeout_task.

Referenced by handle_namecache_block_response().

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

2937{
2938 struct GNS_ResolverHandle *rh = cls;
2939
2940 if (0 == rd_count)
2942 _ ("GNS namecache returned empty result for `%s'\n"),
2943 rh->name);
2945 rd_count,
2946 rd);
2947}

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

2959{
2960 struct GNS_ResolverHandle *rh = cls;
2961 struct AuthorityChain *ac = rh->ac_tail;
2962 const char *label = ac->label;
2963 const struct GNUNET_CRYPTO_BlindablePublicKey *auth =
2965 struct GNUNET_HashCode query;
2966 bool dht_allowed;
2967
2968 GNUNET_assert (NULL != rh->namecache_qe);
2969 rh->namecache_qe = NULL;
2970 dht_allowed = ((GNUNET_GNS_LO_DEFAULT == rh->options) ||
2972 (ac != rh->ac_head)));
2973 if (NULL == block)
2975 "No block found\n");
2976 else
2978 "Got block with expiration %s\n",
2981 if (dht_allowed &&
2982 ((NULL == block) ||
2985 rel_value_us)))
2986 {
2987 /* namecache knows nothing; try DHT lookup */
2989 label,
2990 &query);
2992 "Starting DHT lookup for `%s' in zone `%s' under key `%s'\n",
2993 ac->label,
2995 GNUNET_h2s (&query));
2996 start_dht_request (rh, &query);
2997 return;
2998 }
2999
3000 if ((NULL == block) ||
3003 rel_value_us))
3004 {
3005 /* DHT not permitted and no local result, fail */
3007 "Resolution failed for `%s' in zone %s (DHT lookup not permitted by configuration)\n",
3008 ac->label,
3010 fail_resolution (rh);
3011 return;
3012 }
3014 "Received result from namecache for label `%s'\n",
3015 ac->label);
3016 /* The block is still valid, but a record set that is about to expire
3017 has almost certainly been republished by now; get that version
3018 into the cache before this one dies, instead of paying a cold DHT
3019 lookup then. */
3020 if (dht_allowed &&
3022 GNUNET_GNSRECORD_block_get_expiration (block)).rel_value_us <
3024 {
3026 label,
3027 &query);
3028 start_refresh (&query,
3030 }
3031
3032 if (GNUNET_OK !=
3034 auth,
3035 label,
3037 rh))
3038 {
3039 GNUNET_break_op (0); /* block was ill-formed */
3040 /* try DHT instead */
3042 label,
3043 &query);
3045 "Starting DHT lookup for `%s' in zone `%s' under key `%s'\n",
3046 ac->label,
3048 GNUNET_h2s (&query));
3049 start_dht_request (rh, &query);
3050 return;
3051 }
3052}

References GNS_ResolverHandle::ac_head, GNS_ResolverHandle::ac_tail, AuthorityChain::authority_info, BLOCK_REFRESH_THRESHOLD, 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, GNUNET_TIME_Relative::rel_value_us, AuthorityChain::rh, start_dht_request(), and start_refresh().

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

3062{
3063 struct AuthorityChain *ac = rh->ac_tail;
3064 struct GNUNET_HashCode query;
3065
3067 "Starting GNS resolution for `%s' in zone %s\n",
3068 ac->label,
3071 ac->label,
3072 &query);
3074 {
3075 rh->namecache_qe
3077 &query,
3079 rh);
3080 GNUNET_assert (NULL != rh->namecache_qe);
3081 }
3082 else
3083 {
3085 &query);
3086 }
3087}

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

3099{
3100 struct GNS_ResolverHandle *rh = cls;
3101 struct AuthorityChain *ac = rh->ac_tail;
3102
3103 rh->rev_check = NULL;
3104 if (GNUNET_YES != is_valid)
3105 {
3107 _ ("Zone %s was revoked, resolution fails\n"),
3110 return;
3111 }
3113}

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

3123{
3124 struct AuthorityChain *ac = rh->ac_tail;
3125
3127 "Starting revocation check for zone %s\n",
3132 rh);
3133 GNUNET_assert (NULL != rh->rev_check);
3134}

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

3247{
3248 struct GNS_ResolverHandle *rh;
3249
3251 "Starting lookup for `%s'\n",
3252 name);
3253 rh = GNUNET_new (struct GNS_ResolverHandle);
3255 rlh_tail,
3256 rh);
3257 rh->authority_zone = *zone;
3258 rh->proc = proc;
3259 rh->proc_cls = proc_cls;
3260 rh->options = options;
3262 rh->name = GNUNET_strdup (name);
3263 rh->name_resolution_pos = strlen (name);
3264 rh->loop_threshold = recursion_depth_limit;
3266 rh);
3267 return rh;
3268}

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

3278{
3279 struct DnsResult *dr;
3280 struct AuthorityChain *ac;
3281
3283 rlh_tail,
3284 rh);
3285 if (NULL != rh->dns_request)
3286 {
3288 rh->dns_request = NULL;
3289 }
3290 while (NULL != (ac = rh->ac_head))
3291 {
3293 rh->ac_tail,
3294 ac);
3295 if (GNUNET_NO == ac->gns_authority)
3296 {
3297 struct Gns2DnsPending *gp;
3298
3299 while (NULL != (gp = ac->authority_info.dns_authority.gp_head))
3300 {
3303 gp);
3304 if (NULL != gp->rh)
3305 {
3306 /* rh->g2dc->rh is NOT in the DLL yet, so to enable us
3307 using GNS_resolver_lookup_cancel here, we need to
3308 add it first... */
3310 rlh_tail,
3311 gp->rh);
3312 GNUNET_assert (NULL == gp->rh->task_id);
3315 gp->rh);
3316 gp->rh = NULL;
3317 }
3318 if (NULL != gp->dns_rh)
3319 {
3321 gp->dns_rh = NULL;
3322 }
3323 GNUNET_free (gp);
3324 }
3326 }
3327 GNUNET_free (ac->label);
3328 GNUNET_free (ac);
3329 }
3330 if (NULL != rh->task_id)
3331 {
3333 rh->task_id = NULL;
3334 }
3335 if (NULL != rh->get_handle)
3336 {
3338 rh->get_handle = NULL;
3339 }
3340 if (NULL != rh->dht_heap_node)
3341 {
3343 rh->dht_heap_node = NULL;
3344 }
3345 if (NULL != rh->namecache_qe)
3346 {
3348 rh->namecache_qe = NULL;
3349 }
3350 if (NULL != rh->rev_check)
3351 {
3353 rh->rev_check = NULL;
3354 }
3355 if (NULL != rh->std_resolve)
3356 {
3358 "Canceling standard DNS resolution\n");
3360 rh->std_resolve = NULL;
3361 }
3362 while (NULL != (dr = rh->dns_result_head))
3363 {
3366 dr);
3367 GNUNET_free (dr);
3368 }
3369 if (NULL != rh->prefix)
3370 {
3372 rh->prefix = NULL;
3373 }
3374 GNUNET_free (rh->leho);
3375 GNUNET_free (rh->name);
3376 GNUNET_free (rh);
3377}

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

3396{
3397 cfg = c;
3399 dht_handle = dht;
3402 max_allowed_background_queries = max_bg_queries;
3404 "namecache",
3405 "DISABLE");
3408 "Namecache disabled\n");
3409}

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

3417{
3418 struct GNS_ResolverHandle *rh;
3419 struct CacheOps *co;
3420
3421 /* abort active resolutions */
3422 while (NULL != (rh = rlh_head))
3423 {
3424 rh->proc (rh->proc_cls,
3425 0,
3426 NULL);
3428 }
3429 while (NULL != ro_head)
3431 while (NULL != (co = co_head))
3432 {
3434 co_tail,
3435 co);
3437 GNUNET_free (co);
3438 }
3440 dht_lookup_heap = NULL;
3441 dht_handle = NULL;
3442 namecache_handle = NULL;
3443}

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, refresh_stop(), rlh_head, and ro_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

◆ dht_handle

struct GNUNET_DHT_Handle* dht_handle
static

Resolver handle to the dht.

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

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

◆ dht_lookup_heap

struct GNUNET_CONTAINER_Heap* dht_lookup_heap
static

Heap for limiting parallel DHT lookups.

Definition at line 506 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 511 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 516 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 521 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

◆ co_tail

struct CacheOps* co_tail
static

◆ ro_head

struct RefreshOps* ro_head
static

Organized in a DLL.

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

Referenced by GNS_resolver_done(), refresh_stop(), and start_refresh().

◆ ro_tail

struct RefreshOps* ro_tail
static

Organized in a DLL.

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

Referenced by refresh_stop(), and start_refresh().

◆ disable_cache

int disable_cache
static

◆ cfg

const struct GNUNET_CONFIGURATION_Handle* cfg
static

Global configuration.

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

Referenced by GNS_resolver_init(), and recursive_gns_resolution_revocation().