GNUnet 0.25.0
 
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...
 

Macros

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

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 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_PublicKey *zone, uint32_t record_type, const char *name, enum GNUNET_GNS_LocalOptions options, uint16_t recursion_depth_limit, GNS_ResultProcessor proc, void *proc_cls)
 Lookup of a record in a specific zone calls lookup result processor on result.
 
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 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.

84{
88 struct Gns2DnsPending *next;
89
93 struct Gns2DnsPending *prev;
94
98 struct AuthorityChain *ac;
99
105 struct GNS_ResolverHandle *rh;
106
110 struct GNUNET_RESOLVER_RequestHandle *dns_rh;
111
115 unsigned int num_results;
116};
117
118
123struct GNS_ResolverHandle;
124
125
130struct AuthorityChain
131{
135 struct AuthorityChain *prev;
136
140 struct AuthorityChain *next;
141
145 struct GNS_ResolverHandle *rh;
146
150 char *label;
151
156 int gns_authority;
157
161 union
162 {
167
168 struct
169 {
176
181 struct Gns2DnsPending *gp_head;
182
187 struct Gns2DnsPending *gp_tail;
188
193
198 int found;
199
203 int launched;
206};
207
208
212struct DnsResult
213{
217 struct DnsResult *next;
218
222 struct DnsResult *prev;
223
227 const void *data;
228
233 uint64_t expiration_time;
234
238 size_t data_size;
239
243 uint32_t record_type;
244};
245
246
252{
256 struct GNS_ResolverHandle *next;
257
261 struct GNS_ResolverHandle *prev;
262
267
272
276 void *proc_cls;
277
282
283
288
293
298
303
309
313 struct AuthorityChain *ac_head;
314
318 struct AuthorityChain *ac_tail;
319
324
328 char *name;
329
334 char *leho;
335
340
345
349 size_t name_resolution_pos;
350
355
360 int protocol;
361
366 int service;
367
371 char *prefix;
372
373
377 int record_type;
378
384 unsigned int loop_limiter;
385
389 unsigned int loop_threshold;
390
394 uint16_t original_dns_id;
395};
396
397
401struct CacheOps
402{
406 struct CacheOps *next;
407
411 struct CacheOps *prev;
412
417};
418
419
424
428static struct GNUNET_DHT_Handle *dht_handle;
429
434
438static unsigned long long max_allowed_background_queries;
439
443static struct GNS_ResolverHandle *rlh_head;
444
448static struct GNS_ResolverHandle *rlh_tail;
449
453static struct CacheOps *co_head;
454
458static struct CacheOps *co_tail;
459
463static int disable_cache;
464
468static const struct GNUNET_CONFIGURATION_Handle *cfg;
469
470
471/* ************************** Resolution **************************** */
472
480static char *
482 char *name)
483{
484 char *ret;
485 size_t s_len = strlen (name);
486
487 if (0 != strcmp (&name[s_len - 2],
488 ".+"))
489 return name; /* did not end in ".+" */
492 "%.*s.%s",
493 (int) (s_len - 2),
494 name,
498 return ret;
499}
500
501
508static void
510{
511 struct GNS_ResolverHandle *rh = cls;
512
513 rh->task_id = NULL;
515}
516
517
523static void
525{
526 rh->proc (rh->proc_cls,
527 0,
528 NULL);
529 GNUNET_assert (NULL == rh->task_id);
531 rh);
532}
533
534
540static void
541timeout_resolution (void *cls)
542{
543 struct GNS_ResolverHandle *rh = cls;
544
545 rh->task_id = NULL;
546 fail_resolution (rh);
547}
548
549
555static int
556resolver_getprotobyname (const char *name)
557{
558 struct protoent *pe = getprotobyname (name);
559 if (pe == NULL)
560 {
562 }
563 return pe->p_proto;
564}
565
566
573static int
574resolver_getservbyname (const char *name, const char *proto)
575{
576 struct servent *se = getservbyname (name, proto);
577 if (se == NULL)
578 {
580 }
581 return se->s_port;
582}
583
584
603static char *
605{
606 const char *rp;
607 const char *dot;
608 size_t len;
609 char *ret;
610 char *srv_name;
611 char *proto_name;
612 int protocol;
613 int service;
614
615 if (0 == rh->name_resolution_pos)
616 return NULL;
617 dot = memrchr (rh->name,
618 (int) '.',
620 if (NULL == dot)
621 {
622 /* done, this was the last one */
623 len = rh->name_resolution_pos;
624 rp = rh->name;
625 rh->name_resolution_pos = 0;
626 }
627 else if ('_' == dot[1])
628 {
637 len = strlen (GNUNET_GNS_EMPTY_LABEL_AT);
638 }
639 else
640 {
641 /* advance by one label */
642 len = rh->name_resolution_pos - (dot - rh->name) - 1;
643 rp = dot + 1;
644 rh->name_resolution_pos = dot - rh->name;
645 }
646 rh->protocol = 0;
647 rh->service = 0;
648 rh->prefix = NULL;
649 ret = GNUNET_strndup (rp, len);
654 if (('_' == rh->name[0]) &&
655 (NULL != (dot = memrchr (rh->name,
656 (int) '.',
657 rh->name_resolution_pos))) &&
658 ('_' == dot[1]) &&
659 (NULL == memrchr (rh->name,
660 (int) '.',
661 dot - rh->name)))
662 {
663 srv_name = GNUNET_strndup (&rh->name[1],
664 (dot - rh->name) - 1);
665 proto_name = GNUNET_strndup (&dot[2],
666 rh->name_resolution_pos - (dot - rh->name)
667 - 2);
668 protocol = resolver_getprotobyname (proto_name);
669 if (0 == protocol)
670 {
672 _ (
673 "Protocol `%s' unknown, skipping labels as BOX retain as SBOX.\n"),
674 proto_name);
675 GNUNET_free (proto_name);
676 GNUNET_free (srv_name);
678 rh->name_resolution_pos = 0;
679 return ret;
680 }
682 proto_name);
683 if (0 == service)
684 {
686 _ (
687 "Service `%s' unknown for protocol `%s', trying as number.\n"),
688 srv_name,
689 proto_name);
690 if (1 != sscanf (srv_name, "%u", &rh->service))
691 {
693 _ (
694 "Service `%s' not a port, skipping service labels as BOX retain as SBOX.\n"),
695 srv_name);
696 GNUNET_free (proto_name);
697 GNUNET_free (srv_name);
699 rh->name_resolution_pos = 0;
700 return ret;
701 }
702 }
703 else
704 {
705 rh->service = ntohs (service);
706 }
707 rh->protocol = protocol;
708 GNUNET_free (proto_name);
709 GNUNET_free (srv_name);
710 }
717 if ((NULL != (dot = memrchr (rh->name,
718 (int) '.',
719 rh->name_resolution_pos)) && '_' == dot[1]) ||
720 ((NULL == memrchr (rh->name,
721 (int) '.',
722 rh->name_resolution_pos)) && '_' == rh->name[0]))
723 {
725 rh->name_resolution_pos = 0;
726 }
727 return ret;
728}
729
730
736static void
738{
739 struct DnsResult *pos;
740 unsigned int n;
741 unsigned int i;
742
743 n = 0;
744 for (pos = rh->dns_result_head; NULL != pos; pos = pos->next)
745 n++;
746 {
747 struct GNUNET_GNSRECORD_Data rd[n];
748
749 i = 0;
750 for (pos = rh->dns_result_head; NULL != pos; pos = pos->next)
751 {
752 rd[i].data = pos->data;
753 rd[i].data_size = pos->data_size;
754 rd[i].record_type = pos->record_type;
762 if (0 == pos->expiration_time)
763 {
765 rd[i].expiration_time = 0;
766 }
767 else
768 {
770 }
771 i++;
772 }
773 GNUNET_assert (i == n);
775 "Transmitting standard DNS result with %u records\n",
776 n);
777 rh->proc (rh->proc_cls,
778 n,
779 rd);
780 }
782}
783
784
794static void
796 uint64_t expiration_time,
797 uint32_t record_type,
798 size_t data_size,
799 const void *data)
800{
801 struct DnsResult *res;
802
803 res = GNUNET_malloc (sizeof(struct DnsResult) + data_size);
804 res->expiration_time = expiration_time;
805 res->data_size = data_size;
806 res->record_type = record_type;
807 res->data = &res[1];
808 GNUNET_memcpy (&res[1],
809 data,
810 data_size);
812 rh->dns_result_tail,
813 res);
814}
815
816
825static void
826handle_dns_result (void *cls,
827 const struct sockaddr *addr,
828 socklen_t addrlen)
829{
830 struct GNS_ResolverHandle *rh = cls;
831 const struct sockaddr_in *sa4;
832 const struct sockaddr_in6 *sa6;
833
834 if (NULL == addr)
835 {
836 rh->std_resolve = NULL;
838 return;
839 }
841 "Received %u bytes of DNS IP data\n",
842 addrlen);
843 switch (addr->sa_family)
844 {
845 case AF_INET:
846 sa4 = (const struct sockaddr_in *) addr;
847 add_dns_result (rh,
848 0 /* expiration time is unknown */,
850 sizeof(struct in_addr),
851 &sa4->sin_addr);
852 break;
853
854 case AF_INET6:
855 sa6 = (const struct sockaddr_in6 *) addr;
856 add_dns_result (rh,
857 0 /* expiration time is unknown */,
859 sizeof(struct in6_addr),
860 &sa6->sin6_addr);
861 break;
862
863 default:
864 GNUNET_break (0);
865 break;
866 }
867}
868
869
875static void
876recursive_resolution (void *cls);
877
878
885static void
886start_resolver_lookup (void *cls);
887
888
897static void
898dns_result_parser (void *cls,
899 const struct GNUNET_TUN_DnsHeader *dns,
900 size_t dns_len)
901{
902 struct GNS_ResolverHandle *rh = cls;
904 const struct GNUNET_DNSPARSER_Record *rec;
905 unsigned int rd_count;
906
907 if (NULL == dns)
908 {
909 rh->dns_request = NULL;
911 rh->task_id = NULL;
912 fail_resolution (rh);
913 return;
914 }
915 if (rh->original_dns_id != dns->id)
916 {
917 /* DNS answer, but for another query */
918 return;
919 }
920 p = GNUNET_DNSPARSER_parse ((const char *) dns,
921 dns_len);
922 if (NULL == p)
923 {
925 _ ("Failed to parse DNS response\n"));
926 return;
927 }
928
929 /* We got a result from DNS */
931 "Received DNS response for `%s' with %u answers\n",
932 rh->ac_tail->label,
933 (unsigned int) p->num_answers);
934 if ((p->num_answers > 0) &&
935 (GNUNET_DNSPARSER_TYPE_CNAME == p->answers[0].type) &&
937 {
938 int af;
939
941 "Got CNAME `%s' from DNS for `%s'\n",
942 p->answers[0].data.hostname,
943 rh->name);
944 if (NULL != rh->std_resolve)
945 {
947 "Multiple CNAME results from DNS resolving `%s'! Not really allowed...\n",
948 rh->name);
950 }
951 GNUNET_free (rh->name);
952 rh->name = GNUNET_strdup (p->answers[0].data.hostname);
953 rh->name_resolution_pos = strlen (rh->name);
954 switch (rh->record_type)
955 {
957 af = AF_INET;
958 break;
959
961 af = AF_INET6;
962 break;
963
964 default:
965 af = AF_UNSPEC;
966 break;
967 }
968 if (NULL != rh->leho)
969 add_dns_result (rh,
970 GNUNET_TIME_UNIT_HOURS.rel_value_us,
972 strlen (rh->leho),
973 rh->leho);
975 af,
978 rh);
981 rh->dns_request = NULL;
982 return;
983 }
984
985 /* convert from (parsed) DNS to (binary) GNS format! */
986 rd_count = p->num_answers + p->num_authority_records
987 + p->num_additional_records;
988 {
989 struct GNUNET_GNSRECORD_Data rd[rd_count + 1]; /* +1 for LEHO */
990 int skip;
991 char buf[UINT16_MAX];
992 char *name_ace;
993 size_t buf_off;
994 size_t buf_start;
995
996 buf_off = 0;
997 skip = 0;
998 memset (rd,
999 0,
1000 sizeof(rd));
1001 for (unsigned int i = 0; i < rd_count; i++)
1002 {
1003 if (i < p->num_answers)
1004 rec = &p->answers[i];
1005 else if (i < p->num_answers + p->num_authority_records)
1006 rec = &p->authority_records[i - p->num_answers];
1007 else
1008 rec = &p->additional_records[i - p->num_answers
1009 - p->num_authority_records];
1010 /* As we copied the full DNS name to 'rh->ac_tail->label', this
1011 should be the correct check to see if this record is actually
1012 a record for our label...
1013 However, DNSPARSER will convert the ACE name to UTF-8 so
1014 we must convert back.
1015 */
1016 if (IDNA_SUCCESS != idna_to_ascii_8z (rec->name,
1017 &name_ace,
1018 IDNA_ALLOW_UNASSIGNED))
1019 {
1021 _ ("Name `%s' cannot be converted to IDNA."),
1022 rec->name);
1023 continue;
1024 }
1025
1026 if (0 != strcmp (name_ace,
1027 rh->ac_tail->label))
1028 {
1030 "Dropping record `%s', does not match desired name `%s'\n",
1031 rec->name,
1032 rh->ac_tail->label);
1033 skip++;
1034 continue;
1035 }
1036 rd[i - skip].record_type = rec->type;
1038 switch (rec->type)
1039 {
1041 if (rec->data.raw.data_len != sizeof(struct in_addr))
1042 {
1043 GNUNET_break_op (0);
1044 skip++;
1045 continue;
1046 }
1047 rd[i - skip].data_size = rec->data.raw.data_len;
1048 rd[i - skip].data = rec->data.raw.data;
1049 break;
1050
1052 if (rec->data.raw.data_len != sizeof(struct in6_addr))
1053 {
1054 GNUNET_break_op (0);
1055 skip++;
1056 continue;
1057 }
1058 rd[i - skip].data_size = rec->data.raw.data_len;
1059 rd[i - skip].data = rec->data.raw.data;
1060 break;
1061
1065 buf_start = buf_off;
1066 if (GNUNET_OK !=
1068 sizeof(buf),
1069 &buf_off,
1070 rec->data.hostname))
1071 {
1072 GNUNET_break (0);
1073 skip++;
1074 continue;
1075 }
1076 rd[i - skip].data_size = buf_off - buf_start;
1077 rd[i - skip].data = &buf[buf_start];
1078 break;
1079
1081 buf_start = buf_off;
1082 if (GNUNET_OK !=
1084 sizeof(buf),
1085 &buf_off,
1086 rec->data.soa))
1087 {
1088 GNUNET_break (0);
1089 skip++;
1090 continue;
1091 }
1092 rd[i - skip].data_size = buf_off - buf_start;
1093 rd[i - skip].data = &buf[buf_start];
1094 break;
1095
1097 buf_start = buf_off;
1098 if (GNUNET_OK !=
1100 sizeof(buf),
1101 &buf_off,
1102 rec->data.mx))
1103 {
1104 GNUNET_break (0);
1105 skip++;
1106 continue;
1107 }
1108 rd[i - skip].data_size = buf_off - buf_start;
1109 rd[i - skip].data = &buf[buf_start];
1110 break;
1111
1113 buf_start = buf_off;
1114 if (GNUNET_OK !=
1116 sizeof(buf),
1117 &buf_off,
1118 rec->data.srv))
1119 {
1120 GNUNET_break (0);
1121 skip++;
1122 continue;
1123 }
1124 rd[i - skip].data_size = buf_off - buf_start;
1125 rd[i - skip].data = &buf[buf_start];
1126 break;
1127
1129 buf_start = buf_off;
1130 if (GNUNET_OK !=
1132 sizeof(buf),
1133 &buf_off,
1134 rec->data.uri))
1135 {
1136 GNUNET_break (0);
1137 skip++;
1138 continue;
1139 }
1140 rd[i - skip].data_size = buf_off - buf_start;
1141 rd[i - skip].data = &buf[buf_start];
1142 break;
1143
1144 default:
1146 _ ("Skipping record of unsupported type %d\n"),
1147 rec->type);
1148 skip++;
1149 continue;
1150 }
1151 } /* end of for all records in answer */
1152 if (NULL != rh->leho)
1153 {
1157 rd[rd_count - skip].expiration_time = GNUNET_TIME_UNIT_HOURS.rel_value_us;
1158 rd[rd_count - skip].data = rh->leho;
1159 rd[rd_count - skip].data_size = strlen (rh->leho);
1160 skip--; /* skip one LESS */
1162 "Adding LEHO %s\n",
1163 rh->leho);
1164 }
1166 "Returning DNS response for `%s' with %u answers\n",
1167 rh->ac_tail->label,
1168 (unsigned int) (rd_count - skip));
1169 rh->proc (rh->proc_cls,
1170 rd_count - skip,
1171 rd);
1173 rh->dns_request = NULL;
1174 }
1175
1176
1178 if (NULL != rh->task_id)
1179 GNUNET_SCHEDULER_cancel (rh->task_id); /* should be timeout task */
1181 rh);
1182}
1183
1184
1193static void
1195{
1196 struct AuthorityChain *ac;
1197 struct GNUNET_DNSPARSER_Query *query;
1198 struct GNUNET_DNSPARSER_Packet *p;
1199 char *dns_request;
1200 size_t dns_request_length;
1201 int ret;
1202
1203 ac = rh->ac_tail;
1204 GNUNET_assert (NULL != ac);
1206 "Starting DNS lookup for `%s'\n",
1207 ac->label);
1209 query = GNUNET_new (struct GNUNET_DNSPARSER_Query);
1210 query->name = GNUNET_strdup (ac->label);
1211 query->type = rh->record_type;
1214 p->queries = query;
1215 p->num_queries = 1;
1217 UINT16_MAX);
1218 p->flags.opcode = GNUNET_TUN_DNS_OPCODE_QUERY;
1219 p->flags.recursion_desired = 1;
1221 1024,
1222 &dns_request,
1223 &dns_request_length);
1224 if (GNUNET_OK != ret)
1225 {
1226 GNUNET_break (0);
1227 rh->proc (rh->proc_cls,
1228 0,
1229 NULL);
1230 GNUNET_assert (NULL == rh->task_id);
1232 rh);
1233 }
1234 else
1235 {
1236 rh->original_dns_id = p->id;
1238 GNUNET_assert (NULL == rh->dns_request);
1239 if (IDNA_SUCCESS != idna_to_unicode_8z8z (ac->label,
1240 &rh->leho,
1241 IDNA_ALLOW_UNASSIGNED))
1242 {
1243 GNUNET_break (0);
1244 rh->proc (rh->proc_cls,
1245 0,
1246 NULL);
1247 GNUNET_assert (NULL == rh->task_id);
1249 rh);
1250 }
1253 dns_request,
1254 dns_request_length,
1256 rh);
1259 rh);
1260 }
1261 if (GNUNET_SYSERR != ret)
1262 GNUNET_free (dns_request);
1264}
1265
1266
1275static void
1277 const char *rname)
1278{
1279 size_t nlen;
1280 char *res;
1281 const char *tld;
1282 struct AuthorityChain *ac;
1283 int af;
1284 struct GNUNET_CRYPTO_PublicKey zone;
1285
1287 "Handling GNS REDIRECT result `%s'\n",
1288 rname);
1289 nlen = strlen (rname);
1290 tld = GNS_get_tld (rname);
1291 if (0 == strcmp ("+", tld))
1292 {
1293 /* REDIRECT resolution continues relative to current domain */
1294 if (0 == rh->name_resolution_pos)
1295 {
1296 res = GNUNET_strndup (rname, nlen - 2);
1297 rh->name_resolution_pos = nlen - 2;
1298 }
1299 else
1300 {
1302 "%.*s.%.*s",
1303 (int) rh->name_resolution_pos,
1304 rh->name,
1305 (int) (nlen - 2),
1306 rname);
1307 rh->name_resolution_pos = strlen (res);
1308 }
1309 GNUNET_free (rh->name);
1310 rh->name = res;
1311 ac = GNUNET_new (struct AuthorityChain);
1312 ac->rh = rh;
1317 /* add AC to tail */
1319 rh->ac_tail,
1320 ac);
1322 rh);
1323 return;
1324 }
1325 if (GNUNET_OK == GNUNET_GNSRECORD_zkey_to_pkey (tld, &zone))
1326 {
1327 /* REDIRECT resolution continues relative to current domain */
1328 if (0 == rh->name_resolution_pos)
1329 {
1331 "%.*s",
1332 (int) (strlen (rname) - (strlen (tld) + 1)),
1333 rname);
1334 }
1335 else
1336 {
1338 "%.*s.%.*s",
1339 (int) rh->name_resolution_pos,
1340 rh->name,
1341 (int) (strlen (rname) - (strlen (tld) + 1)),
1342 rname);
1343 }
1344 rh->name_resolution_pos = strlen (res);
1345 GNUNET_free (rh->name);
1346 rh->name = res;
1347 ac = GNUNET_new (struct AuthorityChain);
1348 ac->rh = rh;
1350 ac->authority_info.gns_authority = zone;
1352 /* add AC to tail */
1354 rh->ac_tail,
1355 ac);
1357 rh);
1358 return;
1359 }
1360
1362 "Got REDIRECT `%s' from GNS for `%s'\n",
1363 rname,
1364 rh->name);
1365 if (NULL != rh->std_resolve)
1366 {
1368 "Multiple REDIRECT results from GNS resolving `%s'! Not really allowed...\n",
1369 rh->name);
1371 }
1372 /* name is absolute, go to DNS */
1373 GNUNET_free (rh->name);
1374 rh->name = GNUNET_strdup (rname);
1375 rh->name_resolution_pos = strlen (rh->name);
1376 switch (rh->record_type)
1377 {
1379 af = AF_INET;
1380 break;
1381
1383 af = AF_INET6;
1384 break;
1385
1386 default:
1387 af = AF_UNSPEC;
1388 break;
1389 }
1391 "Doing standard DNS lookup for `%s'\n",
1392 rh->name);
1393
1395 af,
1398 rh);
1399}
1400
1401
1410static void
1412 const char *cname)
1413{
1414 int af;
1415
1416 GNUNET_free (rh->name);
1417 rh->name = GNUNET_strdup (cname);
1418 rh->name_resolution_pos = strlen (rh->name);
1419 switch (rh->record_type)
1420 {
1422 af = AF_INET;
1423 break;
1424
1426 af = AF_INET6;
1427 break;
1428
1429 default:
1430 af = AF_UNSPEC;
1431 break;
1432 }
1434 "Doing standard DNS lookup for `%s'\n",
1435 rh->name);
1436
1438 af,
1441 rh);
1442}
1443
1444
1452static void
1454 unsigned int rd_count,
1455 const struct GNUNET_GNSRECORD_Data *rd);
1456
1457
1465static void
1467{
1468 struct GNS_ResolverHandle *rh = ac->rh;
1469
1470 if ((NULL != ac->authority_info.dns_authority.gp_head) &&
1472 return; /* more pending and none found yet */
1474 {
1476 "Failed to resolve DNS server for `%s' in GNS2DNS resolution\n",
1478 fail_resolution (rh);
1479 return;
1480 }
1482 return; /* already running, do not launch again! */
1483 /* recurse */
1486 "Will continue resolution using DNS to resolve `%s'\n",
1487 ac->label);
1488 GNUNET_assert (NULL == rh->task_id);
1490 rh);
1491}
1492
1493
1502static void
1503handle_gns2dns_result (void *cls,
1504 unsigned int rd_count,
1505 const struct GNUNET_GNSRECORD_Data *rd)
1506{
1507 struct Gns2DnsPending *gp = cls;
1508 struct AuthorityChain *ac = gp->ac;
1509
1512 gp);
1513 /* enable cleanup of 'rh' handle that automatically comes after we return,
1514 and which expects 'rh' to be in the #rlh_head DLL. */
1515 if (NULL != gp->rh)
1516 {
1518 rlh_tail,
1519 gp->rh);
1520 gp->rh = NULL;
1521 }
1522 GNUNET_free (gp);
1524 "Received %u results for IP address of DNS server for GNS2DNS transition\n",
1525 rd_count);
1526 /* find suitable A/AAAA record */
1527 for (unsigned int j = 0; j < rd_count; j++)
1528 {
1529 switch (rd[j].record_type)
1530 {
1532 {
1533 struct sockaddr_in v4;
1534
1535 if (sizeof(struct in_addr) != rd[j].data_size)
1536 {
1537 GNUNET_break_op (0);
1538 continue;
1539 }
1540 memset (&v4,
1541 0,
1542 sizeof(v4));
1543 v4.sin_family = AF_INET;
1544 v4.sin_port = htons (53);
1545#if HAVE_SOCKADDR_IN_SIN_LEN
1546 v4.sin_len = (u_char) sizeof(v4);
1547#endif
1548 GNUNET_memcpy (&v4.sin_addr,
1549 rd[j].data,
1550 sizeof(struct in_addr));
1551 if (GNUNET_OK ==
1554 (const struct sockaddr *) &v4))
1556 break;
1557 }
1558
1560 {
1561 struct sockaddr_in6 v6;
1562
1563 if (sizeof(struct in6_addr) != rd[j].data_size)
1564 {
1565 GNUNET_break_op (0);
1566 continue;
1567 }
1568 /* FIXME: might want to check if we support IPv6 here,
1569 and otherwise skip this one and hope we find another */
1570 memset (&v6,
1571 0,
1572 sizeof(v6));
1573 v6.sin6_family = AF_INET6;
1574 v6.sin6_port = htons (53);
1575#if HAVE_SOCKADDR_IN_SIN_LEN
1576 v6.sin6_len = (u_char) sizeof(v6);
1577#endif
1578 GNUNET_memcpy (&v6.sin6_addr,
1579 rd[j].data,
1580 sizeof(struct in6_addr));
1581 if (GNUNET_OK ==
1584 (const struct sockaddr *) &v6))
1586 break;
1587 }
1588
1589 default:
1590 break;
1591 }
1592 }
1594}
1595
1596
1604static void
1605handle_gns2dns_ip (void *cls,
1606 const struct sockaddr *addr,
1607 socklen_t addrlen)
1608{
1609 struct Gns2DnsPending *gp = cls;
1610 struct AuthorityChain *ac = gp->ac;
1611 struct sockaddr_storage ss;
1612 struct sockaddr_in *v4;
1613 struct sockaddr_in6 *v6;
1614
1615 if (NULL == addr)
1616 {
1617 /* DNS resolution finished */
1618 if (0 == gp->num_results)
1620 "Failed to use DNS to resolve name of DNS resolver\n");
1623 gp);
1624 GNUNET_free (gp);
1626 return;
1627 }
1628 GNUNET_memcpy (&ss,
1629 addr,
1630 addrlen);
1631 switch (ss.ss_family)
1632 {
1633 case AF_INET:
1634 v4 = (struct sockaddr_in *) &ss;
1635 v4->sin_port = htons (53);
1636 gp->num_results++;
1637 break;
1638
1639 case AF_INET6:
1640 v6 = (struct sockaddr_in6 *) &ss;
1641 v6->sin6_port = htons (53);
1642 gp->num_results++;
1643 break;
1644
1645 default:
1647 "Unsupported AF %d\n",
1648 ss.ss_family);
1649 return;
1650 }
1651 if (GNUNET_OK ==
1653 (struct sockaddr *) &ss))
1655}
1656
1657
1664static void
1666 const struct GNUNET_GNSRECORD_Data *rd)
1667{
1669 rd->data);
1670}
1671
1672
1679static void
1681 const struct GNUNET_GNSRECORD_Data *rd)
1682{
1683 char *cname;
1684 size_t off;
1685
1686 off = 0;
1688 rd->data_size,
1689 &off);
1690 if ((NULL == cname) ||
1691 (off != rd->data_size))
1692 {
1693 GNUNET_break_op (0); /* record not well-formed */
1694 GNUNET_free (cname);
1695 fail_resolution (rh);
1696 return;
1697 }
1699 cname);
1700 GNUNET_free (cname);
1701}
1702
1703
1710static void
1712 const struct GNUNET_GNSRECORD_Data *rd)
1713{
1714 struct AuthorityChain *ac;
1715 struct GNUNET_CRYPTO_PublicKey auth;
1716
1717 /* delegation to another zone */
1719 rd->data_size,
1720 rd->record_type,
1721 &auth))
1722 {
1723 GNUNET_break_op (0);
1724 fail_resolution (rh);
1725 return;
1726 }
1727 /* expand authority chain */
1728 ac = GNUNET_new (struct AuthorityChain);
1729 ac->rh = rh;
1731 ac->authority_info.gns_authority = auth;
1733 /* add AC to tail */
1735 rh->ac_tail,
1736 ac);
1737 /* recurse */
1739 rh);
1740}
1741
1742
1753static int
1755 unsigned int rd_count,
1756 const struct GNUNET_GNSRECORD_Data *rd)
1757{
1758 struct AuthorityChain *ac;
1759 const char *tld;
1760 char *ns;
1761
1762 ns = NULL;
1763 /* expand authority chain */
1764 ac = GNUNET_new (struct AuthorityChain);
1765 ac->rh = rh;
1767
1768 for (unsigned int i = 0; i < rd_count; i++)
1769 {
1770 char *ip;
1771 char *n;
1772 struct Gns2DnsPending *gp;
1773 struct GNUNET_CRYPTO_PublicKey zone;
1774 struct sockaddr_in v4;
1775 struct sockaddr_in6 v6;
1776
1777 if (GNUNET_GNSRECORD_TYPE_GNS2DNS != rd[i].record_type)
1778 {
1783 GNUNET_free (ns);
1784 GNUNET_free (ac);
1785 return GNUNET_SYSERR;
1786 }
1787 n = GNUNET_strdup ((const char*) rd[i].data);
1788 if (strlen (n) + 1 >= rd[i].data_size)
1789 {
1790 GNUNET_break_op (0);
1791 continue;
1792 }
1793 ip = GNUNET_strdup (rd[i].data + strlen (n) + 1);
1794 /* resolve 'ip' to determine the IP(s) of the DNS
1795 resolver to use for lookup of 'ns' */
1796 if (NULL != ns)
1797 {
1798 if (0 != strcasecmp (ns,
1799 n))
1800 {
1801 /* NS values must all be the same for all GNS2DNS records,
1802 anything else leads to insanity */
1803 GNUNET_break_op (0);
1804 GNUNET_free (n);
1805 GNUNET_free (ip);
1806 continue;
1807 }
1808 GNUNET_free (n);
1809 }
1810 else
1811 {
1812 ns = n;
1813 }
1814
1815 /* check if 'ip' is already an IPv4/IPv6 address */
1816 if ((1 == inet_pton (AF_INET,
1817 ip,
1818 &v4)) ||
1819 (1 == inet_pton (AF_INET6,
1820 ip,
1821 &v6)))
1822 {
1826 ip));
1828 GNUNET_free (ip);
1829 continue;
1830 }
1831 tld = GNS_get_tld (ip);
1832 if ((0 != strcmp (tld, "+")) &&
1833 (GNUNET_OK != GNUNET_GNSRECORD_zkey_to_pkey (tld, &zone)))
1834 {
1835 /* 'ip' is a DNS name */
1836 gp = GNUNET_new (struct Gns2DnsPending);
1837 gp->ac = ac;
1840 gp);
1842 AF_UNSPEC,
1845 gp);
1846 GNUNET_free (ip);
1847 continue;
1848 }
1849 /* 'ip' should be a GNS name */
1850 gp = GNUNET_new (struct Gns2DnsPending);
1851 gp->ac = ac;
1854 gp);
1855 gp->rh = GNUNET_new (struct GNS_ResolverHandle);
1856 if (0 == strcmp (tld, "+"))
1857 {
1858 ip = translate_dot_plus (rh,
1859 ip);
1860 tld = GNS_get_tld (ip);
1861 if (GNUNET_OK !=
1863 &zone))
1864 {
1865 GNUNET_break_op (0);
1866 GNUNET_free (ip);
1867 continue;
1868 }
1869 }
1870 gp->rh->authority_zone = zone;
1872 "Resolving `%s' to determine IP address of DNS server for GNS2DNS transition for `%s'\n",
1873 ip,
1874 ns);
1875 gp->rh->name = ip;
1876 gp->rh->name_resolution_pos = strlen (ip) - strlen (tld) - 1;
1878 gp->rh->proc_cls = gp;
1881 gp->rh->loop_limiter = rh->loop_limiter + 1;
1882 gp->rh->loop_threshold = rh->loop_threshold;
1883 gp->rh->task_id
1885 gp->rh);
1886 } /* end 'for all records' */
1887
1888 if (NULL == ns)
1889 {
1890 /* not a single GNS2DNS record found */
1891 GNUNET_free (ac);
1892 return GNUNET_SYSERR;
1893 }
1895 strcpy (ac->authority_info.dns_authority.name,
1896 ns);
1897 /* for DNS recursion, the label is the full DNS name,
1898 created from the remainder of the GNS name and the
1899 name in the NS record */
1900 GNUNET_asprintf (&ac->label,
1901 "%.*s%s%s",
1902 (int) rh->name_resolution_pos,
1903 rh->name,
1904 (0 != rh->name_resolution_pos) ? "." : "",
1905 ns);
1906 GNUNET_free (ns);
1907
1908 {
1909 /* the GNS name is UTF-8 and may include multibyte chars.
1910 * We have to convert the combined name to a DNS-compatible IDNA.
1911 */
1912 char *tmp = ac->label;
1913
1914 if (IDNA_SUCCESS != idna_to_ascii_8z (tmp,
1915 &ac->label,
1916 IDNA_ALLOW_UNASSIGNED))
1917 {
1919 _ ("Name `%s' cannot be converted to IDNA."),
1920 tmp);
1921 GNUNET_free (tmp);
1922 GNUNET_free (ac);
1923 return GNUNET_SYSERR;
1924 }
1925 GNUNET_free (tmp);
1926 }
1927
1929 rh->ac_tail,
1930 ac);
1931 if (strlen (ac->label) > GNUNET_DNSPARSER_MAX_NAME_LENGTH)
1932 {
1934 _ ("GNS lookup resulted in DNS name that is too long (`%s')\n"),
1935 ac->label);
1936 GNUNET_free (ac->label);
1937 GNUNET_free (ac);
1938 return GNUNET_SYSERR;
1939 }
1941 return GNUNET_OK;
1942}
1943
1944
1945static void
1947 unsigned int rd_count,
1948 const struct GNUNET_GNSRECORD_Data *rd)
1949{
1950 struct GNS_ResolverHandle *rh = cls;
1951 char *cname;
1952 char scratch[UINT16_MAX];
1953 size_t scratch_off;
1954 size_t scratch_start;
1955 size_t off;
1956 struct GNUNET_GNSRECORD_Data rd_new[rd_count];
1957 unsigned int rd_off;
1958
1960 "Resolution succeeded for `%s' in zone %s, got %u records\n",
1961 rh->ac_tail->label,
1963 rd_count);
1964 if (0 == rd_count)
1965 {
1967 _ ("GNS lookup failed (zero records found for `%s')\n"),
1968 rh->name);
1969 fail_resolution (rh);
1970 return;
1971 }
1972
1973 if (0 == rh->name_resolution_pos)
1974 {
1975 /* top-level match, are we done yet? */
1976 if ((rd_count > 0) &&
1979 {
1980 off = 0;
1982 rd[0].data_size,
1983 &off);
1984 if ((NULL == cname) ||
1985 (off != rd[0].data_size))
1986 {
1987 GNUNET_break_op (0);
1988 GNUNET_free (cname);
1989 fail_resolution (rh);
1990 return;
1991 }
1993 cname);
1994 GNUNET_free (cname);
1995 return;
1996 }
1997 if ((rd_count > 0) &&
2000 {
2002 rd[0].data);
2003 return;
2004 }
2005
2006
2007 /* If A/AAAA was requested,
2008 * but we got a GNS2DNS record */
2009 if ((GNUNET_DNSPARSER_TYPE_A == rh->record_type) ||
2011 {
2012 for (unsigned int i = 0; i < rd_count; i++)
2013 {
2014 switch (rd[i].record_type)
2015 {
2017 {
2018 /* delegation to DNS */
2020 "Found GNS2DNS record, delegating to DNS!\n");
2021 if (GNUNET_OK ==
2023 rd_count,
2024 rd))
2025 return;
2026 else
2027 goto fail;
2028 }
2029
2030 default:
2031 break;
2032 } /* end: switch */
2033 } /* end: for rd */
2034 } /* end: name_resolution_pos */
2035 /* convert relative names in record values to absolute names,
2036 using 'scratch' array for memory allocations */
2037 scratch_off = 0;
2038 rd_off = 0;
2039 for (unsigned int i = 0; i < rd_count; i++)
2040 {
2041 GNUNET_assert (rd_off <= i);
2042 if ((((0 != rh->protocol) &&
2043 (0 != rh->service)) || (NULL != rh->prefix)) &&
2048 continue;
2049 /* we _only_ care about boxed records */
2050
2051 GNUNET_assert (rd_off < rd_count);
2052 rd_new[rd_off] = rd[i];
2053 /* Check if the embedded name(s) end in "+", and if so,
2054 replace the "+" with the zone at "ac_tail", changing the name
2055 to a ".ZONEKEY". The name is allocated on the 'scratch' array,
2056 so we can free it afterwards. */
2057 switch (rd[i].record_type)
2058 {
2060 {
2061 char *rname;
2062 rname = GNUNET_strndup (rd[i].data, rd[i].data_size);
2063 rname = translate_dot_plus (rh, rname);
2064 GNUNET_break (NULL != rname);
2065 scratch_start = scratch_off;
2066 memcpy (&scratch[scratch_start], rname, strlen (rname) + 1);
2067 scratch_off += strlen (rname) + 1;
2068 GNUNET_assert (rd_off < rd_count);
2069 rd_new[rd_off].data = &scratch[scratch_start];
2070 rd_new[rd_off].data_size = scratch_off - scratch_start;
2071 rd_off++;
2072 GNUNET_free (rname);
2073 }
2074 break;
2075
2077 {
2078 char *cname_tmp;
2079
2080 off = 0;
2081 cname_tmp = GNUNET_DNSPARSER_parse_name (rd[i].data,
2082 rd[i].data_size,
2083 &off);
2084 if ((NULL == cname_tmp) ||
2085 (off != rd[i].data_size))
2086 {
2087 GNUNET_break_op (0); /* record not well-formed */
2088 }
2089 else
2090 {
2091 cname_tmp = translate_dot_plus (rh, cname_tmp);
2092 GNUNET_break (NULL != cname_tmp);
2093 scratch_start = scratch_off;
2094 if (GNUNET_OK !=
2096 sizeof(scratch),
2097 &scratch_off,
2098 cname_tmp))
2099 {
2100 GNUNET_break (0);
2101 }
2102 else
2103 {
2104 GNUNET_assert (rd_off < rd_count);
2105 rd_new[rd_off].data = &scratch[scratch_start];
2106 rd_new[rd_off].data_size = scratch_off - scratch_start;
2107 rd_off++;
2108 }
2109 }
2110 GNUNET_free (cname_tmp);
2111 }
2112 break;
2113
2115 {
2116 struct GNUNET_DNSPARSER_SoaRecord *soa;
2117
2118 off = 0;
2120 rd[i].data_size,
2121 &off);
2122 if ((NULL == soa) ||
2123 (off != rd[i].data_size))
2124 {
2125 GNUNET_break_op (0); /* record not well-formed */
2126 }
2127 else
2128 {
2129 soa->mname = translate_dot_plus (rh, soa->mname);
2130 soa->rname = translate_dot_plus (rh, soa->rname);
2131 scratch_start = scratch_off;
2132 if (GNUNET_OK !=
2134 sizeof(scratch),
2135 &scratch_off,
2136 soa))
2137 {
2138 GNUNET_break (0);
2139 }
2140 else
2141 {
2142 GNUNET_assert (rd_off < rd_count);
2143 rd_new[rd_off].data = &scratch[scratch_start];
2144 rd_new[rd_off].data_size = scratch_off - scratch_start;
2145 rd_off++;
2146 }
2147 }
2148 if (NULL != soa)
2150 }
2151 break;
2152
2154 {
2155 struct GNUNET_DNSPARSER_MxRecord *mx;
2156
2157 off = 0;
2159 rd[i].data_size,
2160 &off);
2161 if ((NULL == mx) ||
2162 (off != rd[i].data_size))
2163 {
2164 GNUNET_break_op (0); /* record not well-formed */
2165 }
2166 else
2167 {
2168 mx->mxhost = translate_dot_plus (rh, mx->mxhost);
2169 scratch_start = scratch_off;
2170 if (GNUNET_OK !=
2172 sizeof(scratch),
2173 &scratch_off,
2174 mx))
2175 {
2176 GNUNET_break (0);
2177 }
2178 else
2179 {
2180 GNUNET_assert (rd_off < rd_count);
2181 rd_new[rd_off].data = &scratch[scratch_start];
2182 rd_new[rd_off].data_size = scratch_off - scratch_start;
2183 rd_off++;
2184 }
2185 }
2186 if (NULL != mx)
2188 }
2189 break;
2190
2192 {
2193 struct GNUNET_DNSPARSER_SrvRecord *srv;
2194
2195 off = 0;
2197 rd[i].data_size,
2198 &off);
2199 if ((NULL == srv) ||
2200 (off != rd[i].data_size))
2201 {
2202 GNUNET_break_op (0); /* record not well-formed */
2203 }
2204 else
2205 {
2206 srv->target = translate_dot_plus (rh, srv->target);
2207 scratch_start = scratch_off;
2208 if (GNUNET_OK !=
2210 sizeof(scratch),
2211 &scratch_off,
2212 srv))
2213 {
2214 GNUNET_break (0);
2215 }
2216 else
2217 {
2218 GNUNET_assert (rd_off < rd_count);
2219 rd_new[rd_off].data = &scratch[scratch_start];
2220 rd_new[rd_off].data_size = scratch_off - scratch_start;
2221 rd_off++;
2222 }
2223 }
2224 if (NULL != srv)
2226 }
2227 break;
2228
2230 {
2232
2233 off = 0;
2235 rd[i].data_size,
2236 &off);
2237 if ((NULL == uri) ||
2238 (off != rd[i].data_size))
2239 {
2241 _ ("Failed to deserialize URI record with target\n"));
2242 GNUNET_break_op (0); /* record not well-formed */
2243 }
2244 else
2245 {
2246 scratch_start = scratch_off;
2247 if (GNUNET_OK !=
2249 sizeof(scratch),
2250 &scratch_off,
2251 uri))
2252 {
2253 GNUNET_break (0);
2254 }
2255 else
2256 {
2257 GNUNET_assert (rd_off < rd_count);
2258 rd_new[rd_off].data = &scratch[scratch_start];
2259 rd_new[rd_off].data_size = scratch_off - scratch_start;
2260 rd_off++;
2261 }
2262 }
2263 if (NULL != uri)
2265 }
2266 break;
2267
2270 {
2272 if (rd[i].data_size < sizeof(uint32_t))
2273 {
2274 GNUNET_break_op (0);
2275 break;
2276 }
2277 if (GNUNET_OK !=
2279 rd[i].data_size,
2280 rd[i].record_type,
2281 &pubkey))
2282 {
2283 GNUNET_break_op (0);
2284 break;
2285 }
2286 rd_off++;
2287 if (rd[i].record_type != rh->record_type)
2288 {
2289 /* try to resolve "@" */
2290 struct AuthorityChain *ac;
2291
2292 ac = GNUNET_new (struct AuthorityChain);
2293 ac->rh = rh;
2298 rh->ac_tail,
2299 ac);
2301 rh);
2302 return;
2303 }
2304 }
2305 break;
2306
2308 {
2309 /* delegation to DNS */
2311 {
2312 rd_off++;
2313 break; /* do not follow to DNS, we wanted the GNS2DNS record! */
2314 }
2316 "Found GNS2DNS record, delegating to DNS!\n");
2317 if (GNUNET_OK ==
2319 rd_count,
2320 rd))
2321 return;
2322 else
2323 goto fail;
2324 }
2325
2327 {
2328 /* unbox SRV/TLSA records if a specific one was requested */
2329 if ((0 != rh->protocol) &&
2330 (0 != rh->service) &&
2331 (rd[i].data_size >= sizeof(struct GNUNET_GNSRECORD_BoxRecord)))
2332 {
2333 const struct GNUNET_GNSRECORD_BoxRecord *box;
2334
2335 box = rd[i].data;
2337 "Got BOX record, checking if parameters match... %u/%u vs %u/%u\n",
2338 ntohs (box->protocol), ntohs (box->service),
2339 rh->protocol, rh->service);
2340 if ((ntohs (box->protocol) == rh->protocol) &&
2341 (ntohs (box->service) == rh->service))
2342 {
2343 /* Box matches, unbox! */
2344 GNUNET_assert (rd_off < rd_count);
2345 rd_new[rd_off].record_type = ntohl (box->record_type);
2346 rd_new[rd_off].data_size -= sizeof(struct
2348 rd_new[rd_off].data = &box[1];
2349 rd_off++;
2350 }
2351 }
2352 else
2353 {
2354 /* no specific protocol/service specified, preserve all BOX
2355 records (for modern, GNS-enabled applications) */
2356 rd_off++;
2357 }
2358 break;
2359 }
2361 {
2362 /* unbox SBOX records if a specific one was requested */
2363 if ((rh->prefix != NULL) &&
2364 (rd[i].data_size >= sizeof(struct GNUNET_GNSRECORD_SBoxRecord)))
2365 {
2366 const struct GNUNET_GNSRECORD_SBoxRecord *box;
2367 const char *prefix;
2368 size_t prefix_len;
2369
2370 box = rd[i].data;
2371 prefix = rd[i].data + sizeof(struct GNUNET_GNSRECORD_SBoxRecord);
2372 prefix_len = strnlen (
2373 prefix,
2374 rd[i].data_size - sizeof(struct GNUNET_GNSRECORD_SBoxRecord)) + 1;
2375 if (prefix_len - 1 >= rd[i].data_size - sizeof(struct
2377 {
2379 "SBOX record with invalid prefix length, maybe not null-terminated\n");
2380 continue;
2381 }
2383 "Got SBOX record, checking if prefixes match... %s vs %s\n",
2384 prefix, rh->prefix);
2385 if (strcmp (rh->prefix, prefix) == 0)
2386 {
2387 /* Box matches, unbox! */
2388 GNUNET_assert (rd_off < rd_count);
2389 rd_new[rd_off].record_type = ntohl (box->record_type);
2390 rd_new[rd_off].data_size -= sizeof(struct
2392 + prefix_len;
2393 rd_new[rd_off].data = rd[i].data
2394 + sizeof(struct GNUNET_GNSRECORD_SBoxRecord)
2395 + prefix_len;
2396 rd_off++;
2397 }
2398 }
2399 else
2400 {
2402 _ (
2403 "GNS no specific protocol/service specified, preserve all SBOX `%s')\n"),
2404 rh->name);
2405 /* no specific protocol/service specified, preserve all SBOX
2406 records (for modern, GNS-enabled applications) */
2407 rd_off++;
2408 }
2409 break;
2410 }
2411 default:
2412 rd_off++;
2413 break;
2414 } /* end: switch */
2415 } /* end: for rd_count */
2416
2417 GNUNET_free (rh->prefix);
2418 rh->prefix = NULL;
2419
2420 /* yes, we are done, return result */
2422 "Returning GNS response for `%s' with %u answers\n",
2423 rh->ac_tail->label,
2424 rd_off);
2425 rh->proc (rh->proc_cls,
2426 rd_off,
2427 rd_new);
2429 rh);
2430 return;
2431 }
2432
2433 switch (rd[0].record_type)
2434 {
2436 GNUNET_break_op (1 == rd_count); /* REDIRECT should be unique */
2438 &rd[0]);
2439 return;
2440
2442 GNUNET_break_op (1 == rd_count); /* CNAME should be unique */
2444 &rd[0]);
2445 return;
2446
2449 GNUNET_break_op (1 == rd_count); /* PKEY should be unique */
2451 &rd[0]);
2452 return;
2453
2455 if (GNUNET_OK ==
2457 rd_count,
2458 rd))
2459 return;
2460 break;
2461 default:
2463 return;
2465 _ ("Unable to process critical delegation record\n"));
2466 break;
2467 }
2468fail:
2470 _ ("GNS lookup recursion failed (no delegation record found)\n"));
2471 fail_resolution (rh);
2472}
2473
2474
2483static void
2485 int32_t success,
2486 const char *emsg)
2487{
2488 struct CacheOps *co = cls;
2489
2490 co->namecache_qe_cache = NULL;
2491 if (GNUNET_OK != success)
2493 _ ("Failed to cache GNS resolution: %s\n"),
2494 emsg);
2496 co_tail,
2497 co);
2498 GNUNET_free (co);
2499}
2500
2501
2520static void
2521handle_dht_response (void *cls,
2522 struct GNUNET_TIME_Absolute exp,
2523 const struct GNUNET_HashCode *key,
2524 const struct GNUNET_PeerIdentity *trunc_peer,
2525 const struct GNUNET_DHT_PathElement *get_path,
2526 unsigned int get_path_length,
2527 const struct GNUNET_DHT_PathElement *put_path,
2528 unsigned int put_path_length,
2530 size_t size,
2531 const void *data)
2532{
2533 struct GNS_ResolverHandle *rh = cls;
2534 struct AuthorityChain *ac = rh->ac_tail;
2535 const struct GNUNET_GNSRECORD_Block *block;
2536 struct CacheOps *co;
2537
2538 (void) exp;
2539 (void) key;
2540 (void) get_path;
2541 (void) get_path_length;
2542 (void) put_path;
2543 (void) put_path_length;
2544 (void) type;
2546 rh->get_handle = NULL;
2548 rh->dht_heap_node = NULL;
2550 "Handling response from the DHT\n");
2551 if (size < sizeof(struct GNUNET_GNSRECORD_Block))
2552 {
2553 /* how did this pass DHT block validation!? */
2554 GNUNET_break (0);
2555 fail_resolution (rh);
2556 return;
2557 }
2558 block = data;
2560 {
2561 /* how did this pass DHT block validation!? */
2562 GNUNET_break (0);
2563 fail_resolution (rh);
2564 return;
2565 }
2567 "Decrypting DHT block of size %llu for `%s', expires %s\n",
2568 (unsigned long long) GNUNET_GNSRECORD_block_get_size (block),
2569 rh->name,
2571 if (GNUNET_OK !=
2574 ac->label,
2576 rh))
2577 {
2578 GNUNET_break_op (0); /* block was ill-formed */
2579 fail_resolution (rh);
2580 return;
2581 }
2584 rel_value_us)
2585 {
2587 "Received expired block from the DHT, will not cache it.\n");
2588 return;
2589 }
2591 return;
2592 /* Cache well-formed blocks */
2594 "Caching response from the DHT in namecache\n");
2595 co = GNUNET_new (struct CacheOps);
2597 block,
2598 &
2600 co);
2602 co_tail,
2603 co);
2604}
2605
2606
2613static void
2615 const struct GNUNET_HashCode *query)
2616{
2617 struct GNS_ResolverHandle *rx;
2618
2619 GNUNET_assert (NULL == rh->get_handle);
2622 query,
2625 NULL, 0,
2626 &handle_dht_response, rh);
2628 rh,
2630 abs_value_us);
2633 {
2634 /* fail longest-standing DHT request */
2636 rx->dht_heap_node = NULL;
2637 GNUNET_assert (NULL != rx);
2638 fail_resolution (rx);
2639 }
2640}
2641
2642
2651static void
2653 unsigned int rd_count,
2654 const struct GNUNET_GNSRECORD_Data *rd)
2655{
2656 struct GNS_ResolverHandle *rh = cls;
2657
2658 if (0 == rd_count)
2660 _ ("GNS namecache returned empty result for `%s'\n"),
2661 rh->name);
2663 rd_count,
2664 rd);
2665}
2666
2667
2674static void
2676 const struct GNUNET_GNSRECORD_Block *block)
2677{
2678 struct GNS_ResolverHandle *rh = cls;
2679 struct AuthorityChain *ac = rh->ac_tail;
2680 const char *label = ac->label;
2681 const struct GNUNET_CRYPTO_PublicKey *auth =
2683 struct GNUNET_HashCode query;
2684
2685 GNUNET_assert (NULL != rh->namecache_qe);
2686 rh->namecache_qe = NULL;
2687 if (NULL == block)
2689 "No block found\n");
2690 else
2692 "Got block with expiration %s\n",
2695 if (((GNUNET_GNS_LO_DEFAULT == rh->options) ||
2697 (ac != rh->ac_head))) &&
2698 ((NULL == block) ||
2701 rel_value_us)))
2702 {
2703 /* namecache knows nothing; try DHT lookup */
2705 label,
2706 &query);
2708 "Starting DHT lookup for `%s' in zone `%s' under key `%s'\n",
2709 ac->label,
2711 GNUNET_h2s (&query));
2712 start_dht_request (rh, &query);
2713 return;
2714 }
2715
2716 if ((NULL == block) ||
2719 rel_value_us))
2720 {
2721 /* DHT not permitted and no local result, fail */
2723 "Resolution failed for `%s' in zone %s (DHT lookup not permitted by configuration)\n",
2724 ac->label,
2726 fail_resolution (rh);
2727 return;
2728 }
2730 "Received result from namecache for label `%s'\n",
2731 ac->label);
2732
2733 if (GNUNET_OK !=
2735 auth,
2736 label,
2738 rh))
2739 {
2740 GNUNET_break_op (0); /* block was ill-formed */
2741 /* try DHT instead */
2743 label,
2744 &query);
2746 "Starting DHT lookup for `%s' in zone `%s' under key `%s'\n",
2747 ac->label,
2749 GNUNET_h2s (&query));
2750 start_dht_request (rh, &query);
2751 return;
2752 }
2753}
2754
2755
2761static void
2763{
2764 struct AuthorityChain *ac = rh->ac_tail;
2765 struct GNUNET_HashCode query;
2766
2768 "Starting GNS resolution for `%s' in zone %s\n",
2769 ac->label,
2772 ac->label,
2773 &query);
2775 {
2776 rh->namecache_qe
2778 &query,
2780 rh);
2781 GNUNET_assert (NULL != rh->namecache_qe);
2782 }
2783 else
2784 {
2786 &query);
2787 }
2788}
2789
2790
2797static void
2798handle_revocation_result (void *cls,
2799 int is_valid)
2800{
2801 struct GNS_ResolverHandle *rh = cls;
2802 struct AuthorityChain *ac = rh->ac_tail;
2803
2804 rh->rev_check = NULL;
2805 if (GNUNET_YES != is_valid)
2806 {
2808 _ ("Zone %s was revoked, resolution fails\n"),
2811 return;
2812 }
2814}
2815
2816
2822static void
2824{
2825 struct AuthorityChain *ac = rh->ac_tail;
2826
2828 "Starting revocation check for zone %s\n",
2833 rh);
2834 GNUNET_assert (NULL != rh->rev_check);
2835}
2836
2837
2838static void
2839recursive_resolution (void *cls)
2840{
2841 struct GNS_ResolverHandle *rh = cls;
2842
2843 rh->task_id = NULL;
2844 if (rh->loop_threshold < rh->loop_limiter++)
2845 {
2847 "Encountered unbounded recursion resolving `%s'\n",
2848 rh->name);
2849 fail_resolution (rh);
2850 return;
2851 }
2852 if (GNUNET_YES == rh->ac_tail->gns_authority)
2854 else
2856}
2857
2858
2859static void
2860start_resolver_lookup (void *cls)
2861{
2862 struct GNS_ResolverHandle *rh = cls;
2863 struct AuthorityChain *ac;
2864 struct in_addr v4;
2865 struct in6_addr v6;
2866
2867 rh->task_id = NULL;
2868 if (1 == inet_pton (AF_INET,
2869 rh->name,
2870 &v4))
2871 {
2872 /* name is IPv4 address, pretend it's an A record */
2874
2875 rd.data = &v4;
2876 rd.data_size = sizeof(v4);
2877 rd.expiration_time = UINT64_MAX;
2879 rd.flags = 0;
2880 rh->proc (rh->proc_cls,
2881 1,
2882 &rd);
2883 GNUNET_assert (NULL == rh->task_id);
2885 rh);
2886 return;
2887 }
2888 if (1 == inet_pton (AF_INET6,
2889 rh->name,
2890 &v6))
2891 {
2892 /* name is IPv6 address, pretend it's an AAAA record */
2894
2895 rd.data = &v6;
2896 rd.data_size = sizeof(v6);
2897 rd.expiration_time = UINT64_MAX;
2899 rd.flags = 0;
2900 rh->proc (rh->proc_cls,
2901 1,
2902 &rd);
2903 GNUNET_assert (NULL == rh->task_id);
2905 rh);
2906 return;
2907 }
2908
2909 ac = GNUNET_new (struct AuthorityChain);
2910 ac->rh = rh;
2912 if (NULL == ac->label)
2913 /* name was just the "TLD", so we default to label
2914 #GNUNET_GNS_EMPTY_LABEL_AT */
2919 rh->ac_tail,
2920 ac);
2922 rh);
2923}
2924
2925
2940struct GNS_ResolverHandle *
2942 uint32_t record_type,
2943 const char *name,
2945 uint16_t recursion_depth_limit,
2947 void *proc_cls)
2948{
2949 struct GNS_ResolverHandle *rh;
2950
2952 "Starting lookup for `%s'\n",
2953 name);
2954 rh = GNUNET_new (struct GNS_ResolverHandle);
2956 rlh_tail,
2957 rh);
2958 rh->authority_zone = *zone;
2959 rh->proc = proc;
2960 rh->proc_cls = proc_cls;
2961 rh->options = options;
2963 rh->name = GNUNET_strdup (name);
2964 rh->name_resolution_pos = strlen (name);
2965 rh->loop_threshold = recursion_depth_limit;
2967 rh);
2968 return rh;
2969}
2970
2971
2977void
2979{
2980 struct DnsResult *dr;
2981 struct AuthorityChain *ac;
2982
2984 rlh_tail,
2985 rh);
2986 if (NULL != rh->dns_request)
2987 {
2989 rh->dns_request = NULL;
2990 }
2991 while (NULL != (ac = rh->ac_head))
2992 {
2994 rh->ac_tail,
2995 ac);
2996 if (GNUNET_NO == ac->gns_authority)
2997 {
2998 struct Gns2DnsPending *gp;
2999
3000 while (NULL != (gp = ac->authority_info.dns_authority.gp_head))
3001 {
3004 gp);
3005 if (NULL != gp->rh)
3006 {
3007 /* rh->g2dc->rh is NOT in the DLL yet, so to enable us
3008 using GNS_resolver_lookup_cancel here, we need to
3009 add it first... */
3011 rlh_tail,
3012 gp->rh);
3013 GNUNET_assert (NULL == gp->rh->task_id);
3016 gp->rh);
3017 gp->rh = NULL;
3018 }
3019 if (NULL != gp->dns_rh)
3020 {
3022 gp->dns_rh = NULL;
3023 }
3024 GNUNET_free (gp);
3025 }
3027 }
3028 GNUNET_free (ac->label);
3029 GNUNET_free (ac);
3030 }
3031 if (NULL != rh->task_id)
3032 {
3034 rh->task_id = NULL;
3035 }
3036 if (NULL != rh->get_handle)
3037 {
3039 rh->get_handle = NULL;
3040 }
3041 if (NULL != rh->dht_heap_node)
3042 {
3044 rh->dht_heap_node = NULL;
3045 }
3046 if (NULL != rh->namecache_qe)
3047 {
3049 rh->namecache_qe = NULL;
3050 }
3051 if (NULL != rh->rev_check)
3052 {
3054 rh->rev_check = NULL;
3055 }
3056 if (NULL != rh->std_resolve)
3057 {
3059 "Canceling standard DNS resolution\n");
3061 rh->std_resolve = NULL;
3062 }
3063 while (NULL != (dr = rh->dns_result_head))
3064 {
3067 dr);
3068 GNUNET_free (dr);
3069 }
3070 if (NULL != rh->prefix)
3071 {
3073 rh->prefix = NULL;
3074 }
3075 GNUNET_free (rh->leho);
3076 GNUNET_free (rh->name);
3077 GNUNET_free (rh);
3078}
3079
3080
3081/* ***************** Resolver initialization ********************* */
3082
3083
3092void
3094 struct GNUNET_DHT_Handle *dht,
3095 const struct GNUNET_CONFIGURATION_Handle *c,
3096 unsigned long long max_bg_queries)
3097{
3098 cfg = c;
3100 dht_handle = dht;
3103 max_allowed_background_queries = max_bg_queries;
3105 "namecache",
3106 "DISABLE");
3109 "Namecache disabled\n");
3110}
3111
3112
3116void
3118{
3119 struct GNS_ResolverHandle *rh;
3120 struct CacheOps *co;
3121
3122 /* abort active resolutions */
3123 while (NULL != (rh = rlh_head))
3124 {
3125 rh->proc (rh->proc_cls,
3126 0,
3127 NULL);
3129 }
3130 while (NULL != (co = co_head))
3131 {
3133 co_tail,
3134 co);
3136 GNUNET_free (co);
3137 }
3139 dht_lookup_heap = NULL;
3140 dht_handle = NULL;
3141 namecache_handle = NULL;
3142}
3143
3144
3145/* 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 char * name
Name (label) of the records to list.
static struct GNUNET_NAMECACHE_Handle * ns
Handle to the namecache.
static struct GNUNET_CRYPTO_PublicKey pubkey
Public key of the zone to look in.
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.
#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.
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 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.
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 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_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_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.
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.
struct GNS_ResolverHandle * GNS_resolver_lookup(const struct GNUNET_CRYPTO_PublicKey *zone, uint32_t record_type, const char *name, enum GNUNET_GNS_LocalOptions options, uint16_t recursion_depth_limit, GNS_ResultProcessor proc, void *proc_cls)
Lookup of a record in a specific zone calls lookup result processor on result.
static struct GNUNET_CONTAINER_Heap * dht_lookup_heap
Heap for limiting parallel DHT lookups.
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_OS_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(enum GNUNET_CRYPTO_Quality mode, uint32_t i)
Produce a random value.
@ GNUNET_CRYPTO_QUALITY_NONCE
Randomness for IVs etc.
void GNUNET_DHT_get_stop(struct GNUNET_DHT_GetHandle *get_handle)
Stop async DHT-get.
Definition dht_api.c:1233
struct GNUNET_DHT_GetHandle * GNUNET_DHT_get_start(struct GNUNET_DHT_Handle *handle, enum GNUNET_BLOCK_Type type, const struct GNUNET_HashCode *key, uint32_t desired_replication_level, enum GNUNET_DHT_RouteOption options, const void *xquery, size_t xquery_size, GNUNET_DHT_GetIterator iter, void *iter_cls)
Perform an asynchronous GET operation on the DHT identified.
Definition dht_api.c:1160
@ GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE
Each peer along the way should process the request (otherwise only peers locally closest to the key w...
#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:455
int GNUNET_DNSPARSER_builder_add_name(char *dst, size_t dst_len, size_t *off, const char *name)
Add a DNS name to the UDP packet at the given location, converting the name to IDNA notation as neces...
Definition dnsparser.c:985
void GNUNET_DNSPARSER_free_packet(struct GNUNET_DNSPARSER_Packet *p)
Free memory taken by a packet.
Definition dnsparser.c:950
#define GNUNET_DNSPARSER_TYPE_SRV
#define GNUNET_DNSPARSER_TYPE_SOA
#define GNUNET_DNSPARSER_TYPE_A
void GNUNET_DNSPARSER_free_srv(struct GNUNET_DNSPARSER_SrvRecord *srv)
Free SRV information record.
Definition dnsparser.c:139
#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:410
void GNUNET_DNSPARSER_free_uri(struct GNUNET_DNSPARSER_UriRecord *uri)
Free URI information record.
Definition dnsparser.c:154
#define GNUNET_DNSPARSER_TYPE_NS
int GNUNET_DNSPARSER_builder_add_soa(char *dst, size_t dst_len, size_t *off, const struct GNUNET_DNSPARSER_SoaRecord *soa)
Add an SOA record to the UDP packet at the given location.
Definition dnsparser.c:1177
#define GNUNET_DNSPARSER_TYPE_CNAME
struct GNUNET_DNSPARSER_UriRecord * GNUNET_DNSPARSER_parse_uri(const char *udp_payload, size_t udp_payload_length, size_t *off)
Parse a DNS URI record.
Definition dnsparser.c:537
struct GNUNET_DNSPARSER_SrvRecord * GNUNET_DNSPARSER_parse_srv(const char *udp_payload, size_t udp_payload_length, size_t *off)
Parse a DNS SRV record.
Definition dnsparser.c:496
char * GNUNET_DNSPARSER_parse_name(const char *udp_payload, size_t udp_payload_length, size_t *off)
Parse name inside of a DNS query or record.
Definition dnsparser.c:353
int GNUNET_DNSPARSER_builder_add_mx(char *dst, size_t dst_len, size_t *off, const struct GNUNET_DNSPARSER_MxRecord *mx)
Add an MX record to the UDP packet at the given location.
Definition dnsparser.c:1099
void GNUNET_DNSPARSER_free_soa(struct GNUNET_DNSPARSER_SoaRecord *soa)
Free SOA information record.
Definition dnsparser.c:108
int GNUNET_DNSPARSER_builder_add_srv(char *dst, size_t dst_len, size_t *off, const struct GNUNET_DNSPARSER_SrvRecord *srv)
Add an SRV record to the UDP packet at the given location.
Definition dnsparser.c:1218
void GNUNET_DNSPARSER_free_mx(struct GNUNET_DNSPARSER_MxRecord *mx)
Free MX information record.
Definition dnsparser.c:169
#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:1400
int GNUNET_DNSPARSER_builder_add_uri(char *dst, size_t dst_len, size_t *off, const struct GNUNET_DNSPARSER_UriRecord *uri)
Add an URI record to the UDP packet at the given location.
Definition dnsparser.c:1255
#define GNUNET_DNSPARSER_TYPE_MX
struct GNUNET_DNSPARSER_Packet * GNUNET_DNSPARSER_parse(const char *udp_payload, size_t udp_payload_length)
Parse a UDP payload of a DNS packet in to a nice struct for further processing and manipulation.
Definition dnsparser.c:729
#define GNUNET_DNSPARSER_MAX_NAME_LENGTH
Maximum length of a name in DNS.
struct GNUNET_DNSSTUB_Context * GNUNET_DNSSTUB_start(unsigned int num_sockets)
Start a DNS stub resolver.
Definition dnsstub.c:586
int GNUNET_DNSSTUB_add_dns_ip(struct GNUNET_DNSSTUB_Context *ctx, const char *dns_ip)
Add nameserver for use by the DNSSTUB.
Definition dnsstub.c:613
void GNUNET_DNSSTUB_stop(struct GNUNET_DNSSTUB_Context *ctx)
Cleanup DNSSTUB resolver.
Definition dnsstub.c:705
struct GNUNET_DNSSTUB_RequestSocket * GNUNET_DNSSTUB_resolve(struct GNUNET_DNSSTUB_Context *ctx, const void *request, size_t request_len, GNUNET_DNSSTUB_ResultCallback rc, void *rc_cls)
Perform DNS resolution using our default IP from init.
Definition dnsstub.c:526
void GNUNET_DNSSTUB_resolve_cancel(struct GNUNET_DNSSTUB_RequestSocket *rs)
Cancel DNS resolution.
Definition dnsstub.c:562
int GNUNET_DNSSTUB_add_dns_sa(struct GNUNET_DNSSTUB_Context *ctx, const struct sockaddr *sa)
Add nameserver for use by the DNSSTUB.
Definition dnsstub.c:665
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.
void GNUNET_GNSRECORD_query_from_public_key(const struct GNUNET_CRYPTO_PublicKey *pub, const char *label, struct GNUNET_HashCode *query)
Calculate the DHT query for a given label in a given zone.
const char * GNUNET_GNSRECORD_z2s(const struct GNUNET_CRYPTO_PublicKey *z)
Convert a zone to a string (for printing debug messages).
int GNUNET_GNSRECORD_zkey_to_pkey(const char *zkey, struct GNUNET_CRYPTO_PublicKey *pkey)
Convert an absolute domain name to the respective public key.
enum GNUNET_GenericReturnValue GNUNET_GNSRECORD_block_decrypt(const struct GNUNET_GNSRECORD_Block *block, const struct GNUNET_CRYPTO_PublicKey *zone_key, const char *label, GNUNET_GNSRECORD_RecordCallback proc, void *proc_cls)
Decrypt block.
const char * GNUNET_GNSRECORD_pkey_to_zkey(const struct GNUNET_CRYPTO_PublicKey *pkey)
Convert public key to the respective absolute domain name in the ".zkey" pTLD.
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_PublicKey *key)
Build a #GNUNET_GNSRECORD_PublicKey from zone delegation resource record data.
#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
#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_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.
void GNUNET_REVOCATION_query_cancel(struct GNUNET_REVOCATION_Query *q)
Cancel key revocation check.
struct GNUNET_REVOCATION_Query * GNUNET_REVOCATION_query(const struct GNUNET_CONFIGURATION_Handle *cfg, const struct GNUNET_CRYPTO_PublicKey *key, GNUNET_REVOCATION_Callback func, void *func_cls)
Check if a key was revoked.
void * GNUNET_SCHEDULER_cancel(struct GNUNET_SCHEDULER_Task *task)
Cancel the task with the specified identifier.
Definition scheduler.c:980
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_now(GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run as soon as possible.
Definition scheduler.c:1304
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_delayed(struct GNUNET_TIME_Relative delay, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run with a specified delay.
Definition scheduler.c:1277
#define GNUNET_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:660
#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 * next
This is a DLL.
union AuthorityChain::@55 authority_info
Information about the resolver authority for this label.
int gns_authority
GNUNET_YES if the authority was a GNS authority, GNUNET_NO if the authority was a DNS authority.
struct 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?
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.
struct AuthorityChain::@55::@56 dns_authority
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_CRYPTO_PublicKey authority_zone
The top-level GNS authoritative zone to query.
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 DnsResult * dns_result_head
DLL of results we got from DNS.
struct AuthorityChain * ac_head
DLL to store the authority chain.
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.
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?
char * name
Name of the record that the query is for (0-terminated).
struct GNUNET_DNSPARSER_RawRecord raw
Raw data for all other types.
union GNUNET_DNSPARSER_Record::@20 data
Payload of the record (which one of these is valid depends on the 'type').
struct GNUNET_DNSPARSER_UriRecord * uri
URI data for URI records.
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:136
Time for absolute times used by GNUnet, in microseconds.
uint64_t abs_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?

◆ DNS_LOOKUP_TIMEOUT

#define DNS_LOOKUP_TIMEOUT
Value:

Default timeout for DNS lookups.

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

◆ DHT_GNS_REPLICATION_LEVEL

#define DHT_GNS_REPLICATION_LEVEL   10

DHT replication level.

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

Function Documentation

◆ translate_dot_plus()

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

Expands a name ending in .

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

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

484{
485 char *ret;
486 size_t s_len = strlen (name);
487
488 if (0 != strcmp (&name[s_len - 2],
489 ".+"))
490 return name; /* did not end in ".+" */
493 "%.*s.%s",
494 (int) (s_len - 2),
495 name,
499 return ret;
500}

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

Referenced by handle_gns_resolution_result(), and recursive_gns2dns_resolution().

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

◆ GNS_resolver_lookup_cancel_()

static void GNS_resolver_lookup_cancel_ ( void *  cls)
static

Wrapper around GNS_resolver_lookup_cancel() as a task.

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

Parameters
clsthe struct GNS_ResolverHandle

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

511{
512 struct GNS_ResolverHandle *rh = cls;
513
514 rh->task_id = NULL;
516}

References GNS_resolver_lookup_cancel(), and GNS_ResolverHandle::task_id.

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

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

◆ fail_resolution()

static void fail_resolution ( struct GNS_ResolverHandle rh)
static

Function called to asynchronously fail a resolution.

Parameters
rhthe resolution to fail

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

526{
527 rh->proc (rh->proc_cls,
528 0,
529 NULL);
530 GNUNET_assert (NULL == rh->task_id);
532 rh);
533}

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

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

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

◆ timeout_resolution()

static void timeout_resolution ( void *  cls)
static

Function called when a resolution times out.

Parameters
clsthe struct GNS_ResolverHandle

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

543{
544 struct GNS_ResolverHandle *rh = cls;
545
546 rh->task_id = NULL;
547 fail_resolution (rh);
548}

References fail_resolution(), and GNS_ResolverHandle::task_id.

Referenced by recursive_dns_resolution().

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

◆ resolver_getprotobyname()

static int resolver_getprotobyname ( const char *  name)
static

Function called to receive the protocol number for a service.

Parameters
namename of the protocol

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

558{
559 struct protoent *pe = getprotobyname (name);
560 if (pe == NULL)
561 {
563 }
564 return pe->p_proto;
565}

References GNUNET_GNS_protocol_name_to_number(), and name.

Referenced by resolver_lookup_get_next_label().

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

◆ resolver_getservbyname()

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

Function called to receive the port number for a service.

Parameters
namename of the service
protoname of the protocol

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

576{
577 struct servent *se = getservbyname (name, proto);
578 if (se == NULL)
579 {
581 }
582 return se->s_port;
583}

References GNUNET_GNS_service_port_name_to_number(), name, and proto.

Referenced by resolver_lookup_get_next_label().

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

◆ resolver_lookup_get_next_label()

static char * resolver_lookup_get_next_label ( struct GNS_ResolverHandle rh)
static

Get the next, rightmost label from the name that we are trying to resolve, and update the resolution position accordingly.

Labels usually consist of up to 63 characters without a period ("."); however, we use a special convention to support resource records where the domain name includes a label starting with '_'. The syntax (see RFC 8552) here is "someLabel._Label.Name" and in this special case we include the "someLabel._Label" in the rightmost label. Thus, for "_443._tcp.foo.bar" we first return the label "bar" and then the label "_443._tcp.foo". The special case is detected by the presence of one label beginning with an underscore. The rightmost label beginning with an underscore, is combined with the label to its right (and the "." is preserved). If the label is in the syntax of "_PORT._PROTOCOL" (e.g. "_443._tcp") we also extract the port and protocol. In this implementation, the more specific case is handled first.

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

Do not advance a label. This seems to be a name only consisting of a prefix. Indicating a BOX record (_443,_tcp) Or some version of an SBOX record (HEX,_smimeacert) Which means, it is a BOX/SBOX under the empty label. leaving name_resolution_pos as is and returning empty label.

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

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

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

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

References _, GNUNET_ERROR_TYPE_WARNING, GNUNET_free, GNUNET_GNS_EMPTY_LABEL_AT, GNUNET_log, GNUNET_strndup, memrchr, GNS_ResolverHandle::name, GNS_ResolverHandle::name_resolution_pos, GNS_ResolverHandle::prefix, GNS_ResolverHandle::protocol, resolver_getprotobyname(), resolver_getservbyname(), ret, rp, service, and GNS_ResolverHandle::service.

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

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

◆ transmit_lookup_dns_result()

static void transmit_lookup_dns_result ( struct GNS_ResolverHandle rh)
static

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

Parameters
rhresolution process that has culminated in a result

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

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

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

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

Referenced by handle_dns_result().

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

◆ add_dns_result()

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

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

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

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

801{
802 struct DnsResult *res;
803
804 res = GNUNET_malloc (sizeof(struct DnsResult) + data_size);
805 res->expiration_time = expiration_time;
806 res->data_size = data_size;
807 res->record_type = record_type;
808 res->data = &res[1];
809 GNUNET_memcpy (&res[1],
810 data,
811 data_size);
813 rh->dns_result_tail,
814 res);
815}

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

Referenced by dns_result_parser(), and handle_dns_result().

Here is the caller graph for this function:

◆ handle_dns_result()

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

We had to do a DNS lookup.

Convert the result (if any) and return it.

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

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

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

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

2841{
2842 struct GNS_ResolverHandle *rh = cls;
2843
2844 rh->task_id = NULL;
2845 if (rh->loop_threshold < rh->loop_limiter++)
2846 {
2848 "Encountered unbounded recursion resolving `%s'\n",
2849 rh->name);
2850 fail_resolution (rh);
2851 return;
2852 }
2853 if (GNUNET_YES == rh->ac_tail->gns_authority)
2855 else
2857}

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

2862{
2863 struct GNS_ResolverHandle *rh = cls;
2864 struct AuthorityChain *ac;
2865 struct in_addr v4;
2866 struct in6_addr v6;
2867
2868 rh->task_id = NULL;
2869 if (1 == inet_pton (AF_INET,
2870 rh->name,
2871 &v4))
2872 {
2873 /* name is IPv4 address, pretend it's an A record */
2875
2876 rd.data = &v4;
2877 rd.data_size = sizeof(v4);
2878 rd.expiration_time = UINT64_MAX;
2880 rd.flags = 0;
2881 rh->proc (rh->proc_cls,
2882 1,
2883 &rd);
2884 GNUNET_assert (NULL == rh->task_id);
2886 rh);
2887 return;
2888 }
2889 if (1 == inet_pton (AF_INET6,
2890 rh->name,
2891 &v6))
2892 {
2893 /* name is IPv6 address, pretend it's an AAAA record */
2895
2896 rd.data = &v6;
2897 rd.data_size = sizeof(v6);
2898 rd.expiration_time = UINT64_MAX;
2900 rd.flags = 0;
2901 rh->proc (rh->proc_cls,
2902 1,
2903 &rd);
2904 GNUNET_assert (NULL == rh->task_id);
2906 rh);
2907 return;
2908 }
2909
2910 ac = GNUNET_new (struct AuthorityChain);
2911 ac->rh = rh;
2913 if (NULL == ac->label)
2914 /* name was just the "TLD", so we default to label
2915 #GNUNET_GNS_EMPTY_LABEL_AT */
2920 rh->ac_tail,
2921 ac);
2923 rh);
2924}

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

Referenced by GNS_resolver_lookup(), and recursive_gns2dns_resolution().

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

◆ dns_result_parser()

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

Function called with the result of a DNS resolution.

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

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

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

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

1196{
1197 struct AuthorityChain *ac;
1198 struct GNUNET_DNSPARSER_Query *query;
1199 struct GNUNET_DNSPARSER_Packet *p;
1200 char *dns_request;
1201 size_t dns_request_length;
1202 int ret;
1203
1204 ac = rh->ac_tail;
1205 GNUNET_assert (NULL != ac);
1207 "Starting DNS lookup for `%s'\n",
1208 ac->label);
1210 query = GNUNET_new (struct GNUNET_DNSPARSER_Query);
1211 query->name = GNUNET_strdup (ac->label);
1212 query->type = rh->record_type;
1215 p->queries = query;
1216 p->num_queries = 1;
1218 UINT16_MAX);
1219 p->flags.opcode = GNUNET_TUN_DNS_OPCODE_QUERY;
1220 p->flags.recursion_desired = 1;
1222 1024,
1223 &dns_request,
1224 &dns_request_length);
1225 if (GNUNET_OK != ret)
1226 {
1227 GNUNET_break (0);
1228 rh->proc (rh->proc_cls,
1229 0,
1230 NULL);
1231 GNUNET_assert (NULL == rh->task_id);
1233 rh);
1234 }
1235 else
1236 {
1237 rh->original_dns_id = p->id;
1239 GNUNET_assert (NULL == rh->dns_request);
1240 if (IDNA_SUCCESS != idna_to_unicode_8z8z (ac->label,
1241 &rh->leho,
1242 IDNA_ALLOW_UNASSIGNED))
1243 {
1244 GNUNET_break (0);
1245 rh->proc (rh->proc_cls,
1246 0,
1247 NULL);
1248 GNUNET_assert (NULL == rh->task_id);
1250 rh);
1251 }
1254 dns_request,
1255 dns_request_length,
1257 rh);
1260 rh);
1261 }
1262 if (GNUNET_SYSERR != ret)
1263 GNUNET_free (dns_request);
1265}

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

Referenced by recursive_resolution().

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

◆ handle_gns_redirect_result()

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

We encountered a REDIRECT record during our resolution.

Merge it into our chain.

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

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

1279{
1280 size_t nlen;
1281 char *res;
1282 const char *tld;
1283 struct AuthorityChain *ac;
1284 int af;
1285 struct GNUNET_CRYPTO_PublicKey zone;
1286
1288 "Handling GNS REDIRECT result `%s'\n",
1289 rname);
1290 nlen = strlen (rname);
1291 tld = GNS_get_tld (rname);
1292 if (0 == strcmp ("+", tld))
1293 {
1294 /* REDIRECT resolution continues relative to current domain */
1295 if (0 == rh->name_resolution_pos)
1296 {
1297 res = GNUNET_strndup (rname, nlen - 2);
1298 rh->name_resolution_pos = nlen - 2;
1299 }
1300 else
1301 {
1303 "%.*s.%.*s",
1304 (int) rh->name_resolution_pos,
1305 rh->name,
1306 (int) (nlen - 2),
1307 rname);
1308 rh->name_resolution_pos = strlen (res);
1309 }
1310 GNUNET_free (rh->name);
1311 rh->name = res;
1312 ac = GNUNET_new (struct AuthorityChain);
1313 ac->rh = rh;
1318 /* add AC to tail */
1320 rh->ac_tail,
1321 ac);
1323 rh);
1324 return;
1325 }
1326 if (GNUNET_OK == GNUNET_GNSRECORD_zkey_to_pkey (tld, &zone))
1327 {
1328 /* REDIRECT resolution continues relative to current domain */
1329 if (0 == rh->name_resolution_pos)
1330 {
1332 "%.*s",
1333 (int) (strlen (rname) - (strlen (tld) + 1)),
1334 rname);
1335 }
1336 else
1337 {
1339 "%.*s.%.*s",
1340 (int) rh->name_resolution_pos,
1341 rh->name,
1342 (int) (strlen (rname) - (strlen (tld) + 1)),
1343 rname);
1344 }
1345 rh->name_resolution_pos = strlen (res);
1346 GNUNET_free (rh->name);
1347 rh->name = res;
1348 ac = GNUNET_new (struct AuthorityChain);
1349 ac->rh = rh;
1351 ac->authority_info.gns_authority = zone;
1353 /* add AC to tail */
1355 rh->ac_tail,
1356 ac);
1358 rh);
1359 return;
1360 }
1361
1363 "Got REDIRECT `%s' from GNS for `%s'\n",
1364 rname,
1365 rh->name);
1366 if (NULL != rh->std_resolve)
1367 {
1369 "Multiple REDIRECT results from GNS resolving `%s'! Not really allowed...\n",
1370 rh->name);
1372 }
1373 /* name is absolute, go to DNS */
1374 GNUNET_free (rh->name);
1375 rh->name = GNUNET_strdup (rname);
1376 rh->name_resolution_pos = strlen (rh->name);
1377 switch (rh->record_type)
1378 {
1380 af = AF_INET;
1381 break;
1382
1384 af = AF_INET6;
1385 break;
1386
1387 default:
1388 af = AF_UNSPEC;
1389 break;
1390 }
1392 "Doing standard DNS lookup for `%s'\n",
1393 rh->name);
1394
1396 af,
1399 rh);
1400}

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

1414{
1415 int af;
1416
1417 GNUNET_free (rh->name);
1418 rh->name = GNUNET_strdup (cname);
1419 rh->name_resolution_pos = strlen (rh->name);
1420 switch (rh->record_type)
1421 {
1423 af = AF_INET;
1424 break;
1425
1427 af = AF_INET6;
1428 break;
1429
1430 default:
1431 af = AF_UNSPEC;
1432 break;
1433 }
1435 "Doing standard DNS lookup for `%s'\n",
1436 rh->name);
1437
1439 af,
1442 rh);
1443}

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

1950{
1951 struct GNS_ResolverHandle *rh = cls;
1952 char *cname;
1953 char scratch[UINT16_MAX];
1954 size_t scratch_off;
1955 size_t scratch_start;
1956 size_t off;
1957 struct GNUNET_GNSRECORD_Data rd_new[rd_count];
1958 unsigned int rd_off;
1959
1961 "Resolution succeeded for `%s' in zone %s, got %u records\n",
1962 rh->ac_tail->label,
1964 rd_count);
1965 if (0 == rd_count)
1966 {
1968 _ ("GNS lookup failed (zero records found for `%s')\n"),
1969 rh->name);
1970 fail_resolution (rh);
1971 return;
1972 }
1973
1974 if (0 == rh->name_resolution_pos)
1975 {
1976 /* top-level match, are we done yet? */
1977 if ((rd_count > 0) &&
1980 {
1981 off = 0;
1983 rd[0].data_size,
1984 &off);
1985 if ((NULL == cname) ||
1986 (off != rd[0].data_size))
1987 {
1988 GNUNET_break_op (0);
1989 GNUNET_free (cname);
1990 fail_resolution (rh);
1991 return;
1992 }
1994 cname);
1995 GNUNET_free (cname);
1996 return;
1997 }
1998 if ((rd_count > 0) &&
2001 {
2003 rd[0].data);
2004 return;
2005 }
2006
2007
2008 /* If A/AAAA was requested,
2009 * but we got a GNS2DNS record */
2010 if ((GNUNET_DNSPARSER_TYPE_A == rh->record_type) ||
2012 {
2013 for (unsigned int i = 0; i < rd_count; i++)
2014 {
2015 switch (rd[i].record_type)
2016 {
2018 {
2019 /* delegation to DNS */
2021 "Found GNS2DNS record, delegating to DNS!\n");
2022 if (GNUNET_OK ==
2024 rd_count,
2025 rd))
2026 return;
2027 else
2028 goto fail;
2029 }
2030
2031 default:
2032 break;
2033 } /* end: switch */
2034 } /* end: for rd */
2035 } /* end: name_resolution_pos */
2036 /* convert relative names in record values to absolute names,
2037 using 'scratch' array for memory allocations */
2038 scratch_off = 0;
2039 rd_off = 0;
2040 for (unsigned int i = 0; i < rd_count; i++)
2041 {
2042 GNUNET_assert (rd_off <= i);
2043 if ((((0 != rh->protocol) &&
2044 (0 != rh->service)) || (NULL != rh->prefix)) &&
2049 continue;
2050 /* we _only_ care about boxed records */
2051
2052 GNUNET_assert (rd_off < rd_count);
2053 rd_new[rd_off] = rd[i];
2054 /* Check if the embedded name(s) end in "+", and if so,
2055 replace the "+" with the zone at "ac_tail", changing the name
2056 to a ".ZONEKEY". The name is allocated on the 'scratch' array,
2057 so we can free it afterwards. */
2058 switch (rd[i].record_type)
2059 {
2061 {
2062 char *rname;
2063 rname = GNUNET_strndup (rd[i].data, rd[i].data_size);
2064 rname = translate_dot_plus (rh, rname);
2065 GNUNET_break (NULL != rname);
2066 scratch_start = scratch_off;
2067 memcpy (&scratch[scratch_start], rname, strlen (rname) + 1);
2068 scratch_off += strlen (rname) + 1;
2069 GNUNET_assert (rd_off < rd_count);
2070 rd_new[rd_off].data = &scratch[scratch_start];
2071 rd_new[rd_off].data_size = scratch_off - scratch_start;
2072 rd_off++;
2073 GNUNET_free (rname);
2074 }
2075 break;
2076
2078 {
2079 char *cname_tmp;
2080
2081 off = 0;
2082 cname_tmp = GNUNET_DNSPARSER_parse_name (rd[i].data,
2083 rd[i].data_size,
2084 &off);
2085 if ((NULL == cname_tmp) ||
2086 (off != rd[i].data_size))
2087 {
2088 GNUNET_break_op (0); /* record not well-formed */
2089 }
2090 else
2091 {
2092 cname_tmp = translate_dot_plus (rh, cname_tmp);
2093 GNUNET_break (NULL != cname_tmp);
2094 scratch_start = scratch_off;
2095 if (GNUNET_OK !=
2097 sizeof(scratch),
2098 &scratch_off,
2099 cname_tmp))
2100 {
2101 GNUNET_break (0);
2102 }
2103 else
2104 {
2105 GNUNET_assert (rd_off < rd_count);
2106 rd_new[rd_off].data = &scratch[scratch_start];
2107 rd_new[rd_off].data_size = scratch_off - scratch_start;
2108 rd_off++;
2109 }
2110 }
2111 GNUNET_free (cname_tmp);
2112 }
2113 break;
2114
2116 {
2117 struct GNUNET_DNSPARSER_SoaRecord *soa;
2118
2119 off = 0;
2121 rd[i].data_size,
2122 &off);
2123 if ((NULL == soa) ||
2124 (off != rd[i].data_size))
2125 {
2126 GNUNET_break_op (0); /* record not well-formed */
2127 }
2128 else
2129 {
2130 soa->mname = translate_dot_plus (rh, soa->mname);
2131 soa->rname = translate_dot_plus (rh, soa->rname);
2132 scratch_start = scratch_off;
2133 if (GNUNET_OK !=
2135 sizeof(scratch),
2136 &scratch_off,
2137 soa))
2138 {
2139 GNUNET_break (0);
2140 }
2141 else
2142 {
2143 GNUNET_assert (rd_off < rd_count);
2144 rd_new[rd_off].data = &scratch[scratch_start];
2145 rd_new[rd_off].data_size = scratch_off - scratch_start;
2146 rd_off++;
2147 }
2148 }
2149 if (NULL != soa)
2151 }
2152 break;
2153
2155 {
2156 struct GNUNET_DNSPARSER_MxRecord *mx;
2157
2158 off = 0;
2160 rd[i].data_size,
2161 &off);
2162 if ((NULL == mx) ||
2163 (off != rd[i].data_size))
2164 {
2165 GNUNET_break_op (0); /* record not well-formed */
2166 }
2167 else
2168 {
2169 mx->mxhost = translate_dot_plus (rh, mx->mxhost);
2170 scratch_start = scratch_off;
2171 if (GNUNET_OK !=
2173 sizeof(scratch),
2174 &scratch_off,
2175 mx))
2176 {
2177 GNUNET_break (0);
2178 }
2179 else
2180 {
2181 GNUNET_assert (rd_off < rd_count);
2182 rd_new[rd_off].data = &scratch[scratch_start];
2183 rd_new[rd_off].data_size = scratch_off - scratch_start;
2184 rd_off++;
2185 }
2186 }
2187 if (NULL != mx)
2189 }
2190 break;
2191
2193 {
2194 struct GNUNET_DNSPARSER_SrvRecord *srv;
2195
2196 off = 0;
2198 rd[i].data_size,
2199 &off);
2200 if ((NULL == srv) ||
2201 (off != rd[i].data_size))
2202 {
2203 GNUNET_break_op (0); /* record not well-formed */
2204 }
2205 else
2206 {
2207 srv->target = translate_dot_plus (rh, srv->target);
2208 scratch_start = scratch_off;
2209 if (GNUNET_OK !=
2211 sizeof(scratch),
2212 &scratch_off,
2213 srv))
2214 {
2215 GNUNET_break (0);
2216 }
2217 else
2218 {
2219 GNUNET_assert (rd_off < rd_count);
2220 rd_new[rd_off].data = &scratch[scratch_start];
2221 rd_new[rd_off].data_size = scratch_off - scratch_start;
2222 rd_off++;
2223 }
2224 }
2225 if (NULL != srv)
2227 }
2228 break;
2229
2231 {
2233
2234 off = 0;
2236 rd[i].data_size,
2237 &off);
2238 if ((NULL == uri) ||
2239 (off != rd[i].data_size))
2240 {
2242 _ ("Failed to deserialize URI record with target\n"));
2243 GNUNET_break_op (0); /* record not well-formed */
2244 }
2245 else
2246 {
2247 scratch_start = scratch_off;
2248 if (GNUNET_OK !=
2250 sizeof(scratch),
2251 &scratch_off,
2252 uri))
2253 {
2254 GNUNET_break (0);
2255 }
2256 else
2257 {
2258 GNUNET_assert (rd_off < rd_count);
2259 rd_new[rd_off].data = &scratch[scratch_start];
2260 rd_new[rd_off].data_size = scratch_off - scratch_start;
2261 rd_off++;
2262 }
2263 }
2264 if (NULL != uri)
2266 }
2267 break;
2268
2271 {
2273 if (rd[i].data_size < sizeof(uint32_t))
2274 {
2275 GNUNET_break_op (0);
2276 break;
2277 }
2278 if (GNUNET_OK !=
2280 rd[i].data_size,
2281 rd[i].record_type,
2282 &pubkey))
2283 {
2284 GNUNET_break_op (0);
2285 break;
2286 }
2287 rd_off++;
2288 if (rd[i].record_type != rh->record_type)
2289 {
2290 /* try to resolve "@" */
2291 struct AuthorityChain *ac;
2292
2293 ac = GNUNET_new (struct AuthorityChain);
2294 ac->rh = rh;
2299 rh->ac_tail,
2300 ac);
2302 rh);
2303 return;
2304 }
2305 }
2306 break;
2307
2309 {
2310 /* delegation to DNS */
2312 {
2313 rd_off++;
2314 break; /* do not follow to DNS, we wanted the GNS2DNS record! */
2315 }
2317 "Found GNS2DNS record, delegating to DNS!\n");
2318 if (GNUNET_OK ==
2320 rd_count,
2321 rd))
2322 return;
2323 else
2324 goto fail;
2325 }
2326
2328 {
2329 /* unbox SRV/TLSA records if a specific one was requested */
2330 if ((0 != rh->protocol) &&
2331 (0 != rh->service) &&
2332 (rd[i].data_size >= sizeof(struct GNUNET_GNSRECORD_BoxRecord)))
2333 {
2334 const struct GNUNET_GNSRECORD_BoxRecord *box;
2335
2336 box = rd[i].data;
2338 "Got BOX record, checking if parameters match... %u/%u vs %u/%u\n",
2339 ntohs (box->protocol), ntohs (box->service),
2340 rh->protocol, rh->service);
2341 if ((ntohs (box->protocol) == rh->protocol) &&
2342 (ntohs (box->service) == rh->service))
2343 {
2344 /* Box matches, unbox! */
2345 GNUNET_assert (rd_off < rd_count);
2346 rd_new[rd_off].record_type = ntohl (box->record_type);
2347 rd_new[rd_off].data_size -= sizeof(struct
2349 rd_new[rd_off].data = &box[1];
2350 rd_off++;
2351 }
2352 }
2353 else
2354 {
2355 /* no specific protocol/service specified, preserve all BOX
2356 records (for modern, GNS-enabled applications) */
2357 rd_off++;
2358 }
2359 break;
2360 }
2362 {
2363 /* unbox SBOX records if a specific one was requested */
2364 if ((rh->prefix != NULL) &&
2365 (rd[i].data_size >= sizeof(struct GNUNET_GNSRECORD_SBoxRecord)))
2366 {
2367 const struct GNUNET_GNSRECORD_SBoxRecord *box;
2368 const char *prefix;
2369 size_t prefix_len;
2370
2371 box = rd[i].data;
2372 prefix = rd[i].data + sizeof(struct GNUNET_GNSRECORD_SBoxRecord);
2373 prefix_len = strnlen (
2374 prefix,
2375 rd[i].data_size - sizeof(struct GNUNET_GNSRECORD_SBoxRecord)) + 1;
2376 if (prefix_len - 1 >= rd[i].data_size - sizeof(struct
2378 {
2380 "SBOX record with invalid prefix length, maybe not null-terminated\n");
2381 continue;
2382 }
2384 "Got SBOX record, checking if prefixes match... %s vs %s\n",
2385 prefix, rh->prefix);
2386 if (strcmp (rh->prefix, prefix) == 0)
2387 {
2388 /* Box matches, unbox! */
2389 GNUNET_assert (rd_off < rd_count);
2390 rd_new[rd_off].record_type = ntohl (box->record_type);
2391 rd_new[rd_off].data_size -= sizeof(struct
2393 + prefix_len;
2394 rd_new[rd_off].data = rd[i].data
2395 + sizeof(struct GNUNET_GNSRECORD_SBoxRecord)
2396 + prefix_len;
2397 rd_off++;
2398 }
2399 }
2400 else
2401 {
2403 _ (
2404 "GNS no specific protocol/service specified, preserve all SBOX `%s')\n"),
2405 rh->name);
2406 /* no specific protocol/service specified, preserve all SBOX
2407 records (for modern, GNS-enabled applications) */
2408 rd_off++;
2409 }
2410 break;
2411 }
2412 default:
2413 rd_off++;
2414 break;
2415 } /* end: switch */
2416 } /* end: for rd_count */
2417
2418 GNUNET_free (rh->prefix);
2419 rh->prefix = NULL;
2420
2421 /* yes, we are done, return result */
2423 "Returning GNS response for `%s' with %u answers\n",
2424 rh->ac_tail->label,
2425 rd_off);
2426 rh->proc (rh->proc_cls,
2427 rd_off,
2428 rd_new);
2430 rh);
2431 return;
2432 }
2433
2434 switch (rd[0].record_type)
2435 {
2437 GNUNET_break_op (1 == rd_count); /* REDIRECT should be unique */
2439 &rd[0]);
2440 return;
2441
2443 GNUNET_break_op (1 == rd_count); /* CNAME should be unique */
2445 &rd[0]);
2446 return;
2447
2450 GNUNET_break_op (1 == rd_count); /* PKEY should be unique */
2452 &rd[0]);
2453 return;
2454
2456 if (GNUNET_OK ==
2458 rd_count,
2459 rd))
2460 return;
2461 break;
2462 default:
2464 return;
2466 _ ("Unable to process critical delegation record\n"));
2467 break;
2468 }
2469fail:
2471 _ ("GNS lookup recursion failed (no delegation record found)\n"));
2472 fail_resolution (rh);
2473}

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

1468{
1469 struct GNS_ResolverHandle *rh = ac->rh;
1470
1471 if ((NULL != ac->authority_info.dns_authority.gp_head) &&
1473 return; /* more pending and none found yet */
1475 {
1477 "Failed to resolve DNS server for `%s' in GNS2DNS resolution\n",
1479 fail_resolution (rh);
1480 return;
1481 }
1483 return; /* already running, do not launch again! */
1484 /* recurse */
1487 "Will continue resolution using DNS to resolve `%s'\n",
1488 ac->label);
1489 GNUNET_assert (NULL == rh->task_id);
1491 rh);
1492}

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

1507{
1508 struct Gns2DnsPending *gp = cls;
1509 struct AuthorityChain *ac = gp->ac;
1510
1513 gp);
1514 /* enable cleanup of 'rh' handle that automatically comes after we return,
1515 and which expects 'rh' to be in the #rlh_head DLL. */
1516 if (NULL != gp->rh)
1517 {
1519 rlh_tail,
1520 gp->rh);
1521 gp->rh = NULL;
1522 }
1523 GNUNET_free (gp);
1525 "Received %u results for IP address of DNS server for GNS2DNS transition\n",
1526 rd_count);
1527 /* find suitable A/AAAA record */
1528 for (unsigned int j = 0; j < rd_count; j++)
1529 {
1530 switch (rd[j].record_type)
1531 {
1533 {
1534 struct sockaddr_in v4;
1535
1536 if (sizeof(struct in_addr) != rd[j].data_size)
1537 {
1538 GNUNET_break_op (0);
1539 continue;
1540 }
1541 memset (&v4,
1542 0,
1543 sizeof(v4));
1544 v4.sin_family = AF_INET;
1545 v4.sin_port = htons (53);
1546#if HAVE_SOCKADDR_IN_SIN_LEN
1547 v4.sin_len = (u_char) sizeof(v4);
1548#endif
1549 GNUNET_memcpy (&v4.sin_addr,
1550 rd[j].data,
1551 sizeof(struct in_addr));
1552 if (GNUNET_OK ==
1555 (const struct sockaddr *) &v4))
1557 break;
1558 }
1559
1561 {
1562 struct sockaddr_in6 v6;
1563
1564 if (sizeof(struct in6_addr) != rd[j].data_size)
1565 {
1566 GNUNET_break_op (0);
1567 continue;
1568 }
1569 /* FIXME: might want to check if we support IPv6 here,
1570 and otherwise skip this one and hope we find another */
1571 memset (&v6,
1572 0,
1573 sizeof(v6));
1574 v6.sin6_family = AF_INET6;
1575 v6.sin6_port = htons (53);
1576#if HAVE_SOCKADDR_IN_SIN_LEN
1577 v6.sin6_len = (u_char) sizeof(v6);
1578#endif
1579 GNUNET_memcpy (&v6.sin6_addr,
1580 rd[j].data,
1581 sizeof(struct in6_addr));
1582 if (GNUNET_OK ==
1585 (const struct sockaddr *) &v6))
1587 break;
1588 }
1589
1590 default:
1591 break;
1592 }
1593 }
1595}

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

1609{
1610 struct Gns2DnsPending *gp = cls;
1611 struct AuthorityChain *ac = gp->ac;
1612 struct sockaddr_storage ss;
1613 struct sockaddr_in *v4;
1614 struct sockaddr_in6 *v6;
1615
1616 if (NULL == addr)
1617 {
1618 /* DNS resolution finished */
1619 if (0 == gp->num_results)
1621 "Failed to use DNS to resolve name of DNS resolver\n");
1624 gp);
1625 GNUNET_free (gp);
1627 return;
1628 }
1629 GNUNET_memcpy (&ss,
1630 addr,
1631 addrlen);
1632 switch (ss.ss_family)
1633 {
1634 case AF_INET:
1635 v4 = (struct sockaddr_in *) &ss;
1636 v4->sin_port = htons (53);
1637 gp->num_results++;
1638 break;
1639
1640 case AF_INET6:
1641 v6 = (struct sockaddr_in6 *) &ss;
1642 v6->sin6_port = htons (53);
1643 gp->num_results++;
1644 break;
1645
1646 default:
1648 "Unsupported AF %d\n",
1649 ss.ss_family);
1650 return;
1651 }
1652 if (GNUNET_OK ==
1654 (struct sockaddr *) &ss))
1656}

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

1668{
1670 rd->data);
1671}

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

1683{
1684 char *cname;
1685 size_t off;
1686
1687 off = 0;
1689 rd->data_size,
1690 &off);
1691 if ((NULL == cname) ||
1692 (off != rd->data_size))
1693 {
1694 GNUNET_break_op (0); /* record not well-formed */
1695 GNUNET_free (cname);
1696 fail_resolution (rh);
1697 return;
1698 }
1700 cname);
1701 GNUNET_free (cname);
1702}

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

1714{
1715 struct AuthorityChain *ac;
1716 struct GNUNET_CRYPTO_PublicKey auth;
1717
1718 /* delegation to another zone */
1720 rd->data_size,
1721 rd->record_type,
1722 &auth))
1723 {
1724 GNUNET_break_op (0);
1725 fail_resolution (rh);
1726 return;
1727 }
1728 /* expand authority chain */
1729 ac = GNUNET_new (struct AuthorityChain);
1730 ac->rh = rh;
1732 ac->authority_info.gns_authority = auth;
1734 /* add AC to tail */
1736 rh->ac_tail,
1737 ac);
1738 /* recurse */
1740 rh);
1741}

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

1758{
1759 struct AuthorityChain *ac;
1760 const char *tld;
1761 char *ns;
1762
1763 ns = NULL;
1764 /* expand authority chain */
1765 ac = GNUNET_new (struct AuthorityChain);
1766 ac->rh = rh;
1768
1769 for (unsigned int i = 0; i < rd_count; i++)
1770 {
1771 char *ip;
1772 char *n;
1773 struct Gns2DnsPending *gp;
1774 struct GNUNET_CRYPTO_PublicKey zone;
1775 struct sockaddr_in v4;
1776 struct sockaddr_in6 v6;
1777
1778 if (GNUNET_GNSRECORD_TYPE_GNS2DNS != rd[i].record_type)
1779 {
1784 GNUNET_free (ns);
1785 GNUNET_free (ac);
1786 return GNUNET_SYSERR;
1787 }
1788 n = GNUNET_strdup ((const char*) rd[i].data);
1789 if (strlen (n) + 1 >= rd[i].data_size)
1790 {
1791 GNUNET_break_op (0);
1792 continue;
1793 }
1794 ip = GNUNET_strdup (rd[i].data + strlen (n) + 1);
1795 /* resolve 'ip' to determine the IP(s) of the DNS
1796 resolver to use for lookup of 'ns' */
1797 if (NULL != ns)
1798 {
1799 if (0 != strcasecmp (ns,
1800 n))
1801 {
1802 /* NS values must all be the same for all GNS2DNS records,
1803 anything else leads to insanity */
1804 GNUNET_break_op (0);
1805 GNUNET_free (n);
1806 GNUNET_free (ip);
1807 continue;
1808 }
1809 GNUNET_free (n);
1810 }
1811 else
1812 {
1813 ns = n;
1814 }
1815
1816 /* check if 'ip' is already an IPv4/IPv6 address */
1817 if ((1 == inet_pton (AF_INET,
1818 ip,
1819 &v4)) ||
1820 (1 == inet_pton (AF_INET6,
1821 ip,
1822 &v6)))
1823 {
1827 ip));
1829 GNUNET_free (ip);
1830 continue;
1831 }
1832 tld = GNS_get_tld (ip);
1833 if ((0 != strcmp (tld, "+")) &&
1834 (GNUNET_OK != GNUNET_GNSRECORD_zkey_to_pkey (tld, &zone)))
1835 {
1836 /* 'ip' is a DNS name */
1837 gp = GNUNET_new (struct Gns2DnsPending);
1838 gp->ac = ac;
1841 gp);
1843 AF_UNSPEC,
1846 gp);
1847 GNUNET_free (ip);
1848 continue;
1849 }
1850 /* 'ip' should be a GNS name */
1851 gp = GNUNET_new (struct Gns2DnsPending);
1852 gp->ac = ac;
1855 gp);
1856 gp->rh = GNUNET_new (struct GNS_ResolverHandle);
1857 if (0 == strcmp (tld, "+"))
1858 {
1859 ip = translate_dot_plus (rh,
1860 ip);
1861 tld = GNS_get_tld (ip);
1862 if (GNUNET_OK !=
1864 &zone))
1865 {
1866 GNUNET_break_op (0);
1867 GNUNET_free (ip);
1868 continue;
1869 }
1870 }
1871 gp->rh->authority_zone = zone;
1873 "Resolving `%s' to determine IP address of DNS server for GNS2DNS transition for `%s'\n",
1874 ip,
1875 ns);
1876 gp->rh->name = ip;
1877 gp->rh->name_resolution_pos = strlen (ip) - strlen (tld) - 1;
1879 gp->rh->proc_cls = gp;
1882 gp->rh->loop_limiter = rh->loop_limiter + 1;
1883 gp->rh->loop_threshold = rh->loop_threshold;
1884 gp->rh->task_id
1886 gp->rh);
1887 } /* end 'for all records' */
1888
1889 if (NULL == ns)
1890 {
1891 /* not a single GNS2DNS record found */
1892 GNUNET_free (ac);
1893 return GNUNET_SYSERR;
1894 }
1896 strcpy (ac->authority_info.dns_authority.name,
1897 ns);
1898 /* for DNS recursion, the label is the full DNS name,
1899 created from the remainder of the GNS name and the
1900 name in the NS record */
1901 GNUNET_asprintf (&ac->label,
1902 "%.*s%s%s",
1903 (int) rh->name_resolution_pos,
1904 rh->name,
1905 (0 != rh->name_resolution_pos) ? "." : "",
1906 ns);
1907 GNUNET_free (ns);
1908
1909 {
1910 /* the GNS name is UTF-8 and may include multibyte chars.
1911 * We have to convert the combined name to a DNS-compatible IDNA.
1912 */
1913 char *tmp = ac->label;
1914
1915 if (IDNA_SUCCESS != idna_to_ascii_8z (tmp,
1916 &ac->label,
1917 IDNA_ALLOW_UNASSIGNED))
1918 {
1920 _ ("Name `%s' cannot be converted to IDNA."),
1921 tmp);
1922 GNUNET_free (tmp);
1923 GNUNET_free (ac);
1924 return GNUNET_SYSERR;
1925 }
1926 GNUNET_free (tmp);
1927 }
1928
1930 rh->ac_tail,
1931 ac);
1932 if (strlen (ac->label) > GNUNET_DNSPARSER_MAX_NAME_LENGTH)
1933 {
1935 _ ("GNS lookup resulted in DNS name that is too long (`%s')\n"),
1936 ac->label);
1937 GNUNET_free (ac->label);
1938 GNUNET_free (ac);
1939 return GNUNET_SYSERR;
1940 }
1942 return GNUNET_OK;
1943}

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

2488{
2489 struct CacheOps *co = cls;
2490
2491 co->namecache_qe_cache = NULL;
2492 if (GNUNET_OK != success)
2494 _ ("Failed to cache GNS resolution: %s\n"),
2495 emsg);
2497 co_tail,
2498 co);
2499 GNUNET_free (co);
2500}

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

Referenced by handle_dht_response().

Here is the caller graph for this function:

◆ handle_dht_response()

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

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

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

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

2533{
2534 struct GNS_ResolverHandle *rh = cls;
2535 struct AuthorityChain *ac = rh->ac_tail;
2536 const struct GNUNET_GNSRECORD_Block *block;
2537 struct CacheOps *co;
2538
2539 (void) exp;
2540 (void) key;
2541 (void) get_path;
2542 (void) get_path_length;
2543 (void) put_path;
2544 (void) put_path_length;
2545 (void) type;
2547 rh->get_handle = NULL;
2549 rh->dht_heap_node = NULL;
2551 "Handling response from the DHT\n");
2552 if (size < sizeof(struct GNUNET_GNSRECORD_Block))
2553 {
2554 /* how did this pass DHT block validation!? */
2555 GNUNET_break (0);
2556 fail_resolution (rh);
2557 return;
2558 }
2559 block = data;
2561 {
2562 /* how did this pass DHT block validation!? */
2563 GNUNET_break (0);
2564 fail_resolution (rh);
2565 return;
2566 }
2568 "Decrypting DHT block of size %llu for `%s', expires %s\n",
2569 (unsigned long long) GNUNET_GNSRECORD_block_get_size (block),
2570 rh->name,
2572 if (GNUNET_OK !=
2575 ac->label,
2577 rh))
2578 {
2579 GNUNET_break_op (0); /* block was ill-formed */
2580 fail_resolution (rh);
2581 return;
2582 }
2585 rel_value_us)
2586 {
2588 "Received expired block from the DHT, will not cache it.\n");
2589 return;
2590 }
2592 return;
2593 /* Cache well-formed blocks */
2595 "Caching response from the DHT in namecache\n");
2596 co = GNUNET_new (struct CacheOps);
2598 block,
2599 &
2601 co);
2603 co_tail,
2604 co);
2605}

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

Referenced by start_dht_request().

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

◆ start_dht_request()

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

Initiate a DHT query for a set of GNS records.

Parameters
rhresolution handle
querykey to use in the DHT lookup

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

2617{
2618 struct GNS_ResolverHandle *rx;
2619
2620 GNUNET_assert (NULL == rh->get_handle);
2623 query,
2626 NULL, 0,
2627 &handle_dht_response, rh);
2629 rh,
2631 abs_value_us);
2634 {
2635 /* fail longest-standing DHT request */
2637 rx->dht_heap_node = NULL;
2638 GNUNET_assert (NULL != rx);
2639 fail_resolution (rx);
2640 }
2641}

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

Referenced by handle_namecache_block_response(), and recursive_gns_resolution_namecache().

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

◆ handle_gns_namecache_resolution_result()

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

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

Simply calls handle_gns_resolution_result().

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

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

2656{
2657 struct GNS_ResolverHandle *rh = cls;
2658
2659 if (0 == rd_count)
2661 _ ("GNS namecache returned empty result for `%s'\n"),
2662 rh->name);
2664 rd_count,
2665 rd);
2666}

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

2678{
2679 struct GNS_ResolverHandle *rh = cls;
2680 struct AuthorityChain *ac = rh->ac_tail;
2681 const char *label = ac->label;
2682 const struct GNUNET_CRYPTO_PublicKey *auth =
2684 struct GNUNET_HashCode query;
2685
2686 GNUNET_assert (NULL != rh->namecache_qe);
2687 rh->namecache_qe = NULL;
2688 if (NULL == block)
2690 "No block found\n");
2691 else
2693 "Got block with expiration %s\n",
2696 if (((GNUNET_GNS_LO_DEFAULT == rh->options) ||
2698 (ac != rh->ac_head))) &&
2699 ((NULL == block) ||
2702 rel_value_us)))
2703 {
2704 /* namecache knows nothing; try DHT lookup */
2706 label,
2707 &query);
2709 "Starting DHT lookup for `%s' in zone `%s' under key `%s'\n",
2710 ac->label,
2712 GNUNET_h2s (&query));
2713 start_dht_request (rh, &query);
2714 return;
2715 }
2716
2717 if ((NULL == block) ||
2720 rel_value_us))
2721 {
2722 /* DHT not permitted and no local result, fail */
2724 "Resolution failed for `%s' in zone %s (DHT lookup not permitted by configuration)\n",
2725 ac->label,
2727 fail_resolution (rh);
2728 return;
2729 }
2731 "Received result from namecache for label `%s'\n",
2732 ac->label);
2733
2734 if (GNUNET_OK !=
2736 auth,
2737 label,
2739 rh))
2740 {
2741 GNUNET_break_op (0); /* block was ill-formed */
2742 /* try DHT instead */
2744 label,
2745 &query);
2747 "Starting DHT lookup for `%s' in zone `%s' under key `%s'\n",
2748 ac->label,
2750 GNUNET_h2s (&query));
2751 start_dht_request (rh, &query);
2752 return;
2753 }
2754}

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

Referenced by recursive_gns_resolution_namecache().

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

◆ recursive_gns_resolution_namecache()

static void recursive_gns_resolution_namecache ( struct GNS_ResolverHandle rh)
static

Lookup tail of our authority chain in the namecache.

Parameters
rhquery we are processing

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

2764{
2765 struct AuthorityChain *ac = rh->ac_tail;
2766 struct GNUNET_HashCode query;
2767
2769 "Starting GNS resolution for `%s' in zone %s\n",
2770 ac->label,
2773 ac->label,
2774 &query);
2776 {
2777 rh->namecache_qe
2779 &query,
2781 rh);
2782 GNUNET_assert (NULL != rh->namecache_qe);
2783 }
2784 else
2785 {
2787 &query);
2788 }
2789}

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

2801{
2802 struct GNS_ResolverHandle *rh = cls;
2803 struct AuthorityChain *ac = rh->ac_tail;
2804
2805 rh->rev_check = NULL;
2806 if (GNUNET_YES != is_valid)
2807 {
2809 _ ("Zone %s was revoked, resolution fails\n"),
2812 return;
2813 }
2815}

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

2825{
2826 struct AuthorityChain *ac = rh->ac_tail;
2827
2829 "Starting revocation check for zone %s\n",
2834 rh);
2835 GNUNET_assert (NULL != rh->rev_check);
2836}

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

Referenced by recursive_resolution().

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

◆ GNS_resolver_lookup()

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

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

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

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

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

2949{
2950 struct GNS_ResolverHandle *rh;
2951
2953 "Starting lookup for `%s'\n",
2954 name);
2955 rh = GNUNET_new (struct GNS_ResolverHandle);
2957 rlh_tail,
2958 rh);
2959 rh->authority_zone = *zone;
2960 rh->proc = proc;
2961 rh->proc_cls = proc_cls;
2962 rh->options = options;
2964 rh->name = GNUNET_strdup (name);
2965 rh->name_resolution_pos = strlen (name);
2966 rh->loop_threshold = recursion_depth_limit;
2968 rh);
2969 return rh;
2970}

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

2980{
2981 struct DnsResult *dr;
2982 struct AuthorityChain *ac;
2983
2985 rlh_tail,
2986 rh);
2987 if (NULL != rh->dns_request)
2988 {
2990 rh->dns_request = NULL;
2991 }
2992 while (NULL != (ac = rh->ac_head))
2993 {
2995 rh->ac_tail,
2996 ac);
2997 if (GNUNET_NO == ac->gns_authority)
2998 {
2999 struct Gns2DnsPending *gp;
3000
3001 while (NULL != (gp = ac->authority_info.dns_authority.gp_head))
3002 {
3005 gp);
3006 if (NULL != gp->rh)
3007 {
3008 /* rh->g2dc->rh is NOT in the DLL yet, so to enable us
3009 using GNS_resolver_lookup_cancel here, we need to
3010 add it first... */
3012 rlh_tail,
3013 gp->rh);
3014 GNUNET_assert (NULL == gp->rh->task_id);
3017 gp->rh);
3018 gp->rh = NULL;
3019 }
3020 if (NULL != gp->dns_rh)
3021 {
3023 gp->dns_rh = NULL;
3024 }
3025 GNUNET_free (gp);
3026 }
3028 }
3029 GNUNET_free (ac->label);
3030 GNUNET_free (ac);
3031 }
3032 if (NULL != rh->task_id)
3033 {
3035 rh->task_id = NULL;
3036 }
3037 if (NULL != rh->get_handle)
3038 {
3040 rh->get_handle = NULL;
3041 }
3042 if (NULL != rh->dht_heap_node)
3043 {
3045 rh->dht_heap_node = NULL;
3046 }
3047 if (NULL != rh->namecache_qe)
3048 {
3050 rh->namecache_qe = NULL;
3051 }
3052 if (NULL != rh->rev_check)
3053 {
3055 rh->rev_check = NULL;
3056 }
3057 if (NULL != rh->std_resolve)
3058 {
3060 "Canceling standard DNS resolution\n");
3062 rh->std_resolve = NULL;
3063 }
3064 while (NULL != (dr = rh->dns_result_head))
3065 {
3068 dr);
3069 GNUNET_free (dr);
3070 }
3071 if (NULL != rh->prefix)
3072 {
3074 rh->prefix = NULL;
3075 }
3076 GNUNET_free (rh->leho);
3077 GNUNET_free (rh->name);
3078 GNUNET_free (rh);
3079}

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

3098{
3099 cfg = c;
3101 dht_handle = dht;
3104 max_allowed_background_queries = max_bg_queries;
3106 "namecache",
3107 "DISABLE");
3110 "Namecache disabled\n");
3111}

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

3119{
3120 struct GNS_ResolverHandle *rh;
3121 struct CacheOps *co;
3122
3123 /* abort active resolutions */
3124 while (NULL != (rh = rlh_head))
3125 {
3126 rh->proc (rh->proc_cls,
3127 0,
3128 NULL);
3130 }
3131 while (NULL != (co = co_head))
3132 {
3134 co_tail,
3135 co);
3137 GNUNET_free (co);
3138 }
3140 dht_lookup_heap = NULL;
3141 dht_handle = NULL;
3142 namecache_handle = NULL;
3143}

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

Referenced by shutdown_task().

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

Variable Documentation

◆ namecache_handle

struct GNUNET_NAMECACHE_Handle* namecache_handle
static

Our handle to the namecache service.

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

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

◆ dht_handle

struct GNUNET_DHT_Handle* dht_handle
static

Resolver handle to the dht.

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

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

◆ dht_lookup_heap

struct GNUNET_CONTAINER_Heap* dht_lookup_heap
static

Heap for limiting parallel DHT lookups.

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

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

◆ max_allowed_background_queries

unsigned long long max_allowed_background_queries
static

Maximum amount of parallel queries to the DHT.

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

Referenced by GNS_resolver_init(), and start_dht_request().

◆ rlh_head

struct GNS_ResolverHandle* rlh_head
static

Head of resolver lookup list.

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

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

◆ rlh_tail

struct GNS_ResolverHandle* rlh_tail
static

Tail of resolver lookup list.

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

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

◆ co_head

struct CacheOps* co_head
static

Organized in a DLL.

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

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

◆ co_tail

struct CacheOps* co_tail
static

Organized in a DLL.

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

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

◆ disable_cache

int disable_cache
static

◆ cfg

const struct GNUNET_CONFIGURATION_Handle* cfg
static

Global configuration.

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

Referenced by GNS_resolver_init(), and recursive_gns_resolution_revocation().