2 This file is part of GNUnet.
3 (C) 2012, 2013 Christian Grothoff (and other contributing authors)
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
23 * @file gns/test_gns_ns_lookup.c
24 * @brief base testcase for testing a local GNS record lookup through NS
25 * @author Martin Schanzenbach
28 #include "gnunet_testing_lib.h"
29 #include "gnunet_core_service.h"
30 #include "block_dns.h"
31 #include "gnunet_signatures.h"
32 #include "gnunet_namestore_service.h"
33 #include "gnunet_resolver_service.h"
34 #include "gnunet_dnsparser_lib.h"
35 #include "gnunet_gns_service.h"
38 * Timeout for entire testcase
40 #define TIMEOUT GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 20)
43 * Name to resolve for testing. NS record on 'homepage.gnu' redirects to
44 * DNS 'TEST_RECORD_NS' domain and thus names should be resolved within
47 #define TEST_DOMAIN "www.homepage.gnu"
50 * Name to resolve for testing. NS record on 'homepage.gnu' redirects to
51 * DNS 'TEST_RECORD_NS' domain and thus names should be resolved within
54 #define TEST_DOMAIN_ALT "homepage.gnu"
57 * Name to resolve for testing. NS record on 'homepage.gnu' redirects to
58 * DNS 'TEST_RECORD_NS' domain and thus names should be resolved within
61 #define TEST_DOMAIN_ALT2 "uk.homepage.gnu"
64 * Expected test value (matching TEST_DOMAIN_ALT2).
65 * Currently 'uk.gnunet.org' / 'stat.wensley.org.uk'.
67 #define TEST_IP_ALT2 "81.187.252.184"
70 * Must be the IP address for TEST_RECORD_NS in DNS and TEST_DOMAIN in GADS;
71 * used to check that DNS is working as expected. We use the IPv4
72 * address of gnunet.org.
74 #define TEST_IP "131.159.74.67"
77 * DNS domain name used for testing.
79 #define TEST_RECORD_NS "gnunet.org"
82 * Nameserver for 'TEST_RECORD_NS', currently 'a.ns.joker.com'.
84 #define TEST_IP_NS "184.172.157.218"
87 * Name we use within our GADS zone.
89 #define TEST_RECORD_NAME "homepage"
92 * Task handle to use to schedule test failure
94 static GNUNET_SCHEDULER_TaskIdentifier die_task;
97 * Global return value (0 for success, anything else for failure)
102 * Flag we set if the DNS resolver seems to be working.
104 static int resolver_working;
107 * Handle to namestore.
109 static struct GNUNET_NAMESTORE_Handle *namestore_handle;
112 * Handle to GNS resolver.
114 static struct GNUNET_GNS_Handle *gns_handle;
117 * Handle for DNS request.
119 static struct GNUNET_RESOLVER_RequestHandle *resolver_handle;
124 static const struct GNUNET_CONFIGURATION_Handle *cfg;
127 * Handle for active GNS lookup.
129 static struct GNUNET_GNS_LookupRequest *lr;
132 * Queue for storing records in namestore.
134 static struct GNUNET_NAMESTORE_QueueEntry *qe;
137 * Our private key for signing records.
139 static struct GNUNET_CRYPTO_EccPrivateKey *alice_key;
143 * Check if the get_handle is being used, if so stop the request. Either
144 * way, schedule the end_badly_cont function which actually shuts down the
148 end_badly (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
150 die_task = GNUNET_SCHEDULER_NO_TASK;
151 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Test failed, shutting down...\n");
154 GNUNET_GNS_cancel_lookup_request (lr);
157 if (NULL != resolver_handle)
159 GNUNET_RESOLVER_request_cancel (resolver_handle);
160 resolver_handle = NULL;
164 GNUNET_NAMESTORE_cancel (qe);
167 if (NULL != gns_handle)
169 GNUNET_GNS_disconnect(gns_handle);
172 if (NULL != namestore_handle)
174 GNUNET_NAMESTORE_disconnect (namestore_handle);
175 namestore_handle = NULL;
177 if (NULL != alice_key)
179 GNUNET_free (alice_key);
183 GNUNET_SCHEDULER_shutdown ();
189 * We hit a hard failure, shutdown now.
194 GNUNET_SCHEDULER_cancel (die_task);
195 die_task = GNUNET_SCHEDULER_add_now (&end_badly, NULL);
200 * Testcase is finished, terminate everything.
203 end_now (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
205 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
206 "Test successful, shutting down...\n");
207 if (GNUNET_SCHEDULER_NO_TASK != die_task)
209 GNUNET_SCHEDULER_cancel (die_task);
210 die_task = GNUNET_SCHEDULER_NO_TASK;
214 GNUNET_NAMESTORE_cancel (qe);
217 if (NULL != resolver_handle)
219 GNUNET_RESOLVER_request_cancel (resolver_handle);
220 resolver_handle = NULL;
222 if (NULL != gns_handle)
224 GNUNET_GNS_disconnect(gns_handle);
227 if (NULL != namestore_handle)
229 GNUNET_NAMESTORE_disconnect (namestore_handle);
230 namestore_handle = NULL;
232 if (NULL != alice_key)
234 GNUNET_free (alice_key);
237 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Shutting down peer!\n");
238 GNUNET_SCHEDULER_shutdown ();
243 * We got resolution result for 'TEST_DOMAIN_ALT2', check if
244 * they match our expectations, then finish the test with success.
247 * @param rd_count number of records in rd
248 * @param rd records returned from naming system for the name
251 on_lookup_result_alt2 (void *cls, uint32_t rd_count,
252 const struct GNUNET_NAMESTORE_RecordData *rd)
259 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received alternative results 2\n");
262 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
263 "Lookup for `%s' failed\n",
266 GNUNET_SCHEDULER_add_now (&end_now, NULL);
270 for (i=0; i<rd_count; i++)
272 if (rd[i].record_type == GNUNET_DNSPARSER_TYPE_A)
274 memcpy(&a, rd[i].data, sizeof(a));
276 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "address: %s\n", addr);
277 if (0 == strcmp(addr, TEST_IP_ALT2))
279 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
280 "%s correctly resolved to %s!\n",
281 TEST_DOMAIN_ALT2, addr);
285 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
286 "Got unexpected address %s for %s\n",
293 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
294 "None of the results matched the expected value %s for %s\n",
297 GNUNET_SCHEDULER_add_now (&end_now, NULL);
301 GNUNET_SCHEDULER_add_now (&end_now, NULL);
306 * We got resolution result for 'TEST_DOMAIN_ALT', check if
307 * they match our expectations, then move on to the next
311 * @param rd_count number of records in rd
312 * @param rd records returned from naming system for the name
315 on_lookup_result_alt (void *cls, uint32_t rd_count,
316 const struct GNUNET_NAMESTORE_RecordData *rd)
323 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received alternative results\n");
326 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
327 "Lookup for `%s' failed\n",
330 GNUNET_SCHEDULER_add_now (&end_now, NULL);
333 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
334 "Received %u results for %s\n",
335 (unsigned int) rd_count,
338 for (i=0; i<rd_count; i++)
340 if (rd[i].record_type == GNUNET_DNSPARSER_TYPE_A)
342 memcpy (&a, rd[i].data, sizeof(a));
343 addr = inet_ntoa (a);
344 if (0 == strcmp(addr, TEST_IP))
346 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
347 "%s correctly resolved to %s!\n", TEST_DOMAIN, addr);
351 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
352 "Got unexpected address %s for %s\n",
359 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
360 "None of the results matched the expected value %s for %s\n",
363 GNUNET_SCHEDULER_add_now (&end_now, NULL);
367 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
368 "Starting lookup for `%s'\n",
370 lr = GNUNET_GNS_lookup (gns_handle,
371 TEST_DOMAIN_ALT2, GNUNET_DNSPARSER_TYPE_A,
374 &on_lookup_result_alt2, NULL);
379 * We got resolution result for 'TEST_DOMAIN', check if
380 * they match our expectations, then move on to the next
384 * @param rd_count number of records in rd
385 * @param rd records returned from naming system for the name
388 on_lookup_result (void *cls, uint32_t rd_count,
389 const struct GNUNET_NAMESTORE_RecordData *rd)
398 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
399 "Lookup for `%s' failed\n",
402 GNUNET_SCHEDULER_add_now (&end_now, NULL);
405 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
406 "Received %u results for %s\n",
407 (unsigned int) rd_count,
410 for (i=0; i<rd_count; i++)
412 if (rd[i].record_type == GNUNET_DNSPARSER_TYPE_A)
414 memcpy (&a, rd[i].data, sizeof(a));
416 if (0 == strcmp (addr, TEST_IP))
418 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
419 "%s correctly resolved to %s!\n",
424 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
425 "Got unexpected address %s for %s\n",
432 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
433 "None of the results matched the expected value %s for %s\n",
436 GNUNET_SCHEDULER_add_now (&end_now, NULL);
439 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
440 "Starting lookup for `%s'\n",
443 lr = GNUNET_GNS_lookup (gns_handle, TEST_DOMAIN_ALT, GNUNET_DNSPARSER_TYPE_A,
446 &on_lookup_result_alt, NULL);
451 * Start the actual NS-based lookup.
456 gns_handle = GNUNET_GNS_connect (cfg);
457 if (NULL == gns_handle)
459 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
460 "Failed to connect to GNS!\n");
464 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
465 "Records ready, starting lookup for `%s'\n",
467 lr = GNUNET_GNS_lookup (gns_handle, TEST_DOMAIN, GNUNET_DNSPARSER_TYPE_A,
470 &on_lookup_result, NULL);
475 * Function called with the result of resolving the "NS" record
476 * for TEST_RECORD_NS. Check if the NS record is set as expected,
477 * and if so, continue with the test.
479 * @param cls closure, unused
480 * @param addr NULL for last address,
481 * @param addrlen number of bytes in addr
484 handle_dns_test (void *cls,
485 const struct sockaddr *addr,
488 struct sockaddr_in* sai;
490 resolver_handle = NULL;
494 if (GNUNET_YES != resolver_working)
497 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
498 "System resolver not working as expected. Test inconclusive!\n");
499 GNUNET_SCHEDULER_add_now (&end_now, NULL);
502 /* done preparing records, start lookup */
503 GNUNET_NAMESTORE_disconnect (namestore_handle);
504 namestore_handle = NULL;
508 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
509 "Received DNS response\n");
510 if (addrlen == sizeof (struct sockaddr_in))
512 sai = (struct sockaddr_in*) addr;
513 if (0 == strcmp (TEST_IP, inet_ntoa (sai->sin_addr)))
515 resolver_working = GNUNET_YES;
516 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
517 "Resolver is working (returned expected A record %s for %s)\n",
526 * Function scheduled to be run on the successful start of services
527 * tries to look up the dns record for TEST_DOMAIN
529 * @param cls closure, unused
530 * @param success GNUNET_OK on success
531 * @param emsg error message, NULL on success
534 commence_testing (void *cls, int32_t success, const char *emsg)
538 FPRINTF (stderr, "Failed to create record: %s\n", emsg);
539 GNUNET_assert (GNUNET_YES == success);
540 resolver_working = GNUNET_NO;
541 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
542 "Resolving NS record for %s\n",
544 GNUNET_RESOLVER_connect (cfg);
545 resolver_handle = GNUNET_RESOLVER_ip_get (TEST_RECORD_NS,
554 * Peer is ready, run the actual test. Begins by storing
555 * a record in the namestore.
557 * @param cls closure, NULL
558 * @param ccfg our configuration
559 * @param peer handle to the peer
563 const struct GNUNET_CONFIGURATION_Handle *ccfg,
564 struct GNUNET_TESTING_Peer *peer)
566 struct GNUNET_CRYPTO_EccPublicSignKey alice_pkey;
568 struct GNUNET_NAMESTORE_RecordData rd[2];
572 die_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT, &end_badly, NULL);
574 /* put records into namestore */
575 namestore_handle = GNUNET_NAMESTORE_connect (cfg);
576 if (NULL == namestore_handle)
578 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
579 "Failed to connect to namestore\n");
585 GNUNET_CONFIGURATION_get_value_filename (cfg, "gns",
589 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
590 "Failed to get key from cfg\n");
595 alice_key = GNUNET_CRYPTO_ecc_key_create_from_file (alice_keyfile);
596 GNUNET_CRYPTO_ecc_key_get_public_for_signature (alice_key, &alice_pkey);
597 GNUNET_free (alice_keyfile);
599 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
600 "Creating NS records\n");
601 rd[0].expiration_time = UINT64_MAX;
602 GNUNET_assert(1 == inet_pton (AF_INET, TEST_IP_NS, &ns));
603 rd[0].data_size = sizeof (struct in_addr);
605 rd[0].record_type = GNUNET_DNSPARSER_TYPE_A;
606 rd[0].flags = GNUNET_NAMESTORE_RF_NONE;
608 rd[1].expiration_time = UINT64_MAX;
609 rd[1].data_size = strlen (TEST_RECORD_NS);
610 rd[1].data = TEST_RECORD_NS;
611 rd[1].record_type = GNUNET_DNSPARSER_TYPE_NS;
612 rd[1].flags = GNUNET_NAMESTORE_RF_NONE;
614 qe = GNUNET_NAMESTORE_record_put_by_authority (namestore_handle,
624 main (int argc, char *argv[])
627 GNUNET_TESTING_peer_run ("test-gns-simple-ns-lookup", "test_gns_simple_lookup.conf",
632 /* end of test_gns_ns_lookup.c */