GNUnet debian-0.24.3-29-g453fda2cf
 
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 size_t buf_off;
993 size_t buf_start;
994
995 buf_off = 0;
996 skip = 0;
997 memset (rd,
998 0,
999 sizeof(rd));
1000 for (unsigned int i = 0; i < rd_count; i++)
1001 {
1002 if (i < p->num_answers)
1003 rec = &p->answers[i];
1004 else if (i < p->num_answers + p->num_authority_records)
1005 rec = &p->authority_records[i - p->num_answers];
1006 else
1007 rec = &p->additional_records[i - p->num_answers
1008 - p->num_authority_records];
1009 /* As we copied the full DNS name to 'rh->ac_tail->label', this
1010 should be the correct check to see if this record is actually
1011 a record for our label... */
1012 if (0 != strcmp (rec->name,
1013 rh->ac_tail->label))
1014 {
1016 "Dropping record `%s', does not match desired name `%s'\n",
1017 rec->name,
1018 rh->ac_tail->label);
1019 skip++;
1020 continue;
1021 }
1022 rd[i - skip].record_type = rec->type;
1024 switch (rec->type)
1025 {
1027 if (rec->data.raw.data_len != sizeof(struct in_addr))
1028 {
1029 GNUNET_break_op (0);
1030 skip++;
1031 continue;
1032 }
1033 rd[i - skip].data_size = rec->data.raw.data_len;
1034 rd[i - skip].data = rec->data.raw.data;
1035 break;
1036
1038 if (rec->data.raw.data_len != sizeof(struct in6_addr))
1039 {
1040 GNUNET_break_op (0);
1041 skip++;
1042 continue;
1043 }
1044 rd[i - skip].data_size = rec->data.raw.data_len;
1045 rd[i - skip].data = rec->data.raw.data;
1046 break;
1047
1051 buf_start = buf_off;
1052 if (GNUNET_OK !=
1054 sizeof(buf),
1055 &buf_off,
1056 rec->data.hostname))
1057 {
1058 GNUNET_break (0);
1059 skip++;
1060 continue;
1061 }
1062 rd[i - skip].data_size = buf_off - buf_start;
1063 rd[i - skip].data = &buf[buf_start];
1064 break;
1065
1067 buf_start = buf_off;
1068 if (GNUNET_OK !=
1070 sizeof(buf),
1071 &buf_off,
1072 rec->data.soa))
1073 {
1074 GNUNET_break (0);
1075 skip++;
1076 continue;
1077 }
1078 rd[i - skip].data_size = buf_off - buf_start;
1079 rd[i - skip].data = &buf[buf_start];
1080 break;
1081
1083 buf_start = buf_off;
1084 if (GNUNET_OK !=
1086 sizeof(buf),
1087 &buf_off,
1088 rec->data.mx))
1089 {
1090 GNUNET_break (0);
1091 skip++;
1092 continue;
1093 }
1094 rd[i - skip].data_size = buf_off - buf_start;
1095 rd[i - skip].data = &buf[buf_start];
1096 break;
1097
1099 buf_start = buf_off;
1100 if (GNUNET_OK !=
1102 sizeof(buf),
1103 &buf_off,
1104 rec->data.srv))
1105 {
1106 GNUNET_break (0);
1107 skip++;
1108 continue;
1109 }
1110 rd[i - skip].data_size = buf_off - buf_start;
1111 rd[i - skip].data = &buf[buf_start];
1112 break;
1113
1115 buf_start = buf_off;
1116 if (GNUNET_OK !=
1118 sizeof(buf),
1119 &buf_off,
1120 rec->data.uri))
1121 {
1122 GNUNET_break (0);
1123 skip++;
1124 continue;
1125 }
1126 rd[i - skip].data_size = buf_off - buf_start;
1127 rd[i - skip].data = &buf[buf_start];
1128 break;
1129
1130 default:
1132 _ ("Skipping record of unsupported type %d\n"),
1133 rec->type);
1134 skip++;
1135 continue;
1136 }
1137 } /* end of for all records in answer */
1138 if (NULL != rh->leho)
1139 {
1143 rd[rd_count - skip].expiration_time = GNUNET_TIME_UNIT_HOURS.rel_value_us;
1144 rd[rd_count - skip].data = rh->leho;
1145 rd[rd_count - skip].data_size = strlen (rh->leho);
1146 skip--; /* skip one LESS */
1148 "Adding LEHO %s\n",
1149 rh->leho);
1150 }
1152 "Returning DNS response for `%s' with %u answers\n",
1153 rh->ac_tail->label,
1154 (unsigned int) (rd_count - skip));
1155 rh->proc (rh->proc_cls,
1156 rd_count - skip,
1157 rd);
1159 rh->dns_request = NULL;
1160 }
1162 if (NULL != rh->task_id)
1163 GNUNET_SCHEDULER_cancel (rh->task_id); /* should be timeout task */
1165 rh);
1166}
1167
1168
1177static void
1179{
1180 struct AuthorityChain *ac;
1181 struct GNUNET_DNSPARSER_Query *query;
1182 struct GNUNET_DNSPARSER_Packet *p;
1183 char *dns_request;
1184 size_t dns_request_length;
1185 int ret;
1186
1187 ac = rh->ac_tail;
1188 GNUNET_assert (NULL != ac);
1190 "Starting DNS lookup for `%s'\n",
1191 ac->label);
1193 query = GNUNET_new (struct GNUNET_DNSPARSER_Query);
1194 query->name = GNUNET_strdup (ac->label);
1195 query->type = rh->record_type;
1198 p->queries = query;
1199 p->num_queries = 1;
1201 UINT16_MAX);
1202 p->flags.opcode = GNUNET_TUN_DNS_OPCODE_QUERY;
1203 p->flags.recursion_desired = 1;
1205 1024,
1206 &dns_request,
1207 &dns_request_length);
1208 if (GNUNET_OK != ret)
1209 {
1210 GNUNET_break (0);
1211 rh->proc (rh->proc_cls,
1212 0,
1213 NULL);
1214 GNUNET_assert (NULL == rh->task_id);
1216 rh);
1217 }
1218 else
1219 {
1220 rh->original_dns_id = p->id;
1222 GNUNET_assert (NULL == rh->dns_request);
1223 rh->leho = GNUNET_strdup (ac->label);
1226 dns_request,
1227 dns_request_length,
1229 rh);
1232 rh);
1233 }
1234 if (GNUNET_SYSERR != ret)
1235 GNUNET_free (dns_request);
1237}
1238
1239
1248static void
1250 const char *rname)
1251{
1252 size_t nlen;
1253 char *res;
1254 const char *tld;
1255 struct AuthorityChain *ac;
1256 int af;
1257 struct GNUNET_CRYPTO_PublicKey zone;
1258
1260 "Handling GNS REDIRECT result `%s'\n",
1261 rname);
1262 nlen = strlen (rname);
1263 tld = GNS_get_tld (rname);
1264 if (0 == strcmp ("+", tld))
1265 {
1266 /* REDIRECT resolution continues relative to current domain */
1267 if (0 == rh->name_resolution_pos)
1268 {
1269 res = GNUNET_strndup (rname, nlen - 2);
1270 rh->name_resolution_pos = nlen - 2;
1271 }
1272 else
1273 {
1275 "%.*s.%.*s",
1276 (int) rh->name_resolution_pos,
1277 rh->name,
1278 (int) (nlen - 2),
1279 rname);
1280 rh->name_resolution_pos = strlen (res);
1281 }
1282 GNUNET_free (rh->name);
1283 rh->name = res;
1284 ac = GNUNET_new (struct AuthorityChain);
1285 ac->rh = rh;
1290 /* add AC to tail */
1292 rh->ac_tail,
1293 ac);
1295 rh);
1296 return;
1297 }
1298 if (GNUNET_OK == GNUNET_GNSRECORD_zkey_to_pkey (tld, &zone))
1299 {
1300 /* REDIRECT resolution continues relative to current domain */
1301 if (0 == rh->name_resolution_pos)
1302 {
1304 "%.*s",
1305 (int) (strlen (rname) - (strlen (tld) + 1)),
1306 rname);
1307 }
1308 else
1309 {
1311 "%.*s.%.*s",
1312 (int) rh->name_resolution_pos,
1313 rh->name,
1314 (int) (strlen (rname) - (strlen (tld) + 1)),
1315 rname);
1316 }
1317 rh->name_resolution_pos = strlen (res);
1318 GNUNET_free (rh->name);
1319 rh->name = res;
1320 ac = GNUNET_new (struct AuthorityChain);
1321 ac->rh = rh;
1323 ac->authority_info.gns_authority = zone;
1325 /* add AC to tail */
1327 rh->ac_tail,
1328 ac);
1330 rh);
1331 return;
1332 }
1333
1335 "Got REDIRECT `%s' from GNS for `%s'\n",
1336 rname,
1337 rh->name);
1338 if (NULL != rh->std_resolve)
1339 {
1341 "Multiple REDIRECT results from GNS resolving `%s'! Not really allowed...\n",
1342 rh->name);
1344 }
1345 /* name is absolute, go to DNS */
1346 GNUNET_free (rh->name);
1347 rh->name = GNUNET_strdup (rname);
1348 rh->name_resolution_pos = strlen (rh->name);
1349 switch (rh->record_type)
1350 {
1352 af = AF_INET;
1353 break;
1354
1356 af = AF_INET6;
1357 break;
1358
1359 default:
1360 af = AF_UNSPEC;
1361 break;
1362 }
1364 "Doing standard DNS lookup for `%s'\n",
1365 rh->name);
1366
1368 af,
1371 rh);
1372}
1373
1374
1383static void
1385 const char *cname)
1386{
1387 int af;
1388
1389 GNUNET_free (rh->name);
1390 rh->name = GNUNET_strdup (cname);
1391 rh->name_resolution_pos = strlen (rh->name);
1392 switch (rh->record_type)
1393 {
1395 af = AF_INET;
1396 break;
1397
1399 af = AF_INET6;
1400 break;
1401
1402 default:
1403 af = AF_UNSPEC;
1404 break;
1405 }
1407 "Doing standard DNS lookup for `%s'\n",
1408 rh->name);
1409
1411 af,
1414 rh);
1415}
1416
1417
1425static void
1427 unsigned int rd_count,
1428 const struct GNUNET_GNSRECORD_Data *rd);
1429
1430
1438static void
1440{
1441 struct GNS_ResolverHandle *rh = ac->rh;
1442
1443 if ((NULL != ac->authority_info.dns_authority.gp_head) &&
1445 return; /* more pending and none found yet */
1447 {
1449 "Failed to resolve DNS server for `%s' in GNS2DNS resolution\n",
1451 fail_resolution (rh);
1452 return;
1453 }
1455 return; /* already running, do not launch again! */
1456 /* recurse */
1459 "Will continue resolution using DNS to resolve `%s'\n",
1460 ac->label);
1461 GNUNET_assert (NULL == rh->task_id);
1463 rh);
1464}
1465
1466
1475static void
1476handle_gns2dns_result (void *cls,
1477 unsigned int rd_count,
1478 const struct GNUNET_GNSRECORD_Data *rd)
1479{
1480 struct Gns2DnsPending *gp = cls;
1481 struct AuthorityChain *ac = gp->ac;
1482
1485 gp);
1486 /* enable cleanup of 'rh' handle that automatically comes after we return,
1487 and which expects 'rh' to be in the #rlh_head DLL. */
1488 if (NULL != gp->rh)
1489 {
1491 rlh_tail,
1492 gp->rh);
1493 gp->rh = NULL;
1494 }
1495 GNUNET_free (gp);
1497 "Received %u results for IP address of DNS server for GNS2DNS transition\n",
1498 rd_count);
1499 /* find suitable A/AAAA record */
1500 for (unsigned int j = 0; j < rd_count; j++)
1501 {
1502 switch (rd[j].record_type)
1503 {
1505 {
1506 struct sockaddr_in v4;
1507
1508 if (sizeof(struct in_addr) != rd[j].data_size)
1509 {
1510 GNUNET_break_op (0);
1511 continue;
1512 }
1513 memset (&v4,
1514 0,
1515 sizeof(v4));
1516 v4.sin_family = AF_INET;
1517 v4.sin_port = htons (53);
1518#if HAVE_SOCKADDR_IN_SIN_LEN
1519 v4.sin_len = (u_char) sizeof(v4);
1520#endif
1521 GNUNET_memcpy (&v4.sin_addr,
1522 rd[j].data,
1523 sizeof(struct in_addr));
1524 if (GNUNET_OK ==
1527 (const struct sockaddr *) &v4))
1529 break;
1530 }
1531
1533 {
1534 struct sockaddr_in6 v6;
1535
1536 if (sizeof(struct in6_addr) != rd[j].data_size)
1537 {
1538 GNUNET_break_op (0);
1539 continue;
1540 }
1541 /* FIXME: might want to check if we support IPv6 here,
1542 and otherwise skip this one and hope we find another */
1543 memset (&v6,
1544 0,
1545 sizeof(v6));
1546 v6.sin6_family = AF_INET6;
1547 v6.sin6_port = htons (53);
1548#if HAVE_SOCKADDR_IN_SIN_LEN
1549 v6.sin6_len = (u_char) sizeof(v6);
1550#endif
1551 GNUNET_memcpy (&v6.sin6_addr,
1552 rd[j].data,
1553 sizeof(struct in6_addr));
1554 if (GNUNET_OK ==
1557 (const struct sockaddr *) &v6))
1559 break;
1560 }
1561
1562 default:
1563 break;
1564 }
1565 }
1567}
1568
1569
1577static void
1578handle_gns2dns_ip (void *cls,
1579 const struct sockaddr *addr,
1580 socklen_t addrlen)
1581{
1582 struct Gns2DnsPending *gp = cls;
1583 struct AuthorityChain *ac = gp->ac;
1584 struct sockaddr_storage ss;
1585 struct sockaddr_in *v4;
1586 struct sockaddr_in6 *v6;
1587
1588 if (NULL == addr)
1589 {
1590 /* DNS resolution finished */
1591 if (0 == gp->num_results)
1593 "Failed to use DNS to resolve name of DNS resolver\n");
1596 gp);
1597 GNUNET_free (gp);
1599 return;
1600 }
1601 GNUNET_memcpy (&ss,
1602 addr,
1603 addrlen);
1604 switch (ss.ss_family)
1605 {
1606 case AF_INET:
1607 v4 = (struct sockaddr_in *) &ss;
1608 v4->sin_port = htons (53);
1609 gp->num_results++;
1610 break;
1611
1612 case AF_INET6:
1613 v6 = (struct sockaddr_in6 *) &ss;
1614 v6->sin6_port = htons (53);
1615 gp->num_results++;
1616 break;
1617
1618 default:
1620 "Unsupported AF %d\n",
1621 ss.ss_family);
1622 return;
1623 }
1624 if (GNUNET_OK ==
1626 (struct sockaddr *) &ss))
1628}
1629
1630
1637static void
1639 const struct GNUNET_GNSRECORD_Data *rd)
1640{
1642 rd->data);
1643}
1644
1645
1652static void
1654 const struct GNUNET_GNSRECORD_Data *rd)
1655{
1656 char *cname;
1657 size_t off;
1658
1659 off = 0;
1661 rd->data_size,
1662 &off);
1663 if ((NULL == cname) ||
1664 (off != rd->data_size))
1665 {
1666 GNUNET_break_op (0); /* record not well-formed */
1667 GNUNET_free (cname);
1668 fail_resolution (rh);
1669 return;
1670 }
1672 cname);
1673 GNUNET_free (cname);
1674}
1675
1676
1683static void
1685 const struct GNUNET_GNSRECORD_Data *rd)
1686{
1687 struct AuthorityChain *ac;
1688 struct GNUNET_CRYPTO_PublicKey auth;
1689
1690 /* delegation to another zone */
1692 rd->data_size,
1693 rd->record_type,
1694 &auth))
1695 {
1696 GNUNET_break_op (0);
1697 fail_resolution (rh);
1698 return;
1699 }
1700 /* expand authority chain */
1701 ac = GNUNET_new (struct AuthorityChain);
1702 ac->rh = rh;
1704 ac->authority_info.gns_authority = auth;
1706 /* add AC to tail */
1708 rh->ac_tail,
1709 ac);
1710 /* recurse */
1712 rh);
1713}
1714
1715
1726static int
1728 unsigned int rd_count,
1729 const struct GNUNET_GNSRECORD_Data *rd)
1730{
1731 struct AuthorityChain *ac;
1732 const char *tld;
1733 char *ns;
1734
1735 ns = NULL;
1736 /* expand authority chain */
1737 ac = GNUNET_new (struct AuthorityChain);
1738 ac->rh = rh;
1740
1741 for (unsigned int i = 0; i < rd_count; i++)
1742 {
1743 char *ip;
1744 char *n;
1745 size_t off;
1746 struct Gns2DnsPending *gp;
1747 struct GNUNET_CRYPTO_PublicKey zone;
1748 struct sockaddr_in v4;
1749 struct sockaddr_in6 v6;
1750
1751 if (GNUNET_GNSRECORD_TYPE_GNS2DNS != rd[i].record_type)
1752 {
1756 GNUNET_free (ns);
1757 GNUNET_free (ac);
1758 return GNUNET_SYSERR;
1759 }
1760 off = 0;
1762 rd[i].data_size,
1763 &off);
1764 ip = GNUNET_strdup (&((const char *) rd[i].data)[off]);
1765 if ((NULL == n) ||
1766 (NULL == ip))
1767 {
1768 GNUNET_break_op (0);
1769 GNUNET_free (n);
1770 GNUNET_free (ip);
1771 continue;
1772 }
1773
1774 off += strlen (ip) + 1;
1775
1776 if (off != rd[i].data_size)
1777 {
1778 GNUNET_break_op (0);
1779 GNUNET_free (n);
1780 GNUNET_free (ip);
1781 continue;
1782 }
1783 /* resolve 'ip' to determine the IP(s) of the DNS
1784 resolver to use for lookup of 'ns' */
1785 if (NULL != ns)
1786 {
1787 if (0 != strcasecmp (ns,
1788 n))
1789 {
1790 /* NS values must all be the same for all GNS2DNS records,
1791 anything else leads to insanity */
1792 GNUNET_break_op (0);
1793 GNUNET_free (n);
1794 GNUNET_free (ip);
1795 continue;
1796 }
1797 GNUNET_free (n);
1798 }
1799 else
1800 {
1801 ns = n;
1802 }
1803
1804 /* check if 'ip' is already an IPv4/IPv6 address */
1805 if ((1 == inet_pton (AF_INET,
1806 ip,
1807 &v4)) ||
1808 (1 == inet_pton (AF_INET6,
1809 ip,
1810 &v6)))
1811 {
1815 ip));
1817 GNUNET_free (ip);
1818 continue;
1819 }
1820 tld = GNS_get_tld (ip);
1821 if ((0 != strcmp (tld, "+")) &&
1822 (GNUNET_OK != GNUNET_GNSRECORD_zkey_to_pkey (tld, &zone)))
1823 {
1824 /* 'ip' is a DNS name */
1825 gp = GNUNET_new (struct Gns2DnsPending);
1826 gp->ac = ac;
1829 gp);
1831 AF_UNSPEC,
1834 gp);
1835 GNUNET_free (ip);
1836 continue;
1837 }
1838 /* 'ip' should be a GNS name */
1839 gp = GNUNET_new (struct Gns2DnsPending);
1840 gp->ac = ac;
1843 gp);
1844 gp->rh = GNUNET_new (struct GNS_ResolverHandle);
1845 if (0 == strcmp (tld, "+"))
1846 {
1847 ip = translate_dot_plus (rh,
1848 ip);
1849 tld = GNS_get_tld (ip);
1850 if (GNUNET_OK !=
1852 &zone))
1853 {
1854 GNUNET_break_op (0);
1855 GNUNET_free (ip);
1856 continue;
1857 }
1858 }
1859 gp->rh->authority_zone = zone;
1861 "Resolving `%s' to determine IP address of DNS server for GNS2DNS transition for `%s'\n",
1862 ip,
1863 ns);
1864 gp->rh->name = ip;
1865 gp->rh->name_resolution_pos = strlen (ip) - strlen (tld) - 1;
1867 gp->rh->proc_cls = gp;
1870 gp->rh->loop_limiter = rh->loop_limiter + 1;
1871 gp->rh->loop_threshold = rh->loop_threshold;
1872 gp->rh->task_id
1874 gp->rh);
1875 } /* end 'for all records' */
1876
1877 if (NULL == ns)
1878 {
1879 /* not a single GNS2DNS record found */
1880 GNUNET_free (ac);
1881 return GNUNET_SYSERR;
1882 }
1884 strcpy (ac->authority_info.dns_authority.name,
1885 ns);
1886 /* for DNS recursion, the label is the full DNS name,
1887 created from the remainder of the GNS name and the
1888 name in the NS record */
1889 GNUNET_asprintf (&ac->label,
1890 "%.*s%s%s",
1891 (int) rh->name_resolution_pos,
1892 rh->name,
1893 (0 != rh->name_resolution_pos) ? "." : "",
1894 ns);
1895 GNUNET_free (ns);
1896
1897 {
1898 /* the GNS name is UTF-8 and may include multibyte chars.
1899 * We have to convert the combined name to a DNS-compatible IDNA.
1900 */
1901 char *tmp = ac->label;
1902
1903 if (IDNA_SUCCESS != idna_to_ascii_8z (tmp,
1904 &ac->label,
1905 IDNA_ALLOW_UNASSIGNED))
1906 {
1908 _ ("Name `%s' cannot be converted to IDNA."),
1909 tmp);
1910 GNUNET_free (tmp);
1911 GNUNET_free (ac);
1912 return GNUNET_SYSERR;
1913 }
1914 GNUNET_free (tmp);
1915 }
1916
1918 rh->ac_tail,
1919 ac);
1920 if (strlen (ac->label) > GNUNET_DNSPARSER_MAX_NAME_LENGTH)
1921 {
1923 _ ("GNS lookup resulted in DNS name that is too long (`%s')\n"),
1924 ac->label);
1925 GNUNET_free (ac->label);
1926 GNUNET_free (ac);
1927 return GNUNET_SYSERR;
1928 }
1930 return GNUNET_OK;
1931}
1932
1933
1934static void
1936 unsigned int rd_count,
1937 const struct GNUNET_GNSRECORD_Data *rd)
1938{
1939 struct GNS_ResolverHandle *rh = cls;
1940 char *cname;
1941 char scratch[UINT16_MAX];
1942 size_t scratch_off;
1943 size_t scratch_start;
1944 size_t off;
1945 struct GNUNET_GNSRECORD_Data rd_new[rd_count];
1946 unsigned int rd_off;
1947
1949 "Resolution succeeded for `%s' in zone %s, got %u records\n",
1950 rh->ac_tail->label,
1952 rd_count);
1953 if (0 == rd_count)
1954 {
1956 _ ("GNS lookup failed (zero records found for `%s')\n"),
1957 rh->name);
1958 fail_resolution (rh);
1959 return;
1960 }
1961
1962 if (0 == rh->name_resolution_pos)
1963 {
1964 /* top-level match, are we done yet? */
1965 if ((rd_count > 0) &&
1968 {
1969 off = 0;
1971 rd[0].data_size,
1972 &off);
1973 if ((NULL == cname) ||
1974 (off != rd[0].data_size))
1975 {
1976 GNUNET_break_op (0);
1977 GNUNET_free (cname);
1978 fail_resolution (rh);
1979 return;
1980 }
1982 cname);
1983 GNUNET_free (cname);
1984 return;
1985 }
1986 if ((rd_count > 0) &&
1989 {
1991 rd[0].data);
1992 return;
1993 }
1994
1995
1996 /* If A/AAAA was requested,
1997 * but we got a GNS2DNS record */
1998 if ((GNUNET_DNSPARSER_TYPE_A == rh->record_type) ||
2000 {
2001 for (unsigned int i = 0; i < rd_count; i++)
2002 {
2003 switch (rd[i].record_type)
2004 {
2006 {
2007 /* delegation to DNS */
2009 "Found GNS2DNS record, delegating to DNS!\n");
2010 if (GNUNET_OK ==
2012 rd_count,
2013 rd))
2014 return;
2015 else
2016 goto fail;
2017 }
2018
2019 default:
2020 break;
2021 } /* end: switch */
2022 } /* end: for rd */
2023 } /* end: name_resolution_pos */
2024 /* convert relative names in record values to absolute names,
2025 using 'scratch' array for memory allocations */
2026 scratch_off = 0;
2027 rd_off = 0;
2028 for (unsigned int i = 0; i < rd_count; i++)
2029 {
2030 GNUNET_assert (rd_off <= i);
2031 if ((((0 != rh->protocol) &&
2032 (0 != rh->service)) || (NULL != rh->prefix)) &&
2037 continue;
2038 /* we _only_ care about boxed records */
2039
2040 GNUNET_assert (rd_off < rd_count);
2041 rd_new[rd_off] = rd[i];
2042 /* Check if the embedded name(s) end in "+", and if so,
2043 replace the "+" with the zone at "ac_tail", changing the name
2044 to a ".ZONEKEY". The name is allocated on the 'scratch' array,
2045 so we can free it afterwards. */
2046 switch (rd[i].record_type)
2047 {
2049 {
2050 char *rname;
2051 rname = GNUNET_strndup (rd[i].data, rd[i].data_size);
2052 rname = translate_dot_plus (rh, rname);
2053 GNUNET_break (NULL != rname);
2054 scratch_start = scratch_off;
2055 memcpy (&scratch[scratch_start], rname, strlen (rname) + 1);
2056 scratch_off += strlen (rname) + 1;
2057 GNUNET_assert (rd_off < rd_count);
2058 rd_new[rd_off].data = &scratch[scratch_start];
2059 rd_new[rd_off].data_size = scratch_off - scratch_start;
2060 rd_off++;
2061 GNUNET_free (rname);
2062 }
2063 break;
2064
2066 {
2067 char *cname_tmp;
2068
2069 off = 0;
2070 cname_tmp = GNUNET_DNSPARSER_parse_name (rd[i].data,
2071 rd[i].data_size,
2072 &off);
2073 if ((NULL == cname_tmp) ||
2074 (off != rd[i].data_size))
2075 {
2076 GNUNET_break_op (0); /* record not well-formed */
2077 }
2078 else
2079 {
2080 cname_tmp = translate_dot_plus (rh, cname_tmp);
2081 GNUNET_break (NULL != cname_tmp);
2082 scratch_start = scratch_off;
2083 if (GNUNET_OK !=
2085 sizeof(scratch),
2086 &scratch_off,
2087 cname_tmp))
2088 {
2089 GNUNET_break (0);
2090 }
2091 else
2092 {
2093 GNUNET_assert (rd_off < rd_count);
2094 rd_new[rd_off].data = &scratch[scratch_start];
2095 rd_new[rd_off].data_size = scratch_off - scratch_start;
2096 rd_off++;
2097 }
2098 }
2099 GNUNET_free (cname_tmp);
2100 }
2101 break;
2102
2104 {
2105 struct GNUNET_DNSPARSER_SoaRecord *soa;
2106
2107 off = 0;
2109 rd[i].data_size,
2110 &off);
2111 if ((NULL == soa) ||
2112 (off != rd[i].data_size))
2113 {
2114 GNUNET_break_op (0); /* record not well-formed */
2115 }
2116 else
2117 {
2118 soa->mname = translate_dot_plus (rh, soa->mname);
2119 soa->rname = translate_dot_plus (rh, soa->rname);
2120 scratch_start = scratch_off;
2121 if (GNUNET_OK !=
2123 sizeof(scratch),
2124 &scratch_off,
2125 soa))
2126 {
2127 GNUNET_break (0);
2128 }
2129 else
2130 {
2131 GNUNET_assert (rd_off < rd_count);
2132 rd_new[rd_off].data = &scratch[scratch_start];
2133 rd_new[rd_off].data_size = scratch_off - scratch_start;
2134 rd_off++;
2135 }
2136 }
2137 if (NULL != soa)
2139 }
2140 break;
2141
2143 {
2144 struct GNUNET_DNSPARSER_MxRecord *mx;
2145
2146 off = 0;
2148 rd[i].data_size,
2149 &off);
2150 if ((NULL == mx) ||
2151 (off != rd[i].data_size))
2152 {
2153 GNUNET_break_op (0); /* record not well-formed */
2154 }
2155 else
2156 {
2157 mx->mxhost = translate_dot_plus (rh, mx->mxhost);
2158 scratch_start = scratch_off;
2159 if (GNUNET_OK !=
2161 sizeof(scratch),
2162 &scratch_off,
2163 mx))
2164 {
2165 GNUNET_break (0);
2166 }
2167 else
2168 {
2169 GNUNET_assert (rd_off < rd_count);
2170 rd_new[rd_off].data = &scratch[scratch_start];
2171 rd_new[rd_off].data_size = scratch_off - scratch_start;
2172 rd_off++;
2173 }
2174 }
2175 if (NULL != mx)
2177 }
2178 break;
2179
2181 {
2182 struct GNUNET_DNSPARSER_SrvRecord *srv;
2183
2184 off = 0;
2186 rd[i].data_size,
2187 &off);
2188 if ((NULL == srv) ||
2189 (off != rd[i].data_size))
2190 {
2191 GNUNET_break_op (0); /* record not well-formed */
2192 }
2193 else
2194 {
2195 srv->target = translate_dot_plus (rh, srv->target);
2196 scratch_start = scratch_off;
2197 if (GNUNET_OK !=
2199 sizeof(scratch),
2200 &scratch_off,
2201 srv))
2202 {
2203 GNUNET_break (0);
2204 }
2205 else
2206 {
2207 GNUNET_assert (rd_off < rd_count);
2208 rd_new[rd_off].data = &scratch[scratch_start];
2209 rd_new[rd_off].data_size = scratch_off - scratch_start;
2210 rd_off++;
2211 }
2212 }
2213 if (NULL != srv)
2215 }
2216 break;
2217
2219 {
2221
2222 off = 0;
2224 rd[i].data_size,
2225 &off);
2226 if ((NULL == uri) ||
2227 (off != rd[i].data_size))
2228 {
2230 _ ("Failed to deserialize URI record with target\n"));
2231 GNUNET_break_op (0); /* record not well-formed */
2232 }
2233 else
2234 {
2235 scratch_start = scratch_off;
2236 if (GNUNET_OK !=
2238 sizeof(scratch),
2239 &scratch_off,
2240 uri))
2241 {
2242 GNUNET_break (0);
2243 }
2244 else
2245 {
2246 GNUNET_assert (rd_off < rd_count);
2247 rd_new[rd_off].data = &scratch[scratch_start];
2248 rd_new[rd_off].data_size = scratch_off - scratch_start;
2249 rd_off++;
2250 }
2251 }
2252 if (NULL != uri)
2254 }
2255 break;
2256
2259 {
2261 if (rd[i].data_size < sizeof(uint32_t))
2262 {
2263 GNUNET_break_op (0);
2264 break;
2265 }
2266 if (GNUNET_OK !=
2268 rd[i].data_size,
2269 rd[i].record_type,
2270 &pubkey))
2271 {
2272 GNUNET_break_op (0);
2273 break;
2274 }
2275 rd_off++;
2276 if (rd[i].record_type != rh->record_type)
2277 {
2278 /* try to resolve "@" */
2279 struct AuthorityChain *ac;
2280
2281 ac = GNUNET_new (struct AuthorityChain);
2282 ac->rh = rh;
2287 rh->ac_tail,
2288 ac);
2290 rh);
2291 return;
2292 }
2293 }
2294 break;
2295
2297 {
2298 /* delegation to DNS */
2300 {
2301 rd_off++;
2302 break; /* do not follow to DNS, we wanted the GNS2DNS record! */
2303 }
2305 "Found GNS2DNS record, delegating to DNS!\n");
2306 if (GNUNET_OK ==
2308 rd_count,
2309 rd))
2310 return;
2311 else
2312 goto fail;
2313 }
2314
2316 {
2317 /* unbox SRV/TLSA records if a specific one was requested */
2318 if ((0 != rh->protocol) &&
2319 (0 != rh->service) &&
2320 (rd[i].data_size >= sizeof(struct GNUNET_GNSRECORD_BoxRecord)))
2321 {
2322 const struct GNUNET_GNSRECORD_BoxRecord *box;
2323
2324 box = rd[i].data;
2326 "Got BOX record, checking if parameters match... %u/%u vs %u/%u\n",
2327 ntohs (box->protocol), ntohs (box->service),
2328 rh->protocol, rh->service);
2329 if ((ntohs (box->protocol) == rh->protocol) &&
2330 (ntohs (box->service) == rh->service))
2331 {
2332 /* Box matches, unbox! */
2333 GNUNET_assert (rd_off < rd_count);
2334 rd_new[rd_off].record_type = ntohl (box->record_type);
2335 rd_new[rd_off].data_size -= sizeof(struct
2337 rd_new[rd_off].data = &box[1];
2338 rd_off++;
2339 }
2340 }
2341 else
2342 {
2343 /* no specific protocol/service specified, preserve all BOX
2344 records (for modern, GNS-enabled applications) */
2345 rd_off++;
2346 }
2347 break;
2348 }
2350 {
2351 /* unbox SBOX records if a specific one was requested */
2352 if ((rh->prefix != NULL) &&
2353 (rd[i].data_size >= sizeof(struct GNUNET_GNSRECORD_SBoxRecord)))
2354 {
2355 const struct GNUNET_GNSRECORD_SBoxRecord *box;
2356 const char *prefix;
2357 size_t prefix_len;
2358
2359 box = rd[i].data;
2360 prefix = rd[i].data + sizeof(struct GNUNET_GNSRECORD_SBoxRecord);
2361 prefix_len = strnlen (
2362 prefix,
2363 rd[i].data_size - sizeof(struct GNUNET_GNSRECORD_SBoxRecord)) + 1;
2364 if (prefix_len - 1 >= rd[i].data_size - sizeof(struct
2366 {
2368 "SBOX record with invalid prefix length, maybe not null-terminated\n");
2369 continue;
2370 }
2372 "Got SBOX record, checking if prefixes match... %s vs %s\n",
2373 prefix, rh->prefix);
2374 if (strcmp (rh->prefix, prefix) == 0)
2375 {
2376 /* Box matches, unbox! */
2377 GNUNET_assert (rd_off < rd_count);
2378 rd_new[rd_off].record_type = ntohl (box->record_type);
2379 rd_new[rd_off].data_size -= sizeof(struct
2381 + prefix_len;
2382 rd_new[rd_off].data = rd[i].data
2383 + sizeof(struct GNUNET_GNSRECORD_SBoxRecord)
2384 + prefix_len;
2385 rd_off++;
2386 }
2387 }
2388 else
2389 {
2391 _ (
2392 "GNS no specific protocol/service specified, preserve all SBOX `%s')\n"),
2393 rh->name);
2394 /* no specific protocol/service specified, preserve all SBOX
2395 records (for modern, GNS-enabled applications) */
2396 rd_off++;
2397 }
2398 break;
2399 }
2400 default:
2401 rd_off++;
2402 break;
2403 } /* end: switch */
2404 } /* end: for rd_count */
2405
2406 GNUNET_free (rh->prefix);
2407 rh->prefix = NULL;
2408
2409 /* yes, we are done, return result */
2411 "Returning GNS response for `%s' with %u answers\n",
2412 rh->ac_tail->label,
2413 rd_off);
2414 rh->proc (rh->proc_cls,
2415 rd_off,
2416 rd_new);
2418 rh);
2419 return;
2420 }
2421
2422 switch (rd[0].record_type)
2423 {
2425 GNUNET_break_op (1 == rd_count); /* REDIRECT should be unique */
2427 &rd[0]);
2428 return;
2429
2431 GNUNET_break_op (1 == rd_count); /* CNAME should be unique */
2433 &rd[0]);
2434 return;
2435
2438 GNUNET_break_op (1 == rd_count); /* PKEY should be unique */
2440 &rd[0]);
2441 return;
2442
2444 if (GNUNET_OK ==
2446 rd_count,
2447 rd))
2448 return;
2449 break;
2450 default:
2452 return;
2454 _ ("Unable to process critical delegation record\n"));
2455 break;
2456 }
2457fail:
2459 _ ("GNS lookup recursion failed (no delegation record found)\n"));
2460 fail_resolution (rh);
2461}
2462
2463
2472static void
2474 int32_t success,
2475 const char *emsg)
2476{
2477 struct CacheOps *co = cls;
2478
2479 co->namecache_qe_cache = NULL;
2480 if (GNUNET_OK != success)
2482 _ ("Failed to cache GNS resolution: %s\n"),
2483 emsg);
2485 co_tail,
2486 co);
2487 GNUNET_free (co);
2488}
2489
2490
2509static void
2510handle_dht_response (void *cls,
2511 struct GNUNET_TIME_Absolute exp,
2512 const struct GNUNET_HashCode *key,
2513 const struct GNUNET_PeerIdentity *trunc_peer,
2514 const struct GNUNET_DHT_PathElement *get_path,
2515 unsigned int get_path_length,
2516 const struct GNUNET_DHT_PathElement *put_path,
2517 unsigned int put_path_length,
2519 size_t size,
2520 const void *data)
2521{
2522 struct GNS_ResolverHandle *rh = cls;
2523 struct AuthorityChain *ac = rh->ac_tail;
2524 const struct GNUNET_GNSRECORD_Block *block;
2525 struct CacheOps *co;
2526
2527 (void) exp;
2528 (void) key;
2529 (void) get_path;
2530 (void) get_path_length;
2531 (void) put_path;
2532 (void) put_path_length;
2533 (void) type;
2535 rh->get_handle = NULL;
2537 rh->dht_heap_node = NULL;
2539 "Handling response from the DHT\n");
2540 if (size < sizeof(struct GNUNET_GNSRECORD_Block))
2541 {
2542 /* how did this pass DHT block validation!? */
2543 GNUNET_break (0);
2544 fail_resolution (rh);
2545 return;
2546 }
2547 block = data;
2549 {
2550 /* how did this pass DHT block validation!? */
2551 GNUNET_break (0);
2552 fail_resolution (rh);
2553 return;
2554 }
2556 "Decrypting DHT block of size %llu for `%s', expires %s\n",
2557 (unsigned long long) GNUNET_GNSRECORD_block_get_size (block),
2558 rh->name,
2560 if (GNUNET_OK !=
2563 ac->label,
2565 rh))
2566 {
2567 GNUNET_break_op (0); /* block was ill-formed */
2568 fail_resolution (rh);
2569 return;
2570 }
2573 rel_value_us)
2574 {
2576 "Received expired block from the DHT, will not cache it.\n");
2577 return;
2578 }
2580 return;
2581 /* Cache well-formed blocks */
2583 "Caching response from the DHT in namecache\n");
2584 co = GNUNET_new (struct CacheOps);
2586 block,
2587 &
2589 co);
2591 co_tail,
2592 co);
2593}
2594
2595
2602static void
2604 const struct GNUNET_HashCode *query)
2605{
2606 struct GNS_ResolverHandle *rx;
2607
2608 GNUNET_assert (NULL == rh->get_handle);
2611 query,
2614 NULL, 0,
2615 &handle_dht_response, rh);
2617 rh,
2619 abs_value_us);
2622 {
2623 /* fail longest-standing DHT request */
2625 rx->dht_heap_node = NULL;
2626 GNUNET_assert (NULL != rx);
2627 fail_resolution (rx);
2628 }
2629}
2630
2631
2640static void
2642 unsigned int rd_count,
2643 const struct GNUNET_GNSRECORD_Data *rd)
2644{
2645 struct GNS_ResolverHandle *rh = cls;
2646
2647 if (0 == rd_count)
2649 _ ("GNS namecache returned empty result for `%s'\n"),
2650 rh->name);
2652 rd_count,
2653 rd);
2654}
2655
2656
2663static void
2665 const struct GNUNET_GNSRECORD_Block *block)
2666{
2667 struct GNS_ResolverHandle *rh = cls;
2668 struct AuthorityChain *ac = rh->ac_tail;
2669 const char *label = ac->label;
2670 const struct GNUNET_CRYPTO_PublicKey *auth =
2672 struct GNUNET_HashCode query;
2673
2674 GNUNET_assert (NULL != rh->namecache_qe);
2675 rh->namecache_qe = NULL;
2676 if (NULL == block)
2678 "No block found\n");
2679 else
2681 "Got block with expiration %s\n",
2684 if (((GNUNET_GNS_LO_DEFAULT == rh->options) ||
2686 (ac != rh->ac_head))) &&
2687 ((NULL == block) ||
2690 rel_value_us)))
2691 {
2692 /* namecache knows nothing; try DHT lookup */
2694 label,
2695 &query);
2697 "Starting DHT lookup for `%s' in zone `%s' under key `%s'\n",
2698 ac->label,
2700 GNUNET_h2s (&query));
2701 start_dht_request (rh, &query);
2702 return;
2703 }
2704
2705 if ((NULL == block) ||
2708 rel_value_us))
2709 {
2710 /* DHT not permitted and no local result, fail */
2712 "Resolution failed for `%s' in zone %s (DHT lookup not permitted by configuration)\n",
2713 ac->label,
2715 fail_resolution (rh);
2716 return;
2717 }
2719 "Received result from namecache for label `%s'\n",
2720 ac->label);
2721
2722 if (GNUNET_OK !=
2724 auth,
2725 label,
2727 rh))
2728 {
2729 GNUNET_break_op (0); /* block was ill-formed */
2730 /* try DHT instead */
2732 label,
2733 &query);
2735 "Starting DHT lookup for `%s' in zone `%s' under key `%s'\n",
2736 ac->label,
2738 GNUNET_h2s (&query));
2739 start_dht_request (rh, &query);
2740 return;
2741 }
2742}
2743
2744
2750static void
2752{
2753 struct AuthorityChain *ac = rh->ac_tail;
2754 struct GNUNET_HashCode query;
2755
2757 "Starting GNS resolution for `%s' in zone %s\n",
2758 ac->label,
2761 ac->label,
2762 &query);
2764 {
2765 rh->namecache_qe
2767 &query,
2769 rh);
2770 GNUNET_assert (NULL != rh->namecache_qe);
2771 }
2772 else
2773 {
2775 &query);
2776 }
2777}
2778
2779
2786static void
2787handle_revocation_result (void *cls,
2788 int is_valid)
2789{
2790 struct GNS_ResolverHandle *rh = cls;
2791 struct AuthorityChain *ac = rh->ac_tail;
2792
2793 rh->rev_check = NULL;
2794 if (GNUNET_YES != is_valid)
2795 {
2797 _ ("Zone %s was revoked, resolution fails\n"),
2800 return;
2801 }
2803}
2804
2805
2811static void
2813{
2814 struct AuthorityChain *ac = rh->ac_tail;
2815
2817 "Starting revocation check for zone %s\n",
2822 rh);
2823 GNUNET_assert (NULL != rh->rev_check);
2824}
2825
2826
2827static void
2828recursive_resolution (void *cls)
2829{
2830 struct GNS_ResolverHandle *rh = cls;
2831
2832 rh->task_id = NULL;
2833 if (rh->loop_threshold < rh->loop_limiter++)
2834 {
2836 "Encountered unbounded recursion resolving `%s'\n",
2837 rh->name);
2838 fail_resolution (rh);
2839 return;
2840 }
2841 if (GNUNET_YES == rh->ac_tail->gns_authority)
2843 else
2845}
2846
2847
2848static void
2849start_resolver_lookup (void *cls)
2850{
2851 struct GNS_ResolverHandle *rh = cls;
2852 struct AuthorityChain *ac;
2853 struct in_addr v4;
2854 struct in6_addr v6;
2855
2856 rh->task_id = NULL;
2857 if (1 == inet_pton (AF_INET,
2858 rh->name,
2859 &v4))
2860 {
2861 /* name is IPv4 address, pretend it's an A record */
2863
2864 rd.data = &v4;
2865 rd.data_size = sizeof(v4);
2866 rd.expiration_time = UINT64_MAX;
2868 rd.flags = 0;
2869 rh->proc (rh->proc_cls,
2870 1,
2871 &rd);
2872 GNUNET_assert (NULL == rh->task_id);
2874 rh);
2875 return;
2876 }
2877 if (1 == inet_pton (AF_INET6,
2878 rh->name,
2879 &v6))
2880 {
2881 /* name is IPv6 address, pretend it's an AAAA record */
2883
2884 rd.data = &v6;
2885 rd.data_size = sizeof(v6);
2886 rd.expiration_time = UINT64_MAX;
2888 rd.flags = 0;
2889 rh->proc (rh->proc_cls,
2890 1,
2891 &rd);
2892 GNUNET_assert (NULL == rh->task_id);
2894 rh);
2895 return;
2896 }
2897
2898 ac = GNUNET_new (struct AuthorityChain);
2899 ac->rh = rh;
2901 if (NULL == ac->label)
2902 /* name was just the "TLD", so we default to label
2903 #GNUNET_GNS_EMPTY_LABEL_AT */
2908 rh->ac_tail,
2909 ac);
2911 rh);
2912}
2913
2914
2929struct GNS_ResolverHandle *
2931 uint32_t record_type,
2932 const char *name,
2934 uint16_t recursion_depth_limit,
2936 void *proc_cls)
2937{
2938 struct GNS_ResolverHandle *rh;
2939
2941 "Starting lookup for `%s'\n",
2942 name);
2943 rh = GNUNET_new (struct GNS_ResolverHandle);
2945 rlh_tail,
2946 rh);
2947 rh->authority_zone = *zone;
2948 rh->proc = proc;
2949 rh->proc_cls = proc_cls;
2950 rh->options = options;
2952 rh->name = GNUNET_strdup (name);
2953 rh->name_resolution_pos = strlen (name);
2954 rh->loop_threshold = recursion_depth_limit;
2956 rh);
2957 return rh;
2958}
2959
2960
2966void
2968{
2969 struct DnsResult *dr;
2970 struct AuthorityChain *ac;
2971
2973 rlh_tail,
2974 rh);
2975 if (NULL != rh->dns_request)
2976 {
2978 rh->dns_request = NULL;
2979 }
2980 while (NULL != (ac = rh->ac_head))
2981 {
2983 rh->ac_tail,
2984 ac);
2985 if (GNUNET_NO == ac->gns_authority)
2986 {
2987 struct Gns2DnsPending *gp;
2988
2989 while (NULL != (gp = ac->authority_info.dns_authority.gp_head))
2990 {
2993 gp);
2994 if (NULL != gp->rh)
2995 {
2996 /* rh->g2dc->rh is NOT in the DLL yet, so to enable us
2997 using GNS_resolver_lookup_cancel here, we need to
2998 add it first... */
3000 rlh_tail,
3001 gp->rh);
3002 GNUNET_assert (NULL == gp->rh->task_id);
3005 gp->rh);
3006 gp->rh = NULL;
3007 }
3008 if (NULL != gp->dns_rh)
3009 {
3011 gp->dns_rh = NULL;
3012 }
3013 GNUNET_free (gp);
3014 }
3016 }
3017 GNUNET_free (ac->label);
3018 GNUNET_free (ac);
3019 }
3020 if (NULL != rh->task_id)
3021 {
3023 rh->task_id = NULL;
3024 }
3025 if (NULL != rh->get_handle)
3026 {
3028 rh->get_handle = NULL;
3029 }
3030 if (NULL != rh->dht_heap_node)
3031 {
3033 rh->dht_heap_node = NULL;
3034 }
3035 if (NULL != rh->namecache_qe)
3036 {
3038 rh->namecache_qe = NULL;
3039 }
3040 if (NULL != rh->rev_check)
3041 {
3043 rh->rev_check = NULL;
3044 }
3045 if (NULL != rh->std_resolve)
3046 {
3048 "Canceling standard DNS resolution\n");
3050 rh->std_resolve = NULL;
3051 }
3052 while (NULL != (dr = rh->dns_result_head))
3053 {
3056 dr);
3057 GNUNET_free (dr);
3058 }
3059 if (NULL != rh->prefix)
3060 {
3062 rh->prefix = NULL;
3063 }
3064 GNUNET_free (rh->leho);
3065 GNUNET_free (rh->name);
3066 GNUNET_free (rh);
3067}
3068
3069
3070/* ***************** Resolver initialization ********************* */
3071
3072
3081void
3083 struct GNUNET_DHT_Handle *dht,
3084 const struct GNUNET_CONFIGURATION_Handle *c,
3085 unsigned long long max_bg_queries)
3086{
3087 cfg = c;
3089 dht_handle = dht;
3092 max_allowed_background_queries = max_bg_queries;
3094 "namecache",
3095 "DISABLE");
3098 "Namecache disabled\n");
3099}
3100
3101
3105void
3107{
3108 struct GNS_ResolverHandle *rh;
3109 struct CacheOps *co;
3110
3111 /* abort active resolutions */
3112 while (NULL != (rh = rlh_head))
3113 {
3114 rh->proc (rh->proc_cls,
3115 0,
3116 NULL);
3118 }
3119 while (NULL != (co = co_head))
3120 {
3122 co_tail,
3123 co);
3125 GNUNET_free (co);
3126 }
3128 dht_lookup_heap = NULL;
3129 dht_handle = NULL;
3130 namecache_handle = NULL;
3131}
3132
3133
3134/* 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 2829 of file gnunet-service-gns_resolver.c.

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

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

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

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

◆ start_resolver_lookup()

static void start_resolver_lookup ( void *  cls)
static

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

Parameters
clsclosure with struct GNS_ResolverHandle *rh

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

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

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

Referenced by GNS_resolver_lookup(), and recursive_gns2dns_resolution().

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

◆ dns_result_parser()

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

Function called with the result of a DNS resolution.

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

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

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

References _, GNUNET_TIME_Absolute::abs_value_us, GNS_ResolverHandle::ac_tail, add_dns_result(), GNUNET_DNSPARSER_RawRecord::data, GNUNET_DNSPARSER_Record::data, GNUNET_GNSRECORD_Data::data, GNUNET_DNSPARSER_RawRecord::data_len, GNUNET_GNSRECORD_Data::data_size, DNS_LOOKUP_TIMEOUT, GNS_ResolverHandle::dns_request, GNUNET_DNSPARSER_Record::expiration_time, GNUNET_GNSRECORD_Data::expiration_time, fail_resolution(), GNUNET_GNSRECORD_Data::flags, GNS_resolver_lookup_cancel_(), GNUNET_break, GNUNET_break_op, GNUNET_DNSPARSER_builder_add_mx(), GNUNET_DNSPARSER_builder_add_name(), GNUNET_DNSPARSER_builder_add_soa(), GNUNET_DNSPARSER_builder_add_srv(), GNUNET_DNSPARSER_builder_add_uri(), GNUNET_DNSPARSER_free_packet(), GNUNET_DNSPARSER_parse(), GNUNET_DNSPARSER_TYPE_A, GNUNET_DNSPARSER_TYPE_AAAA, GNUNET_DNSPARSER_TYPE_CNAME, GNUNET_DNSPARSER_TYPE_MX, GNUNET_DNSPARSER_TYPE_NS, GNUNET_DNSPARSER_TYPE_PTR, GNUNET_DNSPARSER_TYPE_SOA, GNUNET_DNSPARSER_TYPE_SRV, GNUNET_DNSPARSER_TYPE_URI, GNUNET_DNSSTUB_resolve_cancel(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_ERROR_TYPE_INFO, GNUNET_ERROR_TYPE_WARNING, GNUNET_free, GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION, GNUNET_GNSRECORD_RF_SUPPLEMENTAL, GNUNET_GNSRECORD_TYPE_LEHO, GNUNET_log, GNUNET_OK, GNUNET_RESOLVER_ip_get(), GNUNET_RESOLVER_request_cancel(), GNUNET_SCHEDULER_add_now(), GNUNET_SCHEDULER_cancel(), GNUNET_strdup, GNUNET_TIME_UNIT_HOURS, handle_dns_result(), GNUNET_DNSPARSER_Record::hostname, GNUNET_TUN_DnsHeader::id, AuthorityChain::label, GNS_ResolverHandle::leho, GNUNET_DNSPARSER_Record::mx, GNUNET_DNSPARSER_Record::name, GNS_ResolverHandle::name, GNS_ResolverHandle::name_resolution_pos, GNS_ResolverHandle::original_dns_id, p, GNS_ResolverHandle::proc, GNS_ResolverHandle::proc_cls, GNUNET_DNSPARSER_Record::raw, rd, rd_count, GNUNET_GNSRECORD_Data::record_type, GNS_ResolverHandle::record_type, GNUNET_DNSPARSER_Record::soa, GNUNET_DNSPARSER_Record::srv, GNS_ResolverHandle::std_resolve, GNS_ResolverHandle::task_id, GNUNET_DNSPARSER_Record::type, and GNUNET_DNSPARSER_Record::uri.

Referenced by recursive_dns_resolution().

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

◆ recursive_dns_resolution()

static void recursive_dns_resolution ( struct GNS_ResolverHandle rh)
static

Perform recursive DNS resolution.

Asks the given DNS resolver to resolve "rh->dns_name", possibly recursively proceeding following NS delegations, CNAMES, etc., until 'rh->loop_limiter' bounds us or we find the answer.

Parameters
rhresolution information

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

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

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

Referenced by recursive_resolution().

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

◆ handle_gns_redirect_result()

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

We encountered a REDIRECT record during our resolution.

Merge it into our chain.

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

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

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

References GNS_ResolverHandle::ac_head, GNS_ResolverHandle::ac_tail, AuthorityChain::authority_info, DNS_LOOKUP_TIMEOUT, AuthorityChain::gns_authority, GNS_get_tld(), GNUNET_asprintf(), GNUNET_CONTAINER_DLL_insert_tail, GNUNET_DNSPARSER_TYPE_A, GNUNET_DNSPARSER_TYPE_AAAA, GNUNET_ERROR_TYPE_DEBUG, GNUNET_ERROR_TYPE_INFO, GNUNET_ERROR_TYPE_WARNING, GNUNET_free, GNUNET_GNSRECORD_zkey_to_pkey(), GNUNET_log, GNUNET_new, GNUNET_OK, GNUNET_RESOLVER_ip_get(), GNUNET_RESOLVER_request_cancel(), GNUNET_SCHEDULER_add_now(), GNUNET_strdup, GNUNET_strndup, GNUNET_YES, handle_dns_result(), AuthorityChain::label, GNS_ResolverHandle::name, GNS_ResolverHandle::name_resolution_pos, GNS_ResolverHandle::record_type, recursive_resolution(), res, resolver_lookup_get_next_label(), AuthorityChain::rh, GNS_ResolverHandle::std_resolve, and GNS_ResolverHandle::task_id.

Referenced by handle_gns_resolution_result(), and recursive_redirect_resolution().

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

◆ handle_gns_cname_result()

static void handle_gns_cname_result ( struct GNS_ResolverHandle rh,
const char *  cname 
)
static

We encountered a CNAME record during our resolution.

Merge it into our chain.

Parameters
rhresolution we are performing
cnamevalue of the cname record we got for the current authority chain tail

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

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

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

Referenced by handle_gns_resolution_result(), and recursive_cname_resolution().

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

◆ handle_gns_resolution_result()

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

Process records that were decrypted from a block.

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

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

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

References _, GNS_ResolverHandle::ac_head, GNS_ResolverHandle::ac_tail, AuthorityChain::authority_info, data, GNUNET_GNSRECORD_Data::data, data_size, GNUNET_GNSRECORD_Data::data_size, fail_resolution(), AuthorityChain::gns_authority, GNS_resolver_lookup_cancel_(), GNUNET_assert, GNUNET_break, GNUNET_break_op, GNUNET_CONTAINER_DLL_insert_tail, GNUNET_DNSPARSER_builder_add_mx(), GNUNET_DNSPARSER_builder_add_name(), GNUNET_DNSPARSER_builder_add_soa(), GNUNET_DNSPARSER_builder_add_srv(), GNUNET_DNSPARSER_builder_add_uri(), GNUNET_DNSPARSER_free_mx(), GNUNET_DNSPARSER_free_soa(), GNUNET_DNSPARSER_free_srv(), GNUNET_DNSPARSER_free_uri(), GNUNET_DNSPARSER_parse_mx(), GNUNET_DNSPARSER_parse_name(), GNUNET_DNSPARSER_parse_soa(), GNUNET_DNSPARSER_parse_srv(), GNUNET_DNSPARSER_parse_uri(), GNUNET_DNSPARSER_TYPE_A, GNUNET_DNSPARSER_TYPE_AAAA, GNUNET_DNSPARSER_TYPE_CNAME, GNUNET_DNSPARSER_TYPE_MX, GNUNET_DNSPARSER_TYPE_SOA, GNUNET_DNSPARSER_TYPE_SRV, GNUNET_DNSPARSER_TYPE_URI, GNUNET_ERROR_TYPE_DEBUG, GNUNET_ERROR_TYPE_ERROR, GNUNET_ERROR_TYPE_INFO, GNUNET_ERROR_TYPE_WARNING, GNUNET_free, GNUNET_GNS_EMPTY_LABEL_AT, GNUNET_GNSRECORD_identity_from_data(), GNUNET_GNSRECORD_is_critical(), GNUNET_GNSRECORD_TYPE_BOX, GNUNET_GNSRECORD_TYPE_EDKEY, GNUNET_GNSRECORD_TYPE_GNS2DNS, GNUNET_GNSRECORD_TYPE_PKEY, GNUNET_GNSRECORD_TYPE_REDIRECT, GNUNET_GNSRECORD_TYPE_SBOX, GNUNET_GNSRECORD_z2s(), GNUNET_log, GNUNET_new, GNUNET_OK, GNUNET_SCHEDULER_add_now(), GNUNET_strdup, GNUNET_strndup, GNUNET_YES, handle_gns_cname_result(), handle_gns_redirect_result(), AuthorityChain::label, GNUNET_DNSPARSER_SoaRecord::mname, GNUNET_DNSPARSER_MxRecord::mxhost, GNS_ResolverHandle::name, GNS_ResolverHandle::name_resolution_pos, prefix, GNS_ResolverHandle::prefix, GNS_ResolverHandle::proc, GNS_ResolverHandle::proc_cls, GNUNET_GNSRECORD_BoxRecord::protocol, GNS_ResolverHandle::protocol, pubkey, rd, rd_count, GNUNET_GNSRECORD_Data::record_type, GNUNET_GNSRECORD_BoxRecord::record_type, GNUNET_GNSRECORD_SBoxRecord::record_type, GNS_ResolverHandle::record_type, recursive_cname_resolution(), recursive_gns2dns_resolution(), recursive_pkey_resolution(), recursive_redirect_resolution(), recursive_resolution(), AuthorityChain::rh, GNUNET_DNSPARSER_SoaRecord::rname, GNUNET_GNSRECORD_BoxRecord::service, GNS_ResolverHandle::service, strnlen(), GNUNET_DNSPARSER_SrvRecord::target, GNS_ResolverHandle::task_id, translate_dot_plus(), and uri.

Referenced by handle_dht_response(), and handle_gns_namecache_resolution_result().

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

◆ continue_with_gns2dns()

static void continue_with_gns2dns ( struct AuthorityChain ac)
static

We have resolved one or more of the nameservers for a GNS2DNS lookup.

Once we have some of them, begin using the DNSSTUB resolver.

Parameters
accontext for GNS2DNS resolution

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

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

References AuthorityChain::authority_info, AuthorityChain::dns_authority, fail_resolution(), AuthorityChain::found, GNUNET_assert, GNUNET_ERROR_TYPE_DEBUG, GNUNET_ERROR_TYPE_INFO, GNUNET_log, GNUNET_NO, GNUNET_SCHEDULER_add_now(), GNUNET_YES, AuthorityChain::gp_head, AuthorityChain::label, AuthorityChain::launched, AuthorityChain::name, recursive_resolution(), AuthorityChain::rh, and GNS_ResolverHandle::task_id.

Referenced by handle_gns2dns_ip(), handle_gns2dns_result(), and recursive_gns2dns_resolution().

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

◆ handle_gns2dns_result()

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

We've resolved the IP address for the DNS resolver to use after encountering a GNS2DNS record.

Parameters
clsthe struct Gns2DnsPending used for this request
rd_countnumber of records in rd
rdaddresses for the DNS resolver (presumably)

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

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

References Gns2DnsPending::ac, AuthorityChain::authority_info, continue_with_gns2dns(), GNUNET_GNSRECORD_Data::data, data_size, AuthorityChain::dns_authority, AuthorityChain::dns_handle, AuthorityChain::found, GNUNET_break_op, GNUNET_CONTAINER_DLL_insert, GNUNET_CONTAINER_DLL_remove, GNUNET_DNSPARSER_TYPE_A, GNUNET_DNSPARSER_TYPE_AAAA, GNUNET_DNSSTUB_add_dns_sa(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_free, GNUNET_log, GNUNET_memcpy, GNUNET_OK, GNUNET_YES, AuthorityChain::gp_head, AuthorityChain::gp_tail, rd, rd_count, Gns2DnsPending::rh, rlh_head, and rlh_tail.

Referenced by recursive_gns2dns_resolution().

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

◆ handle_gns2dns_ip()

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

Function called by the resolver for each address obtained from DNS.

Parameters
clsclosure, a struct Gns2DnsPending *
addrone of the addresses of the host, NULL for the last address
addrlenlength of addr

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

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

References Gns2DnsPending::ac, AuthorityChain::authority_info, continue_with_gns2dns(), AuthorityChain::dns_authority, AuthorityChain::dns_handle, AuthorityChain::found, GNUNET_CONTAINER_DLL_remove, GNUNET_DNSSTUB_add_dns_sa(), GNUNET_ERROR_TYPE_ERROR, GNUNET_ERROR_TYPE_WARNING, GNUNET_free, GNUNET_log, GNUNET_memcpy, GNUNET_OK, GNUNET_YES, AuthorityChain::gp_head, AuthorityChain::gp_tail, and Gns2DnsPending::num_results.

Referenced by recursive_gns2dns_resolution().

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

◆ recursive_redirect_resolution()

static void recursive_redirect_resolution ( struct GNS_ResolverHandle rh,
const struct GNUNET_GNSRECORD_Data rd 
)
static

We found a REDIRECT record, perform recursive resolution on it.

Parameters
rhresolution handle
rdrecord with CNAME to resolve recursively

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

1641{
1643 rd->data);
1644}

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

Referenced by handle_gns_resolution_result().

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

◆ recursive_cname_resolution()

static void recursive_cname_resolution ( struct GNS_ResolverHandle rh,
const struct GNUNET_GNSRECORD_Data rd 
)
static

We found a CNAME record, perform recursive resolution on it.

Parameters
rhresolution handle
rdrecord with CNAME to resolve recursively

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

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

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

Referenced by handle_gns_resolution_result().

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

◆ recursive_pkey_resolution()

static void recursive_pkey_resolution ( struct GNS_ResolverHandle rh,
const struct GNUNET_GNSRECORD_Data rd 
)
static

We found a PKEY record, perform recursive resolution on it.

Parameters
rhresolution handle
rdrecord with PKEY to resolve recursively

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

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

References GNS_ResolverHandle::ac_head, GNS_ResolverHandle::ac_tail, AuthorityChain::authority_info, GNUNET_GNSRECORD_Data::data, GNUNET_GNSRECORD_Data::data_size, fail_resolution(), AuthorityChain::gns_authority, GNUNET_break_op, GNUNET_CONTAINER_DLL_insert_tail, GNUNET_GNSRECORD_identity_from_data(), GNUNET_new, GNUNET_OK, GNUNET_SCHEDULER_add_now(), GNUNET_YES, AuthorityChain::label, rd, GNUNET_GNSRECORD_Data::record_type, recursive_resolution(), resolver_lookup_get_next_label(), AuthorityChain::rh, and GNS_ResolverHandle::task_id.

Referenced by handle_gns_resolution_result().

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

◆ recursive_gns2dns_resolution()

static int recursive_gns2dns_resolution ( struct GNS_ResolverHandle rh,
unsigned int  rd_count,
const struct GNUNET_GNSRECORD_Data rd 
)
static

We found one or more GNS2DNS records, perform recursive resolution on it.

(to be precise, one or more records in rd is GNS2DNS, there may be others, so this function still needs to check which ones are GNS2DNS).

Parameters
rhresolution handle
rd_countlength of the rd array
rdrecord with PKEY to resolve recursively
Returns
GNUNET_OK if this worked, GNUNET_SYSERR if no GNS2DNS records were in rd

Records other than GNS2DNS not allowed

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

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

References _, Gns2DnsPending::ac, GNS_ResolverHandle::ac_head, GNS_ResolverHandle::ac_tail, AuthorityChain::authority_info, GNS_ResolverHandle::authority_zone, continue_with_gns2dns(), data, data_size, AuthorityChain::dns_authority, AuthorityChain::dns_handle, Gns2DnsPending::dns_rh, AuthorityChain::found, GNS_get_tld(), GNUNET_asprintf(), GNUNET_assert, GNUNET_break, GNUNET_break_op, GNUNET_CONTAINER_DLL_insert, GNUNET_CONTAINER_DLL_insert_tail, GNUNET_DNSPARSER_MAX_NAME_LENGTH, GNUNET_DNSPARSER_parse_name(), GNUNET_DNSSTUB_add_dns_ip(), GNUNET_DNSSTUB_start(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_ERROR_TYPE_WARNING, GNUNET_free, GNUNET_GNS_LO_DEFAULT, GNUNET_GNSRECORD_TYPE_ANY, GNUNET_GNSRECORD_TYPE_GNS2DNS, GNUNET_GNSRECORD_zkey_to_pkey(), GNUNET_log, GNUNET_new, GNUNET_OK, GNUNET_RESOLVER_ip_get(), GNUNET_SCHEDULER_add_now(), GNUNET_strdup, GNUNET_SYSERR, GNUNET_TIME_UNIT_FOREVER_REL, GNUNET_YES, AuthorityChain::gp_head, AuthorityChain::gp_tail, handle_gns2dns_ip(), handle_gns2dns_result(), AuthorityChain::label, GNS_ResolverHandle::loop_limiter, GNS_ResolverHandle::loop_threshold, AuthorityChain::name, GNS_ResolverHandle::name, GNS_ResolverHandle::name_resolution_pos, ns, GNS_ResolverHandle::options, GNS_ResolverHandle::proc, GNS_ResolverHandle::proc_cls, rd, rd_count, GNS_ResolverHandle::record_type, Gns2DnsPending::rh, AuthorityChain::rh, start_resolver_lookup(), GNS_ResolverHandle::task_id, and translate_dot_plus().

Referenced by handle_gns_resolution_result().

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

◆ namecache_cache_continuation()

static void namecache_cache_continuation ( void *  cls,
int32_t  success,
const char *  emsg 
)
static

Function called once the namestore has completed the request for caching a block.

Parameters
clsclosure with the struct CacheOps
successGNUNET_OK on success
emsgerror message

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

2477{
2478 struct CacheOps *co = cls;
2479
2480 co->namecache_qe_cache = NULL;
2481 if (GNUNET_OK != success)
2483 _ ("Failed to cache GNS resolution: %s\n"),
2484 emsg);
2486 co_tail,
2487 co);
2488 GNUNET_free (co);
2489}

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

Referenced by handle_dht_response().

Here is the caller graph for this function:

◆ handle_dht_response()

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

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

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

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

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

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

Referenced by start_dht_request().

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

◆ start_dht_request()

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

Initiate a DHT query for a set of GNS records.

Parameters
rhresolution handle
querykey to use in the DHT lookup

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

2606{
2607 struct GNS_ResolverHandle *rx;
2608
2609 GNUNET_assert (NULL == rh->get_handle);
2612 query,
2615 NULL, 0,
2616 &handle_dht_response, rh);
2618 rh,
2620 abs_value_us);
2623 {
2624 /* fail longest-standing DHT request */
2626 rx->dht_heap_node = NULL;
2627 GNUNET_assert (NULL != rx);
2628 fail_resolution (rx);
2629 }
2630}

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

Referenced by handle_namecache_block_response(), and recursive_gns_resolution_namecache().

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

◆ handle_gns_namecache_resolution_result()

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

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

Simply calls handle_gns_resolution_result().

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

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

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

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

Referenced by handle_namecache_block_response().

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

◆ handle_namecache_block_response()

static void handle_namecache_block_response ( void *  cls,
const struct GNUNET_GNSRECORD_Block block 
)
static

Process a record that was stored in the namecache.

Parameters
clsclosure with the struct GNS_ResolverHandle
blockblock that was stored in the namecache

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

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

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

Referenced by recursive_gns_resolution_namecache().

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

◆ recursive_gns_resolution_namecache()

static void recursive_gns_resolution_namecache ( struct GNS_ResolverHandle rh)
static

Lookup tail of our authority chain in the namecache.

Parameters
rhquery we are processing

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

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

References GNS_ResolverHandle::ac_tail, AuthorityChain::authority_info, disable_cache, AuthorityChain::gns_authority, GNUNET_assert, GNUNET_ERROR_TYPE_DEBUG, GNUNET_GNSRECORD_query_from_public_key(), GNUNET_GNSRECORD_z2s(), GNUNET_log, GNUNET_NAMECACHE_lookup_block(), GNUNET_YES, handle_namecache_block_response(), AuthorityChain::label, namecache_handle, GNS_ResolverHandle::namecache_qe, AuthorityChain::rh, and start_dht_request().

Referenced by handle_revocation_result().

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

◆ handle_revocation_result()

static void handle_revocation_result ( void *  cls,
int  is_valid 
)
static

Function called with the result from a revocation check.

Parameters
clsthe struct GNS_ResovlerHandle
is_validGNUNET_YES if the zone was not yet revoked

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

2790{
2791 struct GNS_ResolverHandle *rh = cls;
2792 struct AuthorityChain *ac = rh->ac_tail;
2793
2794 rh->rev_check = NULL;
2795 if (GNUNET_YES != is_valid)
2796 {
2798 _ ("Zone %s was revoked, resolution fails\n"),
2801 return;
2802 }
2804}

References _, GNS_ResolverHandle::ac_tail, AuthorityChain::authority_info, fail_resolution(), AuthorityChain::gns_authority, GNUNET_ERROR_TYPE_WARNING, GNUNET_GNSRECORD_z2s(), GNUNET_log, GNUNET_YES, recursive_gns_resolution_namecache(), GNS_ResolverHandle::rev_check, and AuthorityChain::rh.

Referenced by recursive_gns_resolution_revocation().

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

◆ recursive_gns_resolution_revocation()

static void recursive_gns_resolution_revocation ( struct GNS_ResolverHandle rh)
static

Perform revocation check on tail of our authority chain.

Parameters
rhquery we are processing

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

2814{
2815 struct AuthorityChain *ac = rh->ac_tail;
2816
2818 "Starting revocation check for zone %s\n",
2823 rh);
2824 GNUNET_assert (NULL != rh->rev_check);
2825}

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

Referenced by recursive_resolution().

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

◆ GNS_resolver_lookup()

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

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

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

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

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

2938{
2939 struct GNS_ResolverHandle *rh;
2940
2942 "Starting lookup for `%s'\n",
2943 name);
2944 rh = GNUNET_new (struct GNS_ResolverHandle);
2946 rlh_tail,
2947 rh);
2948 rh->authority_zone = *zone;
2949 rh->proc = proc;
2950 rh->proc_cls = proc_cls;
2951 rh->options = options;
2953 rh->name = GNUNET_strdup (name);
2954 rh->name_resolution_pos = strlen (name);
2955 rh->loop_threshold = recursion_depth_limit;
2957 rh);
2958 return rh;
2959}

References GNS_ResolverHandle::authority_zone, GNUNET_CONTAINER_DLL_insert, GNUNET_ERROR_TYPE_DEBUG, GNUNET_log, GNUNET_new, GNUNET_SCHEDULER_add_now(), GNUNET_strdup, GNS_ResolverHandle::loop_threshold, name, GNS_ResolverHandle::name, GNS_ResolverHandle::name_resolution_pos, options, GNS_ResolverHandle::options, GNS_ResolverHandle::proc, GNS_ResolverHandle::proc_cls, GNS_ResolverHandle::record_type, rlh_head, rlh_tail, start_resolver_lookup(), and GNS_ResolverHandle::task_id.

Referenced by handle_dns_request(), and handle_lookup().

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

◆ GNS_resolver_lookup_cancel()

void GNS_resolver_lookup_cancel ( struct GNS_ResolverHandle rh)

Cancel active resolution (i.e.

client disconnected).

Parameters
rhresolution to abort

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

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

References Gns2DnsPending::ac, GNS_ResolverHandle::ac_head, GNS_ResolverHandle::ac_tail, AuthorityChain::authority_info, GNS_ResolverHandle::dht_heap_node, AuthorityChain::dns_authority, AuthorityChain::dns_handle, GNS_ResolverHandle::dns_request, GNS_ResolverHandle::dns_result_head, GNS_ResolverHandle::dns_result_tail, Gns2DnsPending::dns_rh, GNS_ResolverHandle::get_handle, AuthorityChain::gns_authority, GNS_resolver_lookup_cancel_(), GNUNET_assert, GNUNET_CONTAINER_DLL_insert, GNUNET_CONTAINER_DLL_remove, GNUNET_CONTAINER_heap_remove_node(), GNUNET_DHT_get_stop(), GNUNET_DNSSTUB_resolve_cancel(), GNUNET_DNSSTUB_stop(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_free, GNUNET_log, GNUNET_NAMECACHE_cancel(), GNUNET_NO, GNUNET_RESOLVER_request_cancel(), GNUNET_REVOCATION_query_cancel(), GNUNET_SCHEDULER_add_now(), GNUNET_SCHEDULER_cancel(), AuthorityChain::gp_head, AuthorityChain::gp_tail, AuthorityChain::label, GNS_ResolverHandle::leho, GNS_ResolverHandle::name, GNS_ResolverHandle::namecache_qe, GNS_ResolverHandle::prefix, GNS_ResolverHandle::rev_check, Gns2DnsPending::rh, AuthorityChain::rh, rlh_head, rlh_tail, GNS_ResolverHandle::std_resolve, and GNS_ResolverHandle::task_id.

Referenced by client_disconnect_cb(), GNS_interceptor_done(), GNS_resolver_done(), GNS_resolver_lookup_cancel_(), and transmit_lookup_dns_result().

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

◆ GNS_resolver_init()

void GNS_resolver_init ( struct GNUNET_NAMECACHE_Handle nc,
struct GNUNET_DHT_Handle dht,
const struct GNUNET_CONFIGURATION_Handle c,
unsigned long long  max_bg_queries 
)

Initialize the resolver.

Initialize the resolver subsystem.

Parameters
ncthe namecache handle
dhtthe dht handle
cconfiguration handle
max_bg_queriesmaximum number of parallel background queries in dht

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

3087{
3088 cfg = c;
3090 dht_handle = dht;
3093 max_allowed_background_queries = max_bg_queries;
3095 "namecache",
3096 "DISABLE");
3099 "Namecache disabled\n");
3100}

References cfg, dht, dht_handle, dht_lookup_heap, disable_cache, GNUNET_CONFIGURATION_get_value_yesno(), GNUNET_CONTAINER_heap_create(), GNUNET_CONTAINER_HEAP_ORDER_MIN, GNUNET_ERROR_TYPE_WARNING, GNUNET_log, GNUNET_YES, max_allowed_background_queries, namecache_handle, and nc.

Referenced by run().

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

◆ GNS_resolver_done()

void GNS_resolver_done ( void  )

Shutdown resolver.

Cleanup resolver: Terminate pending lookups.

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

3108{
3109 struct GNS_ResolverHandle *rh;
3110 struct CacheOps *co;
3111
3112 /* abort active resolutions */
3113 while (NULL != (rh = rlh_head))
3114 {
3115 rh->proc (rh->proc_cls,
3116 0,
3117 NULL);
3119 }
3120 while (NULL != (co = co_head))
3121 {
3123 co_tail,
3124 co);
3126 GNUNET_free (co);
3127 }
3129 dht_lookup_heap = NULL;
3130 dht_handle = NULL;
3131 namecache_handle = NULL;
3132}

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().