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 * Namestore calls this function if we have record for this name.
59 * (or with rd_count=0 to indicate no matches)
61 * @param cls the pending query
62 * @param key the key of the zone we did the lookup
63 * @param expiration expiration date of the namestore entry
64 * @param name the name for which we need an authority
65 * @param rd_count the number of records with 'name'
66 * @param rd the record data
67 * @param signature the signature of the authority for the record data
70 process_pseu_lookup_ns(void* cls,
71 const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *key,
72 struct GNUNET_TIME_Absolute expiration,
73 const char *name, unsigned int rd_count,
74 const struct GNUNET_NAMESTORE_RecordData *rd,
75 const struct GNUNET_CRYPTO_RsaSignature *signature)
77 struct GetPseuAuthorityHandle* gph = (struct GetPseuAuthorityHandle*)cls;
78 struct GNUNET_NAMESTORE_RecordData new_pkey;
82 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
83 "Name %s already taken in NS!\n", name);
84 if (0 == strcmp(gph->name, name))
86 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
87 "Intelligent replacement not implemented\n", name);
88 GNUNET_free(gph->new_name);
89 GNUNET_free(gph->name);
94 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
95 "Trying delegated name %s\n", gph->name);
96 gph->new_name = gph->name;
97 GNUNET_NAMESTORE_lookup_record(namestore_handle,
100 GNUNET_GNS_RECORD_PSEU,
101 &process_pseu_lookup_ns,
107 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
108 "Name %s not taken in NS! Adding\n", gph->new_name);
110 new_pkey.expiration = GNUNET_TIME_absolute_get_forever ();
111 new_pkey.data_size = sizeof(GNUNET_HashCode);
112 new_pkey.data = &gph->new_zone;
113 new_pkey.record_type = GNUNET_GNS_RECORD_PKEY;
114 GNUNET_NAMESTORE_record_create (namestore_handle,
120 GNUNET_free(gph->new_name);
121 GNUNET_free(gph->name);
127 * process result of a dht pseu lookup
129 * @param gph the handle
130 * @param name the pseu result or NULL
133 process_pseu_result(struct GetPseuAuthorityHandle* gph, char* name)
137 gph->new_name = GNUNET_malloc(strlen(gph->name)+1);
138 memcpy(gph->new_name, name, strlen(gph->name)+1);
142 gph->new_name = GNUNET_malloc(strlen(name)+1);
143 memcpy(gph->new_name, name, strlen(name)+1);
146 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
147 "Checking %s for collision in NS\n", gph->new_name);
150 * Check for collision
152 GNUNET_NAMESTORE_lookup_record(namestore_handle,
155 GNUNET_GNS_RECORD_PSEU,
156 &process_pseu_lookup_ns,
161 * Handle timeout for dht request
163 * @param cls the request handle as closure
164 * @param tc the task context
167 handle_auth_discovery_timeout(void *cls,
168 const struct GNUNET_SCHEDULER_TaskContext *tc)
170 struct GetPseuAuthorityHandle* gph = (struct GetPseuAuthorityHandle*)cls;
172 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
173 "dht lookup for query PSEU timed out.\n");
174 GNUNET_DHT_get_stop (gph->get_handle);
175 process_pseu_result(gph, NULL);
179 * Function called when we find a PSEU entry in the DHT
181 * @param cls the request handle
182 * @param exp lifetime
183 * @param key the key the record was stored under
184 * @param get_path get path
185 * @param get_path_length get path length
186 * @param put_path put path
187 * @param put_path_length put path length
188 * @param type the block type
189 * @param size the size of the record
190 * @param data the record data
193 process_auth_discovery_dht_result(void* cls,
194 struct GNUNET_TIME_Absolute exp,
195 const GNUNET_HashCode * key,
196 const struct GNUNET_PeerIdentity *get_path,
197 unsigned int get_path_length,
198 const struct GNUNET_PeerIdentity *put_path,
199 unsigned int put_path_length,
200 enum GNUNET_BLOCK_Type type,
201 size_t size, const void *data)
203 struct GetPseuAuthorityHandle* gph = (struct GetPseuAuthorityHandle*)cls;
204 struct GNSNameRecordBlock *nrb;
205 char* rd_data = (char*)data;
211 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "got dht result (size=%d)\n", size);
215 GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "got dht result null!\n", size);
217 GNUNET_free(gph->new_name);
218 GNUNET_free(gph->name);
223 nrb = (struct GNSNameRecordBlock*)data;
225 /* stop lookup and timeout task */
226 GNUNET_DHT_get_stop (gph->get_handle);
227 GNUNET_SCHEDULER_cancel(gph->dht_timeout);
229 gph->get_handle = NULL;
231 nrb = (struct GNSNameRecordBlock*)data;
233 name = (char*)&nrb[1];
234 num_records = ntohl(nrb->rd_count);
236 struct GNUNET_NAMESTORE_RecordData rd[num_records];
238 rd_data += strlen(name) + 1 + sizeof(struct GNSNameRecordBlock);
239 rd_size = size - strlen(name) - 1 - sizeof(struct GNSNameRecordBlock);
241 if (GNUNET_SYSERR == GNUNET_NAMESTORE_records_deserialize (rd_size,
246 GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Error deserializing data!\n");
248 GNUNET_free(gph->new_name);
249 GNUNET_free(gph->name);
254 for (i=0; i<num_records; i++)
256 if ((strcmp(name, "+") == 0) &&
257 (rd[i].record_type == GNUNET_GNS_RECORD_PSEU))
260 process_pseu_result(gph, (char*)rd[i].data);
266 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "no pseu in dht!\n");
267 process_pseu_result(gph, NULL);
271 * Callback called by namestore for a zone to name
274 * @param cls the closure
275 * @param zone_key the zone we queried
276 * @param expire the expiration time of the name
277 * @param name the name found or NULL
278 * @param rd_len number of records for the name
279 * @param rd the record data (PKEY) for the name
280 * @param signature the signature for the record data
283 process_zone_to_name_discover(void *cls,
284 const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *zone_key,
285 struct GNUNET_TIME_Absolute expire,
288 const struct GNUNET_NAMESTORE_RecordData *rd,
289 const struct GNUNET_CRYPTO_RsaSignature *signature)
291 struct GetPseuAuthorityHandle* gph = (struct GetPseuAuthorityHandle*)cls;
293 /* we found a match in our own zone */
296 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
297 "name for zone in our root %d\n", strlen(name));
298 GNUNET_free(gph->new_name);
299 GNUNET_free(gph->name);
309 GNUNET_HashCode name_hash;
310 GNUNET_HashCode lookup_key;
311 struct GNUNET_CRYPTO_HashAsciiEncoded lookup_key_string;
313 GNUNET_CRYPTO_hash("+", strlen("+"), &name_hash);
314 GNUNET_CRYPTO_hash_xor(&name_hash, &gph->new_zone, &lookup_key);
315 GNUNET_CRYPTO_hash_to_enc (&lookup_key, &lookup_key_string);
317 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
318 "starting dht lookup for %s with key: %s\n",
319 "+", (char*)&lookup_key_string);
321 gph->dht_timeout = GNUNET_SCHEDULER_add_delayed(DHT_LOOKUP_TIMEOUT,
322 &handle_auth_discovery_timeout, gph);
324 xquery = htonl(GNUNET_GNS_RECORD_PSEU);
326 gph->get_handle = GNUNET_DHT_get_start(dht_handle,
327 DHT_OPERATION_TIMEOUT,
328 GNUNET_BLOCK_TYPE_GNS_NAMERECORD,
330 DHT_GNS_REPLICATION_LEVEL,
334 &process_auth_discovery_dht_result,
342 * Callback for new authories
344 * @param name the name given by delegation
345 * @param zone the authority
346 * @param the private key of our authority
348 static void process_discovered_authority(char* name, GNUNET_HashCode zone,
349 GNUNET_HashCode our_zone,
350 struct GNUNET_CRYPTO_RsaPrivateKey *key)
352 struct GetPseuAuthorityHandle *gph;
355 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "New authority %s discovered\n",
358 gph = GNUNET_malloc(sizeof(struct GetPseuAuthorityHandle));
359 namelen = strlen(name) + 1;
360 gph->name = GNUNET_malloc(namelen);
361 memcpy(gph->name, name, namelen);
363 gph->new_zone = zone;
364 gph->zone = our_zone;
367 GNUNET_NAMESTORE_zone_to_name (namestore_handle,
370 &process_zone_to_name_discover,
376 * Initialize the resolver
378 * @param nh the namestore handle
379 * @param dh the dht handle
380 * @return GNUNET_OK on success
383 gns_resolver_init(struct GNUNET_NAMESTORE_Handle *nh,
384 struct GNUNET_DHT_Handle *dh)
386 namestore_handle = nh;
388 if ((namestore_handle != NULL) && (dht_handle != NULL))
392 return GNUNET_SYSERR;
397 * Helper function to free resolver handle
399 * @rh the handle to free
402 free_resolver_handle(struct ResolverHandle* rh)
404 struct AuthorityChain *ac;
405 struct AuthorityChain *ac_next;
410 GNUNET_free_non_null (rh->name);
411 GNUNET_free_non_null (rh->authority_name);
413 ac = rh->authority_chain_head;
418 GNUNET_free_non_null (ac->name);
427 * Callback when record data is put into namestore
429 * @param cls the closure
430 * @param success GNUNET_OK on success
431 * @param emsg the error message. NULL if SUCCESS==GNUNET_OK
434 on_namestore_record_put_result(void *cls,
438 if (GNUNET_NO == success)
440 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "records already in namestore\n");
443 else if (GNUNET_YES == success)
445 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
446 "records successfully put in namestore\n");
450 GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
451 "Error putting records into namestore: %s\n", emsg);
456 * Handle timeout for DHT requests
458 * @param cls the request handle as closure
459 * @param tc the task context
462 dht_lookup_timeout(void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
464 struct ResolverHandle *rh = cls;
466 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
467 "dht lookup for query %s timed out.\n",
470 GNUNET_DHT_get_stop (rh->get_handle);
471 rh->proc(rh->proc_cls, rh, 0, NULL);
476 * Function called when we get a result from the dht
477 * for our record query
479 * @param cls the request handle
480 * @param exp lifetime
481 * @param key the key the record was stored under
482 * @param get_path get path
483 * @param get_path_length get path length
484 * @param put_path put path
485 * @param put_path_length put path length
486 * @param type the block type
487 * @param size the size of the record
488 * @param data the record data
491 process_record_result_dht(void* cls,
492 struct GNUNET_TIME_Absolute exp,
493 const GNUNET_HashCode * key,
494 const struct GNUNET_PeerIdentity *get_path,
495 unsigned int get_path_length,
496 const struct GNUNET_PeerIdentity *put_path,
497 unsigned int put_path_length,
498 enum GNUNET_BLOCK_Type type,
499 size_t size, const void *data)
501 struct ResolverHandle *rh;
502 struct RecordLookupHandle *rlh;
503 struct GNSNameRecordBlock *nrb;
504 uint32_t num_records;
506 char* rd_data = (char*)data;
510 GNUNET_HashCode zone, name_hash;
511 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "got dht result (size=%d)\n", size);
516 //FIXME maybe check expiration here, check block type
518 rh = (struct ResolverHandle *)cls;
519 rlh = (struct RecordLookupHandle *) rh->proc_cls;
520 nrb = (struct GNSNameRecordBlock*)data;
522 /* stop lookup and timeout task */
523 GNUNET_DHT_get_stop (rh->get_handle);
524 GNUNET_SCHEDULER_cancel(rh->dht_timeout_task);
526 rh->get_handle = NULL;
527 name = (char*)&nrb[1];
528 num_records = ntohl(nrb->rd_count);
530 struct GNUNET_NAMESTORE_RecordData rd[num_records];
532 rd_data += strlen(name) + 1 + sizeof(struct GNSNameRecordBlock);
533 rd_size = size - strlen(name) - 1 - sizeof(struct GNSNameRecordBlock);
535 if (GNUNET_SYSERR == GNUNET_NAMESTORE_records_deserialize (rd_size,
540 GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Error deserializing data!\n");
544 for (i=0; i<num_records; i++)
546 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
547 "Got name: %s (wanted %s)\n", name, rh->name);
548 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
551 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
552 "Got data length: %d\n", rd[i].data_size);
553 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
554 "Got flag %d\n", rd[i].flags);
556 if ((strcmp(name, rh->name) == 0) &&
557 (rd[i].record_type == rlh->record_type))
564 GNUNET_CRYPTO_hash(name, strlen(name), &name_hash);
565 GNUNET_CRYPTO_hash_xor(key, &name_hash, &zone);
568 * FIXME check pubkey against existing key in namestore?
569 * https://gnunet.org/bugs/view.php?id=2179
572 /* Save to namestore */
573 GNUNET_NAMESTORE_record_put (namestore_handle,
580 &on_namestore_record_put_result, //cont
584 rh->proc(rh->proc_cls, rh, num_records, rd);
586 rh->proc(rh->proc_cls, rh, 0, NULL);
593 * Start DHT lookup for a (name -> query->record_type) record in
594 * rh->authority's zone
596 * @param rh the pending gns query context
599 resolve_record_dht(struct ResolverHandle *rh)
602 GNUNET_HashCode name_hash;
603 GNUNET_HashCode lookup_key;
604 struct GNUNET_CRYPTO_HashAsciiEncoded lookup_key_string;
605 struct RecordLookupHandle *rlh = (struct RecordLookupHandle *)rh->proc_cls;
607 GNUNET_CRYPTO_hash(rh->name, strlen(rh->name), &name_hash);
608 GNUNET_CRYPTO_hash_xor(&name_hash, &rh->authority, &lookup_key);
609 GNUNET_CRYPTO_hash_to_enc (&lookup_key, &lookup_key_string);
611 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
612 "starting dht lookup for %s with key: %s\n",
613 rh->name, (char*)&lookup_key_string);
615 rh->dht_timeout_task = GNUNET_SCHEDULER_add_delayed(DHT_LOOKUP_TIMEOUT,
616 &dht_lookup_timeout, rh);
618 xquery = htonl(rlh->record_type);
619 rh->get_handle = GNUNET_DHT_get_start(dht_handle,
620 DHT_OPERATION_TIMEOUT,
621 GNUNET_BLOCK_TYPE_GNS_NAMERECORD,
623 DHT_GNS_REPLICATION_LEVEL,
627 &process_record_result_dht,
634 * Namestore calls this function if we have record for this name.
635 * (or with rd_count=0 to indicate no matches)
637 * @param cls the pending query
638 * @param key the key of the zone we did the lookup
639 * @param expiration expiration date of the namestore entry
640 * @param name the name for which we need an authority
641 * @param rd_count the number of records with 'name'
642 * @param rd the record data
643 * @param signature the signature of the authority for the record data
646 process_record_result_ns(void* cls,
647 const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *key,
648 struct GNUNET_TIME_Absolute expiration,
649 const char *name, unsigned int rd_count,
650 const struct GNUNET_NAMESTORE_RecordData *rd,
651 const struct GNUNET_CRYPTO_RsaSignature *signature)
653 struct ResolverHandle *rh;
654 struct RecordLookupHandle *rlh;
655 struct GNUNET_TIME_Relative remaining_time;
656 GNUNET_HashCode zone;
658 rh = (struct ResolverHandle *) cls;
659 rlh = (struct RecordLookupHandle *)rh->proc_cls;
660 GNUNET_CRYPTO_hash(key,
661 sizeof(struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded),
663 remaining_time = GNUNET_TIME_absolute_get_remaining (expiration);
669 rh->status |= EXISTS;
672 if (remaining_time.rel_value == 0)
674 rh->status |= EXPIRED;
680 * Lookup terminated and no results
682 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
683 "Namestore lookup for %s terminated without results\n", name);
685 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
686 "Record %s unknown in namestore\n",
689 * Our zone and no result? Cannot resolve TT
691 rh->proc(rh->proc_cls, rh, 0, NULL);
698 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
699 "Processing additional result %s from namestore\n", name);
701 for (i=0; i<rd_count;i++)
704 if (rd[i].record_type != rlh->record_type)
707 if ((GNUNET_TIME_absolute_get_remaining (rd[i].expiration)).rel_value
710 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
711 "This record is expired. Skipping\n");
722 if (rh->answered == 0)
724 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
725 "No answers found. This is odd!\n");
726 rh->proc(rh->proc_cls, rh, 0, NULL);
730 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Found %d answer(s) to query!\n",
733 rh->proc(rh->proc_cls, rh, rd_count, rd);
739 * The final phase of resolution.
740 * rh->name is a name that is canonical and we do not have a delegation.
741 * Query namestore for this record
743 * @param rh the pending lookup
746 resolve_record_ns(struct ResolverHandle *rh)
748 struct RecordLookupHandle *rlh = (struct RecordLookupHandle *)rh->proc_cls;
751 * Try to resolve this record in our namestore.
752 * The name to resolve is now in rh->authority_name
753 * since we tried to resolve it to an authority
756 GNUNET_NAMESTORE_lookup_record(namestore_handle,
760 &process_record_result_ns,
766 * Handle timeout for DHT requests
768 * @param cls the request handle as closure
769 * @param tc the task context
772 dht_authority_lookup_timeout(void *cls,
773 const struct GNUNET_SCHEDULER_TaskContext *tc)
775 struct ResolverHandle *rh = cls;
777 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
778 "dht lookup for query %s timed out.\n",
781 GNUNET_DHT_get_stop (rh->get_handle);
782 if (strcmp(rh->name, "") == 0)
785 * promote authority back to name and try to resolve record
787 strcpy(rh->name, rh->authority_name);
789 rh->proc(rh->proc_cls, rh, 0, NULL);
793 static void resolve_delegation_dht(struct ResolverHandle *rh);
796 * Function called when we get a result from the dht
797 * for our query. Recursively tries to resolve authorities
800 * @param cls the request handle
801 * @param exp lifetime
802 * @param key the key the record was stored under
803 * @param get_path get path
804 * @param get_path_length get path length
805 * @param put_path put path
806 * @param put_path_length put path length
807 * @param type the block type
808 * @param size the size of the record
809 * @param data the record data
812 process_delegation_result_dht(void* cls,
813 struct GNUNET_TIME_Absolute exp,
814 const GNUNET_HashCode * key,
815 const struct GNUNET_PeerIdentity *get_path,
816 unsigned int get_path_length,
817 const struct GNUNET_PeerIdentity *put_path,
818 unsigned int put_path_length,
819 enum GNUNET_BLOCK_Type type,
820 size_t size, const void *data)
822 struct ResolverHandle *rh;
823 struct GNSNameRecordBlock *nrb;
824 uint32_t num_records;
826 char* rd_data = (char*) data;
829 GNUNET_HashCode zone, name_hash;
831 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Got DHT result\n");
836 //FIXME check expiration?
838 rh = (struct ResolverHandle *)cls;
839 nrb = (struct GNSNameRecordBlock*)data;
841 /* stop dht lookup and timeout task */
842 GNUNET_DHT_get_stop (rh->get_handle);
843 GNUNET_SCHEDULER_cancel(rh->dht_timeout_task);
845 rh->get_handle = NULL;
846 num_records = ntohl(nrb->rd_count);
847 name = (char*)&nrb[1];
849 struct GNUNET_NAMESTORE_RecordData rd[num_records];
851 rd_data += strlen(name) + 1 + sizeof(struct GNSNameRecordBlock);
852 rd_size = size - strlen(name) - 1 - sizeof(struct GNSNameRecordBlock);
854 if (GNUNET_SYSERR == GNUNET_NAMESTORE_records_deserialize (rd_size,
859 GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Error deserializing data!\n");
863 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
864 "Got name: %s (wanted %s)\n", name, rh->authority_name);
865 for (i=0; i<num_records; i++)
868 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
869 "Got name: %s (wanted %s)\n", name, rh->authority_name);
870 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
871 "Got type: %d (wanted %d)\n",
872 rd[i].record_type, GNUNET_GNS_RECORD_PKEY);
873 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
874 "Got data length: %d\n", rd[i].data_size);
875 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
876 "Got flag %d\n", rd[i].flags);
878 if ((strcmp(name, rh->authority_name) == 0) &&
879 (rd[i].record_type == GNUNET_GNS_RECORD_PKEY))
881 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Authority found in DHT\n");
883 memcpy(&rh->authority, rd[i].data, sizeof(GNUNET_HashCode));
884 struct AuthorityChain *auth =
885 GNUNET_malloc(sizeof(struct AuthorityChain));
886 auth->zone = rh->authority;
887 auth->name = GNUNET_malloc(strlen(rh->authority_name)+1);
888 memset(auth->name, 0, strlen(rh->authority_name)+1);
889 strcpy(auth->name, rh->authority_name);
890 GNUNET_CONTAINER_DLL_insert (rh->authority_chain_head,
891 rh->authority_chain_tail,
894 /** call process new authority */
896 process_discovered_authority(name, auth->zone,
897 rh->authority_chain_tail->zone,
904 GNUNET_CRYPTO_hash(name, strlen(name), &name_hash);
905 GNUNET_CRYPTO_hash_xor(key, &name_hash, &zone);
907 /* Save to namestore */
908 if (0 != GNUNET_CRYPTO_hash_cmp(&rh->authority_chain_tail->zone, &zone))
910 GNUNET_NAMESTORE_record_put (namestore_handle,
917 &on_namestore_record_put_result, //cont
927 * FIXME in this case. should we ask namestore again?
929 if (strcmp(rh->name, "") == 0)
930 rh->proc(rh->proc_cls, rh, 0, NULL);
932 resolve_delegation_dht(rh);
937 * No pkey but name exists
939 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "DHT authority lookup found no match!\n");
940 rh->proc(rh->proc_cls, rh, 0, NULL);
945 * Process DHT lookup result for record.
947 * @param cls the closure
948 * @param rh resolver handle
949 * @param rd_count number of results
950 * @param rd record data
953 handle_record_dht(void* cls, struct ResolverHandle *rh,
954 unsigned int rd_count,
955 const struct GNUNET_NAMESTORE_RecordData *rd)
957 struct RecordLookupHandle* rlh;
958 rlh = (struct RecordLookupHandle*)cls;
961 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
962 "No records for %s found in DHT. Aborting\n",
964 /* give up, cannot resolve */
965 rlh->proc(rlh->proc_cls, 0, NULL);
966 GNUNET_free(rlh->name);
968 free_resolver_handle(rh);
972 /* results found yay */
973 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
974 "Record resolved from DHT!");
975 rlh->proc(rlh->proc_cls, rd_count, rd);
976 GNUNET_free(rlh->name);
978 free_resolver_handle(rh);
984 * Process namestore lookup result for record.
986 * @param cls the closure
987 * @param rh resolver handle
988 * @param rd_count number of results
989 * @param rd record data
992 handle_record_ns(void* cls, struct ResolverHandle *rh,
993 unsigned int rd_count,
994 const struct GNUNET_NAMESTORE_RecordData *rd)
996 struct RecordLookupHandle* rlh;
997 rlh = (struct RecordLookupHandle*) cls;
1000 /* ns entry expired and not ours. try dht */
1001 if (rh->status & (EXPIRED | !EXISTS) &&
1002 GNUNET_CRYPTO_hash_cmp(&rh->authority_chain_head->zone,
1003 &rh->authority_chain_tail->zone))
1005 rh->proc = &handle_record_dht;
1006 resolve_record_dht(rh);
1009 /* give up, cannot resolve */
1010 rlh->proc(rlh->proc_cls, 0, NULL);
1011 GNUNET_free(rlh->name);
1013 free_resolver_handle(rh);
1017 /* results found yay */
1018 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1019 "Record resolved from namestore!");
1020 rlh->proc(rlh->proc_cls, rd_count, rd);
1021 GNUNET_free(rlh->name);
1023 free_resolver_handle(rh);
1029 * Determine if this name is canonical.
1031 * a.b.gnunet = not canonical
1034 * @param name the name to test
1035 * @return 1 if canonical
1038 is_canonical(char* name)
1040 uint32_t len = strlen(name);
1043 for (i=0; i<len; i++)
1045 if (*(name+i) == '.')
1052 * Move one level up in the domain hierarchy and return the
1053 * passed top level domain.
1055 * @param name the domain
1056 * @param dest the destination where the tld will be put
1059 pop_tld(char* name, char* dest)
1063 if (is_canonical(name))
1070 for (len = strlen(name); len > 0; len--)
1072 if (*(name+len) == '.')
1082 strcpy(dest, (name+len+1));
1086 * DHT resolution for delegation finished. Processing result.
1088 * @param cls the closure
1089 * @param rh resolver handle
1090 * @param rd_count number of results (always 0)
1091 * @param rd record data (always NULL)
1094 handle_delegation_dht(void* cls, struct ResolverHandle *rh,
1095 unsigned int rd_count,
1096 const struct GNUNET_NAMESTORE_RecordData *rd)
1098 struct RecordLookupHandle* rlh;
1099 rlh = (struct RecordLookupHandle*) cls;
1101 if (strcmp(rh->name, "") == 0)
1103 /* We resolved full name for delegation. resolving record */
1104 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1105 "Resolved full name for delegation via DHT. resolving record '' in ns\n");
1106 rh->proc = &handle_record_ns;
1107 resolve_record_ns(rh);
1112 * we still have some left
1114 if (is_canonical(rh->name))
1116 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1117 "Resolving canonical record %s in ns\n", rh->name);
1118 rh->proc = &handle_record_ns;
1119 resolve_record_ns(rh);
1122 /* give up, cannot resolve */
1123 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1124 "Cannot fully resolve delegation for %s via DHT!\n",
1126 rlh->proc(rlh->proc_cls, 0, NULL);
1127 GNUNET_free(rlh->name);
1129 free_resolver_handle(rh);
1134 * Start DHT lookup for a name -> PKEY (compare NS) record in
1135 * rh->authority's zone
1137 * @param rh the pending gns query
1140 resolve_delegation_dht(struct ResolverHandle *rh)
1143 GNUNET_HashCode name_hash;
1144 GNUNET_HashCode lookup_key;
1146 GNUNET_CRYPTO_hash(rh->authority_name,
1147 strlen(rh->authority_name),
1149 GNUNET_CRYPTO_hash_xor(&name_hash, &rh->authority, &lookup_key);
1151 rh->dht_timeout_task = GNUNET_SCHEDULER_add_delayed (DHT_LOOKUP_TIMEOUT,
1152 &dht_authority_lookup_timeout,
1155 xquery = htonl(GNUNET_GNS_RECORD_PKEY);
1157 rh->get_handle = GNUNET_DHT_get_start(dht_handle,
1158 DHT_OPERATION_TIMEOUT,
1159 GNUNET_BLOCK_TYPE_GNS_NAMERECORD,
1161 DHT_GNS_REPLICATION_LEVEL,
1165 &process_delegation_result_dht,
1172 * Namestore resolution for delegation finished. Processing result.
1174 * @param cls the closure
1175 * @param rh resolver handle
1176 * @param rd_count number of results (always 0)
1177 * @param rd record data (always NULL)
1180 handle_delegation_ns(void* cls, struct ResolverHandle *rh,
1181 unsigned int rd_count,
1182 const struct GNUNET_NAMESTORE_RecordData *rd)
1184 struct RecordLookupHandle* rlh;
1185 rlh = (struct RecordLookupHandle*) cls;
1187 if (strcmp(rh->name, "") == 0)
1189 /* We resolved full name for delegation. resolving record */
1190 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1191 "Resolved full name for delegation. resolving record ''\n");
1192 rh->proc = &handle_record_ns;
1193 resolve_record_ns(rh);
1198 * we still have some left
1199 * check if authority in ns is fresh
1201 * or we are authority
1203 if ((rh->status & (EXISTS | !EXPIRED)) ||
1204 !GNUNET_CRYPTO_hash_cmp(&rh->authority_chain_head->zone,
1205 &rh->authority_chain_tail->zone))
1207 if (is_canonical(rh->name))
1209 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1210 "Resolving canonical record %s\n", rh->name);
1211 rh->proc = &handle_record_ns;
1212 resolve_record_ns(rh);
1216 /* give up, cannot resolve */
1217 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1218 "Cannot fully resolve delegation for %s!\n",
1220 rlh->proc(rlh->proc_cls, 0, NULL);
1225 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1226 "Trying to resolve delegation for %s via DHT\n",
1228 rh->proc = &handle_delegation_dht;
1229 resolve_delegation_dht(rh);
1233 static void resolve_delegation_ns(struct ResolverHandle *rh);
1237 * This is a callback function that should give us only PKEY
1238 * records. Used to query the namestore for the authority (PKEY)
1239 * for 'name'. It will recursively try to resolve the
1240 * authority for a given name from the namestore.
1242 * @param cls the pending query
1243 * @param key the key of the zone we did the lookup
1244 * @param expiration expiration date of the record data set in the namestore
1245 * @param name the name for which we need an authority
1246 * @param rd_count the number of records with 'name'
1247 * @param rd the record data
1248 * @param signature the signature of the authority for the record data
1251 process_delegation_result_ns(void* cls,
1252 const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *key,
1253 struct GNUNET_TIME_Absolute expiration,
1255 unsigned int rd_count,
1256 const struct GNUNET_NAMESTORE_RecordData *rd,
1257 const struct GNUNET_CRYPTO_RsaSignature *signature)
1259 struct ResolverHandle *rh;
1260 struct GNUNET_TIME_Relative remaining_time;
1261 GNUNET_HashCode zone;
1264 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Got %d records from authority lookup\n",
1267 rh = (struct ResolverHandle *)cls;
1268 GNUNET_CRYPTO_hash(key,
1269 sizeof(struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded),
1271 remaining_time = GNUNET_TIME_absolute_get_remaining (expiration);
1277 rh->status |= EXISTS;
1280 if (remaining_time.rel_value == 0)
1282 rh->status |= EXPIRED;
1286 * No authority found in namestore.
1291 * We did not find an authority in the namestore
1296 * Promote this authority back to a name maybe it is
1299 if (strcmp(rh->name, "") == 0)
1301 /* simply promote back */
1302 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1303 "Promoting %s back to name\n", rh->authority_name);
1304 strcpy(rh->name, rh->authority_name);
1308 /* add back to existing name */
1309 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1310 "Adding %s back to %s\n",
1311 rh->authority_name, rh->name);
1312 new_name = GNUNET_malloc(strlen(rh->name)
1313 + strlen(rh->authority_name) + 2);
1314 memset(new_name, 0, strlen(rh->name) + strlen(rh->authority_name) + 2);
1315 strcpy(new_name, rh->name);
1316 strcpy(new_name+strlen(new_name)+1, ".");
1317 strcpy(new_name+strlen(new_name)+2, rh->authority_name);
1318 GNUNET_free(rh->name);
1319 rh->name = new_name;
1321 rh->proc(rh->proc_cls, rh, 0, NULL);
1326 * We found an authority that may be able to help us
1327 * move on with query
1328 * Note only 1 pkey should have been returned.. anything else would be strange
1331 for (i=0; i<rd_count;i++)
1334 if (rd[i].record_type != GNUNET_GNS_RECORD_PKEY)
1337 if ((GNUNET_TIME_absolute_get_remaining (rd[i].expiration)).rel_value
1340 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "This pkey is expired.\n");
1341 if (remaining_time.rel_value == 0)
1343 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1344 "This dht entry is expired.\n");
1345 rh->authority_chain_head->fresh = 0;
1346 rh->proc(rh->proc_cls, rh, 0, NULL);
1354 * Resolve rest of query with new authority
1356 GNUNET_assert(rd[i].record_type == GNUNET_GNS_RECORD_PKEY);
1357 memcpy(&rh->authority, rd[i].data, sizeof(GNUNET_HashCode));
1358 struct AuthorityChain *auth = GNUNET_malloc(sizeof(struct AuthorityChain));
1359 auth->zone = rh->authority;
1360 auth->name = GNUNET_malloc(strlen(rh->authority_name)+1);
1361 memset(auth->name, 0, strlen(rh->authority_name)+1);
1362 strcpy(auth->name, rh->authority_name);
1363 GNUNET_CONTAINER_DLL_insert (rh->authority_chain_head,
1364 rh->authority_chain_tail,
1368 * We are done with PKEY resolution if name is empty
1369 * else resolve again with new authority
1371 if (strcmp(rh->name, "") == 0)
1372 rh->proc(rh->proc_cls, rh, 0, NULL);
1374 resolve_delegation_ns(rh);
1381 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1382 "Authority lookup successful but no PKEY... never get here\n");
1383 rh->proc(rh->proc_cls, rh, 0, NULL);
1388 * Resolve the delegation chain for the request in our namestore
1390 * @param rh the resolver handle
1393 resolve_delegation_ns(struct ResolverHandle *rh)
1395 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1396 "Resolving delegation for %s\n", rh->name);
1397 pop_tld(rh->name, rh->authority_name);
1398 GNUNET_NAMESTORE_lookup_record(namestore_handle,
1401 GNUNET_GNS_RECORD_PKEY,
1402 &process_delegation_result_ns,
1409 * Lookup of a record in a specific zone
1410 * calls lookup result processor on result
1412 * @param zone the root zone
1413 * @param record_type the record type to look up
1414 * @param name the name to look up
1415 * @param proc the processor to call on result
1416 * @param cls the closure to pass to proc
1419 gns_resolver_lookup_record(GNUNET_HashCode zone,
1420 uint32_t record_type,
1422 struct GNUNET_CRYPTO_RsaPrivateKey *key,
1423 RecordLookupProcessor proc,
1426 struct ResolverHandle *rh;
1427 struct RecordLookupHandle* rlh;
1429 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1430 "Starting resolution for %s (type=%d)!\n",
1434 if (is_canonical((char*)name) && (strcmp(GNUNET_GNS_TLD, name) != 0))
1436 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1437 "%s is canonical and gnunet not our TLD!\n", name);
1442 rlh = GNUNET_malloc(sizeof(struct RecordLookupHandle));
1443 rh = GNUNET_malloc(sizeof (struct ResolverHandle));
1445 rh->authority = zone;
1449 if (strcmp(GNUNET_GNS_TLD, name) == 0)
1451 rh->name = GNUNET_malloc(2);
1452 strcpy(rh->name, "");
1456 rh->name = GNUNET_malloc(strlen(name)
1457 - strlen(GNUNET_GNS_TLD));
1459 strlen(name)-strlen(GNUNET_GNS_TLD));
1460 memcpy(rh->name, name,
1461 strlen(name)-strlen(GNUNET_GNS_TLD) - 1);
1464 rh->authority_name = GNUNET_malloc(sizeof(char)*MAX_DNS_LABEL_LENGTH);
1465 rh->authority_chain_head = GNUNET_malloc(sizeof(struct AuthorityChain));
1466 rh->authority_chain_head->prev = NULL;
1467 rh->authority_chain_head->next = NULL;
1468 rh->authority_chain_tail = rh->authority_chain_head;
1469 rh->authority_chain_head->zone = zone;
1471 rlh->record_type = record_type;
1472 rlh->name = GNUNET_malloc(strlen(name) + 1);
1473 memset(rlh->name, 0, strlen(name) + 1);
1474 strcpy(rlh->name, name); //FIXME
1476 rlh->proc_cls = cls;
1478 rh->proc = &handle_delegation_ns;
1479 resolve_delegation_ns(rh);
1482 /******** END Record Resolver ***********/
1486 * Callback calles by namestore for a zone to name
1489 * @param cls the closure
1490 * @param zone_key the zone we queried
1491 * @param expire the expiration time of the name
1492 * @param name the name found or NULL
1493 * @param rd_len number of records for the name
1494 * @param rd the record data (PKEY) for the name
1495 * @param signature the signature for the record data
1498 process_zone_to_name_shorten(void *cls,
1499 const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *zone_key,
1500 struct GNUNET_TIME_Absolute expire,
1502 unsigned int rd_len,
1503 const struct GNUNET_NAMESTORE_RecordData *rd,
1504 const struct GNUNET_CRYPTO_RsaSignature *signature)
1506 struct ResolverHandle *rh = (struct ResolverHandle *)cls;
1507 struct NameShortenHandle* nsh = (struct NameShortenHandle*)rh->proc_cls;
1508 struct AuthorityChain *next_authority;
1511 char* next_authority_name;
1514 /* we found a match in our own zone */
1517 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1518 "result strlen %d\n", strlen(name));
1519 answer_len = strlen(rh->name) + strlen(name) + strlen(GNUNET_GNS_TLD) + 3;
1520 result = GNUNET_malloc(answer_len);
1521 memset(result, 0, answer_len);
1522 if (strlen(rh->name) > 0)
1524 strcpy(result, rh->name);
1525 strcpy(result+strlen(rh->name), ".");
1528 strcpy(result+strlen(result), name);
1529 strcpy(result+strlen(result), ".");
1530 strcpy(result+strlen(result), GNUNET_GNS_TLD);
1532 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1533 "Sending shorten result %s\n", result);
1535 nsh->proc(nsh->proc_cls, result);
1537 free_resolver_handle(rh);
1538 GNUNET_free(result);
1540 else if (GNUNET_CRYPTO_hash_cmp(&rh->authority_chain_head->zone,
1541 &rh->authority_chain_tail->zone))
1543 /* our zone, just append .gnunet */
1544 answer_len = strlen(rh->name) + strlen(GNUNET_GNS_TLD) + 2;
1545 result = GNUNET_malloc(answer_len);
1546 memset(result, 0, answer_len);
1547 strcpy(result, rh->name);
1548 strcpy(result+strlen(rh->name), ".");
1549 strcpy(result+strlen(rh->name)+1, GNUNET_GNS_TLD);
1551 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1552 "Our zone: Sending name as shorten result %s\n", rh->name);
1554 nsh->proc(nsh->proc_cls, result);
1556 free_resolver_handle(rh);
1557 GNUNET_free(result);
1563 * continue with next authority
1565 next_authority = rh->authority_chain_head;
1566 next_authority_name = GNUNET_malloc(strlen(rh->name)+
1567 strlen(next_authority->name) + 2);
1568 memset(next_authority_name, 0, strlen(rh->name)+
1569 strlen(next_authority->name) + 2);
1570 strcpy(next_authority_name, rh->name);
1571 strcpy(next_authority_name+strlen(rh->name)+1, ".");
1572 strcpy(next_authority_name+strlen(rh->name)+2, next_authority->name);
1574 GNUNET_free(rh->name);
1575 rh->name = next_authority_name;
1576 GNUNET_CONTAINER_DLL_remove(rh->authority_chain_head,
1577 rh->authority_chain_tail,
1580 GNUNET_NAMESTORE_zone_to_name (namestore_handle,
1581 &rh->authority_chain_tail->zone,
1582 &rh->authority_chain_head->zone,
1583 &process_zone_to_name_shorten,
1590 * Process result from namestore delegation lookup
1591 * for shorten operation
1593 * @param cls the client shorten handle
1594 * @param rh the resolver handle
1595 * @param rd_count number of results (0)
1596 * @param rd data (NULL)
1599 handle_delegation_ns_shorten(void* cls,
1600 struct ResolverHandle *rh,
1602 const struct GNUNET_NAMESTORE_RecordData *rd)
1604 struct NameShortenHandle *nsh;
1608 nsh = (struct NameShortenHandle *)cls;
1611 * At this point rh->name contains the part of the name
1612 * that we do not have a PKEY in our namestore to resolve.
1613 * The authority chain in the resolver handle is now
1614 * useful to backtrack if needed
1617 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1618 "PKEY resolved as far as possible in ns up to %s!\n", rh->name);
1620 if (GNUNET_CRYPTO_hash_cmp(&rh->authority_chain_head->zone,
1621 &rh->authority_chain_tail->zone) == 0)
1624 * This is our zone append .gnunet unless name is empty
1625 * (it shouldn't be, usually FIXME what happens if we
1626 * shorten to our zone to a "" record??)
1629 answer_len = strlen(rh->name) + strlen(GNUNET_GNS_TLD) + 2;
1630 result = GNUNET_malloc(answer_len);
1631 memset(result, 0, answer_len);
1632 strcpy(result, rh->name);
1633 strcpy(result+strlen(rh->name), ".");
1634 strcpy(result+strlen(rh->name)+1, GNUNET_GNS_TLD);
1636 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1637 "Our zone: Sending name as shorten result %s\n", rh->name);
1639 nsh->proc(nsh->proc_cls, result);
1641 free_resolver_handle(rh);
1642 GNUNET_free(result);
1646 /* backtrack authorities for names */
1647 GNUNET_NAMESTORE_zone_to_name (namestore_handle,
1648 &rh->authority_chain_tail->zone, //ours
1649 &rh->authority_chain_head->zone,
1650 &process_zone_to_name_shorten,
1656 * Shorten api from resolver
1658 * @param zone the zone to use
1659 * @param name the name to shorten
1660 * @param proc the processor to call with result
1661 * @param cls closure to pass to proc
1664 gns_resolver_shorten_name(GNUNET_HashCode zone,
1666 ShortenResultProcessor proc,
1669 struct ResolverHandle *rh;
1670 struct NameShortenHandle *nsh;
1672 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1673 "Starting shorten for %s!\n", name);
1675 if (is_canonical((char*)name))
1677 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1678 "%s is canonical. Returning verbatim\n", name);
1683 nsh = GNUNET_malloc(sizeof (struct NameShortenHandle));
1687 nsh->proc_cls = cls;
1689 rh = GNUNET_malloc(sizeof (struct ResolverHandle));
1690 rh->authority = zone;
1691 rh->name = GNUNET_malloc(strlen(name)
1692 - strlen(GNUNET_GNS_TLD));
1694 strlen(name)-strlen(GNUNET_GNS_TLD));
1695 memcpy(rh->name, name,
1696 strlen(name)-strlen(GNUNET_GNS_TLD)-1);
1698 rh->authority_name = GNUNET_malloc(sizeof(char)*MAX_DNS_LABEL_LENGTH);
1699 rh->authority_chain_head = GNUNET_malloc(sizeof(struct AuthorityChain));
1700 rh->authority_chain_tail = rh->authority_chain_head;
1701 rh->authority_chain_head->zone = zone;
1702 rh->proc = &handle_delegation_ns_shorten;
1705 /* Start delegation resolution in our namestore */
1706 resolve_delegation_ns(rh);
1709 /*********** END NAME SHORTEN ********************/
1713 * Process result from namestore delegation lookup
1714 * for get authority operation
1716 * @param cls the client get auth handle
1717 * @param rh the resolver handle
1718 * @param rd_count number of results (0)
1719 * @param rd data (NULL)
1722 handle_delegation_result_ns_get_auth(void* cls,
1723 struct ResolverHandle *rh,
1725 const struct GNUNET_NAMESTORE_RecordData *rd)
1727 struct GetNameAuthorityHandle* nah;
1731 nah = (struct GetNameAuthorityHandle*) rh->proc_cls;
1734 * At this point rh->name contains the part of the name
1735 * that we do not have a PKEY in our namestore to resolve.
1736 * The authority chain in the resolver handle is now
1737 * useful to backtrack if needed
1740 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1741 "PKEY resolved as far as possible in ns up to %s!\n", rh->name);
1743 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1744 "Building response!\n");
1745 if (is_canonical(rh->name))
1748 * We successfully resolved the authority in the ns
1749 * FIXME for our purposes this is fine
1750 * but maybe we want to have an api that also looks
1751 * into the dht (i.e. option in message)
1753 if (strlen(rh->name) > strlen(nah->name))
1755 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1756 "Record name longer than original lookup name... odd!\n");
1760 answer_len = strlen(nah->name) - strlen(rh->name)
1761 + strlen(GNUNET_GNS_TLD) + 1;
1762 result = GNUNET_malloc(answer_len);
1763 memset(result, 0, answer_len);
1764 strcpy(result, nah->name + strlen(rh->name) + 1);
1766 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1767 "Got authority result %s\n", result);
1769 nah->proc(nah->proc_cls, result);
1770 GNUNET_free(nah->name);
1772 free_resolver_handle(rh);
1773 GNUNET_free(result);
1777 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1778 "Unable to resolve authority for remaining %s!\n", rh->name);
1779 nah->proc(nah->proc_cls, "");
1780 GNUNET_free(nah->name);
1782 free_resolver_handle(rh);
1790 * Tries to resolve the authority for name
1793 * @param zone the root zone to look up for
1794 * @param name the name to lookup up
1795 * @param proc the processor to call when finished
1796 * @param cls the closure to pass to the processor
1799 gns_resolver_get_authority(GNUNET_HashCode zone,
1801 GetAuthorityResultProcessor proc,
1804 struct ResolverHandle *rh;
1805 struct GetNameAuthorityHandle *nah;
1807 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1808 "Starting authority resolution for %s!\n", name);
1810 nah = GNUNET_malloc(sizeof (struct GetNameAuthorityHandle));
1811 rh = GNUNET_malloc(sizeof (struct ResolverHandle));
1812 rh->authority = zone;
1814 if (strcmp(GNUNET_GNS_TLD, name) == 0)
1816 rh->name = GNUNET_malloc(2);
1817 strcpy(rh->name, "");
1821 rh->name = GNUNET_malloc(strlen(name)
1822 - strlen(GNUNET_GNS_TLD));
1824 strlen(name)-strlen(GNUNET_GNS_TLD));
1825 memcpy(rh->name, name,
1826 strlen(name)-strlen(GNUNET_GNS_TLD) - 1);
1829 nah->name = GNUNET_malloc(strlen(name)+1);
1830 memset(nah->name, 0,
1832 strcpy(nah->name, name);
1834 rh->authority_name = GNUNET_malloc(MAX_DNS_LABEL_LENGTH);
1836 rh->authority_chain_head = GNUNET_malloc(sizeof(struct AuthorityChain));
1837 rh->authority_chain_tail = rh->authority_chain_head;
1838 rh->authority_chain_head->zone = zone;
1839 rh->proc = &handle_delegation_result_ns_get_auth;
1840 rh->proc_cls = (void*)nah;
1843 nah->proc_cls = cls;
1845 /* Start delegation resolution in our namestore */
1846 resolve_delegation_ns(rh);
1850 /******** END GET AUTHORITY *************/
1852 /* end of gnunet-service-gns_resolver.c */