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_LOOKUP_TIMEOUT DHT_OPERATION_TIMEOUT
42 #define DHT_GNS_REPLICATION_LEVEL 5
43 #define MAX_DNS_LABEL_LENGTH 63
47 * Our handle to the namestore service
49 static struct GNUNET_NAMESTORE_Handle *namestore_handle;
52 * Resolver handle to the dht
54 static struct GNUNET_DHT_Handle *dht_handle;
57 * Heap for parallel DHT lookups
59 static struct GNUNET_CONTAINER_Heap *dht_lookup_heap;
62 * Maximum amount of parallel queries in background
64 static unsigned long long max_allowed_background_queries;
67 * Wheather or not to ignore pending records
69 static int ignore_pending_records;
74 static struct GNUNET_CRYPTO_ShortHashCode local_zone;
77 * a resolution identifier pool variable
79 * This is a non critical identifier useful for debugging
81 static unsigned long long rid = 0;
85 * Determine if this name is canonical.
87 * a.b.gnunet = not canonical
90 * @param name the name to test
91 * @return 1 if canonical
94 is_canonical(char* name)
96 uint32_t len = strlen(name);
101 if (*(name+i) == '.')
109 * Callback that shortens authorities
111 * @param name the name given by delegation
112 * @param zone the authority
113 * @param our_zone our local zone
114 * @param key the private key of our authority
117 shorten_authority_chain (struct GetPseuAuthorityHandle *gph);
121 * Namestore calls this function if we have record for this name.
122 * (or with rd_count=0 to indicate no matches)
124 * @param cls the pending query
125 * @param key the key of the zone we did the lookup
126 * @param expiration expiration date of the namestore entry
127 * @param name the name for which we need an authority
128 * @param rd_count the number of records with 'name'
129 * @param rd the record data
130 * @param signature the signature of the authority for the record data
133 process_pseu_lookup_ns (void* cls,
134 const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *key,
135 struct GNUNET_TIME_Absolute expiration,
136 const char *name, unsigned int rd_count,
137 const struct GNUNET_NAMESTORE_RecordData *rd,
138 const struct GNUNET_CRYPTO_RsaSignature *signature)
140 struct GetPseuAuthorityHandle* gph = (struct GetPseuAuthorityHandle*)cls;
141 struct GNUNET_NAMESTORE_RecordData new_pkey;
142 struct AuthorityChain *iter;
146 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
147 "GNS_AUTO_PSEU: Name %s already taken in NS!\n", name);
148 if (0 == strcmp (gph->name, name))
150 if (gph->ahead->next != NULL)
152 if (GNUNET_CRYPTO_short_hash_cmp (&gph->ahead->next->zone,
155 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "GNS_GET_AUTH: trying next!\n");
156 iter = gph->ahead->next;
157 GNUNET_free (gph->ahead);
159 shorten_authority_chain (gph);
167 iter = gph->ahead->next;
168 GNUNET_free (gph->ahead);
170 } while (iter != NULL);
171 GNUNET_CRYPTO_rsa_key_free (gph->key);
177 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
178 "GNS_AUTO_PSEU: Trying delegated name %s\n", gph->name);
179 memcpy (gph->test_name, gph->name, strlen (gph->name)+1);
180 GNUNET_NAMESTORE_lookup_record (namestore_handle,
183 GNUNET_NAMESTORE_TYPE_ANY,
184 &process_pseu_lookup_ns,
190 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
191 "GNS_AUTO_PSEU: Name %s not taken in NS! Adding\n", gph->test_name);
193 new_pkey.expiration = GNUNET_TIME_UNIT_FOREVER_ABS;
194 new_pkey.data_size = sizeof (struct GNUNET_CRYPTO_ShortHashCode);
195 new_pkey.data = &gph->ahead->zone;
196 new_pkey.record_type = GNUNET_GNS_RECORD_PKEY;
197 new_pkey.flags = GNUNET_NAMESTORE_RF_AUTHORITY
198 | GNUNET_NAMESTORE_RF_PRIVATE
199 | GNUNET_NAMESTORE_RF_PENDING;
200 GNUNET_NAMESTORE_record_create (namestore_handle,
208 iter = gph->ahead->next;
209 GNUNET_free (gph->ahead);
211 } while (iter != NULL);
212 GNUNET_CRYPTO_rsa_key_free (gph->key);
218 * process result of a dht pseu lookup
220 * @param gph the handle
221 * @param name the pseu result or NULL
224 process_pseu_result (struct GetPseuAuthorityHandle* gph, char* name)
228 memcpy (gph->test_name, gph->ahead->name, strlen (gph->ahead->name)+1);
232 memcpy (gph->test_name, name, strlen(name)+1);
235 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
236 "GNS_AUTO_PSEU: Checking %s for collision in NS\n",
240 * Check for collision
242 GNUNET_NAMESTORE_lookup_record (namestore_handle,
245 GNUNET_NAMESTORE_TYPE_ANY,
246 &process_pseu_lookup_ns,
251 * Handle timeout for dht request
253 * @param cls the request handle as closure
254 * @param tc the task context
257 handle_auth_discovery_timeout(void *cls,
258 const struct GNUNET_SCHEDULER_TaskContext *tc)
260 struct GetPseuAuthorityHandle* gph = (struct GetPseuAuthorityHandle*)cls;
261 struct AuthorityChain *iter;
263 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
264 "GNS_GET_AUTH: dht lookup for query PSEU timed out.\n");
265 GNUNET_DHT_get_stop (gph->get_handle);
266 gph->get_handle = NULL;
268 if (gph->ahead->next != NULL)
270 if (GNUNET_CRYPTO_short_hash_cmp (&gph->ahead->next->zone,
273 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "GNS_GET_AUTH: trying next!\n");
274 iter = gph->ahead->next;
275 GNUNET_free (gph->ahead);
277 shorten_authority_chain (gph);
282 process_pseu_result (gph, NULL);
286 * Function called when we find a PSEU entry in the DHT
288 * @param cls the request handle
289 * @param exp lifetime
290 * @param key the key the record was stored under
291 * @param get_path get path
292 * @param get_path_length get path length
293 * @param put_path put path
294 * @param put_path_length put path length
295 * @param type the block type
296 * @param size the size of the record
297 * @param data the record data
300 process_auth_discovery_dht_result(void* cls,
301 struct GNUNET_TIME_Absolute exp,
302 const struct GNUNET_HashCode * key,
303 const struct GNUNET_PeerIdentity *get_path,
304 unsigned int get_path_length,
305 const struct GNUNET_PeerIdentity *put_path,
306 unsigned int put_path_length,
307 enum GNUNET_BLOCK_Type type,
308 size_t size, const void *data)
310 struct GetPseuAuthorityHandle* gph = (struct GetPseuAuthorityHandle*)cls;
311 struct AuthorityChain *iter;
312 struct GNSNameRecordBlock *nrb;
313 char* rd_data = (char*)data;
319 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
320 "GNS_GET_AUTH: got dht result (size=%d)\n", size);
324 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
325 "GNS_GET_AUTH: got dht result null!\n", size);
329 iter = gph->ahead->next;
330 GNUNET_free (gph->ahead);
332 } while (iter != NULL);
333 GNUNET_CRYPTO_rsa_key_free (gph->key);
338 nrb = (struct GNSNameRecordBlock*)data;
340 /* stop lookup and timeout task */
341 GNUNET_DHT_get_stop (gph->get_handle);
342 gph->get_handle = NULL;
343 GNUNET_SCHEDULER_cancel (gph->timeout);
345 gph->get_handle = NULL;
347 nrb = (struct GNSNameRecordBlock*)data;
349 name = (char*)&nrb[1];
350 num_records = ntohl (nrb->rd_count);
352 struct GNUNET_NAMESTORE_RecordData rd[num_records];
354 rd_data += strlen (name) + 1 + sizeof (struct GNSNameRecordBlock);
355 rd_size = size - strlen (name) - 1 - sizeof (struct GNSNameRecordBlock);
357 if (GNUNET_SYSERR == GNUNET_NAMESTORE_records_deserialize (rd_size,
362 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
363 "GNS_GET_AUTH: Error deserializing data!\n");
367 for (i=0; i < num_records; i++)
369 if ((strcmp (name, "+") == 0) &&
370 (rd[i].record_type == GNUNET_GNS_RECORD_PSEU))
373 process_pseu_result (gph, (char*)rd[i].data);
380 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "GNS_GET_AUTH: no pseu in dht!\n");
382 if (gph->ahead->next != NULL)
384 if (GNUNET_CRYPTO_short_hash_cmp (&gph->ahead->next->zone,
387 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "GNS_GET_AUTH: trying next!\n");
388 iter = gph->ahead->next;
389 GNUNET_free (gph->ahead);
391 shorten_authority_chain (gph);
395 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
396 "GNS_GET_AUTH: finished shorten, no results!\n");
397 process_pseu_result (gph, NULL);
401 * Process PSEU discovery for shorten via namestore
403 * @param cls the GetPseuAuthorityHandle
404 * @param key the public key
405 * @param expiration recorddata expiration
406 * @param name the looked up name
407 * @param rd_count number of records in set
408 * @param rd record data
409 * @param signature the signature
412 process_auth_discovery_ns_result(void* cls,
413 const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *key,
414 struct GNUNET_TIME_Absolute expiration,
416 unsigned int rd_count,
417 const struct GNUNET_NAMESTORE_RecordData *rd,
418 const struct GNUNET_CRYPTO_RsaSignature *signature)
421 struct GNUNET_CRYPTO_ShortHashCode name_hash;
422 struct GNUNET_HashCode lookup_key;
423 struct GNUNET_CRYPTO_HashAsciiEncoded lookup_key_string;
424 struct GNUNET_HashCode name_hash_double;
425 struct GNUNET_HashCode zone_hash_double;
427 struct GetPseuAuthorityHandle* gph = (struct GetPseuAuthorityHandle*)cls;
428 struct AuthorityChain *iter;
436 GNUNET_CRYPTO_short_hash ("+", strlen ("+"), &name_hash);
437 GNUNET_CRYPTO_short_hash_double (&name_hash, &name_hash_double);
438 GNUNET_CRYPTO_short_hash_double (&gph->ahead->zone, &zone_hash_double);
439 GNUNET_CRYPTO_hash_xor (&name_hash_double, &zone_hash_double, &lookup_key);
440 GNUNET_CRYPTO_hash_to_enc (&lookup_key, &lookup_key_string);
442 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
443 "GNS_AUTO_PSEU: starting dht lookup for %s with key: %s\n",
444 "+", (char*)&lookup_key_string);
446 gph->timeout = GNUNET_SCHEDULER_add_delayed (DHT_LOOKUP_TIMEOUT,
447 &handle_auth_discovery_timeout, gph);
449 xquery = htonl (GNUNET_GNS_RECORD_PSEU);
451 GNUNET_assert (gph->get_handle == NULL);
453 gph->get_handle = GNUNET_DHT_get_start(dht_handle,
454 GNUNET_BLOCK_TYPE_GNS_NAMERECORD,
456 DHT_GNS_REPLICATION_LEVEL,
460 &process_auth_discovery_dht_result,
465 for (i=0; i < rd_count; i++)
467 if ((strcmp (name, "+") == 0) &&
468 (rd[i].record_type == GNUNET_GNS_RECORD_PSEU))
471 process_pseu_result (gph, (char*)rd[i].data);
476 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "GNS_GET_AUTH: no pseu in namestore!\n");
478 if (gph->ahead->next != NULL)
480 if (GNUNET_CRYPTO_short_hash_cmp (&gph->ahead->next->zone,
483 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "GNS_GET_AUTH: trying next!\n");
484 iter = gph->ahead->next;
485 GNUNET_free (gph->ahead);
487 shorten_authority_chain (gph);
492 process_pseu_result (gph, NULL);
496 * Callback called by namestore for a zone to name
499 * @param cls the closure
500 * @param zone_key the zone we queried
501 * @param expire the expiration time of the name
502 * @param name the name found or NULL
503 * @param rd_len number of records for the name
504 * @param rd the record data (PKEY) for the name
505 * @param signature the signature for the record data
508 process_zone_to_name_discover (void *cls,
509 const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *zone_key,
510 struct GNUNET_TIME_Absolute expire,
513 const struct GNUNET_NAMESTORE_RecordData *rd,
514 const struct GNUNET_CRYPTO_RsaSignature *signature)
516 struct GetPseuAuthorityHandle* gph = (struct GetPseuAuthorityHandle*)cls;
517 struct AuthorityChain *iter;
519 /* we found a match in our own zone */
522 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
523 "GNS_AUTO_PSEU: name for zone in our root %s\n", name);
528 iter = gph->ahead->next;
529 GNUNET_free (gph->ahead);
531 } while (iter != NULL);
532 GNUNET_CRYPTO_rsa_key_free (gph->key);
538 GNUNET_NAMESTORE_lookup_record (namestore_handle,
541 GNUNET_GNS_RECORD_PSEU,
542 &process_auth_discovery_ns_result,
550 * Callback that shortens authorities
552 * @param name the name given by delegation
553 * @param zone the authority
554 * @param our_zone our local zone
555 * @param key the private key of our authority
558 shorten_authority_chain (struct GetPseuAuthorityHandle *gph)
561 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
562 "GNS_AUTO_PSEU: New authority %s discovered\n",
565 GNUNET_NAMESTORE_zone_to_name (namestore_handle,
568 &process_zone_to_name_discover,
574 start_shorten (struct AuthorityChain *atail,
575 struct GNUNET_CRYPTO_RsaPrivateKey *key)
577 struct AuthorityChain *new_head = NULL;
578 struct AuthorityChain *new_tail = NULL;
579 struct AuthorityChain *iter;
580 struct AuthorityChain *acopy;
581 struct GetPseuAuthorityHandle *gph;
582 struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded pkey;
583 struct GNUNET_CRYPTO_RsaPrivateKeyBinaryEncoded *pb_key;
585 /* First copy the authority chain in reverse order */
586 for (iter = atail; iter != NULL; iter = iter->prev)
588 acopy = GNUNET_malloc (sizeof (struct AuthorityChain));
589 memcpy (acopy, iter, sizeof (struct AuthorityChain));
592 GNUNET_CONTAINER_DLL_insert (new_head, new_tail, acopy);
595 gph = GNUNET_malloc (sizeof (struct GetPseuAuthorityHandle));
597 GNUNET_CRYPTO_rsa_key_get_public (key, &pkey);
598 pb_key = GNUNET_CRYPTO_rsa_encode_key (key);
599 gph->key = GNUNET_CRYPTO_rsa_decode_key ((char*)pb_key, ntohs (pb_key->len));
600 //gph->key = key;//GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_RsaPrivateKey));
601 //memcpy (gph->key, key, sizeof (struct GNUNET_CRYPTO_RsaPrivateKey));
603 GNUNET_CRYPTO_short_hash (&pkey,
604 sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded),
606 gph->ahead = new_head;
608 shorten_authority_chain (gph);
612 * Initialize the resolver
614 * @param nh the namestore handle
615 * @param dh the dht handle
616 * @param lz the local zone's hash
617 * @param max_bg_queries maximum number of parallel background queries in dht
618 * @param ignore_pending ignore records that still require user confirmation
620 * @return GNUNET_OK on success
623 gns_resolver_init(struct GNUNET_NAMESTORE_Handle *nh,
624 struct GNUNET_DHT_Handle *dh,
625 struct GNUNET_CRYPTO_ShortHashCode lz,
626 unsigned long long max_bg_queries,
629 namestore_handle = nh;
633 GNUNET_CONTAINER_heap_create(GNUNET_CONTAINER_HEAP_ORDER_MIN);
634 max_allowed_background_queries = max_bg_queries;
635 ignore_pending_records = ignore_pending;
637 if ((namestore_handle != NULL) && (dht_handle != NULL))
641 return GNUNET_SYSERR;
645 * Cleanup background lookups
647 * @param cls closure to iterator
648 * @param node heap nodes
649 * @param element the resolver handle
650 * @param cost heap cost
651 * @return always GNUNET_YES
654 cleanup_pending_background_queries(void* cls,
655 struct GNUNET_CONTAINER_HeapNode *node,
657 GNUNET_CONTAINER_HeapCostType cost)
659 struct ResolverHandle *rh = (struct ResolverHandle *)element;
660 ResolverCleanupContinuation cont = cls;
662 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
663 "GNS_CLEANUP-%llu: Terminating background lookup for %s\n",
665 GNUNET_DHT_get_stop(rh->get_handle);
666 rh->get_handle = NULL;
667 rh->proc(rh->proc_cls, rh, 0, NULL);
669 GNUNET_CONTAINER_heap_remove_node(node);
671 if (GNUNET_CONTAINER_heap_get_size(dht_lookup_heap) == 0)
683 gns_resolver_cleanup(ResolverCleanupContinuation cont)
685 unsigned int s = GNUNET_CONTAINER_heap_get_size(dht_lookup_heap);
686 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
687 "GNS_CLEANUP: %d pending background queries to terminate\n", s);
690 GNUNET_CONTAINER_heap_iterate (dht_lookup_heap,
691 &cleanup_pending_background_queries,
699 * Helper function to free resolver handle
701 * @param rh the handle to free
704 free_resolver_handle(struct ResolverHandle* rh)
706 struct AuthorityChain *ac;
707 struct AuthorityChain *ac_next;
712 ac = rh->authority_chain_head;
725 * Callback when record data is put into namestore
727 * @param cls the closure
728 * @param success GNUNET_OK on success
729 * @param emsg the error message. NULL if SUCCESS==GNUNET_OK
732 on_namestore_record_put_result(void *cls,
736 if (GNUNET_NO == success)
738 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
739 "GNS_NS: records already in namestore\n");
742 else if (GNUNET_YES == success)
744 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
745 "GNS_NS: records successfully put in namestore\n");
749 GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
750 "GNS_NS: Error putting records into namestore: %s\n", emsg);
754 handle_lookup_timeout(void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
756 struct ResolverHandle *rh = cls;
758 if (rh->timeout_cont)
759 rh->timeout_cont(rh->timeout_cont_cls, tc);
763 * Processor for background lookups in the DHT
765 * @param cls closure (NULL)
766 * @param rd_count number of records found (not 0)
767 * @param rd record data
770 background_lookup_result_processor(void *cls,
772 const struct GNUNET_NAMESTORE_RecordData *rd)
774 //We could do sth verbose/more useful here but it doesn't make any difference
775 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
776 "GNS_BG: background dht lookup for finished. (%d results)\n",
781 * Handle timeout for DHT requests
783 * @param cls the request handle as closure
784 * @param tc the task context
787 dht_lookup_timeout(void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
789 struct ResolverHandle *rh = cls;
790 struct RecordLookupHandle *rlh = (struct RecordLookupHandle *)rh->proc_cls;
791 char new_name[MAX_DNS_NAME_LENGTH];
793 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
794 "GNS_PHASE_REC-%d: dht lookup for query %s (%ds)timed out.\n",
795 rh->id, rh->name, rh->timeout.rel_value);
797 * Start resolution in bg
799 //strcpy(new_name, rh->name);
800 //memcpy(new_name+strlen(new_name), GNUNET_GNS_TLD, strlen(GNUNET_GNS_TLD));
801 GNUNET_snprintf(new_name, MAX_DNS_NAME_LENGTH, "%s.%s",
802 rh->name, GNUNET_GNS_TLD);
804 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
805 "GNS_PHASE_REC-%d: Starting background lookup for %s type %d\n",
806 rh->id, new_name, rlh->record_type);
808 gns_resolver_lookup_record(rh->authority,
809 rh->private_local_zone,
813 GNUNET_TIME_UNIT_FOREVER_REL,
815 &background_lookup_result_processor,
817 rh->timeout_task = GNUNET_SCHEDULER_NO_TASK;
819 GNUNET_DHT_get_stop (rh->get_handle);
820 rh->get_handle = NULL;
821 rh->proc(rh->proc_cls, rh, 0, NULL);
826 * Function called when we get a result from the dht
827 * for our record query
829 * @param cls the request handle
830 * @param exp lifetime
831 * @param key the key the record was stored under
832 * @param get_path get path
833 * @param get_path_length get path length
834 * @param put_path put path
835 * @param put_path_length put path length
836 * @param type the block type
837 * @param size the size of the record
838 * @param data the record data
841 process_record_result_dht(void* cls,
842 struct GNUNET_TIME_Absolute exp,
843 const struct GNUNET_HashCode * key,
844 const struct GNUNET_PeerIdentity *get_path,
845 unsigned int get_path_length,
846 const struct GNUNET_PeerIdentity *put_path,
847 unsigned int put_path_length,
848 enum GNUNET_BLOCK_Type type,
849 size_t size, const void *data)
851 struct ResolverHandle *rh;
852 struct RecordLookupHandle *rlh;
853 struct GNSNameRecordBlock *nrb;
854 uint32_t num_records;
856 char* rd_data = (char*)data;
860 rh = (struct ResolverHandle *)cls;
861 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
862 "GNS_PHASE_REC-%d: got dht result (size=%d)\n", rh->id, size);
867 //FIXME maybe check expiration here, check block type
870 rlh = (struct RecordLookupHandle *) rh->proc_cls;
871 nrb = (struct GNSNameRecordBlock*)data;
873 /* stop lookup and timeout task */
874 GNUNET_DHT_get_stop (rh->get_handle);
875 rh->get_handle = NULL;
877 if (rh->dht_heap_node != NULL)
879 GNUNET_CONTAINER_heap_remove_node(rh->dht_heap_node);
880 rh->dht_heap_node = NULL;
883 if (rh->timeout_task != GNUNET_SCHEDULER_NO_TASK)
885 GNUNET_SCHEDULER_cancel(rh->timeout_task);
886 rh->timeout_task = GNUNET_SCHEDULER_NO_TASK;
889 rh->get_handle = NULL;
890 name = (char*)&nrb[1];
891 num_records = ntohl(nrb->rd_count);
893 struct GNUNET_NAMESTORE_RecordData rd[num_records];
895 rd_data += strlen(name) + 1 + sizeof(struct GNSNameRecordBlock);
896 rd_size = size - strlen(name) - 1 - sizeof(struct GNSNameRecordBlock);
898 if (GNUNET_SYSERR == GNUNET_NAMESTORE_records_deserialize (rd_size,
903 GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
904 "GNS_PHASE_REC-%d: Error deserializing data!\n", rh->id);
908 for (i=0; i<num_records; i++)
910 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
911 "GNS_PHASE_REC-%d: Got name: %s (wanted %s)\n",
912 rh->id, name, rh->name);
913 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
914 "GNS_PHASE_REC-%d: Got type: %d\n",
915 rh->id, rd[i].record_type);
916 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
917 "GNS_PHASE_REC-%d: Got data length: %d\n",
918 rh->id, rd[i].data_size);
919 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
920 "GNS_PHASE_REC-%d: Got flag %d\n",
921 rh->id, rd[i].flags);
923 if ((strcmp(name, rh->name) == 0) &&
924 (rd[i].record_type == rlh->record_type))
932 * FIXME check pubkey against existing key in namestore?
933 * https://gnunet.org/bugs/view.php?id=2179
936 /* Save to namestore */
937 GNUNET_NAMESTORE_record_put (namestore_handle,
944 &on_namestore_record_put_result, //cont
949 rh->proc(rh->proc_cls, rh, num_records, rd);
951 rh->proc(rh->proc_cls, rh, 0, NULL);
958 * Start DHT lookup for a (name -> query->record_type) record in
959 * rh->authority's zone
961 * @param rh the pending gns query context
964 resolve_record_dht(struct ResolverHandle *rh)
967 struct GNUNET_CRYPTO_ShortHashCode name_hash;
968 struct GNUNET_HashCode lookup_key;
969 struct GNUNET_HashCode name_hash_double;
970 struct GNUNET_HashCode zone_hash_double;
971 struct GNUNET_CRYPTO_HashAsciiEncoded lookup_key_string;
972 struct RecordLookupHandle *rlh = (struct RecordLookupHandle *)rh->proc_cls;
973 struct ResolverHandle *rh_heap_root;
975 GNUNET_CRYPTO_short_hash(rh->name, strlen(rh->name), &name_hash);
976 GNUNET_CRYPTO_short_hash_double(&name_hash, &name_hash_double);
977 GNUNET_CRYPTO_short_hash_double(&rh->authority, &zone_hash_double);
978 GNUNET_CRYPTO_hash_xor(&name_hash_double, &zone_hash_double, &lookup_key);
979 GNUNET_CRYPTO_hash_to_enc (&lookup_key, &lookup_key_string);
981 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
982 "GNS_PHASE_REC-%d: starting dht lookup for %s with key: %s\n",
983 rh->id, rh->name, (char*)&lookup_key_string);
985 //rh->timeout_task = GNUNET_SCHEDULER_NO_TASK;
986 rh->dht_heap_node = NULL;
988 if (rh->timeout.rel_value != GNUNET_TIME_UNIT_FOREVER_REL.rel_value)
991 * Update timeout if necessary
993 if (rh->timeout_task == GNUNET_SCHEDULER_NO_TASK)
996 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
997 "GNS_PHASE_REC-%d: Adjusting timeout\n", rh->id);
999 * Set timeout for authority lookup phase to 1/2
1001 rh->timeout_task = GNUNET_SCHEDULER_add_delayed(
1002 GNUNET_TIME_relative_divide(rh->timeout, 2),
1003 &handle_lookup_timeout,
1006 //rh->timeout_task = GNUNET_SCHEDULER_add_delayed (DHT_LOOKUP_TIMEOUT,
1007 // &dht_lookup_timeout,
1009 rh->timeout_cont = &dht_lookup_timeout;
1010 rh->timeout_cont_cls = rh;
1014 if (max_allowed_background_queries <=
1015 GNUNET_CONTAINER_heap_get_size (dht_lookup_heap))
1017 rh_heap_root = GNUNET_CONTAINER_heap_remove_root (dht_lookup_heap);
1018 GNUNET_DHT_get_stop(rh_heap_root->get_handle);
1019 rh_heap_root->get_handle = NULL;
1020 rh_heap_root->dht_heap_node = NULL;
1022 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1023 "GNS_PHASE_REC-%d: Replacing oldest background query for %s\n",
1024 rh->id, rh_heap_root->name);
1025 rh_heap_root->proc(rh_heap_root->proc_cls,
1030 rh->dht_heap_node = GNUNET_CONTAINER_heap_insert (dht_lookup_heap,
1032 GNUNET_TIME_absolute_get().abs_value);
1035 xquery = htonl(rlh->record_type);
1037 GNUNET_assert(rh->get_handle == NULL);
1038 rh->get_handle = GNUNET_DHT_get_start(dht_handle,
1039 GNUNET_BLOCK_TYPE_GNS_NAMERECORD,
1041 DHT_GNS_REPLICATION_LEVEL,
1045 &process_record_result_dht,
1052 * Namestore calls this function if we have record for this name.
1053 * (or with rd_count=0 to indicate no matches)
1055 * @param cls the pending query
1056 * @param key the key of the zone we did the lookup
1057 * @param expiration expiration date of the namestore entry
1058 * @param name the name for which we need an authority
1059 * @param rd_count the number of records with 'name'
1060 * @param rd the record data
1061 * @param signature the signature of the authority for the record data
1064 process_record_result_ns(void* cls,
1065 const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *key,
1066 struct GNUNET_TIME_Absolute expiration,
1067 const char *name, unsigned int rd_count,
1068 const struct GNUNET_NAMESTORE_RecordData *rd,
1069 const struct GNUNET_CRYPTO_RsaSignature *signature)
1071 struct ResolverHandle *rh;
1072 struct RecordLookupHandle *rlh;
1073 struct GNUNET_TIME_Relative remaining_time;
1074 struct GNUNET_CRYPTO_ShortHashCode zone;
1076 rh = (struct ResolverHandle *) cls;
1077 rlh = (struct RecordLookupHandle *)rh->proc_cls;
1078 GNUNET_CRYPTO_short_hash(key,
1079 sizeof(struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded),
1081 remaining_time = GNUNET_TIME_absolute_get_remaining (expiration);
1089 rh->status |= RSL_RECORD_EXISTS;
1092 if (remaining_time.rel_value == 0)
1094 rh->status |= RSL_RECORD_EXPIRED;
1100 * Lookup terminated and no results
1102 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1103 "GNS_PHASE_REC-%d: Namestore lookup for %s terminated without results\n",
1106 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1107 "GNS_PHASE_REC-%d: Record %s unknown in namestore\n",
1110 * Our zone and no result? Cannot resolve TT
1112 rh->proc(rh->proc_cls, rh, 0, NULL);
1119 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1120 "GNS_PHASE_REC-%d: Processing additional result %s from namestore\n",
1123 for (i=0; i<rd_count;i++)
1126 if (rd[i].record_type != rlh->record_type)
1129 if (ignore_pending_records &&
1130 (rd[i].flags & GNUNET_NAMESTORE_RF_PENDING))
1132 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1133 "GNS_PHASE_REC-%d: Record %s is awaiting user confirmation. Skipping\n",
1138 if ((GNUNET_TIME_absolute_get_remaining (rd[i].expiration)).rel_value
1141 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1142 "GNS_PHASE_REC-%d: This record is expired. Skipping\n",
1154 if (rh->answered == 0)
1156 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1157 "GNS_PHASE_REC-%d: No answers found. This is odd!\n", rh->id);
1158 rh->proc(rh->proc_cls, rh, 0, NULL);
1162 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1163 "GNS_PHASE_REC-%d: Found %d answer(s) to query in %d records!\n",
1164 rh->id, rh->answered, rd_count);
1166 rh->proc(rh->proc_cls, rh, rd_count, rd);
1172 * The final phase of resolution.
1173 * rh->name is a name that is canonical and we do not have a delegation.
1174 * Query namestore for this record
1176 * @param rh the pending lookup
1179 resolve_record_ns(struct ResolverHandle *rh)
1181 struct RecordLookupHandle *rlh = (struct RecordLookupHandle *)rh->proc_cls;
1183 /* We cancel here as to not include the ns lookup in the timeout */
1184 if (rh->timeout_task != GNUNET_SCHEDULER_NO_TASK)
1186 GNUNET_SCHEDULER_cancel(rh->timeout_task);
1187 rh->timeout_task = GNUNET_SCHEDULER_NO_TASK;
1189 /* Start shortening */
1190 if ((rh->priv_key != NULL) && is_canonical (rh->name))
1192 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1193 "GNS_PHASE_REC-%llu: Trying to shorten authority chain\n",
1195 start_shorten (rh->authority_chain_tail,
1200 * Try to resolve this record in our namestore.
1201 * The name to resolve is now in rh->authority_name
1202 * since we tried to resolve it to an authority
1205 GNUNET_NAMESTORE_lookup_record(namestore_handle,
1209 &process_record_result_ns,
1216 * Handle timeout for DHT requests
1218 * @param cls the request handle as closure
1219 * @param tc the task context
1222 dht_authority_lookup_timeout(void *cls,
1223 const struct GNUNET_SCHEDULER_TaskContext *tc)
1225 struct ResolverHandle *rh = cls;
1226 struct RecordLookupHandle *rlh = rh->proc_cls;
1227 char new_name[MAX_DNS_NAME_LENGTH];
1229 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1230 "GNS_PHASE_DELEGATE_DHT-%llu: dht lookup for query %s (%ds)timed out.\n",
1231 rh->id, rh->authority_name, rh->timeout.rel_value);
1233 rh->status |= RSL_TIMED_OUT;
1235 rh->timeout_task = GNUNET_SCHEDULER_NO_TASK;
1237 GNUNET_DHT_get_stop (rh->get_handle);
1238 rh->get_handle = NULL;
1240 if (strcmp(rh->name, "") == 0)
1243 * promote authority back to name and try to resolve record
1245 strcpy(rh->name, rh->authority_name);
1246 rh->proc(rh->proc_cls, rh, 0, NULL);
1251 * Start resolution in bg
1253 GNUNET_snprintf(new_name, MAX_DNS_NAME_LENGTH,
1254 "%s.%s.%s", rh->name, rh->authority_name, GNUNET_GNS_TLD);
1255 //strcpy(new_name, rh->name);
1256 //strcpy(new_name+strlen(new_name), ".");
1257 //memcpy(new_name+strlen(new_name), GNUNET_GNS_TLD, strlen(GNUNET_GNS_TLD));
1259 strcpy(rh->name, new_name);
1261 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1262 "GNS_PHASE_DELEGATE_DHT-%llu: Starting background query for %s type %d\n",
1263 rh->id, rh->name, rlh->record_type);
1265 gns_resolver_lookup_record(rh->authority,
1266 rh->private_local_zone,
1270 GNUNET_TIME_UNIT_FOREVER_REL,
1272 &background_lookup_result_processor,
1275 rh->proc(rh->proc_cls, rh, 0, NULL);
1279 static void resolve_delegation_dht(struct ResolverHandle *rh);
1282 static void resolve_delegation_ns(struct ResolverHandle *rh);
1286 * Namestore resolution for delegation finished. Processing result.
1288 * @param cls the closure
1289 * @param rh resolver handle
1290 * @param rd_count number of results (always 0)
1291 * @param rd record data (always NULL)
1294 handle_delegation_ns(void* cls, struct ResolverHandle *rh,
1295 unsigned int rd_count,
1296 const struct GNUNET_NAMESTORE_RecordData *rd);
1300 * Function called when we get a result from the dht
1301 * for our query. Recursively tries to resolve authorities
1304 * @param cls the request handle
1305 * @param exp lifetime
1306 * @param key the key the record was stored under
1307 * @param get_path get path
1308 * @param get_path_length get path length
1309 * @param put_path put path
1310 * @param put_path_length put path length
1311 * @param type the block type
1312 * @param size the size of the record
1313 * @param data the record data
1316 process_delegation_result_dht(void* cls,
1317 struct GNUNET_TIME_Absolute exp,
1318 const struct GNUNET_HashCode * key,
1319 const struct GNUNET_PeerIdentity *get_path,
1320 unsigned int get_path_length,
1321 const struct GNUNET_PeerIdentity *put_path,
1322 unsigned int put_path_length,
1323 enum GNUNET_BLOCK_Type type,
1324 size_t size, const void *data)
1326 struct ResolverHandle *rh;
1327 struct GNSNameRecordBlock *nrb;
1328 uint32_t num_records;
1330 char* rd_data = (char*) data;
1333 struct GNUNET_CRYPTO_ShortHashCode zone, name_hash;
1334 struct GNUNET_HashCode zone_hash_double, name_hash_double;
1336 rh = (struct ResolverHandle *)cls;
1338 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1339 "GNS_PHASE_DELEGATE_DHT-%llu: Got DHT result\n", rh->id);
1344 nrb = (struct GNSNameRecordBlock*)data;
1346 /* stop dht lookup and timeout task */
1347 GNUNET_DHT_get_stop (rh->get_handle);
1349 rh->get_handle = NULL;
1351 if (rh->dht_heap_node != NULL)
1353 GNUNET_CONTAINER_heap_remove_node(rh->dht_heap_node);
1354 rh->dht_heap_node = NULL;
1357 num_records = ntohl(nrb->rd_count);
1358 name = (char*)&nrb[1];
1360 struct GNUNET_NAMESTORE_RecordData rd[num_records];
1362 rd_data += strlen(name) + 1 + sizeof(struct GNSNameRecordBlock);
1363 rd_size = size - strlen(name) - 1 - sizeof(struct GNSNameRecordBlock);
1365 if (GNUNET_SYSERR == GNUNET_NAMESTORE_records_deserialize (rd_size,
1370 GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
1371 "GNS_PHASE_DELEGATE_DHT-%llu: Error deserializing data!\n",
1376 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1377 "GNS_PHASE_DELEGATE_DHT-%llu: Got name: %s (wanted %s)\n",
1378 rh->id, name, rh->authority_name);
1379 for (i=0; i<num_records; i++)
1382 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1383 "GNS_PHASE_DELEGATE_DHT-%llu: Got name: %s (wanted %s)\n",
1384 rh->id, name, rh->authority_name);
1385 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1386 "GNS_PHASE_DELEGATE_DHT-%llu: Got type: %d (wanted %d)\n",
1387 rh->id, rd[i].record_type, GNUNET_GNS_RECORD_PKEY);
1388 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1389 "GNS_PHASE_DELEGATE_DHT-%llu: Got data length: %d\n",
1390 rh->id, rd[i].data_size);
1391 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1392 "GNS_PHASE_DELEGATE_DHT-%llu: Got flag %d\n",
1393 rh->id, rd[i].flags);
1395 if ((strcmp(name, rh->authority_name) == 0) &&
1396 (rd[i].record_type == GNUNET_GNS_RECORD_PKEY))
1398 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1399 "GNS_PHASE_DELEGATE_DHT-%llu: Authority found in DHT\n",
1402 memcpy(&rh->authority, rd[i].data, sizeof(struct GNUNET_CRYPTO_ShortHashCode));
1403 struct AuthorityChain *auth =
1404 GNUNET_malloc(sizeof(struct AuthorityChain));
1405 auth->zone = rh->authority;
1406 memset(auth->name, 0, strlen(rh->authority_name)+1);
1407 strcpy(auth->name, rh->authority_name);
1408 GNUNET_CONTAINER_DLL_insert (rh->authority_chain_head,
1409 rh->authority_chain_tail,
1412 /** try to import pkey if private key available */
1413 //if (rh->priv_key && is_canonical (rh->name))
1414 // process_discovered_authority(name, auth->zone,
1415 // rh->authority_chain_tail->zone,
1422 GNUNET_CRYPTO_short_hash(name, strlen(name), &name_hash);
1423 GNUNET_CRYPTO_short_hash_double(&name_hash, &name_hash_double);
1424 GNUNET_CRYPTO_hash_xor(key, &name_hash_double, &zone_hash_double);
1425 GNUNET_CRYPTO_short_hash_from_truncation (&zone_hash_double, &zone);
1427 /* Save to namestore */
1428 if (0 != GNUNET_CRYPTO_short_hash_cmp(&rh->authority_chain_tail->zone,
1431 GNUNET_NAMESTORE_record_put (namestore_handle,
1438 &on_namestore_record_put_result, //cont
1448 * FIXME in this case. should we ask namestore again?
1450 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1451 "GNS_PHASE_DELEGATE_DHT-%llu: Answer from DHT for %s. Yet to resolve: %s\n",
1452 rh->id, rh->authority_name, rh->name);
1454 if (strcmp(rh->name, "") == 0)
1456 /* Start shortening */
1457 if ((rh->priv_key != NULL) && is_canonical (rh->name))
1459 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1460 "GNS_PHASE_DELEGATE_DHT-%llu: Trying to shorten authority chain\n",
1462 start_shorten (rh->authority_chain_tail,
1466 rh->proc(rh->proc_cls, rh, 0, NULL);
1470 rh->proc = &handle_delegation_ns;
1471 resolve_delegation_ns(rh);
1477 * No pkey but name exists
1480 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1481 "GNS_PHASE_DELEGATE_DHT-%llu: Adding %s back to %s\n",
1482 rh->id, rh->authority_name, rh->name);
1483 if (strcmp(rh->name, "") == 0)
1484 strcpy(rh->name, rh->authority_name);
1486 GNUNET_snprintf(rh->name, MAX_DNS_NAME_LENGTH, "%s.%s",
1487 rh->name, rh->authority_name); //FIXME ret
1489 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1490 "GNS_PHASE_DELEGATE_DHT-%llu: %s restored\n", rh->id, rh->name);
1491 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1492 "GNS_PHASE_DELEGATE_DHT-%llu: DHT authority lookup found no match!\n",
1494 rh->proc(rh->proc_cls, rh, 0, NULL);
1497 #define MAX_SOA_LENGTH sizeof(uint32_t)+sizeof(uint32_t)+sizeof(uint32_t)+sizeof(uint32_t)\
1498 +(MAX_DNS_NAME_LENGTH*2)
1499 #define MAX_MX_LENGTH sizeof(uint16_t)+MAX_DNS_NAME_LENGTH
1503 expand_plus(char** dest, char* src, char* repl)
1506 unsigned int s_len = strlen(src)+1;
1508 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1509 "GNS_POSTPROCESS: Got %s to expand with %s\n", src, repl);
1513 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1514 "GNS_POSTPROCESS: %s to short\n", src);
1516 /* no postprocessing */
1517 memcpy(*dest, src, s_len+1);
1521 if (0 == strcmp(src+s_len-3, ".+"))
1523 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1524 "GNS_POSTPROCESS: Expanding .+ in %s\n", src);
1525 memset(*dest, 0, s_len+strlen(repl)+strlen(GNUNET_GNS_TLD));
1527 pos = *dest+s_len-2;
1529 pos += strlen(repl);
1530 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1531 "GNS_POSTPROCESS: Expanded to %s\n", *dest);
1535 memcpy(*dest, src, s_len+1);
1543 finish_lookup(struct ResolverHandle *rh,
1544 struct RecordLookupHandle* rlh,
1545 unsigned int rd_count,
1546 const struct GNUNET_NAMESTORE_RecordData *rd)
1549 char new_rr_data[MAX_DNS_NAME_LENGTH];
1550 char new_mx_data[MAX_MX_LENGTH];
1551 char new_soa_data[MAX_SOA_LENGTH];
1552 struct GNUNET_NAMESTORE_RecordData p_rd[rd_count];
1555 unsigned int offset;
1557 if (rh->timeout_task != GNUNET_SCHEDULER_NO_TASK)
1559 GNUNET_SCHEDULER_cancel(rh->timeout_task);
1560 rh->timeout_task = GNUNET_SCHEDULER_NO_TASK;
1564 memcpy(p_rd, rd, rd_count*sizeof(struct GNUNET_NAMESTORE_RecordData));
1566 for (i = 0; i < rd_count; i++)
1569 if (rd[i].record_type != GNUNET_GNS_RECORD_TYPE_NS &&
1570 rd[i].record_type != GNUNET_GNS_RECORD_TYPE_CNAME &&
1571 rd[i].record_type != GNUNET_GNS_RECORD_MX &&
1572 rd[i].record_type != GNUNET_GNS_RECORD_TYPE_SOA)
1574 p_rd[i].data = rd[i].data;
1579 * for all those records we 'should'
1580 * also try to resolve the A/AAAA records (RFC1035)
1581 * This is a feature and not important
1584 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1585 "GNS_POSTPROCESS: Postprocessing\n");
1587 if (strcmp(rh->name, "+") == 0)
1588 repl_string = rlh->name;
1590 repl_string = rlh->name+strlen(rh->name)+1;
1593 if (rd[i].record_type == GNUNET_GNS_RECORD_MX)
1595 memcpy(new_mx_data, (char*)rd[i].data, sizeof(uint16_t));
1596 offset = sizeof(uint16_t);
1597 pos = new_mx_data+offset;
1598 expand_plus(&pos, (char*)rd[i].data+sizeof(uint16_t),
1600 offset += strlen(new_mx_data+sizeof(uint16_t))+1;
1601 p_rd[i].data = new_mx_data;
1602 p_rd[i].data_size = offset;
1604 else if (rd[i].record_type == GNUNET_GNS_RECORD_TYPE_SOA)
1606 /* expand mname and rname */
1608 expand_plus(&pos, (char*)rd[i].data, repl_string);
1609 offset = strlen(new_soa_data)+1;
1610 pos = new_soa_data+offset;
1611 expand_plus(&pos, (char*)rd[i].data+offset, repl_string);
1612 offset += strlen(new_soa_data+offset)+1;
1613 /* cpy the 4 numbers serial refresh retry and expire */
1614 memcpy(new_soa_data+offset, (char*)rd[i].data+offset, sizeof(uint32_t)*5);
1615 offset += sizeof(uint32_t)*5;
1616 p_rd[i].data_size = offset;
1617 p_rd[i].data = new_soa_data;
1622 expand_plus(&pos, (char*)rd[i].data, repl_string);
1623 p_rd[i].data_size = strlen(new_rr_data)+1;
1624 p_rd[i].data = new_rr_data;
1629 rlh->proc(rlh->proc_cls, rd_count, p_rd);
1635 * Process DHT lookup result for record.
1637 * @param cls the closure
1638 * @param rh resolver handle
1639 * @param rd_count number of results
1640 * @param rd record data
1643 handle_record_dht(void* cls, struct ResolverHandle *rh,
1644 unsigned int rd_count,
1645 const struct GNUNET_NAMESTORE_RecordData *rd)
1647 struct RecordLookupHandle* rlh;
1649 rlh = (struct RecordLookupHandle*)cls;
1652 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1653 "GNS_PHASE_REC-%d: No records for %s found in DHT. Aborting\n",
1655 /* give up, cannot resolve */
1656 finish_lookup(rh, rlh, 0, NULL);
1657 free_resolver_handle(rh);
1661 /* results found yay */
1662 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1663 "GNS_PHASE_REC-%d: Record resolved from DHT!", rh->id);
1665 finish_lookup(rh, rlh, rd_count, rd);
1666 free_resolver_handle(rh);
1672 * Process namestore lookup result for record.
1674 * @param cls the closure
1675 * @param rh resolver handle
1676 * @param rd_count number of results
1677 * @param rd record data
1680 handle_record_ns(void* cls, struct ResolverHandle *rh,
1681 unsigned int rd_count,
1682 const struct GNUNET_NAMESTORE_RecordData *rd)
1684 struct RecordLookupHandle* rlh;
1685 rlh = (struct RecordLookupHandle*) cls;
1688 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1689 "GNS_PHASE_REC-%d: NS returned no records. (status: %d)!\n",
1694 * There are 5 conditions that have to met for us to consult the DHT:
1695 * 1. The entry in the DHT is RSL_RECORD_EXPIRED AND
1696 * 2. No entry in the NS existed AND
1697 * 3. The zone queried is not the local resolver's zone AND
1698 * 4. The name that was looked up is '+'
1699 * because if it was any other canonical name we either already queried
1700 * the DHT for the authority in the authority lookup phase (and thus
1701 * would already have an entry in the NS for the record)
1702 * 5. We are not in cache only mode
1704 if (rh->status & (RSL_RECORD_EXPIRED | !RSL_RECORD_EXISTS) &&
1705 GNUNET_CRYPTO_short_hash_cmp(&rh->authority_chain_head->zone,
1706 &rh->private_local_zone) &&
1707 (strcmp(rh->name, "+") == 0) &&
1708 (rh->only_cached == GNUNET_NO))
1710 rh->proc = &handle_record_dht;
1711 resolve_record_dht(rh);
1714 /* give up, cannot resolve */
1715 finish_lookup(rh, rlh, 0, NULL);
1716 free_resolver_handle(rh);
1720 /* results found yay */
1721 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1722 "GNS_PHASE_REC-%d: Record resolved from namestore!", rh->id);
1724 finish_lookup(rh, rlh, rd_count, rd);
1726 free_resolver_handle(rh);
1732 * Move one level up in the domain hierarchy and return the
1733 * passed top level domain.
1735 * @param name the domain
1736 * @param dest the destination where the tld will be put
1739 pop_tld(char* name, char* dest)
1743 if (is_canonical(name))
1750 for (len = strlen(name); len > 0; len--)
1752 if (*(name+len) == '.')
1762 strcpy(dest, (name+len+1));
1766 * Checks if name is in tld
1768 * @param name the name to check
1769 * @param tld the TLD to check for
1770 * @return GNUNET_YES or GNUNET_NO
1773 is_tld(const char* name, const char* tld)
1777 if (strlen(name) <= strlen(tld))
1782 offset = strlen(name)-strlen(tld);
1783 if (strcmp(name+offset, tld) != 0)
1785 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1786 "%s is not in .%s TLD\n", name, tld);
1793 * DHT resolution for delegation finished. Processing result.
1795 * @param cls the closure
1796 * @param rh resolver handle
1797 * @param rd_count number of results (always 0)
1798 * @param rd record data (always NULL)
1801 handle_delegation_dht(void* cls, struct ResolverHandle *rh,
1802 unsigned int rd_count,
1803 const struct GNUNET_NAMESTORE_RecordData *rd)
1805 struct RecordLookupHandle* rlh;
1806 rlh = (struct RecordLookupHandle*) cls;
1809 if (strcmp(rh->name, "") == 0)
1811 if ((rlh->record_type == GNUNET_GNS_RECORD_PKEY))
1813 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1814 "GNS_PHASE_DELEGATE_DHT-%llu: Resolved queried PKEY via DHT.\n",
1816 finish_lookup(rh, rlh, rd_count, rd);
1817 free_resolver_handle(rh);
1820 /* We resolved full name for delegation. resolving record */
1821 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1822 "GNS_PHASE_DELEGATE_DHT-%llu: Resolved full name for delegation via DHT.\n",
1824 strcpy(rh->name, "+\0");
1825 rh->proc = &handle_record_ns;
1826 resolve_record_ns(rh);
1831 * we still have some left
1833 if (is_canonical(rh->name))
1835 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1836 "GNS_PHASE_DELEGATE_DHT-%llu: Resolving canonical record %s in ns\n",
1839 rh->proc = &handle_record_ns;
1840 resolve_record_ns(rh);
1843 /* give up, cannot resolve */
1844 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1845 "GNS_PHASE_DELEGATE_DHT-%llu: Cannot fully resolve delegation for %s via DHT!\n",
1847 finish_lookup(rh, rlh, 0, NULL);
1848 free_resolver_handle(rh);
1853 * Start DHT lookup for a name -> PKEY (compare NS) record in
1854 * rh->authority's zone
1856 * @param rh the pending gns query
1859 resolve_delegation_dht(struct ResolverHandle *rh)
1862 struct GNUNET_CRYPTO_ShortHashCode name_hash;
1863 struct GNUNET_HashCode name_hash_double;
1864 struct GNUNET_HashCode zone_hash_double;
1865 struct GNUNET_HashCode lookup_key;
1866 struct ResolverHandle *rh_heap_root;
1868 pop_tld(rh->name, rh->authority_name);
1869 GNUNET_CRYPTO_short_hash(rh->authority_name,
1870 strlen(rh->authority_name),
1872 GNUNET_CRYPTO_short_hash_double(&name_hash, &name_hash_double);
1873 GNUNET_CRYPTO_short_hash_double(&rh->authority, &zone_hash_double);
1874 GNUNET_CRYPTO_hash_xor(&name_hash_double, &zone_hash_double, &lookup_key);
1876 rh->dht_heap_node = NULL;
1878 if (rh->timeout.rel_value != GNUNET_TIME_UNIT_FOREVER_REL.rel_value)
1880 //rh->timeout_task = GNUNET_SCHEDULER_add_delayed (DHT_LOOKUP_TIMEOUT,
1881 // &dht_authority_lookup_timeout,
1883 rh->timeout_cont = &dht_authority_lookup_timeout;
1884 rh->timeout_cont_cls = rh;
1888 if (max_allowed_background_queries <=
1889 GNUNET_CONTAINER_heap_get_size (dht_lookup_heap))
1891 /* terminate oldest lookup */
1892 rh_heap_root = GNUNET_CONTAINER_heap_remove_root (dht_lookup_heap);
1893 GNUNET_DHT_get_stop(rh_heap_root->get_handle);
1894 rh_heap_root->dht_heap_node = NULL;
1896 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1897 "GNS_PHASE_DELEGATE_DHT-%llu: Replacing oldest background query for %s\n",
1898 rh->id, rh_heap_root->authority_name);
1900 rh_heap_root->proc(rh_heap_root->proc_cls,
1905 rh->dht_heap_node = GNUNET_CONTAINER_heap_insert (dht_lookup_heap,
1907 GNUNET_TIME_absolute_get().abs_value);
1910 xquery = htonl(GNUNET_GNS_RECORD_PKEY);
1912 GNUNET_assert(rh->get_handle == NULL);
1913 rh->get_handle = GNUNET_DHT_get_start(dht_handle,
1914 GNUNET_BLOCK_TYPE_GNS_NAMERECORD,
1916 DHT_GNS_REPLICATION_LEVEL,
1920 &process_delegation_result_dht,
1927 * Namestore resolution for delegation finished. Processing result.
1929 * @param cls the closure
1930 * @param rh resolver handle
1931 * @param rd_count number of results (always 0)
1932 * @param rd record data (always NULL)
1935 handle_delegation_ns(void* cls, struct ResolverHandle *rh,
1936 unsigned int rd_count,
1937 const struct GNUNET_NAMESTORE_RecordData *rd)
1939 struct RecordLookupHandle* rlh;
1940 rlh = (struct RecordLookupHandle*) cls;
1942 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1943 "GNS_PHASE_DELEGATE_NS-%llu: Resolution status: %d.\n",
1944 rh->id, rh->status);
1946 if (strcmp(rh->name, "") == 0)
1948 if ((rlh->record_type == GNUNET_GNS_RECORD_PKEY))
1950 GNUNET_assert(rd_count == 1);
1951 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1952 "GNS_PHASE_DELEGATE_NS-%llu: Resolved queried PKEY in NS.\n",
1954 finish_lookup(rh, rlh, rd_count, rd);
1955 free_resolver_handle(rh);
1958 /* We resolved full name for delegation. resolving record */
1959 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1960 "GNS_PHASE_DELEGATE_NS-%llu: Resolved full name for delegation.\n",
1962 strcpy(rh->name, "+\0");
1963 rh->proc = &handle_record_ns;
1964 resolve_record_ns(rh);
1969 * we still have some left
1970 * check if authority in ns is fresh
1972 * or we are authority
1974 if (((rh->status & RSL_RECORD_EXISTS) && (!(rh->status & RSL_RECORD_EXPIRED)))
1975 || !GNUNET_CRYPTO_short_hash_cmp(&rh->authority_chain_head->zone,
1976 &rh->private_local_zone))
1978 if (is_canonical(rh->name))
1980 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1981 "GNS_PHASE_DELEGATE_NS-%llu: Resolving canonical record %s\n",
1984 rh->proc = &handle_record_ns;
1985 resolve_record_ns(rh);
1989 /* give up, cannot resolve */
1990 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1991 "GNS_PHASE_DELEGATE_NS-%llu: Cannot fully resolve delegation for %s!\n",
1994 finish_lookup(rh, rlh, rd_count, rd);
1995 //rlh->proc(rlh->proc_cls, 0, NULL);
2000 if (rh->only_cached == GNUNET_YES)
2002 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2003 "GNS_PHASE_DELEGATE_NS-%llu: Only cache resolution, no result\n",
2005 finish_lookup(rh, rlh, rd_count, rd);
2009 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2010 "GNS_PHASE_DELEGATE_NS-%llu: Trying to resolve delegation for %s via DHT\n",
2012 rh->proc = &handle_delegation_dht;
2013 resolve_delegation_dht(rh);
2019 * This is a callback function that should give us only PKEY
2020 * records. Used to query the namestore for the authority (PKEY)
2021 * for 'name'. It will recursively try to resolve the
2022 * authority for a given name from the namestore.
2024 * @param cls the pending query
2025 * @param key the key of the zone we did the lookup
2026 * @param expiration expiration date of the record data set in the namestore
2027 * @param name the name for which we need an authority
2028 * @param rd_count the number of records with 'name'
2029 * @param rd the record data
2030 * @param signature the signature of the authority for the record data
2033 process_delegation_result_ns(void* cls,
2034 const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *key,
2035 struct GNUNET_TIME_Absolute expiration,
2037 unsigned int rd_count,
2038 const struct GNUNET_NAMESTORE_RecordData *rd,
2039 const struct GNUNET_CRYPTO_RsaSignature *signature)
2041 struct ResolverHandle *rh;
2042 struct GNUNET_TIME_Relative remaining_time;
2043 struct GNUNET_CRYPTO_ShortHashCode zone;
2044 char new_name[MAX_DNS_NAME_LENGTH];
2046 rh = (struct ResolverHandle *)cls;
2047 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2048 "GNS_PHASE_DELEGATE_NS-%llu: Got %d records from authority lookup\n",
2051 GNUNET_CRYPTO_short_hash(key,
2052 sizeof(struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded),
2054 remaining_time = GNUNET_TIME_absolute_get_remaining (expiration);
2060 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2061 "GNS_PHASE_DELEGATE_NS-%llu: Records with name %s exist.\n",
2063 rh->status |= RSL_RECORD_EXISTS;
2066 if (remaining_time.rel_value == 0)
2068 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2069 "GNS_PHASE_DELEGATE_NS-%llu: Record set %s expired.\n",
2071 rh->status |= RSL_RECORD_EXPIRED;
2075 * No authority found in namestore.
2080 * We did not find an authority in the namestore
2085 * Promote this authority back to a name maybe it is
2088 if (strcmp(rh->name, "") == 0)
2090 /* simply promote back */
2091 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2092 "GNS_PHASE_DELEGATE_NS-%llu: Promoting %s back to name\n",
2093 rh->id, rh->authority_name);
2094 strcpy(rh->name, rh->authority_name);
2098 /* add back to existing name */
2099 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2100 "GNS_PHASE_DELEGATE_NS-%llu: Adding %s back to %s\n",
2101 rh->id, rh->authority_name, rh->name);
2102 //memset(new_name, 0, strlen(rh->name) + strlen(rh->authority_name) + 2);
2103 GNUNET_snprintf(new_name, MAX_DNS_NAME_LENGTH, "%s.%s",
2104 rh->name, rh->authority_name);
2105 //strcpy(new_name, rh->name);
2106 //strcpy(new_name+strlen(new_name), ".");
2107 //strcpy(new_name+strlen(new_name), rh->authority_name);
2108 strcpy(rh->name, new_name);
2109 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2110 "GNS_PHASE_DELEGATE_NS-%llu: %s restored\n", rh->id, rh->name);
2112 rh->proc(rh->proc_cls, rh, 0, NULL);
2117 * We found an authority that may be able to help us
2118 * move on with query
2119 * Note only 1 pkey should have been returned.. anything else would be strange
2122 for (i=0; i<rd_count;i++)
2125 if (rd[i].record_type != GNUNET_GNS_RECORD_PKEY)
2128 if (ignore_pending_records &&
2129 (rd[i].flags & GNUNET_NAMESTORE_RF_PENDING))
2131 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2132 "GNS_PHASE_DELEGATE_NS-%llu: PKEY for %s is pending user confirmation.\n",
2138 if ((GNUNET_TIME_absolute_get_remaining (rd[i].expiration)).rel_value
2141 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2142 "GNS_PHASE_DELEGATE_NS-%llu: This pkey is expired.\n",
2144 if (remaining_time.rel_value == 0)
2146 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2147 "GNS_PHASE_DELEGATE_NS-%llu: This dht entry is expired.\n",
2149 rh->authority_chain_head->fresh = 0;
2150 rh->proc(rh->proc_cls, rh, 0, NULL);
2158 * Resolve rest of query with new authority
2160 GNUNET_assert(rd[i].record_type == GNUNET_GNS_RECORD_PKEY);
2161 memcpy(&rh->authority, rd[i].data,
2162 sizeof(struct GNUNET_CRYPTO_ShortHashCode));
2163 struct AuthorityChain *auth = GNUNET_malloc(sizeof(struct AuthorityChain));
2164 auth->zone = rh->authority;
2165 memset(auth->name, 0, strlen(rh->authority_name)+1);
2166 strcpy(auth->name, rh->authority_name);
2167 GNUNET_CONTAINER_DLL_insert (rh->authority_chain_head,
2168 rh->authority_chain_tail,
2171 /** try to import pkey if private key available
2172 * TODO: Only import last one?
2174 //if (rh->priv_key && (name != NULL) && is_canonical (rh->name))
2175 // process_discovered_authority((char*)name, auth->zone,
2176 // rh->authority_chain_tail->zone,
2179 * We are done with PKEY resolution if name is empty
2180 * else resolve again with new authority
2182 if (strcmp(rh->name, "") == 0)
2183 rh->proc(rh->proc_cls, rh, rd_count, rd);
2185 resolve_delegation_ns(rh);
2192 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2193 "GNS_PHASE_DELEGATE_NS-%llu: Authority lookup and no PKEY...\n", rh->id);
2195 * If we have found some records for the LAST label
2196 * we return the results. Else null.
2198 if (strcmp(rh->name, "") == 0)
2200 /* Start shortening */
2201 if ((rh->priv_key != NULL) && is_canonical (rh->name))
2203 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2204 "GNS_PHASE_DELEGATE_NS-%llu: Trying to shorten authority chain\n",
2206 start_shorten (rh->authority_chain_tail,
2209 /* simply promote back */
2210 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2211 "GNS_PHASE_DELEGATE_NS-%llu: Promoting %s back to name\n",
2212 rh->id, rh->authority_name);
2213 strcpy(rh->name, rh->authority_name);
2214 rh->proc(rh->proc_cls, rh, rd_count, rd);
2218 rh->proc(rh->proc_cls, rh, 0, NULL);
2224 * Resolve the delegation chain for the request in our namestore
2226 * @param rh the resolver handle
2229 resolve_delegation_ns(struct ResolverHandle *rh)
2231 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2232 "GNS_PHASE_DELEGATE_NS-%llu: Resolving delegation for %s\n",
2234 pop_tld(rh->name, rh->authority_name);
2235 GNUNET_NAMESTORE_lookup_record(namestore_handle,
2238 GNUNET_GNS_RECORD_ANY,
2239 &process_delegation_result_ns,
2246 * Lookup of a record in a specific zone
2247 * calls lookup result processor on result
2249 * @param zone the root zone
2250 * @param pzone the private local zone
2251 * @param record_type the record type to look up
2252 * @param name the name to look up
2253 * @param key a private key for use with PSEU import (can be NULL)
2254 * @param timeout timeout for resolution
2255 * @param only_cached GNUNET_NO to only check locally not DHT for performance
2256 * @param proc the processor to call on result
2257 * @param cls the closure to pass to proc
2260 gns_resolver_lookup_record(struct GNUNET_CRYPTO_ShortHashCode zone,
2261 struct GNUNET_CRYPTO_ShortHashCode pzone,
2262 uint32_t record_type,
2264 struct GNUNET_CRYPTO_RsaPrivateKey *key,
2265 struct GNUNET_TIME_Relative timeout,
2267 RecordLookupProcessor proc,
2270 struct ResolverHandle *rh;
2271 struct RecordLookupHandle* rlh;
2272 char string_hash[MAX_DNS_LABEL_LENGTH];
2273 char nzkey[MAX_DNS_LABEL_LENGTH];
2274 char* nzkey_ptr = nzkey;
2276 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2277 "Starting resolution for %s (type=%d)!\n",
2281 if (is_canonical((char*)name) && (strcmp(GNUNET_GNS_TLD, name) != 0))
2283 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2284 "%s is canonical and not gnunet -> cannot resolve!\n", name);
2289 rlh = GNUNET_malloc(sizeof(struct RecordLookupHandle));
2290 rh = GNUNET_malloc(sizeof (struct ResolverHandle));
2292 rh->authority = zone;
2296 rh->timeout = timeout;
2297 rh->get_handle = NULL;
2298 rh->private_local_zone = pzone;
2299 rh->only_cached = only_cached;
2303 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2304 "No shorten key for resolution\n");
2307 if (timeout.rel_value != GNUNET_TIME_UNIT_FOREVER_REL.rel_value)
2310 * Set timeout for authority lookup phase to 1/2
2312 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2313 "Timeout for lookup set to %ds\n", rh->timeout.rel_value);
2314 rh->timeout_task = GNUNET_SCHEDULER_add_delayed(
2315 GNUNET_TIME_relative_divide(timeout, 2),
2316 &handle_lookup_timeout,
2318 rh->timeout_cont = &dht_authority_lookup_timeout;
2319 rh->timeout_cont_cls = rh;
2323 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "No timeout for query!\n");
2324 rh->timeout_task = GNUNET_SCHEDULER_NO_TASK;
2327 if (strcmp(GNUNET_GNS_TLD, name) == 0)
2330 * Only 'gnunet' given
2332 strcpy(rh->name, "\0");
2336 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2337 "Checking for TLD...\n");
2338 if (is_zkey_tld(name) == GNUNET_YES)
2340 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2343 * This is a zkey tld
2344 * build hash and use as initial authority
2347 strlen(name)-strlen(GNUNET_GNS_TLD_ZKEY));
2348 memcpy(rh->name, name,
2349 strlen(name)-strlen(GNUNET_GNS_TLD_ZKEY) - 1);
2350 pop_tld(rh->name, string_hash);
2352 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2353 "ZKEY is %s!\n", string_hash);
2355 GNUNET_STRINGS_utf8_toupper(string_hash, &nzkey_ptr);
2357 if (GNUNET_OK != GNUNET_CRYPTO_short_hash_from_string(nzkey,
2360 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2361 "Cannot convert ZKEY %s to hash!\n", string_hash);
2371 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2374 * Presumably GNUNET tld
2377 strlen(name)-strlen(GNUNET_GNS_TLD));
2378 memcpy(rh->name, name,
2379 strlen(name)-strlen(GNUNET_GNS_TLD) - 1);
2384 * Initialize authority chain
2386 rh->authority_chain_head = GNUNET_malloc(sizeof(struct AuthorityChain));
2387 rh->authority_chain_head->prev = NULL;
2388 rh->authority_chain_head->next = NULL;
2389 rh->authority_chain_tail = rh->authority_chain_head;
2390 rh->authority_chain_head->zone = rh->authority;
2393 * Copy original query into lookup handle
2395 rlh->record_type = record_type;
2396 memset(rlh->name, 0, strlen(name) + 1);
2397 strcpy(rlh->name, name);
2399 rlh->proc_cls = cls;
2401 rh->proc = &handle_delegation_ns;
2402 resolve_delegation_ns(rh);
2405 /******** END Record Resolver ***********/
2408 * Callback calles by namestore for a zone to name
2411 * @param cls the closure
2412 * @param zone_key the zone we queried
2413 * @param expire the expiration time of the name
2414 * @param name the name found or NULL
2415 * @param rd_len number of records for the name
2416 * @param rd the record data (PKEY) for the name
2417 * @param signature the signature for the record data
2420 process_zone_to_name_shorten_root (void *cls,
2421 const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *zone_key,
2422 struct GNUNET_TIME_Absolute expire,
2424 unsigned int rd_len,
2425 const struct GNUNET_NAMESTORE_RecordData *rd,
2426 const struct GNUNET_CRYPTO_RsaSignature *signature);
2430 * Callback called by namestore for a zone to name
2433 * @param cls the closure
2434 * @param zone_key the zone we queried
2435 * @param expire the expiration time of the name
2436 * @param name the name found or NULL
2437 * @param rd_len number of records for the name
2438 * @param rd the record data (PKEY) for the name
2439 * @param signature the signature for the record data
2442 process_zone_to_name_shorten_shorten (void *cls,
2443 const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *zone_key,
2444 struct GNUNET_TIME_Absolute expire,
2446 unsigned int rd_len,
2447 const struct GNUNET_NAMESTORE_RecordData *rd,
2448 const struct GNUNET_CRYPTO_RsaSignature *signature)
2450 struct ResolverHandle *rh = (struct ResolverHandle *)cls;
2451 struct NameShortenHandle* nsh = (struct NameShortenHandle*)rh->proc_cls;
2452 struct AuthorityChain *next_authority;
2454 char result[MAX_DNS_NAME_LENGTH];
2455 char tmp_name[MAX_DNS_NAME_LENGTH];
2458 /* we found a match in our own root zone */
2461 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2462 "result strlen %d\n", strlen(name));
2463 answer_len = strlen(rh->name) + strlen(name) + strlen(GNUNET_GNS_TLD) + 3;
2464 memset(result, 0, answer_len);
2466 if (strlen(rh->name) > 0)
2468 sprintf (result, "%s.%s.%s.%s.%s",
2470 nsh->shorten_zone_name, nsh->private_zone_name,
2475 sprintf (result, "%s.%s.%s.%s", name,
2476 nsh->shorten_zone_name, nsh->private_zone_name,
2480 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2481 "Found shorten result %s\n", result);
2482 if (strlen (nsh->result) > strlen (result))
2483 strcpy (nsh->result, result);
2485 else if (GNUNET_CRYPTO_short_hash_cmp(&rh->authority_chain_head->zone,
2486 nsh->shorten_zone) == 0)
2489 * This is our zone append .gnunet unless name is empty
2490 * (it shouldn't be, usually FIXME what happens if we
2491 * shorten to our zone to a "" record??)
2494 sprintf (result, "%s.%s.%s.%s",
2496 nsh->shorten_zone_name, nsh->private_zone_name,
2498 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2499 "Our zone: Found %s as shorten result\n", result);
2501 if (strlen (nsh->result) > strlen (result))
2502 strcpy (nsh->result, result);
2503 //nsh->proc(nsh->proc_cls, result);
2505 //free_resolver_handle(rh);
2512 * continue with next authority if exists
2514 if ((rh->authority_chain_head->next == NULL))
2516 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2517 "Sending %s as shorten result\n", nsh->result);
2518 nsh->proc(nsh->proc_cls, nsh->result);
2520 free_resolver_handle (rh);
2523 next_authority = rh->authority_chain_head;
2525 GNUNET_snprintf(tmp_name, MAX_DNS_NAME_LENGTH,
2526 "%s.%s", rh->name, next_authority->name);
2528 strcpy(rh->name, tmp_name);
2529 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2530 "No PSEU found for authority %s. Promoting back: %s\n",
2531 next_authority->name, rh->name);
2533 GNUNET_CONTAINER_DLL_remove(rh->authority_chain_head,
2534 rh->authority_chain_tail,
2537 GNUNET_NAMESTORE_zone_to_name (namestore_handle,
2538 &rh->authority_chain_tail->zone,
2539 &rh->authority_chain_head->zone,
2540 &process_zone_to_name_shorten_root,
2545 * Callback calles by namestore for a zone to name
2548 * @param cls the closure
2549 * @param zone_key the zone we queried
2550 * @param expire the expiration time of the name
2551 * @param name the name found or NULL
2552 * @param rd_len number of records for the name
2553 * @param rd the record data (PKEY) for the name
2554 * @param signature the signature for the record data
2557 process_zone_to_name_shorten_private (void *cls,
2558 const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *zone_key,
2559 struct GNUNET_TIME_Absolute expire,
2561 unsigned int rd_len,
2562 const struct GNUNET_NAMESTORE_RecordData *rd,
2563 const struct GNUNET_CRYPTO_RsaSignature *signature)
2565 struct ResolverHandle *rh = (struct ResolverHandle *)cls;
2566 struct NameShortenHandle* nsh = (struct NameShortenHandle*)rh->proc_cls;
2567 struct AuthorityChain *next_authority;
2569 char result[MAX_DNS_NAME_LENGTH];
2570 char tmp_name[MAX_DNS_NAME_LENGTH];
2573 /* we found a match in our own root zone */
2576 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2577 "result strlen %d\n", strlen(name));
2578 answer_len = strlen(rh->name) + strlen(name) + strlen(GNUNET_GNS_TLD) + 3;
2579 memset(result, 0, answer_len);
2581 if (strlen(rh->name) > 0)
2583 sprintf (result, "%s.%s.%s", rh->name, name, GNUNET_GNS_TLD);
2587 sprintf (result, "%s.%s", name, GNUNET_GNS_TLD);
2590 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2591 "Found shorten result %s\n", result);
2592 if (strlen (nsh->result) > strlen (result))
2593 strcpy (nsh->result, result);
2595 else if (GNUNET_CRYPTO_short_hash_cmp(&rh->authority_chain_head->zone,
2596 nsh->private_zone) == 0)
2599 * This is our zone append .gnunet unless name is empty
2600 * (it shouldn't be, usually FIXME what happens if we
2601 * shorten to our zone to a "" record??)
2604 sprintf (result, "%s.%s.%s",
2605 rh->name, nsh->private_zone_name, GNUNET_GNS_TLD);
2606 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2607 "Our private zone: Found %s as shorten result %s\n", result);
2608 if (strlen (nsh->result) > strlen (result))
2609 strcpy (nsh->result, result);
2612 if (nsh->shorten_zone != NULL)
2614 /* backtrack authorities for names in priv zone */
2615 GNUNET_NAMESTORE_zone_to_name (namestore_handle,
2617 &rh->authority_chain_head->zone,
2618 &process_zone_to_name_shorten_shorten,
2625 * continue with next authority if exists
2627 if ((rh->authority_chain_head->next == NULL))
2629 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2630 "Sending %s as shorten result\n", nsh->result);
2631 nsh->proc(nsh->proc_cls, nsh->result);
2633 free_resolver_handle(rh);
2636 next_authority = rh->authority_chain_head;
2638 GNUNET_snprintf(tmp_name, MAX_DNS_NAME_LENGTH,
2639 "%s.%s", rh->name, next_authority->name);
2641 strcpy(rh->name, tmp_name);
2642 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2643 "No PSEU found for authority %s. Promoting back: %s\n",
2644 next_authority->name, rh->name);
2646 GNUNET_CONTAINER_DLL_remove(rh->authority_chain_head,
2647 rh->authority_chain_tail,
2650 GNUNET_NAMESTORE_zone_to_name (namestore_handle,
2651 &rh->authority_chain_tail->zone,
2652 &rh->authority_chain_head->zone,
2653 &process_zone_to_name_shorten_root,
2659 * Callback calles by namestore for a zone to name
2662 * @param cls the closure
2663 * @param zone_key the zone we queried
2664 * @param expire the expiration time of the name
2665 * @param name the name found or NULL
2666 * @param rd_len number of records for the name
2667 * @param rd the record data (PKEY) for the name
2668 * @param signature the signature for the record data
2671 process_zone_to_name_shorten_root (void *cls,
2672 const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *zone_key,
2673 struct GNUNET_TIME_Absolute expire,
2675 unsigned int rd_len,
2676 const struct GNUNET_NAMESTORE_RecordData *rd,
2677 const struct GNUNET_CRYPTO_RsaSignature *signature)
2679 struct ResolverHandle *rh = (struct ResolverHandle *)cls;
2680 struct NameShortenHandle* nsh = (struct NameShortenHandle*)rh->proc_cls;
2681 struct AuthorityChain *next_authority;
2683 char result[MAX_DNS_NAME_LENGTH];
2684 char tmp_name[MAX_DNS_NAME_LENGTH];
2687 /* we found a match in our own root zone */
2690 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2691 "result strlen %d\n", strlen(name));
2692 answer_len = strlen(rh->name) + strlen(name) + strlen(GNUNET_GNS_TLD) + 3;
2693 memset(result, 0, answer_len);
2695 if (strlen(rh->name) > 0)
2697 sprintf (result, "%s.%s.%s", rh->name, name, GNUNET_GNS_TLD);
2701 sprintf (result, "%s.%s", name, GNUNET_GNS_TLD);
2704 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2705 "Found shorten result %s\n", result);
2706 if (strlen (nsh->result) > strlen (result))
2707 strcpy (nsh->result, result);
2709 else if (GNUNET_CRYPTO_short_hash_cmp(&rh->authority_chain_head->zone,
2710 nsh->root_zone) == 0)
2713 * This is our zone append .gnunet unless name is empty
2714 * (it shouldn't be, usually FIXME what happens if we
2715 * shorten to our zone to a "" record??)
2718 sprintf (result, "%s.%s", rh->name, GNUNET_GNS_TLD);
2719 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2720 "Our zone: Found %s as shorten result\n", result);
2721 if (strlen (nsh->result) > strlen (result))
2722 strcpy (nsh->result, result);
2725 if (nsh->private_zone != NULL)
2727 /* backtrack authorities for names in priv zone */
2728 GNUNET_NAMESTORE_zone_to_name (namestore_handle,
2730 &rh->authority_chain_head->zone,
2731 &process_zone_to_name_shorten_private,
2738 * continue with next authority if exists
2740 if ((rh->authority_chain_head->next == NULL))
2742 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2743 "Sending %s as shorten result\n", nsh->result);
2744 nsh->proc(nsh->proc_cls, nsh->result);
2746 free_resolver_handle(rh);
2749 next_authority = rh->authority_chain_head;
2751 GNUNET_snprintf(tmp_name, MAX_DNS_NAME_LENGTH,
2752 "%s.%s", rh->name, next_authority->name);
2754 strcpy(rh->name, tmp_name);
2755 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2756 "No PSEU found for authority %s. Promoting back: %s\n",
2757 next_authority->name, rh->name);
2759 GNUNET_CONTAINER_DLL_remove(rh->authority_chain_head,
2760 rh->authority_chain_tail,
2763 GNUNET_NAMESTORE_zone_to_name (namestore_handle,
2764 &rh->authority_chain_tail->zone,
2765 &rh->authority_chain_head->zone,
2766 &process_zone_to_name_shorten_root,
2773 * Process result from namestore delegation lookup
2774 * for shorten operation
2776 * @param cls the client shorten handle
2777 * @param rh the resolver handle
2778 * @param rd_count number of results (0)
2779 * @param rd data (NULL)
2782 handle_delegation_ns_shorten(void* cls,
2783 struct ResolverHandle *rh,
2785 const struct GNUNET_NAMESTORE_RecordData *rd)
2787 struct NameShortenHandle *nsh;
2788 char result[MAX_DNS_NAME_LENGTH];
2790 nsh = (struct NameShortenHandle *)cls;
2793 * At this point rh->name contains the part of the name
2794 * that we do not have a PKEY in our namestore to resolve.
2795 * The authority chain in the resolver handle is now
2796 * useful to backtrack if needed
2799 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2800 "PKEY resolved as far as possible in ns up to %s!\n", rh->name);
2801 memset(result, 0, sizeof (result));
2803 if (GNUNET_CRYPTO_short_hash_cmp(&rh->authority_chain_head->zone,
2804 nsh->root_zone) == 0)
2807 * This is our zone append .gnunet unless name is empty
2808 * (it shouldn't be, usually FIXME what happens if we
2809 * shorten to our zone to a "" record??)
2812 sprintf (result, "%s.%s", rh->name, GNUNET_GNS_TLD);
2813 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2814 "Our zone: Found %s as shorten result\n", result);
2816 if (strlen (nsh->result) > strlen (result))
2817 strcpy (nsh->result, result);
2820 else if (GNUNET_CRYPTO_short_hash_cmp(&rh->authority_chain_head->zone,
2821 nsh->private_zone) == 0)
2824 * This is our zone append .gnunet unless name is empty
2825 * (it shouldn't be, usually FIXME what happens if we
2826 * shorten to our zone to a "" record??)
2829 sprintf (result, "%s.%s.%s",
2830 rh->name, nsh->private_zone_name, GNUNET_GNS_TLD);
2831 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2832 "Our zone: Found %s as shorten result %s\n", result);
2834 if (strlen (nsh->result) > strlen (result))
2835 strcpy (nsh->result, result);
2837 else if (GNUNET_CRYPTO_short_hash_cmp(&rh->authority_chain_head->zone,
2838 nsh->shorten_zone) == 0)
2841 * This is our zone append .gnunet unless name is empty
2842 * (it shouldn't be, usually FIXME what happens if we
2843 * shorten to our zone to a "" record??)
2846 sprintf (result, "%s.%s.%s",
2847 rh->name, nsh->private_zone_name, GNUNET_GNS_TLD);
2848 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2849 "Our zone: Found %s as shorten result\n", result);
2851 if (strlen (nsh->result) > strlen (result))
2852 strcpy (nsh->result, result);
2856 /* backtrack authorities for names */
2857 GNUNET_NAMESTORE_zone_to_name (namestore_handle,
2859 &rh->authority_chain_head->zone,
2860 &process_zone_to_name_shorten_root,
2867 * Callback calles by namestore for a zone to name
2870 * @param cls the closure
2871 * @param zone_key the zone we queried
2872 * @param expire the expiration time of the name
2873 * @param name the name found or NULL
2874 * @param rd_len number of records for the name
2875 * @param rd the record data (PKEY) for the name
2876 * @param signature the signature for the record data
2879 process_zone_to_name_zkey(void *cls,
2880 const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *zone_key,
2881 struct GNUNET_TIME_Absolute expire,
2883 unsigned int rd_len,
2884 const struct GNUNET_NAMESTORE_RecordData *rd,
2885 const struct GNUNET_CRYPTO_RsaSignature *signature)
2887 struct ResolverHandle *rh = cls;
2888 struct NameShortenHandle *nsh = rh->proc_cls;
2889 struct GNUNET_CRYPTO_ShortHashAsciiEncoded enc;
2890 char new_name[MAX_DNS_NAME_LENGTH];
2892 /* zkey not in our zone */
2896 * In this case we have not given this PKEY a name (yet)
2897 * It is either just not in our zone or not even cached
2898 * Since we do not know at this point we will not try to shorten
2899 * because PKEY import will happen if the user follows the zkey
2902 GNUNET_CRYPTO_short_hash_to_enc ((struct GNUNET_CRYPTO_ShortHashCode*)rd,
2904 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2905 "No name found for zkey %s returning verbatim!\n", enc);
2906 if (strcmp(rh->name, "") != 0)
2907 GNUNET_snprintf(new_name, MAX_DNS_NAME_LENGTH, "%s.%s.%s",
2908 rh->name, enc, GNUNET_GNS_TLD_ZKEY);
2910 GNUNET_snprintf(new_name, MAX_DNS_NAME_LENGTH, "%s.%s",
2911 enc, GNUNET_GNS_TLD_ZKEY);
2913 strcpy (nsh->result, new_name);
2915 nsh->proc(nsh->proc_cls, new_name);
2917 free_resolver_handle(rh);
2921 if (strcmp(rh->name, "") != 0)
2922 GNUNET_snprintf(new_name, MAX_DNS_NAME_LENGTH, "%s.%s",
2925 strcpy(new_name, name);
2927 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2928 "Continue shorten for %s!\n", new_name);
2930 strcpy(rh->name, new_name);
2932 rh->authority_chain_head = GNUNET_malloc(sizeof(struct AuthorityChain));
2933 rh->authority_chain_tail = rh->authority_chain_head;
2934 rh->authority_chain_head->zone = rh->authority;
2937 /* Start delegation resolution in our namestore */
2938 resolve_delegation_ns(rh);
2943 * Shorten api from resolver
2945 * @param zone the root zone to use
2946 * @param pzone the private zone to use
2947 * @param szone the shorten zone to use
2948 * @param name the name to shorten
2949 * @param private_zone_name name of the private zone
2950 * @param shorten_zone_name name of the shorten zone
2951 * @param proc the processor to call with result
2952 * @param proc_cls closure to pass to proc
2955 gns_resolver_shorten_name (struct GNUNET_CRYPTO_ShortHashCode *zone,
2956 struct GNUNET_CRYPTO_ShortHashCode *pzone,
2957 struct GNUNET_CRYPTO_ShortHashCode *szone,
2959 const char* private_zone_name,
2960 const char* shorten_zone_name,
2961 ShortenResultProcessor proc,
2964 struct ResolverHandle *rh;
2965 struct NameShortenHandle *nsh;
2966 char string_hash[MAX_DNS_LABEL_LENGTH];
2967 struct GNUNET_CRYPTO_ShortHashCode zkey;
2968 char nzkey[MAX_DNS_LABEL_LENGTH];
2969 char* nzkey_ptr = nzkey;
2972 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2973 "Starting shorten for %s!\n", name);
2975 if (is_canonical ((char*)name))
2977 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2978 "%s is canonical. Returning verbatim\n", name);
2979 proc (proc_cls, name);
2983 nsh = GNUNET_malloc (sizeof (struct NameShortenHandle));
2986 nsh->proc_cls = proc_cls;
2987 nsh->root_zone = zone;
2988 nsh->private_zone = pzone;
2989 nsh->shorten_zone = szone;
2990 strcpy (nsh->private_zone_name, private_zone_name);
2991 strcpy (nsh->shorten_zone_name, shorten_zone_name);
2992 strcpy (nsh->result, name);
2994 rh = GNUNET_malloc (sizeof (struct ResolverHandle));
2995 rh->authority = *zone;
2997 rh->priv_key = NULL;
2998 rh->proc = &handle_delegation_ns_shorten;
3001 rh->private_local_zone = *zone;
3003 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3004 "Checking for TLD...\n");
3005 if (is_zkey_tld (name) == GNUNET_YES)
3007 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3010 * This is a zkey tld
3011 * build hash and use as initial authority
3014 memset (rh->name, 0,
3015 strlen (name)-strlen (GNUNET_GNS_TLD_ZKEY));
3016 memcpy (rh->name, name,
3017 strlen(name)-strlen (GNUNET_GNS_TLD_ZKEY) - 1);
3018 pop_tld (rh->name, string_hash);
3020 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3021 "ZKEY is %s!\n", string_hash);
3023 GNUNET_STRINGS_utf8_toupper (string_hash, &nzkey_ptr);
3025 if (GNUNET_OK != GNUNET_CRYPTO_short_hash_from_string (nzkey,
3028 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
3029 "Cannot convert ZKEY %s to hash!\n", nzkey);
3032 proc (proc_cls, name);
3036 GNUNET_NAMESTORE_zone_to_name (namestore_handle,
3039 &process_zone_to_name_zkey,
3046 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3049 * Presumably GNUNET tld
3051 memset (rh->name, 0,
3052 strlen (name)-strlen (GNUNET_GNS_TLD));
3053 memcpy (rh->name, name,
3054 strlen (name)-strlen (GNUNET_GNS_TLD) - 1);
3057 rh->authority_chain_head = GNUNET_malloc (sizeof (struct AuthorityChain));
3058 rh->authority_chain_tail = rh->authority_chain_head;
3059 rh->authority_chain_head->zone = *zone;
3062 /* Start delegation resolution in our namestore */
3063 resolve_delegation_ns (rh);
3066 /*********** END NAME SHORTEN ********************/
3070 * Process result from namestore delegation lookup
3071 * for get authority operation
3073 * @param cls the client get auth handle
3074 * @param rh the resolver handle
3075 * @param rd_count number of results (0)
3076 * @param rd data (NULL)
3079 handle_delegation_result_ns_get_auth(void* cls,
3080 struct ResolverHandle *rh,
3082 const struct GNUNET_NAMESTORE_RecordData *rd)
3084 struct GetNameAuthorityHandle* nah;
3085 char result[MAX_DNS_NAME_LENGTH];
3088 nah = (struct GetNameAuthorityHandle*) rh->proc_cls;
3091 * At this point rh->name contains the part of the name
3092 * that we do not have a PKEY in our namestore to resolve.
3093 * The authority chain in the resolver handle is now
3094 * useful to backtrack if needed
3097 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
3098 "PKEY resolved as far as possible in ns up to %s!\n", rh->name);
3100 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
3101 "Building response!\n");
3102 if (is_canonical(rh->name))
3105 * We successfully resolved the authority in the ns
3106 * FIXME for our purposes this is fine
3107 * but maybe we want to have an api that also looks
3108 * into the dht (i.e. option in message)
3110 if (strlen(rh->name) > strlen(nah->name))
3112 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
3113 "Record name longer than original lookup name... odd!\n");
3117 answer_len = strlen(nah->name) - strlen(rh->name)
3118 + strlen(GNUNET_GNS_TLD) + 1;
3119 memset(result, 0, answer_len);
3120 strcpy(result, nah->name + strlen(rh->name) + 1);
3122 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
3123 "Got authority result %s\n", result);
3125 nah->proc(nah->proc_cls, result);
3127 free_resolver_handle(rh);
3131 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
3132 "Unable to resolve authority for remaining %s!\n", rh->name);
3133 nah->proc(nah->proc_cls, "");
3135 free_resolver_handle(rh);
3143 * Tries to resolve the authority for name
3146 * @param zone the root zone to look up for
3147 * @param pzone the private local zone
3148 * @param name the name to lookup up
3149 * @param proc the processor to call when finished
3150 * @param proc_cls the closure to pass to the processor
3153 gns_resolver_get_authority(struct GNUNET_CRYPTO_ShortHashCode zone,
3154 struct GNUNET_CRYPTO_ShortHashCode pzone,
3156 GetAuthorityResultProcessor proc,
3159 struct ResolverHandle *rh;
3160 struct GetNameAuthorityHandle *nah;
3162 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3163 "Starting authority resolution for %s!\n", name);
3165 nah = GNUNET_malloc(sizeof (struct GetNameAuthorityHandle));
3166 rh = GNUNET_malloc(sizeof (struct ResolverHandle));
3167 rh->authority = zone;
3169 rh->private_local_zone = pzone;
3171 if (strcmp(GNUNET_GNS_TLD, name) == 0)
3173 strcpy(rh->name, "\0");
3178 strlen(name)-strlen(GNUNET_GNS_TLD));
3179 memcpy(rh->name, name,
3180 strlen(name)-strlen(GNUNET_GNS_TLD) - 1);
3183 memset(nah->name, 0,
3185 strcpy(nah->name, name);
3187 rh->authority_chain_head = GNUNET_malloc(sizeof(struct AuthorityChain));
3188 rh->authority_chain_tail = rh->authority_chain_head;
3189 rh->authority_chain_head->zone = zone;
3190 rh->proc = &handle_delegation_result_ns_get_auth;
3191 rh->proc_cls = (void*)nah;
3194 nah->proc_cls = proc_cls;
3196 /* Start delegation resolution in our namestore */
3197 resolve_delegation_ns(rh);
3201 /******** END GET AUTHORITY *************/
3203 /* end of gnunet-service-gns_resolver.c */