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 GNUNET_free(gph->new_name);
97 gph->new_name = GNUNET_malloc(strlen(gph->name)+1);
98 memcpy(gph->new_name, gph->name, strlen(gph->name)+1);
99 GNUNET_NAMESTORE_lookup_record(namestore_handle,
102 GNUNET_GNS_RECORD_PSEU,
103 &process_pseu_lookup_ns,
109 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
110 "Name %s not taken in NS! Adding\n", gph->new_name);
112 new_pkey.expiration = GNUNET_TIME_absolute_get_forever ();
113 new_pkey.data_size = sizeof(GNUNET_HashCode);
114 new_pkey.data = &gph->new_zone;
115 new_pkey.record_type = GNUNET_GNS_RECORD_PKEY;
116 GNUNET_NAMESTORE_record_create (namestore_handle,
122 GNUNET_free(gph->new_name);
123 GNUNET_free(gph->name);
129 * process result of a dht pseu lookup
131 * @param gph the handle
132 * @param name the pseu result or NULL
135 process_pseu_result(struct GetPseuAuthorityHandle* gph, char* name)
139 gph->new_name = GNUNET_malloc(strlen(gph->name)+1);
140 memcpy(gph->new_name, name, strlen(gph->name)+1);
144 gph->new_name = GNUNET_malloc(strlen(name)+1);
145 memcpy(gph->new_name, name, strlen(name)+1);
148 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
149 "Checking %s for collision in NS\n", gph->new_name);
152 * Check for collision
154 GNUNET_NAMESTORE_lookup_record(namestore_handle,
157 GNUNET_GNS_RECORD_PSEU,
158 &process_pseu_lookup_ns,
163 * Handle timeout for dht request
165 * @param cls the request handle as closure
166 * @param tc the task context
169 handle_auth_discovery_timeout(void *cls,
170 const struct GNUNET_SCHEDULER_TaskContext *tc)
172 struct GetPseuAuthorityHandle* gph = (struct GetPseuAuthorityHandle*)cls;
174 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
175 "dht lookup for query PSEU timed out.\n");
176 GNUNET_DHT_get_stop (gph->get_handle);
177 process_pseu_result(gph, NULL);
181 * Function called when we find a PSEU entry in the DHT
183 * @param cls the request handle
184 * @param exp lifetime
185 * @param key the key the record was stored under
186 * @param get_path get path
187 * @param get_path_length get path length
188 * @param put_path put path
189 * @param put_path_length put path length
190 * @param type the block type
191 * @param size the size of the record
192 * @param data the record data
195 process_auth_discovery_dht_result(void* cls,
196 struct GNUNET_TIME_Absolute exp,
197 const GNUNET_HashCode * key,
198 const struct GNUNET_PeerIdentity *get_path,
199 unsigned int get_path_length,
200 const struct GNUNET_PeerIdentity *put_path,
201 unsigned int put_path_length,
202 enum GNUNET_BLOCK_Type type,
203 size_t size, const void *data)
205 struct GetPseuAuthorityHandle* gph = (struct GetPseuAuthorityHandle*)cls;
206 struct GNSNameRecordBlock *nrb;
207 char* rd_data = (char*)data;
213 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "got dht result (size=%d)\n", size);
217 GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "got dht result null!\n", size);
219 GNUNET_free(gph->new_name);
220 GNUNET_free(gph->name);
225 nrb = (struct GNSNameRecordBlock*)data;
227 /* stop lookup and timeout task */
228 GNUNET_DHT_get_stop (gph->get_handle);
229 GNUNET_SCHEDULER_cancel(gph->dht_timeout);
231 gph->get_handle = NULL;
233 nrb = (struct GNSNameRecordBlock*)data;
235 name = (char*)&nrb[1];
236 num_records = ntohl(nrb->rd_count);
238 struct GNUNET_NAMESTORE_RecordData rd[num_records];
240 rd_data += strlen(name) + 1 + sizeof(struct GNSNameRecordBlock);
241 rd_size = size - strlen(name) - 1 - sizeof(struct GNSNameRecordBlock);
243 if (GNUNET_SYSERR == GNUNET_NAMESTORE_records_deserialize (rd_size,
248 GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Error deserializing data!\n");
250 GNUNET_free(gph->new_name);
251 GNUNET_free(gph->name);
256 for (i=0; i<num_records; i++)
258 if ((strcmp(name, "+") == 0) &&
259 (rd[i].record_type == GNUNET_GNS_RECORD_PSEU))
262 process_pseu_result(gph, (char*)rd[i].data);
268 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "no pseu in dht!\n");
269 process_pseu_result(gph, NULL);
273 * Callback called by namestore for a zone to name
276 * @param cls the closure
277 * @param zone_key the zone we queried
278 * @param expire the expiration time of the name
279 * @param name the name found or NULL
280 * @param rd_len number of records for the name
281 * @param rd the record data (PKEY) for the name
282 * @param signature the signature for the record data
285 process_zone_to_name_discover(void *cls,
286 const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *zone_key,
287 struct GNUNET_TIME_Absolute expire,
290 const struct GNUNET_NAMESTORE_RecordData *rd,
291 const struct GNUNET_CRYPTO_RsaSignature *signature)
293 struct GetPseuAuthorityHandle* gph = (struct GetPseuAuthorityHandle*)cls;
295 /* we found a match in our own zone */
298 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
299 "name for zone in our root %d\n", strlen(name));
300 GNUNET_free(gph->new_name);
301 GNUNET_free(gph->name);
311 GNUNET_HashCode name_hash;
312 GNUNET_HashCode lookup_key;
313 struct GNUNET_CRYPTO_HashAsciiEncoded lookup_key_string;
315 GNUNET_CRYPTO_hash("+", strlen("+"), &name_hash);
316 GNUNET_CRYPTO_hash_xor(&name_hash, &gph->new_zone, &lookup_key);
317 GNUNET_CRYPTO_hash_to_enc (&lookup_key, &lookup_key_string);
319 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
320 "starting dht lookup for %s with key: %s\n",
321 "+", (char*)&lookup_key_string);
323 gph->dht_timeout = GNUNET_SCHEDULER_add_delayed(DHT_LOOKUP_TIMEOUT,
324 &handle_auth_discovery_timeout, gph);
326 xquery = htonl(GNUNET_GNS_RECORD_PSEU);
328 gph->get_handle = GNUNET_DHT_get_start(dht_handle,
329 DHT_OPERATION_TIMEOUT,
330 GNUNET_BLOCK_TYPE_GNS_NAMERECORD,
332 DHT_GNS_REPLICATION_LEVEL,
336 &process_auth_discovery_dht_result,
344 * Callback for new authories
346 * @param name the name given by delegation
347 * @param zone the authority
348 * @param the private key of our authority
350 static void process_discovered_authority(char* name, GNUNET_HashCode zone,
351 GNUNET_HashCode our_zone,
352 struct GNUNET_CRYPTO_RsaPrivateKey *key)
354 struct GetPseuAuthorityHandle *gph;
357 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "New authority %s discovered\n",
360 gph = GNUNET_malloc(sizeof(struct GetPseuAuthorityHandle));
361 namelen = strlen(name) + 1;
362 gph->name = GNUNET_malloc(namelen);
363 memcpy(gph->name, name, namelen);
365 gph->new_zone = zone;
366 gph->zone = our_zone;
369 GNUNET_NAMESTORE_zone_to_name (namestore_handle,
372 &process_zone_to_name_discover,
378 * Initialize the resolver
380 * @param nh the namestore handle
381 * @param dh the dht handle
382 * @return GNUNET_OK on success
385 gns_resolver_init(struct GNUNET_NAMESTORE_Handle *nh,
386 struct GNUNET_DHT_Handle *dh)
388 namestore_handle = nh;
390 if ((namestore_handle != NULL) && (dht_handle != NULL))
394 return GNUNET_SYSERR;
399 * Helper function to free resolver handle
401 * @rh the handle to free
404 free_resolver_handle(struct ResolverHandle* rh)
406 struct AuthorityChain *ac;
407 struct AuthorityChain *ac_next;
412 GNUNET_free_non_null (rh->name);
413 GNUNET_free_non_null (rh->authority_name);
415 ac = rh->authority_chain_head;
420 GNUNET_free_non_null (ac->name);
429 * Callback when record data is put into namestore
431 * @param cls the closure
432 * @param success GNUNET_OK on success
433 * @param emsg the error message. NULL if SUCCESS==GNUNET_OK
436 on_namestore_record_put_result(void *cls,
440 if (GNUNET_NO == success)
442 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "records already in namestore\n");
445 else if (GNUNET_YES == success)
447 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
448 "records successfully put in namestore\n");
452 GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
453 "Error putting records into namestore: %s\n", emsg);
458 * Handle timeout for DHT requests
460 * @param cls the request handle as closure
461 * @param tc the task context
464 dht_lookup_timeout(void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
466 struct ResolverHandle *rh = cls;
468 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
469 "dht lookup for query %s timed out.\n",
472 GNUNET_DHT_get_stop (rh->get_handle);
473 rh->proc(rh->proc_cls, rh, 0, NULL);
478 * Function called when we get a result from the dht
479 * for our record query
481 * @param cls the request handle
482 * @param exp lifetime
483 * @param key the key the record was stored under
484 * @param get_path get path
485 * @param get_path_length get path length
486 * @param put_path put path
487 * @param put_path_length put path length
488 * @param type the block type
489 * @param size the size of the record
490 * @param data the record data
493 process_record_result_dht(void* cls,
494 struct GNUNET_TIME_Absolute exp,
495 const GNUNET_HashCode * key,
496 const struct GNUNET_PeerIdentity *get_path,
497 unsigned int get_path_length,
498 const struct GNUNET_PeerIdentity *put_path,
499 unsigned int put_path_length,
500 enum GNUNET_BLOCK_Type type,
501 size_t size, const void *data)
503 struct ResolverHandle *rh;
504 struct RecordLookupHandle *rlh;
505 struct GNSNameRecordBlock *nrb;
506 uint32_t num_records;
508 char* rd_data = (char*)data;
512 GNUNET_HashCode zone, name_hash;
513 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "got dht result (size=%d)\n", size);
518 //FIXME maybe check expiration here, check block type
520 rh = (struct ResolverHandle *)cls;
521 rlh = (struct RecordLookupHandle *) rh->proc_cls;
522 nrb = (struct GNSNameRecordBlock*)data;
524 /* stop lookup and timeout task */
525 GNUNET_DHT_get_stop (rh->get_handle);
526 GNUNET_SCHEDULER_cancel(rh->dht_timeout_task);
528 rh->get_handle = NULL;
529 name = (char*)&nrb[1];
530 num_records = ntohl(nrb->rd_count);
532 struct GNUNET_NAMESTORE_RecordData rd[num_records];
534 rd_data += strlen(name) + 1 + sizeof(struct GNSNameRecordBlock);
535 rd_size = size - strlen(name) - 1 - sizeof(struct GNSNameRecordBlock);
537 if (GNUNET_SYSERR == GNUNET_NAMESTORE_records_deserialize (rd_size,
542 GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Error deserializing data!\n");
546 for (i=0; i<num_records; i++)
548 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
549 "Got name: %s (wanted %s)\n", name, rh->name);
550 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
553 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
554 "Got data length: %d\n", rd[i].data_size);
555 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
556 "Got flag %d\n", rd[i].flags);
558 if ((strcmp(name, rh->name) == 0) &&
559 (rd[i].record_type == rlh->record_type))
566 GNUNET_CRYPTO_hash(name, strlen(name), &name_hash);
567 GNUNET_CRYPTO_hash_xor(key, &name_hash, &zone);
570 * FIXME check pubkey against existing key in namestore?
571 * https://gnunet.org/bugs/view.php?id=2179
574 /* Save to namestore */
575 GNUNET_NAMESTORE_record_put (namestore_handle,
582 &on_namestore_record_put_result, //cont
586 rh->proc(rh->proc_cls, rh, num_records, rd);
588 rh->proc(rh->proc_cls, rh, 0, NULL);
595 * Start DHT lookup for a (name -> query->record_type) record in
596 * rh->authority's zone
598 * @param rh the pending gns query context
601 resolve_record_dht(struct ResolverHandle *rh)
604 GNUNET_HashCode name_hash;
605 GNUNET_HashCode lookup_key;
606 struct GNUNET_CRYPTO_HashAsciiEncoded lookup_key_string;
607 struct RecordLookupHandle *rlh = (struct RecordLookupHandle *)rh->proc_cls;
609 GNUNET_CRYPTO_hash(rh->name, strlen(rh->name), &name_hash);
610 GNUNET_CRYPTO_hash_xor(&name_hash, &rh->authority, &lookup_key);
611 GNUNET_CRYPTO_hash_to_enc (&lookup_key, &lookup_key_string);
613 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
614 "starting dht lookup for %s with key: %s\n",
615 rh->name, (char*)&lookup_key_string);
617 rh->dht_timeout_task = GNUNET_SCHEDULER_add_delayed(DHT_LOOKUP_TIMEOUT,
618 &dht_lookup_timeout, rh);
620 xquery = htonl(rlh->record_type);
621 rh->get_handle = GNUNET_DHT_get_start(dht_handle,
622 DHT_OPERATION_TIMEOUT,
623 GNUNET_BLOCK_TYPE_GNS_NAMERECORD,
625 DHT_GNS_REPLICATION_LEVEL,
629 &process_record_result_dht,
636 * Namestore calls this function if we have record for this name.
637 * (or with rd_count=0 to indicate no matches)
639 * @param cls the pending query
640 * @param key the key of the zone we did the lookup
641 * @param expiration expiration date of the namestore entry
642 * @param name the name for which we need an authority
643 * @param rd_count the number of records with 'name'
644 * @param rd the record data
645 * @param signature the signature of the authority for the record data
648 process_record_result_ns(void* cls,
649 const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *key,
650 struct GNUNET_TIME_Absolute expiration,
651 const char *name, unsigned int rd_count,
652 const struct GNUNET_NAMESTORE_RecordData *rd,
653 const struct GNUNET_CRYPTO_RsaSignature *signature)
655 struct ResolverHandle *rh;
656 struct RecordLookupHandle *rlh;
657 struct GNUNET_TIME_Relative remaining_time;
658 GNUNET_HashCode zone;
660 rh = (struct ResolverHandle *) cls;
661 rlh = (struct RecordLookupHandle *)rh->proc_cls;
662 GNUNET_CRYPTO_hash(key,
663 sizeof(struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded),
665 remaining_time = GNUNET_TIME_absolute_get_remaining (expiration);
671 rh->status |= EXISTS;
674 if (remaining_time.rel_value == 0)
676 rh->status |= EXPIRED;
682 * Lookup terminated and no results
684 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
685 "Namestore lookup for %s terminated without results\n", name);
687 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
688 "Record %s unknown in namestore\n",
691 * Our zone and no result? Cannot resolve TT
693 rh->proc(rh->proc_cls, rh, 0, NULL);
700 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
701 "Processing additional result %s from namestore\n", name);
703 for (i=0; i<rd_count;i++)
706 if (rd[i].record_type != rlh->record_type)
709 if ((GNUNET_TIME_absolute_get_remaining (rd[i].expiration)).rel_value
712 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
713 "This record is expired. Skipping\n");
724 if (rh->answered == 0)
726 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
727 "No answers found. This is odd!\n");
728 rh->proc(rh->proc_cls, rh, 0, NULL);
732 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Found %d answer(s) to query!\n",
735 rh->proc(rh->proc_cls, rh, rd_count, rd);
741 * The final phase of resolution.
742 * rh->name is a name that is canonical and we do not have a delegation.
743 * Query namestore for this record
745 * @param rh the pending lookup
748 resolve_record_ns(struct ResolverHandle *rh)
750 struct RecordLookupHandle *rlh = (struct RecordLookupHandle *)rh->proc_cls;
753 * Try to resolve this record in our namestore.
754 * The name to resolve is now in rh->authority_name
755 * since we tried to resolve it to an authority
758 GNUNET_NAMESTORE_lookup_record(namestore_handle,
762 &process_record_result_ns,
768 * Handle timeout for DHT requests
770 * @param cls the request handle as closure
771 * @param tc the task context
774 dht_authority_lookup_timeout(void *cls,
775 const struct GNUNET_SCHEDULER_TaskContext *tc)
777 struct ResolverHandle *rh = cls;
779 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
780 "dht lookup for query %s timed out.\n",
783 GNUNET_DHT_get_stop (rh->get_handle);
784 if (strcmp(rh->name, "") == 0)
787 * promote authority back to name and try to resolve record
789 strcpy(rh->name, rh->authority_name);
791 rh->proc(rh->proc_cls, rh, 0, NULL);
795 static void resolve_delegation_dht(struct ResolverHandle *rh);
798 * Function called when we get a result from the dht
799 * for our query. Recursively tries to resolve authorities
802 * @param cls the request handle
803 * @param exp lifetime
804 * @param key the key the record was stored under
805 * @param get_path get path
806 * @param get_path_length get path length
807 * @param put_path put path
808 * @param put_path_length put path length
809 * @param type the block type
810 * @param size the size of the record
811 * @param data the record data
814 process_delegation_result_dht(void* cls,
815 struct GNUNET_TIME_Absolute exp,
816 const GNUNET_HashCode * key,
817 const struct GNUNET_PeerIdentity *get_path,
818 unsigned int get_path_length,
819 const struct GNUNET_PeerIdentity *put_path,
820 unsigned int put_path_length,
821 enum GNUNET_BLOCK_Type type,
822 size_t size, const void *data)
824 struct ResolverHandle *rh;
825 struct GNSNameRecordBlock *nrb;
826 uint32_t num_records;
828 char* rd_data = (char*) data;
831 GNUNET_HashCode zone, name_hash;
833 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Got DHT result\n");
838 //FIXME check expiration?
840 rh = (struct ResolverHandle *)cls;
841 nrb = (struct GNSNameRecordBlock*)data;
843 /* stop dht lookup and timeout task */
844 GNUNET_DHT_get_stop (rh->get_handle);
845 GNUNET_SCHEDULER_cancel(rh->dht_timeout_task);
847 rh->get_handle = NULL;
848 num_records = ntohl(nrb->rd_count);
849 name = (char*)&nrb[1];
851 struct GNUNET_NAMESTORE_RecordData rd[num_records];
853 rd_data += strlen(name) + 1 + sizeof(struct GNSNameRecordBlock);
854 rd_size = size - strlen(name) - 1 - sizeof(struct GNSNameRecordBlock);
856 if (GNUNET_SYSERR == GNUNET_NAMESTORE_records_deserialize (rd_size,
861 GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Error deserializing data!\n");
865 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
866 "Got name: %s (wanted %s)\n", name, rh->authority_name);
867 for (i=0; i<num_records; i++)
870 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
871 "Got name: %s (wanted %s)\n", name, rh->authority_name);
872 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
873 "Got type: %d (wanted %d)\n",
874 rd[i].record_type, GNUNET_GNS_RECORD_PKEY);
875 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
876 "Got data length: %d\n", rd[i].data_size);
877 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
878 "Got flag %d\n", rd[i].flags);
880 if ((strcmp(name, rh->authority_name) == 0) &&
881 (rd[i].record_type == GNUNET_GNS_RECORD_PKEY))
883 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Authority found in DHT\n");
885 memcpy(&rh->authority, rd[i].data, sizeof(GNUNET_HashCode));
886 struct AuthorityChain *auth =
887 GNUNET_malloc(sizeof(struct AuthorityChain));
888 auth->zone = rh->authority;
889 auth->name = GNUNET_malloc(strlen(rh->authority_name)+1);
890 memset(auth->name, 0, strlen(rh->authority_name)+1);
891 strcpy(auth->name, rh->authority_name);
892 GNUNET_CONTAINER_DLL_insert (rh->authority_chain_head,
893 rh->authority_chain_tail,
896 /** call process new authority */
898 process_discovered_authority(name, auth->zone,
899 rh->authority_chain_tail->zone,
906 GNUNET_CRYPTO_hash(name, strlen(name), &name_hash);
907 GNUNET_CRYPTO_hash_xor(key, &name_hash, &zone);
909 /* Save to namestore */
910 if (0 != GNUNET_CRYPTO_hash_cmp(&rh->authority_chain_tail->zone, &zone))
912 GNUNET_NAMESTORE_record_put (namestore_handle,
919 &on_namestore_record_put_result, //cont
929 * FIXME in this case. should we ask namestore again?
931 if (strcmp(rh->name, "") == 0)
932 rh->proc(rh->proc_cls, rh, 0, NULL);
934 resolve_delegation_dht(rh);
939 * No pkey but name exists
941 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "DHT authority lookup found no match!\n");
942 rh->proc(rh->proc_cls, rh, 0, NULL);
947 * Process DHT lookup result for record.
949 * @param cls the closure
950 * @param rh resolver handle
951 * @param rd_count number of results
952 * @param rd record data
955 handle_record_dht(void* cls, struct ResolverHandle *rh,
956 unsigned int rd_count,
957 const struct GNUNET_NAMESTORE_RecordData *rd)
959 struct RecordLookupHandle* rlh;
960 rlh = (struct RecordLookupHandle*)cls;
963 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
964 "No records for %s found in DHT. Aborting\n",
966 /* give up, cannot resolve */
967 rlh->proc(rlh->proc_cls, 0, NULL);
968 GNUNET_free(rlh->name);
970 free_resolver_handle(rh);
974 /* results found yay */
975 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
976 "Record resolved from DHT!");
977 rlh->proc(rlh->proc_cls, rd_count, rd);
978 GNUNET_free(rlh->name);
980 free_resolver_handle(rh);
986 * Process namestore lookup result for record.
988 * @param cls the closure
989 * @param rh resolver handle
990 * @param rd_count number of results
991 * @param rd record data
994 handle_record_ns(void* cls, struct ResolverHandle *rh,
995 unsigned int rd_count,
996 const struct GNUNET_NAMESTORE_RecordData *rd)
998 struct RecordLookupHandle* rlh;
999 rlh = (struct RecordLookupHandle*) cls;
1002 /* ns entry expired and not ours. try dht */
1003 if (rh->status & (EXPIRED | !EXISTS) &&
1004 GNUNET_CRYPTO_hash_cmp(&rh->authority_chain_head->zone,
1005 &rh->authority_chain_tail->zone))
1007 rh->proc = &handle_record_dht;
1008 resolve_record_dht(rh);
1011 /* give up, cannot resolve */
1012 rlh->proc(rlh->proc_cls, 0, NULL);
1013 GNUNET_free(rlh->name);
1015 free_resolver_handle(rh);
1019 /* results found yay */
1020 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1021 "Record resolved from namestore!");
1022 rlh->proc(rlh->proc_cls, rd_count, rd);
1023 GNUNET_free(rlh->name);
1025 free_resolver_handle(rh);
1031 * Determine if this name is canonical.
1033 * a.b.gnunet = not canonical
1036 * @param name the name to test
1037 * @return 1 if canonical
1040 is_canonical(char* name)
1042 uint32_t len = strlen(name);
1045 for (i=0; i<len; i++)
1047 if (*(name+i) == '.')
1054 * Move one level up in the domain hierarchy and return the
1055 * passed top level domain.
1057 * @param name the domain
1058 * @param dest the destination where the tld will be put
1061 pop_tld(char* name, char* dest)
1065 if (is_canonical(name))
1072 for (len = strlen(name); len > 0; len--)
1074 if (*(name+len) == '.')
1084 strcpy(dest, (name+len+1));
1088 * DHT resolution for delegation finished. Processing result.
1090 * @param cls the closure
1091 * @param rh resolver handle
1092 * @param rd_count number of results (always 0)
1093 * @param rd record data (always NULL)
1096 handle_delegation_dht(void* cls, struct ResolverHandle *rh,
1097 unsigned int rd_count,
1098 const struct GNUNET_NAMESTORE_RecordData *rd)
1100 struct RecordLookupHandle* rlh;
1101 rlh = (struct RecordLookupHandle*) cls;
1103 if (strcmp(rh->name, "") == 0)
1105 /* We resolved full name for delegation. resolving record */
1106 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1107 "Resolved full name for delegation via DHT. resolving record '' in ns\n");
1108 rh->proc = &handle_record_ns;
1109 resolve_record_ns(rh);
1114 * we still have some left
1116 if (is_canonical(rh->name))
1118 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1119 "Resolving canonical record %s in ns\n", rh->name);
1120 rh->proc = &handle_record_ns;
1121 resolve_record_ns(rh);
1124 /* give up, cannot resolve */
1125 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1126 "Cannot fully resolve delegation for %s via DHT!\n",
1128 rlh->proc(rlh->proc_cls, 0, NULL);
1129 GNUNET_free(rlh->name);
1131 free_resolver_handle(rh);
1136 * Start DHT lookup for a name -> PKEY (compare NS) record in
1137 * rh->authority's zone
1139 * @param rh the pending gns query
1142 resolve_delegation_dht(struct ResolverHandle *rh)
1145 GNUNET_HashCode name_hash;
1146 GNUNET_HashCode lookup_key;
1148 GNUNET_CRYPTO_hash(rh->authority_name,
1149 strlen(rh->authority_name),
1151 GNUNET_CRYPTO_hash_xor(&name_hash, &rh->authority, &lookup_key);
1153 rh->dht_timeout_task = GNUNET_SCHEDULER_add_delayed (DHT_LOOKUP_TIMEOUT,
1154 &dht_authority_lookup_timeout,
1157 xquery = htonl(GNUNET_GNS_RECORD_PKEY);
1159 rh->get_handle = GNUNET_DHT_get_start(dht_handle,
1160 DHT_OPERATION_TIMEOUT,
1161 GNUNET_BLOCK_TYPE_GNS_NAMERECORD,
1163 DHT_GNS_REPLICATION_LEVEL,
1167 &process_delegation_result_dht,
1174 * Namestore resolution for delegation finished. Processing result.
1176 * @param cls the closure
1177 * @param rh resolver handle
1178 * @param rd_count number of results (always 0)
1179 * @param rd record data (always NULL)
1182 handle_delegation_ns(void* cls, struct ResolverHandle *rh,
1183 unsigned int rd_count,
1184 const struct GNUNET_NAMESTORE_RecordData *rd)
1186 struct RecordLookupHandle* rlh;
1187 rlh = (struct RecordLookupHandle*) cls;
1189 if (strcmp(rh->name, "") == 0)
1191 /* We resolved full name for delegation. resolving record */
1192 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1193 "Resolved full name for delegation. resolving record ''\n");
1194 rh->proc = &handle_record_ns;
1195 resolve_record_ns(rh);
1200 * we still have some left
1201 * check if authority in ns is fresh
1203 * or we are authority
1205 if ((rh->status & (EXISTS | !EXPIRED)) ||
1206 !GNUNET_CRYPTO_hash_cmp(&rh->authority_chain_head->zone,
1207 &rh->authority_chain_tail->zone))
1209 if (is_canonical(rh->name))
1211 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1212 "Resolving canonical record %s\n", rh->name);
1213 rh->proc = &handle_record_ns;
1214 resolve_record_ns(rh);
1218 /* give up, cannot resolve */
1219 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1220 "Cannot fully resolve delegation for %s!\n",
1222 rlh->proc(rlh->proc_cls, 0, NULL);
1227 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1228 "Trying to resolve delegation for %s via DHT\n",
1230 rh->proc = &handle_delegation_dht;
1231 resolve_delegation_dht(rh);
1235 static void resolve_delegation_ns(struct ResolverHandle *rh);
1239 * This is a callback function that should give us only PKEY
1240 * records. Used to query the namestore for the authority (PKEY)
1241 * for 'name'. It will recursively try to resolve the
1242 * authority for a given name from the namestore.
1244 * @param cls the pending query
1245 * @param key the key of the zone we did the lookup
1246 * @param expiration expiration date of the record data set in the namestore
1247 * @param name the name for which we need an authority
1248 * @param rd_count the number of records with 'name'
1249 * @param rd the record data
1250 * @param signature the signature of the authority for the record data
1253 process_delegation_result_ns(void* cls,
1254 const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *key,
1255 struct GNUNET_TIME_Absolute expiration,
1257 unsigned int rd_count,
1258 const struct GNUNET_NAMESTORE_RecordData *rd,
1259 const struct GNUNET_CRYPTO_RsaSignature *signature)
1261 struct ResolverHandle *rh;
1262 struct GNUNET_TIME_Relative remaining_time;
1263 GNUNET_HashCode zone;
1266 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Got %d records from authority lookup\n",
1269 rh = (struct ResolverHandle *)cls;
1270 GNUNET_CRYPTO_hash(key,
1271 sizeof(struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded),
1273 remaining_time = GNUNET_TIME_absolute_get_remaining (expiration);
1279 rh->status |= EXISTS;
1282 if (remaining_time.rel_value == 0)
1284 rh->status |= EXPIRED;
1288 * No authority found in namestore.
1293 * We did not find an authority in the namestore
1298 * Promote this authority back to a name maybe it is
1301 if (strcmp(rh->name, "") == 0)
1303 /* simply promote back */
1304 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1305 "Promoting %s back to name\n", rh->authority_name);
1306 strcpy(rh->name, rh->authority_name);
1310 /* add back to existing name */
1311 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1312 "Adding %s back to %s\n",
1313 rh->authority_name, rh->name);
1314 new_name = GNUNET_malloc(strlen(rh->name)
1315 + strlen(rh->authority_name) + 2);
1316 memset(new_name, 0, strlen(rh->name) + strlen(rh->authority_name) + 2);
1317 strcpy(new_name, rh->name);
1318 strcpy(new_name+strlen(new_name)+1, ".");
1319 strcpy(new_name+strlen(new_name)+2, rh->authority_name);
1320 GNUNET_free(rh->name);
1321 rh->name = new_name;
1323 rh->proc(rh->proc_cls, rh, 0, NULL);
1328 * We found an authority that may be able to help us
1329 * move on with query
1330 * Note only 1 pkey should have been returned.. anything else would be strange
1333 for (i=0; i<rd_count;i++)
1336 if (rd[i].record_type != GNUNET_GNS_RECORD_PKEY)
1339 if ((GNUNET_TIME_absolute_get_remaining (rd[i].expiration)).rel_value
1342 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "This pkey is expired.\n");
1343 if (remaining_time.rel_value == 0)
1345 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1346 "This dht entry is expired.\n");
1347 rh->authority_chain_head->fresh = 0;
1348 rh->proc(rh->proc_cls, rh, 0, NULL);
1356 * Resolve rest of query with new authority
1358 GNUNET_assert(rd[i].record_type == GNUNET_GNS_RECORD_PKEY);
1359 memcpy(&rh->authority, rd[i].data, sizeof(GNUNET_HashCode));
1360 struct AuthorityChain *auth = GNUNET_malloc(sizeof(struct AuthorityChain));
1361 auth->zone = rh->authority;
1362 auth->name = GNUNET_malloc(strlen(rh->authority_name)+1);
1363 memset(auth->name, 0, strlen(rh->authority_name)+1);
1364 strcpy(auth->name, rh->authority_name);
1365 GNUNET_CONTAINER_DLL_insert (rh->authority_chain_head,
1366 rh->authority_chain_tail,
1370 * We are done with PKEY resolution if name is empty
1371 * else resolve again with new authority
1373 if (strcmp(rh->name, "") == 0)
1374 rh->proc(rh->proc_cls, rh, 0, NULL);
1376 resolve_delegation_ns(rh);
1383 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1384 "Authority lookup successful but no PKEY... never get here\n");
1385 rh->proc(rh->proc_cls, rh, 0, NULL);
1390 * Resolve the delegation chain for the request in our namestore
1392 * @param rh the resolver handle
1395 resolve_delegation_ns(struct ResolverHandle *rh)
1397 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1398 "Resolving delegation for %s\n", rh->name);
1399 pop_tld(rh->name, rh->authority_name);
1400 GNUNET_NAMESTORE_lookup_record(namestore_handle,
1403 GNUNET_GNS_RECORD_PKEY,
1404 &process_delegation_result_ns,
1411 * Lookup of a record in a specific zone
1412 * calls lookup result processor on result
1414 * @param zone the root zone
1415 * @param record_type the record type to look up
1416 * @param name the name to look up
1417 * @param proc the processor to call on result
1418 * @param cls the closure to pass to proc
1421 gns_resolver_lookup_record(GNUNET_HashCode zone,
1422 uint32_t record_type,
1424 struct GNUNET_CRYPTO_RsaPrivateKey *key,
1425 RecordLookupProcessor proc,
1428 struct ResolverHandle *rh;
1429 struct RecordLookupHandle* rlh;
1431 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1432 "Starting resolution for %s (type=%d)!\n",
1436 if (is_canonical((char*)name) && (strcmp(GNUNET_GNS_TLD, name) != 0))
1438 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1439 "%s is canonical and gnunet not our TLD!\n", name);
1444 rlh = GNUNET_malloc(sizeof(struct RecordLookupHandle));
1445 rh = GNUNET_malloc(sizeof (struct ResolverHandle));
1447 rh->authority = zone;
1451 if (strcmp(GNUNET_GNS_TLD, name) == 0)
1453 rh->name = GNUNET_malloc(2);
1454 strcpy(rh->name, "");
1458 rh->name = GNUNET_malloc(strlen(name)
1459 - strlen(GNUNET_GNS_TLD));
1461 strlen(name)-strlen(GNUNET_GNS_TLD));
1462 memcpy(rh->name, name,
1463 strlen(name)-strlen(GNUNET_GNS_TLD) - 1);
1466 rh->authority_name = GNUNET_malloc(sizeof(char)*MAX_DNS_LABEL_LENGTH);
1467 rh->authority_chain_head = GNUNET_malloc(sizeof(struct AuthorityChain));
1468 rh->authority_chain_head->prev = NULL;
1469 rh->authority_chain_head->next = NULL;
1470 rh->authority_chain_tail = rh->authority_chain_head;
1471 rh->authority_chain_head->zone = zone;
1473 rlh->record_type = record_type;
1474 rlh->name = GNUNET_malloc(strlen(name) + 1);
1475 memset(rlh->name, 0, strlen(name) + 1);
1476 strcpy(rlh->name, name); //FIXME
1478 rlh->proc_cls = cls;
1480 rh->proc = &handle_delegation_ns;
1481 resolve_delegation_ns(rh);
1484 /******** END Record Resolver ***********/
1488 * Callback calles by namestore for a zone to name
1491 * @param cls the closure
1492 * @param zone_key the zone we queried
1493 * @param expire the expiration time of the name
1494 * @param name the name found or NULL
1495 * @param rd_len number of records for the name
1496 * @param rd the record data (PKEY) for the name
1497 * @param signature the signature for the record data
1500 process_zone_to_name_shorten(void *cls,
1501 const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *zone_key,
1502 struct GNUNET_TIME_Absolute expire,
1504 unsigned int rd_len,
1505 const struct GNUNET_NAMESTORE_RecordData *rd,
1506 const struct GNUNET_CRYPTO_RsaSignature *signature)
1508 struct ResolverHandle *rh = (struct ResolverHandle *)cls;
1509 struct NameShortenHandle* nsh = (struct NameShortenHandle*)rh->proc_cls;
1510 struct AuthorityChain *next_authority;
1513 char* next_authority_name;
1516 /* we found a match in our own zone */
1519 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1520 "result strlen %d\n", strlen(name));
1521 answer_len = strlen(rh->name) + strlen(name) + strlen(GNUNET_GNS_TLD) + 3;
1522 result = GNUNET_malloc(answer_len);
1523 memset(result, 0, answer_len);
1524 if (strlen(rh->name) > 0)
1526 strcpy(result, rh->name);
1527 strcpy(result+strlen(rh->name), ".");
1530 strcpy(result+strlen(result), name);
1531 strcpy(result+strlen(result), ".");
1532 strcpy(result+strlen(result), GNUNET_GNS_TLD);
1534 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1535 "Sending shorten result %s\n", result);
1537 nsh->proc(nsh->proc_cls, result);
1539 free_resolver_handle(rh);
1540 GNUNET_free(result);
1542 else if (GNUNET_CRYPTO_hash_cmp(&rh->authority_chain_head->zone,
1543 &rh->authority_chain_tail->zone))
1545 /* our zone, just append .gnunet */
1546 answer_len = strlen(rh->name) + strlen(GNUNET_GNS_TLD) + 2;
1547 result = GNUNET_malloc(answer_len);
1548 memset(result, 0, answer_len);
1549 strcpy(result, rh->name);
1550 strcpy(result+strlen(rh->name), ".");
1551 strcpy(result+strlen(rh->name)+1, GNUNET_GNS_TLD);
1553 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1554 "Our zone: Sending name as shorten result %s\n", rh->name);
1556 nsh->proc(nsh->proc_cls, result);
1558 free_resolver_handle(rh);
1559 GNUNET_free(result);
1565 * continue with next authority
1567 next_authority = rh->authority_chain_head;
1568 next_authority_name = GNUNET_malloc(strlen(rh->name)+
1569 strlen(next_authority->name) + 2);
1570 memset(next_authority_name, 0, strlen(rh->name)+
1571 strlen(next_authority->name) + 2);
1572 strcpy(next_authority_name, rh->name);
1573 strcpy(next_authority_name+strlen(rh->name)+1, ".");
1574 strcpy(next_authority_name+strlen(rh->name)+2, next_authority->name);
1576 GNUNET_free(rh->name);
1577 rh->name = next_authority_name;
1578 GNUNET_CONTAINER_DLL_remove(rh->authority_chain_head,
1579 rh->authority_chain_tail,
1582 GNUNET_NAMESTORE_zone_to_name (namestore_handle,
1583 &rh->authority_chain_tail->zone,
1584 &rh->authority_chain_head->zone,
1585 &process_zone_to_name_shorten,
1592 * Process result from namestore delegation lookup
1593 * for shorten operation
1595 * @param cls the client shorten handle
1596 * @param rh the resolver handle
1597 * @param rd_count number of results (0)
1598 * @param rd data (NULL)
1601 handle_delegation_ns_shorten(void* cls,
1602 struct ResolverHandle *rh,
1604 const struct GNUNET_NAMESTORE_RecordData *rd)
1606 struct NameShortenHandle *nsh;
1610 nsh = (struct NameShortenHandle *)cls;
1613 * At this point rh->name contains the part of the name
1614 * that we do not have a PKEY in our namestore to resolve.
1615 * The authority chain in the resolver handle is now
1616 * useful to backtrack if needed
1619 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1620 "PKEY resolved as far as possible in ns up to %s!\n", rh->name);
1622 if (GNUNET_CRYPTO_hash_cmp(&rh->authority_chain_head->zone,
1623 &rh->authority_chain_tail->zone) == 0)
1626 * This is our zone append .gnunet unless name is empty
1627 * (it shouldn't be, usually FIXME what happens if we
1628 * shorten to our zone to a "" record??)
1631 answer_len = strlen(rh->name) + strlen(GNUNET_GNS_TLD) + 2;
1632 result = GNUNET_malloc(answer_len);
1633 memset(result, 0, answer_len);
1634 strcpy(result, rh->name);
1635 strcpy(result+strlen(rh->name), ".");
1636 strcpy(result+strlen(rh->name)+1, GNUNET_GNS_TLD);
1638 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1639 "Our zone: Sending name as shorten result %s\n", rh->name);
1641 nsh->proc(nsh->proc_cls, result);
1643 free_resolver_handle(rh);
1644 GNUNET_free(result);
1648 /* backtrack authorities for names */
1649 GNUNET_NAMESTORE_zone_to_name (namestore_handle,
1650 &rh->authority_chain_tail->zone, //ours
1651 &rh->authority_chain_head->zone,
1652 &process_zone_to_name_shorten,
1658 * Shorten api from resolver
1660 * @param zone the zone to use
1661 * @param name the name to shorten
1662 * @param proc the processor to call with result
1663 * @param cls closure to pass to proc
1666 gns_resolver_shorten_name(GNUNET_HashCode zone,
1668 ShortenResultProcessor proc,
1671 struct ResolverHandle *rh;
1672 struct NameShortenHandle *nsh;
1674 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1675 "Starting shorten for %s!\n", name);
1677 if (is_canonical((char*)name))
1679 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1680 "%s is canonical. Returning verbatim\n", name);
1685 nsh = GNUNET_malloc(sizeof (struct NameShortenHandle));
1689 nsh->proc_cls = cls;
1691 rh = GNUNET_malloc(sizeof (struct ResolverHandle));
1692 rh->authority = zone;
1693 rh->name = GNUNET_malloc(strlen(name)
1694 - strlen(GNUNET_GNS_TLD));
1696 strlen(name)-strlen(GNUNET_GNS_TLD));
1697 memcpy(rh->name, name,
1698 strlen(name)-strlen(GNUNET_GNS_TLD)-1);
1700 rh->authority_name = GNUNET_malloc(sizeof(char)*MAX_DNS_LABEL_LENGTH);
1701 rh->authority_chain_head = GNUNET_malloc(sizeof(struct AuthorityChain));
1702 rh->authority_chain_tail = rh->authority_chain_head;
1703 rh->authority_chain_head->zone = zone;
1704 rh->proc = &handle_delegation_ns_shorten;
1707 /* Start delegation resolution in our namestore */
1708 resolve_delegation_ns(rh);
1711 /*********** END NAME SHORTEN ********************/
1715 * Process result from namestore delegation lookup
1716 * for get authority operation
1718 * @param cls the client get auth handle
1719 * @param rh the resolver handle
1720 * @param rd_count number of results (0)
1721 * @param rd data (NULL)
1724 handle_delegation_result_ns_get_auth(void* cls,
1725 struct ResolverHandle *rh,
1727 const struct GNUNET_NAMESTORE_RecordData *rd)
1729 struct GetNameAuthorityHandle* nah;
1733 nah = (struct GetNameAuthorityHandle*) rh->proc_cls;
1736 * At this point rh->name contains the part of the name
1737 * that we do not have a PKEY in our namestore to resolve.
1738 * The authority chain in the resolver handle is now
1739 * useful to backtrack if needed
1742 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1743 "PKEY resolved as far as possible in ns up to %s!\n", rh->name);
1745 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1746 "Building response!\n");
1747 if (is_canonical(rh->name))
1750 * We successfully resolved the authority in the ns
1751 * FIXME for our purposes this is fine
1752 * but maybe we want to have an api that also looks
1753 * into the dht (i.e. option in message)
1755 if (strlen(rh->name) > strlen(nah->name))
1757 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1758 "Record name longer than original lookup name... odd!\n");
1762 answer_len = strlen(nah->name) - strlen(rh->name)
1763 + strlen(GNUNET_GNS_TLD) + 1;
1764 result = GNUNET_malloc(answer_len);
1765 memset(result, 0, answer_len);
1766 strcpy(result, nah->name + strlen(rh->name) + 1);
1768 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1769 "Got authority result %s\n", result);
1771 nah->proc(nah->proc_cls, result);
1772 GNUNET_free(nah->name);
1774 free_resolver_handle(rh);
1775 GNUNET_free(result);
1779 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1780 "Unable to resolve authority for remaining %s!\n", rh->name);
1781 nah->proc(nah->proc_cls, "");
1782 GNUNET_free(nah->name);
1784 free_resolver_handle(rh);
1792 * Tries to resolve the authority for name
1795 * @param zone the root zone to look up for
1796 * @param name the name to lookup up
1797 * @param proc the processor to call when finished
1798 * @param cls the closure to pass to the processor
1801 gns_resolver_get_authority(GNUNET_HashCode zone,
1803 GetAuthorityResultProcessor proc,
1806 struct ResolverHandle *rh;
1807 struct GetNameAuthorityHandle *nah;
1809 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1810 "Starting authority resolution for %s!\n", name);
1812 nah = GNUNET_malloc(sizeof (struct GetNameAuthorityHandle));
1813 rh = GNUNET_malloc(sizeof (struct ResolverHandle));
1814 rh->authority = zone;
1816 if (strcmp(GNUNET_GNS_TLD, name) == 0)
1818 rh->name = GNUNET_malloc(2);
1819 strcpy(rh->name, "");
1823 rh->name = GNUNET_malloc(strlen(name)
1824 - strlen(GNUNET_GNS_TLD));
1826 strlen(name)-strlen(GNUNET_GNS_TLD));
1827 memcpy(rh->name, name,
1828 strlen(name)-strlen(GNUNET_GNS_TLD) - 1);
1831 nah->name = GNUNET_malloc(strlen(name)+1);
1832 memset(nah->name, 0,
1834 strcpy(nah->name, name);
1836 rh->authority_name = GNUNET_malloc(MAX_DNS_LABEL_LENGTH);
1838 rh->authority_chain_head = GNUNET_malloc(sizeof(struct AuthorityChain));
1839 rh->authority_chain_tail = rh->authority_chain_head;
1840 rh->authority_chain_head->zone = zone;
1841 rh->proc = &handle_delegation_result_ns_get_auth;
1842 rh->proc_cls = (void*)nah;
1845 nah->proc_cls = cls;
1847 /* Start delegation resolution in our namestore */
1848 resolve_delegation_ns(rh);
1852 /******** END GET AUTHORITY *************/
1854 /* end of gnunet-service-gns_resolver.c */