2 This file is part of GNUnet.
3 (C) 2009, 2010, 2011 Christian Grothoff (and other contributing authors)
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
24 * @file gns/gnunet-service-gns_resolver.c
25 * @brief GNUnet GNS resolver logic
26 * @author Martin Schanzenbach
29 #include "gnunet_util_lib.h"
30 #include "gnunet_transport_service.h"
31 #include "gnunet_dns_service.h"
32 #include "gnunet_dht_service.h"
33 #include "gnunet_namestore_service.h"
34 #include "gnunet_dns_service.h"
35 #include "gnunet_dnsparser_lib.h"
36 #include "gnunet_gns_service.h"
37 #include "block_gns.h"
39 #include "gnunet-service-gns_resolver.h"
41 #define DHT_OPERATION_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 3)
42 #define DHT_LOOKUP_TIMEOUT DHT_OPERATION_TIMEOUT
43 #define DHT_GNS_REPLICATION_LEVEL 5
44 #define MAX_DNS_LABEL_LENGTH 63
48 * Our handle to the namestore service
50 static struct GNUNET_NAMESTORE_Handle *namestore_handle;
53 * Resolver handle to the dht
55 static struct GNUNET_DHT_Handle *dht_handle;
58 * Heap for parallel DHT lookups
60 static struct GNUNET_CONTAINER_Heap *dht_lookup_heap;
63 * Maximum amount of parallel queries in background
65 static unsigned long long max_allowed_background_queries;
70 static struct GNUNET_CRYPTO_ShortHashCode local_zone;
72 static unsigned long long rid = 0;
75 * Namestore calls this function if we have record for this name.
76 * (or with rd_count=0 to indicate no matches)
78 * @param cls the pending query
79 * @param key the key of the zone we did the lookup
80 * @param expiration expiration date of the namestore entry
81 * @param name the name for which we need an authority
82 * @param rd_count the number of records with 'name'
83 * @param rd the record data
84 * @param signature the signature of the authority for the record data
87 process_pseu_lookup_ns(void* cls,
88 const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *key,
89 struct GNUNET_TIME_Absolute expiration,
90 const char *name, unsigned int rd_count,
91 const struct GNUNET_NAMESTORE_RecordData *rd,
92 const struct GNUNET_CRYPTO_RsaSignature *signature)
94 struct GetPseuAuthorityHandle* gph = (struct GetPseuAuthorityHandle*)cls;
95 struct GNUNET_NAMESTORE_RecordData new_pkey;
99 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
100 "GNS_AUTO_PSEU: Name %s already taken in NS!\n", name);
101 if (0 == strcmp(gph->name, name))
103 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
104 "GNS_AUTO_PSEU: Intelligent replacement not implemented\n",
110 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
111 "GNS_AUTO_PSEU: Trying delegated name %s\n", gph->name);
112 memcpy(gph->new_name, gph->name, strlen(gph->name)+1);
113 GNUNET_NAMESTORE_lookup_record(namestore_handle,
116 GNUNET_GNS_RECORD_PSEU,
117 &process_pseu_lookup_ns,
123 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
124 "GNS_AUTO_PSEU: Name %s not taken in NS! Adding\n", gph->new_name);
126 new_pkey.expiration = GNUNET_TIME_absolute_get_forever ();
127 new_pkey.data_size = sizeof(struct GNUNET_CRYPTO_ShortHashCode);
128 new_pkey.data = &gph->new_zone;
129 new_pkey.record_type = GNUNET_GNS_RECORD_PKEY;
130 GNUNET_NAMESTORE_record_create (namestore_handle,
141 * process result of a dht pseu lookup
143 * @param gph the handle
144 * @param name the pseu result or NULL
147 process_pseu_result(struct GetPseuAuthorityHandle* gph, char* name)
151 memcpy(gph->new_name, gph->name, strlen(gph->name)+1);
155 memcpy(gph->new_name, name, strlen(name)+1);
158 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
159 "GNS_AUTO_PSEU: Checking %s for collision in NS\n", gph->new_name);
162 * Check for collision
164 GNUNET_NAMESTORE_lookup_record(namestore_handle,
167 GNUNET_GNS_RECORD_PSEU,
168 &process_pseu_lookup_ns,
173 * Handle timeout for dht request
175 * @param cls the request handle as closure
176 * @param tc the task context
179 handle_auth_discovery_timeout(void *cls,
180 const struct GNUNET_SCHEDULER_TaskContext *tc)
182 struct GetPseuAuthorityHandle* gph = (struct GetPseuAuthorityHandle*)cls;
184 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
185 "GNS_GET_AUTH: dht lookup for query PSEU timed out.\n");
186 GNUNET_DHT_get_stop (gph->get_handle);
187 gph->get_handle = NULL;
188 process_pseu_result(gph, NULL);
192 * Function called when we find a PSEU entry in the DHT
194 * @param cls the request handle
195 * @param exp lifetime
196 * @param key the key the record was stored under
197 * @param get_path get path
198 * @param get_path_length get path length
199 * @param put_path put path
200 * @param put_path_length put path length
201 * @param type the block type
202 * @param size the size of the record
203 * @param data the record data
206 process_auth_discovery_dht_result(void* cls,
207 struct GNUNET_TIME_Absolute exp,
208 const GNUNET_HashCode * key,
209 const struct GNUNET_PeerIdentity *get_path,
210 unsigned int get_path_length,
211 const struct GNUNET_PeerIdentity *put_path,
212 unsigned int put_path_length,
213 enum GNUNET_BLOCK_Type type,
214 size_t size, const void *data)
216 struct GetPseuAuthorityHandle* gph = (struct GetPseuAuthorityHandle*)cls;
217 struct GNSNameRecordBlock *nrb;
218 char* rd_data = (char*)data;
224 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
225 "GNS_GET_AUTH: got dht result (size=%d)\n", size);
229 GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
230 "GNS_GET_AUTH: got dht result null!\n", size);
236 nrb = (struct GNSNameRecordBlock*)data;
238 /* stop lookup and timeout task */
239 GNUNET_DHT_get_stop (gph->get_handle);
240 gph->get_handle = NULL;
241 GNUNET_SCHEDULER_cancel(gph->timeout);
243 gph->get_handle = NULL;
245 nrb = (struct GNSNameRecordBlock*)data;
247 name = (char*)&nrb[1];
248 num_records = ntohl(nrb->rd_count);
250 struct GNUNET_NAMESTORE_RecordData rd[num_records];
252 rd_data += strlen(name) + 1 + sizeof(struct GNSNameRecordBlock);
253 rd_size = size - strlen(name) - 1 - sizeof(struct GNSNameRecordBlock);
255 if (GNUNET_SYSERR == GNUNET_NAMESTORE_records_deserialize (rd_size,
260 GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
261 "GNS_GET_AUTH: Error deserializing data!\n");
267 for (i=0; i<num_records; i++)
269 if ((strcmp(name, "+") == 0) &&
270 (rd[i].record_type == GNUNET_GNS_RECORD_PSEU))
273 process_pseu_result(gph, (char*)rd[i].data);
279 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "GNS_GET_AUTH: no pseu in dht!\n");
280 process_pseu_result(gph, NULL);
284 process_auth_discovery_ns_result(void* cls,
285 const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *key,
286 struct GNUNET_TIME_Absolute expiration,
287 const char *name, unsigned int rd_count,
288 const struct GNUNET_NAMESTORE_RecordData *rd,
289 const struct GNUNET_CRYPTO_RsaSignature *signature)
292 struct GNUNET_CRYPTO_ShortHashCode name_hash;
293 GNUNET_HashCode lookup_key;
294 struct GNUNET_CRYPTO_HashAsciiEncoded lookup_key_string;
295 GNUNET_HashCode name_hash_double;
296 GNUNET_HashCode zone_hash_double;
298 struct GetPseuAuthorityHandle* gph = (struct GetPseuAuthorityHandle*)cls;
306 GNUNET_CRYPTO_short_hash("+", strlen("+"), &name_hash);
307 GNUNET_CRYPTO_short_hash_double (&name_hash, &name_hash_double);
308 GNUNET_CRYPTO_short_hash_double (&gph->new_zone, &zone_hash_double);
309 GNUNET_CRYPTO_hash_xor(&name_hash_double, &zone_hash_double, &lookup_key);
310 GNUNET_CRYPTO_hash_to_enc (&lookup_key, &lookup_key_string);
312 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
313 "GNS_AUTO_PSEU: starting dht lookup for %s with key: %s\n",
314 "+", (char*)&lookup_key_string);
316 gph->timeout = GNUNET_SCHEDULER_add_delayed(DHT_LOOKUP_TIMEOUT,
317 &handle_auth_discovery_timeout, gph);
319 xquery = htonl(GNUNET_GNS_RECORD_PSEU);
321 GNUNET_assert(gph->get_handle == NULL);
322 gph->get_handle = GNUNET_DHT_get_start(dht_handle,
323 GNUNET_TIME_UNIT_FOREVER_REL,
324 GNUNET_BLOCK_TYPE_GNS_NAMERECORD,
326 DHT_GNS_REPLICATION_LEVEL,
330 &process_auth_discovery_dht_result,
334 for (i=0; i<rd_count; i++)
336 if ((strcmp(name, "+") == 0) &&
337 (rd[i].record_type == GNUNET_GNS_RECORD_PSEU))
340 process_pseu_result(gph, (char*)rd[i].data);
347 * Callback called by namestore for a zone to name
350 * @param cls the closure
351 * @param zone_key the zone we queried
352 * @param expire the expiration time of the name
353 * @param name the name found or NULL
354 * @param rd_len number of records for the name
355 * @param rd the record data (PKEY) for the name
356 * @param signature the signature for the record data
359 process_zone_to_name_discover(void *cls,
360 const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *zone_key,
361 struct GNUNET_TIME_Absolute expire,
364 const struct GNUNET_NAMESTORE_RecordData *rd,
365 const struct GNUNET_CRYPTO_RsaSignature *signature)
367 struct GetPseuAuthorityHandle* gph = (struct GetPseuAuthorityHandle*)cls;
369 /* we found a match in our own zone */
372 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
373 "GNS_AUTO_PSEU: name for zone in our root %s\n", name);
379 GNUNET_NAMESTORE_lookup_record(namestore_handle,
382 GNUNET_GNS_RECORD_PSEU,
383 &process_auth_discovery_ns_result,
392 * Callback for new authories
394 * @param name the name given by delegation
395 * @param zone the authority
396 * @param our_zone our local zone
397 * @param key the private key of our authority
399 static void process_discovered_authority(char* name,
400 struct GNUNET_CRYPTO_ShortHashCode zone,
401 struct GNUNET_CRYPTO_ShortHashCode our_zone,
402 struct GNUNET_CRYPTO_RsaPrivateKey *key)
404 struct GetPseuAuthorityHandle *gph;
407 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
408 "GNS_AUTO_PSEU: New authority %s discovered\n",
411 gph = GNUNET_malloc(sizeof(struct GetPseuAuthorityHandle));
412 namelen = strlen(name) + 1;
413 memcpy(gph->name, name, namelen);
415 gph->new_zone = zone;
416 gph->zone = our_zone;
419 GNUNET_NAMESTORE_zone_to_name (namestore_handle,
422 &process_zone_to_name_discover,
428 * Initialize the resolver
430 * @param nh the namestore handle
431 * @param dh the dht handle
432 * @param lz the local zone's hash
433 * @param max_bg_queries maximum number of parallel background queries in dht
434 * @return GNUNET_OK on success
437 gns_resolver_init(struct GNUNET_NAMESTORE_Handle *nh,
438 struct GNUNET_DHT_Handle *dh,
439 struct GNUNET_CRYPTO_ShortHashCode lz,
440 unsigned long long max_bg_queries)
442 namestore_handle = nh;
446 GNUNET_CONTAINER_heap_create(GNUNET_CONTAINER_HEAP_ORDER_MIN);
447 max_allowed_background_queries = max_bg_queries;
449 if ((namestore_handle != NULL) && (dht_handle != NULL))
453 return GNUNET_SYSERR;
457 * Cleanup background lookups
459 * @param cls closure to iterator
460 * @param node heap nodes
461 * @param element the resolver handle
462 * @param cost heap cost
463 * @return always GNUNET_YES
466 cleanup_pending_background_queries(void* cls,
467 struct GNUNET_CONTAINER_HeapNode *node,
469 GNUNET_CONTAINER_HeapCostType cost)
471 struct ResolverHandle *rh = (struct ResolverHandle *)element;
472 ResolverCleanupContinuation cont = cls;
474 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
475 "GNS_CLEANUP-%d: Terminating background lookup for %s\n",
477 GNUNET_DHT_get_stop(rh->get_handle);
478 rh->get_handle = NULL;
479 rh->proc(rh->proc_cls, rh, 0, NULL);
481 GNUNET_CONTAINER_heap_remove_node(node);
483 if (GNUNET_CONTAINER_heap_get_size(dht_lookup_heap) == 0)
495 gns_resolver_cleanup(ResolverCleanupContinuation cont)
497 unsigned int s = GNUNET_CONTAINER_heap_get_size(dht_lookup_heap);
498 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
499 "GNS_CLEANUP: %d pending background queries to terminate\n", s);
502 GNUNET_CONTAINER_heap_iterate (dht_lookup_heap,
503 &cleanup_pending_background_queries,
511 * Helper function to free resolver handle
513 * @param rh the handle to free
516 free_resolver_handle(struct ResolverHandle* rh)
518 struct AuthorityChain *ac;
519 struct AuthorityChain *ac_next;
524 ac = rh->authority_chain_head;
537 * Callback when record data is put into namestore
539 * @param cls the closure
540 * @param success GNUNET_OK on success
541 * @param emsg the error message. NULL if SUCCESS==GNUNET_OK
544 on_namestore_record_put_result(void *cls,
548 if (GNUNET_NO == success)
550 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
551 "GNS_NS: records already in namestore\n");
554 else if (GNUNET_YES == success)
556 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
557 "GNS_NS: records successfully put in namestore\n");
561 GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
562 "GNS_NS: Error putting records into namestore: %s\n", emsg);
566 handle_lookup_timeout(void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
568 struct ResolverHandle *rh = cls;
570 if (rh->timeout_cont)
571 rh->timeout_cont(rh->timeout_cont_cls, tc);
575 * Processor for background lookups in the DHT
577 * @param cls closure (NULL)
578 * @param rd_count number of records found (not 0)
579 * @param rd record data
582 background_lookup_result_processor(void *cls,
584 const struct GNUNET_NAMESTORE_RecordData *rd)
586 //We could do sth verbose/more useful here but it doesn't make any difference
587 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
588 "GNS_BG: background dht lookup for finished. (%d results)\n",
593 * Handle timeout for DHT requests
595 * @param cls the request handle as closure
596 * @param tc the task context
599 dht_lookup_timeout(void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
601 struct ResolverHandle *rh = cls;
602 struct RecordLookupHandle *rlh = (struct RecordLookupHandle *)rh->proc_cls;
603 char new_name[MAX_DNS_NAME_LENGTH];
605 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
606 "GNS_PHASE_REC-%d: dht lookup for query %s (%ds)timed out.\n",
607 rh->id, rh->name, rh->timeout.rel_value);
609 * Start resolution in bg
611 //strcpy(new_name, rh->name);
612 //memcpy(new_name+strlen(new_name), GNUNET_GNS_TLD, strlen(GNUNET_GNS_TLD));
613 GNUNET_snprintf(new_name, MAX_DNS_NAME_LENGTH, "%s.%s",
614 rh->name, GNUNET_GNS_TLD);
616 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
617 "GNS_PHASE_REC-%d: Starting background lookup for %s type %d\n",
618 rh->id, new_name, rlh->record_type);
620 gns_resolver_lookup_record(rh->authority,
624 GNUNET_TIME_UNIT_FOREVER_REL,
625 &background_lookup_result_processor,
627 rh->timeout_task = GNUNET_SCHEDULER_NO_TASK;
629 GNUNET_DHT_get_stop (rh->get_handle);
630 rh->get_handle = NULL;
631 rh->proc(rh->proc_cls, rh, 0, NULL);
636 * Function called when we get a result from the dht
637 * for our record query
639 * @param cls the request handle
640 * @param exp lifetime
641 * @param key the key the record was stored under
642 * @param get_path get path
643 * @param get_path_length get path length
644 * @param put_path put path
645 * @param put_path_length put path length
646 * @param type the block type
647 * @param size the size of the record
648 * @param data the record data
651 process_record_result_dht(void* cls,
652 struct GNUNET_TIME_Absolute exp,
653 const GNUNET_HashCode * key,
654 const struct GNUNET_PeerIdentity *get_path,
655 unsigned int get_path_length,
656 const struct GNUNET_PeerIdentity *put_path,
657 unsigned int put_path_length,
658 enum GNUNET_BLOCK_Type type,
659 size_t size, const void *data)
661 struct ResolverHandle *rh;
662 struct RecordLookupHandle *rlh;
663 struct GNSNameRecordBlock *nrb;
664 uint32_t num_records;
666 char* rd_data = (char*)data;
670 rh = (struct ResolverHandle *)cls;
671 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
672 "GNS_PHASE_REC-%d: got dht result (size=%d)\n", rh->id, size);
677 //FIXME maybe check expiration here, check block type
680 rlh = (struct RecordLookupHandle *) rh->proc_cls;
681 nrb = (struct GNSNameRecordBlock*)data;
683 /* stop lookup and timeout task */
684 GNUNET_DHT_get_stop (rh->get_handle);
685 rh->get_handle = NULL;
687 if (rh->dht_heap_node != NULL)
689 GNUNET_CONTAINER_heap_remove_node(rh->dht_heap_node);
690 rh->dht_heap_node = NULL;
693 if (rh->timeout_task != GNUNET_SCHEDULER_NO_TASK)
695 GNUNET_SCHEDULER_cancel(rh->timeout_task);
696 rh->timeout_task = GNUNET_SCHEDULER_NO_TASK;
699 rh->get_handle = NULL;
700 name = (char*)&nrb[1];
701 num_records = ntohl(nrb->rd_count);
703 struct GNUNET_NAMESTORE_RecordData rd[num_records];
705 rd_data += strlen(name) + 1 + sizeof(struct GNSNameRecordBlock);
706 rd_size = size - strlen(name) - 1 - sizeof(struct GNSNameRecordBlock);
708 if (GNUNET_SYSERR == GNUNET_NAMESTORE_records_deserialize (rd_size,
713 GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
714 "GNS_PHASE_REC-%d: Error deserializing data!\n", rh->id);
718 for (i=0; i<num_records; i++)
720 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
721 "GNS_PHASE_REC-%d: Got name: %s (wanted %s)\n",
722 rh->id, name, rh->name);
723 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
724 "GNS_PHASE_REC-%d: Got type: %d\n",
725 rh->id, rd[i].record_type);
726 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
727 "GNS_PHASE_REC-%d: Got data length: %d\n",
728 rh->id, rd[i].data_size);
729 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
730 "GNS_PHASE_REC-%d: Got flag %d\n",
731 rh->id, rd[i].flags);
733 if ((strcmp(name, rh->name) == 0) &&
734 (rd[i].record_type == rlh->record_type))
742 * FIXME check pubkey against existing key in namestore?
743 * https://gnunet.org/bugs/view.php?id=2179
746 /* Save to namestore */
747 GNUNET_NAMESTORE_record_put (namestore_handle,
754 &on_namestore_record_put_result, //cont
759 rh->proc(rh->proc_cls, rh, num_records, rd);
761 rh->proc(rh->proc_cls, rh, 0, NULL);
768 * Start DHT lookup for a (name -> query->record_type) record in
769 * rh->authority's zone
771 * @param rh the pending gns query context
774 resolve_record_dht(struct ResolverHandle *rh)
777 struct GNUNET_CRYPTO_ShortHashCode name_hash;
778 GNUNET_HashCode lookup_key;
779 GNUNET_HashCode name_hash_double;
780 GNUNET_HashCode zone_hash_double;
781 struct GNUNET_CRYPTO_HashAsciiEncoded lookup_key_string;
782 struct RecordLookupHandle *rlh = (struct RecordLookupHandle *)rh->proc_cls;
783 struct ResolverHandle *rh_heap_root;
785 GNUNET_CRYPTO_short_hash(rh->name, strlen(rh->name), &name_hash);
786 GNUNET_CRYPTO_short_hash_double(&name_hash, &name_hash_double);
787 GNUNET_CRYPTO_short_hash_double(&rh->authority, &zone_hash_double);
788 GNUNET_CRYPTO_hash_xor(&name_hash_double, &zone_hash_double, &lookup_key);
789 GNUNET_CRYPTO_hash_to_enc (&lookup_key, &lookup_key_string);
791 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
792 "GNS_PHASE_REC-%d: starting dht lookup for %s with key: %s\n",
793 rh->id, rh->name, (char*)&lookup_key_string);
795 //rh->timeout_task = GNUNET_SCHEDULER_NO_TASK;
796 rh->dht_heap_node = NULL;
798 if (rh->timeout.rel_value != GNUNET_TIME_UNIT_FOREVER_REL.rel_value)
801 * Update timeout if necessary
803 if (rh->timeout_task == GNUNET_SCHEDULER_NO_TASK)
806 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
807 "GNS_PHASE_REC-%d: Adjusting timeout\n", rh->id);
809 * Set timeout for authority lookup phase to 1/2
811 rh->timeout_task = GNUNET_SCHEDULER_add_delayed(
812 GNUNET_TIME_relative_divide(rh->timeout, 2),
813 &handle_lookup_timeout,
816 //rh->timeout_task = GNUNET_SCHEDULER_add_delayed (DHT_LOOKUP_TIMEOUT,
817 // &dht_lookup_timeout,
819 rh->timeout_cont = &dht_lookup_timeout;
820 rh->timeout_cont_cls = rh;
824 if (max_allowed_background_queries <=
825 GNUNET_CONTAINER_heap_get_size (dht_lookup_heap))
827 rh_heap_root = GNUNET_CONTAINER_heap_remove_root (dht_lookup_heap);
828 GNUNET_DHT_get_stop(rh_heap_root->get_handle);
829 rh_heap_root->get_handle = NULL;
830 rh_heap_root->dht_heap_node = NULL;
832 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
833 "GNS_PHASE_REC-%d: Replacing oldest background query for %s\n",
834 rh->id, rh_heap_root->name);
835 rh_heap_root->proc(rh_heap_root->proc_cls,
840 rh->dht_heap_node = GNUNET_CONTAINER_heap_insert (dht_lookup_heap,
842 GNUNET_TIME_absolute_get().abs_value);
845 xquery = htonl(rlh->record_type);
847 GNUNET_assert(rh->get_handle == NULL);
848 rh->get_handle = GNUNET_DHT_get_start(dht_handle,
849 GNUNET_TIME_UNIT_FOREVER_REL,
850 GNUNET_BLOCK_TYPE_GNS_NAMERECORD,
852 DHT_GNS_REPLICATION_LEVEL,
856 &process_record_result_dht,
863 * Namestore calls this function if we have record for this name.
864 * (or with rd_count=0 to indicate no matches)
866 * @param cls the pending query
867 * @param key the key of the zone we did the lookup
868 * @param expiration expiration date of the namestore entry
869 * @param name the name for which we need an authority
870 * @param rd_count the number of records with 'name'
871 * @param rd the record data
872 * @param signature the signature of the authority for the record data
875 process_record_result_ns(void* cls,
876 const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *key,
877 struct GNUNET_TIME_Absolute expiration,
878 const char *name, unsigned int rd_count,
879 const struct GNUNET_NAMESTORE_RecordData *rd,
880 const struct GNUNET_CRYPTO_RsaSignature *signature)
882 struct ResolverHandle *rh;
883 struct RecordLookupHandle *rlh;
884 struct GNUNET_TIME_Relative remaining_time;
885 struct GNUNET_CRYPTO_ShortHashCode zone;
887 rh = (struct ResolverHandle *) cls;
888 rlh = (struct RecordLookupHandle *)rh->proc_cls;
889 GNUNET_CRYPTO_short_hash(key,
890 sizeof(struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded),
892 remaining_time = GNUNET_TIME_absolute_get_remaining (expiration);
900 rh->status |= EXISTS;
903 if (remaining_time.rel_value == 0)
905 rh->status |= EXPIRED;
911 * Lookup terminated and no results
913 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
914 "GNS_PHASE_REC-%d: Namestore lookup for %s terminated without results\n",
917 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
918 "GNS_PHASE_REC-%d: Record %s unknown in namestore\n",
921 * Our zone and no result? Cannot resolve TT
923 rh->proc(rh->proc_cls, rh, 0, NULL);
930 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
931 "GNS_PHASE_REC-%d: Processing additional result %s from namestore\n",
934 for (i=0; i<rd_count;i++)
937 if (rd[i].record_type != rlh->record_type)
940 if ((GNUNET_TIME_absolute_get_remaining (rd[i].expiration)).rel_value
943 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
944 "GNS_PHASE_REC-%d: This record is expired. Skipping\n",
956 if (rh->answered == 0)
958 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
959 "GNS_PHASE_REC-%d: No answers found. This is odd!\n", rh->id);
960 rh->proc(rh->proc_cls, rh, 0, NULL);
964 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
965 "GNS_PHASE_REC-%d: Found %d answer(s) to query in %d records!\n",
966 rh->id, rh->answered, rd_count);
968 rh->proc(rh->proc_cls, rh, rd_count, rd);
974 * The final phase of resolution.
975 * rh->name is a name that is canonical and we do not have a delegation.
976 * Query namestore for this record
978 * @param rh the pending lookup
981 resolve_record_ns(struct ResolverHandle *rh)
983 struct RecordLookupHandle *rlh = (struct RecordLookupHandle *)rh->proc_cls;
985 /* We cancel here as to not include the ns lookup in the timeout */
986 if (rh->timeout_task != GNUNET_SCHEDULER_NO_TASK)
988 GNUNET_SCHEDULER_cancel(rh->timeout_task);
989 rh->timeout_task = GNUNET_SCHEDULER_NO_TASK;
993 * Try to resolve this record in our namestore.
994 * The name to resolve is now in rh->authority_name
995 * since we tried to resolve it to an authority
998 GNUNET_NAMESTORE_lookup_record(namestore_handle,
1002 &process_record_result_ns,
1009 * Handle timeout for DHT requests
1011 * @param cls the request handle as closure
1012 * @param tc the task context
1015 dht_authority_lookup_timeout(void *cls,
1016 const struct GNUNET_SCHEDULER_TaskContext *tc)
1018 struct ResolverHandle *rh = cls;
1019 struct RecordLookupHandle *rlh = rh->proc_cls;
1020 char new_name[MAX_DNS_NAME_LENGTH];
1022 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1023 "GNS_PHASE_DELEGATE_DHT-%llu: dht lookup for query %s (%ds)timed out.\n",
1024 rh->id, rh->authority_name, rh->timeout.rel_value);
1026 rh->status |= TIMED_OUT;
1028 rh->timeout_task = GNUNET_SCHEDULER_NO_TASK;
1030 GNUNET_DHT_get_stop (rh->get_handle);
1031 rh->get_handle = NULL;
1033 if (strcmp(rh->name, "") == 0)
1036 * promote authority back to name and try to resolve record
1038 strcpy(rh->name, rh->authority_name);
1039 rh->proc(rh->proc_cls, rh, 0, NULL);
1044 * Start resolution in bg
1046 GNUNET_snprintf(new_name, MAX_DNS_NAME_LENGTH,
1047 "%s.%s.%s", rh->name, rh->authority_name, GNUNET_GNS_TLD);
1048 //strcpy(new_name, rh->name);
1049 //strcpy(new_name+strlen(new_name), ".");
1050 //memcpy(new_name+strlen(new_name), GNUNET_GNS_TLD, strlen(GNUNET_GNS_TLD));
1052 strcpy(rh->name, new_name);
1054 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1055 "GNS_PHASE_DELEGATE_DHT-%llu: Starting background query for %s type %d\n",
1056 rh->id, rh->name, rlh->record_type);
1058 gns_resolver_lookup_record(rh->authority,
1062 GNUNET_TIME_UNIT_FOREVER_REL,
1063 &background_lookup_result_processor,
1066 rh->proc(rh->proc_cls, rh, 0, NULL);
1070 static void resolve_delegation_dht(struct ResolverHandle *rh);
1073 static void resolve_delegation_ns(struct ResolverHandle *rh);
1077 * Namestore resolution for delegation finished. Processing result.
1079 * @param cls the closure
1080 * @param rh resolver handle
1081 * @param rd_count number of results (always 0)
1082 * @param rd record data (always NULL)
1085 handle_delegation_ns(void* cls, struct ResolverHandle *rh,
1086 unsigned int rd_count,
1087 const struct GNUNET_NAMESTORE_RecordData *rd);
1091 * Function called when we get a result from the dht
1092 * for our query. Recursively tries to resolve authorities
1095 * @param cls the request handle
1096 * @param exp lifetime
1097 * @param key the key the record was stored under
1098 * @param get_path get path
1099 * @param get_path_length get path length
1100 * @param put_path put path
1101 * @param put_path_length put path length
1102 * @param type the block type
1103 * @param size the size of the record
1104 * @param data the record data
1107 process_delegation_result_dht(void* cls,
1108 struct GNUNET_TIME_Absolute exp,
1109 const GNUNET_HashCode * key,
1110 const struct GNUNET_PeerIdentity *get_path,
1111 unsigned int get_path_length,
1112 const struct GNUNET_PeerIdentity *put_path,
1113 unsigned int put_path_length,
1114 enum GNUNET_BLOCK_Type type,
1115 size_t size, const void *data)
1117 struct ResolverHandle *rh;
1118 struct GNSNameRecordBlock *nrb;
1119 uint32_t num_records;
1121 char* rd_data = (char*) data;
1124 struct GNUNET_CRYPTO_ShortHashCode zone, name_hash;
1125 GNUNET_HashCode zone_hash_double, name_hash_double;
1127 rh = (struct ResolverHandle *)cls;
1129 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1130 "GNS_PHASE_DELEGATE_DHT-%llu: Got DHT result\n", rh->id);
1135 nrb = (struct GNSNameRecordBlock*)data;
1137 /* stop dht lookup and timeout task */
1138 GNUNET_DHT_get_stop (rh->get_handle);
1140 rh->get_handle = NULL;
1142 if (rh->dht_heap_node != NULL)
1144 GNUNET_CONTAINER_heap_remove_node(rh->dht_heap_node);
1145 rh->dht_heap_node = NULL;
1148 num_records = ntohl(nrb->rd_count);
1149 name = (char*)&nrb[1];
1151 struct GNUNET_NAMESTORE_RecordData rd[num_records];
1153 rd_data += strlen(name) + 1 + sizeof(struct GNSNameRecordBlock);
1154 rd_size = size - strlen(name) - 1 - sizeof(struct GNSNameRecordBlock);
1156 if (GNUNET_SYSERR == GNUNET_NAMESTORE_records_deserialize (rd_size,
1161 GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
1162 "GNS_PHASE_DELEGATE_DHT-%llu: Error deserializing data!\n",
1167 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1168 "GNS_PHASE_DELEGATE_DHT-%llu: Got name: %s (wanted %s)\n",
1169 rh->id, name, rh->authority_name);
1170 for (i=0; i<num_records; i++)
1173 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1174 "GNS_PHASE_DELEGATE_DHT-%llu: Got name: %s (wanted %s)\n",
1175 rh->id, name, rh->authority_name);
1176 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1177 "GNS_PHASE_DELEGATE_DHT-%llu: Got type: %d (wanted %d)\n",
1178 rh->id, rd[i].record_type, GNUNET_GNS_RECORD_PKEY);
1179 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1180 "GNS_PHASE_DELEGATE_DHT-%llu: Got data length: %d\n",
1181 rh->id, rd[i].data_size);
1182 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1183 "GNS_PHASE_DELEGATE_DHT-%llu: Got flag %d\n",
1184 rh->id, rd[i].flags);
1186 if ((strcmp(name, rh->authority_name) == 0) &&
1187 (rd[i].record_type == GNUNET_GNS_RECORD_PKEY))
1189 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1190 "GNS_PHASE_DELEGATE_DHT-%llu: Authority found in DHT\n",
1193 memcpy(&rh->authority, rd[i].data, sizeof(struct GNUNET_CRYPTO_ShortHashCode));
1194 struct AuthorityChain *auth =
1195 GNUNET_malloc(sizeof(struct AuthorityChain));
1196 auth->zone = rh->authority;
1197 memset(auth->name, 0, strlen(rh->authority_name)+1);
1198 strcpy(auth->name, rh->authority_name);
1199 GNUNET_CONTAINER_DLL_insert (rh->authority_chain_head,
1200 rh->authority_chain_tail,
1203 /** try to import pkey if private key available */
1205 process_discovered_authority(name, auth->zone,
1206 rh->authority_chain_tail->zone,
1213 GNUNET_CRYPTO_short_hash(name, strlen(name), &name_hash);
1214 GNUNET_CRYPTO_short_hash_double(&name_hash, &name_hash_double);
1215 GNUNET_CRYPTO_hash_xor(key, &name_hash_double, &zone_hash_double);
1216 GNUNET_CRYPTO_short_hash_from_truncation (&zone_hash_double, &zone);
1218 /* Save to namestore */
1219 if (0 != GNUNET_CRYPTO_short_hash_cmp(&rh->authority_chain_tail->zone,
1222 GNUNET_NAMESTORE_record_put (namestore_handle,
1229 &on_namestore_record_put_result, //cont
1239 * FIXME in this case. should we ask namestore again?
1241 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1242 "GNS_PHASE_DELEGATE_DHT-%llu: Answer from DHT for %s. Yet to resolve: %s\n",
1243 rh->id, rh->authority_name, rh->name);
1244 if (strcmp(rh->name, "") == 0)
1246 rh->proc(rh->proc_cls, rh, 0, NULL);
1250 rh->proc = &handle_delegation_ns;
1251 resolve_delegation_ns(rh);
1257 * No pkey but name exists
1260 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1261 "GNS_PHASE_DELEGATE_DHT-%llu: Adding %s back to %s\n",
1262 rh->id, rh->authority_name, rh->name);
1263 if (strcmp(rh->name, "") == 0)
1264 strcpy(rh->name, rh->authority_name);
1266 GNUNET_snprintf(rh->name, MAX_DNS_NAME_LENGTH, "%s.%s",
1267 rh->name, rh->authority_name); //FIXME ret
1269 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1270 "GNS_PHASE_DELEGATE_DHT-%llu: %s restored\n", rh->id, rh->name);
1271 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1272 "GNS_PHASE_DELEGATE_DHT-%llu: DHT authority lookup found no match!\n",
1274 rh->proc(rh->proc_cls, rh, 0, NULL);
1277 #define MAX_SOA_LENGTH sizeof(uint32_t)+sizeof(uint32_t)+sizeof(uint32_t)+sizeof(uint32_t)\
1278 +(MAX_DNS_NAME_LENGTH*2)
1279 #define MAX_MX_LENGTH sizeof(uint16_t)+MAX_DNS_NAME_LENGTH
1283 expand_plus(char** dest, char* src, char* repl)
1286 unsigned int s_len = strlen(src)+1;
1288 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1289 "GNS_POSTPROCESS: Got %s to expand with %s\n", src, repl);
1293 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1294 "GNS_POSTPROCESS: %s to short\n", src);
1296 /* no postprocessing */
1297 memcpy(*dest, src, s_len+1);
1301 if (0 == strcmp(src+s_len-3, ".+"))
1303 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1304 "GNS_POSTPROCESS: Expanding .+ in %s\n", src);
1305 memset(*dest, 0, s_len+strlen(repl)+strlen(GNUNET_GNS_TLD));
1307 pos = *dest+s_len-2;
1309 pos += strlen(repl);
1310 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1311 "GNS_POSTPROCESS: Expanded to %s\n", *dest);
1315 memcpy(*dest, src, s_len+1);
1323 finish_lookup(struct ResolverHandle *rh,
1324 struct RecordLookupHandle* rlh,
1325 unsigned int rd_count,
1326 const struct GNUNET_NAMESTORE_RecordData *rd)
1329 char new_rr_data[MAX_DNS_NAME_LENGTH];
1330 char new_mx_data[MAX_MX_LENGTH];
1331 char new_soa_data[MAX_SOA_LENGTH];
1332 struct GNUNET_NAMESTORE_RecordData p_rd[rd_count];
1335 unsigned int offset;
1337 if (rh->timeout_task != GNUNET_SCHEDULER_NO_TASK)
1338 GNUNET_SCHEDULER_cancel(rh->timeout_task);
1341 memcpy(p_rd, rd, rd_count*sizeof(struct GNUNET_NAMESTORE_RecordData));
1343 for (i = 0; i < rd_count; i++)
1346 if (rd[i].record_type != GNUNET_GNS_RECORD_TYPE_NS &&
1347 rd[i].record_type != GNUNET_GNS_RECORD_TYPE_CNAME &&
1348 rd[i].record_type != GNUNET_GNS_RECORD_MX &&
1349 rd[i].record_type != GNUNET_GNS_RECORD_TYPE_SOA)
1351 p_rd[i].data = rd[i].data;
1356 * for all those records we 'should'
1357 * also try to resolve the A/AAAA records (RFC1035)
1358 * This is a feature and not important
1361 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1362 "GNS_POSTPROCESS: Postprocessing\n");
1364 if (strcmp(rh->name, "+") == 0)
1365 repl_string = rlh->name;
1367 repl_string = rlh->name+strlen(rh->name)+1;
1370 if (rd[i].record_type == GNUNET_GNS_RECORD_MX)
1372 memcpy(new_mx_data, (char*)rd[i].data, sizeof(uint16_t));
1373 offset = sizeof(uint16_t);
1374 pos = new_mx_data+offset;
1375 expand_plus(&pos, (char*)rd[i].data+sizeof(uint16_t),
1377 offset += strlen(new_mx_data+sizeof(uint16_t))+1;
1378 p_rd[i].data = new_mx_data;
1379 p_rd[i].data_size = offset;
1381 else if (rd[i].record_type == GNUNET_GNS_RECORD_TYPE_SOA)
1383 /* expand mname and rname */
1385 expand_plus(&pos, (char*)rd[i].data, repl_string);
1386 offset = strlen(new_soa_data)+1;
1387 pos = new_soa_data+offset;
1388 expand_plus(&pos, (char*)rd[i].data+offset, repl_string);
1389 offset += strlen(new_soa_data+offset)+1;
1390 /* cpy the 4 numbers serial refresh retry and expire */
1391 memcpy(new_soa_data+offset, (char*)rd[i].data+offset, sizeof(uint32_t)*5);
1392 offset += sizeof(uint32_t)*5;
1393 p_rd[i].data_size = offset;
1394 p_rd[i].data = new_soa_data;
1399 expand_plus(&pos, (char*)rd[i].data, repl_string);
1400 p_rd[i].data_size = strlen(new_rr_data)+1;
1401 p_rd[i].data = new_rr_data;
1406 rlh->proc(rlh->proc_cls, rd_count, p_rd);
1412 * Process DHT lookup result for record.
1414 * @param cls the closure
1415 * @param rh resolver handle
1416 * @param rd_count number of results
1417 * @param rd record data
1420 handle_record_dht(void* cls, struct ResolverHandle *rh,
1421 unsigned int rd_count,
1422 const struct GNUNET_NAMESTORE_RecordData *rd)
1424 struct RecordLookupHandle* rlh;
1426 rlh = (struct RecordLookupHandle*)cls;
1429 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1430 "GNS_PHASE_REC-%d: No records for %s found in DHT. Aborting\n",
1432 /* give up, cannot resolve */
1433 finish_lookup(rh, rlh, 0, NULL);
1434 free_resolver_handle(rh);
1438 /* results found yay */
1439 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1440 "GNS_PHASE_REC-%d: Record resolved from DHT!", rh->id);
1442 finish_lookup(rh, rlh, rd_count, rd);
1443 free_resolver_handle(rh);
1449 * Process namestore lookup result for record.
1451 * @param cls the closure
1452 * @param rh resolver handle
1453 * @param rd_count number of results
1454 * @param rd record data
1457 handle_record_ns(void* cls, struct ResolverHandle *rh,
1458 unsigned int rd_count,
1459 const struct GNUNET_NAMESTORE_RecordData *rd)
1461 struct RecordLookupHandle* rlh;
1462 rlh = (struct RecordLookupHandle*) cls;
1465 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1466 "GNS_PHASE_REC-%d: NS returned no records. (status: %d)!\n",
1471 * There are 4 conditions that have to met for us to consult the DHT:
1472 * 1. The entry in the DHT is EXPIRED AND
1473 * 2. No entry in the NS existed AND
1474 * 3. The zone queried is not the local resolver's zone AND
1475 * 4. The name that was looked up is '+'
1476 * because if it was any other canonical name we either already queried
1477 * the DHT for the authority in the authority lookup phase (and thus
1478 * would already have an entry in the NS for the record)
1480 if (rh->status & (EXPIRED | !EXISTS) &&
1481 GNUNET_CRYPTO_short_hash_cmp(&rh->authority_chain_head->zone,
1483 (strcmp(rh->name, "+") == 0))
1485 rh->proc = &handle_record_dht;
1486 resolve_record_dht(rh);
1489 /* give up, cannot resolve */
1490 finish_lookup(rh, rlh, 0, NULL);
1491 free_resolver_handle(rh);
1495 /* results found yay */
1496 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1497 "GNS_PHASE_REC-%d: Record resolved from namestore!", rh->id);
1499 finish_lookup(rh, rlh, rd_count, rd);
1501 free_resolver_handle(rh);
1507 * Determine if this name is canonical.
1509 * a.b.gnunet = not canonical
1512 * @param name the name to test
1513 * @return 1 if canonical
1516 is_canonical(char* name)
1518 uint32_t len = strlen(name);
1521 for (i=0; i<len; i++)
1523 if (*(name+i) == '.')
1530 * Move one level up in the domain hierarchy and return the
1531 * passed top level domain.
1533 * @param name the domain
1534 * @param dest the destination where the tld will be put
1537 pop_tld(char* name, char* dest)
1541 if (is_canonical(name))
1548 for (len = strlen(name); len > 0; len--)
1550 if (*(name+len) == '.')
1560 strcpy(dest, (name+len+1));
1564 * Checks if name is in tld
1566 * @param name the name to check
1567 * @param tld the TLD to check for
1568 * @return GNUNET_YES or GNUNET_NO
1571 is_tld(const char* name, const char* tld)
1575 if (strlen(name) <= strlen(tld))
1580 offset = strlen(name)-strlen(tld);
1581 if (strcmp(name+offset, tld) != 0)
1583 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1584 "%s is not in .%s TLD\n", name, tld);
1591 * DHT resolution for delegation finished. Processing result.
1593 * @param cls the closure
1594 * @param rh resolver handle
1595 * @param rd_count number of results (always 0)
1596 * @param rd record data (always NULL)
1599 handle_delegation_dht(void* cls, struct ResolverHandle *rh,
1600 unsigned int rd_count,
1601 const struct GNUNET_NAMESTORE_RecordData *rd)
1603 struct RecordLookupHandle* rlh;
1604 rlh = (struct RecordLookupHandle*) cls;
1607 if (strcmp(rh->name, "") == 0)
1609 if ((rlh->record_type == GNUNET_GNS_RECORD_PKEY))
1611 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1612 "GNS_PHASE_DELEGATE_DHT-%llu: Resolved queried PKEY via DHT.\n",
1614 finish_lookup(rh, rlh, rd_count, rd);
1615 free_resolver_handle(rh);
1618 /* We resolved full name for delegation. resolving record */
1619 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1620 "GNS_PHASE_DELEGATE_DHT-%llu: Resolved full name for delegation via DHT.\n",
1622 strcpy(rh->name, "+\0");
1623 rh->proc = &handle_record_ns;
1624 resolve_record_ns(rh);
1629 * we still have some left
1631 if (is_canonical(rh->name))
1633 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1634 "GNS_PHASE_DELEGATE_DHT-%llu: Resolving canonical record %s in ns\n",
1637 rh->proc = &handle_record_ns;
1638 resolve_record_ns(rh);
1641 /* give up, cannot resolve */
1642 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1643 "GNS_PHASE_DELEGATE_DHT-%llu: Cannot fully resolve delegation for %s via DHT!\n",
1645 finish_lookup(rh, rlh, 0, NULL);
1646 free_resolver_handle(rh);
1651 * Start DHT lookup for a name -> PKEY (compare NS) record in
1652 * rh->authority's zone
1654 * @param rh the pending gns query
1657 resolve_delegation_dht(struct ResolverHandle *rh)
1660 struct GNUNET_CRYPTO_ShortHashCode name_hash;
1661 GNUNET_HashCode name_hash_double;
1662 GNUNET_HashCode zone_hash_double;
1663 GNUNET_HashCode lookup_key;
1664 struct ResolverHandle *rh_heap_root;
1666 pop_tld(rh->name, rh->authority_name);
1667 GNUNET_CRYPTO_short_hash(rh->authority_name,
1668 strlen(rh->authority_name),
1670 GNUNET_CRYPTO_short_hash_double(&name_hash, &name_hash_double);
1671 GNUNET_CRYPTO_short_hash_double(&rh->authority, &zone_hash_double);
1672 GNUNET_CRYPTO_hash_xor(&name_hash_double, &zone_hash_double, &lookup_key);
1674 rh->dht_heap_node = NULL;
1676 if (rh->timeout.rel_value != GNUNET_TIME_UNIT_FOREVER_REL.rel_value)
1678 //rh->timeout_task = GNUNET_SCHEDULER_add_delayed (DHT_LOOKUP_TIMEOUT,
1679 // &dht_authority_lookup_timeout,
1681 rh->timeout_cont = &dht_authority_lookup_timeout;
1682 rh->timeout_cont_cls = rh;
1686 if (max_allowed_background_queries <=
1687 GNUNET_CONTAINER_heap_get_size (dht_lookup_heap))
1689 /* terminate oldest lookup */
1690 rh_heap_root = GNUNET_CONTAINER_heap_remove_root (dht_lookup_heap);
1691 GNUNET_DHT_get_stop(rh_heap_root->get_handle);
1692 rh_heap_root->dht_heap_node = NULL;
1694 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1695 "GNS_PHASE_DELEGATE_DHT-%llu: Replacing oldest background query for %s\n",
1696 rh->id, rh_heap_root->authority_name);
1698 rh_heap_root->proc(rh_heap_root->proc_cls,
1703 rh->dht_heap_node = GNUNET_CONTAINER_heap_insert (dht_lookup_heap,
1705 GNUNET_TIME_absolute_get().abs_value);
1708 xquery = htonl(GNUNET_GNS_RECORD_PKEY);
1710 GNUNET_assert(rh->get_handle == NULL);
1711 rh->get_handle = GNUNET_DHT_get_start(dht_handle,
1712 GNUNET_TIME_UNIT_FOREVER_REL,
1713 GNUNET_BLOCK_TYPE_GNS_NAMERECORD,
1715 DHT_GNS_REPLICATION_LEVEL,
1719 &process_delegation_result_dht,
1726 * Namestore resolution for delegation finished. Processing result.
1728 * @param cls the closure
1729 * @param rh resolver handle
1730 * @param rd_count number of results (always 0)
1731 * @param rd record data (always NULL)
1734 handle_delegation_ns(void* cls, struct ResolverHandle *rh,
1735 unsigned int rd_count,
1736 const struct GNUNET_NAMESTORE_RecordData *rd)
1738 struct RecordLookupHandle* rlh;
1739 rlh = (struct RecordLookupHandle*) cls;
1741 if (strcmp(rh->name, "") == 0)
1743 if ((rlh->record_type == GNUNET_GNS_RECORD_PKEY))
1745 GNUNET_assert(rd_count == 1);
1746 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1747 "GNS_PHASE_DELEGATE_NS-%llu: Resolved queried PKEY in NS.\n",
1749 finish_lookup(rh, rlh, rd_count, rd);
1750 free_resolver_handle(rh);
1753 /* We resolved full name for delegation. resolving record */
1754 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1755 "GNS_PHASE_DELEGATE_NS-%llu: Resolved full name for delegation.\n",
1757 strcpy(rh->name, "+\0");
1758 rh->proc = &handle_record_ns;
1759 resolve_record_ns(rh);
1764 * we still have some left
1765 * check if authority in ns is fresh
1767 * or we are authority
1769 if ((rh->status & (EXISTS | !EXPIRED)) ||
1770 !GNUNET_CRYPTO_short_hash_cmp(&rh->authority_chain_head->zone,
1771 &rh->authority_chain_tail->zone))
1773 if (is_canonical(rh->name))
1775 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1776 "GNS_PHASE_DELEGATE_NS-%llu: Resolving canonical record %s\n",
1779 rh->proc = &handle_record_ns;
1780 resolve_record_ns(rh);
1784 /* give up, cannot resolve */
1785 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1786 "GNS_PHASE_DELEGATE_NS-%llu: Cannot fully resolve delegation for %s!\n",
1789 finish_lookup(rh, rlh, rd_count, rd);
1790 //rlh->proc(rlh->proc_cls, 0, NULL);
1795 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1796 "GNS_PHASE_DELEGATE_NS-%llu: Trying to resolve delegation for %s via DHT\n",
1798 rh->proc = &handle_delegation_dht;
1799 resolve_delegation_dht(rh);
1805 * This is a callback function that should give us only PKEY
1806 * records. Used to query the namestore for the authority (PKEY)
1807 * for 'name'. It will recursively try to resolve the
1808 * authority for a given name from the namestore.
1810 * @param cls the pending query
1811 * @param key the key of the zone we did the lookup
1812 * @param expiration expiration date of the record data set in the namestore
1813 * @param name the name for which we need an authority
1814 * @param rd_count the number of records with 'name'
1815 * @param rd the record data
1816 * @param signature the signature of the authority for the record data
1819 process_delegation_result_ns(void* cls,
1820 const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *key,
1821 struct GNUNET_TIME_Absolute expiration,
1823 unsigned int rd_count,
1824 const struct GNUNET_NAMESTORE_RecordData *rd,
1825 const struct GNUNET_CRYPTO_RsaSignature *signature)
1827 struct ResolverHandle *rh;
1828 struct GNUNET_TIME_Relative remaining_time;
1829 struct GNUNET_CRYPTO_ShortHashCode zone;
1830 char new_name[MAX_DNS_NAME_LENGTH];
1832 rh = (struct ResolverHandle *)cls;
1833 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1834 "GNS_PHASE_DELEGATE_NS-%llu: Got %d records from authority lookup\n",
1837 GNUNET_CRYPTO_short_hash(key,
1838 sizeof(struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded),
1840 remaining_time = GNUNET_TIME_absolute_get_remaining (expiration);
1846 rh->status |= EXISTS;
1849 if (remaining_time.rel_value == 0)
1851 rh->status |= EXPIRED;
1855 * No authority found in namestore.
1860 * We did not find an authority in the namestore
1865 * Promote this authority back to a name maybe it is
1868 if (strcmp(rh->name, "") == 0)
1870 /* simply promote back */
1871 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1872 "GNS_PHASE_DELEGATE_NS-%llu: Promoting %s back to name\n",
1873 rh->id, rh->authority_name);
1874 strcpy(rh->name, rh->authority_name);
1878 /* add back to existing name */
1879 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1880 "GNS_PHASE_DELEGATE_NS-%llu: Adding %s back to %s\n",
1881 rh->id, rh->authority_name, rh->name);
1882 //memset(new_name, 0, strlen(rh->name) + strlen(rh->authority_name) + 2);
1883 GNUNET_snprintf(new_name, MAX_DNS_NAME_LENGTH, "%s.%s",
1884 rh->name, rh->authority_name);
1885 //strcpy(new_name, rh->name);
1886 //strcpy(new_name+strlen(new_name), ".");
1887 //strcpy(new_name+strlen(new_name), rh->authority_name);
1888 strcpy(rh->name, new_name);
1889 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1890 "GNS_PHASE_DELEGATE_NS-%llu: %s restored\n", rh->id, rh->name);
1892 rh->proc(rh->proc_cls, rh, 0, NULL);
1897 * We found an authority that may be able to help us
1898 * move on with query
1899 * Note only 1 pkey should have been returned.. anything else would be strange
1902 for (i=0; i<rd_count;i++)
1905 if (rd[i].record_type != GNUNET_GNS_RECORD_PKEY)
1908 if ((GNUNET_TIME_absolute_get_remaining (rd[i].expiration)).rel_value
1911 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1912 "GNS_PHASE_DELEGATE_NS-%llu: This pkey is expired.\n",
1914 if (remaining_time.rel_value == 0)
1916 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1917 "GNS_PHASE_DELEGATE_NS-%llu: This dht entry is expired.\n",
1919 rh->authority_chain_head->fresh = 0;
1920 rh->proc(rh->proc_cls, rh, 0, NULL);
1928 * Resolve rest of query with new authority
1930 GNUNET_assert(rd[i].record_type == GNUNET_GNS_RECORD_PKEY);
1931 memcpy(&rh->authority, rd[i].data,
1932 sizeof(struct GNUNET_CRYPTO_ShortHashCode));
1933 struct AuthorityChain *auth = GNUNET_malloc(sizeof(struct AuthorityChain));
1934 auth->zone = rh->authority;
1935 memset(auth->name, 0, strlen(rh->authority_name)+1);
1936 strcpy(auth->name, rh->authority_name);
1937 GNUNET_CONTAINER_DLL_insert (rh->authority_chain_head,
1938 rh->authority_chain_tail,
1941 /** try to import pkey if private key available */
1943 process_discovered_authority((char*)name, auth->zone,
1944 rh->authority_chain_tail->zone,
1947 * We are done with PKEY resolution if name is empty
1948 * else resolve again with new authority
1950 if (strcmp(rh->name, "") == 0)
1951 rh->proc(rh->proc_cls, rh, rd_count, rd);
1953 resolve_delegation_ns(rh);
1960 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1961 "GNS_PHASE_DELEGATE_NS-%llu: Authority lookup and no PKEY...\n", rh->id);
1962 rh->proc(rh->proc_cls, rh, 0, NULL);
1967 * Resolve the delegation chain for the request in our namestore
1969 * @param rh the resolver handle
1972 resolve_delegation_ns(struct ResolverHandle *rh)
1974 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1975 "GNS_PHASE_DELEGATE_NS-%llu: Resolving delegation for %s\n",
1977 pop_tld(rh->name, rh->authority_name);
1978 GNUNET_NAMESTORE_lookup_record(namestore_handle,
1981 GNUNET_GNS_RECORD_PKEY,
1982 &process_delegation_result_ns,
1989 * Lookup of a record in a specific zone
1990 * calls lookup result processor on result
1992 * @param zone the root zone
1993 * @param record_type the record type to look up
1994 * @param name the name to look up
1995 * @param key a private key for use with PSEU import (can be NULL)
1996 * @param timeout timeout for resolution
1997 * @param proc the processor to call on result
1998 * @param cls the closure to pass to proc
2001 gns_resolver_lookup_record(struct GNUNET_CRYPTO_ShortHashCode zone,
2002 uint32_t record_type,
2004 struct GNUNET_CRYPTO_RsaPrivateKey *key,
2005 struct GNUNET_TIME_Relative timeout,
2006 RecordLookupProcessor proc,
2009 struct ResolverHandle *rh;
2010 struct RecordLookupHandle* rlh;
2011 char string_hash[MAX_DNS_LABEL_LENGTH];
2012 char nzkey[MAX_DNS_LABEL_LENGTH];
2013 char* nzkey_ptr = nzkey;
2015 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2016 "Starting resolution for %s (type=%d)!\n",
2020 if (is_canonical((char*)name) && (strcmp(GNUNET_GNS_TLD, name) != 0))
2022 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2023 "%s is canonical and not gnunet -> cannot resolve!\n", name);
2028 rlh = GNUNET_malloc(sizeof(struct RecordLookupHandle));
2029 rh = GNUNET_malloc(sizeof (struct ResolverHandle));
2031 rh->authority = zone;
2035 rh->timeout = timeout;
2036 rh->get_handle = NULL;
2037 if (timeout.rel_value != GNUNET_TIME_UNIT_FOREVER_REL.rel_value)
2040 * Set timeout for authority lookup phase to 1/2
2042 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2043 "Timeout for lookup set to %ds\n", rh->timeout.rel_value);
2044 rh->timeout_task = GNUNET_SCHEDULER_add_delayed(
2045 GNUNET_TIME_relative_divide(timeout, 2),
2046 &handle_lookup_timeout,
2048 rh->timeout_cont = &dht_authority_lookup_timeout;
2049 rh->timeout_cont_cls = rh;
2053 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "No timeout for query!\n");
2054 rh->timeout_task = GNUNET_SCHEDULER_NO_TASK;
2057 if (strcmp(GNUNET_GNS_TLD, name) == 0)
2060 * Only 'gnunet' given
2062 strcpy(rh->name, "\0");
2066 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2067 "Checking for TLD...\n");
2068 if (is_zkey_tld(name) == GNUNET_YES)
2070 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2073 * This is a zkey tld
2074 * build hash and use as initial authority
2077 strlen(name)-strlen(GNUNET_GNS_TLD_ZKEY));
2078 memcpy(rh->name, name,
2079 strlen(name)-strlen(GNUNET_GNS_TLD_ZKEY) - 1);
2080 pop_tld(rh->name, string_hash);
2082 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2083 "ZKEY is %s!\n", string_hash);
2085 GNUNET_STRINGS_utf8_toupper(string_hash, &nzkey_ptr);
2087 if (GNUNET_OK != GNUNET_CRYPTO_short_hash_from_string(nzkey,
2090 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2091 "Cannot convert ZKEY %s to hash!\n", string_hash);
2101 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2104 * Presumably GNUNET tld
2107 strlen(name)-strlen(GNUNET_GNS_TLD));
2108 memcpy(rh->name, name,
2109 strlen(name)-strlen(GNUNET_GNS_TLD) - 1);
2114 * Initialize authority chain
2116 rh->authority_chain_head = GNUNET_malloc(sizeof(struct AuthorityChain));
2117 rh->authority_chain_head->prev = NULL;
2118 rh->authority_chain_head->next = NULL;
2119 rh->authority_chain_tail = rh->authority_chain_head;
2120 rh->authority_chain_head->zone = rh->authority;
2123 * Copy original query into lookup handle
2125 rlh->record_type = record_type;
2126 memset(rlh->name, 0, strlen(name) + 1);
2127 strcpy(rlh->name, name);
2129 rlh->proc_cls = cls;
2131 rh->proc = &handle_delegation_ns;
2132 resolve_delegation_ns(rh);
2135 /******** END Record Resolver ***********/
2139 * Callback calles by namestore for a zone to name
2142 * @param cls the closure
2143 * @param zone_key the zone we queried
2144 * @param expire the expiration time of the name
2145 * @param name the name found or NULL
2146 * @param rd_len number of records for the name
2147 * @param rd the record data (PKEY) for the name
2148 * @param signature the signature for the record data
2151 process_zone_to_name_shorten(void *cls,
2152 const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *zone_key,
2153 struct GNUNET_TIME_Absolute expire,
2155 unsigned int rd_len,
2156 const struct GNUNET_NAMESTORE_RecordData *rd,
2157 const struct GNUNET_CRYPTO_RsaSignature *signature)
2159 struct ResolverHandle *rh = (struct ResolverHandle *)cls;
2160 struct NameShortenHandle* nsh = (struct NameShortenHandle*)rh->proc_cls;
2161 struct AuthorityChain *next_authority;
2163 char result[MAX_DNS_NAME_LENGTH];
2164 char next_authority_name[MAX_DNS_LABEL_LENGTH];
2167 /* we found a match in our own zone */
2170 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2171 "result strlen %d\n", strlen(name));
2172 answer_len = strlen(rh->name) + strlen(name) + strlen(GNUNET_GNS_TLD) + 3;
2173 memset(result, 0, answer_len);
2174 if (strlen(rh->name) > 0)
2176 strcpy(result, rh->name);
2177 strcpy(result+strlen(rh->name), ".");
2180 strcpy(result+strlen(result), name);
2181 strcpy(result+strlen(result), ".");
2182 strcpy(result+strlen(result), GNUNET_GNS_TLD);
2184 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2185 "Sending shorten result %s\n", result);
2187 nsh->proc(nsh->proc_cls, result);
2189 free_resolver_handle(rh);
2191 else if (GNUNET_CRYPTO_short_hash_cmp(&rh->authority_chain_head->zone,
2194 /* our zone, just append .gnunet */
2195 answer_len = strlen(rh->name) + strlen(GNUNET_GNS_TLD) + 2;
2196 memset(result, 0, answer_len);
2197 strcpy(result, rh->name);
2198 strcpy(result+strlen(rh->name), ".");
2199 strcpy(result+strlen(rh->name)+1, GNUNET_GNS_TLD);
2201 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2202 "Our zone: Sending name as shorten result %s\n", rh->name);
2204 nsh->proc(nsh->proc_cls, result);
2206 free_resolver_handle(rh);
2212 * continue with next authority
2214 next_authority = rh->authority_chain_head;
2215 // strlen(next_authority->name) + 2);
2216 memset(next_authority_name, 0, strlen(rh->name)+
2217 strlen(next_authority->name) + 2);
2218 GNUNET_snprintf(next_authority_name, MAX_DNS_NAME_LENGTH,
2219 "%s.%s", rh->name, next_authority->name);
2220 //strcpy(next_authority_name, rh->name);
2221 //strcpy(next_authority_name+strlen(rh->name)+1, ".");
2222 //strcpy(next_authority_name+strlen(rh->name)+2, next_authority->name);
2224 strcpy(rh->name, next_authority_name);
2225 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2226 "No PSEU found for authority %s. Promoting back: %s\n",
2227 next_authority->name, rh->name);
2229 GNUNET_CONTAINER_DLL_remove(rh->authority_chain_head,
2230 rh->authority_chain_tail,
2233 GNUNET_NAMESTORE_zone_to_name (namestore_handle,
2234 &rh->authority_chain_tail->zone,
2235 &rh->authority_chain_head->zone,
2236 &process_zone_to_name_shorten,
2242 * DHT resolution for delegation finished. Processing result.
2244 * @param cls the closure
2245 * @param rh resolver handle
2246 * @param rd_count number of results (always 0)
2247 * @param rd record data (always NULL)
2250 handle_delegation_dht_bg_shorten(void* cls, struct ResolverHandle *rh,
2251 unsigned int rd_count,
2252 const struct GNUNET_NAMESTORE_RecordData *rd)
2255 /* We resolved full name for delegation. resolving record */
2256 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2257 "GNS_SHORTEN: Resolved up to %s for delegation via DHT in background.\n",
2259 free_resolver_handle(rh);
2263 * Process result from namestore delegation lookup
2264 * for shorten operation
2266 * @param cls the client shorten handle
2267 * @param rh the resolver handle
2268 * @param rd_count number of results (0)
2269 * @param rd data (NULL)
2272 handle_delegation_ns_shorten(void* cls,
2273 struct ResolverHandle *rh,
2275 const struct GNUNET_NAMESTORE_RecordData *rd)
2277 struct NameShortenHandle *nsh;
2278 char result[MAX_DNS_NAME_LENGTH];
2280 struct ResolverHandle *rh_bg;
2282 nsh = (struct NameShortenHandle *)cls;
2285 * At this point rh->name contains the part of the name
2286 * that we do not have a PKEY in our namestore to resolve.
2287 * The authority chain in the resolver handle is now
2288 * useful to backtrack if needed
2291 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2292 "PKEY resolved as far as possible in ns up to %s!\n", rh->name);
2294 if (GNUNET_CRYPTO_short_hash_cmp(&rh->authority_chain_head->zone,
2298 * This is our zone append .gnunet unless name is empty
2299 * (it shouldn't be, usually FIXME what happens if we
2300 * shorten to our zone to a "" record??)
2303 answer_len = strlen(rh->name) + strlen(GNUNET_GNS_TLD) + 2;
2304 memset(result, 0, answer_len);
2305 strcpy(result, rh->name);
2306 strcpy(result+strlen(rh->name), ".");
2307 strcpy(result+strlen(rh->name)+1, GNUNET_GNS_TLD);
2309 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2310 "Our zone: Sending name as shorten result %s\n", rh->name);
2312 nsh->proc(nsh->proc_cls, result);
2314 free_resolver_handle(rh);
2319 * we have to this before zone to name for rh might
2323 if (!is_canonical(rh->name))
2325 rh_bg = GNUNET_malloc(sizeof(struct ResolverHandle));
2326 memcpy(rh_bg, rh, sizeof(struct ResolverHandle));
2330 /* backtrack authorities for names */
2331 GNUNET_NAMESTORE_zone_to_name (namestore_handle,
2332 &rh->authority_chain_tail->zone, //ours
2333 &rh->authority_chain_head->zone,
2334 &process_zone_to_name_shorten,
2343 * If authority resolution is incomplete we can do a background lookup
2344 * of the full name so that next time we can (likely) fully or at least
2345 * further shorten the name
2347 rh_bg->authority_chain_head = GNUNET_malloc(sizeof(struct AuthorityChain));
2348 rh_bg->authority_chain_tail = rh_bg->authority_chain_head;
2349 rh_bg->authority_chain_head->zone = rh_bg->authority;
2351 rh_bg->proc = &handle_delegation_dht_bg_shorten;
2352 rh_bg->proc_cls = NULL;
2354 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2355 "GNS_SHORTEN: Starting background lookup for %s\n",
2358 resolve_delegation_dht(rh_bg);
2364 * Callback calles by namestore for a zone to name
2367 * @param cls the closure
2368 * @param zone_key the zone we queried
2369 * @param expire the expiration time of the name
2370 * @param name the name found or NULL
2371 * @param rd_len number of records for the name
2372 * @param rd the record data (PKEY) for the name
2373 * @param signature the signature for the record data
2376 process_zone_to_name_zkey(void *cls,
2377 const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *zone_key,
2378 struct GNUNET_TIME_Absolute expire,
2380 unsigned int rd_len,
2381 const struct GNUNET_NAMESTORE_RecordData *rd,
2382 const struct GNUNET_CRYPTO_RsaSignature *signature)
2384 struct ResolverHandle *rh = cls;
2385 struct NameShortenHandle *nsh = rh->proc_cls;
2386 struct GNUNET_CRYPTO_ShortHashAsciiEncoded enc;
2387 char new_name[MAX_DNS_NAME_LENGTH];
2389 /* zkey not in our zone */
2393 * In this case we have not given this PKEY a name (yet)
2394 * It is either just not in our zone or not even cached
2395 * Since we do not know at this point we will not try to shorten
2396 * because PKEY import will happen if the user follows the zkey
2399 GNUNET_CRYPTO_short_hash_to_enc ((struct GNUNET_CRYPTO_ShortHashCode*)rd,
2401 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2402 "No name found for zkey %s returning verbatim!\n", enc);
2403 if (strcmp(rh->name, "") != 0)
2404 GNUNET_snprintf(new_name, MAX_DNS_NAME_LENGTH, "%s.%s.%s",
2405 rh->name, enc, GNUNET_GNS_TLD_ZKEY);
2407 GNUNET_snprintf(new_name, MAX_DNS_NAME_LENGTH, "%s.%s",
2408 enc, GNUNET_GNS_TLD_ZKEY);
2409 nsh->proc(nsh->proc_cls, new_name);
2411 free_resolver_handle(rh);
2415 if (strcmp(rh->name, "") != 0)
2416 GNUNET_snprintf(new_name, MAX_DNS_NAME_LENGTH, "%s.%s",
2419 strcpy(new_name, name);
2421 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2422 "Continue shorten for %s!\n", new_name);
2424 strcpy(rh->name, new_name);
2426 rh->authority_chain_head = GNUNET_malloc(sizeof(struct AuthorityChain));
2427 rh->authority_chain_tail = rh->authority_chain_head;
2428 rh->authority_chain_head->zone = rh->authority;
2431 /* Start delegation resolution in our namestore */
2432 resolve_delegation_ns(rh);
2436 * Shorten api from resolver
2438 * @param zone the zone to use
2439 * @param name the name to shorten
2440 * @param key optional private key for background lookups and PSEU import
2441 * @param proc the processor to call with result
2442 * @param proc_cls closure to pass to proc
2445 gns_resolver_shorten_name(struct GNUNET_CRYPTO_ShortHashCode zone,
2447 struct GNUNET_CRYPTO_RsaPrivateKey *key,
2448 ShortenResultProcessor proc,
2451 struct ResolverHandle *rh;
2452 struct NameShortenHandle *nsh;
2453 char string_hash[MAX_DNS_LABEL_LENGTH];
2454 struct GNUNET_CRYPTO_ShortHashCode zkey;
2455 char nzkey[MAX_DNS_LABEL_LENGTH];
2456 char* nzkey_ptr = nzkey;
2459 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2460 "Starting shorten for %s!\n", name);
2462 if (is_canonical((char*)name))
2464 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2465 "%s is canonical. Returning verbatim\n", name);
2466 proc(proc_cls, name);
2470 nsh = GNUNET_malloc(sizeof (struct NameShortenHandle));
2473 nsh->proc_cls = proc_cls;
2475 rh = GNUNET_malloc(sizeof (struct ResolverHandle));
2476 rh->authority = zone;
2479 rh->proc = &handle_delegation_ns_shorten;
2483 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2484 "Checking for TLD...\n");
2485 if (is_zkey_tld(name) == GNUNET_YES)
2487 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2490 * This is a zkey tld
2491 * build hash and use as initial authority
2495 strlen(name)-strlen(GNUNET_GNS_TLD_ZKEY));
2496 memcpy(rh->name, name,
2497 strlen(name)-strlen(GNUNET_GNS_TLD_ZKEY) - 1);
2498 pop_tld(rh->name, string_hash);
2500 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2501 "ZKEY is %s!\n", string_hash);
2503 GNUNET_STRINGS_utf8_toupper(string_hash, &nzkey_ptr);
2505 if (GNUNET_OK != GNUNET_CRYPTO_short_hash_from_string(nzkey,
2508 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2509 "Cannot convert ZKEY %s to hash!\n", nzkey);
2512 proc(proc_cls, name);
2516 GNUNET_NAMESTORE_zone_to_name (namestore_handle,
2519 &process_zone_to_name_zkey,
2526 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2529 * Presumably GNUNET tld
2532 strlen(name)-strlen(GNUNET_GNS_TLD));
2533 memcpy(rh->name, name,
2534 strlen(name)-strlen(GNUNET_GNS_TLD) - 1);
2537 rh->authority_chain_head = GNUNET_malloc(sizeof(struct AuthorityChain));
2538 rh->authority_chain_tail = rh->authority_chain_head;
2539 rh->authority_chain_head->zone = zone;
2542 /* Start delegation resolution in our namestore */
2543 resolve_delegation_ns(rh);
2546 /*********** END NAME SHORTEN ********************/
2550 * Process result from namestore delegation lookup
2551 * for get authority operation
2553 * @param cls the client get auth handle
2554 * @param rh the resolver handle
2555 * @param rd_count number of results (0)
2556 * @param rd data (NULL)
2559 handle_delegation_result_ns_get_auth(void* cls,
2560 struct ResolverHandle *rh,
2562 const struct GNUNET_NAMESTORE_RecordData *rd)
2564 struct GetNameAuthorityHandle* nah;
2565 char result[MAX_DNS_NAME_LENGTH];
2568 nah = (struct GetNameAuthorityHandle*) rh->proc_cls;
2571 * At this point rh->name contains the part of the name
2572 * that we do not have a PKEY in our namestore to resolve.
2573 * The authority chain in the resolver handle is now
2574 * useful to backtrack if needed
2577 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2578 "PKEY resolved as far as possible in ns up to %s!\n", rh->name);
2580 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2581 "Building response!\n");
2582 if (is_canonical(rh->name))
2585 * We successfully resolved the authority in the ns
2586 * FIXME for our purposes this is fine
2587 * but maybe we want to have an api that also looks
2588 * into the dht (i.e. option in message)
2590 if (strlen(rh->name) > strlen(nah->name))
2592 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2593 "Record name longer than original lookup name... odd!\n");
2597 answer_len = strlen(nah->name) - strlen(rh->name)
2598 + strlen(GNUNET_GNS_TLD) + 1;
2599 memset(result, 0, answer_len);
2600 strcpy(result, nah->name + strlen(rh->name) + 1);
2602 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2603 "Got authority result %s\n", result);
2605 nah->proc(nah->proc_cls, result);
2607 free_resolver_handle(rh);
2611 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2612 "Unable to resolve authority for remaining %s!\n", rh->name);
2613 nah->proc(nah->proc_cls, "");
2615 free_resolver_handle(rh);
2623 * Tries to resolve the authority for name
2626 * @param zone the root zone to look up for
2627 * @param name the name to lookup up
2628 * @param proc the processor to call when finished
2629 * @param proc_cls the closure to pass to the processor
2632 gns_resolver_get_authority(struct GNUNET_CRYPTO_ShortHashCode zone,
2634 GetAuthorityResultProcessor proc,
2637 struct ResolverHandle *rh;
2638 struct GetNameAuthorityHandle *nah;
2640 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2641 "Starting authority resolution for %s!\n", name);
2643 nah = GNUNET_malloc(sizeof (struct GetNameAuthorityHandle));
2644 rh = GNUNET_malloc(sizeof (struct ResolverHandle));
2645 rh->authority = zone;
2648 if (strcmp(GNUNET_GNS_TLD, name) == 0)
2650 strcpy(rh->name, "\0");
2655 strlen(name)-strlen(GNUNET_GNS_TLD));
2656 memcpy(rh->name, name,
2657 strlen(name)-strlen(GNUNET_GNS_TLD) - 1);
2660 memset(nah->name, 0,
2662 strcpy(nah->name, name);
2664 rh->authority_chain_head = GNUNET_malloc(sizeof(struct AuthorityChain));
2665 rh->authority_chain_tail = rh->authority_chain_head;
2666 rh->authority_chain_head->zone = zone;
2667 rh->proc = &handle_delegation_result_ns_get_auth;
2668 rh->proc_cls = (void*)nah;
2671 nah->proc_cls = proc_cls;
2673 /* Start delegation resolution in our namestore */
2674 resolve_delegation_ns(rh);
2678 /******** END GET AUTHORITY *************/
2680 /* end of gnunet-service-gns_resolver.c */