From: Martin Schanzenbach Date: Fri, 22 Jun 2012 00:37:08 +0000 (+0000) Subject: Added proper SRV handling and test X-Git-Tag: initial-import-from-subversion-38251~12889 X-Git-Url: https://git.librecmc.org/?a=commitdiff_plain;h=eec111fe95456619682d12859685d326ca161e46;p=oweals%2Fgnunet.git Added proper SRV handling and test --- diff --git a/src/gns/Makefile.am b/src/gns/Makefile.am index bb10a5973..c65d52492 100644 --- a/src/gns/Makefile.am +++ b/src/gns/Makefile.am @@ -45,6 +45,7 @@ check_PROGRAMS = \ test_gns_simple_lookup \ test_gns_simple_delegated_lookup \ test_gns_simple_mx_lookup \ + test_gns_simple_srv_lookup \ test_gns_simple_zkey_lookup \ test_gns_dht_delegated_lookup \ test_gns_pseu_shorten \ @@ -115,6 +116,19 @@ test_gns_simple_mx_lookup_DEPENDENCIES = \ $(top_builddir)/src/gns/libgnunetgns.la \ $(top_builddir)/src/testing_old/libgnunettesting_old.la +test_gns_simple_srv_lookup_SOURCES = \ + test_gns_simple_srv_lookup.c +test_gns_simple_srv_lookup_LDADD = \ + $(top_builddir)/src/util/libgnunetutil.la \ + $(top_builddir)/src/namestore/libgnunetnamestore.la \ + $(top_builddir)/src/gns/libgnunetgns.la \ + $(top_builddir)/src/testing_old/libgnunettesting_old.la +test_gns_simple_srv_lookup_DEPENDENCIES = \ + $(top_builddir)/src/util/libgnunetutil.la \ + $(top_builddir)/src/namestore/libgnunetnamestore.la \ + $(top_builddir)/src/gns/libgnunetgns.la \ + $(top_builddir)/src/testing_old/libgnunettesting_old.la + test_gns_simple_zkey_lookup_SOURCES = \ test_gns_simple_zkey_lookup.c test_gns_simple_zkey_lookup_LDADD = \ diff --git a/src/gns/gnunet-service-gns_resolver.c b/src/gns/gnunet-service-gns_resolver.c index 045112eae..bbeea86f4 100644 --- a/src/gns/gnunet-service-gns_resolver.c +++ b/src/gns/gnunet-service-gns_resolver.c @@ -97,6 +97,31 @@ static struct GetPseuAuthorityHandle *gph_tail; */ static unsigned long long rid = 0; +static int +is_srv (char* name) +{ + char* ndup; + int ret = 1; + + if (*name != '_') + return 0; + if (NULL == strstr (name, "._")) + return 0; + + ndup = GNUNET_strdup (name); + strtok (ndup, "."); + + if (NULL == strtok (NULL, ".")) + ret = 0; + + if (NULL == strtok (NULL, ".")) + ret = 0; + + if (NULL != strtok (NULL, ".")) + ret = 0; + + return ret; +} /** * Determine if this name is canonical. @@ -110,14 +135,23 @@ static unsigned long long rid = 0; static int is_canonical(char* name) { - uint32_t len = strlen(name); - int i; + char* ndup; + char* tok; + + ndup = GNUNET_strdup (name); + tok = strtok (ndup, "."); - for (i=0; istatus & RSL_RECORD_EXPIRED) != 0) || - ((rh->status & RSL_RECORD_EXISTS) == 0) ) && - GNUNET_CRYPTO_short_hash_cmp(&rh->authority_chain_head->zone, - &rh->private_local_zone) && - (strcmp(rh->name, "+") == 0) && - (rh->only_cached == GNUNET_NO)) + if (((rh->status & RSL_RECORD_EXPIRED) != 0) && + ((rh->status & RSL_RECORD_EXISTS) == 0) ) + check_dht = GNUNET_NO; + + if (0 != GNUNET_CRYPTO_short_hash_cmp(&rh->authority_chain_head->zone, + &rh->private_local_zone)) + check_dht = GNUNET_NO; + + if ((strcmp (rh->name, "+") != 0) && (is_srv (rh->name) != 0)) + check_dht = GNUNET_NO; + + + if (rh->only_cached == GNUNET_YES) + check_dht = GNUNET_NO; + + if (GNUNET_YES == check_dht) { rh->proc = &handle_record_dht; resolve_record_dht(rh); @@ -2559,7 +2622,7 @@ pop_tld(char* name, char* dest) { uint32_t len; - if (is_canonical(name)) + if (is_canonical (name)) { strcpy(dest, name); strcpy(name, ""); @@ -2757,6 +2820,7 @@ handle_delegation_ns (void* cls, struct ResolverHandle *rh, { struct RecordLookupHandle* rlh; rlh = (struct RecordLookupHandle*) cls; + int check_dht = GNUNET_YES; int s_len = 0; GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, @@ -2920,9 +2984,19 @@ handle_delegation_ns (void* cls, struct ResolverHandle *rh, * and exists * or we are authority **/ - if (((rh->status & RSL_RECORD_EXISTS) && (!(rh->status & RSL_RECORD_EXPIRED))) - || !GNUNET_CRYPTO_short_hash_cmp(&rh->authority_chain_head->zone, - &rh->private_local_zone)) + + if ((rh->status & RSL_RECORD_EXISTS) && + !(rh->status & RSL_RECORD_EXPIRED)) + check_dht = GNUNET_NO; + + if (0 == GNUNET_CRYPTO_short_hash_cmp(&rh->authority_chain_head->zone, + &rh->private_local_zone)) + check_dht = GNUNET_NO; + + if (rh->only_cached == GNUNET_YES) + check_dht = GNUNET_NO; + + if (check_dht == GNUNET_NO) { if (is_canonical(rh->name)) { @@ -2946,15 +3020,6 @@ handle_delegation_ns (void* cls, struct ResolverHandle *rh, return; } - if (rh->only_cached == GNUNET_YES) - { - GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, - "GNS_PHASE_DELEGATE_NS-%llu: Only cache resolution, no result\n", - rh->id, rh->name); - finish_lookup(rh, rlh, rd_count, rd); - return; - } - GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "GNS_PHASE_DELEGATE_NS-%llu: Trying to resolve delegation for %s via DHT\n", rh->id, rh->name); @@ -2994,29 +3059,29 @@ process_delegation_result_ns (void* cls, struct GNUNET_TIME_Absolute et; rh = (struct ResolverHandle *)cls; - GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, - "GNS_PHASE_DELEGATE_NS-%llu: Got %d records from authority lookup\n", - rh->id, rd_count); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "GNS_PHASE_DELEGATE_NS-%llu: Got %d records from authority lookup\n", + rh->id, rd_count); - GNUNET_CRYPTO_short_hash(key, - sizeof(struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded), - &zone); + GNUNET_CRYPTO_short_hash (key, + sizeof(struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded), + &zone); remaining_time = GNUNET_TIME_absolute_get_remaining (expiration); rh->status = 0; if (name != NULL) { - GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, - "GNS_PHASE_DELEGATE_NS-%llu: Records with name %s exist.\n", - rh->id, name); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "GNS_PHASE_DELEGATE_NS-%llu: Records with name %s exist.\n", + rh->id, name); rh->status |= RSL_RECORD_EXISTS; if (remaining_time.rel_value == 0) { - GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, - "GNS_PHASE_DELEGATE_NS-%llu: Record set %s expired.\n", - rh->id, name); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "GNS_PHASE_DELEGATE_NS-%llu: Record set %s expired.\n", + rh->id, name); rh->status |= RSL_RECORD_EXPIRED; } } @@ -3035,31 +3100,29 @@ process_delegation_result_ns (void* cls, * Promote this authority back to a name maybe it is * our record. */ - if (strcmp(rh->name, "") == 0) + if (strcmp (rh->name, "") == 0) { /* simply promote back */ - GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, - "GNS_PHASE_DELEGATE_NS-%llu: Promoting %s back to name\n", - rh->id, rh->authority_name); - strcpy(rh->name, rh->authority_name); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "GNS_PHASE_DELEGATE_NS-%llu: Promoting %s back to name\n", + rh->id, rh->authority_name); + strcpy (rh->name, rh->authority_name); } else { /* add back to existing name */ - GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, - "GNS_PHASE_DELEGATE_NS-%llu: Adding %s back to %s\n", - rh->id, rh->authority_name, rh->name); - //memset(new_name, 0, strlen(rh->name) + strlen(rh->authority_name) + 2); - GNUNET_snprintf(new_name, MAX_DNS_NAME_LENGTH, "%s.%s", - rh->name, rh->authority_name); - //strcpy(new_name, rh->name); - //strcpy(new_name+strlen(new_name), "."); - //strcpy(new_name+strlen(new_name), rh->authority_name); - strcpy(rh->name, new_name); - GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, - "GNS_PHASE_DELEGATE_NS-%llu: %s restored\n", rh->id, rh->name); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "GNS_PHASE_DELEGATE_NS-%llu: Adding %s back to %s\n", + rh->id, rh->authority_name, rh->name); + GNUNET_snprintf (new_name, MAX_DNS_NAME_LENGTH, "%s.%s", + rh->name, rh->authority_name); + strcpy (rh->name, new_name); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "GNS_PHASE_DELEGATE_NS-%llu: %s restored\n", + rh->id, rh->name); } - rh->proc(rh->proc_cls, rh, 0, NULL); + + rh->proc (rh->proc_cls, rh, 0, NULL); return; } @@ -3068,7 +3131,7 @@ process_delegation_result_ns (void* cls, * move on with query * Note only 1 pkey should have been returned.. anything else would be strange */ - for (i=0; istatus |= RSL_DELEGATE_PKEY; - if (ignore_pending_records && + if ((ignore_pending_records != 0) && (rd[i].flags & GNUNET_NAMESTORE_RF_PENDING)) { - GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, - "GNS_PHASE_DELEGATE_NS-%llu: PKEY for %s is pending user confirmation.\n", + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "GNS_PHASE_DELEGATE_NS-%llu: PKEY for %s is pending user confirmation.\n", rh->id, name); continue; @@ -3133,16 +3196,16 @@ process_delegation_result_ns (void* cls, if ((GNUNET_TIME_absolute_get_remaining (et)).rel_value == 0) { - GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, - "GNS_PHASE_DELEGATE_NS-%llu: This pkey is expired.\n", - rh->id); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "GNS_PHASE_DELEGATE_NS-%llu: This pkey is expired.\n", + rh->id); if (remaining_time.rel_value == 0) { - GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, - "GNS_PHASE_DELEGATE_NS-%llu: This dht entry is expired.\n", - rh->id); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "GNS_PHASE_DELEGATE_NS-%llu: This dht entry is expired.\n", + rh->id); rh->authority_chain_head->fresh = 0; - rh->proc(rh->proc_cls, rh, 0, NULL); + rh->proc (rh->proc_cls, rh, 0, NULL); return; } @@ -3152,13 +3215,13 @@ process_delegation_result_ns (void* cls, /** * Resolve rest of query with new authority */ - GNUNET_assert(rd[i].record_type == GNUNET_GNS_RECORD_PKEY); - memcpy(&rh->authority, rd[i].data, - sizeof(struct GNUNET_CRYPTO_ShortHashCode)); - struct AuthorityChain *auth = GNUNET_malloc(sizeof(struct AuthorityChain)); + GNUNET_assert (rd[i].record_type == GNUNET_GNS_RECORD_PKEY); + memcpy (&rh->authority, rd[i].data, + sizeof (struct GNUNET_CRYPTO_ShortHashCode)); + struct AuthorityChain *auth = GNUNET_malloc(sizeof (struct AuthorityChain)); auth->zone = rh->authority; - memset(auth->name, 0, strlen(rh->authority_name)+1); - strcpy(auth->name, rh->authority_name); + memset (auth->name, 0, strlen (rh->authority_name)+1); + strcpy (auth->name, rh->authority_name); GNUNET_CONTAINER_DLL_insert (rh->authority_chain_head, rh->authority_chain_tail, auth); diff --git a/src/gns/test_gns_simple_srv_lookup.c b/src/gns/test_gns_simple_srv_lookup.c new file mode 100644 index 000000000..b23d6ded3 --- /dev/null +++ b/src/gns/test_gns_simple_srv_lookup.c @@ -0,0 +1,387 @@ +/* + This file is part of GNUnet. + (C) 2009 Christian Grothoff (and other contributing authors) + + GNUnet is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 3, or (at your + option) any later version. + + GNUnet is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with GNUnet; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ +/** + * @file gns/test_gns_simple_srv_lookup.c + * @brief base testcase for testing GNS SRV lookups + * + */ +#include "platform.h" +#include "gnunet_testing_lib.h" +#include "gnunet_core_service.h" +#include "block_dns.h" +#include "gnunet_signatures.h" +#include "gnunet_namestore_service.h" +#include "../namestore/namestore.h" +#include "gnunet_dnsparser_lib.h" +#include "gnunet_gns_service.h" + +/* DEFINES */ +#define VERBOSE GNUNET_YES + +/* Timeout for entire testcase */ +#define TIMEOUT GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 20) + +/* If number of peers not in config file, use this number */ +#define DEFAULT_NUM_PEERS 2 + +/* test records to resolve */ +#define TEST_DOMAIN "_sip._tcp.bob.gnunet" +#define TEST_IP "127.0.0.1" +#define TEST_RECORD_NAME "sipserver" +#define TEST_RECORD_NAME_SRV "_sip._tcp" +#define TEST_SRV_NAME "sipserver.+" +#define TEST_EXPECTED_SRV "sipserver.bob.gnunet" + +#define TEST_AUTHORITY_NAME "bob" + +#define KEYFILE_BOB "../namestore/zonefiles/HGU0A0VCU334DN7F2I9UIUMVQMM7JMSD142LIMNUGTTV9R0CF4EG.zkey" + +/* Globals */ + +/** + * Directory to store temp data in, defined in config file + */ +static char *test_directory; + +static struct GNUNET_TESTING_PeerGroup *pg; + +/* Task handle to use to schedule test failure */ +GNUNET_SCHEDULER_TaskIdentifier die_task; + +/* Global return value (0 for success, anything else for failure) */ +static int ok; + +static struct GNUNET_NAMESTORE_Handle *namestore_handle; + +static struct GNUNET_GNS_Handle *gns_handle; + +const struct GNUNET_CONFIGURATION_Handle *cfg; + +/** + * Check whether peers successfully shut down. + */ +void +shutdown_callback (void *cls, const char *emsg) +{ + if (emsg != NULL) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Error on shutdown! ret=%d\n", ok); + if (ok == 0) + ok = 2; + } + + GNUNET_log (GNUNET_ERROR_TYPE_INFO, "done(ret=%d)!\n", ok); +} + +static void +on_lookup_result(void *cls, uint32_t rd_count, + const struct GNUNET_NAMESTORE_RecordData *rd) +{ + int i; + uint16_t *srv_data; + char* srv; + + if (rd_count == 0) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Lookup failed, rp_filtering?\n"); + ok = 2; + } + else + { + ok = 1; + GNUNET_log (GNUNET_ERROR_TYPE_INFO, "name: %s\n", (char*)cls); + for (i=0; iport = srv_port; + srv_data->prio = srv_prio; + srv_data->weight = srv_weight; + strcpy((char*)&srv_data[1], TEST_SRV_NAME); + rd.data = srv_data; + rd.record_type = GNUNET_GNS_RECORD_TYPE_SRV; + sig = GNUNET_NAMESTORE_create_signature(bob_key, + GNUNET_TIME_UNIT_FOREVER_ABS, + TEST_RECORD_NAME_SRV, + &rd, 1); + et.abs_value = rd.expiration_time; + GNUNET_NAMESTORE_record_put (namestore_handle, + &bob_pkey, + TEST_RECORD_NAME_SRV, + et, + 1, + &rd, + sig, + &commence_testing, + NULL); + GNUNET_free(srv_data); + GNUNET_free(sipserver); + GNUNET_free(sig); + GNUNET_CRYPTO_rsa_key_free(bob_key); + GNUNET_CRYPTO_rsa_key_free(alice_key); +} + +static void +run (void *cls, char *const *args, const char *cfgfile, + const struct GNUNET_CONFIGURATION_Handle *c) +{ + cfg = c; + /* Get path from configuration file */ + if (GNUNET_YES != + GNUNET_CONFIGURATION_get_value_string (cfg, "paths", "servicehome", + &test_directory)) + { + ok = 404; + return; + } + + + /* Set up a task to end testing if peer start fails */ + die_task = + GNUNET_SCHEDULER_add_delayed (TIMEOUT, &end_badly, + "didn't start all daemons in reasonable amount of time!!!"); + + /* Start alice */ + pg = GNUNET_TESTING_daemons_start(cfg, 1, 1, 1, TIMEOUT, + NULL, NULL, &do_lookup, NULL, + NULL, NULL, NULL); +} + +static int +check () +{ + int ret; + + /* Arguments for GNUNET_PROGRAM_run */ + char *const argv[] = { "test-gns-simple-mx-lookup", /* Name to give running binary */ + "-c", + "test_gns_simple_lookup.conf", /* Config file to use */ +#if VERBOSE + "-L", "DEBUG", +#endif + NULL + }; + struct GNUNET_GETOPT_CommandLineOption options[] = { + GNUNET_GETOPT_OPTION_END + }; + /* Run the run function as a new program */ + ret = + GNUNET_PROGRAM_run ((sizeof (argv) / sizeof (char *)) - 1, argv, + "test-gns-simple-mx-lookup", "nohelp", options, &run, + &ok); + if (ret != GNUNET_OK) + { + GNUNET_log (GNUNET_ERROR_TYPE_WARNING, + "`test-gns-simple-mx-lookup': Failed with error code %d\n", ret); + } + return ok; +} + +int +main (int argc, char *argv[]) +{ + int ret; + + GNUNET_log_setup ("test-gns-simple-mx-lookup", +#if VERBOSE + "DEBUG", +#else + "WARNING", +#endif + NULL); + ret = check (); + /** + * Need to remove base directory, subdirectories taken care + * of by the testing framework. + */ + return ret; +} + +/* end of test_gns_simple_mx_lookup.c */ diff --git a/src/include/gnunet_dnsparser_lib.h b/src/include/gnunet_dnsparser_lib.h index 5a42baea6..a36996432 100644 --- a/src/include/gnunet_dnsparser_lib.h +++ b/src/include/gnunet_dnsparser_lib.h @@ -190,8 +190,7 @@ struct GNUNET_DNSPARSER_SrvRecord { /** - * Preference for this entry (lower value is higher preference). - * Without the underscore (!). Note that RFC 6335 clarifies the + * Service name without the underscore (!). Note that RFC 6335 clarifies the * set of legal characters for service names. */ char *service; diff --git a/src/include/gnunet_gns_service.h b/src/include/gnunet_gns_service.h index 86caf249e..521fcfadf 100644 --- a/src/include/gnunet_gns_service.h +++ b/src/include/gnunet_gns_service.h @@ -71,6 +71,7 @@ enum GNUNET_GNS_RecordType GNUNET_GNS_RECORD_TYPE_NS = GNUNET_DNSPARSER_TYPE_NS, GNUNET_GNS_RECORD_TYPE_CNAME = GNUNET_DNSPARSER_TYPE_CNAME, GNUNET_GNS_RECORD_TYPE_SOA = GNUNET_DNSPARSER_TYPE_SOA, + GNUNET_GNS_RECORD_TYPE_SRV = GNUNET_DNSPARSER_TYPE_SRV, GNUNET_GNS_RECORD_TYPE_PTR = GNUNET_DNSPARSER_TYPE_PTR, GNUNET_GNS_RECORD_MX = GNUNET_DNSPARSER_TYPE_MX, GNUNET_GNS_RECORD_TXT = GNUNET_DNSPARSER_TYPE_TXT,