From 763feb7960b78a14971a6f36b73ceb92ff9b3ad4 Mon Sep 17 00:00:00 2001 From: Martin Schanzenbach Date: Wed, 14 Mar 2012 13:16:35 +0000 Subject: [PATCH] -large cleanup and bugfixes --- src/gns/Makefile.am | 20 +- src/gns/gns.h | 2 + src/gns/gnunet-service-gns.c | 2216 +--------------------- src/gns/gnunet-service-gns_interceptor.c | 327 ++++ src/gns/gnunet-service-gns_interceptor.h | 18 + src/gns/gnunet-service-gns_resolver.c | 1712 +++++++++++++++++ src/gns/gnunet-service-gns_resolver.h | 226 +++ src/gns/test_gns_dht_shorten.c | 500 ----- src/gns/test_gns_simple_shorten.c | 19 +- 9 files changed, 2349 insertions(+), 2691 deletions(-) create mode 100644 src/gns/gnunet-service-gns_interceptor.c create mode 100644 src/gns/gnunet-service-gns_interceptor.h create mode 100644 src/gns/gnunet-service-gns_resolver.c create mode 100644 src/gns/gnunet-service-gns_resolver.h delete mode 100644 src/gns/test_gns_dht_shorten.c diff --git a/src/gns/Makefile.am b/src/gns/Makefile.am index 866df1d88..679991fe1 100644 --- a/src/gns/Makefile.am +++ b/src/gns/Makefile.am @@ -28,7 +28,6 @@ bin_PROGRAMS = \ check_PROGRAMS = \ test_gns_simple_shorten \ - test_gns_dht_shorten \ test_gns_simple_get_authority \ test_gns_simple_lookup \ test_gns_simple_delegated_lookup \ @@ -108,21 +107,6 @@ test_gns_simple_shorten_DEPENDENCIES = \ $(top_builddir)/src/gns/libgnunetgns.la \ $(top_builddir)/src/testing/libgnunettesting.la -test_gns_dht_shorten_SOURCES = \ - test_gns_dht_shorten.c -test_gns_dht_shorten_LDADD = \ - $(top_builddir)/src/util/libgnunetutil.la \ - $(top_builddir)/src/namestore/libgnunetnamestore.la \ - $(top_builddir)/src/gns/libgnunetgns.la \ - $(top_builddir)/src/dht/libgnunetdht.la \ - $(top_builddir)/src/testing/libgnunettesting.la -test_gns_dht_shorten_DEPENDENCIES = \ - $(top_builddir)/src/util/libgnunetutil.la \ - $(top_builddir)/src/namestore/libgnunetnamestore.la \ - $(top_builddir)/src/gns/libgnunetgns.la \ - $(top_builddir)/src/dht/libgnunetdht.la \ - $(top_builddir)/src/testing/libgnunettesting.la - test_gns_simple_get_authority_SOURCES = \ test_gns_simple_get_authority.c test_gns_simple_get_authority_LDADD = \ @@ -148,7 +132,9 @@ gnunet_gns_DEPENDENCIES = \ libgnunetgns.la gnunet_service_gns_SOURCES = \ - gnunet-service-gns.c + gnunet-service-gns.c \ + gnunet-service-gns_resolver.c \ + gnunet-service-gns_interceptor.c gnunet_service_gns_LDADD = \ $(top_builddir)/src/tun/libgnunettun.la \ $(top_builddir)/src/mesh/libgnunetmesh.la \ diff --git a/src/gns/gns.h b/src/gns/gns.h index aad36ebfe..31730f8ac 100644 --- a/src/gns/gns.h +++ b/src/gns/gns.h @@ -28,6 +28,8 @@ #ifndef GNS_H #define GNS_H +#define GNUNET_GNS_TLD "gnunet" + GNUNET_NETWORK_STRUCT_BEGIN /** diff --git a/src/gns/gnunet-service-gns.c b/src/gns/gnunet-service-gns.c index ea9afcb4c..0d33fad81 100644 --- a/src/gns/gnunet-service-gns.c +++ b/src/gns/gnunet-service-gns.c @@ -38,11 +38,8 @@ #include "gnunet_gns_service.h" #include "block_gns.h" #include "gns.h" - -#define DHT_OPERATION_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 3) -#define DHT_LOOKUP_TIMEOUT DHT_OPERATION_TIMEOUT -#define DHT_GNS_REPLICATION_LEVEL 5 -#define MAX_DNS_LABEL_LENGTH 63 +#include "gnunet-service-gns_resolver.h" +#include "gnunet-service-gns_interceptor.h" /* FIXME move to proper header in include */ #define GNUNET_MESSAGE_TYPE_GNS_LOOKUP 23 @@ -53,113 +50,6 @@ #define GNUNET_MESSAGE_TYPE_GNS_GET_AUTH_RESULT 28 -struct AuthorityChain -{ - struct AuthorityChain *prev; - - struct AuthorityChain *next; - - GNUNET_HashCode zone; - - /* (local) name of the authority */ - char* name; - - /* was the ns entry fresh */ - int fresh; -}; - -/* handle to a resolution process */ -struct GNUNET_GNS_ResolverHandle; - -/** - * processor for a resultion result - * - * @param cls the closure - * @param rh the resolution handle - * @param rd_count number of results - * @pram rd resukt data - */ -typedef void (*ResolutionResultProcessor) (void *cls, - struct GNUNET_GNS_ResolverHandle *rh, - uint32_t rd_count, - const struct GNUNET_NAMESTORE_RecordData *rd); - -/** - * Resoltion status indicator - * EXISTS: the name to lookup exists - * EXPIRED: the name in the record expired - */ -enum ResolutionStatus -{ - EXISTS = 1, - EXPIRED = 2 -}; - -/** - * Handle to a currenty pending resolution - */ -struct GNUNET_GNS_ResolverHandle -{ - /* The name to resolve */ - char *name; - - /* has this query been answered? how many matches */ - int answered; - - /* the authoritative zone to query */ - GNUNET_HashCode authority; - - /* the name of the authoritative zone to query */ - char *authority_name; - - /** - * we have an authority in namestore that - * may be able to resolve - */ - int authority_found; - - /* a handle for dht lookups. should be NULL if no lookups are in progress */ - struct GNUNET_DHT_GetHandle *get_handle; - - /* timeout task for dht lookups */ - GNUNET_SCHEDULER_TaskIdentifier dht_timeout_task; - - /* called when resolution phase finishes */ - ResolutionResultProcessor proc; - - /* closure passed to proc */ - void* proc_cls; - - /* DLL to store the authority chain */ - struct AuthorityChain *authority_chain_head; - - /* DLL to store the authority chain */ - struct AuthorityChain *authority_chain_tail; - - /* status of the resolution result */ - enum ResolutionStatus status; - -}; - -/** - * Handle to a record lookup - */ -struct RecordLookupHandle -{ - /* the record type to look up */ - enum GNUNET_GNS_RecordType record_type; - - /* the name to look up */ - char *name; - - /* Method to call on record resolution result */ - ResolutionResultProcessor proc; - - /* closure to pass to proc */ - void* proc_cls; - -}; - /** * Handle to a shorten operation from api */ @@ -215,28 +105,6 @@ struct ClientLookupHandle char* name; //Needed? }; -/** - * Handle to a DNS intercepted - * reslution request - */ -struct InterceptLookupHandle -{ - /* the request handle to reply to */ - struct GNUNET_DNS_RequestHandle *request_handle; - - /* the dns parser packet received */ - struct GNUNET_DNSPARSER_Packet *packet; - - /* the query parsed from the packet */ - struct GNUNET_DNSPARSER_Query *query; -}; - - -/** - * Our handle to the DNS handler library - */ -struct GNUNET_DNS_Handle *dns_handle; - /** * Our handle to the DHT */ @@ -273,11 +141,6 @@ static struct GNUNET_SERVER_NotificationContext *nc; */ GNUNET_HashCode zone_hash; -/** - * Our tld. Maybe get from config file - */ -const char* gnunet_tld = ".gnunet"; - /** * Useful for zone update for DHT put */ @@ -289,1276 +152,31 @@ static struct GNUNET_TIME_Relative dht_update_interval; /* zone update task */ GNUNET_SCHEDULER_TaskIdentifier zone_update_taskid = GNUNET_SCHEDULER_NO_TASK; -/** - * Helper function to free resolver handle - * - * @rh the handle to free - */ -static void -free_resolver_handle(struct GNUNET_GNS_ResolverHandle* rh) -{ - struct AuthorityChain *ac; - struct AuthorityChain *ac_next; - - if (NULL == rh) - return; - - GNUNET_free_non_null (rh->name); - GNUNET_free_non_null (rh->authority_name); - - ac = rh->authority_chain_head; - - while (NULL != ac) - { - ac_next = ac->next; - GNUNET_free_non_null (ac->name); - GNUNET_free(ac); - ac = ac_next; - } - GNUNET_free(rh); -} - - -/** - * Reply to dns request with the result from our lookup. - * - * @param cls the closure to the request (an InterceptLookupHandle) - * @param rh the request handle of the lookup - * @param rd_count the number of records to return - * @param rd the record data - */ -static void -reply_to_dns(void* cls, struct GNUNET_GNS_ResolverHandle *rh, uint32_t rd_count, - const struct GNUNET_NAMESTORE_RecordData *rd) -{ - int i; - size_t len; - int ret; - char *buf; - struct InterceptLookupHandle* ilh = (struct InterceptLookupHandle*)cls; - struct GNUNET_DNSPARSER_Packet *packet = ilh->packet; - struct GNUNET_DNSPARSER_Record answer_records[rh->answered]; - struct GNUNET_DNSPARSER_Record additional_records[rd_count-(rh->answered)]; - packet->answers = answer_records; - packet->additional_records = additional_records; - - /** - * Put records in the DNS packet and modify it - * to a response - */ - len = sizeof(struct GNUNET_DNSPARSER_Record*); - for (i=0; i < rd_count; i++) - { - - GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, - "Adding type %d to DNS response\n", rd[i].record_type); - GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Name: %s\n", rh->name); - GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "QName: %s\n", ilh->query->name); - GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Record %d/%d\n", i+1, rd_count); - GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Record len %d\n", rd[i].data_size); - - if (rd[i].record_type == ilh->query->type) - { - answer_records[i].name = ilh->query->name; - answer_records[i].type = rd[i].record_type; - answer_records[i].data.raw.data_len = rd[i].data_size; - answer_records[i].data.raw.data = (char*)rd[i].data; - answer_records[i].expiration_time = rd[i].expiration; - answer_records[i].class = GNUNET_DNSPARSER_CLASS_INTERNET;//hmmn - } - else - { - additional_records[i].name = ilh->query->name; - additional_records[i].type = rd[i].record_type; - additional_records[i].data.raw.data_len = rd[i].data_size; - additional_records[i].data.raw.data = (char*)rd[i].data; - additional_records[i].expiration_time = rd[i].expiration; - additional_records[i].class = GNUNET_DNSPARSER_CLASS_INTERNET;//hmmn - } - } - - packet->num_answers = rh->answered; - packet->num_additional_records = rd_count-(rh->answered); - - if (0 == GNUNET_CRYPTO_hash_cmp(&rh->authority, &zone_hash)) - packet->flags.authoritative_answer = 1; - else - packet->flags.authoritative_answer = 0; - - if (rd == NULL) - packet->flags.return_code = GNUNET_DNSPARSER_RETURN_CODE_NAME_ERROR; - else - packet->flags.return_code = GNUNET_DNSPARSER_RETURN_CODE_NO_ERROR; - - packet->flags.query_or_response = 1; - - - /** - * Reply to DNS - */ - GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, - "Building DNS response\n"); - ret = GNUNET_DNSPARSER_pack (packet, - 1024, /* FIXME magic from dns redirector */ - &buf, - &len); - GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, - "Built DNS response! (ret=%d,len=%d)\n", ret, len); - if (ret == GNUNET_OK) - { - GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, - "Answering DNS request\n"); - GNUNET_DNS_request_answer(ilh->request_handle, - len, - buf); - - GNUNET_free(buf); - GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Answered DNS request\n"); - } - else - { - GNUNET_log(GNUNET_ERROR_TYPE_ERROR, - "Error building DNS response! (ret=%d)", ret); - } - - packet->num_answers = 0; - packet->answers = NULL; - packet->num_additional_records = 0; - packet->additional_records = NULL; - GNUNET_DNSPARSER_free_packet(packet); - //FIXME free more! - GNUNET_free((struct RecordLookupHandle*)rh->proc_cls); - free_resolver_handle(rh); - GNUNET_free(ilh); -} - - -/** - * Task run during shutdown. - * - * @param cls unused - * @param tc unused - */ -static void -shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) -{ - - GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, - "Shutting down!"); - /* Kill zone task for it may make the scheduler hang */ - if (zone_update_taskid) - GNUNET_SCHEDULER_cancel(zone_update_taskid); - - GNUNET_SERVER_notification_context_destroy (nc); - - if (dns_handle) - GNUNET_DNS_disconnect(dns_handle); - - GNUNET_NAMESTORE_disconnect(namestore_handle, 1); - GNUNET_DHT_disconnect(dht_handle); -} - - -/** - * Callback when record data is put into namestore - * - * @param cls the closure - * @param success GNUNET_OK on success - * @param emsg the error message. NULL if SUCCESS==GNUNET_OK - */ -void -on_namestore_record_put_result(void *cls, - int32_t success, - const char *emsg) -{ - if (GNUNET_NO == success) - { - GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "records already in namestore\n"); - return; - } - else if (GNUNET_YES == success) - { - GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, - "records successfully put in namestore\n"); - return; - } - - GNUNET_log(GNUNET_ERROR_TYPE_ERROR, - "Error putting records into namestore: %s\n", emsg); -} - - -/** - * Handle timeout for DHT requests - * - * @param cls the request handle as closure - * @param tc the task context - */ -static void -dht_lookup_timeout(void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) -{ - struct GNUNET_GNS_ResolverHandle *rh = cls; - - GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, - "dht lookup for query %s timed out.\n", - rh->name); - - GNUNET_DHT_get_stop (rh->get_handle); - rh->proc(rh->proc_cls, rh, 0, NULL); -} - - -/** - * Function called when we get a result from the dht - * for our record query - * - * @param cls the request handle - * @param exp lifetime - * @param key the key the record was stored under - * @param get_path get path - * @param get_path_length get path length - * @param put_path put path - * @param put_path_length put path length - * @param type the block type - * @param size the size of the record - * @param data the record data - */ -static void -process_record_dht_result(void* cls, - struct GNUNET_TIME_Absolute exp, - const GNUNET_HashCode * key, - const struct GNUNET_PeerIdentity *get_path, - unsigned int get_path_length, - const struct GNUNET_PeerIdentity *put_path, - unsigned int put_path_length, - enum GNUNET_BLOCK_Type type, - size_t size, const void *data) -{ - struct GNUNET_GNS_ResolverHandle *rh; - struct RecordLookupHandle *rlh; - struct GNSNameRecordBlock *nrb; - uint32_t num_records; - char* name = NULL; - char* rd_data = (char*)data; - int i; - int rd_size; - - GNUNET_HashCode zone, name_hash; - GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "got dht result (size=%d)\n", size); - - if (data == NULL) - return; - - //FIXME maybe check expiration here, check block type - - rh = (struct GNUNET_GNS_ResolverHandle *)cls; - rlh = (struct RecordLookupHandle *) rh->proc_cls; - nrb = (struct GNSNameRecordBlock*)data; - - /* stop lookup and timeout task */ - GNUNET_DHT_get_stop (rh->get_handle); - GNUNET_SCHEDULER_cancel(rh->dht_timeout_task); - - rh->get_handle = NULL; - name = (char*)&nrb[1]; - num_records = ntohl(nrb->rd_count); - { - struct GNUNET_NAMESTORE_RecordData rd[num_records]; - - rd_data += strlen(name) + 1 + sizeof(struct GNSNameRecordBlock); - rd_size = size - strlen(name) - 1 - sizeof(struct GNSNameRecordBlock); - - if (GNUNET_SYSERR == GNUNET_NAMESTORE_records_deserialize (rd_size, - rd_data, - num_records, - rd)) - { - GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Error deserializing data!\n"); - return; - } - - for (i=0; iname); - GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, - "Got type: %d\n", - rd[i].record_type); - GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, - "Got data length: %d\n", rd[i].data_size); - GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, - "Got flag %d\n", rd[i].flags); - - if ((strcmp(name, rh->name) == 0) && - (rd[i].record_type == rlh->record_type)) - { - rh->answered++; - } - - } - - GNUNET_CRYPTO_hash(name, strlen(name), &name_hash); - GNUNET_CRYPTO_hash_xor(key, &name_hash, &zone); - - /** - * FIXME check pubkey against existing key in namestore? - * https://gnunet.org/bugs/view.php?id=2179 - */ - - /* Save to namestore */ - GNUNET_NAMESTORE_record_put (namestore_handle, - &nrb->public_key, - name, - exp, - num_records, - rd, - &nrb->signature, - &on_namestore_record_put_result, //cont - NULL); //cls - - if (rh->answered) - rh->proc(rh->proc_cls, rh, num_records, rd); - else - rh->proc(rh->proc_cls, rh, 0, NULL); - } - -} - - -/** - * Start DHT lookup for a (name -> query->record_type) record in - * rh->authority's zone - * - * @param rh the pending gns query context - */ -static void -resolve_record_dht(struct GNUNET_GNS_ResolverHandle *rh) -{ - uint32_t xquery; - GNUNET_HashCode name_hash; - GNUNET_HashCode lookup_key; - struct GNUNET_CRYPTO_HashAsciiEncoded lookup_key_string; - struct RecordLookupHandle *rlh = (struct RecordLookupHandle *)rh->proc_cls; - - GNUNET_CRYPTO_hash(rh->name, strlen(rh->name), &name_hash); - GNUNET_CRYPTO_hash_xor(&name_hash, &rh->authority, &lookup_key); - GNUNET_CRYPTO_hash_to_enc (&lookup_key, &lookup_key_string); - - GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, - "starting dht lookup for %s with key: %s\n", - rh->name, (char*)&lookup_key_string); - - rh->dht_timeout_task = GNUNET_SCHEDULER_add_delayed(DHT_LOOKUP_TIMEOUT, - &dht_lookup_timeout, rh); - - xquery = htonl(rlh->record_type); - rh->get_handle = GNUNET_DHT_get_start(dht_handle, - DHT_OPERATION_TIMEOUT, - GNUNET_BLOCK_TYPE_GNS_NAMERECORD, - &lookup_key, - DHT_GNS_REPLICATION_LEVEL, - GNUNET_DHT_RO_NONE, - &xquery, - sizeof(xquery), - &process_record_dht_result, - rh); - -} - - -/** - * Namestore calls this function if we have record for this name. - * (or with rd_count=0 to indicate no matches) - * - * @param cls the pending query - * @param key the key of the zone we did the lookup - * @param expiration expiration date of the namestore entry - * @param name the name for which we need an authority - * @param rd_count the number of records with 'name' - * @param rd the record data - * @param signature the signature of the authority for the record data - */ -static void -process_record_lookup_ns(void* cls, - const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *key, - struct GNUNET_TIME_Absolute expiration, - const char *name, unsigned int rd_count, - const struct GNUNET_NAMESTORE_RecordData *rd, - const struct GNUNET_CRYPTO_RsaSignature *signature) -{ - struct GNUNET_GNS_ResolverHandle *rh; - struct RecordLookupHandle *rlh; - struct GNUNET_TIME_Relative remaining_time; - GNUNET_HashCode zone; - - rh = (struct GNUNET_GNS_ResolverHandle *) cls; - rlh = (struct RecordLookupHandle *)rh->proc_cls; - GNUNET_CRYPTO_hash(key, - sizeof(struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded), - &zone); - remaining_time = GNUNET_TIME_absolute_get_remaining (expiration); - - rh->status = 0; - - if (name != NULL) - { - rh->status |= EXISTS; - } - - if (remaining_time.rel_value == 0) - { - rh->status |= EXPIRED; - } - - if (rd_count == 0) - { - /** - * Lookup terminated and no results - */ - GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, - "Namestore lookup for %s terminated without results\n", name); - - GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, - "Record %s unknown in namestore\n", - rh->name); - /** - * Our zone and no result? Cannot resolve TT - */ - rh->proc(rh->proc_cls, rh, 0, NULL); - return; - - } - else - { - - GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, - "Processing additional result %s from namestore\n", name); - int i; - for (i=0; irecord_type) - continue; - - if ((GNUNET_TIME_absolute_get_remaining (rd[i].expiration)).rel_value - == 0) - { - GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "This record is expired. Skipping\n"); - continue; - } - - rh->answered++; - - } - - /** - * no answers found - */ - if (rh->answered == 0) - { - GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, - "No answers found. This is odd!\n"); - rh->proc(rh->proc_cls, rh, 0, NULL); - return; - } - - GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Found %d answer(s) to query!\n", - rh->answered); - - rh->proc(rh->proc_cls, rh, rd_count, rd); - } -} - - -/** - * The final phase of resolution. - * rh->name is a name that is canonical and we do not have a delegation. - * Query namestore for this record - * - * @param rh the pending lookup - */ -static void -resolve_record_ns(struct GNUNET_GNS_ResolverHandle *rh) -{ - struct RecordLookupHandle *rlh = (struct RecordLookupHandle *)rh->proc_cls; - - /** - * Try to resolve this record in our namestore. - * The name to resolve is now in rh->authority_name - * since we tried to resolve it to an authority - * and failed. - **/ - GNUNET_NAMESTORE_lookup_record(namestore_handle, - &rh->authority, - rh->name, - rlh->record_type, - &process_record_lookup_ns, - rh); -} - - -/** - * Handle timeout for DHT requests - * - * @param cls the request handle as closure - * @param tc the task context - */ -static void -dht_authority_lookup_timeout(void *cls, - const struct GNUNET_SCHEDULER_TaskContext *tc) -{ - struct GNUNET_GNS_ResolverHandle *rh = cls; - - GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, - "dht lookup for query %s timed out.\n", - rh->name); - - GNUNET_DHT_get_stop (rh->get_handle); - if (strcmp(rh->name, "") == 0) - { - /* - * promote authority back to name and try to resolve record - */ - strcpy(rh->name, rh->authority_name); - } - rh->proc(rh->proc_cls, rh, 0, NULL); -} - -/* Prototype */ -static void resolve_delegation_dht(struct GNUNET_GNS_ResolverHandle *rh); - -/** - * Function called when we get a result from the dht - * for our query. Recursively tries to resolve authorities - * for name in DHT. - * - * @param cls the request handle - * @param exp lifetime - * @param key the key the record was stored under - * @param get_path get path - * @param get_path_length get path length - * @param put_path put path - * @param put_path_length put path length - * @param type the block type - * @param size the size of the record - * @param data the record data - */ -static void -process_delegation_result_dht(void* cls, - struct GNUNET_TIME_Absolute exp, - const GNUNET_HashCode * key, - const struct GNUNET_PeerIdentity *get_path, - unsigned int get_path_length, - const struct GNUNET_PeerIdentity *put_path, - unsigned int put_path_length, - enum GNUNET_BLOCK_Type type, - size_t size, const void *data) -{ - struct GNUNET_GNS_ResolverHandle *rh; - struct GNSNameRecordBlock *nrb; - uint32_t num_records; - char* name = NULL; - char* rd_data = (char*) data; - int i; - int rd_size; - GNUNET_HashCode zone, name_hash; - - GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Got DHT result\n"); - - if (data == NULL) - return; - - //FIXME check expiration? - - rh = (struct GNUNET_GNS_ResolverHandle *)cls; - nrb = (struct GNSNameRecordBlock*)data; - - /* stop dht lookup and timeout task */ - GNUNET_DHT_get_stop (rh->get_handle); - GNUNET_SCHEDULER_cancel(rh->dht_timeout_task); - - rh->get_handle = NULL; - num_records = ntohl(nrb->rd_count); - name = (char*)&nrb[1]; - { - struct GNUNET_NAMESTORE_RecordData rd[num_records]; - - rd_data += strlen(name) + 1 + sizeof(struct GNSNameRecordBlock); - rd_size = size - strlen(name) - 1 - sizeof(struct GNSNameRecordBlock); - - if (GNUNET_SYSERR == GNUNET_NAMESTORE_records_deserialize (rd_size, - rd_data, - num_records, - rd)) - { - GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Error deserializing data!\n"); - return; - } - - GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, - "Got name: %s (wanted %s)\n", name, rh->authority_name); - for (i=0; iauthority_name); - GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, - "Got type: %d (wanted %d)\n", - rd[i].record_type, GNUNET_GNS_RECORD_PKEY); - GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, - "Got data length: %d\n", rd[i].data_size); - GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, - "Got flag %d\n", rd[i].flags); - - if ((strcmp(name, rh->authority_name) == 0) && - (rd[i].record_type == GNUNET_GNS_RECORD_PKEY)) - { - GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Authority found in DHT\n"); - rh->answered = 1; - memcpy(&rh->authority, rd[i].data, sizeof(GNUNET_HashCode)); - struct AuthorityChain *auth = - GNUNET_malloc(sizeof(struct AuthorityChain)); - auth->zone = rh->authority; - auth->name = GNUNET_malloc(strlen(rh->authority_name)+1); - 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); - } - - } - - - GNUNET_CRYPTO_hash(name, strlen(name), &name_hash); - GNUNET_CRYPTO_hash_xor(key, &name_hash, &zone); - - /* Save to namestore */ - if (0 != GNUNET_CRYPTO_hash_cmp(&zone_hash, &zone)) - { - GNUNET_NAMESTORE_record_put (namestore_handle, - &nrb->public_key, - name, - exp, - num_records, - rd, - &nrb->signature, - &on_namestore_record_put_result, //cont - NULL); //cls - } - } - - if (rh->answered) - { - rh->answered = 0; - /** - * delegate - * FIXME in this case. should we ask namestore again? - */ - if (strcmp(rh->name, "") == 0) - rh->proc(rh->proc_cls, rh, 0, NULL); - else - resolve_delegation_dht(rh); - return; - } - - /** - * should never get here unless false dht key/put - * block plugin should handle this - **/ - GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "DHT authority lookup error!\n"); - GNUNET_break(0); -} - - -/** - * Process DHT lookup result for record. - * - * @param cls the closure - * @param rh resolver handle - * @param rd_count number of results (always 0) - * @param rd record data (always NULL) - */ -static void -process_record_result_dht(void* cls, struct GNUNET_GNS_ResolverHandle *rh, - unsigned int rd_count, - const struct GNUNET_NAMESTORE_RecordData *rd) -{ - struct RecordLookupHandle* rlh; - rlh = (struct RecordLookupHandle*)cls; - if (rd_count == 0) - { - GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, - "No records for %s found in DHT. Aborting\n", - rh->name); - /* give up, cannot resolve */ - rlh->proc(rlh->proc_cls, rh, 0, NULL); - return; - } - - /* results found yay */ - GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, - "Record resolved from namestore!"); - rlh->proc(rlh->proc_cls, rh, rd_count, rd); - -} - - -/** - * Process namestore lookup result for record. - * - * @param cls the closure - * @param rh resolver handle - * @param rd_count number of results (always 0) - * @param rd record data (always NULL) - */ -static void -process_record_result_ns(void* cls, struct GNUNET_GNS_ResolverHandle *rh, - unsigned int rd_count, - const struct GNUNET_NAMESTORE_RecordData *rd) -{ - struct RecordLookupHandle* rlh; - rlh = (struct RecordLookupHandle*) cls; - if (rd_count == 0) - { - /* ns entry expired. try dht */ - if (rh->status & (EXPIRED | !EXISTS)) - { - rh->proc = &process_record_result_dht; - resolve_record_dht(rh); - return; - } - /* give up, cannot resolve */ - rlh->proc(rlh->proc_cls, rh, 0, NULL); - return; - } - - /* results found yay */ - GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, - "Record resolved from namestore!"); - rlh->proc(rlh->proc_cls, rh, rd_count, rd); - -} - - -/** - * Determine if this name is canonical. - * i.e. - * a.b.gnunet = not canonical - * a = canonical - * - * @param name the name to test - * @return 1 if canonical - */ -static int -is_canonical(char* name) -{ - uint32_t len = strlen(name); - int i; - - for (i=0; i 0; len--) - { - if (*(name+len) == '.') - break; - } - - //Was canonical? - if (len == 0) - return; - - name[len] = '\0'; - - strcpy(dest, (name+len+1)); -} - -/** - * DHT resolution for delegation finished. Processing result. - * - * @param cls the closure - * @param rh resolver handle - * @param rd_count number of results (always 0) - * @param rd record data (always NULL) - */ -static void -process_delegation_dht(void* cls, struct GNUNET_GNS_ResolverHandle *rh, - unsigned int rd_count, - const struct GNUNET_NAMESTORE_RecordData *rd) -{ - struct RecordLookupHandle* rlh; - rlh = (struct RecordLookupHandle*) cls; - - if (strcmp(rh->name, "") == 0) - { - /* We resolved full name for delegation. resolving record */ - GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, - "Resolved full name for delegation via DHT. resolving record '' in ns\n"); - rh->proc = &process_record_result_ns; - resolve_record_ns(rh); - return; - } - - /** - * we still have some left - **/ - if (is_canonical(rh->name)) - { - GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, - "Resolving canonical record %s in ns\n", rh->name); - rh->proc = &process_record_result_ns; - resolve_record_ns(rh); - return; - } - /* give up, cannot resolve */ - GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, - "Cannot fully resolve delegation for %s via DHT!\n", - rh->name); - rlh->proc(rlh->proc_cls, rh, 0, NULL); -} - - -/** - * Start DHT lookup for a name -> PKEY (compare NS) record in - * rh->authority's zone - * - * @param rh the pending gns query - * @param name the name of the PKEY record - */ -static void -resolve_delegation_dht(struct GNUNET_GNS_ResolverHandle *rh) -{ - uint32_t xquery; - GNUNET_HashCode name_hash; - GNUNET_HashCode lookup_key; - - GNUNET_CRYPTO_hash(rh->authority_name, - strlen(rh->authority_name), - &name_hash); - GNUNET_CRYPTO_hash_xor(&name_hash, &rh->authority, &lookup_key); - - rh->dht_timeout_task = GNUNET_SCHEDULER_add_delayed (DHT_LOOKUP_TIMEOUT, - &dht_authority_lookup_timeout, - rh); - - xquery = htonl(GNUNET_GNS_RECORD_PKEY); - - rh->get_handle = GNUNET_DHT_get_start(dht_handle, - DHT_OPERATION_TIMEOUT, - GNUNET_BLOCK_TYPE_GNS_NAMERECORD, - &lookup_key, - DHT_GNS_REPLICATION_LEVEL, - GNUNET_DHT_RO_NONE, - &xquery, - sizeof(xquery), - &process_delegation_result_dht, - rh); - -} - - -/** - * Namestore resolution for delegation finished. Processing result. - * - * @param cls the closure - * @param rh resolver handle - * @param rd_count number of results (always 0) - * @param rd record data (always NULL) - */ -static void -process_delegation_ns(void* cls, struct GNUNET_GNS_ResolverHandle *rh, - unsigned int rd_count, - const struct GNUNET_NAMESTORE_RecordData *rd) -{ - struct RecordLookupHandle* rlh; - rlh = (struct RecordLookupHandle*) cls; - - if (strcmp(rh->name, "") == 0) - { - /* We resolved full name for delegation. resolving record */ - GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, - "Resolved full name for delegation. resolving record ''\n"); - rh->proc = &process_record_result_ns; - resolve_record_ns(rh); - return; - } - - /** - * we still have some left - * check if ns entry is fresh - **/ - if (rh->status & (EXISTS | !EXPIRED)) - { - if (is_canonical(rh->name)) - { - GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, - "Resolving canonical record %s\n", rh->name); - rh->proc = &process_record_result_ns; - resolve_record_ns(rh); - } - else - { - /* give up, cannot resolve */ - GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, - "Cannot fully resolve delegation for %s!\n", - rh->name); - rlh->proc(rlh->proc_cls, rh, 0, NULL); - } - return; - } - - GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, - "Trying to resolve delegation for %s via DHT\n", - rh->name); - rh->proc = &process_delegation_dht; - resolve_delegation_dht(rh); -} - -//Prototype -static void resolve_delegation_ns(struct GNUNET_GNS_ResolverHandle *rh); - -/** - * This is a callback function that should give us only PKEY - * records. Used to query the namestore for the authority (PKEY) - * for 'name'. It will recursively try to resolve the - * authority for a given name from the namestore. - * - * @param cls the pending query - * @param key the key of the zone we did the lookup - * @param expiration expiration date of the record data set in the namestore - * @param name the name for which we need an authority - * @param rd_count the number of records with 'name' - * @param rd the record data - * @param signature the signature of the authority for the record data - */ -static void -process_delegation_result_ns(void* cls, - const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *key, - struct GNUNET_TIME_Absolute expiration, - const char *name, - unsigned int rd_count, - const struct GNUNET_NAMESTORE_RecordData *rd, - const struct GNUNET_CRYPTO_RsaSignature *signature) -{ - struct GNUNET_GNS_ResolverHandle *rh; - struct GNUNET_TIME_Relative remaining_time; - GNUNET_HashCode zone; - char* new_name; - - GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Got %d records from authority lookup\n", - rd_count); - - rh = (struct GNUNET_GNS_ResolverHandle *)cls; - GNUNET_CRYPTO_hash(key, - sizeof(struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded), - &zone); - remaining_time = GNUNET_TIME_absolute_get_remaining (expiration); - - rh->status = 0; - - if (name != NULL) - { - rh->status |= EXISTS; - } - - if (remaining_time.rel_value == 0) - { - rh->status |= EXPIRED; - } - - /** - * No authority found in namestore. - */ - if (rd_count == 0) - { - /** - * We did not find an authority in the namestore - */ - - /** - * No PKEY in zone. - * Promote this authority back to a name maybe it is - * our record. - */ - if (strcmp(rh->name, "") == 0) - { - /* simply promote back */ - GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, - "Promoting %s back to name\n", rh->authority_name); - strcpy(rh->name, rh->authority_name); - } - else - { - /* add back to existing name */ - GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, - "Adding %s back to %s\n", - rh->authority_name, rh->name); - new_name = GNUNET_malloc(strlen(rh->name) - + strlen(rh->authority_name) + 2); - memset(new_name, 0, strlen(rh->name) + strlen(rh->authority_name) + 2); - strcpy(new_name, rh->name); - strcpy(new_name+strlen(new_name)+1, "."); - strcpy(new_name+strlen(new_name)+2, rh->authority_name); - GNUNET_free(rh->name); - rh->name = new_name; - } - rh->proc(rh->proc_cls, rh, 0, NULL); - return; - } - - //Note only 1 pkey should have been returned.. anything else would be strange - /** - * We found an authority that may be able to help us - * move on with query - */ - int i; - for (i=0; iauthority_chain_head->fresh = 0; - rh->proc(rh->proc_cls, rh, 0, NULL); - return; - } - - continue; - } - - /** - * Resolve rest of query with new authority - */ - GNUNET_assert(rd[i].record_type == GNUNET_GNS_RECORD_PKEY); - memcpy(&rh->authority, rd[i].data, sizeof(GNUNET_HashCode)); - struct AuthorityChain *auth = GNUNET_malloc(sizeof(struct AuthorityChain)); - auth->zone = rh->authority; - auth->name = GNUNET_malloc(strlen(rh->authority_name)+1); - 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); - - /** - * We are done with PKEY resolution if name is empty - * else resolve again with new authority - */ - if (strcmp(rh->name, "") == 0) - rh->proc(rh->proc_cls, rh, 0, NULL); - else - resolve_delegation_ns(rh); - return; - } - - /** - * no answers found - */ - GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, - "Authority lookup successful but no PKEY... never get here\n"); - rh->proc(rh->proc_cls, rh, 0, NULL); -} - - -/** - * Resolve the delegation chain for the request in our namestore - * - * @param rh the resolver handle - */ -static void -resolve_delegation_ns(struct GNUNET_GNS_ResolverHandle *rh) -{ - - pop_tld(rh->name, rh->authority_name); - GNUNET_NAMESTORE_lookup_record(namestore_handle, - &rh->authority, - rh->authority_name, - GNUNET_GNS_RECORD_PKEY, - &process_delegation_result_ns, - rh); - -} - -/** - * Entry point for name resolution - * Setup a new query and try to resolve - * - * @param request the request handle of the DNS request from a client - * @param p the DNS query packet we received - * @param q the DNS query we received parsed from p - */ -static void -start_resolution_for_dns(struct GNUNET_DNS_RequestHandle *request, - struct GNUNET_DNSPARSER_Packet *p, - struct GNUNET_DNSPARSER_Query *q) -{ - struct GNUNET_GNS_ResolverHandle *rh; - struct RecordLookupHandle* rlh; - struct InterceptLookupHandle* ilh; - - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Starting resolution for %s (type=%d)!\n", - q->name, q->type); - - rh = GNUNET_malloc(sizeof (struct GNUNET_GNS_ResolverHandle)); - rlh = GNUNET_malloc(sizeof(struct RecordLookupHandle)); - ilh = GNUNET_malloc(sizeof(struct InterceptLookupHandle)); - ilh->packet = p; - ilh->query = q; - ilh->request_handle = request; - - rh->authority = zone_hash; - - rlh->record_type = q->type; - rlh->name = q->name; - rlh->proc = &reply_to_dns; - rlh->proc_cls = ilh; - - rh->proc_cls = rlh; - - rh->name = GNUNET_malloc(strlen(q->name) - - strlen(gnunet_tld) + 1); - memset(rh->name, 0, - strlen(q->name)-strlen(gnunet_tld) + 1); - memcpy(rh->name, q->name, - strlen(q->name)-strlen(gnunet_tld)); - - rh->authority_name = GNUNET_malloc(sizeof(char)*MAX_DNS_LABEL_LENGTH); - - rh->authority_chain_head = GNUNET_malloc(sizeof(struct AuthorityChain)); - rh->authority_chain_head->prev = NULL; - rh->authority_chain_head->next = NULL; - rh->authority_chain_tail = rh->authority_chain_head; - rh->authority_chain_head->zone = zone_hash; - - /* Start resolution in our zone */ - rh->proc = &process_delegation_ns; - resolve_delegation_ns(rh); -} - - - -/** - * The DNS request handler - * Called for every incoming DNS request. - * - * @param cls closure - * @param rh request handle to user for reply - * @param request_length number of bytes in request - * @param request udp payload of the DNS request - */ -static void -handle_dns_request(void *cls, - struct GNUNET_DNS_RequestHandle *rh, - size_t request_length, - const char *request) -{ - struct GNUNET_DNSPARSER_Packet *p; - int i; - char *tldoffset; - - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Hijacked a DNS request...processing\n"); - p = GNUNET_DNSPARSER_parse (request, request_length); - - if (NULL == p) - { - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - "Received malformed DNS packet, leaving it untouched\n"); - GNUNET_DNS_request_forward (rh); - GNUNET_DNSPARSER_free_packet (p); - return; - } - - /** - * Check tld and decide if we or - * legacy dns is responsible - * - * FIXME now in theory there could be more than 1 query in the request - * but if this is case we get into trouble: - * either we query the GNS or the DNS. We cannot do both! - * So I suggest to either only allow a single query per request or - * only allow GNS or DNS requests. - * The way it is implemented here now is buggy and will lead to erratic - * behaviour (if multiple queries are present). - */ - if (p->num_queries == 0) - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "No Queries in DNS packet... forwarding\n"); - GNUNET_DNS_request_forward (rh); - GNUNET_DNSPARSER_free_packet(p); - return; - } - - if (p->num_queries > 1) - { - /* Note: We could also look for .gnunet */ - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - ">1 queriy in DNS packet... odd. We only process #1\n"); - } - - - /** - * Check for .gnunet - */ - tldoffset = p->queries[0].name + strlen(p->queries[0].name) - 1; +/** + * Task run during shutdown. + * + * @param cls unused + * @param tc unused + */ +static void +shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) +{ + + GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, + "Shutting down!"); + /* Kill zone task for it may make the scheduler hang */ + if (zone_update_taskid) + GNUNET_SCHEDULER_cancel(zone_update_taskid); - for (i=0; iqueries[0].name); i++) - { - if (*(tldoffset-i) == '.') - break; - } + GNUNET_SERVER_notification_context_destroy (nc); - if ((i==strlen(gnunet_tld)-1) && (0 == strcmp(tldoffset-i, gnunet_tld))) - { - start_resolution_for_dns(rh, p, p->queries); - } - else - { - /** - * This request does not concern us. Forward to real DNS. - */ - GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, - "Request for %s is forwarded to DNS\n", p->queries[0].name); - GNUNET_DNS_request_forward (rh); - GNUNET_DNSPARSER_free_packet (p); - } + gns_interceptor_stop(); + GNUNET_NAMESTORE_disconnect(namestore_handle, 1); + GNUNET_DHT_disconnect(dht_handle); } + /** * Method called periodicattluy that triggers * iteration over root zone @@ -1727,577 +345,8 @@ update_zone_dht_start(void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) NULL); } -//Prototype -static void send_shorten_response(const char* name, - struct ClientShortenHandle *csh); -static void -process_shorten_pseu_lookup_ns(void *cls, - const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *zone_key, - struct GNUNET_TIME_Absolute expire, - const char *name, - unsigned int rd_len, - const struct GNUNET_NAMESTORE_RecordData *rd, - const struct GNUNET_CRYPTO_RsaSignature *signature) -{ - struct GNUNET_GNS_ResolverHandle *rh = - (struct GNUNET_GNS_ResolverHandle *)cls; - struct GNUNET_TIME_Relative remaining_time; - - GNUNET_TIME_absolute_get_remaining (expire); - rh->status = 0; - - if (name != NULL) - { - rh->status |= EXISTS; - } - - if (remaining_time.rel_value == 0) - { - rh->status |= EXPIRED; - } - - rh->proc(rh->proc_cls, rh, rd_len, rd); -} - - -/** - * Function called when we get a result from the dht - * for our record query - * - * @param cls the request handle - * @param exp lifetime - * @param key the key the record was stored under - * @param get_path get path - * @param get_path_length get path length - * @param put_path put path - * @param put_path_length put path length - * @param type the block type - * @param size the size of the record - * @param data the record data - */ -static void -process_pseu_dht_result(void* cls, - struct GNUNET_TIME_Absolute exp, - const GNUNET_HashCode * key, - const struct GNUNET_PeerIdentity *get_path, - unsigned int get_path_length, - const struct GNUNET_PeerIdentity *put_path, - unsigned int put_path_length, - enum GNUNET_BLOCK_Type type, - size_t size, const void *data) -{ - struct GNUNET_GNS_ResolverHandle *rh; - struct RecordLookupHandle *rlh; - struct GNSNameRecordBlock *nrb; - uint32_t num_records; - char* name = NULL; - char* rd_data = (char*)data; - int i; - int rd_size; - - GNUNET_HashCode zone, name_hash; - GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "got PSEU dht result (size=%d)\n", size); - - if (data == NULL) - return; - - //FIXME maybe check expiration here, check block type - - rh = (struct GNUNET_GNS_ResolverHandle *)cls; - rlh = (struct RecordLookupHandle *) rh->proc_cls; - nrb = (struct GNSNameRecordBlock*)data; - - /* stop lookup and timeout task */ - GNUNET_DHT_get_stop (rh->get_handle); - GNUNET_SCHEDULER_cancel(rh->dht_timeout_task); - - rh->get_handle = NULL; - name = (char*)&nrb[1]; - num_records = ntohl(nrb->rd_count); - { - struct GNUNET_NAMESTORE_RecordData rd[num_records]; - - rd_data += strlen(name) + 1 + sizeof(struct GNSNameRecordBlock); - rd_size = size - strlen(name) - 1 - sizeof(struct GNSNameRecordBlock); - - if (GNUNET_SYSERR == GNUNET_NAMESTORE_records_deserialize (rd_size, - rd_data, - num_records, - rd)) - { - GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Error deserializing data!\n"); - return; - } - - for (i=0; iname); - GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, - "Got type: %d\n", - rd[i].record_type); - GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, - "Got data length: %d\n", rd[i].data_size); - GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, - "Got flag %d\n", rd[i].flags); - - if ((strcmp(name, "+") == 0) && - (rd[i].record_type == GNUNET_GNS_RECORD_PSEU)) - { - rh->answered++; - } - - } - - GNUNET_CRYPTO_hash(name, strlen(name), &name_hash); - GNUNET_CRYPTO_hash_xor(key, &name_hash, &zone); - - /** - * FIXME check pubkey against existing key in namestore? - * https://gnunet.org/bugs/view.php?id=2179 - */ - - /* Save to namestore */ - GNUNET_NAMESTORE_record_put (namestore_handle, - &nrb->public_key, - name, - exp, - num_records, - rd, - &nrb->signature, - &on_namestore_record_put_result, //cont - NULL); //cls - - if (rh->answered) - rh->proc(rh->proc_cls, rh, num_records, rd); - else - rh->proc(rh->proc_cls, rh, 0, NULL); - } - -} - - -/** - * Start DHT lookup for a PSEUdonym record in - * rh->authority's zone - * - * @param rh the pending gns query - */ -static void -resolve_pseu_dht(struct GNUNET_GNS_ResolverHandle *rh) -{ - uint32_t xquery; - GNUNET_HashCode name_hash; - GNUNET_HashCode lookup_key; - - GNUNET_CRYPTO_hash("+", - strlen("+"), - &name_hash); - - GNUNET_CRYPTO_hash_xor(&name_hash, &rh->authority, &lookup_key); - - rh->dht_timeout_task = GNUNET_SCHEDULER_add_delayed (DHT_LOOKUP_TIMEOUT, - &dht_lookup_timeout, - rh); - - xquery = htonl(GNUNET_GNS_RECORD_PSEU); - - rh->get_handle = GNUNET_DHT_get_start(dht_handle, - DHT_OPERATION_TIMEOUT, - GNUNET_BLOCK_TYPE_GNS_NAMERECORD, - &lookup_key, - DHT_GNS_REPLICATION_LEVEL, - GNUNET_DHT_RO_NONE, - &xquery, - sizeof(xquery), - &process_pseu_dht_result, - rh); - -} - -//Prototype -static void -handle_shorten_pseu_ns_result(void* cls, - struct GNUNET_GNS_ResolverHandle *rh, - uint32_t rd_count, - const struct GNUNET_NAMESTORE_RecordData *rd); - -static void -handle_shorten_zone_to_name(void *cls, - const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *zone_key, - struct GNUNET_TIME_Absolute expire, - const char *name, - unsigned int rd_len, - const struct GNUNET_NAMESTORE_RecordData *rd, - const struct GNUNET_CRYPTO_RsaSignature *signature) -{ - struct GNUNET_GNS_ResolverHandle *rh = - (struct GNUNET_GNS_ResolverHandle *)cls; - struct ClientShortenHandle* csh = (struct ClientShortenHandle*) rh->proc_cls; - - char* result; - size_t answer_len; - - /* we found a match in our own zone */ - if (rd_len != 0) - { - answer_len = strlen(rh->name) + strlen(name) + strlen(gnunet_tld) + 2; - result = GNUNET_malloc(answer_len); - memset(result, 0, answer_len); - strcpy(result, rh->name); - strcpy(result+strlen(rh->name), "."); - strcpy(result+strlen(rh->name)+1, name); - strcpy(result+strlen(rh->name)+strlen(name), gnunet_tld); - - GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, - "Sending shorten result %s\n", result); - - send_shorten_response(result, csh); - free_resolver_handle(rh); - GNUNET_free(result); - } - else - { - /** - * Nothing in our zone - * check PSEU for this authority in namestore - */ - rh->proc = &handle_shorten_pseu_ns_result; - GNUNET_NAMESTORE_lookup_record(namestore_handle, - &rh->authority_chain_head->zone, - "+", - GNUNET_GNS_RECORD_PSEU, - &process_shorten_pseu_lookup_ns, - rh); - } -} - -/** - * Process result from namestore delegation lookup - * for shorten operation - * - * @param cls the client shorten handle - * @param rh the resolver handle - * @param rd_count number of results (0) - * @param rd data (NULL) - */ -void -handle_shorten_pseu_dht_result(void* cls, - struct GNUNET_GNS_ResolverHandle *rh, - uint32_t rd_len, - const struct GNUNET_NAMESTORE_RecordData *rd) -{ - struct ClientShortenHandle* csh = (struct ClientShortenHandle*) cls; - struct AuthorityChain *auth_chain; - char* pseu; - char* result; - char* new_name; - size_t answer_len; - int i; - - /** - * PSEU found - */ - if (rd_len != 0) - { - for (i=0; i < rd_len; i++) - { - if (rd[i].record_type == GNUNET_GNS_RECORD_PSEU) - { - GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, - "Found PSEU %s\n", (char*) rd[i].data); - break; - } - } - - pseu = (char*) rd[i].data; - answer_len = strlen(rh->name) + strlen(pseu) + strlen(gnunet_tld) + 2; - result = GNUNET_malloc(answer_len); - memset(result, 0, answer_len); - strcpy(result, rh->name); - strcpy(result+strlen(rh->name), "."); - strcpy(result+strlen(rh->name)+1, pseu); - strcpy(result+strlen(rh->name)+strlen(pseu)+1, gnunet_tld); - - GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, - "Sending pseudonym shorten result %s\n", result); - - send_shorten_response(result, csh); - free_resolver_handle(rh); - GNUNET_free(result); - return; - } - - /** - * No PSEU found. - * continue with next authority - * backtrack - */ - auth_chain = rh->authority_chain_head; - - if ((auth_chain->next->next == NULL) && - GNUNET_CRYPTO_hash_cmp(&auth_chain->next->zone, &zone_hash) == 0) - { - /** - * Our zone is next - */ - answer_len = strlen(rh->name) + strlen(auth_chain->name) - + strlen(gnunet_tld) + 2; - - result = GNUNET_malloc(answer_len); - memset(result, 0, answer_len); - strcpy(result, rh->name); - strcpy(result+strlen(rh->name), "."); - strcpy(result+strlen(rh->name)+1, auth_chain->name); - strcpy(result+strlen(rh->name)+strlen(auth_chain->name)+1, gnunet_tld); - GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, - "Sending non pseudonym shorten result %s\n", result); - - send_shorten_response(result, csh); - free_resolver_handle(rh); - GNUNET_free(result); - return; - } - - /** - * Continue with next authority - */ - new_name = GNUNET_malloc(strlen(rh->name)+ - strlen(auth_chain->name) + 2); - memset(new_name, 0, strlen(rh->name)+ - strlen(auth_chain->name) + 2); - strcpy(new_name, rh->name); - strcpy(new_name+strlen(rh->name)+1, "."); - strcpy(new_name+strlen(rh->name)+2, auth_chain->name); - GNUNET_CONTAINER_DLL_remove(rh->authority_chain_head, - rh->authority_chain_tail, - auth_chain); - GNUNET_free(rh->name); - rh->name = new_name; - GNUNET_free(auth_chain->name); - GNUNET_free(auth_chain); - GNUNET_NAMESTORE_zone_to_name (namestore_handle, - &zone_hash, - &rh->authority_chain_head->zone, - &handle_shorten_zone_to_name, - rh); - -} - - - -/** - * Process result from namestore PSEU lookup - * for shorten operation - * FIXME do we need to check for own zone here? - * - * @param cls the client shorten handle - * @param rh the resolver handle - * @param rd_count number of results (0 if none found) - * @param rd data (NULL if none found) - */ -static void -handle_shorten_pseu_ns_result(void* cls, - struct GNUNET_GNS_ResolverHandle *rh, - uint32_t rd_len, - const struct GNUNET_NAMESTORE_RecordData *rd) -{ - struct ClientShortenHandle* csh = (struct ClientShortenHandle*) cls; - struct AuthorityChain *auth_chain; - char* pseu; - char* result; - char* new_name; - size_t answer_len; - int i; - - /** - * PSEU found - */ - if (rd_len != 0) - { - for (i=0; i < rd_len; i++) - { - if (rd[i].record_type == GNUNET_GNS_RECORD_PSEU) - { - GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, - "Found PSEU %s\n", (char*) rd[i].data); - break; - } - } - - pseu = (char*) rd[i].data; - answer_len = strlen(rh->name) + strlen(pseu) + strlen(gnunet_tld) + 2; - result = GNUNET_malloc(answer_len); - memset(result, 0, answer_len); - strcpy(result, rh->name); - strcpy(result+strlen(rh->name), "."); - strcpy(result+strlen(rh->name)+1, pseu); - strcpy(result+strlen(rh->name)+strlen(pseu)+1, gnunet_tld); - - GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, - "Sending shorten result %s\n", result); - - send_shorten_response(result, csh); - free_resolver_handle(rh); - GNUNET_free(result); - return; - } - - /** - * No PSEU found. Ask DHT if expired. - * Else contunue with next authority - */ - if (rh->status & (EXISTS | !EXPIRED)) - { - /** - * backtrack - */ - auth_chain = rh->authority_chain_head; - new_name = GNUNET_malloc(strlen(rh->name)+ - strlen(auth_chain->name) + 2); - memset(new_name, 0, strlen(rh->name)+ - strlen(auth_chain->name) + 2); - strcpy(new_name, rh->name); - strcpy(new_name+strlen(rh->name)+1, "."); - strcpy(new_name+strlen(rh->name)+2, auth_chain->name); - - GNUNET_free(rh->name); - rh->name = new_name; - GNUNET_CONTAINER_DLL_remove(rh->authority_chain_head, - rh->authority_chain_tail, - auth_chain); - - GNUNET_NAMESTORE_zone_to_name (namestore_handle, - &zone_hash, - &rh->authority_chain_head->zone, - &handle_shorten_zone_to_name, - rh); - return; - } - - /** - * Ask DHT - */ - rh->authority = rh->authority_chain_head->zone; - rh->proc = &handle_shorten_pseu_dht_result; - resolve_pseu_dht(rh); - -} - - - -/** - * Process result from namestore delegation lookup - * for shorten operation - * - * @param cls the client shorten handle - * @param rh the resolver handle - * @param rd_count number of results (0) - * @param rd data (NULL) - */ -void -handle_shorten_delegation_result(void* cls, - struct GNUNET_GNS_ResolverHandle *rh, - uint32_t rd_count, - const struct GNUNET_NAMESTORE_RecordData *rd) -{ - struct ClientShortenHandle* csh = (struct ClientShortenHandle*) cls; - struct AuthorityChain *auth_chain; - char* result; - size_t answer_len; - - /** - * At this point rh->name contains the part of the name - * that we do not have a PKEY in our namestore to resolve. - * The authority chain in the resolver handle is now - * useful to backtrack if needed - */ - - GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, - "PKEY resolved as far as possible in ns up to %s!\n", rh->name); - - if (GNUNET_CRYPTO_hash_cmp(&rh->authority_chain_head->zone, - &zone_hash) == 0) - { - /** - * This is our zone append .gnunet unless name is empty - * (it shouldn't be, usually FIXME what happens if we - * shorten to our zone to a "" record??) - **/ - - answer_len = strlen(rh->name) + strlen(gnunet_tld) + 2; - result = GNUNET_malloc(answer_len); - memset(result, 0, answer_len); - strcpy(result, rh->name); - strcpy(result+strlen(rh->name), "."); - strcpy(result+strlen(rh->name)+1, gnunet_tld); - - GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, - "Our zone: Sending name as shorten result %s\n", rh->name); - - send_shorten_response(result, csh); //FIXME +.gnunet! - free_resolver_handle(rh); - GNUNET_free(result); - return; - } - - auth_chain = rh->authority_chain_head; - /* backtrack authorities for pseu */ - GNUNET_NAMESTORE_zone_to_name (namestore_handle, - &zone_hash, //ours - &auth_chain->zone, - &handle_shorten_zone_to_name, - rh); - -} - -typedef void (*ShortenResponseProc) (void* cls, const char* name); - -/** - * Shorten a given name - * - * @param name the name to shorten - * @param csh the shorten handle of the request - */ -static void -shorten_name(char* name, struct ClientShortenHandle* csh) -{ - - struct GNUNET_GNS_ResolverHandle *rh; - - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Starting resolution for %s (type=%d)!\n", - name, GNUNET_GNS_RECORD_PKEY); - - rh = GNUNET_malloc(sizeof (struct GNUNET_GNS_ResolverHandle)); - rh->authority = zone_hash; - - rh->name = GNUNET_malloc(strlen(name) - - strlen(gnunet_tld) + 1); - memset(rh->name, 0, - strlen(name)-strlen(gnunet_tld) + 1); - memcpy(rh->name, name, - strlen(name)-strlen(gnunet_tld)); - - csh->name = GNUNET_malloc(strlen(name) - - strlen(gnunet_tld) + 1); - memset(csh->name, 0, - strlen(name)-strlen(gnunet_tld) + 1); - memcpy(csh->name, name, - strlen(name)-strlen(gnunet_tld)); - - rh->authority_name = GNUNET_malloc(sizeof(char)*MAX_DNS_LABEL_LENGTH); - - rh->authority_chain_head = GNUNET_malloc(sizeof(struct AuthorityChain)); - rh->authority_chain_tail = rh->authority_chain_head; - rh->authority_chain_head->zone = zone_hash; - rh->proc = &handle_shorten_delegation_result; - rh->proc_cls = (void*)csh; - - /* Start delegation resolution in our namestore */ - resolve_delegation_ns(rh); -} +/* END DHT ZONE PROPAGATION */ /** * Send shorten response back to client @@ -2306,11 +355,12 @@ shorten_name(char* name, struct ClientShortenHandle* csh) * @param csh the handle to the shorten request */ static void -send_shorten_response(const char* name, struct ClientShortenHandle *csh) +send_shorten_response(void* cls, const char* name) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message with %s\n", "SHORTEN_RESULT", name); struct GNUNET_GNS_ClientShortenResultMessage *rmsg; + struct ClientShortenHandle *csh = (struct ClientShortenHandle *)cls; if (name == NULL) { @@ -2354,6 +404,7 @@ static void handle_shorten(void *cls, size_t msg_size = 0; struct ClientShortenHandle *csh; + const char* name; if (ntohs (message->size) < sizeof (struct GNUNET_GNS_ClientShortenMessage)) { @@ -2380,8 +431,16 @@ static void handle_shorten(void *cls, csh->client = client; csh->unique_id = sh_msg->id; - shorten_name((char*)&sh_msg[1], csh); + name = (char*)&sh_msg[1]; + csh->name = GNUNET_malloc(strlen(name) + - strlen(GNUNET_GNS_TLD) + 1); + memset(csh->name, 0, + strlen(name)-strlen(GNUNET_GNS_TLD) + 1); + memcpy(csh->name, name, + strlen(name)-strlen(GNUNET_GNS_TLD)); + /* Start shortening */ + gns_resolver_shorten_name(zone_hash, name, &send_shorten_response, csh); } @@ -2392,11 +451,12 @@ static void handle_shorten(void *cls, * @param cah the handle to the get authority request */ static void -send_get_auth_response(const char* name, struct ClientGetAuthHandle *cah) +send_get_auth_response(void *cls, const char* name) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message with %s\n", "GET_AUTH_RESULT", name); struct GNUNET_GNS_ClientGetAuthResultMessage *rmsg; + struct ClientGetAuthHandle *cah = (struct ClientGetAuthHandle *)cls; if (name == NULL) { @@ -2429,124 +489,6 @@ send_get_auth_response(const char* name, struct ClientGetAuthHandle *cah) } -/** - * Process result from namestore delegation lookup - * for get authority operation - * - * @param cls the client get auth handle - * @param rh the resolver handle - * @param rd_count number of results (0) - * @param rd data (NULL) - */ -void -handle_get_auth_delegation_result(void* cls, - struct GNUNET_GNS_ResolverHandle *rh, - uint32_t rd_count, - const struct GNUNET_NAMESTORE_RecordData *rd) -{ - struct ClientGetAuthHandle* cah = (struct ClientGetAuthHandle*) cls; - struct AuthorityChain *auth_chain; - char* result; - size_t answer_len; - - /** - * At this point rh->name contains the part of the name - * that we do not have a PKEY in our namestore to resolve. - * The authority chain in the resolver handle is now - * useful to backtrack if needed - */ - - GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, - "PKEY resolved as far as possible in ns up to %s!\n", rh->name); - - if (is_canonical(rh->name)) - { - /** - * We successfully resolved the authority in the ns - * FIXME for our purposes this is fine - * but maybe we want to have an api that also looks - * into the dht (i.e. option in message) - **/ - if (strlen(rh->name) > strlen(cah->name)) - { - GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, - "Record name longer than original lookup name... odd!\n"); - //FIXME to sth here - } - - - answer_len = strlen(cah->name) - strlen(rh->name) + strlen(gnunet_tld) + 1; - result = GNUNET_malloc(answer_len); - memset(result, 0, answer_len); - strcpy(result, cah->name + strlen(rh->name) + 1); - strcpy(result+strlen(result), gnunet_tld); - - GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, - "Got authority result %s\n", result); - - send_get_auth_response(result, cah); - free_resolver_handle(rh); - GNUNET_free(result); - return; - } - - auth_chain = rh->authority_chain_head; - /* backtrack authorities for pseu */ - GNUNET_NAMESTORE_zone_to_name (namestore_handle, - &zone_hash, //ours - &auth_chain->zone, - &handle_shorten_zone_to_name, - rh); - -} - - -/** - * Get authority for a given name - * - * @param name the name to shorten - * @param csh the shorten handle of the request - */ -static void -get_authority(char* name, struct ClientGetAuthHandle* cah) -{ - - struct GNUNET_GNS_ResolverHandle *rh; - - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Starting authority resolution for %s (type=%d)!\n", - name, GNUNET_GNS_RECORD_PKEY); - - rh = GNUNET_malloc(sizeof (struct GNUNET_GNS_ResolverHandle)); - rh->authority = zone_hash; - - rh->name = GNUNET_malloc(strlen(name) - - strlen(gnunet_tld) + 1); - memset(rh->name, 0, - strlen(name)-strlen(gnunet_tld) + 1); - memcpy(rh->name, name, - strlen(name)-strlen(gnunet_tld)); - - cah->name = GNUNET_malloc(strlen(name) - - strlen(gnunet_tld) + 1); - memset(cah->name, 0, - strlen(name)-strlen(gnunet_tld) + 1); - memcpy(cah->name, name, - strlen(name)-strlen(gnunet_tld)); - - rh->authority_name = GNUNET_malloc(sizeof(char)*MAX_DNS_LABEL_LENGTH); - - rh->authority_chain_head = GNUNET_malloc(sizeof(struct AuthorityChain)); - rh->authority_chain_tail = rh->authority_chain_head; - rh->authority_chain_head->zone = zone_hash; - rh->proc = &handle_get_auth_delegation_result; - rh->proc_cls = (void*)cah; - - /* Start delegation resolution in our namestore */ - resolve_delegation_ns(rh); - -} - /** * Handle a get authority message from the api @@ -2563,6 +505,7 @@ static void handle_get_authority(void *cls, size_t msg_size = 0; struct ClientGetAuthHandle *cah; + const char* name; if (ntohs (message->size) < sizeof (struct GNUNET_GNS_ClientGetAuthMessage)) { @@ -2589,8 +532,16 @@ static void handle_get_authority(void *cls, cah->client = client; cah->unique_id = sh_msg->id; - get_authority((char*)&sh_msg[1], cah); + name = (char*)&sh_msg[1]; + cah->name = GNUNET_malloc(strlen(name) + - strlen(GNUNET_GNS_TLD) + 1); + memset(cah->name, 0, + strlen(name)-strlen(GNUNET_GNS_TLD) + 1); + memcpy(cah->name, name, + strlen(name)-strlen(GNUNET_GNS_TLD)); + /* Start delegation resolution in our namestore */ + gns_resolver_get_authority(zone_hash, name, &send_get_auth_response, cah); } @@ -2603,9 +554,9 @@ static void handle_get_authority(void *cls, * @param rd the record data */ static void -reply_to_client(void* cls, struct GNUNET_GNS_ResolverHandle *rh, - uint32_t rd_count, - const struct GNUNET_NAMESTORE_RecordData *rd) +send_lookup_response(void* cls, + uint32_t rd_count, + const struct GNUNET_NAMESTORE_RecordData *rd) { struct ClientLookupHandle* clh = (struct ClientLookupHandle*)cls; struct GNUNET_GNS_ClientLookupResultMessage *rmsg; @@ -2630,63 +581,12 @@ reply_to_client(void* cls, struct GNUNET_GNS_ResolverHandle *rh, GNUNET_NO); GNUNET_SERVER_receive_done (clh->client, GNUNET_OK); - GNUNET_free(rh->proc_cls); - free_resolver_handle(rh); GNUNET_free(rmsg); GNUNET_free(clh->name); GNUNET_free(clh); } -/** - * Lookup a given name - * - * @param name the name to looku[ - * @param clh the client lookup handle - */ -static void -lookup_name(char* name, struct ClientLookupHandle* clh) -{ - - struct GNUNET_GNS_ResolverHandle *rh; - struct RecordLookupHandle* rlh; - - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Starting resolution for %s (type=%d)!\n", - name, clh->type); - - rh = GNUNET_malloc(sizeof (struct GNUNET_GNS_ResolverHandle)); - rlh = GNUNET_malloc(sizeof(struct RecordLookupHandle)); - - rh->authority = zone_hash; - - rlh->record_type = clh->type; - rlh->name = clh->name; - rlh->proc = &reply_to_client; - rlh->proc_cls = clh; - - rh->proc_cls = rlh; - - rh->name = GNUNET_malloc(strlen(name) - - strlen(gnunet_tld) + 1); - memset(rh->name, 0, - strlen(name)-strlen(gnunet_tld) + 1); - memcpy(rh->name, name, - strlen(name)-strlen(gnunet_tld)); - - rh->authority_name = GNUNET_malloc(sizeof(char)*MAX_DNS_LABEL_LENGTH); - - rh->authority_chain_head = GNUNET_malloc(sizeof(struct AuthorityChain)); - rh->authority_chain_head->prev = NULL; - rh->authority_chain_head->next = NULL; - rh->authority_chain_tail = rh->authority_chain_head; - rh->authority_chain_head->zone = zone_hash; - - /* Start resolution in our zone */ - rh->proc = &process_delegation_ns; - resolve_delegation_ns(rh); -} - /** * Handle lookup requests from client @@ -2733,7 +633,8 @@ handle_lookup(void *cls, clh->unique_id = sh_msg->id; clh->type = ntohl(sh_msg->type); - lookup_name((char*)&sh_msg[1], clh); + gns_resolver_lookup_record(zone_hash, clh->type, (char*)&sh_msg[1], + &send_lookup_response, clh); } @@ -2778,24 +679,17 @@ run (void *cls, struct GNUNET_SERVER_Handle *server, GNUNET_free(keyfile); - dns_handle = NULL; if (GNUNET_YES == GNUNET_CONFIGURATION_get_value_yesno (c, "gns", "HIJACK_DNS")) { GNUNET_log(GNUNET_ERROR_TYPE_INFO, "DNS hijacking enabled... connecting to service.\n"); - /** - * Do gnunet dns init here - */ - dns_handle = GNUNET_DNS_connect(c, - GNUNET_DNS_FLAG_PRE_RESOLUTION, - &handle_dns_request, /* rh */ - NULL); /* Closure */ - if (NULL == dns_handle) + + if (gns_interceptor_init(zone_hash, c) == GNUNET_SYSERR) { GNUNET_log(GNUNET_ERROR_TYPE_ERROR, - "Failed to connect to the dnsservice!\n"); + "Failed to enable the dns interceptor!\n"); } } diff --git a/src/gns/gnunet-service-gns_interceptor.c b/src/gns/gnunet-service-gns_interceptor.c new file mode 100644 index 000000000..1a14eb96e --- /dev/null +++ b/src/gns/gnunet-service-gns_interceptor.c @@ -0,0 +1,327 @@ +/* + This file is part of GNUnet. + (C) 2009, 2010, 2011 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/gns_interceptor.c + * @brief GNUnet GNS interceptor logic + * @author Martin Schanzenbach + */ +#include "platform.h" +#include "gnunet_util_lib.h" +#include "gnunet_transport_service.h" +#include "gnunet_dns_service.h" +#include "gnunet_dnsparser_lib.h" +#include "gnunet-service-gns_resolver.h" +#include "gns.h" + +#define MAX_DNS_LABEL_LENGTH 63 + +/** + * Handle to a DNS intercepted + * reslution request + */ +struct InterceptLookupHandle +{ + /* the request handle to reply to */ + struct GNUNET_DNS_RequestHandle *request_handle; + + /* the dns parser packet received */ + struct GNUNET_DNSPARSER_Packet *packet; + + /* the query parsed from the packet */ + struct GNUNET_DNSPARSER_Query *query; +}; + + +/** + * Our handle to the DNS handler library + */ +struct GNUNET_DNS_Handle *dns_handle; + +/** + * The root zone for this interceptor + */ +static GNUNET_HashCode our_zone; + +/** + * Reply to dns request with the result from our lookup. + * + * @param cls the closure to the request (an InterceptLookupHandle) + * @param rh the request handle of the lookup + * @param rd_count the number of records to return + * @param rd the record data + */ +static void +reply_to_dns(void* cls, uint32_t rd_count, + const struct GNUNET_NAMESTORE_RecordData *rd) +{ + int i; + size_t len; + int ret; + char *buf; + struct InterceptLookupHandle* ilh = (struct InterceptLookupHandle*)cls; + struct GNUNET_DNSPARSER_Packet *packet = ilh->packet; + unsigned int num_answers = 0; + + + /** + * Put records in the DNS packet and modify it + * to a response + */ + for (i=0; i < rd_count; i++) + { + if (rd[i].record_type == ilh->query->type) + num_answers++; + } + + struct GNUNET_DNSPARSER_Record answer_records[num_answers]; + struct GNUNET_DNSPARSER_Record additional_records[rd_count-(num_answers)]; + packet->answers = answer_records; + packet->additional_records = additional_records; + + for (i=0; i < rd_count; i++) + { + GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, + "Adding type %d to DNS response\n", rd[i].record_type); + GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Name: %s\n", ilh->query->name); + GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Record %d/%d\n", i+1, rd_count); + GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Record len %d\n", rd[i].data_size); + + if (rd[i].record_type == ilh->query->type) + { + num_answers++; + answer_records[i].name = ilh->query->name; + answer_records[i].type = rd[i].record_type; + answer_records[i].data.raw.data_len = rd[i].data_size; + answer_records[i].data.raw.data = (char*)rd[i].data; + answer_records[i].expiration_time = rd[i].expiration; + answer_records[i].class = GNUNET_DNSPARSER_CLASS_INTERNET;//hmmn + } + else + { + additional_records[i].name = ilh->query->name; + additional_records[i].type = rd[i].record_type; + additional_records[i].data.raw.data_len = rd[i].data_size; + additional_records[i].data.raw.data = (char*)rd[i].data; + additional_records[i].expiration_time = rd[i].expiration; + additional_records[i].class = GNUNET_DNSPARSER_CLASS_INTERNET;//hmmn + } + } + + packet->num_answers = num_answers; + packet->num_additional_records = rd_count-(num_answers); + + packet->flags.authoritative_answer = 1; + + if (rd == NULL) + packet->flags.return_code = GNUNET_DNSPARSER_RETURN_CODE_NAME_ERROR; + else + packet->flags.return_code = GNUNET_DNSPARSER_RETURN_CODE_NO_ERROR; + + packet->flags.query_or_response = 1; + + + /** + * Reply to DNS + */ + GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, + "Building DNS response\n"); + ret = GNUNET_DNSPARSER_pack (packet, + 1024, /* FIXME magic from dns redirector */ + &buf, + &len); + GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, + "Built DNS response! (ret=%d,len=%d)\n", ret, len); + if (ret == GNUNET_OK) + { + GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, + "Answering DNS request\n"); + GNUNET_DNS_request_answer(ilh->request_handle, + len, + buf); + + GNUNET_free(buf); + GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Answered DNS request\n"); + } + else + { + GNUNET_log(GNUNET_ERROR_TYPE_ERROR, + "Error building DNS response! (ret=%d)", ret); + } + + packet->num_answers = 0; + packet->answers = NULL; + packet->num_additional_records = 0; + packet->additional_records = NULL; + GNUNET_DNSPARSER_free_packet(packet); + //FIXME free resolver handle in resp functions in resolver! + //GNUNET_free((struct RecordLookupHandle*)rh->proc_cls); + //free_resolver_handle(rh); + GNUNET_free(ilh); +} + + +/** + * Entry point for name resolution + * Setup a new query and try to resolve + * + * @param request the request handle of the DNS request from a client + * @param p the DNS query packet we received + * @param q the DNS query we received parsed from p + */ +static void +start_resolution_for_dns(struct GNUNET_DNS_RequestHandle *request, + struct GNUNET_DNSPARSER_Packet *p, + struct GNUNET_DNSPARSER_Query *q) +{ + struct InterceptLookupHandle* ilh; + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Starting resolution for %s (type=%d)!\n", + q->name, q->type); + + ilh = GNUNET_malloc(sizeof(struct InterceptLookupHandle)); + ilh->packet = p; + ilh->query = q; + ilh->request_handle = request; + + /* Start resolution in our zone */ + gns_resolver_lookup_record(our_zone, q->type, q->name, &reply_to_dns, ilh); +} + + + +/** + * The DNS request handler + * Called for every incoming DNS request. + * + * @param cls closure + * @param rh request handle to user for reply + * @param request_length number of bytes in request + * @param request udp payload of the DNS request + */ +static void +handle_dns_request(void *cls, + struct GNUNET_DNS_RequestHandle *rh, + size_t request_length, + const char *request) +{ + struct GNUNET_DNSPARSER_Packet *p; + int i; + char *tldoffset; + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Hijacked a DNS request...processing\n"); + p = GNUNET_DNSPARSER_parse (request, request_length); + + if (NULL == p) + { + GNUNET_log (GNUNET_ERROR_TYPE_WARNING, + "Received malformed DNS packet, leaving it untouched\n"); + GNUNET_DNS_request_forward (rh); + GNUNET_DNSPARSER_free_packet (p); + return; + } + + /** + * Check tld and decide if we or + * legacy dns is responsible + * + * FIXME now in theory there could be more than 1 query in the request + * but if this is case we get into trouble: + * either we query the GNS or the DNS. We cannot do both! + * So I suggest to either only allow a single query per request or + * only allow GNS or DNS requests. + * The way it is implemented here now is buggy and will lead to erratic + * behaviour (if multiple queries are present). + */ + if (p->num_queries == 0) + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "No Queries in DNS packet... forwarding\n"); + GNUNET_DNS_request_forward (rh); + GNUNET_DNSPARSER_free_packet(p); + return; + } + + if (p->num_queries > 1) + { + /* Note: We could also look for .gnunet */ + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + ">1 queriy in DNS packet... odd. We only process #1\n"); + } + + + /** + * Check for .gnunet + */ + tldoffset = p->queries[0].name + strlen(p->queries[0].name) - 1; + + for (i=0; iqueries[0].name); i++) + { + if (*(tldoffset-i) == '.') + break; + } + + if ((i==strlen(GNUNET_GNS_TLD)-1) + && (0 == strcmp(tldoffset-i, GNUNET_GNS_TLD))) + { + start_resolution_for_dns(rh, p, p->queries); + } + else + { + /** + * This request does not concern us. Forward to real DNS. + */ + GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, + "Request for %s is forwarded to DNS\n", p->queries[0].name); + GNUNET_DNS_request_forward (rh); + GNUNET_DNSPARSER_free_packet (p); + } + +} + + +int +gns_interceptor_init(GNUNET_HashCode zone, + const struct GNUNET_CONFIGURATION_Handle *c) +{ + GNUNET_log(GNUNET_ERROR_TYPE_INFO, + "DNS hijacking enabled... connecting to service.\n"); + + our_zone = zone; + /** + * Do gnunet dns init here + */ + dns_handle = GNUNET_DNS_connect(c, + GNUNET_DNS_FLAG_PRE_RESOLUTION, + &handle_dns_request, /* rh */ + NULL); /* Closure */ + if (NULL == dns_handle) + { + GNUNET_log(GNUNET_ERROR_TYPE_ERROR, + "Failed to connect to the dnsservice!\n"); + return GNUNET_SYSERR; + } + + return GNUNET_YES; +} + +/* end of gns_interceptor.c */ diff --git a/src/gns/gnunet-service-gns_interceptor.h b/src/gns/gnunet-service-gns_interceptor.h new file mode 100644 index 000000000..03b91856e --- /dev/null +++ b/src/gns/gnunet-service-gns_interceptor.h @@ -0,0 +1,18 @@ +#ifndef GNUNET_GNS_INTERCEPTOR_H +#define GNUNET_GNS_INTERCEPTOR_H + +/** + * Initialize dns interceptor + * + * @param zone the zone + * @param c the configuration + * @return GNUNET_YES on success GNUNET_SYSERR on error + */ +int +gns_interceptor_init(GNUNET_HashCode zone, + const struct GNUNET_CONFIGURATION_Handle *c); + +void +gns_interceptor_stop(void){}; + +#endif diff --git a/src/gns/gnunet-service-gns_resolver.c b/src/gns/gnunet-service-gns_resolver.c new file mode 100644 index 000000000..53fdcc463 --- /dev/null +++ b/src/gns/gnunet-service-gns_resolver.c @@ -0,0 +1,1712 @@ +/* + This file is part of GNUnet. + (C) 2009, 2010, 2011 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/gns_resolver.c + * @brief GNUnet GNS service + * @author Martin Schanzenbach + */ +#include "platform.h" +#include "gnunet_util_lib.h" +#include "gnunet_transport_service.h" +#include "gnunet_dns_service.h" +#include "gnunet_dht_service.h" +#include "gnunet_namestore_service.h" +#include "gnunet_dns_service.h" +#include "gnunet_dnsparser_lib.h" +#include "gnunet_gns_service.h" +#include "block_gns.h" +#include "gns.h" +#include "gnunet-service-gns_resolver.h" + +#define DHT_OPERATION_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 3) +#define DHT_LOOKUP_TIMEOUT DHT_OPERATION_TIMEOUT +#define DHT_GNS_REPLICATION_LEVEL 5 +#define MAX_DNS_LABEL_LENGTH 63 + + +/** + * Our handle to the namestore service + * FIXME maybe need a second handle for iteration + */ +struct GNUNET_NAMESTORE_Handle *namestore_handle; + +struct GNUNET_DHT_Handle *dht_handle; + +static void +connect_to_dht() +{ + //FIXME +} + +/** + * Helper function to free resolver handle + * + * @rh the handle to free + */ +static void +free_resolver_handle(struct ResolverHandle* rh) +{ + struct AuthorityChain *ac; + struct AuthorityChain *ac_next; + + if (NULL == rh) + return; + + GNUNET_free_non_null (rh->name); + GNUNET_free_non_null (rh->authority_name); + + ac = rh->authority_chain_head; + + while (NULL != ac) + { + ac_next = ac->next; + GNUNET_free_non_null (ac->name); + GNUNET_free(ac); + ac = ac_next; + } + GNUNET_free(rh); +} + + +/** + * Callback when record data is put into namestore + * + * @param cls the closure + * @param success GNUNET_OK on success + * @param emsg the error message. NULL if SUCCESS==GNUNET_OK + */ +void +on_namestore_record_put_result(void *cls, + int32_t success, + const char *emsg) +{ + if (GNUNET_NO == success) + { + GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "records already in namestore\n"); + return; + } + else if (GNUNET_YES == success) + { + GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, + "records successfully put in namestore\n"); + return; + } + + GNUNET_log(GNUNET_ERROR_TYPE_ERROR, + "Error putting records into namestore: %s\n", emsg); +} + + +/** + * Handle timeout for DHT requests + * + * @param cls the request handle as closure + * @param tc the task context + */ +static void +dht_lookup_timeout(void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) +{ + struct ResolverHandle *rh = cls; + + GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, + "dht lookup for query %s timed out.\n", + rh->name); + + GNUNET_DHT_get_stop (rh->get_handle); + rh->proc(rh->proc_cls, rh, 0, NULL); +} + + +/** + * Function called when we get a result from the dht + * for our record query + * + * @param cls the request handle + * @param exp lifetime + * @param key the key the record was stored under + * @param get_path get path + * @param get_path_length get path length + * @param put_path put path + * @param put_path_length put path length + * @param type the block type + * @param size the size of the record + * @param data the record data + */ +static void +process_record_result_dht(void* cls, + struct GNUNET_TIME_Absolute exp, + const GNUNET_HashCode * key, + const struct GNUNET_PeerIdentity *get_path, + unsigned int get_path_length, + const struct GNUNET_PeerIdentity *put_path, + unsigned int put_path_length, + enum GNUNET_BLOCK_Type type, + size_t size, const void *data) +{ + struct ResolverHandle *rh; + struct RecordLookupHandle *rlh; + struct GNSNameRecordBlock *nrb; + uint32_t num_records; + char* name = NULL; + char* rd_data = (char*)data; + int i; + int rd_size; + + GNUNET_HashCode zone, name_hash; + GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "got dht result (size=%d)\n", size); + + if (data == NULL) + return; + + //FIXME maybe check expiration here, check block type + + rh = (struct ResolverHandle *)cls; + rlh = (struct RecordLookupHandle *) rh->proc_cls; + nrb = (struct GNSNameRecordBlock*)data; + + /* stop lookup and timeout task */ + GNUNET_DHT_get_stop (rh->get_handle); + GNUNET_SCHEDULER_cancel(rh->dht_timeout_task); + + rh->get_handle = NULL; + name = (char*)&nrb[1]; + num_records = ntohl(nrb->rd_count); + { + struct GNUNET_NAMESTORE_RecordData rd[num_records]; + + rd_data += strlen(name) + 1 + sizeof(struct GNSNameRecordBlock); + rd_size = size - strlen(name) - 1 - sizeof(struct GNSNameRecordBlock); + + if (GNUNET_SYSERR == GNUNET_NAMESTORE_records_deserialize (rd_size, + rd_data, + num_records, + rd)) + { + GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Error deserializing data!\n"); + return; + } + + for (i=0; iname); + GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, + "Got type: %d\n", + rd[i].record_type); + GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, + "Got data length: %d\n", rd[i].data_size); + GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, + "Got flag %d\n", rd[i].flags); + + if ((strcmp(name, rh->name) == 0) && + (rd[i].record_type == rlh->record_type)) + { + rh->answered++; + } + + } + + GNUNET_CRYPTO_hash(name, strlen(name), &name_hash); + GNUNET_CRYPTO_hash_xor(key, &name_hash, &zone); + + /** + * FIXME check pubkey against existing key in namestore? + * https://gnunet.org/bugs/view.php?id=2179 + */ + + /* Save to namestore */ + GNUNET_NAMESTORE_record_put (namestore_handle, + &nrb->public_key, + name, + exp, + num_records, + rd, + &nrb->signature, + &on_namestore_record_put_result, //cont + NULL); //cls + + if (rh->answered) + rh->proc(rh->proc_cls, rh, num_records, rd); + else + rh->proc(rh->proc_cls, rh, 0, NULL); + } + +} + + +/** + * Start DHT lookup for a (name -> query->record_type) record in + * rh->authority's zone + * + * @param rh the pending gns query context + */ +static void +resolve_record_dht(struct ResolverHandle *rh) +{ + uint32_t xquery; + GNUNET_HashCode name_hash; + GNUNET_HashCode lookup_key; + struct GNUNET_CRYPTO_HashAsciiEncoded lookup_key_string; + struct RecordLookupHandle *rlh = (struct RecordLookupHandle *)rh->proc_cls; + + GNUNET_CRYPTO_hash(rh->name, strlen(rh->name), &name_hash); + GNUNET_CRYPTO_hash_xor(&name_hash, &rh->authority, &lookup_key); + GNUNET_CRYPTO_hash_to_enc (&lookup_key, &lookup_key_string); + + GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, + "starting dht lookup for %s with key: %s\n", + rh->name, (char*)&lookup_key_string); + + rh->dht_timeout_task = GNUNET_SCHEDULER_add_delayed(DHT_LOOKUP_TIMEOUT, + &dht_lookup_timeout, rh); + + xquery = htonl(rlh->record_type); + rh->get_handle = GNUNET_DHT_get_start(dht_handle, + DHT_OPERATION_TIMEOUT, + GNUNET_BLOCK_TYPE_GNS_NAMERECORD, + &lookup_key, + DHT_GNS_REPLICATION_LEVEL, + GNUNET_DHT_RO_NONE, + &xquery, + sizeof(xquery), + &process_record_result_dht, + rh); + +} + + +/** + * Namestore calls this function if we have record for this name. + * (or with rd_count=0 to indicate no matches) + * + * @param cls the pending query + * @param key the key of the zone we did the lookup + * @param expiration expiration date of the namestore entry + * @param name the name for which we need an authority + * @param rd_count the number of records with 'name' + * @param rd the record data + * @param signature the signature of the authority for the record data + */ +static void +process_record_result_ns(void* cls, + const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *key, + struct GNUNET_TIME_Absolute expiration, + const char *name, unsigned int rd_count, + const struct GNUNET_NAMESTORE_RecordData *rd, + const struct GNUNET_CRYPTO_RsaSignature *signature) +{ + struct ResolverHandle *rh; + struct RecordLookupHandle *rlh; + struct GNUNET_TIME_Relative remaining_time; + GNUNET_HashCode zone; + + rh = (struct ResolverHandle *) cls; + rlh = (struct RecordLookupHandle *)rh->proc_cls; + GNUNET_CRYPTO_hash(key, + sizeof(struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded), + &zone); + remaining_time = GNUNET_TIME_absolute_get_remaining (expiration); + + rh->status = 0; + + if (name != NULL) + { + rh->status |= EXISTS; + } + + if (remaining_time.rel_value == 0) + { + rh->status |= EXPIRED; + } + + if (rd_count == 0) + { + /** + * Lookup terminated and no results + */ + GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, + "Namestore lookup for %s terminated without results\n", name); + + GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, + "Record %s unknown in namestore\n", + rh->name); + /** + * Our zone and no result? Cannot resolve TT + */ + rh->proc(rh->proc_cls, rh, 0, NULL); + return; + + } + else + { + + GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, + "Processing additional result %s from namestore\n", name); + int i; + for (i=0; irecord_type) + continue; + + if ((GNUNET_TIME_absolute_get_remaining (rd[i].expiration)).rel_value + == 0) + { + GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, + "This record is expired. Skipping\n"); + continue; + } + + rh->answered++; + + } + + /** + * no answers found + */ + if (rh->answered == 0) + { + GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, + "No answers found. This is odd!\n"); + rh->proc(rh->proc_cls, rh, 0, NULL); + return; + } + + GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Found %d answer(s) to query!\n", + rh->answered); + + rh->proc(rh->proc_cls, rh, rd_count, rd); + } +} + + +/** + * The final phase of resolution. + * rh->name is a name that is canonical and we do not have a delegation. + * Query namestore for this record + * + * @param rh the pending lookup + */ +static void +resolve_record_ns(struct ResolverHandle *rh) +{ + struct RecordLookupHandle *rlh = (struct RecordLookupHandle *)rh->proc_cls; + + /** + * Try to resolve this record in our namestore. + * The name to resolve is now in rh->authority_name + * since we tried to resolve it to an authority + * and failed. + **/ + GNUNET_NAMESTORE_lookup_record(namestore_handle, + &rh->authority, + rh->name, + rlh->record_type, + &process_record_result_ns, + rh); +} + + +/** + * Handle timeout for DHT requests + * + * @param cls the request handle as closure + * @param tc the task context + */ +static void +dht_authority_lookup_timeout(void *cls, + const struct GNUNET_SCHEDULER_TaskContext *tc) +{ + struct ResolverHandle *rh = cls; + + GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, + "dht lookup for query %s timed out.\n", + rh->name); + + GNUNET_DHT_get_stop (rh->get_handle); + if (strcmp(rh->name, "") == 0) + { + /* + * promote authority back to name and try to resolve record + */ + strcpy(rh->name, rh->authority_name); + } + rh->proc(rh->proc_cls, rh, 0, NULL); +} + +/* Prototype */ +static void resolve_delegation_dht(struct ResolverHandle *rh); + +/** + * Function called when we get a result from the dht + * for our query. Recursively tries to resolve authorities + * for name in DHT. + * + * @param cls the request handle + * @param exp lifetime + * @param key the key the record was stored under + * @param get_path get path + * @param get_path_length get path length + * @param put_path put path + * @param put_path_length put path length + * @param type the block type + * @param size the size of the record + * @param data the record data + */ +static void +process_delegation_result_dht(void* cls, + struct GNUNET_TIME_Absolute exp, + const GNUNET_HashCode * key, + const struct GNUNET_PeerIdentity *get_path, + unsigned int get_path_length, + const struct GNUNET_PeerIdentity *put_path, + unsigned int put_path_length, + enum GNUNET_BLOCK_Type type, + size_t size, const void *data) +{ + struct ResolverHandle *rh; + struct GNSNameRecordBlock *nrb; + uint32_t num_records; + char* name = NULL; + char* rd_data = (char*) data; + int i; + int rd_size; + GNUNET_HashCode zone, name_hash; + + GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Got DHT result\n"); + + if (data == NULL) + return; + + //FIXME check expiration? + + rh = (struct ResolverHandle *)cls; + nrb = (struct GNSNameRecordBlock*)data; + + /* stop dht lookup and timeout task */ + GNUNET_DHT_get_stop (rh->get_handle); + GNUNET_SCHEDULER_cancel(rh->dht_timeout_task); + + rh->get_handle = NULL; + num_records = ntohl(nrb->rd_count); + name = (char*)&nrb[1]; + { + struct GNUNET_NAMESTORE_RecordData rd[num_records]; + + rd_data += strlen(name) + 1 + sizeof(struct GNSNameRecordBlock); + rd_size = size - strlen(name) - 1 - sizeof(struct GNSNameRecordBlock); + + if (GNUNET_SYSERR == GNUNET_NAMESTORE_records_deserialize (rd_size, + rd_data, + num_records, + rd)) + { + GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Error deserializing data!\n"); + return; + } + + GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, + "Got name: %s (wanted %s)\n", name, rh->authority_name); + for (i=0; iauthority_name); + GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, + "Got type: %d (wanted %d)\n", + rd[i].record_type, GNUNET_GNS_RECORD_PKEY); + GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, + "Got data length: %d\n", rd[i].data_size); + GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, + "Got flag %d\n", rd[i].flags); + + if ((strcmp(name, rh->authority_name) == 0) && + (rd[i].record_type == GNUNET_GNS_RECORD_PKEY)) + { + GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Authority found in DHT\n"); + rh->answered = 1; + memcpy(&rh->authority, rd[i].data, sizeof(GNUNET_HashCode)); + struct AuthorityChain *auth = + GNUNET_malloc(sizeof(struct AuthorityChain)); + auth->zone = rh->authority; + auth->name = GNUNET_malloc(strlen(rh->authority_name)+1); + 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); + } + + } + + + GNUNET_CRYPTO_hash(name, strlen(name), &name_hash); + GNUNET_CRYPTO_hash_xor(key, &name_hash, &zone); + + /* Save to namestore */ + if (0 != GNUNET_CRYPTO_hash_cmp(&rh->authority_chain_tail->zone, &zone)) + { + GNUNET_NAMESTORE_record_put (namestore_handle, + &nrb->public_key, + name, + exp, + num_records, + rd, + &nrb->signature, + &on_namestore_record_put_result, //cont + NULL); //cls + } + } + + if (rh->answered) + { + rh->answered = 0; + /** + * delegate + * FIXME in this case. should we ask namestore again? + */ + if (strcmp(rh->name, "") == 0) + rh->proc(rh->proc_cls, rh, 0, NULL); + else + resolve_delegation_dht(rh); + return; + } + + /** + * should never get here unless false dht key/put + * block plugin should handle this + **/ + GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "DHT authority lookup error!\n"); + GNUNET_break(0); +} + + +/** + * Process DHT lookup result for record. + * + * @param cls the closure + * @param rh resolver handle + * @param rd_count number of results (always 0) + * @param rd record data (always NULL) + */ +static void +handle_record_dht(void* cls, struct ResolverHandle *rh, + unsigned int rd_count, + const struct GNUNET_NAMESTORE_RecordData *rd) +{ + struct RecordLookupHandle* rlh; + rlh = (struct RecordLookupHandle*)cls; + if (rd_count == 0) + { + GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, + "No records for %s found in DHT. Aborting\n", + rh->name); + /* give up, cannot resolve */ + rlh->proc(rlh->proc_cls, 0, NULL); + return; + } + + /* results found yay */ + GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, + "Record resolved from namestore!"); + rlh->proc(rlh->proc_cls, rd_count, rd); + +} + + +/** + * Process namestore lookup result for record. + * + * @param cls the closure + * @param rh resolver handle + * @param rd_count number of results (always 0) + * @param rd record data (always NULL) + */ +static void +handle_record_ns(void* cls, struct ResolverHandle *rh, + unsigned int rd_count, + const struct GNUNET_NAMESTORE_RecordData *rd) +{ + struct RecordLookupHandle* rlh; + rlh = (struct RecordLookupHandle*) cls; + if (rd_count == 0) + { + /* ns entry expired. try dht */ + if (rh->status & (EXPIRED | !EXISTS)) + { + rh->proc = &handle_record_dht; + resolve_record_dht(rh); + return; + } + /* give up, cannot resolve */ + rlh->proc(rlh->proc_cls, 0, NULL); + return; + } + + /* results found yay */ + GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, + "Record resolved from namestore!"); + rlh->proc(rlh->proc_cls, rd_count, rd); + +} + + +/** + * Determine if this name is canonical. + * i.e. + * a.b.gnunet = not canonical + * a = canonical + * + * @param name the name to test + * @return 1 if canonical + */ +static int +is_canonical(char* name) +{ + uint32_t len = strlen(name); + int i; + + for (i=0; i 0; len--) + { + if (*(name+len) == '.') + break; + } + + //Was canonical? + if (len == 0) + return; + + name[len] = '\0'; + + strcpy(dest, (name+len+1)); +} + +/** + * DHT resolution for delegation finished. Processing result. + * + * @param cls the closure + * @param rh resolver handle + * @param rd_count number of results (always 0) + * @param rd record data (always NULL) + */ +static void +handle_delegation_dht(void* cls, struct ResolverHandle *rh, + unsigned int rd_count, + const struct GNUNET_NAMESTORE_RecordData *rd) +{ + struct RecordLookupHandle* rlh; + rlh = (struct RecordLookupHandle*) cls; + + if (strcmp(rh->name, "") == 0) + { + /* We resolved full name for delegation. resolving record */ + GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, + "Resolved full name for delegation via DHT. resolving record '' in ns\n"); + rh->proc = &handle_record_ns; + resolve_record_ns(rh); + return; + } + + /** + * we still have some left + **/ + if (is_canonical(rh->name)) + { + GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, + "Resolving canonical record %s in ns\n", rh->name); + rh->proc = &handle_record_ns; + resolve_record_ns(rh); + return; + } + /* give up, cannot resolve */ + GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, + "Cannot fully resolve delegation for %s via DHT!\n", + rh->name); + rlh->proc(rlh->proc_cls, 0, NULL); +} + + +/** + * Start DHT lookup for a name -> PKEY (compare NS) record in + * rh->authority's zone + * + * @param rh the pending gns query + * @param name the name of the PKEY record + */ +static void +resolve_delegation_dht(struct ResolverHandle *rh) +{ + uint32_t xquery; + GNUNET_HashCode name_hash; + GNUNET_HashCode lookup_key; + + GNUNET_CRYPTO_hash(rh->authority_name, + strlen(rh->authority_name), + &name_hash); + GNUNET_CRYPTO_hash_xor(&name_hash, &rh->authority, &lookup_key); + + rh->dht_timeout_task = GNUNET_SCHEDULER_add_delayed (DHT_LOOKUP_TIMEOUT, + &dht_authority_lookup_timeout, + rh); + + xquery = htonl(GNUNET_GNS_RECORD_PKEY); + + rh->get_handle = GNUNET_DHT_get_start(dht_handle, + DHT_OPERATION_TIMEOUT, + GNUNET_BLOCK_TYPE_GNS_NAMERECORD, + &lookup_key, + DHT_GNS_REPLICATION_LEVEL, + GNUNET_DHT_RO_NONE, + &xquery, + sizeof(xquery), + &process_delegation_result_dht, + rh); + +} + + +/** + * Namestore resolution for delegation finished. Processing result. + * + * @param cls the closure + * @param rh resolver handle + * @param rd_count number of results (always 0) + * @param rd record data (always NULL) + */ +static void +handle_delegation_ns(void* cls, struct ResolverHandle *rh, + unsigned int rd_count, + const struct GNUNET_NAMESTORE_RecordData *rd) +{ + struct RecordLookupHandle* rlh; + rlh = (struct RecordLookupHandle*) cls; + + if (strcmp(rh->name, "") == 0) + { + /* We resolved full name for delegation. resolving record */ + GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, + "Resolved full name for delegation. resolving record ''\n"); + rh->proc = &handle_record_ns; + resolve_record_ns(rh); + return; + } + + /** + * we still have some left + * check if ns entry is fresh + **/ + if (rh->status & (EXISTS | !EXPIRED)) + { + if (is_canonical(rh->name)) + { + GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, + "Resolving canonical record %s\n", rh->name); + rh->proc = &handle_record_ns; + resolve_record_ns(rh); + } + else + { + /* give up, cannot resolve */ + GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, + "Cannot fully resolve delegation for %s!\n", + rh->name); + rlh->proc(rlh->proc_cls, 0, NULL); + } + return; + } + + GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, + "Trying to resolve delegation for %s via DHT\n", + rh->name); + rh->proc = &handle_delegation_dht; + resolve_delegation_dht(rh); +} + +//Prototype +static void resolve_delegation_ns(struct ResolverHandle *rh); + + +/** + * This is a callback function that should give us only PKEY + * records. Used to query the namestore for the authority (PKEY) + * for 'name'. It will recursively try to resolve the + * authority for a given name from the namestore. + * + * @param cls the pending query + * @param key the key of the zone we did the lookup + * @param expiration expiration date of the record data set in the namestore + * @param name the name for which we need an authority + * @param rd_count the number of records with 'name' + * @param rd the record data + * @param signature the signature of the authority for the record data + */ +static void +process_delegation_result_ns(void* cls, + const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *key, + struct GNUNET_TIME_Absolute expiration, + const char *name, + unsigned int rd_count, + const struct GNUNET_NAMESTORE_RecordData *rd, + const struct GNUNET_CRYPTO_RsaSignature *signature) +{ + struct ResolverHandle *rh; + struct GNUNET_TIME_Relative remaining_time; + GNUNET_HashCode zone; + char* new_name; + + GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Got %d records from authority lookup\n", + rd_count); + + rh = (struct ResolverHandle *)cls; + GNUNET_CRYPTO_hash(key, + sizeof(struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded), + &zone); + remaining_time = GNUNET_TIME_absolute_get_remaining (expiration); + + rh->status = 0; + + if (name != NULL) + { + rh->status |= EXISTS; + } + + if (remaining_time.rel_value == 0) + { + rh->status |= EXPIRED; + } + + /** + * No authority found in namestore. + */ + if (rd_count == 0) + { + /** + * We did not find an authority in the namestore + */ + + /** + * No PKEY in zone. + * Promote this authority back to a name maybe it is + * our record. + */ + if (strcmp(rh->name, "") == 0) + { + /* simply promote back */ + GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, + "Promoting %s back to name\n", rh->authority_name); + strcpy(rh->name, rh->authority_name); + } + else + { + /* add back to existing name */ + GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, + "Adding %s back to %s\n", + rh->authority_name, rh->name); + new_name = GNUNET_malloc(strlen(rh->name) + + strlen(rh->authority_name) + 2); + memset(new_name, 0, strlen(rh->name) + strlen(rh->authority_name) + 2); + strcpy(new_name, rh->name); + strcpy(new_name+strlen(new_name)+1, "."); + strcpy(new_name+strlen(new_name)+2, rh->authority_name); + GNUNET_free(rh->name); + rh->name = new_name; + } + rh->proc(rh->proc_cls, rh, 0, NULL); + return; + } + + //Note only 1 pkey should have been returned.. anything else would be strange + /** + * We found an authority that may be able to help us + * move on with query + */ + int i; + for (i=0; iauthority_chain_head->fresh = 0; + rh->proc(rh->proc_cls, rh, 0, NULL); + return; + } + + continue; + } + + /** + * Resolve rest of query with new authority + */ + GNUNET_assert(rd[i].record_type == GNUNET_GNS_RECORD_PKEY); + memcpy(&rh->authority, rd[i].data, sizeof(GNUNET_HashCode)); + struct AuthorityChain *auth = GNUNET_malloc(sizeof(struct AuthorityChain)); + auth->zone = rh->authority; + auth->name = GNUNET_malloc(strlen(rh->authority_name)+1); + 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); + + /** + * We are done with PKEY resolution if name is empty + * else resolve again with new authority + */ + if (strcmp(rh->name, "") == 0) + rh->proc(rh->proc_cls, rh, 0, NULL); + else + resolve_delegation_ns(rh); + return; + } + + /** + * no answers found + */ + GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, + "Authority lookup successful but no PKEY... never get here\n"); + rh->proc(rh->proc_cls, rh, 0, NULL); +} + + +/** + * Resolve the delegation chain for the request in our namestore + * + * @param rh the resolver handle + */ +static void +resolve_delegation_ns(struct ResolverHandle *rh) +{ + GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, + "Resolving delegation for %s\n", rh->name); + pop_tld(rh->name, rh->authority_name); + GNUNET_NAMESTORE_lookup_record(namestore_handle, + &rh->authority, + rh->authority_name, + GNUNET_GNS_RECORD_PKEY, + &process_delegation_result_ns, + rh); + +} + + +/** + * Lookup of a record in a specific zone + * calls lookup result processor on result + * + * @param zone the root zone + * @param record_type the record type to look up + * @param proc the processor to call + * @param cls the closure to pass to proc + */ +void +gns_resolver_lookup_record(GNUNET_HashCode zone, + uint32_t record_type, + const char* name, + RecordLookupProcessor proc, + void* cls) +{ + struct ResolverHandle *rh; + struct RecordLookupHandle* rlh; + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Starting resolution for %s (type=%d)!\n", + name, record_type); + + rlh = GNUNET_malloc(sizeof(struct RecordLookupHandle)); + rh = GNUNET_malloc(sizeof (struct ResolverHandle)); + + rh->authority = zone; + rh->proc_cls = rlh; + rh->name = GNUNET_malloc(strlen(name) + - strlen(GNUNET_GNS_TLD)); + memset(rh->name, 0, + strlen(name)-strlen(GNUNET_GNS_TLD)); + memcpy(rh->name, name, + strlen(name)-strlen(GNUNET_GNS_TLD) - 1); + rh->authority_name = GNUNET_malloc(sizeof(char)*MAX_DNS_LABEL_LENGTH); + rh->authority_chain_head = GNUNET_malloc(sizeof(struct AuthorityChain)); + rh->authority_chain_head->prev = NULL; + rh->authority_chain_head->next = NULL; + rh->authority_chain_tail = rh->authority_chain_head; + rh->authority_chain_head->zone = zone; + + rlh->record_type = record_type; + rlh->name = (char*)name; //FIXME + rlh->proc = proc; + rlh->proc_cls = cls; + + rh->proc = &handle_delegation_ns; + resolve_delegation_ns(rh); +} + +/******** END Record Resolver ***********/ + + +static void +process_pseu_result_ns_shorten(void *cls, + const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *zone_key, + struct GNUNET_TIME_Absolute expire, + const char *name, + unsigned int rd_len, + const struct GNUNET_NAMESTORE_RecordData *rd, + const struct GNUNET_CRYPTO_RsaSignature *signature) +{ + struct ResolverHandle *rh = + (struct ResolverHandle *)cls; + struct GNUNET_TIME_Relative remaining_time; + + GNUNET_TIME_absolute_get_remaining (expire); + rh->status = 0; + + if (name != NULL) + { + rh->status |= EXISTS; + } + + if (remaining_time.rel_value == 0) + { + rh->status |= EXPIRED; + } + + rh->proc(rh->proc_cls, rh, rd_len, rd); +} + + +/** + * Function called when we get a result from the dht + * for our record query + * + * @param cls the request handle + * @param exp lifetime + * @param key the key the record was stored under + * @param get_path get path + * @param get_path_length get path length + * @param put_path put path + * @param put_path_length put path length + * @param type the block type + * @param size the size of the record + * @param data the record data + */ +static void +process_pseu_dht_result(void* cls, + struct GNUNET_TIME_Absolute exp, + const GNUNET_HashCode * key, + const struct GNUNET_PeerIdentity *get_path, + unsigned int get_path_length, + const struct GNUNET_PeerIdentity *put_path, + unsigned int put_path_length, + enum GNUNET_BLOCK_Type type, + size_t size, const void *data) +{ + struct ResolverHandle *rh; + struct RecordLookupHandle *rlh; + struct GNSNameRecordBlock *nrb; + uint32_t num_records; + char* name = NULL; + char* rd_data = (char*)data; + int i; + int rd_size; + + GNUNET_HashCode zone, name_hash; + GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "got PSEU dht result (size=%d)\n", size); + + if (data == NULL) + return; + + //FIXME maybe check expiration here, check block type + + rh = (struct ResolverHandle *)cls; + rlh = (struct RecordLookupHandle *) rh->proc_cls; + nrb = (struct GNSNameRecordBlock*)data; + + /* stop lookup and timeout task */ + GNUNET_DHT_get_stop (rh->get_handle); + GNUNET_SCHEDULER_cancel(rh->dht_timeout_task); + + rh->get_handle = NULL; + name = (char*)&nrb[1]; + num_records = ntohl(nrb->rd_count); + { + struct GNUNET_NAMESTORE_RecordData rd[num_records]; + + rd_data += strlen(name) + 1 + sizeof(struct GNSNameRecordBlock); + rd_size = size - strlen(name) - 1 - sizeof(struct GNSNameRecordBlock); + + if (GNUNET_SYSERR == GNUNET_NAMESTORE_records_deserialize (rd_size, + rd_data, + num_records, + rd)) + { + GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Error deserializing data!\n"); + return; + } + + for (i=0; iname); + GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, + "Got type: %d\n", + rd[i].record_type); + GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, + "Got data length: %d\n", rd[i].data_size); + GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, + "Got flag %d\n", rd[i].flags); + + if ((strcmp(name, "+") == 0) && + (rd[i].record_type == GNUNET_GNS_RECORD_PSEU)) + { + rh->answered++; + } + + } + + GNUNET_CRYPTO_hash(name, strlen(name), &name_hash); + GNUNET_CRYPTO_hash_xor(key, &name_hash, &zone); + + /** + * FIXME check pubkey against existing key in namestore? + * https://gnunet.org/bugs/view.php?id=2179 + */ + + /* Save to namestore */ + GNUNET_NAMESTORE_record_put (namestore_handle, + &nrb->public_key, + name, + exp, + num_records, + rd, + &nrb->signature, + &on_namestore_record_put_result, //cont + NULL); //cls + + if (rh->answered) + rh->proc(rh->proc_cls, rh, num_records, rd); + else + rh->proc(rh->proc_cls, rh, 0, NULL); + } + +} + + +/** + * Start DHT lookup for a PSEUdonym record in + * rh->authority's zone + * + * @param rh the pending gns query + */ +static void +resolve_pseu_dht(struct ResolverHandle *rh) +{ + uint32_t xquery; + GNUNET_HashCode name_hash; + GNUNET_HashCode lookup_key; + + GNUNET_CRYPTO_hash("+", + strlen("+"), + &name_hash); + + GNUNET_CRYPTO_hash_xor(&name_hash, &rh->authority, &lookup_key); + + rh->dht_timeout_task = GNUNET_SCHEDULER_add_delayed (DHT_LOOKUP_TIMEOUT, + &dht_lookup_timeout, + rh); + + xquery = htonl(GNUNET_GNS_RECORD_PSEU); + + rh->get_handle = GNUNET_DHT_get_start(dht_handle, + DHT_OPERATION_TIMEOUT, + GNUNET_BLOCK_TYPE_GNS_NAMERECORD, + &lookup_key, + DHT_GNS_REPLICATION_LEVEL, + GNUNET_DHT_RO_NONE, + &xquery, + sizeof(xquery), + &process_pseu_dht_result, + rh); + +} + +//Prototype +static void +handle_shorten_pseu_ns_result(void* cls, + struct ResolverHandle *rh, + uint32_t rd_count, + const struct GNUNET_NAMESTORE_RecordData *rd); + +static void +process_zone_to_name_shorten(void *cls, + const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *zone_key, + struct GNUNET_TIME_Absolute expire, + const char *name, + unsigned int rd_len, + const struct GNUNET_NAMESTORE_RecordData *rd, + const struct GNUNET_CRYPTO_RsaSignature *signature) +{ + struct ResolverHandle *rh = + (struct ResolverHandle *)cls; + struct NameShortenHandle* nsh = (struct NameShortenHandle*)rh->proc_cls; + struct AuthorityChain *next_authority; + + char* result; + char* next_authority_name; + size_t answer_len; + + /* we found a match in our own zone */ + if (rd_len != 0) + { + GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, + "result strlen %d\n", strlen(name)); + answer_len = strlen(rh->name) + strlen(name) + strlen(GNUNET_GNS_TLD) + 3; + result = GNUNET_malloc(answer_len); + memset(result, 0, answer_len); + strcpy(result, rh->name); + strcpy(result+strlen(rh->name), "."); + strcpy(result+strlen(rh->name)+1, name); + strcpy(result+strlen(rh->name)+strlen(name)+1, "."); + strcpy(result+strlen(rh->name)+strlen(name)+2, GNUNET_GNS_TLD); + + GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, + "Sending shorten result %s\n", result); + + nsh->proc(nsh->proc_cls, result); + free_resolver_handle(rh); + GNUNET_free(result); + } + else if (GNUNET_CRYPTO_hash_cmp(&rh->authority_chain_head->zone, + &rh->authority_chain_tail->zone)) + { + /* our zone, just append .gnunet */ + answer_len = strlen(rh->name) + strlen(GNUNET_GNS_TLD) + 2; + result = GNUNET_malloc(answer_len); + memset(result, 0, answer_len); + strcpy(result, rh->name); + strcpy(result+strlen(rh->name), "."); + strcpy(result+strlen(rh->name)+1, GNUNET_GNS_TLD); + + GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, + "Our zone: Sending name as shorten result %s\n", rh->name); + + nsh->proc(nsh->proc_cls, result); //FIXME +.gnunet! + free_resolver_handle(rh); + GNUNET_free(result); + } + else + { + /** + * No PSEU found. + * continue with next authority + */ + next_authority = rh->authority_chain_head; + next_authority_name = GNUNET_malloc(strlen(rh->name)+ + strlen(next_authority->name) + 2); + memset(next_authority_name, 0, strlen(rh->name)+ + strlen(next_authority->name) + 2); + strcpy(next_authority_name, rh->name); + strcpy(next_authority_name+strlen(rh->name)+1, "."); + strcpy(next_authority_name+strlen(rh->name)+2, next_authority->name); + + GNUNET_free(rh->name); + rh->name = next_authority_name; + GNUNET_CONTAINER_DLL_remove(rh->authority_chain_head, + rh->authority_chain_tail, + next_authority); + + GNUNET_NAMESTORE_zone_to_name (namestore_handle, + &rh->authority_chain_tail->zone, + &rh->authority_chain_head->zone, + &process_zone_to_name_shorten, + rh); + } +} + + +/** + * Process result from namestore PSEU lookup + * for shorten operation + * + * @param cls the client shorten handle + * @param rh the resolver handle + * @param rd_count number of results (0 if none found) + * @param rd data (NULL if none found) + */ +static void +handle_pseu_ns_result_shorten(void* cls, + struct ResolverHandle *rh, + uint32_t rd_len, + const struct GNUNET_NAMESTORE_RecordData *rd) +{ + struct NameShortenHandle* nsh = (struct NameShortenHandle*) cls; + struct AuthorityChain *next_authority; + char* pseu; + char* result; + char* new_name; + size_t answer_len; + int i; + + /** + * PSEU found + */ + if (rd_len != 0) + { + for (i=0; i < rd_len; i++) + { + if (rd[i].record_type == GNUNET_GNS_RECORD_PSEU) + { + GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, + "Found PSEU %s len %d\n", (char*) rd[i].data, + strlen((char*) rd[i].data)); + break; + } + } + + pseu = (char*) rd[i].data; + answer_len = strlen(rh->name) + strlen(pseu) + strlen(GNUNET_GNS_TLD) + 3; + result = GNUNET_malloc(answer_len); + memset(result, 0, answer_len); + strcpy(result, rh->name); + strcpy(result+strlen(rh->name), "."); + strcpy(result+strlen(rh->name)+1, pseu); + strcpy(result+strlen(rh->name)+strlen(pseu)+1, "."); + strcpy(result+strlen(rh->name)+strlen(pseu)+2, GNUNET_GNS_TLD); + + GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, + "Sending shorten result %s\n", result); + + nsh->proc(nsh->proc_cls, result); + free_resolver_handle(rh); + GNUNET_free(result); + return; + } + + /** + * No PSEU found. + * continue with next authority + * Note that we never have <2 authorities + * in our list at this point since tail is always our root + * And we filter fot this in handle_delegation_ns_shorten + */ + next_authority = rh->authority_chain_head; + new_name = GNUNET_malloc(strlen(rh->name)+ + strlen(next_authority->name) + 2); + memset(new_name, 0, strlen(rh->name)+ + strlen(next_authority->name) + 2); + strcpy(new_name, rh->name); + strcpy(new_name+strlen(rh->name)+1, "."); + strcpy(new_name+strlen(rh->name)+2, next_authority->name); + + GNUNET_free(rh->name); + rh->name = new_name; + GNUNET_CONTAINER_DLL_remove(rh->authority_chain_head, + rh->authority_chain_tail, + next_authority); + + GNUNET_NAMESTORE_zone_to_name (namestore_handle, + &rh->authority_chain_tail->zone, + &rh->authority_chain_head->zone, + &process_zone_to_name_shorten, + rh); + +} + + + +/** + * Process result from namestore delegation lookup + * for shorten operation + * + * @param cls the client shorten handle + * @param rh the resolver handle + * @param rd_count number of results (0) + * @param rd data (NULL) + */ +void +handle_delegation_ns_shorten(void* cls, + struct ResolverHandle *rh, + uint32_t rd_count, + const struct GNUNET_NAMESTORE_RecordData *rd) +{ + struct NameShortenHandle *nsh; + char* result; + size_t answer_len; + + nsh = (struct NameShortenHandle *)cls; + + /** + * At this point rh->name contains the part of the name + * that we do not have a PKEY in our namestore to resolve. + * The authority chain in the resolver handle is now + * useful to backtrack if needed + */ + + GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, + "PKEY resolved as far as possible in ns up to %s!\n", rh->name); + + if (GNUNET_CRYPTO_hash_cmp(&rh->authority_chain_head->zone, + &rh->authority_chain_tail->zone) == 0) + { + /** + * This is our zone append .gnunet unless name is empty + * (it shouldn't be, usually FIXME what happens if we + * shorten to our zone to a "" record??) + **/ + + answer_len = strlen(rh->name) + strlen(GNUNET_GNS_TLD) + 2; + result = GNUNET_malloc(answer_len); + memset(result, 0, answer_len); + strcpy(result, rh->name); + strcpy(result+strlen(rh->name), "."); + strcpy(result+strlen(rh->name)+1, GNUNET_GNS_TLD); + + GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, + "Our zone: Sending name as shorten result %s\n", rh->name); + + nsh->proc(nsh->proc_cls, result); //FIXME +.gnunet! + free_resolver_handle(rh); + GNUNET_free(result); + return; + } + + /* backtrack authorities for names */ + GNUNET_NAMESTORE_zone_to_name (namestore_handle, + &rh->authority_chain_tail->zone, //ours + &rh->authority_chain_head->zone, + &process_zone_to_name_shorten, + rh); + +} + +/** + * Shorten api from resolver + * + * @param zone the zone to use + * @param name the name to shorten + * @param proc the processor to call with result + * @param cls closure to pass to proc + */ +void +gns_resolver_shorten_name(GNUNET_HashCode zone, + const char* name, + ShortenResultProcessor proc, + void* cls) +{ + struct ResolverHandle *rh; + struct NameShortenHandle *nsh; + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Starting shorten for %s!\n", name); + + nsh = GNUNET_malloc(sizeof (struct NameShortenHandle)); + rh = GNUNET_malloc(sizeof (struct ResolverHandle)); + rh->authority = zone; + rh->name = GNUNET_malloc(strlen(name) + - strlen(GNUNET_GNS_TLD)); + memset(rh->name, 0, + strlen(name)-strlen(GNUNET_GNS_TLD)); + memcpy(rh->name, name, + strlen(name)-strlen(GNUNET_GNS_TLD)-1); + + rh->authority_name = GNUNET_malloc(sizeof(char)*MAX_DNS_LABEL_LENGTH); + rh->authority_chain_head = GNUNET_malloc(sizeof(struct AuthorityChain)); + rh->authority_chain_tail = rh->authority_chain_head; + rh->authority_chain_head->zone = zone; + rh->proc = &handle_delegation_ns_shorten; + rh->proc_cls = nsh; + + nsh->proc = proc; + nsh->proc_cls = cls; + + /* Start delegation resolution in our namestore */ + resolve_delegation_ns(rh); +} + +/*********** END NAME SHORTEN ********************/ + + +/** + * Process result from namestore delegation lookup + * for get authority operation + * + * @param cls the client get auth handle + * @param rh the resolver handle + * @param rd_count number of results (0) + * @param rd data (NULL) + */ +void +handle_delegation_result_ns_get_auth(void* cls, + struct ResolverHandle *rh, + uint32_t rd_count, + const struct GNUNET_NAMESTORE_RecordData *rd) +{ + struct GetNameAuthorityHandle* nah; + char* result; + size_t answer_len; + + nah = (struct GetNameAuthorityHandle*) rh->proc_cls; + + /** + * At this point rh->name contains the part of the name + * that we do not have a PKEY in our namestore to resolve. + * The authority chain in the resolver handle is now + * useful to backtrack if needed + */ + + GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, + "PKEY resolved as far as possible in ns up to %s!\n", rh->name); + + GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, + "Building response!\n"); + if (is_canonical(rh->name)) + { + /** + * We successfully resolved the authority in the ns + * FIXME for our purposes this is fine + * but maybe we want to have an api that also looks + * into the dht (i.e. option in message) + **/ + if (strlen(rh->name) > strlen(nah->name)) + { + GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, + "Record name longer than original lookup name... odd!\n"); + //FIXME to sth here + } + + answer_len = strlen(nah->name) - strlen(rh->name) + + strlen(GNUNET_GNS_TLD) + 1; + result = GNUNET_malloc(answer_len); + memset(result, 0, answer_len); + strcpy(result, nah->name + strlen(rh->name) + 1); + + GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, + "Got authority result %s\n", result); + + nah->proc(nah->proc_cls, result); + free_resolver_handle(rh); + GNUNET_free(result); + GNUNET_free(nah); + } + else + { + GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, + "Unable to resolve authority for remaining %s!\n", rh->name); + nah->proc(nah->proc_cls, ""); + free_resolver_handle(rh); + GNUNET_free(nah); + } + + +} + + +/** + * Tries to resolve the authority for name + * in our namestore + * + * @param zone the root zone to look up for + * @param name the name to lookup up + * @param proc the processor to call when finished + * @param cls the closure to pass to the processor + */ +void +gns_resolver_get_authority(GNUNET_HashCode zone, + const char* name, + GetAuthorityResultProcessor proc, + void* cls) +{ + struct ResolverHandle *rh; + struct GetNameAuthorityHandle *nah; + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Starting authority resolution for %s!\n", name); + + nah = GNUNET_malloc(sizeof (struct GetNameAuthorityHandle)); + rh = GNUNET_malloc(sizeof (struct ResolverHandle)); + rh->authority = zone; + + rh->name = GNUNET_malloc(strlen(name) + - strlen(GNUNET_GNS_TLD)); + memset(rh->name, 0, + strlen(name)-strlen(GNUNET_GNS_TLD)); + memcpy(rh->name, name, + strlen(name)-strlen(GNUNET_GNS_TLD) - 1); + + nah->name = GNUNET_malloc(strlen(name)+1); + memset(nah->name, 0, + strlen(name)+1); + strcpy(nah->name, name); + + rh->authority_name = GNUNET_malloc(MAX_DNS_LABEL_LENGTH); + + rh->authority_chain_head = GNUNET_malloc(sizeof(struct AuthorityChain)); + rh->authority_chain_tail = rh->authority_chain_head; + rh->authority_chain_head->zone = zone; + rh->proc = &handle_delegation_result_ns_get_auth; + rh->proc_cls = (void*)nah; + + nah->proc = proc; + nah->proc_cls = cls; + + /* Start delegation resolution in our namestore */ + resolve_delegation_ns(rh); + +} + +/******** END GET AUTHORITY *************/ + +/* end of gns_resolver.c */ diff --git a/src/gns/gnunet-service-gns_resolver.h b/src/gns/gnunet-service-gns_resolver.h new file mode 100644 index 000000000..2b0c4755d --- /dev/null +++ b/src/gns/gnunet-service-gns_resolver.h @@ -0,0 +1,226 @@ +#ifndef GNS_RESOLVER_H +#define GNS_RESOLVER_H + +#include "gns.h" + +#define DHT_OPERATION_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 3) +#define DHT_LOOKUP_TIMEOUT DHT_OPERATION_TIMEOUT +#define DHT_GNS_REPLICATION_LEVEL 5 +#define MAX_DNS_LABEL_LENGTH 63 + +/* + * DLL to hold the authority chain + * we had to pass in the resolution process + */ +struct AuthorityChain +{ + struct AuthorityChain *prev; + + struct AuthorityChain *next; + + /* the zone hash of the authority */ + GNUNET_HashCode zone; + + /* (local) name of the authority */ + char* name; + + /* was the ns entry fresh */ + int fresh; +}; + +/* handle to a resolution process */ +struct ResolverHandle; + +/** + * processor for a resultion result + * + * @param cls the closure + * @param rh the resolution handle + * @param rd_count number of results + * @pram rd resukt data + */ +typedef void (*RecordLookupProcessor) (void *cls, + uint32_t rd_count, + const struct GNUNET_NAMESTORE_RecordData *rd); + + +/** + * processor for a shorten result + * + * @param cls the closure + * @param name shortened name + */ +typedef void (*ShortenResultProcessor) (void *cls, const char* name); + + +/** + * processor for an authority result + * + * @param cls the closure + * @param name name + */ +typedef void (*GetAuthorityResultProcessor) (void *cls, const char* name); + +/** + * processor for a resultion result + * + * @param cls the closure + * @param rh the resolution handle + * @param rd_count number of results + * @param rd result data + */ +typedef void (*ResolutionResultProcessor) (void *cls, + struct ResolverHandle *rh, + uint32_t rd_count, + const struct GNUNET_NAMESTORE_RecordData *rd); + + +/** + * Resoltion status indicator + * EXISTS: the name to lookup exists + * EXPIRED: the name in the record expired + */ +enum ResolutionStatus +{ + EXISTS = 1, + EXPIRED = 2 +}; + +/** + * Handle to a currenty pending resolution + */ +struct ResolverHandle +{ + /* The name to resolve */ + char *name; + + /* has this query been answered? how many matches */ + int answered; + + /* the authoritative zone to query */ + GNUNET_HashCode authority; + + /* the name of the authoritative zone to query */ + char *authority_name; + + /** + * we have an authority in namestore that + * may be able to resolve + */ + int authority_found; + + /* a handle for dht lookups. should be NULL if no lookups are in progress */ + struct GNUNET_DHT_GetHandle *get_handle; + + /* timeout task for dht lookups */ + GNUNET_SCHEDULER_TaskIdentifier dht_timeout_task; + + /* called when resolution phase finishes */ + ResolutionResultProcessor proc; + + /* closure passed to proc */ + void* proc_cls; + + /* DLL to store the authority chain */ + struct AuthorityChain *authority_chain_head; + + /* DLL to store the authority chain */ + struct AuthorityChain *authority_chain_tail; + + /* status of the resolution result */ + enum ResolutionStatus status; + +}; + + +/** + * Handle to a record lookup + */ +struct RecordLookupHandle +{ + /* the record type to look up */ + enum GNUNET_GNS_RecordType record_type; + + /* the name to look up */ + char *name; + + /* Method to call on record resolution result */ + RecordLookupProcessor proc; + + /* closure to pass to proc */ + void* proc_cls; + +}; + + +/** + * Handle to a shorten context + */ +struct NameShortenHandle +{ + + + /* Method to call on shorten result */ + ShortenResultProcessor proc; + + /* closure to pass to proc */ + void* proc_cls; + +}; + +/** + * Handle to a get authority context + */ +struct GetNameAuthorityHandle +{ + + /* the name to look up authority for */ + char* name; + + /* Method to call on result */ + GetAuthorityResultProcessor proc; + + /* closure to pass to proc */ + void* proc_cls; + +}; + + +/** + * Lookup of a record in a specific zone + * calls lookup result processor on result + * + * @param zone the root zone + * @param record_type the record type to look up + * @param proc the processor to call + * @param cls the closure to pass to proc + */ +void +gns_resolver_lookup_record(GNUNET_HashCode zone, + uint32_t record_type, + const char* name, + RecordLookupProcessor proc, + void* cls); + +void +gns_resolver_shorten_name(GNUNET_HashCode zone, + const char* name, + ShortenResultProcessor proc, + void* cls); + +/** + * Tries to resolve the authority for name + * in our namestore + * + * @param zone the root zone to look up for + * @param name the name to lookup up + * @param proc the processor to call when finished + * @param cls the closure to pass to the processor + */ +void +gns_resolver_get_authority(GNUNET_HashCode zone, + const char* name, + GetAuthorityResultProcessor proc, + void* cls); + +#endif diff --git a/src/gns/test_gns_dht_shorten.c b/src/gns/test_gns_dht_shorten.c deleted file mode 100644 index 32d978290..000000000 --- a/src/gns/test_gns_dht_shorten.c +++ /dev/null @@ -1,500 +0,0 @@ -/* - 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_twopeer.c - * @brief base testcase for testing DHT service with - * two running peers. - * - * This testcase starts peers using the GNUNET_TESTING_daemons_start - * function call. On peer start, connects to the peers DHT service - * by calling GNUNET_DHT_connected. Once notified about all peers - * being started (by the peers_started_callback function), calls - * GNUNET_TESTING_connect_topology, which connects the peers in a - * "straight line" topology. On notification that all peers have - * been properly connected, calls the do_get function which initiates - * a GNUNET_DHT_get from the *second* peer. Once the GNUNET_DHT_get - * function starts, runs the do_put function to insert data at the first peer. - * If the GET is successful, schedules finish_testing - * to stop the test and shut down peers. If GET is unsuccessful - * after GET_TIMEOUT seconds, prints an error message and shuts down - * the peers. - */ -#include "platform.h" -#include "gnunet_testing_lib.h" -#include "gnunet_core_service.h" -#include "block_gns.h" -#include "gnunet_signatures.h" -#include "gnunet_namestore_service.h" -#include "../namestore/namestore.h" -#include "gnunet_dnsparser_lib.h" -#include "gnunet_dht_service.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, 10) - -/* If number of peers not in config file, use this number */ -#define DEFAULT_NUM_PEERS 2 - -/* test records to resolve */ -#define TEST_DOMAIN "www.alice.bob.gnunet" -#define TEST_IP "127.0.0.1" -#define TEST_RECORD_NAME "www" - -#define TEST_AUTHORITY_NAME "bob" -#define TEST_AUTHORITY_ALICE "alice" -#define TEST_ALICE_PSEU "carol" -#define TEST_EXPECTED_RESULT "www.carol.gnunet" - -#define DHT_OPERATION_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 1) - -/* Globals */ - -/** - * Directory to store temp data in, defined in config file - */ -static char *test_directory; - -struct GNUNET_TESTING_Daemon *d1; - - -/* 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; - -static struct GNUNET_DHT_Handle *dht_handle; - -const struct GNUNET_CONFIGURATION_Handle *cfg; - -struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded alice_pkey; -struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded bob_pkey; -struct GNUNET_CRYPTO_RsaPrivateKey *alice_key; -struct GNUNET_CRYPTO_RsaPrivateKey *bob_key; - -/** - * 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); -} - - -/** - * Called when gns shorten finishes - */ -static void -process_shorten_result(void* cls, const char* sname) -{ - GNUNET_GNS_disconnect(gns_handle); - - ok = 0; - - if (sname == NULL) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "shorten test failed!\n"); - ok = 1; - } - else - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "%s shortened to %s\n", (char*)cls, sname); - if (0 != strcmp(sname, TEST_EXPECTED_RESULT)) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "shorten test failed! (wanted: %s got: %s\n", - (char*)cls, sname); - ok = 1; - } - - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "shorten test succeeded!\n"); - - } - - GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Shutting down peer1!\n"); - GNUNET_TESTING_daemon_stop (d1, TIMEOUT, &shutdown_callback, NULL, - GNUNET_YES, GNUNET_NO); -} - -/** - * Function scheduled to be run on the successful start of services - * tries to look up the dns record for TEST_DOMAIN - */ -static void -commence_testing (void* cls, const struct GNUNET_SCHEDULER_TaskContext *tc) -{ - GNUNET_NAMESTORE_disconnect(namestore_handle, GNUNET_YES); - - gns_handle = GNUNET_GNS_connect(cfg); - - if (NULL == gns_handle) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Failed to connect to GNS!\n"); - ok = 1; - } - - GNUNET_GNS_shorten(gns_handle, TEST_DOMAIN, &process_shorten_result, - TEST_DOMAIN); -} - -/** - * Continuation for the GNUNET_DHT_get_stop call, so that we don't shut - * down the peers without freeing memory associated with GET request. - */ -static void -end_badly_cont (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) -{ - - if (d1 != NULL) - GNUNET_TESTING_daemon_stop (d1, TIMEOUT, &shutdown_callback, NULL, - GNUNET_YES, GNUNET_NO); - GNUNET_SCHEDULER_cancel (die_task); -} - -/** - * Check if the get_handle is being used, if so stop the request. Either - * way, schedule the end_badly_cont function which actually shuts down the - * test. - */ -static void -end_badly (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) -{ - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failing test with error: `%s'!\n", - (char *) cls); - GNUNET_SCHEDULER_add_now (&end_badly_cont, NULL); - ok = 1; -} - - -static void -put_www_dht(void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) -{ - struct GNSNameRecordBlock *nrb; - GNUNET_HashCode name_hash; - GNUNET_HashCode xor_hash; - GNUNET_HashCode zone_hash; - uint32_t rd_payload_length; - char* nrb_data = NULL; - struct GNUNET_CRYPTO_RsaSignature *sig; - struct GNUNET_NAMESTORE_RecordData rd; - char* ip = TEST_IP; - struct in_addr *web = GNUNET_malloc(sizeof(struct in_addr)); - - rd.expiration = GNUNET_TIME_absolute_get_forever (); - GNUNET_assert(1 == inet_pton (AF_INET, ip, web)); - rd.data_size = sizeof(struct in_addr); - rd.data = web; - rd.record_type = GNUNET_DNSPARSER_TYPE_A; - - sig = GNUNET_NAMESTORE_create_signature(alice_key, - GNUNET_TIME_absolute_get_forever(), - TEST_RECORD_NAME, - &rd, 1); - rd_payload_length = GNUNET_NAMESTORE_records_get_size (1, &rd); - nrb = GNUNET_malloc(rd_payload_length + strlen(TEST_RECORD_NAME) + 1 - + sizeof(struct GNSNameRecordBlock)); - nrb->signature = *sig; - nrb->public_key = alice_pkey; - nrb->rd_count = htonl(1); - memset(&nrb[1], 0, strlen(TEST_RECORD_NAME) + 1); - memcpy(&nrb[1], TEST_RECORD_NAME, strlen(TEST_RECORD_NAME)); - nrb_data = (char*)&nrb[1]; - nrb_data += strlen(TEST_RECORD_NAME) + 1; - - if (-1 == GNUNET_NAMESTORE_records_serialize (1, - &rd, - rd_payload_length, - nrb_data)) - { - GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Record serialization failed!\n"); - ok = 3; - GNUNET_free (nrb); - return; - } - GNUNET_CRYPTO_hash(TEST_RECORD_NAME, strlen(TEST_RECORD_NAME), &name_hash); - GNUNET_CRYPTO_hash(&alice_pkey, - sizeof(struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded), - &zone_hash); - GNUNET_CRYPTO_hash_xor(&zone_hash, &name_hash, &xor_hash); - - rd_payload_length += sizeof(struct GNSNameRecordBlock) + - strlen(TEST_RECORD_NAME) + 1; - GNUNET_DHT_put (dht_handle, &xor_hash, - 0, - GNUNET_DHT_RO_NONE, - GNUNET_BLOCK_TYPE_GNS_NAMERECORD, - rd_payload_length, - (char*)nrb, - rd.expiration, - DHT_OPERATION_TIMEOUT, - NULL, - NULL); - GNUNET_free (nrb); - GNUNET_SCHEDULER_add_delayed(TIMEOUT, &commence_testing, NULL); -} - - -static void -put_alice_pseu_dht(void *cls, int32_t success, const char *emsg) -{ - struct GNSNameRecordBlock *nrb; - GNUNET_HashCode name_hash; - GNUNET_HashCode xor_hash; - GNUNET_HashCode zone_hash; - uint32_t rd_payload_length; - char* nrb_data = NULL; - struct GNUNET_CRYPTO_RsaSignature *sig; - struct GNUNET_NAMESTORE_RecordData rd; - - rd.expiration = GNUNET_TIME_absolute_get_forever (); - rd.data_size = strlen(TEST_ALICE_PSEU); - rd.data = TEST_ALICE_PSEU; - rd.record_type = GNUNET_GNS_RECORD_PSEU; - - sig = GNUNET_NAMESTORE_create_signature(alice_key, - GNUNET_TIME_absolute_get_forever(), - "+", //empty name for pseu - &rd, 1); - rd_payload_length = GNUNET_NAMESTORE_records_get_size (1, &rd); - nrb = GNUNET_malloc(rd_payload_length + strlen("") + 1 - + sizeof(struct GNSNameRecordBlock)); - nrb->signature = *sig; - nrb->public_key = alice_pkey; - nrb->rd_count = htonl(1); - memset(&nrb[1], 0, strlen("+") + 1); - memcpy(&nrb[1], "+", strlen("+")); - nrb_data = (char*)&nrb[1]; - nrb_data += strlen("+") + 1; - - if (-1 == GNUNET_NAMESTORE_records_serialize (1, - &rd, - rd_payload_length, - nrb_data)) - { - GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Record serialization failed!\n"); - ok = 3; - GNUNET_free (nrb); - return; - } - GNUNET_CRYPTO_hash("+", strlen("+"), &name_hash); - GNUNET_CRYPTO_hash(&alice_pkey, - sizeof(struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded), - &zone_hash); - GNUNET_CRYPTO_hash_xor(&zone_hash, &name_hash, &xor_hash); - - rd_payload_length += sizeof(struct GNSNameRecordBlock) + - strlen("+") + 1; - GNUNET_DHT_put (dht_handle, &xor_hash, - 0, - GNUNET_DHT_RO_NONE, - GNUNET_BLOCK_TYPE_GNS_NAMERECORD, - rd_payload_length, - (char*)nrb, - rd.expiration, - DHT_OPERATION_TIMEOUT, - NULL, - NULL); - GNUNET_free (nrb); - GNUNET_SCHEDULER_add_delayed(TIMEOUT, &put_www_dht, NULL); -} - -static void -do_shorten(void *cls, const struct GNUNET_PeerIdentity *id, - const struct GNUNET_CONFIGURATION_Handle *cfg, - struct GNUNET_TESTING_Daemon *d, const char *emsg) -{ - - char* my_keyfile; - struct GNUNET_CRYPTO_RsaPrivateKey *my_key; - GNUNET_HashCode bob_hash; - GNUNET_HashCode alice_hash; - struct GNUNET_CRYPTO_RsaSignature *sig; - - - GNUNET_SCHEDULER_cancel (die_task); - - /* put records into namestore */ - namestore_handle = GNUNET_NAMESTORE_connect(cfg); - if (NULL == namestore_handle) - { - GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Failed to connect to namestore\n"); - ok = -1; - return; - } - - /* dht */ - dht_handle = GNUNET_DHT_connect(cfg, 1); - if (NULL == dht_handle) - { - GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Failed to connect to dht\n"); - ok = -1; - return; - } - - if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string (cfg, "gns", - "ZONEKEY", - &my_keyfile)) - { - GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Failed to get key from cfg\n"); - ok = -1; - return; - } - - my_key = GNUNET_CRYPTO_rsa_key_create_from_file (my_keyfile); - alice_key = GNUNET_CRYPTO_rsa_key_create (); - bob_key = GNUNET_CRYPTO_rsa_key_create (); - - GNUNET_CRYPTO_rsa_key_get_public (alice_key, &alice_pkey); - GNUNET_CRYPTO_rsa_key_get_public (bob_key, &bob_pkey); - GNUNET_CRYPTO_hash(&bob_pkey, sizeof(bob_pkey), &bob_hash); - GNUNET_CRYPTO_hash(&alice_pkey, sizeof(alice_pkey), &alice_hash); - - struct GNUNET_NAMESTORE_RecordData rd; - rd.expiration = GNUNET_TIME_absolute_get_forever (); - rd.data_size = sizeof(GNUNET_HashCode); - rd.data = &bob_hash; - rd.record_type = GNUNET_GNS_RECORD_PKEY; - - GNUNET_NAMESTORE_record_create (namestore_handle, - my_key, - TEST_AUTHORITY_NAME, - &rd, - NULL, - NULL); - - rd.data = &alice_hash; - - sig = GNUNET_NAMESTORE_create_signature(bob_key, - GNUNET_TIME_absolute_get_forever(), - TEST_AUTHORITY_ALICE, - &rd, - 1); - - GNUNET_NAMESTORE_record_put (namestore_handle, - &bob_pkey, - TEST_AUTHORITY_ALICE, - GNUNET_TIME_absolute_get_forever(), - 1, - &rd, - sig, - &put_alice_pseu_dht, - NULL); - - - - - -} - -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 */ - d1 = GNUNET_TESTING_daemon_start(cfg, TIMEOUT, GNUNET_NO, NULL, NULL, 0, - NULL, NULL, NULL, &do_shorten, NULL); -} - -static int -check () -{ - int ret; - - /* Arguments for GNUNET_PROGRAM_run */ - char *const argv[] = { "test-gns-dht-delegated-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-dht-delegated-lookup", "nohelp", options, &run, - &ok); - if (ret != GNUNET_OK) - { - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - "`test-gns-dht-delegated-lookup': Failed with error code %d\n", ret); - } - return ok; -} - -int -main (int argc, char *argv[]) -{ - int ret; - - GNUNET_log_setup ("test-gns-simple-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_twopeer.c */ diff --git a/src/gns/test_gns_simple_shorten.c b/src/gns/test_gns_simple_shorten.c index 17076bb4a..8f93c471f 100644 --- a/src/gns/test_gns_simple_shorten.c +++ b/src/gns/test_gns_simple_shorten.c @@ -285,25 +285,18 @@ do_shorten(void *cls, const struct GNUNET_PeerIdentity *id, NULL, NULL); - rd.data_size = strlen(TEST_ALICE_PSEU); - rd.data = TEST_ALICE_PSEU; - rd.record_type = GNUNET_GNS_RECORD_PSEU; + rd.data_size = sizeof(GNUNET_HashCode); + rd.data = &alice_hash; + rd.record_type = GNUNET_GNS_RECORD_PKEY; GNUNET_free(sig); - sig = GNUNET_NAMESTORE_create_signature(alice_key,GNUNET_TIME_absolute_get_forever(), "+", - &rd, 1); - - GNUNET_NAMESTORE_record_put (namestore_handle, - &alice_pkey, - "+", - GNUNET_TIME_absolute_get_forever(), - 1, + GNUNET_NAMESTORE_record_create (namestore_handle, + our_key, + TEST_ALICE_PSEU, &rd, - sig, &commence_testing, NULL); - GNUNET_free(sig); } -- 2.25.1