aboutsummaryrefslogtreecommitdiff
path: root/src/gns
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2018-04-19 18:38:41 +0200
committerChristian Grothoff <christian@grothoff.org>2018-04-19 18:38:41 +0200
commitff4d7b51f37f61633766664647e9b148af1e4f0a (patch)
tree500aa14d9452ce90c19dbbb18cfaec0dd51e6ec2 /src/gns
parent9c699755967529e59815561d03b85e9a90d789f8 (diff)
downloadgnunet-ff4d7b51f37f61633766664647e9b148af1e4f0a.tar.gz
gnunet-ff4d7b51f37f61633766664647e9b148af1e4f0a.zip
support multiple DNS resolvers for queries (in DNSSTUB and GNS2DNS resolution for now)
Diffstat (limited to 'src/gns')
-rw-r--r--src/gns/gnunet-dns2gns.c19
-rw-r--r--src/gns/gnunet-service-gns_resolver.c1072
-rw-r--r--src/gns/test_gns_lookup.conf2
3 files changed, 600 insertions, 493 deletions
diff --git a/src/gns/gnunet-dns2gns.c b/src/gns/gnunet-dns2gns.c
index 47cc6dde0..bc66f1325 100644
--- a/src/gns/gnunet-dns2gns.c
+++ b/src/gns/gnunet-dns2gns.c
@@ -247,19 +247,16 @@ do_timeout (void *cls)
247 * Iterator called on obtained result for a DNS lookup 247 * Iterator called on obtained result for a DNS lookup
248 * 248 *
249 * @param cls closure 249 * @param cls closure
250 * @param rs the request socket
251 * @param dns the DNS udp payload 250 * @param dns the DNS udp payload
252 * @param r size of the DNS payload 251 * @param r size of the DNS payload
253 */ 252 */
254static void 253static void
255dns_result_processor (void *cls, 254dns_result_processor (void *cls,
256 struct GNUNET_DNSSTUB_RequestSocket *rs,
257 const struct GNUNET_TUN_DnsHeader *dns, 255 const struct GNUNET_TUN_DnsHeader *dns,
258 size_t r) 256 size_t r)
259{ 257{
260 struct Request *request = cls; 258 struct Request *request = cls;
261 259
262 (void) rs;
263 if (NULL == dns) 260 if (NULL == dns)
264 { 261 {
265 /* DNSSTUB gave up, so we trigger timeout early */ 262 /* DNSSTUB gave up, so we trigger timeout early */
@@ -307,11 +304,11 @@ result_processor (void *cls,
307 request->original_request_id = request->packet->id; 304 request->original_request_id = request->packet->id;
308 GNUNET_DNSPARSER_free_packet (request->packet); 305 GNUNET_DNSPARSER_free_packet (request->packet);
309 request->packet = NULL; 306 request->packet = NULL;
310 request->dns_lookup = GNUNET_DNSSTUB_resolve2 (dns_stub, 307 request->dns_lookup = GNUNET_DNSSTUB_resolve (dns_stub,
311 request->udp_msg, 308 request->udp_msg,
312 request->udp_msg_size, 309 request->udp_msg_size,
313 &dns_result_processor, 310 &dns_result_processor,
314 request); 311 request);
315 return; 312 return;
316 } 313 }
317 packet = request->packet; 314 packet = request->packet;
@@ -594,8 +591,12 @@ run (void *cls,
594 NULL); 591 NULL);
595 if (NULL == (gns = GNUNET_GNS_connect (cfg))) 592 if (NULL == (gns = GNUNET_GNS_connect (cfg)))
596 return; 593 return;
597 if (NULL == (dns_stub = GNUNET_DNSSTUB_start (dns_ip))) 594 GNUNET_assert (NULL != (dns_stub = GNUNET_DNSSTUB_start (128)));
595 if (GNUNET_OK !=
596 GNUNET_DNSSTUB_add_dns_ip (dns_stub,
597 dns_ip))
598 { 598 {
599 GNUNET_DNSSTUB_stop (dns_stub);
599 GNUNET_GNS_disconnect (gns); 600 GNUNET_GNS_disconnect (gns);
600 gns = NULL; 601 gns = NULL;
601 return; 602 return;
diff --git a/src/gns/gnunet-service-gns_resolver.c b/src/gns/gnunet-service-gns_resolver.c
index 94819b040..74eb47f29 100644
--- a/src/gns/gnunet-service-gns_resolver.c
+++ b/src/gns/gnunet-service-gns_resolver.c
@@ -72,6 +72,57 @@
72 * DLL to hold the authority chain we had to pass in the resolution 72 * DLL to hold the authority chain we had to pass in the resolution
73 * process. 73 * process.
74 */ 74 */
75struct AuthorityChain;
76
77
78/**
79 * Element of a resolution process for looking up the
80 * responsible DNS server hostname in a GNS2DNS recursive
81 * resolution.
82 */
83struct Gns2DnsPending
84{
85
86 /**
87 * Kept in a DLL.
88 */
89 struct Gns2DnsPending *next;
90
91 /**
92 * Kept in a DLL.
93 */
94 struct Gns2DnsPending *prev;
95
96 /**
97 * Context this activity belongs with.
98 */
99 struct AuthorityChain *ac;
100
101 /**
102 * Handle for the resolution of the IP part of the
103 * GNS2DNS record. Will return to us the addresses
104 * of the DNS resolver to use.
105 */
106 struct GNS_ResolverHandle *rh;
107
108 /**
109 * Handle for DNS resolution of the DNS nameserver.
110 */
111 struct GNUNET_RESOLVER_RequestHandle *dns_rh;
112};
113
114
115/**
116 * Handle to a currenty pending resolution. On result (positive or
117 * negative) the #GNS_ResultProcessor is called.
118 */
119struct GNS_ResolverHandle;
120
121
122/**
123 * DLL to hold the authority chain we had to pass in the resolution
124 * process.
125 */
75struct AuthorityChain 126struct AuthorityChain
76{ 127{
77 /** 128 /**
@@ -131,11 +182,32 @@ struct AuthorityChain
131 char name[GNUNET_DNSPARSER_MAX_NAME_LENGTH + 1]; 182 char name[GNUNET_DNSPARSER_MAX_NAME_LENGTH + 1];
132 183
133 /** 184 /**
134 * IP address of the DNS resolver that is authoritative. 185 * List of resolutions of the 'ip' of the name server that
135 * (this implementation currently only supports one 186 * are still pending.
136 * IP at a time). 187 */
188 struct Gns2DnsPending *gp_head;
189
190 /**
191 * Tail of list of resolutions of the 'ip' of the name server that
192 * are still pending.
193 */
194 struct Gns2DnsPending *gp_tail;
195
196 /**
197 * Handle to perform DNS lookups with this authority (in GNS2DNS handling).
198 */
199 struct GNUNET_DNSSTUB_Context *dns_handle;
200
201 /**
202 * Did we succeed in getting an IP address for *any* of the DNS servers listed?
203 * Once we do, we can start with DNS queries.
204 */
205 int found;
206
207 /**
208 * Did we start the recursive resolution via DNS?
137 */ 209 */
138 struct sockaddr_storage dns_ip; 210 int launched;
139 211
140 } dns_authority; 212 } dns_authority;
141 213
@@ -218,34 +290,6 @@ struct VpnContext
218 290
219 291
220/** 292/**
221 * Information we keep during the resolution of an
222 * IP address for a DNS server while handling a
223 * GNS2DNS record.
224 */
225struct Gns2DnsContext
226{
227
228 /**
229 * DNS domain in which the resolution will continue
230 * (first part of the GNS2DNS record).
231 */
232 char *ns;
233
234 /**
235 * Handle for the resolution of the IP part of the
236 * GNS2DNS record. Will return to us the addresses
237 * of the DNS resolver to use.
238 */
239 struct GNS_ResolverHandle *rh;
240
241 /**
242 * Handle for DNS resolution of the DNS nameserver.
243 */
244 struct GNUNET_RESOLVER_RequestHandle *dns_rh;
245};
246
247
248/**
249 * Handle to a currenty pending resolution. On result (positive or 293 * Handle to a currenty pending resolution. On result (positive or
250 * negative) the #GNS_ResultProcessor is called. 294 * negative) the #GNS_ResultProcessor is called.
251 */ 295 */
@@ -278,12 +322,6 @@ struct GNS_ResolverHandle
278 void* proc_cls; 322 void* proc_cls;
279 323
280 /** 324 /**
281 * Handle used during GNS2DNS resolution for looking up the
282 * IP address of the DNS server.
283 */
284 struct Gns2DnsContext *g2dc;
285
286 /**
287 * Handle for DHT lookups. should be NULL if no lookups are in progress 325 * Handle for DHT lookups. should be NULL if no lookups are in progress
288 */ 326 */
289 struct GNUNET_DHT_GetHandle *get_handle; 327 struct GNUNET_DHT_GetHandle *get_handle;
@@ -431,11 +469,6 @@ static struct GNUNET_VPN_Handle *vpn_handle;
431static struct GNUNET_DHT_Handle *dht_handle; 469static struct GNUNET_DHT_Handle *dht_handle;
432 470
433/** 471/**
434 * Handle to perform DNS lookups.
435 */
436static struct GNUNET_DNSSTUB_Context *dns_handle;
437
438/**
439 * Heap for limiting parallel DHT lookups 472 * Heap for limiting parallel DHT lookups
440 */ 473 */
441static struct GNUNET_CONTAINER_Heap *dht_lookup_heap; 474static struct GNUNET_CONTAINER_Heap *dht_lookup_heap;
@@ -543,21 +576,53 @@ translate_dot_plus (struct GNS_ResolverHandle *rh,
543 576
544 577
545/** 578/**
546 * Task scheduled to asynchronously fail a resolution. 579 * Wrapper around #GNS_resolver_lookup_cancel() as a task.
580 * Used for delayed cleanup so we can unwind the stack first.
547 * 581 *
548 * @param cls the 'struct GNS_ResolverHandle' of the resolution to fail 582 * @param cls the `struct GNS_ResolverHandle`
549 */ 583 */
550static void 584static void
551fail_resolution (void *cls) 585GNS_resolver_lookup_cancel_ (void *cls)
552{ 586{
553 struct GNS_ResolverHandle *rh = cls; 587 struct GNS_ResolverHandle *rh = cls;
554 588
555 rh->task_id = NULL; 589 rh->task_id = NULL;
556 rh->proc (rh->proc_cls, 0, NULL);
557 GNS_resolver_lookup_cancel (rh); 590 GNS_resolver_lookup_cancel (rh);
558} 591}
559 592
560 593
594/**
595 * Function called to asynchronously fail a resolution.
596 *
597 * @param rh the resolution to fail
598 */
599static void
600fail_resolution (struct GNS_ResolverHandle *rh)
601{
602 rh->proc (rh->proc_cls,
603 0,
604 NULL);
605 GNUNET_assert (NULL == rh->task_id);
606 rh->task_id = GNUNET_SCHEDULER_add_now (&GNS_resolver_lookup_cancel_,
607 rh);
608}
609
610
611/**
612 * Function called when a resolution times out.
613 *
614 * @param cls the `struct GNS_ResolverHandle`
615 */
616static void
617timeout_resolution (void *cls)
618{
619 struct GNS_ResolverHandle *rh = cls;
620
621 rh->task_id = NULL;
622 fail_resolution (rh);
623}
624
625
561#if (defined WINDOWS) || (defined DARWIN) 626#if (defined WINDOWS) || (defined DARWIN)
562/* Don't have this on W32, here's a naive implementation 627/* Don't have this on W32, here's a naive implementation
563 * Was somehow removed on OS X ... */ 628 * Was somehow removed on OS X ... */
@@ -831,13 +896,11 @@ start_resolver_lookup (void *cls);
831 * 896 *
832 * @param cls the request handle of the resolution that 897 * @param cls the request handle of the resolution that
833 * we were attempting to make 898 * we were attempting to make
834 * @param rs socket that received the response
835 * @param dns dns response, never NULL 899 * @param dns dns response, never NULL
836 * @param dns_len number of bytes in @a dns 900 * @param dns_len number of bytes in @a dns
837 */ 901 */
838static void 902static void
839dns_result_parser (void *cls, 903dns_result_parser (void *cls,
840 struct GNUNET_DNSSTUB_RequestSocket *rs,
841 const struct GNUNET_TUN_DnsHeader *dns, 904 const struct GNUNET_TUN_DnsHeader *dns,
842 size_t dns_len) 905 size_t dns_len)
843{ 906{
@@ -845,18 +908,13 @@ dns_result_parser (void *cls,
845 struct GNUNET_DNSPARSER_Packet *p; 908 struct GNUNET_DNSPARSER_Packet *p;
846 const struct GNUNET_DNSPARSER_Record *rec; 909 const struct GNUNET_DNSPARSER_Record *rec;
847 unsigned int rd_count; 910 unsigned int rd_count;
848 unsigned int i;
849 911
850 (void) rs;
851 if (NULL == dns) 912 if (NULL == dns)
852 { 913 {
853 rh->dns_request = NULL; 914 rh->dns_request = NULL;
854 GNUNET_SCHEDULER_cancel (rh->task_id); 915 GNUNET_SCHEDULER_cancel (rh->task_id);
855 rh->task_id = NULL; 916 rh->task_id = NULL;
856 rh->proc (rh->proc_cls, 917 fail_resolution (rh);
857 0,
858 NULL);
859 GNS_resolver_lookup_cancel (rh);
860 return; 918 return;
861 } 919 }
862 if (rh->original_dns_id != dns->id) 920 if (rh->original_dns_id != dns->id)
@@ -872,6 +930,8 @@ dns_result_parser (void *cls,
872 _("Failed to parse DNS response\n")); 930 _("Failed to parse DNS response\n"));
873 return; 931 return;
874 } 932 }
933
934 /* We got a result from DNS */
875 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 935 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
876 "Received DNS response for `%s' with %u answers\n", 936 "Received DNS response for `%s' with %u answers\n",
877 rh->ac_tail->label, 937 rh->ac_tail->label,
@@ -920,8 +980,10 @@ dns_result_parser (void *cls,
920 980
921 buf_off = 0; 981 buf_off = 0;
922 skip = 0; 982 skip = 0;
923 memset (rd, 0, sizeof (rd)); 983 memset (rd,
924 for (i=0;i<rd_count;i++) 984 0,
985 sizeof (rd));
986 for (unsigned int i=0;i<rd_count;i++)
925 { 987 {
926 if (i < p->num_answers) 988 if (i < p->num_answers)
927 rec = &p->answers[i]; 989 rec = &p->answers[i];
@@ -1043,9 +1105,12 @@ dns_result_parser (void *cls,
1043 rh->proc (rh->proc_cls, 1105 rh->proc (rh->proc_cls,
1044 rd_count - skip, 1106 rd_count - skip,
1045 rd); 1107 rd);
1046 GNS_resolver_lookup_cancel (rh);
1047 } 1108 }
1048 GNUNET_DNSPARSER_free_packet (p); 1109 GNUNET_DNSPARSER_free_packet (p);
1110 if (NULL != rh->task_id)
1111 GNUNET_SCHEDULER_cancel (rh->task_id); /* should be timeout task */
1112 rh->task_id = GNUNET_SCHEDULER_add_now (&GNS_resolver_lookup_cancel_,
1113 rh);
1049} 1114}
1050 1115
1051 1116
@@ -1061,7 +1126,6 @@ static void
1061recursive_dns_resolution (struct GNS_ResolverHandle *rh) 1126recursive_dns_resolution (struct GNS_ResolverHandle *rh)
1062{ 1127{
1063 struct AuthorityChain *ac; 1128 struct AuthorityChain *ac;
1064 socklen_t sa_len;
1065 struct GNUNET_DNSPARSER_Query *query; 1129 struct GNUNET_DNSPARSER_Query *query;
1066 struct GNUNET_DNSPARSER_Packet *p; 1130 struct GNUNET_DNSPARSER_Packet *p;
1067 char *dns_request; 1131 char *dns_request;
@@ -1074,20 +1138,6 @@ recursive_dns_resolution (struct GNS_ResolverHandle *rh)
1074 "Starting DNS lookup for `%s'\n", 1138 "Starting DNS lookup for `%s'\n",
1075 ac->label); 1139 ac->label);
1076 GNUNET_assert (GNUNET_NO == ac->gns_authority); 1140 GNUNET_assert (GNUNET_NO == ac->gns_authority);
1077 switch (((const struct sockaddr *) &ac->authority_info.dns_authority.dns_ip)->sa_family)
1078 {
1079 case AF_INET:
1080 sa_len = sizeof (struct sockaddr_in);
1081 break;
1082 case AF_INET6:
1083 sa_len = sizeof (struct sockaddr_in6);
1084 break;
1085 default:
1086 GNUNET_break (0);
1087 rh->proc (rh->proc_cls, 0, NULL);
1088 GNS_resolver_lookup_cancel (rh);
1089 return;
1090 }
1091 query = GNUNET_new (struct GNUNET_DNSPARSER_Query); 1141 query = GNUNET_new (struct GNUNET_DNSPARSER_Query);
1092 query->name = GNUNET_strdup (ac->label); 1142 query->name = GNUNET_strdup (ac->label);
1093 query->type = rh->record_type; 1143 query->type = rh->record_type;
@@ -1109,20 +1159,22 @@ recursive_dns_resolution (struct GNS_ResolverHandle *rh)
1109 rh->proc (rh->proc_cls, 1159 rh->proc (rh->proc_cls,
1110 0, 1160 0,
1111 NULL); 1161 NULL);
1112 GNS_resolver_lookup_cancel (rh); 1162 GNUNET_assert (NULL == rh->task_id);
1163 rh->task_id = GNUNET_SCHEDULER_add_now (&GNS_resolver_lookup_cancel_,
1164 rh);
1113 } 1165 }
1114 else 1166 else
1115 { 1167 {
1116 rh->original_dns_id = p->id; 1168 rh->original_dns_id = p->id;
1117 rh->dns_request = GNUNET_DNSSTUB_resolve (dns_handle, 1169 GNUNET_assert (NULL != ac->authority_info.dns_authority.dns_handle);
1118 (const struct sockaddr *) &ac->authority_info.dns_authority.dns_ip, 1170 GNUNET_assert (NULL == rh->dns_request);
1119 sa_len, 1171 rh->dns_request = GNUNET_DNSSTUB_resolve (ac->authority_info.dns_authority.dns_handle,
1120 dns_request, 1172 dns_request,
1121 dns_request_length, 1173 dns_request_length,
1122 &dns_result_parser, 1174 &dns_result_parser,
1123 rh); 1175 rh);
1124 rh->task_id = GNUNET_SCHEDULER_add_delayed (DNS_LOOKUP_TIMEOUT, 1176 rh->task_id = GNUNET_SCHEDULER_add_delayed (DNS_LOOKUP_TIMEOUT,
1125 &fail_resolution, 1177 &timeout_resolution,
1126 rh); 1178 rh);
1127 } 1179 }
1128 if (GNUNET_SYSERR != ret) 1180 if (GNUNET_SYSERR != ret)
@@ -1293,15 +1345,47 @@ vpn_allocation_cb (void *cls,
1293 1345
1294 1346
1295/** 1347/**
1348 * We have resolved one or more of the nameservers for a
1349 * GNS2DNS lookup. Once we have some of them, begin using
1350 * the DNSSTUB resolver.
1351 *
1352 * @param ac context for GNS2DNS resolution
1353 */
1354static void
1355continue_with_gns2dns (struct AuthorityChain *ac)
1356{
1357 struct GNS_ResolverHandle *rh = ac->rh;
1358
1359 if ( (NULL != ac->authority_info.dns_authority.gp_head) &&
1360 (GNUNET_NO == ac->authority_info.dns_authority.found) )
1361 return; /* more pending and none found yet */
1362 if (GNUNET_NO == ac->authority_info.dns_authority.found)
1363 {
1364 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1365 "Failed to resolve DNS server for `%s' in GNS2DNS resolution\n",
1366 ac->authority_info.dns_authority.name);
1367 fail_resolution (rh);
1368 return;
1369 }
1370 if (GNUNET_NO != ac->authority_info.dns_authority.launched)
1371 return; /* already running, do not launch again! */
1372 /* recurse */
1373 ac->authority_info.dns_authority.launched = GNUNET_YES;
1374 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1375 "Will continue resolution using DNS to resolve `%s'\n",
1376 ac->label);
1377 GNUNET_assert (NULL == rh->task_id);
1378 rh->task_id = GNUNET_SCHEDULER_add_now (&recursive_resolution,
1379 rh);
1380
1381}
1382
1383
1384/**
1296 * We've resolved the IP address for the DNS resolver to use 1385 * We've resolved the IP address for the DNS resolver to use
1297 * after encountering a GNS2DNS record. 1386 * after encountering a GNS2DNS record.
1298 * 1387 *
1299 * TODO: Right now we only foward the request to ONE DNS resolver, 1388 * @param cls the `struct Gns2DnsPending` used for this request
1300 * even if we get multiple IP addresses back; a correct implementation
1301 * should try all DNS resolvers.
1302 *
1303 * @param cls the `struct GNS_ResolverHandle` where we encountered
1304 * the GNS2DNS record
1305 * @param rd_count number of records in @a rd 1389 * @param rd_count number of records in @a rd
1306 * @param rd addresses for the DNS resolver (presumably) 1390 * @param rd addresses for the DNS resolver (presumably)
1307 */ 1391 */
@@ -1310,136 +1394,96 @@ handle_gns2dns_result (void *cls,
1310 unsigned int rd_count, 1394 unsigned int rd_count,
1311 const struct GNUNET_GNSRECORD_Data *rd) 1395 const struct GNUNET_GNSRECORD_Data *rd)
1312{ 1396{
1313 struct GNS_ResolverHandle *rh = cls; 1397 struct Gns2DnsPending *gp = cls;
1314 struct AuthorityChain *ac; 1398 struct AuthorityChain *ac = gp->ac;
1315 struct sockaddr *sa; 1399
1316 struct sockaddr_in v4; 1400 GNUNET_CONTAINER_DLL_remove (ac->authority_info.dns_authority.gp_head,
1317 struct sockaddr_in6 v6; 1401 ac->authority_info.dns_authority.gp_tail,
1318 size_t sa_len; 1402 gp);
1319 1403 /* enable cleanup of 'rh' handle that automatically comes after we return,
1320 /* find suitable A/AAAA record */ 1404 and which expects 'rh' to be in the #rlh_head DLL. */
1321 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1405 if (NULL != gp->rh)
1322 "Received %u results for IP address of DNS server for GNS2DNS transition\n",
1323 rd_count);
1324 /* enable cleanup of 'rh' handle that comes next... */
1325 if (NULL != rh->g2dc->rh)
1326 { 1406 {
1327 GNUNET_CONTAINER_DLL_insert (rlh_head, 1407 GNUNET_CONTAINER_DLL_insert (rlh_head,
1328 rlh_tail, 1408 rlh_tail,
1329 rh->g2dc->rh); 1409 gp->rh);
1330 rh->g2dc->rh = NULL; 1410 gp->rh = NULL;
1331 } 1411 }
1332 sa = NULL; 1412 GNUNET_free (gp);
1333 sa_len = 0; 1413 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1414 "Received %u results for IP address of DNS server for GNS2DNS transition\n",
1415 rd_count);
1416 /* find suitable A/AAAA record */
1334 for (unsigned int j=0;j<rd_count;j++) 1417 for (unsigned int j=0;j<rd_count;j++)
1335 { 1418 {
1336 switch (rd[j].record_type) 1419 switch (rd[j].record_type)
1337 { 1420 {
1338 case GNUNET_DNSPARSER_TYPE_A: 1421 case GNUNET_DNSPARSER_TYPE_A:
1339 if (sizeof (struct in_addr) != rd[j].data_size)
1340 { 1422 {
1341 GNUNET_break_op (0); 1423 struct sockaddr_in v4;
1342 rh->proc (rh->proc_cls, 0, NULL); 1424
1343 GNS_resolver_lookup_cancel (rh); 1425 if (sizeof (struct in_addr) != rd[j].data_size)
1344 return; 1426 {
1345 } 1427 GNUNET_break_op (0);
1346 /* FIXME: might want to check if we support IPv4 here, 1428 continue;
1347 and otherwise skip this one and hope we find another */ 1429 }
1348 memset (&v4, 0, sizeof (v4)); 1430 memset (&v4,
1349 sa_len = sizeof (v4); 1431 0,
1350 v4.sin_family = AF_INET; 1432 sizeof (v4));
1351 v4.sin_port = htons (53); 1433 v4.sin_family = AF_INET;
1434 v4.sin_port = htons (53);
1352#if HAVE_SOCKADDR_IN_SIN_LEN 1435#if HAVE_SOCKADDR_IN_SIN_LEN
1353 v4.sin_len = (u_char) sa_len; 1436 v4.sin_len = (u_char) sizeof (v4);
1354#endif 1437#endif
1355 GNUNET_memcpy (&v4.sin_addr, 1438 GNUNET_memcpy (&v4.sin_addr,
1356 rd[j].data, 1439 rd[j].data,
1357 sizeof (struct in_addr)); 1440 sizeof (struct in_addr));
1358 sa = (struct sockaddr *) &v4; 1441 if (GNUNET_OK ==
1359 break; 1442 GNUNET_DNSSTUB_add_dns_sa (ac->authority_info.dns_authority.dns_handle,
1443 (const struct sockaddr *) &v4))
1444 ac->authority_info.dns_authority.found = GNUNET_YES;
1445 break;
1446 }
1360 case GNUNET_DNSPARSER_TYPE_AAAA: 1447 case GNUNET_DNSPARSER_TYPE_AAAA:
1361 if (sizeof (struct in6_addr) != rd[j].data_size)
1362 { 1448 {
1363 GNUNET_break_op (0); 1449 struct sockaddr_in6 v6;
1364 rh->proc (rh->proc_cls, 0, NULL); 1450
1365 GNS_resolver_lookup_cancel (rh); 1451 if (sizeof (struct in6_addr) != rd[j].data_size)
1366 return; 1452 {
1367 } 1453 GNUNET_break_op (0);
1368 /* FIXME: might want to check if we support IPv6 here, 1454 continue;
1369 and otherwise skip this one and hope we find another */ 1455 }
1370 memset (&v6, 0, sizeof (v6)); 1456 /* FIXME: might want to check if we support IPv6 here,
1371 sa_len = sizeof (v6); 1457 and otherwise skip this one and hope we find another */
1372 v6.sin6_family = AF_INET6; 1458 memset (&v6,
1373 v6.sin6_port = htons (53); 1459 0,
1460 sizeof (v6));
1461 v6.sin6_family = AF_INET6;
1462 v6.sin6_port = htons (53);
1374#if HAVE_SOCKADDR_IN_SIN_LEN 1463#if HAVE_SOCKADDR_IN_SIN_LEN
1375 v6.sin6_len = (u_char) sa_len; 1464 v6.sin6_len = (u_char) sizeof (v6);
1376#endif 1465#endif
1377 GNUNET_memcpy (&v6.sin6_addr, 1466 GNUNET_memcpy (&v6.sin6_addr,
1378 rd[j].data, 1467 rd[j].data,
1379 sizeof (struct in6_addr)); 1468 sizeof (struct in6_addr));
1380 sa = (struct sockaddr *) &v6; 1469 if (GNUNET_OK ==
1381 break; 1470 GNUNET_DNSSTUB_add_dns_sa (ac->authority_info.dns_authority.dns_handle,
1471 (const struct sockaddr *) &v6))
1472 ac->authority_info.dns_authority.found = GNUNET_YES;
1473 break;
1474 }
1382 default: 1475 default:
1383 break; 1476 break;
1384 } 1477 }
1385 if (NULL != sa)
1386 break;
1387 }
1388 if (NULL == sa)
1389 {
1390 /* we cannot continue; NS without A/AAAA */
1391 rh->proc (rh->proc_cls, 0, NULL);
1392 GNS_resolver_lookup_cancel (rh);
1393 return;
1394 }
1395 /* expand authority chain */
1396 ac = GNUNET_new (struct AuthorityChain);
1397 ac->rh = rh;
1398 GNUNET_assert (strlen (rh->g2dc->ns) <= GNUNET_DNSPARSER_MAX_NAME_LENGTH);
1399 strcpy (ac->authority_info.dns_authority.name,
1400 rh->g2dc->ns);
1401 GNUNET_memcpy (&ac->authority_info.dns_authority.dns_ip,
1402 sa,
1403 sa_len);
1404 /* for DNS recursion, the label is the full DNS name,
1405 created from the remainder of the GNS name and the
1406 name in the NS record */
1407 GNUNET_asprintf (&ac->label,
1408 "%.*s%s%s",
1409 (int) rh->name_resolution_pos,
1410 rh->name,
1411 (0 != rh->name_resolution_pos) ? "." : "",
1412 rh->g2dc->ns);
1413 GNUNET_free (rh->g2dc->ns);
1414 GNUNET_free (rh->g2dc);
1415 rh->g2dc = NULL;
1416 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1417 "Will continue resolution using DNS server `%s' to resolve `%s'\n",
1418 GNUNET_a2s (sa,
1419 sa_len),
1420 ac->label);
1421 GNUNET_CONTAINER_DLL_insert_tail (rh->ac_head,
1422 rh->ac_tail,
1423 ac);
1424 if (strlen (ac->label) > GNUNET_DNSPARSER_MAX_NAME_LENGTH)
1425 {
1426 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1427 _("GNS lookup resulted in DNS name that is too long (`%s')\n"),
1428 ac->label);
1429 rh->proc (rh->proc_cls, 0, NULL);
1430 GNS_resolver_lookup_cancel (rh);
1431 return;
1432 } 1478 }
1433 /* recurse */ 1479 continue_with_gns2dns (ac);
1434 rh->task_id = GNUNET_SCHEDULER_add_now (&recursive_resolution,
1435 rh);
1436} 1480}
1437 1481
1438 1482
1439/** 1483/**
1440 * Function called by the resolver for each address obtained from DNS. 1484 * Function called by the resolver for each address obtained from DNS.
1441 * 1485 *
1442 * @param cls closure, a `struct Gns2DnsContext *` 1486 * @param cls closure, a `struct Gns2DnsPending *`
1443 * @param addr one of the addresses of the host, NULL for the last address 1487 * @param addr one of the addresses of the host, NULL for the last address
1444 * @param addrlen length of @a addr 1488 * @param addrlen length of @a addr
1445 */ 1489 */
@@ -1448,57 +1492,270 @@ handle_gns2dns_ip (void *cls,
1448 const struct sockaddr *addr, 1492 const struct sockaddr *addr,
1449 socklen_t addrlen) 1493 socklen_t addrlen)
1450{ 1494{
1451 struct Gns2DnsContext *g2dc = cls; 1495 struct Gns2DnsPending *gp = cls;
1452 struct GNUNET_GNSRECORD_Data rd; 1496 struct AuthorityChain *ac = gp->ac;
1453 1497
1498 GNUNET_RESOLVER_request_cancel (gp->dns_rh);
1499 GNUNET_CONTAINER_DLL_remove (ac->authority_info.dns_authority.gp_head,
1500 ac->authority_info.dns_authority.gp_tail,
1501 gp);
1502 GNUNET_free (gp);
1454 if (NULL == addr) 1503 if (NULL == addr)
1455 { 1504 {
1456 /* DNS resolution failed */ 1505 /* DNS resolution failed */
1457 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 1506 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1458 "Failed to use DNS to resolve name of DNS resolver\n"); 1507 "Failed to use DNS to resolve name of DNS resolver\n");
1459 g2dc->rh->g2dc = NULL;
1460 fail_resolution (g2dc->rh);
1461 GNUNET_free (g2dc);
1462 } 1508 }
1463 switch (addr->sa_family) 1509 else
1464 { 1510 {
1465 case AF_INET: 1511 if (GNUNET_OK ==
1512 GNUNET_DNSSTUB_add_dns_sa (ac->authority_info.dns_authority.dns_handle,
1513 addr))
1514 ac->authority_info.dns_authority.found = GNUNET_YES;
1515 }
1516 continue_with_gns2dns (ac);
1517}
1518
1519
1520/**
1521 * We found a CNAME record, perform recursive resolution on it.
1522 *
1523 * @param rh resolution handle
1524 * @param rd record with CNAME to resolve recursively
1525 */
1526static void
1527recursive_cname_resolution (struct GNS_ResolverHandle *rh,
1528 const struct GNUNET_GNSRECORD_Data *rd)
1529{
1530 char *cname;
1531 size_t off;
1532
1533 off = 0;
1534 cname = GNUNET_DNSPARSER_parse_name (rd->data,
1535 rd->data_size,
1536 &off);
1537 if ( (NULL == cname) ||
1538 (off != rd->data_size) )
1539 {
1540 GNUNET_break_op (0); /* record not well-formed */
1541 GNUNET_free_non_null (cname);
1542 fail_resolution (rh);
1543 return;
1544 }
1545 handle_gns_cname_result (rh,
1546 cname);
1547 GNUNET_free (cname);
1548}
1549
1550
1551/**
1552 * We found a PKEY record, perform recursive resolution on it.
1553 *
1554 * @param rh resolution handle
1555 * @param rd record with PKEY to resolve recursively
1556 */
1557static void
1558recursive_pkey_resolution (struct GNS_ResolverHandle *rh,
1559 const struct GNUNET_GNSRECORD_Data *rd)
1560{
1561 struct AuthorityChain *ac;
1562
1563 /* delegation to another zone */
1564 if (sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey) !=
1565 rd->data_size)
1566 {
1567 GNUNET_break_op (0);
1568 fail_resolution (rh);
1569 return;
1570 }
1571 /* expand authority chain */
1572 ac = GNUNET_new (struct AuthorityChain);
1573 ac->rh = rh;
1574 ac->gns_authority = GNUNET_YES;
1575 ac->suggested_shortening_label = NULL;
1576 ac->shortening_started = GNUNET_NO;
1577 GNUNET_memcpy (&ac->authority_info.gns_authority,
1578 rd->data,
1579 sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
1580 ac->label = resolver_lookup_get_next_label (rh);
1581 /* add AC to tail */
1582 GNUNET_CONTAINER_DLL_insert_tail (rh->ac_head,
1583 rh->ac_tail,
1584 ac);
1585 /* recurse */
1586 rh->task_id = GNUNET_SCHEDULER_add_now (&recursive_resolution,
1587 rh);
1588}
1589
1590
1591/**
1592 * We found one or more GNS2DNS records, perform recursive resolution on it.
1593 * (to be precise, one or more records in @a rd is GNS2DNS, there may be others,
1594 * so this function still needs to check which ones are GNS2DNS).
1595 *
1596 * @param rh resolution handle
1597 * @param rd_count length of the @a rd array
1598 * @param rd record with PKEY to resolve recursively
1599 * @return #GNUNET_OK if this worked, #GNUNET_SYSERR if no GNS2DNS records were in @a rd
1600 */
1601static int
1602recursive_gns2dns_resolution (struct GNS_ResolverHandle *rh,
1603 unsigned int rd_count,
1604 const struct GNUNET_GNSRECORD_Data *rd)
1605{
1606 struct AuthorityChain *ac;
1607 const char *tld;
1608 char *ns;
1609
1610 ns = NULL;
1611 /* expand authority chain */
1612 ac = GNUNET_new (struct AuthorityChain);
1613 ac->rh = rh;
1614 ac->authority_info.dns_authority.dns_handle = GNUNET_DNSSTUB_start (4);
1615
1616 for (unsigned int i=0;i<rd_count;i++)
1617 {
1618 char *ip;
1619 char *n;
1620 size_t off;
1621 struct Gns2DnsPending *gp;
1622 struct GNUNET_CRYPTO_EcdsaPublicKey zone;
1623
1624 if (GNUNET_GNSRECORD_TYPE_GNS2DNS != rd[i].record_type)
1625 continue;
1626 off = 0;
1627 n = GNUNET_DNSPARSER_parse_name (rd[i].data,
1628 rd[i].data_size,
1629 &off);
1630 ip = GNUNET_DNSPARSER_parse_name (rd[i].data,
1631 rd[i].data_size,
1632 &off);
1633 if ( (NULL == n) ||
1634 (NULL == ip) ||
1635 (off != rd[i].data_size) )
1466 { 1636 {
1467 const struct sockaddr_in *v4 = (const struct sockaddr_in *) addr; 1637 GNUNET_break_op (0);
1468 1638 GNUNET_free_non_null (n);
1469 GNUNET_assert (sizeof (*v4) == addrlen); 1639 GNUNET_free_non_null (ip);
1470 rd.data = v4; 1640 continue;
1471 rd.data_size = sizeof (*v4);
1472 rd.expiration_time = UINT64_MAX;
1473 rd.record_type = GNUNET_DNSPARSER_TYPE_A;
1474 rd.flags = 0;
1475 break;
1476 } 1641 }
1477 case AF_INET6: 1642 /* resolve 'ip' to determine the IP(s) of the DNS
1643 resolver to use for lookup of 'ns' */
1644 if (NULL != ns)
1478 { 1645 {
1479 const struct sockaddr_in6 *v6 = (const struct sockaddr_in6 *) addr; 1646 if (0 != strcasecmp (ns,
1480 1647 n))
1481 GNUNET_assert (sizeof (*v6) == addrlen); 1648 {
1482 rd.data = v6; 1649 /* NS values must all be the same for all GNS2DNS records,
1483 rd.data_size = sizeof (v6); 1650 anything else leads to insanity */
1484 rd.expiration_time = UINT64_MAX; 1651 GNUNET_break_op (0);
1485 rd.record_type = GNUNET_DNSPARSER_TYPE_AAAA; 1652 GNUNET_free (n);
1486 rd.flags = 0; 1653 GNUNET_free (ip);
1487 break; 1654 continue;
1655 }
1656 GNUNET_free (n);
1657 }
1658 else
1659 {
1660 ns = n;
1488 } 1661 }
1489 default:
1490 return;
1491 }
1492 GNUNET_RESOLVER_request_cancel (g2dc->dns_rh);
1493 g2dc->dns_rh = NULL;
1494 handle_gns2dns_result (g2dc->rh,
1495 1,
1496 &rd);
1497 1662
1663 /* check if 'ip' is already an IPv4/IPv6 address */
1664 if (GNUNET_OK ==
1665 GNUNET_DNSSTUB_add_dns_ip (ac->authority_info.dns_authority.dns_handle,
1666 ip))
1667 {
1668 ac->authority_info.dns_authority.found = GNUNET_YES;
1669 GNUNET_free (ip);
1670 continue;
1671 }
1672 tld = GNS_get_tld (ip);
1673 if (0 != strcmp (tld,
1674 "+"))
1675 {
1676 /* 'ip' is a DNS name */
1677 gp = GNUNET_new (struct Gns2DnsPending);
1678 gp->ac = ac;
1679 GNUNET_CONTAINER_DLL_insert (ac->authority_info.dns_authority.gp_head,
1680 ac->authority_info.dns_authority.gp_tail,
1681 gp);
1682 gp->dns_rh = GNUNET_RESOLVER_ip_get (ip,
1683 AF_UNSPEC,
1684 GNUNET_TIME_UNIT_FOREVER_REL,
1685 &handle_gns2dns_ip,
1686 gp);
1687 GNUNET_free (ip);
1688 continue;
1689 }
1690 /* 'ip' should be a GNS name */
1691 gp = GNUNET_new (struct Gns2DnsPending);
1692 gp->ac = ac;
1693 GNUNET_CONTAINER_DLL_insert (ac->authority_info.dns_authority.gp_head,
1694 ac->authority_info.dns_authority.gp_tail,
1695 gp);
1696 gp->rh = GNUNET_new (struct GNS_ResolverHandle);
1697 ip = translate_dot_plus (rh,
1698 ip);
1699 tld = GNS_get_tld (ip);
1700 if (GNUNET_OK !=
1701 GNUNET_GNSRECORD_zkey_to_pkey (tld,
1702 &zone))
1703 {
1704 GNUNET_break_op (0);
1705 GNUNET_free (ip);
1706 continue;
1707 }
1708 gp->rh->authority_zone = zone;
1709 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1710 "Resolving `%s' to determine IP address of DNS server for GNS2DNS transition for `%s'\n",
1711 ip,
1712 ns);
1713 gp->rh->name = ip;
1714 gp->rh->name_resolution_pos = strlen (ip) - strlen (tld) - 1;
1715 gp->rh->proc = &handle_gns2dns_result;
1716 gp->rh->proc_cls = gp;
1717 gp->rh->record_type = GNUNET_GNSRECORD_TYPE_ANY;
1718 gp->rh->options = GNUNET_GNS_LO_DEFAULT;
1719 gp->rh->loop_limiter = rh->loop_limiter + 1;
1720 gp->rh->task_id
1721 = GNUNET_SCHEDULER_add_now (&start_resolver_lookup,
1722 gp->rh);
1723 } /* end 'for all records' */
1724
1725 if (NULL == ns)
1726 {
1727 /* not a single GNS2DNS record found */
1728 GNUNET_free (ac);
1729 return GNUNET_SYSERR;
1730 }
1731 GNUNET_assert (strlen (ns) <= GNUNET_DNSPARSER_MAX_NAME_LENGTH);
1732 strcpy (ac->authority_info.dns_authority.name,
1733 ns);
1734 /* for DNS recursion, the label is the full DNS name,
1735 created from the remainder of the GNS name and the
1736 name in the NS record */
1737 GNUNET_asprintf (&ac->label,
1738 "%.*s%s%s",
1739 (int) rh->name_resolution_pos,
1740 rh->name,
1741 (0 != rh->name_resolution_pos) ? "." : "",
1742 ns);
1743 GNUNET_free (ns);
1744 GNUNET_CONTAINER_DLL_insert_tail (rh->ac_head,
1745 rh->ac_tail,
1746 ac);
1747 if (strlen (ac->label) > GNUNET_DNSPARSER_MAX_NAME_LENGTH)
1748 {
1749 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1750 _("GNS lookup resulted in DNS name that is too long (`%s')\n"),
1751 ac->label);
1752 return GNUNET_SYSERR;
1753 }
1754 continue_with_gns2dns (ac);
1755 return GNUNET_OK;
1498} 1756}
1499 1757
1500 1758
1501
1502/** 1759/**
1503 * Process a records that were decrypted from a block. 1760 * Process a records that were decrypted from a block.
1504 * 1761 *
@@ -1512,7 +1769,6 @@ handle_gns_resolution_result (void *cls,
1512 const struct GNUNET_GNSRECORD_Data *rd) 1769 const struct GNUNET_GNSRECORD_Data *rd)
1513{ 1770{
1514 struct GNS_ResolverHandle *rh = cls; 1771 struct GNS_ResolverHandle *rh = cls;
1515 struct AuthorityChain *ac;
1516 struct AuthorityChain *shorten_ac; 1772 struct AuthorityChain *shorten_ac;
1517 char *cname; 1773 char *cname;
1518 struct VpnContext *vpn_ctx; 1774 struct VpnContext *vpn_ctx;
@@ -1532,6 +1788,14 @@ handle_gns_resolution_result (void *cls,
1532 rh->ac_tail->label, 1788 rh->ac_tail->label,
1533 GNUNET_GNSRECORD_z2s (&rh->ac_tail->authority_info.gns_authority), 1789 GNUNET_GNSRECORD_z2s (&rh->ac_tail->authority_info.gns_authority),
1534 rd_count); 1790 rd_count);
1791 if (0 == rd_count)
1792 {
1793 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1794 _("GNS lookup failed (zero records found)\n"));
1795 fail_resolution (rh);
1796 return;
1797 }
1798
1535 if (0 == rh->name_resolution_pos) 1799 if (0 == rh->name_resolution_pos)
1536 { 1800 {
1537 /* top-level match, are we done yet? */ 1801 /* top-level match, are we done yet? */
@@ -1547,9 +1811,8 @@ handle_gns_resolution_result (void *cls,
1547 (off != rd[0].data_size) ) 1811 (off != rd[0].data_size) )
1548 { 1812 {
1549 GNUNET_break_op (0); 1813 GNUNET_break_op (0);
1550 rh->proc (rh->proc_cls, 0, NULL);
1551 GNS_resolver_lookup_cancel (rh);
1552 GNUNET_free_non_null (cname); 1814 GNUNET_free_non_null (cname);
1815 fail_resolution (rh);
1553 return; 1816 return;
1554 } 1817 }
1555 handle_gns_cname_result (rh, 1818 handle_gns_cname_result (rh,
@@ -1573,8 +1836,7 @@ handle_gns_resolution_result (void *cls,
1573 rd[i].data_size) 1836 rd[i].data_size)
1574 { 1837 {
1575 GNUNET_break_op (0); 1838 GNUNET_break_op (0);
1576 rh->proc (rh->proc_cls, 0, NULL); 1839 fail_resolution (rh);
1577 GNS_resolver_lookup_cancel (rh);
1578 return; 1840 return;
1579 } 1841 }
1580 vpn = (const struct GNUNET_TUN_GnsVpnRecord *) rd[i].data; 1842 vpn = (const struct GNUNET_TUN_GnsVpnRecord *) rd[i].data;
@@ -1582,8 +1844,7 @@ handle_gns_resolution_result (void *cls,
1582 if ('\0' != vname[rd[i].data_size - 1 - sizeof (struct GNUNET_TUN_GnsVpnRecord)]) 1844 if ('\0' != vname[rd[i].data_size - 1 - sizeof (struct GNUNET_TUN_GnsVpnRecord)])
1583 { 1845 {
1584 GNUNET_break_op (0); 1846 GNUNET_break_op (0);
1585 rh->proc (rh->proc_cls, 0, NULL); 1847 fail_resolution (rh);
1586 GNS_resolver_lookup_cancel (rh);
1587 return; 1848 return;
1588 } 1849 }
1589 GNUNET_TUN_service_name_to_hash (vname, 1850 GNUNET_TUN_service_name_to_hash (vname,
@@ -1621,7 +1882,13 @@ handle_gns_resolution_result (void *cls,
1621 /* delegation to DNS */ 1882 /* delegation to DNS */
1622 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1883 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1623 "Found GNS2DNS record, delegating to DNS!\n"); 1884 "Found GNS2DNS record, delegating to DNS!\n");
1624 goto do_recurse; 1885 if (GNUNET_OK ==
1886 recursive_gns2dns_resolution (rh,
1887 rd_count,
1888 rd))
1889 return;
1890 else
1891 goto fail;
1625 } 1892 }
1626 default: 1893 default:
1627 break; 1894 break;
@@ -1823,7 +2090,9 @@ handle_gns_resolution_result (void *cls,
1823 GNUNET_break_op (0); 2090 GNUNET_break_op (0);
1824 break; 2091 break;
1825 } 2092 }
1826 GNUNET_memcpy (&pub, rd[i].data, rd[i].data_size); 2093 GNUNET_memcpy (&pub,
2094 rd[i].data,
2095 rd[i].data_size);
1827 rd_off++; 2096 rd_off++;
1828 if (GNUNET_GNSRECORD_TYPE_PKEY != rh->record_type) 2097 if (GNUNET_GNSRECORD_TYPE_PKEY != rh->record_type)
1829 { 2098 {
@@ -1856,7 +2125,13 @@ handle_gns_resolution_result (void *cls,
1856 } 2125 }
1857 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 2126 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1858 "Found GNS2DNS record, delegating to DNS!\n"); 2127 "Found GNS2DNS record, delegating to DNS!\n");
1859 goto do_recurse; 2128 if (GNUNET_OK ==
2129 recursive_gns2dns_resolution (rh,
2130 rd_count,
2131 rd))
2132 return;
2133 else
2134 goto fail;
1860 } 2135 }
1861 case GNUNET_GNSRECORD_TYPE_BOX: 2136 case GNUNET_GNSRECORD_TYPE_BOX:
1862 { 2137 {
@@ -1901,200 +2176,35 @@ handle_gns_resolution_result (void *cls,
1901 rh->proc (rh->proc_cls, 2176 rh->proc (rh->proc_cls,
1902 rd_off, 2177 rd_off,
1903 rd_new); 2178 rd_new);
1904 GNS_resolver_lookup_cancel (rh); 2179 rh->task_id = GNUNET_SCHEDULER_add_now (&GNS_resolver_lookup_cancel_,
2180 rh);
1905 return; 2181 return;
1906 } 2182 }
1907 do_recurse: 2183
1908 /* need to recurse, check if we can */ 2184 switch (rd[0].record_type)
1909 for (unsigned int i=0;i<rd_count;i++)
1910 { 2185 {
1911 switch (rd[i].record_type) 2186 case GNUNET_DNSPARSER_TYPE_CNAME:
1912 { 2187 GNUNET_break_op (1 == rd_count); /* CNAME should be unique */
1913 case GNUNET_GNSRECORD_TYPE_PKEY: 2188 recursive_cname_resolution (rh,
1914 /* delegation to another zone */ 2189 &rd[0]);
1915 if (sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey) != 2190 return;
1916 rd[i].data_size) 2191 case GNUNET_GNSRECORD_TYPE_PKEY:
1917 { 2192 GNUNET_break_op (1 == rd_count); /* PKEY should be unique */
1918 GNUNET_break_op (0); 2193 recursive_pkey_resolution (rh,
1919 rh->proc (rh->proc_cls, 0, NULL); 2194 &rd[0]);
1920 GNS_resolver_lookup_cancel (rh); 2195 return;
1921 return; 2196 default:
1922 } 2197 if (GNUNET_OK ==
1923 /* expand authority chain */ 2198 recursive_gns2dns_resolution (rh,
1924 ac = GNUNET_new (struct AuthorityChain); 2199 rd_count,
1925 ac->rh = rh; 2200 rd))
1926 ac->gns_authority = GNUNET_YES;
1927 ac->suggested_shortening_label = NULL;
1928 ac->shortening_started = GNUNET_NO;
1929 GNUNET_memcpy (&ac->authority_info.gns_authority,
1930 rd[i].data,
1931 sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
1932 ac->label = resolver_lookup_get_next_label (rh);
1933 /* add AC to tail */
1934 GNUNET_CONTAINER_DLL_insert_tail (rh->ac_head,
1935 rh->ac_tail,
1936 ac);
1937 /* recurse */
1938 rh->task_id = GNUNET_SCHEDULER_add_now (&recursive_resolution,
1939 rh);
1940 return; 2201 return;
1941 case GNUNET_GNSRECORD_TYPE_GNS2DNS: 2202 break;
1942 {
1943 /* TODO: Right now we only foward the request to ONE DNS resolver,
1944 even if we get multiple IP addresses back; a correct implementation
1945 should try all DNS resolvers. */
1946 /* resolution continues within DNS */
1947 struct Gns2DnsContext *g2dc;
1948 char *ip;
1949 char *ns;
1950 const char *tld;
1951 struct GNUNET_CRYPTO_EcdsaPublicKey zone;
1952 struct in_addr v4;
1953 struct in6_addr v6;
1954
1955 off = 0;
1956 ns = GNUNET_DNSPARSER_parse_name (rd[i].data,
1957 rd[i].data_size,
1958 &off);
1959 ip = GNUNET_DNSPARSER_parse_name (rd[i].data,
1960 rd[i].data_size,
1961 &off);
1962 if ( (NULL == ns) ||
1963 (NULL == ip) ||
1964 (off != rd[i].data_size) )
1965 {
1966 GNUNET_break_op (0);
1967 GNUNET_free_non_null (ns);
1968 GNUNET_free_non_null (ip);
1969 fail_resolution (rh);
1970 return;
1971 }
1972 /* resolve 'ip' to determine the IP(s) of the DNS
1973 resolver to use for lookup of 'ns' */
1974 g2dc = GNUNET_new (struct Gns2DnsContext);
1975 g2dc->ns = ns;
1976 rh->g2dc = g2dc;
1977
1978 /* check if 'ip' is already an IPv4/IPv6 address */
1979 if (1 == inet_pton (AF_INET,
1980 ip,
1981 &v4))
1982 {
1983 /* name is IPv4 address, pretend it's an A record */
1984 struct GNUNET_GNSRECORD_Data rd;
1985
1986 GNUNET_free (ip);
1987 rd.data = &v4;
1988 rd.data_size = sizeof (v4);
1989 rd.expiration_time = UINT64_MAX;
1990 rd.record_type = GNUNET_DNSPARSER_TYPE_A;
1991 rd.flags = 0;
1992 handle_gns2dns_result (rh,
1993 1,
1994 &rd);
1995 return;
1996 }
1997 if (1 == inet_pton (AF_INET6,
1998 ip,
1999 &v6))
2000 {
2001 /* name is IPv6 address, pretend it's an AAAA record */
2002 struct GNUNET_GNSRECORD_Data rd;
2003
2004 GNUNET_free (ip);
2005 rd.data = &v6;
2006 rd.data_size = sizeof (v6);
2007 rd.expiration_time = UINT64_MAX;
2008 rd.record_type = GNUNET_DNSPARSER_TYPE_AAAA;
2009 rd.flags = 0;
2010 handle_gns2dns_result (rh,
2011 1,
2012 &rd);
2013 return;
2014 }
2015
2016 tld = GNS_get_tld (ip);
2017 if (0 != strcmp (tld,
2018 "+"))
2019 {
2020 /* 'ip' is a DNS name */
2021 g2dc->dns_rh = GNUNET_RESOLVER_ip_get (ip,
2022 AF_UNSPEC,
2023 GNUNET_TIME_UNIT_FOREVER_REL,
2024 &handle_gns2dns_ip,
2025 g2dc);
2026 GNUNET_free (ip);
2027 return;
2028 }
2029
2030 /* 'ip' should be a GNS name */
2031 g2dc->rh = GNUNET_new (struct GNS_ResolverHandle);
2032
2033 ip = translate_dot_plus (rh,
2034 ip);
2035 tld = GNS_get_tld (ip);
2036 if (GNUNET_OK !=
2037 GNUNET_GNSRECORD_zkey_to_pkey (tld,
2038 &zone))
2039 {
2040 GNUNET_break_op (0);
2041 GNUNET_free_non_null (ns);
2042 GNUNET_free_non_null (ip);
2043 GNUNET_free (g2dc);
2044 fail_resolution (rh);
2045 return;
2046 }
2047 g2dc->rh->authority_zone = zone;
2048 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2049 "Resolving `%s' to determine IP address of DNS server for GNS2DNS transition for `%s'\n",
2050 ip,
2051 ns);
2052 g2dc->rh->name = ip;
2053 g2dc->rh->name_resolution_pos = strlen (ip) - strlen (tld) - 1;
2054 g2dc->rh->proc = &handle_gns2dns_result;
2055 g2dc->rh->proc_cls = rh;
2056 g2dc->rh->record_type = GNUNET_GNSRECORD_TYPE_ANY;
2057 g2dc->rh->options = GNUNET_GNS_LO_DEFAULT;
2058 g2dc->rh->loop_limiter = rh->loop_limiter + 1;
2059 g2dc->rh->task_id
2060 = GNUNET_SCHEDULER_add_now (&start_resolver_lookup,
2061 g2dc->rh);
2062 return;
2063 }
2064 case GNUNET_DNSPARSER_TYPE_CNAME:
2065 {
2066 char *cname;
2067
2068 off = 0;
2069 cname = GNUNET_DNSPARSER_parse_name (rd[i].data,
2070 rd[i].data_size,
2071 &off);
2072 if ( (NULL == cname) ||
2073 (off != rd[i].data_size) )
2074 {
2075 GNUNET_break_op (0); /* record not well-formed */
2076 rh->proc (rh->proc_cls, 0, NULL);
2077 GNS_resolver_lookup_cancel (rh);
2078 GNUNET_free_non_null (cname);
2079 return;
2080 }
2081 handle_gns_cname_result (rh,
2082 cname);
2083 GNUNET_free (cname);
2084 return;
2085 }
2086 /* FIXME: handle DNAME */
2087 default:
2088 /* skip */
2089 break;
2090 }
2091 } 2203 }
2204 fail:
2092 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 2205 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
2093 _("GNS lookup recursion failed (no delegation record found)\n")); 2206 _("GNS lookup recursion failed (no delegation record found)\n"));
2094 rh->proc (rh->proc_cls, 2207 fail_resolution (rh);
2095 0,
2096 NULL);
2097 GNS_resolver_lookup_cancel (rh);
2098} 2208}
2099 2209
2100 2210
@@ -2176,8 +2286,7 @@ handle_dht_response (void *cls,
2176 { 2286 {
2177 /* how did this pass DHT block validation!? */ 2287 /* how did this pass DHT block validation!? */
2178 GNUNET_break (0); 2288 GNUNET_break (0);
2179 rh->proc (rh->proc_cls, 0, NULL); 2289 fail_resolution (rh);
2180 GNS_resolver_lookup_cancel (rh);
2181 return; 2290 return;
2182 } 2291 }
2183 block = data; 2292 block = data;
@@ -2188,8 +2297,7 @@ handle_dht_response (void *cls,
2188 { 2297 {
2189 /* how did this pass DHT block validation!? */ 2298 /* how did this pass DHT block validation!? */
2190 GNUNET_break (0); 2299 GNUNET_break (0);
2191 rh->proc (rh->proc_cls, 0, NULL); 2300 fail_resolution (rh);
2192 GNS_resolver_lookup_cancel (rh);
2193 return; 2301 return;
2194 } 2302 }
2195 if (GNUNET_OK != 2303 if (GNUNET_OK !=
@@ -2200,8 +2308,7 @@ handle_dht_response (void *cls,
2200 rh)) 2308 rh))
2201 { 2309 {
2202 GNUNET_break_op (0); /* block was ill-formed */ 2310 GNUNET_break_op (0); /* block was ill-formed */
2203 rh->proc (rh->proc_cls, 0, NULL); 2311 fail_resolution (rh);
2204 GNS_resolver_lookup_cancel (rh);
2205 return; 2312 return;
2206 } 2313 }
2207 if (0 == GNUNET_TIME_absolute_get_remaining (GNUNET_TIME_absolute_ntoh (block->expiration_time)).rel_value_us) 2314 if (0 == GNUNET_TIME_absolute_get_remaining (GNUNET_TIME_absolute_ntoh (block->expiration_time)).rel_value_us)
@@ -2252,8 +2359,7 @@ start_dht_request (struct GNS_ResolverHandle *rh,
2252 /* fail longest-standing DHT request */ 2359 /* fail longest-standing DHT request */
2253 rx = GNUNET_CONTAINER_heap_peek (dht_lookup_heap); 2360 rx = GNUNET_CONTAINER_heap_peek (dht_lookup_heap);
2254 GNUNET_assert (NULL != rx); 2361 GNUNET_assert (NULL != rx);
2255 rx->proc (rx->proc_cls, 0, NULL); 2362 fail_resolution (rx);
2256 GNS_resolver_lookup_cancel (rx);
2257 } 2363 }
2258} 2364}
2259 2365
@@ -2324,8 +2430,7 @@ handle_namecache_block_response (void *cls,
2324 "Resolution failed for `%s' in zone %s (DHT lookup not permitted by configuration)\n", 2430 "Resolution failed for `%s' in zone %s (DHT lookup not permitted by configuration)\n",
2325 ac->label, 2431 ac->label,
2326 GNUNET_GNSRECORD_z2s (&ac->authority_info.gns_authority)); 2432 GNUNET_GNSRECORD_z2s (&ac->authority_info.gns_authority));
2327 rh->proc (rh->proc_cls, 0, NULL); 2433 fail_resolution (rh);
2328 GNS_resolver_lookup_cancel (rh);
2329 return; 2434 return;
2330 } 2435 }
2331 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 2436 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
@@ -2408,8 +2513,7 @@ handle_revocation_result (void *cls,
2408 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 2513 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
2409 _("Zone %s was revoked, resolution fails\n"), 2514 _("Zone %s was revoked, resolution fails\n"),
2410 GNUNET_GNSRECORD_z2s (&ac->authority_info.gns_authority)); 2515 GNUNET_GNSRECORD_z2s (&ac->authority_info.gns_authority));
2411 rh->proc (rh->proc_cls, 0, NULL); 2516 fail_resolution (rh);
2412 GNS_resolver_lookup_cancel (rh);
2413 return; 2517 return;
2414 } 2518 }
2415 recursive_gns_resolution_namecache (rh); 2519 recursive_gns_resolution_namecache (rh);
@@ -2453,8 +2557,7 @@ recursive_resolution (void *cls)
2453 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 2557 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
2454 "Encountered unbounded recursion resolving `%s'\n", 2558 "Encountered unbounded recursion resolving `%s'\n",
2455 rh->name); 2559 rh->name);
2456 rh->proc (rh->proc_cls, 0, NULL); 2560 fail_resolution (rh);
2457 GNS_resolver_lookup_cancel (rh);
2458 return; 2561 return;
2459 } 2562 }
2460 if (GNUNET_YES == rh->ac_tail->gns_authority) 2563 if (GNUNET_YES == rh->ac_tail->gns_authority)
@@ -2491,8 +2594,12 @@ start_resolver_lookup (void *cls)
2491 rd.expiration_time = UINT64_MAX; 2594 rd.expiration_time = UINT64_MAX;
2492 rd.record_type = GNUNET_DNSPARSER_TYPE_A; 2595 rd.record_type = GNUNET_DNSPARSER_TYPE_A;
2493 rd.flags = 0; 2596 rd.flags = 0;
2494 rh->proc (rh->proc_cls, 1, &rd); 2597 rh->proc (rh->proc_cls,
2495 GNS_resolver_lookup_cancel (rh); 2598 1,
2599 &rd);
2600 GNUNET_assert (NULL == rh->task_id);
2601 rh->task_id = GNUNET_SCHEDULER_add_now (&GNS_resolver_lookup_cancel_,
2602 rh);
2496 return; 2603 return;
2497 } 2604 }
2498 if (1 == inet_pton (AF_INET6, 2605 if (1 == inet_pton (AF_INET6,
@@ -2507,8 +2614,12 @@ start_resolver_lookup (void *cls)
2507 rd.expiration_time = UINT64_MAX; 2614 rd.expiration_time = UINT64_MAX;
2508 rd.record_type = GNUNET_DNSPARSER_TYPE_AAAA; 2615 rd.record_type = GNUNET_DNSPARSER_TYPE_AAAA;
2509 rd.flags = 0; 2616 rd.flags = 0;
2510 rh->proc (rh->proc_cls, 1, &rd); 2617 rh->proc (rh->proc_cls,
2511 GNS_resolver_lookup_cancel (rh); 2618 1,
2619 &rd);
2620 GNUNET_assert (NULL == rh->task_id);
2621 rh->task_id = GNUNET_SCHEDULER_add_now (&GNS_resolver_lookup_cancel_,
2622 rh);
2512 return; 2623 return;
2513 } 2624 }
2514 2625
@@ -2587,37 +2698,51 @@ GNS_resolver_lookup_cancel (struct GNS_ResolverHandle *rh)
2587 GNUNET_CONTAINER_DLL_remove (rlh_head, 2698 GNUNET_CONTAINER_DLL_remove (rlh_head,
2588 rlh_tail, 2699 rlh_tail,
2589 rh); 2700 rh);
2701 if (NULL != rh->dns_request)
2702 {
2703 GNUNET_DNSSTUB_resolve_cancel (rh->dns_request);
2704 rh->dns_request = NULL;
2705 }
2590 while (NULL != (ac = rh->ac_head)) 2706 while (NULL != (ac = rh->ac_head))
2591 { 2707 {
2592 GNUNET_CONTAINER_DLL_remove (rh->ac_head, 2708 GNUNET_CONTAINER_DLL_remove (rh->ac_head,
2593 rh->ac_tail, 2709 rh->ac_tail,
2594 ac); 2710 ac);
2711 if (GNUNET_NO == ac->gns_authority)
2712 {
2713 struct Gns2DnsPending *gp;
2714
2715 while (NULL != (gp = ac->authority_info.dns_authority.gp_head))
2716 {
2717 GNUNET_CONTAINER_DLL_remove (ac->authority_info.dns_authority.gp_head,
2718 ac->authority_info.dns_authority.gp_tail,
2719 gp);
2720 if (NULL != gp->rh)
2721 {
2722 /* rh->g2dc->rh is NOT in the DLL yet, so to enable us
2723 using GNS_resolver_lookup_cancel here, we need to
2724 add it first... */
2725 GNUNET_CONTAINER_DLL_insert (rlh_head,
2726 rlh_tail,
2727 gp->rh);
2728 GNUNET_assert (NULL == gp->rh->task_id);
2729 gp->rh->task_id = GNUNET_SCHEDULER_add_now (&GNS_resolver_lookup_cancel_,
2730 gp->rh);
2731 gp->rh = NULL;
2732 }
2733 if (NULL != gp->dns_rh)
2734 {
2735 GNUNET_RESOLVER_request_cancel (gp->dns_rh);
2736 gp->dns_rh = NULL;
2737 }
2738 GNUNET_free (gp);
2739 }
2740 GNUNET_DNSSTUB_stop (ac->authority_info.dns_authority.dns_handle);
2741 }
2595 GNUNET_free (ac->label); 2742 GNUNET_free (ac->label);
2596 GNUNET_free_non_null (ac->suggested_shortening_label); 2743 GNUNET_free_non_null (ac->suggested_shortening_label);
2597 GNUNET_free (ac); 2744 GNUNET_free (ac);
2598 } 2745 }
2599 if (NULL != rh->g2dc)
2600 {
2601 /* rh->g2dc->rh is NOT in the DLL yet, so to enable us
2602 using GNS_resolver_lookup_cancel here, we need to
2603 add it first... */
2604 if (NULL != rh->g2dc->rh)
2605 {
2606 GNUNET_CONTAINER_DLL_insert (rlh_head,
2607 rlh_tail,
2608 rh->g2dc->rh);
2609 GNS_resolver_lookup_cancel (rh->g2dc->rh);
2610 rh->g2dc->rh = NULL;
2611 }
2612 if (NULL != rh->g2dc->dns_rh)
2613 {
2614 GNUNET_RESOLVER_request_cancel (rh->g2dc->dns_rh);
2615 rh->g2dc->rh = NULL;
2616 }
2617 GNUNET_free (rh->g2dc->ns);
2618 GNUNET_free (rh->g2dc);
2619 rh->g2dc = NULL;
2620 }
2621 if (NULL != rh->task_id) 2746 if (NULL != rh->task_id)
2622 { 2747 {
2623 GNUNET_SCHEDULER_cancel (rh->task_id); 2748 GNUNET_SCHEDULER_cancel (rh->task_id);
@@ -2639,11 +2764,6 @@ GNS_resolver_lookup_cancel (struct GNS_ResolverHandle *rh)
2639 GNUNET_free (vpn_ctx->rd_data); 2764 GNUNET_free (vpn_ctx->rd_data);
2640 GNUNET_free (vpn_ctx); 2765 GNUNET_free (vpn_ctx);
2641 } 2766 }
2642 if (NULL != rh->dns_request)
2643 {
2644 GNUNET_DNSSTUB_resolve_cancel (rh->dns_request);
2645 rh->dns_request = NULL;
2646 }
2647 if (NULL != rh->namecache_qe) 2767 if (NULL != rh->namecache_qe)
2648 { 2768 {
2649 GNUNET_NAMECACHE_cancel (rh->namecache_qe); 2769 GNUNET_NAMECACHE_cancel (rh->namecache_qe);
@@ -2690,8 +2810,6 @@ GNS_resolver_init (struct GNUNET_NAMECACHE_Handle *nc,
2690 const struct GNUNET_CONFIGURATION_Handle *c, 2810 const struct GNUNET_CONFIGURATION_Handle *c,
2691 unsigned long long max_bg_queries) 2811 unsigned long long max_bg_queries)
2692{ 2812{
2693 char *dns_ip;
2694
2695 cfg = c; 2813 cfg = c;
2696 namecache_handle = nc; 2814 namecache_handle = nc;
2697 dht_handle = dht; 2815 dht_handle = dht;
@@ -2706,18 +2824,6 @@ GNS_resolver_init (struct GNUNET_NAMECACHE_Handle *nc,
2706 if (GNUNET_NO == use_cache) 2824 if (GNUNET_NO == use_cache)
2707 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 2825 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2708 "Namecache disabled\n"); 2826 "Namecache disabled\n");
2709
2710 if (GNUNET_OK !=
2711 GNUNET_CONFIGURATION_get_value_string (c,
2712 "gns",
2713 "DNS_RESOLVER",
2714 &dns_ip))
2715 {
2716 /* user did not specify DNS resolver, use 8.8.8.8 */
2717 dns_ip = GNUNET_strdup ("8.8.8.8");
2718 }
2719 dns_handle = GNUNET_DNSSTUB_start (dns_ip);
2720 GNUNET_free (dns_ip);
2721 vpn_handle = GNUNET_VPN_connect (cfg); 2827 vpn_handle = GNUNET_VPN_connect (cfg);
2722} 2828}
2723 2829
@@ -2734,7 +2840,9 @@ GNS_resolver_done ()
2734 /* abort active resolutions */ 2840 /* abort active resolutions */
2735 while (NULL != (rh = rlh_head)) 2841 while (NULL != (rh = rlh_head))
2736 { 2842 {
2737 rh->proc (rh->proc_cls, 0, NULL); 2843 rh->proc (rh->proc_cls,
2844 0,
2845 NULL);
2738 GNS_resolver_lookup_cancel (rh); 2846 GNS_resolver_lookup_cancel (rh);
2739 } 2847 }
2740 while (NULL != (co = co_head)) 2848 while (NULL != (co = co_head))
@@ -2747,8 +2855,6 @@ GNS_resolver_done ()
2747 } 2855 }
2748 GNUNET_CONTAINER_heap_destroy (dht_lookup_heap); 2856 GNUNET_CONTAINER_heap_destroy (dht_lookup_heap);
2749 dht_lookup_heap = NULL; 2857 dht_lookup_heap = NULL;
2750 GNUNET_DNSSTUB_stop (dns_handle);
2751 dns_handle = NULL;
2752 GNUNET_VPN_disconnect (vpn_handle); 2858 GNUNET_VPN_disconnect (vpn_handle);
2753 vpn_handle = NULL; 2859 vpn_handle = NULL;
2754 dht_handle = NULL; 2860 dht_handle = NULL;
diff --git a/src/gns/test_gns_lookup.conf b/src/gns/test_gns_lookup.conf
index ea8c7c3fc..a9a2345c7 100644
--- a/src/gns/test_gns_lookup.conf
+++ b/src/gns/test_gns_lookup.conf
@@ -10,7 +10,7 @@ AUTOSTART = YES
10PLUGINS = 10PLUGINS =
11 11
12[gns] 12[gns]
13#PREFIX = valgrind --leak-check=full --track-origins=yes 13# PREFIX = valgrind --leak-check=full --track-origins=yes
14AUTOSTART = YES 14AUTOSTART = YES
15AUTO_IMPORT_PKEY = YES 15AUTO_IMPORT_PKEY = YES
16MAX_PARALLEL_BACKGROUND_QUERIES = 10 16MAX_PARALLEL_BACKGROUND_QUERIES = 10