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.
21 * @file gns/test_gns_ns_lookup.c
22 * @brief base testcase for testing a local GNS record lookup through NS
23 * @author Martin Schanzenbach
26 #include "gnunet_testing_lib.h"
27 #include "gnunet_core_service.h"
28 #include "block_dns.h"
29 #include "gnunet_signatures.h"
30 #include "gnunet_namestore_service.h"
31 #include "gnunet_resolver_service.h"
32 #include "gnunet_dnsparser_lib.h"
33 #include "gnunet_gns_service.h"
36 * Timeout for entire testcase
38 #define TIMEOUT GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 20)
41 * Name to resolve for testing. NS record on 'homepage.gads' redirects to
42 * DNS 'TEST_RECORD_NS' domain and thus names should be resolved within
45 #define TEST_DOMAIN "www.homepage.gads"
48 * Name to resolve for testing. NS record on 'homepage.gads' redirects to
49 * DNS 'TEST_RECORD_NS' domain and thus names should be resolved within
52 #define TEST_DOMAIN_ALT "homepage.gads"
55 * Name to resolve for testing. NS record on 'homepage.gads' redirects to
56 * DNS 'TEST_RECORD_NS' domain and thus names should be resolved within
59 #define TEST_DOMAIN_ALT2 "uk.homepage.gads"
62 * Expected test value (matching TEST_DOMAIN_ALT2).
63 * Currently 'uk.gnunet.org' / 'stat.wensley.org.uk'.
65 #define TEST_IP_ALT2 "81.187.252.184"
68 * Must be the IP address for TEST_RECORD_NS in DNS and TEST_DOMAIN in GADS;
69 * used to check that DNS is working as expected. We use the IPv4
70 * address of gnunet.org.
72 #define TEST_IP "131.159.74.67"
75 * DNS domain name used for testing.
77 #define TEST_RECORD_NS "gnunet.org"
80 * Nameserver for 'TEST_RECORD_NS', currently 'a.ns.joker.com'.
82 #define TEST_IP_NS "184.172.157.218"
85 * Name we use within our GADS zone.
87 #define TEST_RECORD_NAME "homepage"
90 * Task handle to use to schedule test failure
92 static GNUNET_SCHEDULER_TaskIdentifier die_task;
95 * Global return value (0 for success, anything else for failure)
100 * Flag we set if the DNS resolver seems to be working.
102 static int resolver_working;
105 * Handle to namestore.
107 static struct GNUNET_NAMESTORE_Handle *namestore_handle;
110 * Handle to GNS resolver.
112 static struct GNUNET_GNS_Handle *gns_handle;
115 * Handle for DNS request.
117 static struct GNUNET_RESOLVER_RequestHandle *resolver_handle;
122 static const struct GNUNET_CONFIGURATION_Handle *cfg;
125 * Handle for active GNS lookup.
127 static struct GNUNET_GNS_LookupRequest *lr;
130 * Queue for storing records in namestore.
132 static struct GNUNET_NAMESTORE_QueueEntry *qe;
135 * Our private key for signing records.
137 static struct GNUNET_CRYPTO_RsaPrivateKey *alice_key;
141 * Check if the get_handle is being used, if so stop the request. Either
142 * way, schedule the end_badly_cont function which actually shuts down the
146 end_badly (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
148 die_task = GNUNET_SCHEDULER_NO_TASK;
149 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Test failed, shutting down...\n");
152 GNUNET_GNS_cancel_lookup_request (lr);
155 if (NULL != resolver_handle)
157 GNUNET_RESOLVER_request_cancel (resolver_handle);
158 resolver_handle = NULL;
162 GNUNET_NAMESTORE_cancel (qe);
165 if (NULL != gns_handle)
167 GNUNET_GNS_disconnect(gns_handle);
170 if (NULL != namestore_handle)
172 GNUNET_NAMESTORE_disconnect (namestore_handle);
173 namestore_handle = NULL;
175 if (NULL != alice_key)
177 GNUNET_CRYPTO_rsa_key_free (alice_key);
181 GNUNET_SCHEDULER_shutdown ();
187 * We hit a hard failure, shutdown now.
192 GNUNET_SCHEDULER_cancel (die_task);
193 die_task = GNUNET_SCHEDULER_add_now (&end_badly, NULL);
198 * Testcase is finished, terminate everything.
201 end_now (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
203 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
204 "Test successful, shutting down...\n");
205 if (GNUNET_SCHEDULER_NO_TASK != die_task)
207 GNUNET_SCHEDULER_cancel (die_task);
208 die_task = GNUNET_SCHEDULER_NO_TASK;
212 GNUNET_NAMESTORE_cancel (qe);
215 if (NULL != resolver_handle)
217 GNUNET_RESOLVER_request_cancel (resolver_handle);
218 resolver_handle = NULL;
220 if (NULL != gns_handle)
222 GNUNET_GNS_disconnect(gns_handle);
225 if (NULL != namestore_handle)
227 GNUNET_NAMESTORE_disconnect (namestore_handle);
228 namestore_handle = NULL;
230 if (NULL != alice_key)
232 GNUNET_CRYPTO_rsa_key_free (alice_key);
235 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Shutting down peer!\n");
236 GNUNET_SCHEDULER_shutdown ();
241 * We got resolution result for 'TEST_DOMAIN_ALT2', check if
242 * they match our expectations, then finish the test with success.
245 * @param rd_count number of records in rd
246 * @param rd records returned from naming system for the name
249 on_lookup_result_alt2 (void *cls, uint32_t rd_count,
250 const struct GNUNET_NAMESTORE_RecordData *rd)
257 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received alternative results 2\n");
260 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
261 "Lookup for `%s' failed\n",
264 GNUNET_SCHEDULER_add_now (&end_now, NULL);
268 for (i=0; i<rd_count; i++)
270 if (rd[i].record_type == GNUNET_GNS_RECORD_A)
272 memcpy(&a, rd[i].data, sizeof(a));
274 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "address: %s\n", addr);
275 if (0 == strcmp(addr, TEST_IP_ALT2))
277 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
278 "%s correctly resolved to %s!\n",
279 TEST_DOMAIN_ALT2, addr);
283 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
284 "Got unexpected address %s for %s\n",
291 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
292 "None of the results matched the expected value %s for %s\n",
295 GNUNET_SCHEDULER_add_now (&end_now, NULL);
299 GNUNET_SCHEDULER_add_now (&end_now, NULL);
304 * We got resolution result for 'TEST_DOMAIN_ALT', check if
305 * they match our expectations, then move on to the next
309 * @param rd_count number of records in rd
310 * @param rd records returned from naming system for the name
313 on_lookup_result_alt (void *cls, uint32_t rd_count,
314 const struct GNUNET_NAMESTORE_RecordData *rd)
321 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received alternative results\n");
324 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
325 "Lookup for `%s' failed\n",
328 GNUNET_SCHEDULER_add_now (&end_now, NULL);
331 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
332 "Received %u results for %s\n",
333 (unsigned int) rd_count,
336 for (i=0; i<rd_count; i++)
338 if (rd[i].record_type == GNUNET_GNS_RECORD_A)
340 memcpy (&a, rd[i].data, sizeof(a));
341 addr = inet_ntoa (a);
342 if (0 == strcmp(addr, TEST_IP))
344 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
345 "%s correctly resolved to %s!\n", TEST_DOMAIN, addr);
349 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
350 "Got unexpected address %s for %s\n",
357 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
358 "None of the results matched the expected value %s for %s\n",
361 GNUNET_SCHEDULER_add_now (&end_now, NULL);
365 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
366 "Starting lookup for `%s'\n",
368 lr = GNUNET_GNS_lookup (gns_handle,
369 TEST_DOMAIN_ALT2, GNUNET_GNS_RECORD_A,
372 &on_lookup_result_alt2, NULL);
377 * We got resolution result for 'TEST_DOMAIN', check if
378 * they match our expectations, then move on to the next
382 * @param rd_count number of records in rd
383 * @param rd records returned from naming system for the name
386 on_lookup_result (void *cls, uint32_t rd_count,
387 const struct GNUNET_NAMESTORE_RecordData *rd)
396 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
397 "Lookup for `%s' failed\n",
400 GNUNET_SCHEDULER_add_now (&end_now, NULL);
403 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
404 "Received %u results for %s\n",
405 (unsigned int) rd_count,
408 for (i=0; i<rd_count; i++)
410 if (rd[i].record_type == GNUNET_GNS_RECORD_A)
412 memcpy (&a, rd[i].data, sizeof(a));
414 if (0 == strcmp (addr, TEST_IP))
416 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
417 "%s correctly resolved to %s!\n",
422 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
423 "Got unexpected address %s for %s\n",
430 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
431 "None of the results matched the expected value %s for %s\n",
434 GNUNET_SCHEDULER_add_now (&end_now, NULL);
437 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
438 "Starting lookup for `%s'\n",
441 lr = GNUNET_GNS_lookup (gns_handle, TEST_DOMAIN_ALT, GNUNET_GNS_RECORD_A,
444 &on_lookup_result_alt, NULL);
449 * Start the actual NS-based lookup.
454 gns_handle = GNUNET_GNS_connect (cfg);
455 if (NULL == gns_handle)
457 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
458 "Failed to connect to GNS!\n");
462 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
463 "Records ready, starting lookup for `%s'\n",
465 lr = GNUNET_GNS_lookup (gns_handle, TEST_DOMAIN, GNUNET_GNS_RECORD_A,
468 &on_lookup_result, NULL);
473 * Function called with the result of resolving the "NS" record
474 * for TEST_RECORD_NS. Check if the NS record is set as expected,
475 * and if so, continue with the test.
477 * @param cls closure, unused
478 * @param addr NULL for last address,
479 * @param addrlen number of bytes in addr
482 handle_dns_test (void *cls,
483 const struct sockaddr *addr,
486 struct sockaddr_in* sai;
488 resolver_handle = NULL;
492 if (GNUNET_YES != resolver_working)
495 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
496 "System resolver not working as expected. Test inconclusive!\n");
497 GNUNET_SCHEDULER_add_now (&end_now, NULL);
500 /* done preparing records, start lookup */
501 GNUNET_NAMESTORE_disconnect (namestore_handle);
502 namestore_handle = NULL;
506 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
507 "Received DNS response\n");
508 if (addrlen == sizeof (struct sockaddr_in))
510 sai = (struct sockaddr_in*) addr;
511 if (0 == strcmp (TEST_IP, inet_ntoa (sai->sin_addr)))
513 resolver_working = GNUNET_YES;
514 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
515 "Resolver is working (returned expected A record %s for %s)\n",
524 * Function scheduled to be run on the successful start of services
525 * tries to look up the dns record for TEST_DOMAIN
527 * @param cls closure, unused
528 * @param success GNUNET_OK on success
529 * @param emsg error message, NULL on success
532 commence_testing (void *cls, int32_t success, const char *emsg)
536 FPRINTF (stderr, "Failed to create record: %s\n", emsg);
537 GNUNET_assert (GNUNET_YES == success);
538 resolver_working = GNUNET_NO;
539 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
540 "Resolving NS record for %s\n",
542 GNUNET_RESOLVER_connect (cfg);
543 resolver_handle = GNUNET_RESOLVER_ip_get (TEST_RECORD_NS,
552 * Function called once we've created the first NS record,
553 * create the second one.
555 * @param cls closure, unused
556 * @param success GNUNET_OK on success
557 * @param emsg error message, NULL on success
560 create_next_record (void *cls,
564 struct GNUNET_NAMESTORE_RecordData rd;
568 FPRINTF (stderr, "Failed to create record: %s\n", emsg);
569 GNUNET_assert (GNUNET_YES == success);
570 rd.data_size = strlen (TEST_RECORD_NS);
571 rd.data = TEST_RECORD_NS;
572 rd.record_type = GNUNET_GNS_RECORD_NS;
573 qe = GNUNET_NAMESTORE_record_create (namestore_handle,
583 * Peer is ready, run the actual test. Begins by storing
584 * a record in the namestore.
586 * @param cls closure, NULL
587 * @param ccfg our configuration
588 * @param peer handle to the peer
592 const struct GNUNET_CONFIGURATION_Handle *ccfg,
593 struct GNUNET_TESTING_Peer *peer)
595 struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded alice_pkey;
597 struct GNUNET_NAMESTORE_RecordData rd;
601 die_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT, &end_badly, NULL);
603 /* put records into namestore */
604 namestore_handle = GNUNET_NAMESTORE_connect (cfg);
605 if (NULL == namestore_handle)
607 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
608 "Failed to connect to namestore\n");
614 GNUNET_CONFIGURATION_get_value_filename (cfg, "gns",
618 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
619 "Failed to get key from cfg\n");
624 alice_key = GNUNET_CRYPTO_rsa_key_create_from_file (alice_keyfile);
625 GNUNET_CRYPTO_rsa_key_get_public (alice_key, &alice_pkey);
626 GNUNET_free (alice_keyfile);
628 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
629 "Creating NS records\n");
630 rd.expiration_time = UINT64_MAX;
631 GNUNET_assert(1 == inet_pton (AF_INET, TEST_IP_NS, &ns));
632 rd.data_size = sizeof (struct in_addr);
634 rd.record_type = GNUNET_DNSPARSER_TYPE_A;
635 rd.flags = GNUNET_NAMESTORE_RF_AUTHORITY;
637 qe = GNUNET_NAMESTORE_record_create (namestore_handle,
647 main (int argc, char *argv[])
650 GNUNET_TESTING_peer_run ("test-gns-simple-ns-lookup", "test_gns_simple_lookup.conf",
655 /* end of test_gns_ns_lookup.c */