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);
92 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
93 "Trying delegated name %s\n", gph->name);
94 memcpy(gph->new_name, gph->name, strlen(gph->name)+1);
95 GNUNET_NAMESTORE_lookup_record(namestore_handle,
98 GNUNET_GNS_RECORD_PSEU,
99 &process_pseu_lookup_ns,
105 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
106 "Name %s not taken in NS! Adding\n", gph->new_name);
108 new_pkey.expiration = GNUNET_TIME_absolute_get_forever ();
109 new_pkey.data_size = sizeof(GNUNET_HashCode);
110 new_pkey.data = &gph->new_zone;
111 new_pkey.record_type = GNUNET_GNS_RECORD_PKEY;
112 GNUNET_NAMESTORE_record_create (namestore_handle,
123 * process result of a dht pseu lookup
125 * @param gph the handle
126 * @param name the pseu result or NULL
129 process_pseu_result(struct GetPseuAuthorityHandle* gph, char* name)
133 memcpy(gph->new_name, name, strlen(gph->name)+1);
137 memcpy(gph->new_name, name, strlen(name)+1);
140 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
141 "Checking %s for collision in NS\n", gph->new_name);
144 * Check for collision
146 GNUNET_NAMESTORE_lookup_record(namestore_handle,
149 GNUNET_GNS_RECORD_PSEU,
150 &process_pseu_lookup_ns,
155 * Handle timeout for dht request
157 * @param cls the request handle as closure
158 * @param tc the task context
161 handle_auth_discovery_timeout(void *cls,
162 const struct GNUNET_SCHEDULER_TaskContext *tc)
164 struct GetPseuAuthorityHandle* gph = (struct GetPseuAuthorityHandle*)cls;
166 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
167 "dht lookup for query PSEU timed out.\n");
168 GNUNET_DHT_get_stop (gph->get_handle);
169 process_pseu_result(gph, NULL);
173 * Function called when we find a PSEU entry in the DHT
175 * @param cls the request handle
176 * @param exp lifetime
177 * @param key the key the record was stored under
178 * @param get_path get path
179 * @param get_path_length get path length
180 * @param put_path put path
181 * @param put_path_length put path length
182 * @param type the block type
183 * @param size the size of the record
184 * @param data the record data
187 process_auth_discovery_dht_result(void* cls,
188 struct GNUNET_TIME_Absolute exp,
189 const GNUNET_HashCode * key,
190 const struct GNUNET_PeerIdentity *get_path,
191 unsigned int get_path_length,
192 const struct GNUNET_PeerIdentity *put_path,
193 unsigned int put_path_length,
194 enum GNUNET_BLOCK_Type type,
195 size_t size, const void *data)
197 struct GetPseuAuthorityHandle* gph = (struct GetPseuAuthorityHandle*)cls;
198 struct GNSNameRecordBlock *nrb;
199 char* rd_data = (char*)data;
205 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "got dht result (size=%d)\n", size);
209 GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "got dht result null!\n", size);
215 nrb = (struct GNSNameRecordBlock*)data;
217 /* stop lookup and timeout task */
218 GNUNET_DHT_get_stop (gph->get_handle);
219 GNUNET_SCHEDULER_cancel(gph->dht_timeout);
221 gph->get_handle = NULL;
223 nrb = (struct GNSNameRecordBlock*)data;
225 name = (char*)&nrb[1];
226 num_records = ntohl(nrb->rd_count);
228 struct GNUNET_NAMESTORE_RecordData rd[num_records];
230 rd_data += strlen(name) + 1 + sizeof(struct GNSNameRecordBlock);
231 rd_size = size - strlen(name) - 1 - sizeof(struct GNSNameRecordBlock);
233 if (GNUNET_SYSERR == GNUNET_NAMESTORE_records_deserialize (rd_size,
238 GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Error deserializing data!\n");
244 for (i=0; i<num_records; i++)
246 if ((strcmp(name, "+") == 0) &&
247 (rd[i].record_type == GNUNET_GNS_RECORD_PSEU))
250 process_pseu_result(gph, (char*)rd[i].data);
256 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "no pseu in dht!\n");
257 process_pseu_result(gph, NULL);
261 * Callback called by namestore for a zone to name
264 * @param cls the closure
265 * @param zone_key the zone we queried
266 * @param expire the expiration time of the name
267 * @param name the name found or NULL
268 * @param rd_len number of records for the name
269 * @param rd the record data (PKEY) for the name
270 * @param signature the signature for the record data
273 process_zone_to_name_discover(void *cls,
274 const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *zone_key,
275 struct GNUNET_TIME_Absolute expire,
278 const struct GNUNET_NAMESTORE_RecordData *rd,
279 const struct GNUNET_CRYPTO_RsaSignature *signature)
281 struct GetPseuAuthorityHandle* gph = (struct GetPseuAuthorityHandle*)cls;
283 /* we found a match in our own zone */
286 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
287 "name for zone in our root %d\n", strlen(name));
297 GNUNET_HashCode name_hash;
298 GNUNET_HashCode lookup_key;
299 struct GNUNET_CRYPTO_HashAsciiEncoded lookup_key_string;
301 GNUNET_CRYPTO_hash("+", strlen("+"), &name_hash);
302 GNUNET_CRYPTO_hash_xor(&name_hash, &gph->new_zone, &lookup_key);
303 GNUNET_CRYPTO_hash_to_enc (&lookup_key, &lookup_key_string);
305 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
306 "starting dht lookup for %s with key: %s\n",
307 "+", (char*)&lookup_key_string);
309 gph->dht_timeout = GNUNET_SCHEDULER_add_delayed(DHT_LOOKUP_TIMEOUT,
310 &handle_auth_discovery_timeout, gph);
312 xquery = htonl(GNUNET_GNS_RECORD_PSEU);
314 gph->get_handle = GNUNET_DHT_get_start(dht_handle,
315 DHT_OPERATION_TIMEOUT,
316 GNUNET_BLOCK_TYPE_GNS_NAMERECORD,
318 DHT_GNS_REPLICATION_LEVEL,
322 &process_auth_discovery_dht_result,
330 * Callback for new authories
332 * @param name the name given by delegation
333 * @param zone the authority
334 * @param the private key of our authority
336 static void process_discovered_authority(char* name, GNUNET_HashCode zone,
337 GNUNET_HashCode our_zone,
338 struct GNUNET_CRYPTO_RsaPrivateKey *key)
340 struct GetPseuAuthorityHandle *gph;
343 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "New authority %s discovered\n",
346 gph = GNUNET_malloc(sizeof(struct GetPseuAuthorityHandle));
347 namelen = strlen(name) + 1;
348 memcpy(gph->name, name, namelen);
350 gph->new_zone = zone;
351 gph->zone = our_zone;
354 GNUNET_NAMESTORE_zone_to_name (namestore_handle,
357 &process_zone_to_name_discover,
363 * Initialize the resolver
365 * @param nh the namestore handle
366 * @param dh the dht handle
367 * @return GNUNET_OK on success
370 gns_resolver_init(struct GNUNET_NAMESTORE_Handle *nh,
371 struct GNUNET_DHT_Handle *dh)
373 namestore_handle = nh;
375 if ((namestore_handle != NULL) && (dht_handle != NULL))
379 return GNUNET_SYSERR;
384 * Helper function to free resolver handle
386 * @rh the handle to free
389 free_resolver_handle(struct ResolverHandle* rh)
391 struct AuthorityChain *ac;
392 struct AuthorityChain *ac_next;
397 ac = rh->authority_chain_head;
410 * Callback when record data is put into namestore
412 * @param cls the closure
413 * @param success GNUNET_OK on success
414 * @param emsg the error message. NULL if SUCCESS==GNUNET_OK
417 on_namestore_record_put_result(void *cls,
421 if (GNUNET_NO == success)
423 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "records already in namestore\n");
426 else if (GNUNET_YES == success)
428 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
429 "records successfully put in namestore\n");
433 GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
434 "Error putting records into namestore: %s\n", emsg);
439 * Handle timeout for DHT requests
441 * @param cls the request handle as closure
442 * @param tc the task context
445 dht_lookup_timeout(void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
447 struct ResolverHandle *rh = cls;
449 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
450 "dht lookup for query %s timed out.\n",
453 GNUNET_DHT_get_stop (rh->get_handle);
454 rh->proc(rh->proc_cls, rh, 0, NULL);
459 * Function called when we get a result from the dht
460 * for our record query
462 * @param cls the request handle
463 * @param exp lifetime
464 * @param key the key the record was stored under
465 * @param get_path get path
466 * @param get_path_length get path length
467 * @param put_path put path
468 * @param put_path_length put path length
469 * @param type the block type
470 * @param size the size of the record
471 * @param data the record data
474 process_record_result_dht(void* cls,
475 struct GNUNET_TIME_Absolute exp,
476 const GNUNET_HashCode * key,
477 const struct GNUNET_PeerIdentity *get_path,
478 unsigned int get_path_length,
479 const struct GNUNET_PeerIdentity *put_path,
480 unsigned int put_path_length,
481 enum GNUNET_BLOCK_Type type,
482 size_t size, const void *data)
484 struct ResolverHandle *rh;
485 struct RecordLookupHandle *rlh;
486 struct GNSNameRecordBlock *nrb;
487 uint32_t num_records;
489 char* rd_data = (char*)data;
493 GNUNET_HashCode zone, name_hash;
494 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "got dht result (size=%d)\n", size);
499 //FIXME maybe check expiration here, check block type
501 rh = (struct ResolverHandle *)cls;
502 rlh = (struct RecordLookupHandle *) rh->proc_cls;
503 nrb = (struct GNSNameRecordBlock*)data;
505 /* stop lookup and timeout task */
506 GNUNET_DHT_get_stop (rh->get_handle);
507 GNUNET_SCHEDULER_cancel(rh->dht_timeout_task);
509 rh->get_handle = NULL;
510 name = (char*)&nrb[1];
511 num_records = ntohl(nrb->rd_count);
513 struct GNUNET_NAMESTORE_RecordData rd[num_records];
515 rd_data += strlen(name) + 1 + sizeof(struct GNSNameRecordBlock);
516 rd_size = size - strlen(name) - 1 - sizeof(struct GNSNameRecordBlock);
518 if (GNUNET_SYSERR == GNUNET_NAMESTORE_records_deserialize (rd_size,
523 GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Error deserializing data!\n");
527 for (i=0; i<num_records; i++)
529 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
530 "Got name: %s (wanted %s)\n", name, rh->name);
531 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
534 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
535 "Got data length: %d\n", rd[i].data_size);
536 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
537 "Got flag %d\n", rd[i].flags);
539 if ((strcmp(name, rh->name) == 0) &&
540 (rd[i].record_type == rlh->record_type))
547 GNUNET_CRYPTO_hash(name, strlen(name), &name_hash);
548 GNUNET_CRYPTO_hash_xor(key, &name_hash, &zone);
551 * FIXME check pubkey against existing key in namestore?
552 * https://gnunet.org/bugs/view.php?id=2179
555 /* Save to namestore */
556 GNUNET_NAMESTORE_record_put (namestore_handle,
563 &on_namestore_record_put_result, //cont
567 rh->proc(rh->proc_cls, rh, num_records, rd);
569 rh->proc(rh->proc_cls, rh, 0, NULL);
576 * Start DHT lookup for a (name -> query->record_type) record in
577 * rh->authority's zone
579 * @param rh the pending gns query context
582 resolve_record_dht(struct ResolverHandle *rh)
585 GNUNET_HashCode name_hash;
586 GNUNET_HashCode lookup_key;
587 struct GNUNET_CRYPTO_HashAsciiEncoded lookup_key_string;
588 struct RecordLookupHandle *rlh = (struct RecordLookupHandle *)rh->proc_cls;
590 GNUNET_CRYPTO_hash(rh->name, strlen(rh->name), &name_hash);
591 GNUNET_CRYPTO_hash_xor(&name_hash, &rh->authority, &lookup_key);
592 GNUNET_CRYPTO_hash_to_enc (&lookup_key, &lookup_key_string);
594 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
595 "starting dht lookup for %s with key: %s\n",
596 rh->name, (char*)&lookup_key_string);
598 rh->dht_timeout_task = GNUNET_SCHEDULER_add_delayed(DHT_LOOKUP_TIMEOUT,
599 &dht_lookup_timeout, rh);
601 xquery = htonl(rlh->record_type);
602 rh->get_handle = GNUNET_DHT_get_start(dht_handle,
603 DHT_OPERATION_TIMEOUT,
604 GNUNET_BLOCK_TYPE_GNS_NAMERECORD,
606 DHT_GNS_REPLICATION_LEVEL,
610 &process_record_result_dht,
617 * Namestore calls this function if we have record for this name.
618 * (or with rd_count=0 to indicate no matches)
620 * @param cls the pending query
621 * @param key the key of the zone we did the lookup
622 * @param expiration expiration date of the namestore entry
623 * @param name the name for which we need an authority
624 * @param rd_count the number of records with 'name'
625 * @param rd the record data
626 * @param signature the signature of the authority for the record data
629 process_record_result_ns(void* cls,
630 const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *key,
631 struct GNUNET_TIME_Absolute expiration,
632 const char *name, unsigned int rd_count,
633 const struct GNUNET_NAMESTORE_RecordData *rd,
634 const struct GNUNET_CRYPTO_RsaSignature *signature)
636 struct ResolverHandle *rh;
637 struct RecordLookupHandle *rlh;
638 struct GNUNET_TIME_Relative remaining_time;
639 GNUNET_HashCode zone;
641 rh = (struct ResolverHandle *) cls;
642 rlh = (struct RecordLookupHandle *)rh->proc_cls;
643 GNUNET_CRYPTO_hash(key,
644 sizeof(struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded),
646 remaining_time = GNUNET_TIME_absolute_get_remaining (expiration);
652 rh->status |= EXISTS;
655 if (remaining_time.rel_value == 0)
657 rh->status |= EXPIRED;
663 * Lookup terminated and no results
665 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
666 "Namestore lookup for %s terminated without results\n", name);
668 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
669 "Record %s unknown in namestore\n",
672 * Our zone and no result? Cannot resolve TT
674 rh->proc(rh->proc_cls, rh, 0, NULL);
681 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
682 "Processing additional result %s from namestore\n", name);
684 for (i=0; i<rd_count;i++)
687 if (rd[i].record_type != rlh->record_type)
690 if ((GNUNET_TIME_absolute_get_remaining (rd[i].expiration)).rel_value
693 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
694 "This record is expired. Skipping\n");
705 if (rh->answered == 0)
707 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
708 "No answers found. This is odd!\n");
709 rh->proc(rh->proc_cls, rh, 0, NULL);
713 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Found %d answer(s) to query!\n",
716 rh->proc(rh->proc_cls, rh, rd_count, rd);
722 * The final phase of resolution.
723 * rh->name is a name that is canonical and we do not have a delegation.
724 * Query namestore for this record
726 * @param rh the pending lookup
729 resolve_record_ns(struct ResolverHandle *rh)
731 struct RecordLookupHandle *rlh = (struct RecordLookupHandle *)rh->proc_cls;
734 * Try to resolve this record in our namestore.
735 * The name to resolve is now in rh->authority_name
736 * since we tried to resolve it to an authority
739 GNUNET_NAMESTORE_lookup_record(namestore_handle,
743 &process_record_result_ns,
749 * Handle timeout for DHT requests
751 * @param cls the request handle as closure
752 * @param tc the task context
755 dht_authority_lookup_timeout(void *cls,
756 const struct GNUNET_SCHEDULER_TaskContext *tc)
758 struct ResolverHandle *rh = cls;
760 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
761 "dht lookup for query %s timed out.\n",
764 GNUNET_DHT_get_stop (rh->get_handle);
765 if (strcmp(rh->name, "") == 0)
768 * promote authority back to name and try to resolve record
770 strcpy(rh->name, rh->authority_name);
772 rh->proc(rh->proc_cls, rh, 0, NULL);
776 static void resolve_delegation_dht(struct ResolverHandle *rh);
779 * Function called when we get a result from the dht
780 * for our query. Recursively tries to resolve authorities
783 * @param cls the request handle
784 * @param exp lifetime
785 * @param key the key the record was stored under
786 * @param get_path get path
787 * @param get_path_length get path length
788 * @param put_path put path
789 * @param put_path_length put path length
790 * @param type the block type
791 * @param size the size of the record
792 * @param data the record data
795 process_delegation_result_dht(void* cls,
796 struct GNUNET_TIME_Absolute exp,
797 const GNUNET_HashCode * key,
798 const struct GNUNET_PeerIdentity *get_path,
799 unsigned int get_path_length,
800 const struct GNUNET_PeerIdentity *put_path,
801 unsigned int put_path_length,
802 enum GNUNET_BLOCK_Type type,
803 size_t size, const void *data)
805 struct ResolverHandle *rh;
806 struct GNSNameRecordBlock *nrb;
807 uint32_t num_records;
809 char* rd_data = (char*) data;
812 GNUNET_HashCode zone, name_hash;
814 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Got DHT result\n");
819 //FIXME check expiration?
821 rh = (struct ResolverHandle *)cls;
822 nrb = (struct GNSNameRecordBlock*)data;
824 /* stop dht lookup and timeout task */
825 GNUNET_DHT_get_stop (rh->get_handle);
826 GNUNET_SCHEDULER_cancel(rh->dht_timeout_task);
828 rh->get_handle = NULL;
829 num_records = ntohl(nrb->rd_count);
830 name = (char*)&nrb[1];
832 struct GNUNET_NAMESTORE_RecordData rd[num_records];
834 rd_data += strlen(name) + 1 + sizeof(struct GNSNameRecordBlock);
835 rd_size = size - strlen(name) - 1 - sizeof(struct GNSNameRecordBlock);
837 if (GNUNET_SYSERR == GNUNET_NAMESTORE_records_deserialize (rd_size,
842 GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Error deserializing data!\n");
846 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
847 "Got name: %s (wanted %s)\n", name, rh->authority_name);
848 for (i=0; i<num_records; i++)
851 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
852 "Got name: %s (wanted %s)\n", name, rh->authority_name);
853 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
854 "Got type: %d (wanted %d)\n",
855 rd[i].record_type, GNUNET_GNS_RECORD_PKEY);
856 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
857 "Got data length: %d\n", rd[i].data_size);
858 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
859 "Got flag %d\n", rd[i].flags);
861 if ((strcmp(name, rh->authority_name) == 0) &&
862 (rd[i].record_type == GNUNET_GNS_RECORD_PKEY))
864 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Authority found in DHT\n");
866 memcpy(&rh->authority, rd[i].data, sizeof(GNUNET_HashCode));
867 struct AuthorityChain *auth =
868 GNUNET_malloc(sizeof(struct AuthorityChain));
869 auth->zone = rh->authority;
870 memset(auth->name, 0, strlen(rh->authority_name)+1);
871 strcpy(auth->name, rh->authority_name);
872 GNUNET_CONTAINER_DLL_insert (rh->authority_chain_head,
873 rh->authority_chain_tail,
876 /** call process new authority */
878 process_discovered_authority(name, auth->zone,
879 rh->authority_chain_tail->zone,
886 GNUNET_CRYPTO_hash(name, strlen(name), &name_hash);
887 GNUNET_CRYPTO_hash_xor(key, &name_hash, &zone);
889 /* Save to namestore */
890 if (0 != GNUNET_CRYPTO_hash_cmp(&rh->authority_chain_tail->zone, &zone))
892 GNUNET_NAMESTORE_record_put (namestore_handle,
899 &on_namestore_record_put_result, //cont
909 * FIXME in this case. should we ask namestore again?
911 if (strcmp(rh->name, "") == 0)
912 rh->proc(rh->proc_cls, rh, 0, NULL);
914 resolve_delegation_dht(rh);
919 * No pkey but name exists
921 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "DHT authority lookup found no match!\n");
922 rh->proc(rh->proc_cls, rh, 0, NULL);
929 finish_lookup(struct ResolverHandle *rh,
930 struct RecordLookupHandle* rlh,
931 unsigned int rd_count,
932 const struct GNUNET_NAMESTORE_RecordData *rd)
936 char new_s_value[256];
937 char new_mx_value[sizeof(struct GNUNET_DNSPARSER_MxRecord)+256];
939 struct GNUNET_NAMESTORE_RecordData p_rd[rd_count];
942 struct GNUNET_DNSPARSER_MxRecord *mx;
945 memcpy(p_rd, rd, rd_count*sizeof(struct GNUNET_NAMESTORE_RecordData));
947 for (i = 0; i < rd_count; i++)
950 if (rd[i].record_type != GNUNET_GNS_RECORD_TYPE_NS &&
951 rd[i].record_type != GNUNET_GNS_RECORD_TYPE_CNAME &&
952 rd[i].record_type != GNUNET_GNS_RECORD_MX)
954 p_rd[i].data = rd[i].data;
959 * for all those records we 'should'
960 * also try to resolve the A/AAAA records (RFC1035)
963 if (rd[i].record_type == GNUNET_GNS_RECORD_MX)
965 mx = (struct GNUNET_DNSPARSER_MxRecord*)rd[i].data;
966 s_value = (char*)&mx[1];
970 s_value = (char*)rd[i].data;
973 s_len = strlen(s_value)+1;
977 /* no postprocessing */
978 p_rd[i].data = rd[i].data;
982 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
983 "Postprocessing %s\n", s_value);
985 if (0 == strcmp(s_value+s_len-3, ".+"))
987 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
988 "Expanding .+ in %s\n", s_value);
989 if (strcmp(rh->name, "+") == 0)
995 trailer = rlh->name+strlen(rh->name)+1;
997 memset(new_s_value, 0, s_len+strlen(trailer)+strlen(GNUNET_GNS_TLD));
998 strcpy(new_s_value, s_value);
999 pos = new_s_value+s_len-2;
1000 strcpy(pos, trailer);
1001 pos += strlen(trailer);
1002 if (rd[i].record_type == GNUNET_GNS_RECORD_MX)
1005 p_rd[i].data_size = sizeof(struct GNUNET_DNSPARSER_MxRecord)
1006 +strlen(new_s_value)+1;
1008 p_rd[i].data = new_mx_value;
1009 mx = (struct GNUNET_DNSPARSER_MxRecord*)p_rd[i].data;
1011 ((struct GNUNET_DNSPARSER_MxRecord*)rd[i].data)->preference;
1012 memcpy((char*)&mx[1], new_s_value, strlen(new_s_value)+1);
1013 mx->mxhost = (char*)&mx[1];
1017 p_rd[i].data = new_s_value;
1018 p_rd[i].data_size = strlen(new_s_value)+1;
1020 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1021 "Expanded to %s\n", new_s_value);
1025 rlh->proc(rlh->proc_cls, rd_count, p_rd);
1031 * Process DHT lookup result for record.
1033 * @param cls the closure
1034 * @param rh resolver handle
1035 * @param rd_count number of results
1036 * @param rd record data
1039 handle_record_dht(void* cls, struct ResolverHandle *rh,
1040 unsigned int rd_count,
1041 const struct GNUNET_NAMESTORE_RecordData *rd)
1043 struct RecordLookupHandle* rlh;
1045 rlh = (struct RecordLookupHandle*)cls;
1048 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1049 "No records for %s found in DHT. Aborting\n",
1051 /* give up, cannot resolve */
1052 finish_lookup(rh, rlh, 0, NULL);
1053 free_resolver_handle(rh);
1057 /* results found yay */
1058 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1059 "Record resolved from DHT!");
1061 finish_lookup(rh, rlh, rd_count, rd);
1062 free_resolver_handle(rh);
1068 * Process namestore lookup result for record.
1070 * @param cls the closure
1071 * @param rh resolver handle
1072 * @param rd_count number of results
1073 * @param rd record data
1076 handle_record_ns(void* cls, struct ResolverHandle *rh,
1077 unsigned int rd_count,
1078 const struct GNUNET_NAMESTORE_RecordData *rd)
1080 struct RecordLookupHandle* rlh;
1081 rlh = (struct RecordLookupHandle*) cls;
1084 /* ns entry expired and not ours. try dht */
1085 if (rh->status & (EXPIRED | !EXISTS) &&
1086 GNUNET_CRYPTO_hash_cmp(&rh->authority_chain_head->zone,
1087 &rh->authority_chain_tail->zone))
1089 rh->proc = &handle_record_dht;
1090 resolve_record_dht(rh);
1093 /* give up, cannot resolve */
1094 finish_lookup(rh, rlh, 0, NULL);
1095 free_resolver_handle(rh);
1099 /* results found yay */
1100 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1101 "Record resolved from namestore!");
1103 finish_lookup(rh, rlh, rd_count, rd);
1104 free_resolver_handle(rh);
1110 * Determine if this name is canonical.
1112 * a.b.gnunet = not canonical
1115 * @param name the name to test
1116 * @return 1 if canonical
1119 is_canonical(char* name)
1121 uint32_t len = strlen(name);
1124 for (i=0; i<len; i++)
1126 if (*(name+i) == '.')
1133 * Move one level up in the domain hierarchy and return the
1134 * passed top level domain.
1136 * @param name the domain
1137 * @param dest the destination where the tld will be put
1140 pop_tld(char* name, char* dest)
1144 if (is_canonical(name))
1151 for (len = strlen(name); len > 0; len--)
1153 if (*(name+len) == '.')
1163 strcpy(dest, (name+len+1));
1167 * Checks if name is in .zkey TLD
1169 * @param name the name to check
1170 * @return GNUNET_YES or GNUNET_NO
1173 is_zkey_tld(const char* name)
1177 if (strlen(name) <= strlen(GNUNET_GNS_TLD_ZKEY))
1182 offset = strlen(name)-strlen(GNUNET_GNS_TLD_ZKEY);
1183 if (strcmp(name+offset, GNUNET_GNS_TLD_ZKEY) != 0)
1185 GNUNET_log(GNUNET_ERROR_TYPE_INFO,
1186 "%s is not in zkey TLD\n", name);
1193 * DHT resolution for delegation finished. Processing result.
1195 * @param cls the closure
1196 * @param rh resolver handle
1197 * @param rd_count number of results (always 0)
1198 * @param rd record data (always NULL)
1201 handle_delegation_dht(void* cls, struct ResolverHandle *rh,
1202 unsigned int rd_count,
1203 const struct GNUNET_NAMESTORE_RecordData *rd)
1205 struct RecordLookupHandle* rlh;
1206 rlh = (struct RecordLookupHandle*) cls;
1208 if (strcmp(rh->name, "") == 0)
1210 if ((rlh->record_type == GNUNET_GNS_RECORD_PKEY))
1212 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1213 "Resolved queried PKEY via DHT.\n");
1214 finish_lookup(rh, rlh, rd_count, rd);
1215 free_resolver_handle(rh);
1218 /* We resolved full name for delegation. resolving record */
1219 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1220 "Resolved full name for delegation via DHT. resolving record '' in ns\n");
1221 strcpy(rh->name, "+\0");
1222 rh->proc = &handle_record_ns;
1223 resolve_record_ns(rh);
1228 * we still have some left
1230 if (is_canonical(rh->name))
1232 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1233 "Resolving canonical record %s in ns\n", rh->name);
1234 rh->proc = &handle_record_ns;
1235 resolve_record_ns(rh);
1238 /* give up, cannot resolve */
1239 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1240 "Cannot fully resolve delegation for %s via DHT!\n",
1242 finish_lookup(rh, rlh, 0, NULL);
1243 free_resolver_handle(rh);
1248 * Start DHT lookup for a name -> PKEY (compare NS) record in
1249 * rh->authority's zone
1251 * @param rh the pending gns query
1254 resolve_delegation_dht(struct ResolverHandle *rh)
1257 GNUNET_HashCode name_hash;
1258 GNUNET_HashCode lookup_key;
1260 GNUNET_CRYPTO_hash(rh->authority_name,
1261 strlen(rh->authority_name),
1263 GNUNET_CRYPTO_hash_xor(&name_hash, &rh->authority, &lookup_key);
1265 rh->dht_timeout_task = GNUNET_SCHEDULER_add_delayed (DHT_LOOKUP_TIMEOUT,
1266 &dht_authority_lookup_timeout,
1269 xquery = htonl(GNUNET_GNS_RECORD_PKEY);
1271 rh->get_handle = GNUNET_DHT_get_start(dht_handle,
1272 DHT_OPERATION_TIMEOUT,
1273 GNUNET_BLOCK_TYPE_GNS_NAMERECORD,
1275 DHT_GNS_REPLICATION_LEVEL,
1279 &process_delegation_result_dht,
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)
1298 struct RecordLookupHandle* rlh;
1299 rlh = (struct RecordLookupHandle*) cls;
1301 if (strcmp(rh->name, "") == 0)
1303 if ((rlh->record_type == GNUNET_GNS_RECORD_PKEY))
1305 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1306 "Resolved queried PKEY in NS.\n");
1307 finish_lookup(rh, rlh, rd_count, rd);
1308 free_resolver_handle(rh);
1311 /* We resolved full name for delegation. resolving record */
1312 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1313 "Resolved full name for delegation. resolving record '+'\n");
1314 strcpy(rh->name, "+\0");
1315 rh->proc = &handle_record_ns;
1316 resolve_record_ns(rh);
1321 * we still have some left
1322 * check if authority in ns is fresh
1324 * or we are authority
1326 if ((rh->status & (EXISTS | !EXPIRED)) ||
1327 !GNUNET_CRYPTO_hash_cmp(&rh->authority_chain_head->zone,
1328 &rh->authority_chain_tail->zone))
1330 if (is_canonical(rh->name))
1332 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1333 "Resolving canonical record %s\n", rh->name);
1334 rh->proc = &handle_record_ns;
1335 resolve_record_ns(rh);
1339 /* give up, cannot resolve */
1340 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1341 "Cannot fully resolve delegation for %s!\n",
1343 rlh->proc(rlh->proc_cls, 0, NULL);
1348 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1349 "Trying to resolve delegation for %s via DHT\n",
1351 rh->proc = &handle_delegation_dht;
1352 resolve_delegation_dht(rh);
1356 static void resolve_delegation_ns(struct ResolverHandle *rh);
1360 * This is a callback function that should give us only PKEY
1361 * records. Used to query the namestore for the authority (PKEY)
1362 * for 'name'. It will recursively try to resolve the
1363 * authority for a given name from the namestore.
1365 * @param cls the pending query
1366 * @param key the key of the zone we did the lookup
1367 * @param expiration expiration date of the record data set in the namestore
1368 * @param name the name for which we need an authority
1369 * @param rd_count the number of records with 'name'
1370 * @param rd the record data
1371 * @param signature the signature of the authority for the record data
1374 process_delegation_result_ns(void* cls,
1375 const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *key,
1376 struct GNUNET_TIME_Absolute expiration,
1378 unsigned int rd_count,
1379 const struct GNUNET_NAMESTORE_RecordData *rd,
1380 const struct GNUNET_CRYPTO_RsaSignature *signature)
1382 struct ResolverHandle *rh;
1383 struct GNUNET_TIME_Relative remaining_time;
1384 GNUNET_HashCode zone;
1385 char new_name[MAX_DNS_NAME_LENGTH];
1387 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Got %d records from authority lookup\n",
1390 rh = (struct ResolverHandle *)cls;
1391 GNUNET_CRYPTO_hash(key,
1392 sizeof(struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded),
1394 remaining_time = GNUNET_TIME_absolute_get_remaining (expiration);
1400 rh->status |= EXISTS;
1403 if (remaining_time.rel_value == 0)
1405 rh->status |= EXPIRED;
1409 * No authority found in namestore.
1414 * We did not find an authority in the namestore
1419 * Promote this authority back to a name maybe it is
1422 if (strcmp(rh->name, "") == 0)
1424 /* simply promote back */
1425 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1426 "Promoting %s back to name\n", rh->authority_name);
1427 strcpy(rh->name, rh->authority_name);
1431 /* add back to existing name */
1432 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1433 "Adding %s back to %s\n",
1434 rh->authority_name, rh->name);
1435 memset(new_name, 0, strlen(rh->name) + strlen(rh->authority_name) + 2);
1436 strcpy(new_name, rh->name);
1437 strcpy(new_name+strlen(new_name)+1, ".");
1438 strcpy(new_name+strlen(new_name)+2, rh->authority_name);
1439 strcpy(rh->name, new_name);
1441 rh->proc(rh->proc_cls, rh, 0, NULL);
1446 * We found an authority that may be able to help us
1447 * move on with query
1448 * Note only 1 pkey should have been returned.. anything else would be strange
1451 for (i=0; i<rd_count;i++)
1454 if (rd[i].record_type != GNUNET_GNS_RECORD_PKEY)
1457 if ((GNUNET_TIME_absolute_get_remaining (rd[i].expiration)).rel_value
1460 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "This pkey is expired.\n");
1461 if (remaining_time.rel_value == 0)
1463 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1464 "This dht entry is expired.\n");
1465 rh->authority_chain_head->fresh = 0;
1466 rh->proc(rh->proc_cls, rh, 0, NULL);
1474 * Resolve rest of query with new authority
1476 GNUNET_assert(rd[i].record_type == GNUNET_GNS_RECORD_PKEY);
1477 memcpy(&rh->authority, rd[i].data, sizeof(GNUNET_HashCode));
1478 struct AuthorityChain *auth = GNUNET_malloc(sizeof(struct AuthorityChain));
1479 auth->zone = rh->authority;
1480 memset(auth->name, 0, strlen(rh->authority_name)+1);
1481 strcpy(auth->name, rh->authority_name);
1482 GNUNET_CONTAINER_DLL_insert (rh->authority_chain_head,
1483 rh->authority_chain_tail,
1487 * We are done with PKEY resolution if name is empty
1488 * else resolve again with new authority
1490 if (strcmp(rh->name, "") == 0)
1491 rh->proc(rh->proc_cls, rh, 0, NULL);
1493 resolve_delegation_ns(rh);
1500 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1501 "Authority lookup successful but no PKEY... never get here\n");
1502 rh->proc(rh->proc_cls, rh, 0, NULL);
1507 * Resolve the delegation chain for the request in our namestore
1509 * @param rh the resolver handle
1512 resolve_delegation_ns(struct ResolverHandle *rh)
1514 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1515 "Resolving delegation for %s\n", rh->name);
1516 pop_tld(rh->name, rh->authority_name);
1517 GNUNET_NAMESTORE_lookup_record(namestore_handle,
1520 GNUNET_GNS_RECORD_PKEY,
1521 &process_delegation_result_ns,
1528 * Lookup of a record in a specific zone
1529 * calls lookup result processor on result
1531 * @param zone the root zone
1532 * @param record_type the record type to look up
1533 * @param name the name to look up
1534 * @param proc the processor to call on result
1535 * @param cls the closure to pass to proc
1538 gns_resolver_lookup_record(GNUNET_HashCode zone,
1539 uint32_t record_type,
1541 struct GNUNET_CRYPTO_RsaPrivateKey *key,
1542 RecordLookupProcessor proc,
1545 struct ResolverHandle *rh;
1546 struct RecordLookupHandle* rlh;
1547 char string_hash[MAX_DNS_NAME_LENGTH]; //FIXME name len as soon as shorthash
1549 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1550 "Starting resolution for %s (type=%d)!\n",
1554 if (is_canonical((char*)name) && (strcmp(GNUNET_GNS_TLD, name) != 0))
1556 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1557 "%s is canonical and not gnunet -> cannot resolve!\n", name);
1562 rlh = GNUNET_malloc(sizeof(struct RecordLookupHandle));
1563 rh = GNUNET_malloc(sizeof (struct ResolverHandle));
1565 rh->authority = zone;
1569 if (strcmp(GNUNET_GNS_TLD, name) == 0)
1572 * Only 'gnunet' given
1574 strcpy(rh->name, "\0");
1578 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1579 "Checking for TLD...\n");
1580 if (is_zkey_tld(name) == GNUNET_YES)
1582 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1585 * This is a zkey tld
1586 * build hash and use as initial authority
1589 strlen(name)-strlen(GNUNET_GNS_TLD_ZKEY));
1590 memcpy(rh->name, name,
1591 strlen(name)-strlen(GNUNET_GNS_TLD_ZKEY) - 1);
1592 pop_tld(rh->name, string_hash);
1594 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1595 "ZKEY is %s!\n", string_hash);
1597 if (GNUNET_OK != GNUNET_CRYPTO_hash_from_string(string_hash,
1600 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1601 "Cannot convert ZKEY %s to hash!\n", string_hash);
1611 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1614 * Presumably GNUNET tld
1617 strlen(name)-strlen(GNUNET_GNS_TLD));
1618 memcpy(rh->name, name,
1619 strlen(name)-strlen(GNUNET_GNS_TLD) - 1);
1624 * Initialize authority chain
1626 rh->authority_chain_head = GNUNET_malloc(sizeof(struct AuthorityChain));
1627 rh->authority_chain_head->prev = NULL;
1628 rh->authority_chain_head->next = NULL;
1629 rh->authority_chain_tail = rh->authority_chain_head;
1630 rh->authority_chain_head->zone = rh->authority;
1633 * Copy original query into lookup handle
1635 rlh->record_type = record_type;
1636 memset(rlh->name, 0, strlen(name) + 1);
1637 strcpy(rlh->name, name);
1639 rlh->proc_cls = cls;
1641 rh->proc = &handle_delegation_ns;
1642 resolve_delegation_ns(rh);
1645 /******** END Record Resolver ***********/
1649 * Callback calles by namestore for a zone to name
1652 * @param cls the closure
1653 * @param zone_key the zone we queried
1654 * @param expire the expiration time of the name
1655 * @param name the name found or NULL
1656 * @param rd_len number of records for the name
1657 * @param rd the record data (PKEY) for the name
1658 * @param signature the signature for the record data
1661 process_zone_to_name_shorten(void *cls,
1662 const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *zone_key,
1663 struct GNUNET_TIME_Absolute expire,
1665 unsigned int rd_len,
1666 const struct GNUNET_NAMESTORE_RecordData *rd,
1667 const struct GNUNET_CRYPTO_RsaSignature *signature)
1669 struct ResolverHandle *rh = (struct ResolverHandle *)cls;
1670 struct NameShortenHandle* nsh = (struct NameShortenHandle*)rh->proc_cls;
1671 struct AuthorityChain *next_authority;
1673 char result[MAX_DNS_NAME_LENGTH];
1674 char next_authority_name[MAX_DNS_LABEL_LENGTH];
1677 /* we found a match in our own zone */
1680 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1681 "result strlen %d\n", strlen(name));
1682 answer_len = strlen(rh->name) + strlen(name) + strlen(GNUNET_GNS_TLD) + 3;
1683 memset(result, 0, answer_len);
1684 if (strlen(rh->name) > 0)
1686 strcpy(result, rh->name);
1687 strcpy(result+strlen(rh->name), ".");
1690 strcpy(result+strlen(result), name);
1691 strcpy(result+strlen(result), ".");
1692 strcpy(result+strlen(result), GNUNET_GNS_TLD);
1694 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1695 "Sending shorten result %s\n", result);
1697 nsh->proc(nsh->proc_cls, result);
1699 free_resolver_handle(rh);
1701 else if (GNUNET_CRYPTO_hash_cmp(&rh->authority_chain_head->zone,
1702 &rh->authority_chain_tail->zone))
1704 /* our zone, just append .gnunet */
1705 answer_len = strlen(rh->name) + strlen(GNUNET_GNS_TLD) + 2;
1706 memset(result, 0, answer_len);
1707 strcpy(result, rh->name);
1708 strcpy(result+strlen(rh->name), ".");
1709 strcpy(result+strlen(rh->name)+1, GNUNET_GNS_TLD);
1711 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1712 "Our zone: Sending name as shorten result %s\n", rh->name);
1714 nsh->proc(nsh->proc_cls, result);
1716 free_resolver_handle(rh);
1722 * continue with next authority
1724 next_authority = rh->authority_chain_head;
1725 // strlen(next_authority->name) + 2);
1726 memset(next_authority_name, 0, strlen(rh->name)+
1727 strlen(next_authority->name) + 2);
1728 strcpy(next_authority_name, rh->name);
1729 strcpy(next_authority_name+strlen(rh->name)+1, ".");
1730 strcpy(next_authority_name+strlen(rh->name)+2, next_authority->name);
1732 strcpy(rh->name, next_authority_name);
1733 GNUNET_CONTAINER_DLL_remove(rh->authority_chain_head,
1734 rh->authority_chain_tail,
1737 GNUNET_NAMESTORE_zone_to_name (namestore_handle,
1738 &rh->authority_chain_tail->zone,
1739 &rh->authority_chain_head->zone,
1740 &process_zone_to_name_shorten,
1747 * Process result from namestore delegation lookup
1748 * for shorten operation
1750 * @param cls the client shorten handle
1751 * @param rh the resolver handle
1752 * @param rd_count number of results (0)
1753 * @param rd data (NULL)
1756 handle_delegation_ns_shorten(void* cls,
1757 struct ResolverHandle *rh,
1759 const struct GNUNET_NAMESTORE_RecordData *rd)
1761 struct NameShortenHandle *nsh;
1762 char result[MAX_DNS_NAME_LENGTH];
1765 nsh = (struct NameShortenHandle *)cls;
1768 * At this point rh->name contains the part of the name
1769 * that we do not have a PKEY in our namestore to resolve.
1770 * The authority chain in the resolver handle is now
1771 * useful to backtrack if needed
1774 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1775 "PKEY resolved as far as possible in ns up to %s!\n", rh->name);
1777 if (GNUNET_CRYPTO_hash_cmp(&rh->authority_chain_head->zone,
1778 &rh->authority_chain_tail->zone) == 0)
1781 * This is our zone append .gnunet unless name is empty
1782 * (it shouldn't be, usually FIXME what happens if we
1783 * shorten to our zone to a "" record??)
1786 answer_len = strlen(rh->name) + strlen(GNUNET_GNS_TLD) + 2;
1787 memset(result, 0, answer_len);
1788 strcpy(result, rh->name);
1789 strcpy(result+strlen(rh->name), ".");
1790 strcpy(result+strlen(rh->name)+1, GNUNET_GNS_TLD);
1792 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1793 "Our zone: Sending name as shorten result %s\n", rh->name);
1795 nsh->proc(nsh->proc_cls, result);
1797 free_resolver_handle(rh);
1801 /* backtrack authorities for names */
1802 GNUNET_NAMESTORE_zone_to_name (namestore_handle,
1803 &rh->authority_chain_tail->zone, //ours
1804 &rh->authority_chain_head->zone,
1805 &process_zone_to_name_shorten,
1811 * Shorten api from resolver
1813 * @param zone the zone to use
1814 * @param name the name to shorten
1815 * @param proc the processor to call with result
1816 * @param cls closure to pass to proc
1819 gns_resolver_shorten_name(GNUNET_HashCode zone,
1821 ShortenResultProcessor proc,
1824 struct ResolverHandle *rh;
1825 struct NameShortenHandle *nsh;
1827 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1828 "Starting shorten for %s!\n", name);
1830 if (is_canonical((char*)name))
1832 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1833 "%s is canonical. Returning verbatim\n", name);
1838 nsh = GNUNET_malloc(sizeof (struct NameShortenHandle));
1842 nsh->proc_cls = cls;
1844 rh = GNUNET_malloc(sizeof (struct ResolverHandle));
1845 rh->authority = zone;
1847 strlen(name)-strlen(GNUNET_GNS_TLD));
1848 memcpy(rh->name, name,
1849 strlen(name)-strlen(GNUNET_GNS_TLD)-1);
1851 rh->authority_chain_head = GNUNET_malloc(sizeof(struct AuthorityChain));
1852 rh->authority_chain_tail = rh->authority_chain_head;
1853 rh->authority_chain_head->zone = zone;
1854 rh->proc = &handle_delegation_ns_shorten;
1857 /* Start delegation resolution in our namestore */
1858 resolve_delegation_ns(rh);
1861 /*********** END NAME SHORTEN ********************/
1865 * Process result from namestore delegation lookup
1866 * for get authority operation
1868 * @param cls the client get auth handle
1869 * @param rh the resolver handle
1870 * @param rd_count number of results (0)
1871 * @param rd data (NULL)
1874 handle_delegation_result_ns_get_auth(void* cls,
1875 struct ResolverHandle *rh,
1877 const struct GNUNET_NAMESTORE_RecordData *rd)
1879 struct GetNameAuthorityHandle* nah;
1880 char result[MAX_DNS_NAME_LENGTH];
1883 nah = (struct GetNameAuthorityHandle*) rh->proc_cls;
1886 * At this point rh->name contains the part of the name
1887 * that we do not have a PKEY in our namestore to resolve.
1888 * The authority chain in the resolver handle is now
1889 * useful to backtrack if needed
1892 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1893 "PKEY resolved as far as possible in ns up to %s!\n", rh->name);
1895 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1896 "Building response!\n");
1897 if (is_canonical(rh->name))
1900 * We successfully resolved the authority in the ns
1901 * FIXME for our purposes this is fine
1902 * but maybe we want to have an api that also looks
1903 * into the dht (i.e. option in message)
1905 if (strlen(rh->name) > strlen(nah->name))
1907 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1908 "Record name longer than original lookup name... odd!\n");
1912 answer_len = strlen(nah->name) - strlen(rh->name)
1913 + strlen(GNUNET_GNS_TLD) + 1;
1914 memset(result, 0, answer_len);
1915 strcpy(result, nah->name + strlen(rh->name) + 1);
1917 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1918 "Got authority result %s\n", result);
1920 nah->proc(nah->proc_cls, result);
1922 free_resolver_handle(rh);
1926 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1927 "Unable to resolve authority for remaining %s!\n", rh->name);
1928 nah->proc(nah->proc_cls, "");
1930 free_resolver_handle(rh);
1938 * Tries to resolve the authority for name
1941 * @param zone the root zone to look up for
1942 * @param name the name to lookup up
1943 * @param proc the processor to call when finished
1944 * @param cls the closure to pass to the processor
1947 gns_resolver_get_authority(GNUNET_HashCode zone,
1949 GetAuthorityResultProcessor proc,
1952 struct ResolverHandle *rh;
1953 struct GetNameAuthorityHandle *nah;
1955 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1956 "Starting authority resolution for %s!\n", name);
1958 nah = GNUNET_malloc(sizeof (struct GetNameAuthorityHandle));
1959 rh = GNUNET_malloc(sizeof (struct ResolverHandle));
1960 rh->authority = zone;
1962 if (strcmp(GNUNET_GNS_TLD, name) == 0)
1964 strcpy(rh->name, "\0");
1969 strlen(name)-strlen(GNUNET_GNS_TLD));
1970 memcpy(rh->name, name,
1971 strlen(name)-strlen(GNUNET_GNS_TLD) - 1);
1974 memset(nah->name, 0,
1976 strcpy(nah->name, name);
1978 rh->authority_chain_head = GNUNET_malloc(sizeof(struct AuthorityChain));
1979 rh->authority_chain_tail = rh->authority_chain_head;
1980 rh->authority_chain_head->zone = zone;
1981 rh->proc = &handle_delegation_result_ns_get_auth;
1982 rh->proc_cls = (void*)nah;
1985 nah->proc_cls = cls;
1987 /* Start delegation resolution in our namestore */
1988 resolve_delegation_ns(rh);
1992 /******** END GET AUTHORITY *************/
1994 /* end of gnunet-service-gns_resolver.c */