From 5f5f1974b15c646bde44583aede2433254138661 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Tue, 13 Aug 2013 19:14:19 +0000 Subject: -more coding towards working new GNS service --- src/gns/gnunet-service-gns.c | 494 +++++----- src/gns/gnunet-service-gns_interceptor.c | 401 ++++---- src/gns/gnunet-service-gns_interceptor.h | 11 +- src/gns/gnunet-service-gns_resolver.c | 1567 ++++++++---------------------- src/gns/gnunet-service-gns_resolver.h | 606 +----------- 5 files changed, 862 insertions(+), 2217 deletions(-) (limited to 'src/gns') diff --git a/src/gns/gnunet-service-gns.c b/src/gns/gnunet-service-gns.c index 822cc7d12..be41f8c84 100644 --- a/src/gns/gnunet-service-gns.c +++ b/src/gns/gnunet-service-gns.c @@ -1,6 +1,6 @@ /* This file is part of GNUnet. - (C) 2009, 2010, 2011, 2012 Christian Grothoff (and other contributing authors) + (C) 2011-2013 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 @@ -50,7 +50,7 @@ /** * The default put interval for the zone iteration. In case - * No option is found + * no option is found */ #define DEFAULT_ZONE_PUBLISH_TIME_WINDOW GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_HOURS, 4) @@ -60,6 +60,16 @@ */ #define LATE_ITERATION_SPEEDUP_FACTOR 2 +/** + * How long until a DHT PUT attempt should time out? + */ +#define DHT_OPERATION_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 60) + +/** + * What replication level do we use for DHT PUT operations? + */ +#define DHT_GNS_REPLICATION_LEVEL 5 + /** * Handle to a lookup operation from api @@ -68,39 +78,30 @@ struct ClientLookupHandle { /** - * Handle to the requesting client + * We keep these in a DLL. */ - struct GNUNET_SERVER_Client *client; + struct ClientLookupHandle *next; /** - * optional zone private key used for shorten + * We keep these in a DLL. */ - struct GNUNET_CRYPTO_EccPrivateKey *shorten_key; + struct ClientLookupHandle *prev; /** - * the name to look up + * Handle to the requesting client */ - char *name; + struct GNUNET_SERVER_Client *client; /** - * The zone we look up in + * Active handle for the lookup. */ - struct GNUNET_CRYPTO_ShortHashCode zone; + struct GNS_ResolverHandle *lookup; /** * request id */ uint32_t request_id; - /** - * GNUNET_YES if we only want to lookup from local cache - */ - int only_cached; - - /** - * request type - */ - int type; }; @@ -110,9 +111,9 @@ struct ClientLookupHandle static struct GNUNET_DHT_Handle *dht_handle; /** - * Our zone's private key + * Active DHT put operation (or NULL) */ -static struct GNUNET_CRYPTO_EccPrivateKey *zone_key; +static struct GNUNET_DHT_PutHandle *active_put; /** * Our handle to the namestore service @@ -130,9 +131,14 @@ static struct GNUNET_NAMESTORE_ZoneIterator *namestore_iter; static struct GNUNET_SERVER_NotificationContext *nc; /** - * Our zone hash + * Head of the DLL. + */ +static struct ClientLookupHandle *clh_head; + +/** + * Tail of the DLL. */ -static struct GNUNET_CRYPTO_ShortHashCode zone_hash; +static struct ClientLookupHandle *clh_tail; /** * Useful for zone update for DHT put @@ -160,13 +166,7 @@ static struct GNUNET_TIME_Relative zone_publish_time_window; static GNUNET_SCHEDULER_TaskIdentifier zone_publish_task; /** - * GNUNET_YES if automatic pkey import for name shortening - * is enabled - */ -static int auto_import_pkey; - -/** - * GNUNET_YES if zone has never been published before + * #GNUNET_YES if zone has never been published before */ static int first_zone_iteration; @@ -176,12 +176,12 @@ static int first_zone_iteration; static struct GNUNET_TIME_Relative default_lookup_timeout; /** - * GNUNET_YES if ipv6 is supported + * #GNUNET_YES if ipv6 is supported */ static int v6_enabled; /** - * GNUNET_YES if ipv4 is supported + * #GNUNET_YES if ipv4 is supported */ static int v4_enabled; @@ -200,13 +200,20 @@ static struct GNUNET_STATISTICS_Handle *statistics; static void shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { - struct ClientShortenHandle *csh_tmp; + struct ClientLookupHandle *clh; - GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, - "Shutting down!\n"); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Shutting down!\n"); GNUNET_SERVER_notification_context_destroy (nc); - gns_interceptor_stop (); - gns_resolver_cleanup (); + while (NULL != (clh = clh_head)) + { + GNS_resolver_lookup_cancel (clh->lookup); + GNUNET_CONTAINER_DLL_remove (clh_head, clh_tail, clh); + GNUNET_free (clh); + } + + GNS_interceptor_done (); + GNS_resolver_done (); if (NULL != statistics) { GNUNET_STATISTICS_destroy (statistics, GNUNET_NO); @@ -227,6 +234,11 @@ shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) GNUNET_NAMESTORE_disconnect (namestore_handle); namestore_handle = NULL; } + if (NULL != active_put) + { + GNUNET_DHT_put_cancel (active_put); + active_put = NULL; + } if (NULL != dht_handle) { GNUNET_DHT_disconnect (dht_handle); @@ -261,37 +273,66 @@ publish_zone_dht_start (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc); +/** + * Continuation called from DHT once the PUT operation is done. + * + * @param cls closure, NULL + * @param success #GNUNET_OK on success + */ +static void +dht_put_continuation (void *cls, + int success) +{ + struct GNUNET_TIME_Relative next_put_interval; + + num_public_records++; + if ( (num_public_records > last_num_public_records) && + (GNUNET_NO == first_zone_iteration) ) + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Last record count was lower than current record count. Reducing interval.\n"); + put_interval = GNUNET_TIME_relative_divide (zone_publish_time_window, + num_public_records); + next_put_interval = GNUNET_TIME_relative_divide (put_interval, + LATE_ITERATION_SPEEDUP_FACTOR); + } + else + next_put_interval = put_interval; + + GNUNET_STATISTICS_set (statistics, + "Current zone iteration interval (ms)", + next_put_interval.rel_value_us / 1000LL, + GNUNET_NO); + zone_publish_task = GNUNET_SCHEDULER_add_delayed (next_put_interval, + &publish_zone_dht_next, + NULL); +} + + /** * Function used to put all records successively into the DHT. * * @param cls the closure (NULL) - * @param key the public key of the authority (ours) - * @param expiration lifetime of the namestore entry - * @param name the name of the records - * @param rd_count the number of records in data + * @param key the private key of the authority (ours) + * @param name the name of the records, NULL once the iteration is done + * @param rd_count the number of records in @a rd * @param rd the record data - * @param signature the signature for the record data */ static void put_gns_record (void *cls, - const struct GNUNET_CRYPTO_EccPublicKey *key, - struct GNUNET_TIME_Absolute expiration, + const struct GNUNET_CRYPTO_EccPrivateKey *key, const char *name, unsigned int rd_count, - const struct GNUNET_NAMESTORE_RecordData *rd, - const struct GNUNET_CRYPTO_EccSignature *signature) + const struct GNUNET_NAMESTORE_RecordData *rd) { - struct GNSNameRecordBlock *nrb; - struct GNUNET_CRYPTO_ShortHashCode zhash; - struct GNUNET_HashCode dht_key; - uint32_t rd_payload_length; - char* nrb_data = NULL; - size_t namelen; - struct GNUNET_TIME_Relative next_put_interval; + struct GNUNET_NAMESTORE_Block *block; + struct GNUNET_HashCode query; + struct GNUNET_TIME_Absolute expire; + size_t block_size; if (NULL == name) { - /* we're done */ + /* we're done with one iteration, calculate when to do the next one */ namestore_iter = NULL; last_num_public_records = num_public_records; first_zone_iteration = GNUNET_NO; @@ -304,7 +345,7 @@ put_gns_record (void *cls, */ put_interval = zone_publish_time_window; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK, - "No records in db.\n"); + "No records in namestore database.\n"); } else { @@ -322,126 +363,62 @@ put_gns_record (void *cls, put_interval.rel_value_us / 1000LL, GNUNET_NO); GNUNET_STATISTICS_update (statistics, - "Number of zone iterations", 1, GNUNET_NO); + "Number of zone iterations", + 1, + GNUNET_NO); GNUNET_STATISTICS_set (statistics, "Number of public records in DHT", last_num_public_records, GNUNET_NO); if (0 == num_public_records) zone_publish_task = GNUNET_SCHEDULER_add_delayed (put_interval, - &publish_zone_dht_start, - NULL); + &publish_zone_dht_start, + NULL); else - zone_publish_task = GNUNET_SCHEDULER_add_now (&publish_zone_dht_start, NULL); + zone_publish_task = GNUNET_SCHEDULER_add_now (&publish_zone_dht_start, + NULL); return; } - - namelen = strlen (name) + 1; + + /* FIXME: filter out records that are not public! */ + + /* We got a set of records to publish */ if (0 == rd_count) { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "No records for name `%s'! Skipping.\n", - name); zone_publish_task = GNUNET_SCHEDULER_add_now (&publish_zone_dht_next, NULL); return; } - if (NULL == signature) + expire = GNUNET_NAMESTORE_record_get_expiration_time (rd_count, + rd); + block = GNUNET_NAMESTORE_block_create (key, + expire, + name, + rd, + rd_count); + block_size = ntohl (block->purpose.size) + + sizeof (struct GNUNET_CRYPTO_EccSignature) + + sizeof (struct GNUNET_CRYPTO_EccPublicKey); + GNUNET_NAMESTORE_query_from_private_key (key, + name, + &query); + + active_put = GNUNET_DHT_put (dht_handle, &query, + DHT_GNS_REPLICATION_LEVEL, + GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE, + GNUNET_BLOCK_TYPE_GNS_NAMERECORD, + block_size, + block, + expire, + DHT_OPERATION_TIMEOUT, + &dht_put_continuation, + NULL); + if (NULL == active_put) { GNUNET_break (0); - zone_publish_task = GNUNET_SCHEDULER_add_now (&publish_zone_dht_next, - NULL); - return; - } - - /* TODO 2) AB: New publishing - * - * - Use new signature S_d - * - Obtain new derived public key V = H(H(i,Q) * Q) - * - Obtain HKDF(i,Q) - * - Compute encrypte record block E with HKDF(i,Q) (rd, rd_count) - * - Create block B = |V,E,S_d| - * - Compute new DHT key H(V) in TODO 3) - * - * -> Put (H(V), B) - */ - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Putting records for `%s' into the DHT\n", name); - rd_payload_length = GNUNET_NAMESTORE_records_get_size (rd_count, rd); - nrb = GNUNET_malloc (rd_payload_length + namelen - + sizeof (struct GNSNameRecordBlock)); - nrb->signature = *signature; - nrb->public_key = *key; - nrb->rd_count = htonl (rd_count); - memcpy (&nrb[1], name, namelen); - nrb_data = (char *) &nrb[1]; - nrb_data += namelen; - rd_payload_length += sizeof(struct GNSNameRecordBlock) + namelen; - GNUNET_CRYPTO_short_hash (key, - sizeof (struct GNUNET_CRYPTO_EccPublicKey), - &zhash); - if (-1 == GNUNET_NAMESTORE_records_serialize (rd_count, - rd, - rd_payload_length, - nrb_data)) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - _("Records for name `%s' in zone %s too large to fit into DHT"), - name, - GNUNET_short_h2s (&zhash)); - GNUNET_free (nrb); - zone_publish_task = GNUNET_SCHEDULER_add_now (&publish_zone_dht_next, - NULL); - return; - } - /* TODO AB: Here records are put in the DHT: modify dht_key to H(key) = H(H(name,zone) * zone) */ - GNUNET_GNS_get_key_for_record (name, &zhash, &dht_key); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "putting %u records from zone %s for `%s' under key: %s with size %u and timeout %s\n", - rd_count, - GNUNET_short_h2s (&zhash), - name, - GNUNET_h2s (&dht_key), - (unsigned int) rd_payload_length, - GNUNET_STRINGS_relative_time_to_string (DHT_OPERATION_TIMEOUT, GNUNET_YES)); - - GNUNET_STATISTICS_update (statistics, - "Record bytes put into DHT", - rd_payload_length, GNUNET_NO); - - (void) GNUNET_DHT_put (dht_handle, &dht_key, - DHT_GNS_REPLICATION_LEVEL, - GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE, - GNUNET_BLOCK_TYPE_GNS_NAMERECORD, - rd_payload_length, - (char*)nrb, - expiration, - DHT_OPERATION_TIMEOUT, - NULL, - NULL); - GNUNET_free (nrb); - - num_public_records++; - if ( (num_public_records > last_num_public_records) - && (GNUNET_NO == first_zone_iteration) ) - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Last record count was lower than current record count. Reducing interval.\n"); - put_interval = GNUNET_TIME_relative_divide (zone_publish_time_window, - num_public_records); - next_put_interval = GNUNET_TIME_relative_divide (put_interval, - LATE_ITERATION_SPEEDUP_FACTOR); + dht_put_continuation (NULL, GNUNET_NO); } - else - next_put_interval = put_interval; - - GNUNET_STATISTICS_set (statistics, - "Current zone iteration interval (ms)", - next_put_interval.rel_value_us / 1000LL, - GNUNET_NO); - zone_publish_task = GNUNET_SCHEDULER_add_delayed (next_put_interval, - &publish_zone_dht_next, - NULL); + GNUNET_free (block); } @@ -463,8 +440,6 @@ publish_zone_dht_start (void *cls, num_public_records = 0; namestore_iter = GNUNET_NAMESTORE_zone_iteration_start (namestore_handle, NULL, /* All zones */ - GNUNET_NAMESTORE_RF_AUTHORITY, - GNUNET_NAMESTORE_RF_PRIVATE, &put_gns_record, NULL); } @@ -485,40 +460,39 @@ send_lookup_response (void* cls, uint32_t rd_count, const struct GNUNET_NAMESTORE_RecordData *rd) { - struct ClientLookupHandle* clh = cls; + struct ClientLookupHandle *clh = cls; struct GNUNET_GNS_ClientLookupResultMessage *rmsg; size_t len; - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message with %d results\n", - "LOOKUP_RESULT", rd_count); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Sending `%s' message with %d results\n", + "LOOKUP_RESULT", + rd_count); len = GNUNET_NAMESTORE_records_get_size (rd_count, rd); - rmsg = GNUNET_malloc (len + sizeof (struct GNUNET_GNS_ClientLookupResultMessage)); - + rmsg = GNUNET_malloc (len + sizeof (struct GNUNET_GNS_ClientLookupResultMessage)); + rmsg->header.type = htons (GNUNET_MESSAGE_TYPE_GNS_LOOKUP_RESULT); + rmsg->header.size = htons (len + sizeof(struct GNUNET_GNS_ClientLookupResultMessage)); rmsg->id = clh->request_id; - rmsg->rd_count = htonl(rd_count); - rmsg->header.type = htons(GNUNET_MESSAGE_TYPE_GNS_LOOKUP_RESULT); - rmsg->header.size = - htons(len+sizeof(struct GNUNET_GNS_ClientLookupResultMessage)); - - GNUNET_NAMESTORE_records_serialize (rd_count, rd, len, (char*)&rmsg[1]); - - GNUNET_SERVER_notification_context_unicast (nc, clh->client, - (const struct GNUNET_MessageHeader *) rmsg, - GNUNET_NO); - GNUNET_SERVER_receive_done (clh->client, GNUNET_OK); - - GNUNET_free(rmsg); - GNUNET_free(clh->name); - - if (NULL != clh->shorten_key) - GNUNET_CRYPTO_ecc_key_free (clh->shorten_key); + rmsg->rd_count = htonl (rd_count); + GNUNET_NAMESTORE_records_serialize (rd_count, rd, len, + (char*) &rmsg[1]); + GNUNET_SERVER_notification_context_unicast (nc, + clh->client, + &rmsg->header, + GNUNET_NO); + GNUNET_free (rmsg); + GNUNET_SERVER_receive_done (clh->client, + GNUNET_OK); + GNUNET_CONTAINER_DLL_remove (clh_head, clh_tail, clh); GNUNET_free (clh); GNUNET_STATISTICS_update (statistics, - "Completed lookups", 1, GNUNET_NO); - if (NULL != rd) - GNUNET_STATISTICS_update (statistics, - "Records resolved", rd_count, GNUNET_NO); + "Completed lookups", 1, + GNUNET_NO); + GNUNET_STATISTICS_update (statistics, + "Records resolved", + rd_count, + GNUNET_NO); } @@ -531,22 +505,21 @@ send_lookup_response (void* cls, */ static void handle_lookup (void *cls, - struct GNUNET_SERVER_Client * client, - const struct GNUNET_MessageHeader * message) + struct GNUNET_SERVER_Client *client, + const struct GNUNET_MessageHeader *message) { - size_t namelen; - char name[GNUNET_DNSPARSER_MAX_NAME_LENGTH]; + char name[GNUNET_DNSPARSER_MAX_NAME_LENGTH + 1]; struct ClientLookupHandle *clh; - char* nameptr = name; + char *nameptr = name; const char *utf_in; - int only_cached; const struct GNUNET_CRYPTO_EccPrivateKey *key; uint16_t msg_size; const struct GNUNET_GNS_ClientLookupMessage *sh_msg; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Received `%s' message\n", "LOOKUP"); - msg_size = ntohs(message->size); + "Received `%s' message\n", + "LOOKUP"); + msg_size = ntohs (message->size); if (msg_size < sizeof (struct GNUNET_GNS_ClientLookupMessage)) { GNUNET_break (0); @@ -556,88 +529,48 @@ handle_lookup (void *cls, sh_msg = (const struct GNUNET_GNS_ClientLookupMessage *) message; GNUNET_SERVER_notification_context_add (nc, client); if (GNUNET_YES == ntohl (sh_msg->have_key)) - { key = &sh_msg->shorten_key; - } else - { key = NULL; - } utf_in = (const char *) &sh_msg[1]; - if ('\0' != utf_in[msg_size - sizeof (struct GNUNET_GNS_ClientLookupMessage) - 1]) + if ( ('\0' != utf_in[msg_size - sizeof (struct GNUNET_GNS_ClientLookupMessage) - 1]) || + (strlen (utf_in) > GNUNET_DNSPARSER_MAX_NAME_LENGTH) ) { GNUNET_break (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; - } + } GNUNET_STRINGS_utf8_tolower (utf_in, &nameptr); - namelen = strlen (name) + 1; - clh = GNUNET_malloc (sizeof (struct ClientLookupHandle)); - memset (clh, 0, sizeof (struct ClientLookupHandle)); + clh = GNUNET_new (struct ClientLookupHandle); + GNUNET_CONTAINER_DLL_insert (clh_head, clh_tail, clh); clh->client = client; - clh->name = GNUNET_malloc (namelen); - strcpy (clh->name, name); clh->request_id = sh_msg->id; - clh->type = ntohl (sh_msg->type); - if (NULL != key) + if ( (GNUNET_DNSPARSER_TYPE_A == ntohl (sh_msg->type)) && + (GNUNET_OK != v4_enabled) ) { - clh->shorten_key = GNUNET_new (struct GNUNET_CRYPTO_EccPrivateKey); - *clh->shorten_key = *key; - } - only_cached = ntohl (sh_msg->only_cached); - - if (strlen (name) > GNUNET_DNSPARSER_MAX_NAME_LENGTH) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "LOOKUP: %s is too long", name); - clh->name = NULL; - send_lookup_response (clh, 0, NULL); - return; - } - - if ((GNUNET_DNSPARSER_TYPE_A == clh->type) && - (GNUNET_OK != v4_enabled)) - { - GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, - "LOOKUP: Query for A record but AF_INET not supported!"); - clh->name = NULL; + "LOOKUP: Query for A record but AF_INET not supported!"); send_lookup_response (clh, 0, NULL); return; - } - - if ((GNUNET_DNSPARSER_TYPE_AAAA == clh->type) && - (GNUNET_OK != v6_enabled)) + } + if ( (GNUNET_DNSPARSER_TYPE_AAAA == ntohl (sh_msg->type)) && + (GNUNET_OK != v6_enabled) ) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "LOOKUP: Query for AAAA record but AF_INET6 not supported!"); - clh->name = NULL; send_lookup_response (clh, 0, NULL); return; } - - if (GNUNET_NO == ntohl (sh_msg->have_zone)) - clh->zone = zone_hash; /* Default zone */ - else - clh->zone = sh_msg->zone; - - if (GNUNET_YES == auto_import_pkey) - { - gns_resolver_lookup_record (clh->zone, clh->zone, clh->type, clh->name, - clh->shorten_key, - default_lookup_timeout, - clh->only_cached, - &send_lookup_response, clh); - } - else - { - gns_resolver_lookup_record (clh->zone, clh->zone, clh->type, name, - NULL, - default_lookup_timeout, - only_cached, - &send_lookup_response, clh); - } + clh->lookup = GNS_resolver_lookup (&sh_msg->zone, + ntohl (sh_msg->type), + name, + key, + ntohl (sh_msg->only_cached), + &send_lookup_response, clh); GNUNET_STATISTICS_update (statistics, - "Record lookup attempts", 1, GNUNET_NO); + "Lookup attempts", + 1, GNUNET_NO); } @@ -656,9 +589,10 @@ run (void *cls, struct GNUNET_SERVER_Handle *server, { &handle_lookup, NULL, GNUNET_MESSAGE_TYPE_GNS_LOOKUP, 0}, {NULL, NULL, 0, 0} }; - struct GNUNET_CRYPTO_EccPublicKey pkey; + struct GNUNET_CRYPTO_EccPublicKey dns_root; unsigned long long max_parallel_bg_queries = 0; int ignore_pending = GNUNET_NO; + char *dns_root_name; v6_enabled = GNUNET_NETWORK_test_pf (PF_INET6); v4_enabled = GNUNET_NETWORK_test_pf (PF_INET); @@ -672,15 +606,6 @@ run (void *cls, struct GNUNET_SERVER_Handle *server, return; } - auto_import_pkey = GNUNET_NO; - if (GNUNET_YES == - GNUNET_CONFIGURATION_get_value_yesno (c, "gns", - "AUTO_IMPORT_PKEY")) - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Automatic PKEY import is enabled.\n"); - auto_import_pkey = GNUNET_YES; - } put_interval = INITIAL_PUT_INTERVAL; zone_publish_time_window = DEFAULT_ZONE_PUBLISH_TIME_WINDOW; @@ -734,7 +659,8 @@ run (void *cls, struct GNUNET_SERVER_Handle *server, } if (GNUNET_SYSERR == - gns_resolver_init (namestore_handle, dht_handle, zone_hash, c, + GNS_resolver_init (namestore_handle, dht_handle, + c, max_parallel_bg_queries, ignore_pending)) { @@ -744,31 +670,45 @@ run (void *cls, struct GNUNET_SERVER_Handle *server, return; } - if (GNUNET_YES == - GNUNET_CONFIGURATION_get_value_yesno (c, "gns", "HIJACK_DNS")) + if (GNUNET_OK == + GNUNET_CONFIGURATION_get_value_string (c, "gns", "DNS_ROOT", + &dns_root_name)) { + if (GNUNET_OK != + GNUNET_CRYPTO_ecc_public_key_from_string (dns_root_name, + strlen (dns_root_name), + &dns_root)) + { + GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, + "gns", "DNS_ROOT", + _("valid public key required")); + GNUNET_SCHEDULER_add_now (&shutdown_task, NULL); + GNUNET_free (dns_root_name); + return; + } GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "DNS hijacking enabled. Connecting to DNS service.\n"); - + "DNS hijacking with root `%s' enabled. Connecting to DNS service.\n", + dns_root_name); + GNUNET_free (dns_root_name); if (GNUNET_SYSERR == - gns_interceptor_init (zone_hash, zone_key, c)) + GNS_interceptor_init (&dns_root, c)) { - GNUNET_log(GNUNET_ERROR_TYPE_ERROR, - "Failed to enable the DNS interceptor!\n"); + GNUNET_SCHEDULER_add_now (&shutdown_task, NULL); + return; } } + /* FIXME: install client disconnect handle to clean up pending + lookups on client disconnect! */ - /** - * Schedule periodic put for our records We have roughly an hour for - * all records; - */ + /* Schedule periodic put for our records. */ first_zone_iteration = GNUNET_YES; - zone_publish_task = GNUNET_SCHEDULER_add_now (&publish_zone_dht_start, NULL); GNUNET_SERVER_add_handlers (server, handlers); statistics = GNUNET_STATISTICS_create ("gns", c); nc = GNUNET_SERVER_notification_context_create (server, 1); - GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &shutdown_task, - NULL); + zone_publish_task = GNUNET_SCHEDULER_add_now (&publish_zone_dht_start, + NULL); + GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, + &shutdown_task, NULL); } diff --git a/src/gns/gnunet-service-gns_interceptor.c b/src/gns/gnunet-service-gns_interceptor.c index 8f1f1fb0b..ec6664454 100644 --- a/src/gns/gnunet-service-gns_interceptor.c +++ b/src/gns/gnunet-service-gns_interceptor.c @@ -1,6 +1,6 @@ /* This file is part of GNUnet. - (C) 2009, 2010, 2011, 2012 Christian Grothoff (and other contributing authors) + (C) 2009-2013 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 @@ -24,18 +24,30 @@ */ #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 "gnunet-service-gns_interceptor.h" #include "gns.h" + /** * Handle to a DNS intercepted * reslution request */ struct InterceptLookupHandle { + + /** + * We keep these in a DLL. + */ + struct InterceptLookupHandle *next; + + /** + * We keep these in a DLL. + */ + struct InterceptLookupHandle *prev; + /** * the request handle to reply to */ @@ -45,11 +57,12 @@ struct InterceptLookupHandle * the dns parser packet received */ struct GNUNET_DNSPARSER_Packet *packet; - + /** - * the query parsed from the packet + * Handle for the lookup operation. */ - struct GNUNET_DNSPARSER_Query *query; + struct GNS_ResolverHandle *lookup; + }; @@ -59,19 +72,19 @@ struct InterceptLookupHandle static struct GNUNET_DNS_Handle *dns_handle; /** - * The root zone for this interceptor + * Key of the zone we start lookups in. */ -static struct GNUNET_CRYPTO_ShortHashCode our_zone; +static struct GNUNET_CRYPTO_EccPublicKey zone; /** - * Our priv key + * Head of the DLL. */ -static struct GNUNET_CRYPTO_EccPrivateKey *our_key; +static struct InterceptLookupHandle *ilh_head; /** - * Default timeout + * Tail of the DLL. */ -static struct GNUNET_TIME_Relative default_lookup_timeout; +static struct InterceptLookupHandle *ilh_tail; /** @@ -82,189 +95,132 @@ static struct GNUNET_TIME_Relative default_lookup_timeout; * @param rd the record data */ static void -reply_to_dns (void* cls, uint32_t rd_count, +reply_to_dns (void *cls, uint32_t rd_count, const struct GNUNET_NAMESTORE_RecordData *rd) { + struct InterceptLookupHandle *ilh = cls; + struct GNUNET_DNSPARSER_Packet *packet = ilh->packet; + struct GNUNET_DNSPARSER_Query *query = &packet->queries[0]; uint32_t 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 - */ + unsigned int num_answers; + + /* Put records in the DNS packet */ + num_answers = 0; for (i=0; i < rd_count; i++) - { - if (rd[i].record_type == ilh->query->type) + if (rd[i].record_type == 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) + 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++) { - answer_records[i].name = ilh->query->name; - answer_records[i].type = rd[i].record_type; - switch(rd[i].record_type) + if (rd[i].record_type == query->type) { - case GNUNET_DNSPARSER_TYPE_NS: - case GNUNET_DNSPARSER_TYPE_CNAME: - case GNUNET_DNSPARSER_TYPE_PTR: - answer_records[i].data.hostname = (char*)rd[i].data; - break; - case GNUNET_DNSPARSER_TYPE_SOA: - answer_records[i].data.soa = - (struct GNUNET_DNSPARSER_SoaRecord *)rd[i].data; - break; - case GNUNET_DNSPARSER_TYPE_MX: - answer_records[i].data.mx = - (struct GNUNET_DNSPARSER_MxRecord *)rd[i].data; - break; - default: - answer_records[i].data.raw.data_len = rd[i].data_size; - answer_records[i].data.raw.data = (char*)rd[i].data; + answer_records[i].name = query->name; + answer_records[i].type = rd[i].record_type; + switch(rd[i].record_type) + { + case GNUNET_DNSPARSER_TYPE_NS: + case GNUNET_DNSPARSER_TYPE_CNAME: + case GNUNET_DNSPARSER_TYPE_PTR: + answer_records[i].data.hostname = (char*)rd[i].data; + break; + case GNUNET_DNSPARSER_TYPE_SOA: + answer_records[i].data.soa = + (struct GNUNET_DNSPARSER_SoaRecord *)rd[i].data; + break; + case GNUNET_DNSPARSER_TYPE_MX: + answer_records[i].data.mx = + (struct GNUNET_DNSPARSER_MxRecord *)rd[i].data; + break; + default: + answer_records[i].data.raw.data_len = rd[i].data_size; + answer_records[i].data.raw.data = (char*)rd[i].data; + break; + } + GNUNET_break (0 == (rd[i].flags & GNUNET_NAMESTORE_RF_RELATIVE_EXPIRATION)); + answer_records[i].expiration_time.abs_value_us = rd[i].expiration_time; + answer_records[i].class = GNUNET_DNSPARSER_CLASS_INTERNET; } - GNUNET_break (0 == (rd[i].flags & GNUNET_NAMESTORE_RF_RELATIVE_EXPIRATION)); - answer_records[i].expiration_time.abs_value_us = rd[i].expiration_time; - 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; - switch(rd[i].record_type) + else { - case GNUNET_DNSPARSER_TYPE_NS: - case GNUNET_DNSPARSER_TYPE_CNAME: - case GNUNET_DNSPARSER_TYPE_PTR: - additional_records[i].data.hostname = (char*)rd[i].data; - break; - case GNUNET_DNSPARSER_TYPE_SOA: - additional_records[i].data.soa = - (struct GNUNET_DNSPARSER_SoaRecord *)rd[i].data; - break; - case GNUNET_DNSPARSER_TYPE_MX: - additional_records[i].data.mx = - (struct GNUNET_DNSPARSER_MxRecord *)rd[i].data; - break; - default: - additional_records[i].data.raw.data_len = rd[i].data_size; - additional_records[i].data.raw.data = (char*)rd[i].data; + additional_records[i].name = query->name; + additional_records[i].type = rd[i].record_type; + switch(rd[i].record_type) + { + case GNUNET_DNSPARSER_TYPE_NS: + case GNUNET_DNSPARSER_TYPE_CNAME: + case GNUNET_DNSPARSER_TYPE_PTR: + additional_records[i].data.hostname = (char*)rd[i].data; + break; + case GNUNET_DNSPARSER_TYPE_SOA: + additional_records[i].data.soa = + (struct GNUNET_DNSPARSER_SoaRecord *)rd[i].data; + break; + case GNUNET_DNSPARSER_TYPE_MX: + additional_records[i].data.mx = + (struct GNUNET_DNSPARSER_MxRecord *)rd[i].data; + break; + default: + additional_records[i].data.raw.data_len = rd[i].data_size; + additional_records[i].data.raw.data = (char*)rd[i].data; + break; + } + GNUNET_break (0 == (rd[i].flags & GNUNET_NAMESTORE_RF_RELATIVE_EXPIRATION)); + additional_records[i].expiration_time.abs_value_us = rd[i].expiration_time; + additional_records[i].class = GNUNET_DNSPARSER_CLASS_INTERNET; } - GNUNET_break (0 == (rd[i].flags & GNUNET_NAMESTORE_RF_RELATIVE_EXPIRATION)); - additional_records[i].expiration_time.abs_value_us = rd[i].expiration_time; - 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 (NULL == rd) + 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; + ret = GNUNET_DNSPARSER_pack (packet, + 1024, /* maximum allowed size for DNS reply */ + &buf, + &len); + if (GNUNET_OK != ret) + { + GNUNET_log (GNUNET_ERROR_TYPE_WARNING, + _("Error converting GNS response to DNS response!\n")); + } + else + { + GNUNET_DNS_request_answer (ilh->request_handle, + len, + buf); + GNUNET_free (buf); + } + packet->num_answers = 0; + packet->answers = NULL; + packet->num_additional_records = 0; + packet->additional_records = NULL; + GNUNET_DNSPARSER_free_packet (packet); } - - 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); - 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, our_zone, q->type, q->name, - our_key, - default_lookup_timeout, - GNUNET_NO, - &reply_to_dns, ilh); + GNUNET_CONTAINER_DLL_remove (ilh_head, ilh_tail, ilh); + GNUNET_free (ilh); } /** - * The DNS request handler - * Called for every incoming DNS request. + * The DNS request handler. Called for every incoming DNS request. * - * @param cls closure + * @param cls closure, unused * @param rh request handle to user for reply - * @param request_length number of bytes in request - * @param request udp payload of the DNS request + * @param request_length number of bytes in @a request + * @param request UDP payload of the DNS request */ static void handle_dns_request (void *cls, @@ -273,61 +229,50 @@ handle_dns_request (void *cls, const char *request) { struct GNUNET_DNSPARSER_Packet *p; + struct InterceptLookupHandle *ilh; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Hijacked a DNS request...processing\n"); + "Hijacked a DNS request. Processing.\n"); if (NULL == (p = GNUNET_DNSPARSER_parse (request, request_length))) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - "Received malformed DNS packet, leaving it untouched\n"); + "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 (0 == p->num_queries) + /* Check TLD and decide if we or legacy dns is responsible */ + if (1 != p->num_queries) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "No Queries in DNS packet... forwarding\n"); + "Not exactly one query in DNS packet. Forwarding untouched.\n"); GNUNET_DNS_request_forward (rh); GNUNET_DNSPARSER_free_packet(p); return; } - /** - * Check for .gads/.zkey - */ - - if ((is_gads_tld(p->queries[0].name) == GNUNET_YES) || - (is_zkey_tld(p->queries[0].name) == GNUNET_YES) || - (strcmp(p->queries[0].name, GNUNET_GNS_TLD) == 0)) + /* Check for GNS TLDs. */ + if ( (GNUNET_YES == is_gads_tld (p->queries[0].name)) || + (GNUNET_YES == is_zkey_tld (p->queries[0].name)) || + (0 == strcmp (p->queries[0].name, GNUNET_GNS_TLD)) ) { - if (p->num_queries > 1) - { - /* Note: We could also look for .gads */ - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - ">1 queriy in DNS packet... odd. We only process #1\n"); - } - start_resolution_for_dns (rh, p, p->queries); + /* Start resolution in GNS */ + ilh = GNUNET_new (struct InterceptLookupHandle); + GNUNET_CONTAINER_DLL_insert (ilh_head, ilh_tail, ilh); + ilh->packet = p; + ilh->request_handle = rh; + ilh->lookup = GNS_resolver_lookup (&zone, + p->queries[0].type, + p->queries[0].name, + NULL /* FIXME: enable shorten for DNS intercepts? */, + GNUNET_NO, + &reply_to_dns, ilh); return; } - /** - * This request does not concern us. Forward to real DNS. - */ + /* This request does not concern us. Forward to real DNS. */ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Request for %s is forwarded to DNS\n", + "Request for `%s' is forwarded to DNS untouched.\n", p->queries[0].name); GNUNET_DNS_request_forward (rh); GNUNET_DNSPARSER_free_packet (p); @@ -337,37 +282,25 @@ handle_dns_request (void *cls, /** * Initialized the interceptor * - * @param zone the zone to work in - * @param key the prov key of the zone (can be null, needed for caching) + * @param gnu_zone the zone to work in * @param c the configuration * @return GNUNET_OK on success */ int -gns_interceptor_init (struct GNUNET_CRYPTO_ShortHashCode zone, - struct GNUNET_CRYPTO_EccPrivateKey *key, +GNS_interceptor_init (const struct GNUNET_CRYPTO_EccPublicKey *gnu_zone, const struct GNUNET_CONFIGURATION_Handle *c) { - GNUNET_log(GNUNET_ERROR_TYPE_INFO, - "DNS hijacking enabled... connecting to service.\n"); - our_zone = zone; - our_key = key; - /** - * Do gnunet dns init here - */ + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "DNS hijacking enabled. Connecting to DNS service.\n"); + zone = *gnu_zone; dns_handle = GNUNET_DNS_connect (c, GNUNET_DNS_FLAG_PRE_RESOLUTION, - &handle_dns_request, /* rh */ - NULL); /* Closure */ - - if (GNUNET_OK != - GNUNET_CONFIGURATION_get_value_time (c, "gns", - "DEFAULT_LOOKUP_TIMEOUT", - &default_lookup_timeout)) - default_lookup_timeout = GNUNET_TIME_UNIT_ZERO; + &handle_dns_request, + NULL); if (NULL == dns_handle) { - GNUNET_log(GNUNET_ERROR_TYPE_ERROR, - "Failed to connect to the dnsservice!\n"); + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + _("Failed to connect to the DNS service!\n")); return GNUNET_SYSERR; } return GNUNET_YES; @@ -378,13 +311,23 @@ gns_interceptor_init (struct GNUNET_CRYPTO_ShortHashCode zone, * Disconnect from interceptor */ void -gns_interceptor_stop () +GNS_interceptor_done () { + struct InterceptLookupHandle *ilh; + + while (NULL != (ilh = ilh_head)) + { + GNUNET_CONTAINER_DLL_remove (ilh_head, ilh_tail, ilh); + GNS_resolver_lookup_cancel (ilh->lookup); + GNUNET_DNS_request_drop (ilh->request_handle); + GNUNET_DNSPARSER_free_packet (ilh->packet); + GNUNET_free (ilh); + } if (NULL != dns_handle) { - GNUNET_DNS_disconnect(dns_handle); + GNUNET_DNS_disconnect (dns_handle); dns_handle = NULL; } } -/* end of gns_interceptor.c */ +/* end of gnunet-service-gns_interceptor.c */ diff --git a/src/gns/gnunet-service-gns_interceptor.h b/src/gns/gnunet-service-gns_interceptor.h index a1da4938b..92a154e2c 100644 --- a/src/gns/gnunet-service-gns_interceptor.h +++ b/src/gns/gnunet-service-gns_interceptor.h @@ -27,23 +27,22 @@ #include "gnunet_util_lib.h" + /** - * Initialize dns interceptor + * Initialize DNS interceptor * - * @param zone the zone - * @param key the private key of the local zone + * @param gnu_zone the zone we start lookups in * @param c the configuration * @return GNUNET_YES on success GNUNET_SYSERR on error */ int -gns_interceptor_init (struct GNUNET_CRYPTO_ShortHashCode zone, - struct GNUNET_CRYPTO_EccPrivateKey *key, +GNS_interceptor_init (const struct GNUNET_CRYPTO_EccPublicKey *gnu_zone, const struct GNUNET_CONFIGURATION_Handle *c); /** * Stops the interceptor */ void -gns_interceptor_stop (void); +GNS_interceptor_done (void); #endif diff --git a/src/gns/gnunet-service-gns_resolver.c b/src/gns/gnunet-service-gns_resolver.c index b01200d8e..fb334c1a0 100644 --- a/src/gns/gnunet-service-gns_resolver.c +++ b/src/gns/gnunet-service-gns_resolver.c @@ -36,7 +36,6 @@ #include "gns_protocol.h" #include "gnunet_gns_service.h" #include "gns_common.h" -#include "block_gns.h" #include "gns.h" #include "gnunet-service-gns_resolver.h" #ifndef WINDOWS @@ -44,6 +43,20 @@ #endif +#define DHT_OPERATION_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 60) + +#define GNUNET_GNS_DEFAULT_LOOKUP_TIMEOUT \ + GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 10) + +#define DHT_LOOKUP_TIMEOUT DHT_OPERATION_TIMEOUT + +#define DHT_GNS_REPLICATION_LEVEL 5 + +#define GNUNET_GNS_MAX_PARALLEL_LOOKUPS 500 + +#define GNUNET_GNS_MAX_NS_TASKS 500 + + /** * Default DHT timeout */ @@ -55,17 +68,406 @@ #define DHT_GNS_REPLICATION_LEVEL 5 +/* + * 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 + */ + struct GNUNET_CRYPTO_ShortHashCode zone; + + /** + * (local) name of the authority + */ + char name[GNUNET_DNSPARSER_MAX_LABEL_LENGTH]; + + /** + * was the ns entry fresh + */ + int fresh; +}; + + +/** + * handle to a resolution process + */ +struct ResolverHandle; + + +/** + * processor for a record lookup result + * + * @param cls the closure + * @param rd_count number of results + * @param rd result data + */ +typedef void (*RecordLookupProcessor) (void *cls, + uint32_t rd_count, + const struct GNUNET_NAMESTORE_RecordData *rd); + + +/** + * processor for a resolution result + * + * @param cls the closure + * @param rh the resolution handle + * @param rd_count number of results + * @param rd result data (array of 'rd_count' records) + */ +typedef void (*ResolutionResultProcessor) (void *cls, + struct ResolverHandle *rh, + uint32_t rd_count, + const struct GNUNET_NAMESTORE_RecordData *rd); + + +/** + * Resolution status indicator + */ +enum ResolutionStatus +{ + /** + * the name to lookup exists + */ + RSL_RECORD_EXISTS = 1, + + /** + * the name in the record expired + */ + RSL_RECORD_EXPIRED = 2, + + /** + * resolution timed out + */ + RSL_TIMED_OUT = 4, + + /** + * Found VPN delegation + */ + RSL_DELEGATE_VPN = 8, + + /** + * Found NS delegation + */ + RSL_DELEGATE_NS = 16, + + /** + * Found PKEY delegation + */ + RSL_DELEGATE_PKEY = 32, + + /** + * Found CNAME record + */ + RSL_CNAME_FOUND = 64, + + /** + * Found PKEY has been revoked + */ + RSL_PKEY_REVOKED = 128 +}; + + +/** + * Handle to a currenty pending resolution + * a ResolverHandle is passed to, for example + * resolve_record_ns to resolve a record in the namestore. + * On result (positive or negative) the ResolutionResultProcessor + * is called. + * If a timeout is set timeout_cont will be called. + * If no timeout is set (ie timeout forever) then background resolutions + * might be triggered. + */ +struct GNS_ResolverHandle +{ + + /** + * DLL + */ + struct ResolverHandle *next; + + /** + * DLL + */ + struct ResolverHandle *prev; + + /** + * Last record data found + */ + struct GNUNET_NAMESTORE_RecordData rd; + + /** + * Number of last record data found + */ + unsigned int rd_count; + + /** + * The name to resolve + */ + char name[GNUNET_DNSPARSER_MAX_NAME_LENGTH]; + + /** + * has this query been answered? how many matches + */ + int answered; + + /** + * Use only cache + */ + int only_cached; + + /** + * the authoritative zone to query + */ + struct GNUNET_CRYPTO_ShortHashCode authority; + + /** + * the name of the authoritative zone to query + */ + char authority_name[GNUNET_DNSPARSER_MAX_LABEL_LENGTH]; + + /** + * a handle for dht lookups. should be NULL if no lookups are in progress + */ + struct GNUNET_DHT_GetHandle *get_handle; + + /** + * timeout set for this lookup task + */ + struct GNUNET_TIME_Relative timeout; + + /** + * a handle to a vpn request + */ + struct GNUNET_VPN_RedirectionRequest *vpn_handle; + + /** + * a socket for a dns request + */ + struct GNUNET_NETWORK_Handle *dns_sock; + + /** + * a synthesized dns name + */ + char dns_name[GNUNET_DNSPARSER_MAX_NAME_LENGTH]; + + /** + * the authoritative dns zone + */ + char dns_zone[GNUNET_DNSPARSER_MAX_NAME_LENGTH]; + + /** + * the address of the DNS server FIXME not needed? + */ + struct sockaddr_in dns_addr; + + /** + * handle to the local stub resolver request + */ + struct GNUNET_RESOLVER_RequestHandle *dns_resolver_handle; + + /** + * select task for DNS + */ + GNUNET_SCHEDULER_TaskIdentifier dns_read_task; + + /** + * pointer to raw dns query payload FIXME needs to be freed/NULL + */ + char *dns_raw_packet; + + /** + * size of the raw dns query + */ + size_t dns_raw_packet_size; + + /** + * timeout task for the lookup + */ + GNUNET_SCHEDULER_TaskIdentifier timeout_task; + + /** + * continuation to call on timeout + */ + GNUNET_SCHEDULER_Task timeout_cont; + + /** + * closure for timeout cont + */ + void* timeout_cont_cls; + + /** + * 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; + + /** + * The provate local zone of this request + */ + struct GNUNET_CRYPTO_ShortHashCode private_local_zone; + + /** + * private key of an/our authoritative zone + * can be NULL but automatical PKEY import will not work + */ + struct GNUNET_CRYPTO_EccPrivateKey *priv_key; + + /** + * the heap node associated with this lookup, null if timeout is set + * used for DHT background lookups. + */ + struct GNUNET_CONTAINER_HeapNode *dht_heap_node; + + /** + * Id for resolution process + */ + unsigned long long id; + + /** + * Pending Namestore task + */ + struct GNUNET_NAMESTORE_QueueEntry *namestore_task; + +}; + + +/** + * Handle to a record lookup + */ +struct RecordLookupHandle +{ + /** + * the record type to look up + */ + int record_type; + + /** + * the name to look up + */ + char name[GNUNET_DNSPARSER_MAX_NAME_LENGTH]; + + /** + * Method to call on record resolution result + */ + RecordLookupProcessor proc; + + /** + * closure to pass to proc + */ + void* proc_cls; + +}; + + +/** + * Handle to a pseu lookup + */ +struct GetPseuAuthorityHandle +{ + /** + * DLL + */ + struct GetPseuAuthorityHandle *next; + + /** + * DLL + */ + struct GetPseuAuthorityHandle *prev; + + /** + * the name to store the zone under + */ + char name[GNUNET_DNSPARSER_MAX_LABEL_LENGTH]; + + /** + * test name to store the zone under + */ + char test_name[GNUNET_DNSPARSER_MAX_LABEL_LENGTH]; + + /** + * the zone of our authority + */ + struct GNUNET_CRYPTO_ShortHashCode our_zone; + + /** + * the private key of the zone to store the pseu in + */ + struct GNUNET_CRYPTO_EccPrivateKey *key; + + /** + * a handle for dht lookups. should be NULL if no lookups are in progress + */ + struct GNUNET_DHT_GetHandle *get_handle; + + /** + * timeout task for lookup + */ + GNUNET_SCHEDULER_TaskIdentifier timeout; + + /** + * Authority to shorten + */ + struct AuthorityChain *auth; + + /** + * handle to namestore request + */ + struct GNUNET_NAMESTORE_QueueEntry* namestore_task; +}; + + +/** + * Namestore queue entries in background + */ +struct NamestoreBGTask +{ + /** + * node in heap + */ + struct GNUNET_CONTAINER_HeapNode *node; + + /** + * queue entry + */ + struct GNUNET_NAMESTORE_QueueEntry *qe; +}; + + /** * Our handle to the namestore service */ static struct GNUNET_NAMESTORE_Handle *namestore_handle; -#ifndef WINDOWS /** * Our handle to the vpn service */ static struct GNUNET_VPN_Handle *vpn_handle; -#endif /** * Resolver handle to the dht @@ -93,25 +495,10 @@ static unsigned long long max_allowed_background_queries; static unsigned long long max_allowed_ns_tasks; /** - * Wheather or not to ignore pending records + * Whether or not to ignore pending records */ static int ignore_pending_records; -/** - * Our local zone - */ -static struct GNUNET_CRYPTO_ShortHashCode local_zone; - -/** - * Background shortening handles - */ -static struct GetPseuAuthorityHandle *gph_head; - -/** - * Background shortening handles - */ -static struct GetPseuAuthorityHandle *gph_tail; - /** * Resolver lookup list */ @@ -123,36 +510,16 @@ static struct ResolverHandle *rlh_head; static struct ResolverHandle *rlh_tail; /** - * Resolver shorten list + * Global configuration. */ -static struct ResolverHandle *nsh_head; +static const struct GNUNET_CONFIGURATION_Handle *cfg; /** - * Resolver shorten list + * a resolution identifier pool variable + * This is a non critical identifier useful for debugging */ -static struct ResolverHandle *nsh_tail; - -/** - * Resolver get auth list - */ -static struct ResolverHandle *nah_head; - -/** - * Resolver get auth list - */ -static struct ResolverHandle *nah_tail; - -/** - * Global configuration. - */ -static const struct GNUNET_CONFIGURATION_Handle *cfg; - -/** - * a resolution identifier pool variable - * This is a non critical identifier useful for debugging - */ -static unsigned long long rid_gen; - +static unsigned long long rid_gen; + /** * Check if name is in srv format (_x._y.xxx) @@ -344,245 +711,6 @@ process_pseu_result (struct GetPseuAuthorityHandle* gph, } -/** - * Handle timeout for dht request - * - * @param cls the request handle as closure - * @param tc the task context - */ -static void -handle_auth_discovery_timeout (void *cls, - const struct GNUNET_SCHEDULER_TaskContext *tc) -{ - struct GetPseuAuthorityHandle* gph = cls; - - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "GNS_GET_AUTH: dht lookup for query PSEU timed out.\n"); - GNUNET_DHT_get_stop (gph->get_handle); - gph->get_handle = NULL; - process_pseu_result (gph, NULL); -} - - -/** - * Function called when we find a PSEU entry in the 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_auth_discovery_dht_result (void* cls, - struct GNUNET_TIME_Absolute exp, - const struct 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 GetPseuAuthorityHandle* gph = cls; - struct GNSNameRecordBlock *nrb; - const char* rd_data = data; - char* name; - int num_records; - size_t rd_size; - int i; - - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "GNS_GET_AUTH: got dht result (size=%d)\n", size); - - /* stop lookup and timeout task */ - GNUNET_DHT_get_stop (gph->get_handle); - gph->get_handle = NULL; - GNUNET_SCHEDULER_cancel (gph->timeout); - - if (NULL == data) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "GNS_GET_AUTH: got dht result null!\n", size); - free_get_pseu_authority_handle (gph); - return; - } - - nrb = (struct GNSNameRecordBlock*)data; - 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, - "GNS_GET_AUTH: Error deserializing data!\n"); - } - else - { - for (i=0; i < num_records; i++) - { - if ((strcmp (name, GNUNET_GNS_MASTERZONE_STR) == 0) && - (rd[i].record_type == GNUNET_NAMESTORE_TYPE_PSEU)) - { - /* found pseu */ - process_pseu_result (gph, (char*)rd[i].data); - return; - } - } - } - } - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "GNS_GET_AUTH: finished shorten, no results!\n"); - process_pseu_result (gph, NULL); -} - - -/** - * Process PSEU discovery for shorten via namestore - * - * @param cls the GetPseuAuthorityHandle - * @param key the public key - * @param expiration recorddata expiration - * @param name the looked up name - * @param rd_count number of records in set - * @param rd record data - * @param signature the signature - */ -static void -process_auth_discovery_ns_result (void* cls, - const struct GNUNET_CRYPTO_EccPublicKey *key, - struct GNUNET_TIME_Absolute expiration, - const char *name, - unsigned int rd_count, - const struct GNUNET_NAMESTORE_RecordData *rd, - const struct GNUNET_CRYPTO_EccSignature *signature) -{ - struct GetPseuAuthorityHandle* gph = cls; - struct GNUNET_HashCode lookup_key; - unsigned int i; - uint32_t xquery; - - gph->namestore_task = NULL; - /* no pseu found */ - if (0 == rd_count) - { - GNUNET_GNS_get_key_for_record (GNUNET_GNS_TLD_PLUS, &gph->auth->zone, &lookup_key); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "GNS_AUTO_PSEU: starting dht lookup for %s with key: %s\n", - GNUNET_GNS_TLD_PLUS, - GNUNET_h2s (&lookup_key)); - - gph->timeout = GNUNET_SCHEDULER_add_delayed (DHT_LOOKUP_TIMEOUT, - &handle_auth_discovery_timeout, gph); - - xquery = htonl (GNUNET_NAMESTORE_TYPE_PSEU); - - GNUNET_assert (gph->get_handle == NULL); - - gph->get_handle = GNUNET_DHT_get_start (dht_handle, - GNUNET_BLOCK_TYPE_GNS_NAMERECORD, - &lookup_key, - DHT_GNS_REPLICATION_LEVEL, - GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE, - &xquery, - sizeof(xquery), - &process_auth_discovery_dht_result, - gph); - return; - } - - for (i=0; i < rd_count; i++) - { - if (0 != (strcmp (name, GNUNET_GNS_TLD_PLUS))) - continue; - - if (rd[i].record_type != GNUNET_NAMESTORE_TYPE_PSEU) - continue; - - /* found pseu */ - process_pseu_result (gph, (char*)rd[i].data); - return; - } - - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "GNS_GET_AUTH: no pseu in namestore!\n"); - process_pseu_result (gph, NULL); -} - - -/** - * Callback called by namestore for a zone to name - * result - * - * @param cls the closure - * @param zone_key the zone we queried - * @param expire the expiration time of the name - * @param name the name found or NULL - * @param rd_len number of records for the name - * @param rd the record data (PKEY) for the name - * @param signature the signature for the record data - */ -static void -process_zone_to_name_discover (void *cls, - const struct GNUNET_CRYPTO_EccPublicKey *zone_key, - struct GNUNET_TIME_Absolute expire, - const char *name, - unsigned int rd_len, - const struct GNUNET_NAMESTORE_RecordData *rd, - const struct GNUNET_CRYPTO_EccSignature *signature) -{ - struct GetPseuAuthorityHandle* gph = cls; - - gph->namestore_task = NULL; - if (0 == rd_len) - { - gph->namestore_task = GNUNET_NAMESTORE_lookup_record (namestore_handle, - &gph->auth->zone, - GNUNET_GNS_MASTERZONE_STR, - GNUNET_NAMESTORE_TYPE_PSEU, - &process_auth_discovery_ns_result, - gph); - return; - } - /* we found a match in our own zone */ - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "GNS_AUTO_PSEU: name for zone in our root %s\n", name); - free_get_pseu_authority_handle (gph); -} - - -/** - * Callback that shortens authorities - * - * @param gph the handle to the shorten request - */ -static void -shorten_authority_chain (struct GetPseuAuthorityHandle *gph) -{ - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "GNS_AUTO_PSEU: New authority %s discovered\n", - gph->auth->name); - gph->namestore_task = GNUNET_NAMESTORE_zone_to_name (namestore_handle, - &gph->our_zone, - &gph->auth->zone, - &process_zone_to_name_discover, - gph); -} - - /** * Start shortening algorithm using auth as * authority chain @@ -631,9 +759,8 @@ start_shorten (struct AuthorityChain *auth, * @return GNUNET_OK on success */ int -gns_resolver_init (struct GNUNET_NAMESTORE_Handle *nh, +GNS_resolver_init (struct GNUNET_NAMESTORE_Handle *nh, struct GNUNET_DHT_Handle *dh, - struct GNUNET_CRYPTO_ShortHashCode lz, const struct GNUNET_CONFIGURATION_Handle *c, unsigned long long max_bg_queries, int ignore_pending) @@ -657,6 +784,7 @@ gns_resolver_init (struct GNUNET_NAMESTORE_Handle *nh, return GNUNET_OK; } + /** * finish lookup * @@ -744,7 +872,7 @@ finish_get_auth (struct ResolverHandle *rh, * Shutdown resolver */ void -gns_resolver_cleanup () +GNS_resolver_done () { struct GetPseuAuthorityHandle *tmp; struct ResolverHandle *rh; @@ -3311,25 +3439,21 @@ resolve_delegation_ns (struct ResolverHandle *rh) * calls lookup result processor on result * * @param zone the root zone - * @param pzone the private local zone * @param record_type the record type to look up * @param name the name to look up - * @param key a private key for use with PSEU import (can be NULL) - * @param timeout timeout for resolution + * @param shorten_key a private key for use with PSEU import (can be NULL) * @param only_cached GNUNET_NO to only check locally not DHT for performance * @param proc the processor to call on result - * @param cls the closure to pass to proc + * @param proc_cls the closure to pass to @a proc */ void -gns_resolver_lookup_record (struct GNUNET_CRYPTO_ShortHashCode zone, - struct GNUNET_CRYPTO_ShortHashCode pzone, - uint32_t record_type, - const char* name, - struct GNUNET_CRYPTO_EccPrivateKey *key, - struct GNUNET_TIME_Relative timeout, - int only_cached, - RecordLookupProcessor proc, - void* cls) +GNS_resolver_lookup (const struct GNUNET_CRYPTO_EccPublicKey * zone, + uint32_t record_type, + const char* name, + struct GNUNET_CRYPTO_EccPrivateKey *shorten_key, + int only_cached, + RecordLookupProcessor proc, + void *proc_cls) { struct ResolverHandle *rh; struct RecordLookupHandle* rlh; @@ -3479,848 +3603,5 @@ gns_resolver_lookup_record (struct GNUNET_CRYPTO_ShortHashCode zone, resolve_delegation_ns (rh); } -/******** END Record Resolver ***********/ - -static void -finish_shorten (struct ResolverHandle *rh, - struct NameShortenHandle *nsh) -{ - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Sending %s as shorten result\n", nsh->result); - nsh->proc (nsh->proc_cls, nsh->result); - GNUNET_CONTAINER_DLL_remove (nsh_head, nsh_tail, rh); - GNUNET_free (nsh); - free_resolver_handle (rh); -} - - -/** - * Callback calles by namestore for a zone to name - * result - * - * @param cls the closure - * @param zone_key the zone we queried - * @param expire the expiration time of the name - * @param name the name found or NULL - * @param rd_len number of records for the name - * @param rd the record data (PKEY) for the name - * @param signature the signature for the record data - */ -static void -process_zone_to_name_shorten_root (void *cls, - const struct GNUNET_CRYPTO_EccPublicKey *zone_key, - struct GNUNET_TIME_Absolute expire, - const char *name, - unsigned int rd_len, - const struct GNUNET_NAMESTORE_RecordData *rd, - const struct GNUNET_CRYPTO_EccSignature *signature); - - -/** - * Callback called by namestore for a zone to name - * result - * - * @param cls the closure - * @param zone_key the zone we queried - * @param expire the expiration time of the name - * @param name the name found or NULL - * @param rd_len number of records for the name - * @param rd the record data (PKEY) for the name - * @param signature the signature for the record data - */ -static void -process_zone_to_name_shorten_shorten (void *cls, - const struct GNUNET_CRYPTO_EccPublicKey *zone_key, - struct GNUNET_TIME_Absolute expire, - const char *name, - unsigned int rd_len, - const struct GNUNET_NAMESTORE_RecordData *rd, - const struct GNUNET_CRYPTO_EccSignature *signature) -{ - struct ResolverHandle *rh = cls; - struct NameShortenHandle* nsh = rh->proc_cls; - struct AuthorityChain *next_authority; - - char result[GNUNET_DNSPARSER_MAX_NAME_LENGTH]; - char tmp_name[GNUNET_DNSPARSER_MAX_NAME_LENGTH]; - size_t answer_len; - - rh->namestore_task = NULL; - /* we found a match in our own root zone */ - if (rd_len != 0) - { - answer_len = strlen(rh->name) + strlen(name) + strlen(GNUNET_GNS_TLD) + 3; - memset(result, 0, answer_len); - - if (strlen(rh->name) > 0) - { - sprintf (result, "%s.%s.%s.%s", - rh->name, name, - nsh->shorten_zone_name, - GNUNET_GNS_TLD); - } - else - { - sprintf (result, "%s.%s.%s", name, - nsh->shorten_zone_name, - GNUNET_GNS_TLD); - } - - GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, - "Found shorten result %s\n", result); - if (strlen (nsh->result) > strlen (result)) - strcpy (nsh->result, result); - } - else if (GNUNET_CRYPTO_short_hash_cmp(&rh->authority_chain_head->zone, - nsh->shorten_zone) == 0) - { - /** - * This is our zone append .gads unless name is empty - * (it shouldn't be, usually FIXME what happens if we - * shorten to our zone to a "" record??) - */ - - sprintf (result, "%s.%s.%s", - rh->name, - nsh->shorten_zone_name, - GNUNET_GNS_TLD); - GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, - "Our zone: Found %s as shorten result\n", result); - - if (strlen (nsh->result) > strlen (result)) - strcpy (nsh->result, result); - //nsh->proc(nsh->proc_cls, result); - //GNUNET_free(nsh); - //free_resolver_handle(rh); - //return; - } - - - /** - * No PSEU found. - * continue with next authority if exists - */ - if (NULL == rh->authority_chain_head->next) - { - finish_shorten (rh, nsh); - return; - } - next_authority = rh->authority_chain_head; - - if (0 == strcmp (rh->name, "")) - strcpy (tmp_name, next_authority->name); - else - GNUNET_snprintf(tmp_name, GNUNET_DNSPARSER_MAX_NAME_LENGTH, - "%s.%s", rh->name, next_authority->name); - - strcpy(rh->name, tmp_name); - GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, - "No PSEU found for authority %s. Promoting back: %s\n", - next_authority->name, rh->name); - - GNUNET_CONTAINER_DLL_remove(rh->authority_chain_head, - rh->authority_chain_tail, - next_authority); - - GNUNET_free (next_authority); - - rh->namestore_task = GNUNET_NAMESTORE_zone_to_name (namestore_handle, - &rh->authority_chain_tail->zone, - &rh->authority_chain_head->zone, - &process_zone_to_name_shorten_root, - rh); -} - - -/** - * Callback calles by namestore for a zone to name - * result - * - * @param cls the closure - * @param zone_key the zone we queried - * @param expire the expiration time of the name - * @param name the name found or NULL - * @param rd_len number of records for the name - * @param rd the record data (PKEY) for the name - * @param signature the signature for the record data - */ -static void -process_zone_to_name_shorten_private (void *cls, - const struct GNUNET_CRYPTO_EccPublicKey *zone_key, - struct GNUNET_TIME_Absolute expire, - const char *name, - unsigned int rd_len, - const struct GNUNET_NAMESTORE_RecordData *rd, - const struct GNUNET_CRYPTO_EccSignature *signature) -{ - struct ResolverHandle *rh = cls; - struct NameShortenHandle* nsh = rh->proc_cls; - struct AuthorityChain *next_authority; - - char result[GNUNET_DNSPARSER_MAX_NAME_LENGTH]; - char tmp_name[GNUNET_DNSPARSER_MAX_NAME_LENGTH]; - size_t answer_len; - - rh->namestore_task = NULL; - /* we found a match in our own root zone */ - if (rd_len != 0) - { - answer_len = strlen(rh->name) + strlen(name) + strlen(GNUNET_GNS_TLD) + 3; - memset(result, 0, answer_len); - - if (strlen(rh->name) > 0) - { - sprintf (result, "%s.%s.%s", rh->name, name, GNUNET_GNS_TLD); - } - else - { - sprintf (result, "%s.%s", name, GNUNET_GNS_TLD); - } - - GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, - "Found shorten result %s\n", result); - if (strlen (nsh->result) > strlen (result)) - strcpy (nsh->result, result); - } - else if (GNUNET_CRYPTO_short_hash_cmp(&rh->authority_chain_head->zone, - nsh->private_zone) == 0) - { - /** - * This is our zone append .gads unless name is empty - * (it shouldn't be, usually FIXME what happens if we - * shorten to our zone to a "" record??) - */ - - sprintf (result, "%s.%s.%s", - rh->name, nsh->private_zone_name, GNUNET_GNS_TLD); - GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, - "Our private zone: Found %s as shorten result %s\n", result); - if (strlen (nsh->result) > strlen (result)) - strcpy (nsh->result, result); - } - - if (0 != strcmp (nsh->shorten_zone_name, "")) - { - /* backtrack authorities for names in priv zone */ - rh->namestore_task = GNUNET_NAMESTORE_zone_to_name (namestore_handle, - nsh->shorten_zone, - &rh->authority_chain_head->zone, - &process_zone_to_name_shorten_shorten, - rh); - } - else - { - /** - * No PSEU found. - * continue with next authority if exists - */ - if (NULL == rh->authority_chain_head->next) - { - finish_shorten (rh, nsh); - return; - } - next_authority = rh->authority_chain_head; - - if (0 == strcmp (rh->name, "")) - strcpy (tmp_name, next_authority->name); - else - GNUNET_snprintf(tmp_name, GNUNET_DNSPARSER_MAX_NAME_LENGTH, - "%s.%s", rh->name, next_authority->name); - - strcpy(rh->name, tmp_name); - GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, - "No PSEU found for authority %s. Promoting back: %s\n", - next_authority->name, rh->name); - - GNUNET_CONTAINER_DLL_remove(rh->authority_chain_head, - rh->authority_chain_tail, - next_authority); - - GNUNET_free (next_authority); - - rh->namestore_task = GNUNET_NAMESTORE_zone_to_name (namestore_handle, - &rh->authority_chain_tail->zone, - &rh->authority_chain_head->zone, - &process_zone_to_name_shorten_root, - rh); - } -} - - -/** - * Callback calles by namestore for a zone to name - * result - * - * @param cls the closure - * @param zone_key the zone we queried - * @param expire the expiration time of the name - * @param name the name found or NULL - * @param rd_len number of records for the name - * @param rd the record data (PKEY) for the name - * @param signature the signature for the record data - */ -static void -process_zone_to_name_shorten_root (void *cls, - const struct GNUNET_CRYPTO_EccPublicKey *zone_key, - struct GNUNET_TIME_Absolute expire, - const char *name, - unsigned int rd_len, - const struct GNUNET_NAMESTORE_RecordData *rd, - const struct GNUNET_CRYPTO_EccSignature *signature) -{ - struct ResolverHandle *rh = cls; - struct NameShortenHandle* nsh = rh->proc_cls; - struct AuthorityChain *next_authority; - char result[GNUNET_DNSPARSER_MAX_NAME_LENGTH]; - char tmp_name[GNUNET_DNSPARSER_MAX_NAME_LENGTH]; - size_t answer_len; - - rh->namestore_task = NULL; - /* we found a match in our own root zone */ - if (rd_len != 0) - { - answer_len = strlen(rh->name) + strlen(name) + strlen(GNUNET_GNS_TLD) + 3; - memset(result, 0, answer_len); - - if (strlen(rh->name) > 0) - { - sprintf (result, "%s.%s.%s", rh->name, name, GNUNET_GNS_TLD); - } - else - { - sprintf (result, "%s.%s", name, GNUNET_GNS_TLD); - } - - GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, - "Found shorten result %s\n", result); - if (strlen (nsh->result) > strlen (result)) - strcpy (nsh->result, result); - } - else if (GNUNET_CRYPTO_short_hash_cmp(&rh->authority_chain_head->zone, - nsh->root_zone) == 0) - { - /** - * This is our zone append .gads unless name is empty - * (it shouldn't be, usually FIXME what happens if we - * shorten to our zone to a "" record??) - */ - - sprintf (result, "%s.%s", rh->name, GNUNET_GNS_TLD); - GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, - "Our zone: Found %s as shorten result\n", result); - if (strlen (nsh->result) > strlen (result)) - strcpy (nsh->result, result); - } - - if (NULL != nsh->private_zone) - { - /* backtrack authorities for names in priv zone */ - rh->namestore_task = GNUNET_NAMESTORE_zone_to_name (namestore_handle, - nsh->private_zone, - &rh->authority_chain_head->zone, - &process_zone_to_name_shorten_private, - rh); - } - else if (NULL != nsh->shorten_zone) - { - /* backtrack authorities for names in shorten zone */ - rh->namestore_task = GNUNET_NAMESTORE_zone_to_name (namestore_handle, - nsh->shorten_zone, - &rh->authority_chain_head->zone, - &process_zone_to_name_shorten_shorten, - rh); - } - else - { - /** - * No PSEU found. - * continue with next authority if exists - */ - if (NULL == rh->authority_chain_head->next) - { - finish_shorten (rh, nsh); - return; - } - next_authority = rh->authority_chain_head; - - if (0 == strcmp (rh->name, "")) - strcpy (tmp_name, next_authority->name); - else - GNUNET_snprintf(tmp_name, GNUNET_DNSPARSER_MAX_NAME_LENGTH, - "%s.%s", rh->name, next_authority->name); - - strcpy(rh->name, tmp_name); - GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, - "No PSEU found for authority %s. Promoting back: %s\n", - next_authority->name, rh->name); - - GNUNET_CONTAINER_DLL_remove(rh->authority_chain_head, - rh->authority_chain_tail, - next_authority); - - GNUNET_free (next_authority); - - rh->namestore_task = GNUNET_NAMESTORE_zone_to_name (namestore_handle, - &rh->authority_chain_tail->zone, - &rh->authority_chain_head->zone, - &process_zone_to_name_shorten_root, - 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) - */ -static 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[GNUNET_DNSPARSER_MAX_NAME_LENGTH]; - - nsh = (struct NameShortenHandle *)cls; - rh->namestore_task = NULL; - /** - * 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); - memset(result, 0, sizeof (result)); - - if (0 == GNUNET_CRYPTO_short_hash_cmp(&rh->authority_chain_head->zone, - nsh->root_zone)) - { - /** - * This is our zone append .gads unless name is empty - * (it shouldn't be, usually FIXME what happens if we - * shorten to our zone to a "" record??) - */ - - sprintf (result, "%s.%s", rh->name, GNUNET_GNS_TLD); - GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, - "Our zone: Found %s as shorten result\n", result); - - if (strlen (nsh->result) > strlen (result)) - strcpy (nsh->result, result); - - } - else if (NULL != nsh->private_zone) - { - /** - * This is our zone append .gads unless name is empty - * (it shouldn't be, usually FIXME what happens if we - * shorten to our zone to a "" record??) - */ - if (GNUNET_CRYPTO_short_hash_cmp(&rh->authority_chain_head->zone, - nsh->private_zone) == 0) - { - - sprintf (result, "%s.%s.%s", - rh->name, nsh->private_zone_name, GNUNET_GNS_TLD); - GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, - "Our zone: Found %s as shorten result in private zone %s\n", - result); - - if (strlen (nsh->result) > strlen (result)) - strcpy (nsh->result, result); - } - } - else if (NULL != nsh->shorten_zone) - { - /** - * This is our zone append .gads unless name is empty - * (it shouldn't be, usually FIXME what happens if we - * shorten to our zone to a "" record??) - */ - if (GNUNET_CRYPTO_short_hash_cmp(&rh->authority_chain_head->zone, - nsh->shorten_zone) == 0) - { - sprintf (result, "%s.%s.%s", - rh->name, nsh->private_zone_name, GNUNET_GNS_TLD); - GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, - "Our zone: Found %s as shorten result in shorten zone\n", - result); - - if (strlen (nsh->result) > strlen (result)) - strcpy (nsh->result, result); - } - } - - - /* backtrack authorities for names */ - rh->namestore_task = GNUNET_NAMESTORE_zone_to_name (namestore_handle, - nsh->root_zone, - &rh->authority_chain_head->zone, - &process_zone_to_name_shorten_root, - rh); - -} - - -/** - * Callback calles by namestore for a zone to name - * result - * - * @param cls the closure - * @param zone_key the zone we queried - * @param expire the expiration time of the name - * @param name the name found or NULL - * @param rd_len number of records for the name - * @param rd the record data (PKEY) for the name - * @param signature the signature for the record data - */ -static void -process_zone_to_name_zkey (void *cls, - const struct GNUNET_CRYPTO_EccPublicKey *zone_key, - struct GNUNET_TIME_Absolute expire, - const char *name, - unsigned int rd_len, - const struct GNUNET_NAMESTORE_RecordData *rd, - const struct GNUNET_CRYPTO_EccSignature *signature) -{ - struct ResolverHandle *rh = cls; - struct NameShortenHandle *nsh = rh->proc_cls; - char new_name[GNUNET_DNSPARSER_MAX_NAME_LENGTH]; - - rh->namestore_task = NULL; - - /* zkey not in our zone */ - if (name == NULL) - { - /** - * In this case we have not given this PKEY a name (yet) - * It is either just not in our zone or not even cached - * Since we do not know at this point we will not try to shorten - * because PKEY import will happen if the user follows the zkey - * link. - */ - GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, - "No name found for zkey %s returning verbatim!\n", nsh->result); - /*if (strcmp(rh->name, "") != 0) - GNUNET_snprintf(new_name, GNUNET_DNSPARSER_MAX_NAME_LENGTH, "%s.%s.%s", - rh->name, enc, GNUNET_GNS_TLD_ZKEY); - else - GNUNET_snprintf(new_name, GNUNET_DNSPARSER_MAX_NAME_LENGTH, "%s.%s", - enc, GNUNET_GNS_TLD_ZKEY); - - strcpy (nsh->result, new_name);*/ - - finish_shorten (rh, nsh); - return; - } - - if (strcmp(rh->name, "") != 0) - GNUNET_snprintf(new_name, GNUNET_DNSPARSER_MAX_NAME_LENGTH, "%s.%s", - rh->name, name); - else - strcpy(new_name, name); - - GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, - "Continue shorten for %s!\n", new_name); - - strcpy(rh->name, new_name); - - rh->authority_chain_head = GNUNET_malloc(sizeof(struct AuthorityChain)); - rh->authority_chain_tail = rh->authority_chain_head; - rh->authority_chain_head->zone = rh->authority; - - - /* Start delegation resolution in our namestore */ - resolve_delegation_ns (rh); -} - - -/** - * Shorten api from resolver - * - * @param zone the root zone to use - * @param pzone the private zone to use - * @param szone the shorten zone to use - * @param name the name to shorten - * @param private_zone_name name of the private zone - * @param shorten_zone_name name of the shorten zone - * @param proc the processor to call with result - * @param proc_cls closure to pass to proc - */ -void -gns_resolver_shorten_name (struct GNUNET_CRYPTO_ShortHashCode *zone, - struct GNUNET_CRYPTO_ShortHashCode *pzone, - struct GNUNET_CRYPTO_ShortHashCode *szone, - const char* name, - const char* private_zone_name, - const char* shorten_zone_name, - ShortenResultProcessor proc, - void* proc_cls) -{ - struct ResolverHandle *rh; - struct NameShortenHandle *nsh; - char string_hash[GNUNET_DNSPARSER_MAX_LABEL_LENGTH]; - struct GNUNET_CRYPTO_ShortHashCode zkey; - char nzkey[GNUNET_DNSPARSER_MAX_LABEL_LENGTH]; - char* nzkey_ptr = nzkey; - - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Starting shorten for %s!\n", name); - - if (is_canonical ((char*)name) == GNUNET_YES) - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "%s is canonical. Returning verbatim\n", name); - proc (proc_cls, name); - return; - } - - nsh = GNUNET_malloc (sizeof (struct NameShortenHandle)); - nsh->proc = proc; - nsh->proc_cls = proc_cls; - nsh->root_zone = zone; - nsh->private_zone = pzone; - nsh->shorten_zone = szone; - strcpy (nsh->private_zone_name, private_zone_name); - strcpy (nsh->shorten_zone_name, shorten_zone_name); - strcpy (nsh->result, name); - - rh = GNUNET_malloc (sizeof (struct ResolverHandle)); - rh->authority = *zone; - rh->id = rid_gen++; - rh->proc = &handle_delegation_ns_shorten; - rh->proc_cls = nsh; - rh->private_local_zone = *zone; - - GNUNET_CONTAINER_DLL_insert (nsh_head, nsh_tail, rh); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Checking for TLD...\n"); - if (is_zkey_tld (name) == GNUNET_YES) - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "TLD is zkey\n"); - /** - * This is a zkey tld - * build hash and use as initial authority - * FIXME sscanf - */ - memset (rh->name, 0, - strlen (name)-strlen (GNUNET_GNS_TLD_ZKEY)); - memcpy (rh->name, name, - strlen(name)-strlen (GNUNET_GNS_TLD_ZKEY) - 1); - pop_tld (rh->name, string_hash); - - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "ZKEY is %s!\n", string_hash); - - GNUNET_STRINGS_utf8_toupper (string_hash, &nzkey_ptr); - - if (GNUNET_OK != GNUNET_CRYPTO_short_hash_from_string (nzkey, - &zkey)) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Cannot convert ZKEY %s to hash!\n", nzkey); - GNUNET_CONTAINER_DLL_remove (nsh_head, nsh_tail, rh); - GNUNET_free (rh); - GNUNET_free (nsh); - proc (proc_cls, name); - return; - } - rh->namestore_task = GNUNET_NAMESTORE_zone_to_name (namestore_handle, - zone, //ours - &zkey, - &process_zone_to_name_zkey, - rh); - return; - - } - else if (is_gads_tld (name) == GNUNET_YES) - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "TLD is gnunet\n"); - /** - * Presumably GNUNET tld - */ - memset (rh->name, 0, - strlen (name)-strlen (GNUNET_GNS_TLD)); - memcpy (rh->name, name, - strlen (name)-strlen (GNUNET_GNS_TLD) - 1); - } - else - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Unknown TLD in %s\n", name); - GNUNET_CONTAINER_DLL_remove (nsh_head, nsh_tail, rh); - GNUNET_free (rh); - GNUNET_free (nsh); - proc (proc_cls, name); - return; - } - - rh->authority_chain_head = GNUNET_malloc (sizeof (struct AuthorityChain)); - rh->authority_chain_tail = rh->authority_chain_head; - rh->authority_chain_head->zone = *zone; - - /* Start delegation resolution in our namestore */ - resolve_delegation_ns (rh); -} - -/*********** END NAME SHORTEN ********************/ - -/** - * Conclude get authority lookup - * - * @param rh resolver handle - * @param nah get authority lookup handle - */ -static void -finish_get_auth (struct ResolverHandle *rh, - struct GetNameAuthorityHandle *nah) -{ - GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, - "Got authority result %s\n", nah->result); - - nah->proc (nah->proc_cls, nah->result); - GNUNET_CONTAINER_DLL_remove (nah_head, nah_tail, rh); - GNUNET_free (nah); - free_resolver_handle (rh); -} - - -/** - * 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) - */ -static 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 = rh->proc_cls; - 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); - - GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, - "Building response!\n"); - if (is_canonical (rh->name) == GNUNET_YES) - { - /** - * 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; - memset(nah->result, 0, answer_len); - if (0 != strcmp (rh->name, "")) - strcpy(nah->result, nah->name + strlen(rh->name) + 1); - else - strcpy(nah->result, nah->name); - - finish_get_auth (rh, nah); - } - else - { - GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, - "Unable to resolve authority for remaining %s!\n", rh->name); - strcpy(nah->result, ""); - finish_get_auth (rh, nah); - } -} - - -/** - * Tries to resolve the authority for name - * in our namestore - * - * @param zone the root zone to look up for - * @param pzone the private local zone - * @param name the name to lookup up - * @param proc the processor to call when finished - * @param proc_cls the closure to pass to the processor - */ -void -gns_resolver_get_authority(struct GNUNET_CRYPTO_ShortHashCode zone, - struct GNUNET_CRYPTO_ShortHashCode pzone, - const char* name, - GetAuthorityResultProcessor proc, - void* proc_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->id = rid_gen++; - rh->private_local_zone = pzone; - - GNUNET_CONTAINER_DLL_insert (nah_head, nah_tail, rh); - - if (strcmp(GNUNET_GNS_TLD, name) == 0) - { - strcpy(rh->name, "\0"); - } - else - { - memset(rh->name, 0, - strlen(name)-strlen(GNUNET_GNS_TLD)); - memcpy(rh->name, name, - strlen(name)-strlen(GNUNET_GNS_TLD) - 1); - } - - memset(nah->name, 0, - strlen(name)+1); - strcpy(nah->name, name); - - 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 = proc_cls; - strcpy (nah->result, ""); - - /* Start delegation resolution in our namestore */ - resolve_delegation_ns(rh); - -} - -/******** END GET AUTHORITY *************/ /* end of gnunet-service-gns_resolver.c */ diff --git a/src/gns/gnunet-service-gns_resolver.h b/src/gns/gnunet-service-gns_resolver.h index 1b10297c2..bc83b6b3d 100644 --- a/src/gns/gnunet-service-gns_resolver.h +++ b/src/gns/gnunet-service-gns_resolver.h @@ -1,6 +1,6 @@ /* This file is part of GNUnet. - (C) 2009, 2010, 2011, 2012 Christian Grothoff (and other contributing authors) + (C) 2009-2013 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 @@ -24,514 +24,16 @@ */ #ifndef GNS_RESOLVER_H #define GNS_RESOLVER_H - #include "gns.h" #include "gnunet_dht_service.h" -#define DHT_OPERATION_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 60) - -#define GNUNET_GNS_DEFAULT_LOOKUP_TIMEOUT \ - GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 10) - -#define DHT_LOOKUP_TIMEOUT DHT_OPERATION_TIMEOUT - -#define DHT_GNS_REPLICATION_LEVEL 5 - -#define GNUNET_GNS_MAX_PARALLEL_LOOKUPS 500 - -#define GNUNET_GNS_MAX_NS_TASKS 500 - -/* - * 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 - */ - struct GNUNET_CRYPTO_ShortHashCode zone; - - /** - * (local) name of the authority - */ - char name[GNUNET_DNSPARSER_MAX_LABEL_LENGTH]; - - /** - * was the ns entry fresh - */ - int fresh; -}; - - -/** - * handle to a resolution process - */ -struct ResolverHandle; - /** - * processor for a record lookup result - * - * @param cls the closure - * @param rd_count number of results - * @param rd result 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 of the authority - */ -typedef void (*GetAuthorityResultProcessor) (void *cls, - const char* name); - -/** - * processor for a resolution result - * - * @param cls the closure - * @param rh the resolution handle - * @param rd_count number of results - * @param rd result data (array of 'rd_count' records) - */ -typedef void (*ResolutionResultProcessor) (void *cls, - struct ResolverHandle *rh, - uint32_t rd_count, - const struct GNUNET_NAMESTORE_RecordData *rd); - - -/** - * Resolution status indicator - */ -enum ResolutionStatus -{ - /** - * the name to lookup exists - */ - RSL_RECORD_EXISTS = 1, - - /** - * the name in the record expired - */ - RSL_RECORD_EXPIRED = 2, - - /** - * resolution timed out - */ - RSL_TIMED_OUT = 4, - - /** - * Found VPN delegation - */ - RSL_DELEGATE_VPN = 8, - - /** - * Found NS delegation - */ - RSL_DELEGATE_NS = 16, - - /** - * Found PKEY delegation - */ - RSL_DELEGATE_PKEY = 32, - - /** - * Found CNAME record - */ - RSL_CNAME_FOUND = 64, - - /** - * Found PKEY has been revoked - */ - RSL_PKEY_REVOKED = 128 -}; - -/** - * Handle to a currenty pending resolution - * a ResolverHandle is passed to, for example - * resolve_record_ns to resolve a record in the namestore. - * On result (positive or negative) the ResolutionResultProcessor - * is called. - * If a timeout is set timeout_cont will be called. - * If no timeout is set (ie timeout forever) then background resolutions - * might be triggered. - */ -struct ResolverHandle -{ - - /** - * DLL - */ - struct ResolverHandle *next; - - /** - * DLL - */ - struct ResolverHandle *prev; - - /** - * Last record data found - */ - struct GNUNET_NAMESTORE_RecordData rd; - - /** - * Number of last record data found - */ - unsigned int rd_count; - - /** - * The name to resolve - */ - char name[GNUNET_DNSPARSER_MAX_NAME_LENGTH]; - - /** - * has this query been answered? how many matches - */ - int answered; - - /** - * Use only cache - */ - int only_cached; - - /** - * the authoritative zone to query - */ - struct GNUNET_CRYPTO_ShortHashCode authority; - - /** - * the name of the authoritative zone to query - */ - char authority_name[GNUNET_DNSPARSER_MAX_LABEL_LENGTH]; - - /** - * a handle for dht lookups. should be NULL if no lookups are in progress - */ - struct GNUNET_DHT_GetHandle *get_handle; - - /** - * timeout set for this lookup task - */ - struct GNUNET_TIME_Relative timeout; - - /** - * a handle to a vpn request - */ - struct GNUNET_VPN_RedirectionRequest *vpn_handle; - - /** - * a socket for a dns request - */ - struct GNUNET_NETWORK_Handle *dns_sock; - - /** - * a synthesized dns name - */ - char dns_name[GNUNET_DNSPARSER_MAX_NAME_LENGTH]; - - /** - * the authoritative dns zone - */ - char dns_zone[GNUNET_DNSPARSER_MAX_NAME_LENGTH]; - - /** - * the address of the DNS server FIXME not needed? - */ - struct sockaddr_in dns_addr; - - /** - * handle to the local stub resolver request - */ - struct GNUNET_RESOLVER_RequestHandle *dns_resolver_handle; - - /** - * select task for DNS - */ - GNUNET_SCHEDULER_TaskIdentifier dns_read_task; - - /** - * pointer to raw dns query payload FIXME needs to be freed/NULL - */ - char *dns_raw_packet; - - /** - * size of the raw dns query - */ - size_t dns_raw_packet_size; - - /** - * timeout task for the lookup - */ - GNUNET_SCHEDULER_TaskIdentifier timeout_task; - - /** - * continuation to call on timeout - */ - GNUNET_SCHEDULER_Task timeout_cont; - - /** - * closure for timeout cont - */ - void* timeout_cont_cls; - - /** - * 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; - - /** - * The provate local zone of this request - */ - struct GNUNET_CRYPTO_ShortHashCode private_local_zone; - - /** - * private key of an/our authoritative zone - * can be NULL but automatical PKEY import will not work - */ - struct GNUNET_CRYPTO_EccPrivateKey *priv_key; - - /** - * the heap node associated with this lookup, null if timeout is set - * used for DHT background lookups. - */ - struct GNUNET_CONTAINER_HeapNode *dht_heap_node; - - /** - * Id for resolution process - */ - unsigned long long id; - - /** - * Pending Namestore task - */ - struct GNUNET_NAMESTORE_QueueEntry *namestore_task; - -}; - - -/** - * Handle to a record lookup - */ -struct RecordLookupHandle -{ - /** - * the record type to look up - */ - int record_type; - - /** - * the name to look up - */ - char name[GNUNET_DNSPARSER_MAX_NAME_LENGTH]; - - /** - * 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; - - /** - * result of shorten - */ - char result[GNUNET_DNSPARSER_MAX_NAME_LENGTH]; - - /** - * root zone - */ - struct GNUNET_CRYPTO_ShortHashCode *root_zone; - - /** - * private zone - */ - struct GNUNET_CRYPTO_ShortHashCode *private_zone; - - /** - * name of private zone - */ - char private_zone_name[GNUNET_DNSPARSER_MAX_LABEL_LENGTH]; - - /** - * shorten zone - */ - struct GNUNET_CRYPTO_ShortHashCode *shorten_zone; - - /** - * name of shorten zone - */ - char shorten_zone_name[GNUNET_DNSPARSER_MAX_LABEL_LENGTH]; - -}; - - -/** - * Handle to a get authority context - */ -struct GetNameAuthorityHandle -{ - /** - * the name to look up authority for - */ - char name[GNUNET_DNSPARSER_MAX_NAME_LENGTH]; - - /** - * the result - */ - char result[GNUNET_DNSPARSER_MAX_NAME_LENGTH]; - - /** - * Method to call on result - */ - GetAuthorityResultProcessor proc; - - /** - * closure to pass to proc - */ - void* proc_cls; -}; - - -/** - * Handle to a pseu lookup - */ -struct GetPseuAuthorityHandle -{ - /** - * DLL - */ - struct GetPseuAuthorityHandle *next; - - /** - * DLL - */ - struct GetPseuAuthorityHandle *prev; - - /** - * the name to store the zone under - */ - char name[GNUNET_DNSPARSER_MAX_LABEL_LENGTH]; - - /** - * test name to store the zone under - */ - char test_name[GNUNET_DNSPARSER_MAX_LABEL_LENGTH]; - - /** - * the zone of our authority - */ - struct GNUNET_CRYPTO_ShortHashCode our_zone; - - /** - * the private key of the zone to store the pseu in - */ - struct GNUNET_CRYPTO_EccPrivateKey *key; - - /** - * a handle for dht lookups. should be NULL if no lookups are in progress - */ - struct GNUNET_DHT_GetHandle *get_handle; - - /** - * timeout task for lookup - */ - GNUNET_SCHEDULER_TaskIdentifier timeout; - - /** - * Authority to shorten - */ - struct AuthorityChain *auth; - - /** - * handle to namestore request - */ - struct GNUNET_NAMESTORE_QueueEntry* namestore_task; -}; - - -/** - * Namestore queue entries in background - */ -struct NamestoreBGTask -{ - /** - * node in heap - */ - struct GNUNET_CONTAINER_HeapNode *node; - - /** - * queue entry - */ - struct GNUNET_NAMESTORE_QueueEntry *qe; -}; - - -/** - * Initialize the resolver - * MUST be called before other gns_resolver_* methods + * Initialize the resolver subsystem. + * MUST be called before #GNS_resolver_lookup. * * @param nh handle to the namestore - * @param dh handle to the dht - * @param lz the local zone + * @param dht handle to the dht * @param c configuration handle * @param max_bg_queries maximum amount of background queries * @param ignore_pending ignore records that still require user confirmation @@ -539,9 +41,8 @@ struct NamestoreBGTask * @returns GNUNET_OK on success */ int -gns_resolver_init (struct GNUNET_NAMESTORE_Handle *nh, - struct GNUNET_DHT_Handle *dh, - struct GNUNET_CRYPTO_ShortHashCode lz, +GNS_resolver_init (struct GNUNET_NAMESTORE_Handle *nh, + struct GNUNET_DHT_Handle *dht, const struct GNUNET_CONFIGURATION_Handle *c, unsigned long long max_bg_queries, int ignore_pending); @@ -551,78 +52,59 @@ gns_resolver_init (struct GNUNET_NAMESTORE_Handle *nh, * Cleanup resolver: Terminate pending lookups */ void -gns_resolver_cleanup (void); +GNS_resolver_done (void); + + +/** + * Handle for an active request. + */ +struct GNS_ResolverHandle; + + +/** + * Function called with results for a GNS resolution. + * + * @param cls closure + * @param rd_count number of records in @a rd + * @param rd records returned for the lookup + */ +typedef void (*GNS_ResultProcessor)(void *cls, + uint32_t rd_count, + const struct GNUNET_NAMESTORE_RecordData *rd); /** * Lookup of a record in a specific zone * calls RecordLookupProcessor on result or timeout * - * @param zone the root zone - * @param pzone the private local zone + * @param zone the zone to perform the lookup in * @param record_type the record type to look up * @param name the name to look up - * @param key optional private key for authority caching - * @param timeout timeout for the resolution + * @param shorten_key optional private key for authority caching, can be NULL * @param only_cached GNUNET_NO to only check locally not DHT for performance * @param proc the processor to call - * @param cls the closure to pass to proc + * @param proc_cls the closure to pass to @a proc */ -void -gns_resolver_lookup_record (struct GNUNET_CRYPTO_ShortHashCode zone, - struct GNUNET_CRYPTO_ShortHashCode pzone, - uint32_t record_type, - const char* name, - struct GNUNET_CRYPTO_EccPrivateKey *key, - struct GNUNET_TIME_Relative timeout, - int only_cached, - RecordLookupProcessor proc, - void* cls); +struct GNS_ResolverHandle * +GNS_resolver_lookup (const struct GNUNET_CRYPTO_EccPublicKey *zone, + uint32_t record_type, + const char *name, + const struct GNUNET_CRYPTO_EccPrivateKey *shorten_key, + int only_cached, + GNS_ResultProcessor proc, + void *proc_cls); /** - * Shortens a name if possible. If the shortening fails - * name will be returned as shortened string. Else - * a shorter version of the name will be returned. - * There is no guarantee that the shortened name will - * actually be canonical/short etc. + * Cancel active resolution (i.e. client disconnected). * - * @param zone the root zone to use - * @param pzone the private zone to use - * @param szone the shorten zone to use - * @param name name to shorten - * @param private_zone_name name of the private zone - * @param shorten_zone_name name of the shorten zone - * @param proc the processor to call on shorten result - * @param proc_cls the closure to pass to proc + * @param h resolution to abort */ void -gns_resolver_shorten_name (struct GNUNET_CRYPTO_ShortHashCode *zone, - struct GNUNET_CRYPTO_ShortHashCode *pzone, - struct GNUNET_CRYPTO_ShortHashCode *szone, - const char* name, - const char* private_zone_name, - const char* shorten_zone_name, - ShortenResultProcessor proc, - void* proc_cls); +GNS_resolver_lookup_cancel (struct GNS_ResolverHandle *h); + -/** - * Tries to resolve the authority for name - * in our namestore - * - * @param zone the root zone to look up for - * @param pzone the private local zone - * @param name the name to lookup up - * @param proc the processor to call when finished - * @param proc_cls the closure to pass to the processor - */ -void -gns_resolver_get_authority (struct GNUNET_CRYPTO_ShortHashCode zone, - struct GNUNET_CRYPTO_ShortHashCode pzone, - const char* name, - GetAuthorityResultProcessor proc, - void* proc_cls); /** @@ -630,16 +112,16 @@ gns_resolver_get_authority (struct GNUNET_CRYPTO_ShortHashCode zone, * * @param name the name to check * @param tld the tld to check - * @return GNUNET_YES or GNUNET_NO + * @return #GNUNET_YES or #GNUNET_NO */ int -is_tld (const char* name, - const char* tld); +is_tld (const char *name, + const char *tld); /** - * Checks for gads/zkey + * Checks for gnu/zkey */ #define is_gads_tld(name) is_tld(name, GNUNET_GNS_TLD) #define is_zkey_tld(name) is_tld(name, GNUNET_GNS_TLD_ZKEY) -- cgit v1.2.3