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(struct GNUNET_CRYPTO_ShortHashCode);
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 struct GNUNET_CRYPTO_ShortHashCode name_hash;
298 GNUNET_HashCode lookup_key;
299 struct GNUNET_CRYPTO_HashAsciiEncoded lookup_key_string;
300 GNUNET_HashCode name_hash_double;
301 GNUNET_HashCode zone_hash_double;
303 GNUNET_CRYPTO_short_hash("+", strlen("+"), &name_hash);
304 GNUNET_CRYPTO_short_hash_double (&name_hash, &name_hash_double);
305 GNUNET_CRYPTO_short_hash_double (&gph->new_zone, &zone_hash_double);
306 GNUNET_CRYPTO_hash_xor(&name_hash_double, &zone_hash_double, &lookup_key);
307 GNUNET_CRYPTO_hash_to_enc (&lookup_key, &lookup_key_string);
309 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
310 "starting dht lookup for %s with key: %s\n",
311 "+", (char*)&lookup_key_string);
313 gph->dht_timeout = GNUNET_SCHEDULER_add_delayed(DHT_LOOKUP_TIMEOUT,
314 &handle_auth_discovery_timeout, gph);
316 xquery = htonl(GNUNET_GNS_RECORD_PSEU);
318 gph->get_handle = GNUNET_DHT_get_start(dht_handle,
319 DHT_OPERATION_TIMEOUT,
320 GNUNET_BLOCK_TYPE_GNS_NAMERECORD,
322 DHT_GNS_REPLICATION_LEVEL,
326 &process_auth_discovery_dht_result,
334 * Callback for new authories
336 * @param name the name given by delegation
337 * @param zone the authority
338 * @param the private key of our authority
340 static void process_discovered_authority(char* name,
341 struct GNUNET_CRYPTO_ShortHashCode zone,
342 struct GNUNET_CRYPTO_ShortHashCode our_zone,
343 struct GNUNET_CRYPTO_RsaPrivateKey *key)
345 struct GetPseuAuthorityHandle *gph;
348 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "New authority %s discovered\n",
351 gph = GNUNET_malloc(sizeof(struct GetPseuAuthorityHandle));
352 namelen = strlen(name) + 1;
353 memcpy(gph->name, name, namelen);
355 gph->new_zone = zone;
356 gph->zone = our_zone;
359 GNUNET_NAMESTORE_zone_to_name (namestore_handle,
362 &process_zone_to_name_discover,
368 * Initialize the resolver
370 * @param nh the namestore handle
371 * @param dh the dht handle
372 * @return GNUNET_OK on success
375 gns_resolver_init(struct GNUNET_NAMESTORE_Handle *nh,
376 struct GNUNET_DHT_Handle *dh)
378 namestore_handle = nh;
380 if ((namestore_handle != NULL) && (dht_handle != NULL))
384 return GNUNET_SYSERR;
389 * Helper function to free resolver handle
391 * @rh the handle to free
394 free_resolver_handle(struct ResolverHandle* rh)
396 struct AuthorityChain *ac;
397 struct AuthorityChain *ac_next;
402 ac = rh->authority_chain_head;
415 * Callback when record data is put into namestore
417 * @param cls the closure
418 * @param success GNUNET_OK on success
419 * @param emsg the error message. NULL if SUCCESS==GNUNET_OK
422 on_namestore_record_put_result(void *cls,
426 if (GNUNET_NO == success)
428 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "records already in namestore\n");
431 else if (GNUNET_YES == success)
433 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
434 "records successfully put in namestore\n");
438 GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
439 "Error putting records into namestore: %s\n", emsg);
444 * Handle timeout for DHT requests
446 * @param cls the request handle as closure
447 * @param tc the task context
450 dht_lookup_timeout(void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
452 struct ResolverHandle *rh = cls;
454 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
455 "dht lookup for query %s timed out.\n",
458 GNUNET_DHT_get_stop (rh->get_handle);
459 rh->proc(rh->proc_cls, rh, 0, NULL);
464 * Function called when we get a result from the dht
465 * for our record query
467 * @param cls the request handle
468 * @param exp lifetime
469 * @param key the key the record was stored under
470 * @param get_path get path
471 * @param get_path_length get path length
472 * @param put_path put path
473 * @param put_path_length put path length
474 * @param type the block type
475 * @param size the size of the record
476 * @param data the record data
479 process_record_result_dht(void* cls,
480 struct GNUNET_TIME_Absolute exp,
481 const GNUNET_HashCode * key,
482 const struct GNUNET_PeerIdentity *get_path,
483 unsigned int get_path_length,
484 const struct GNUNET_PeerIdentity *put_path,
485 unsigned int put_path_length,
486 enum GNUNET_BLOCK_Type type,
487 size_t size, const void *data)
489 struct ResolverHandle *rh;
490 struct RecordLookupHandle *rlh;
491 struct GNSNameRecordBlock *nrb;
492 uint32_t num_records;
494 char* rd_data = (char*)data;
498 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "got dht result (size=%d)\n", size);
503 //FIXME maybe check expiration here, check block type
505 rh = (struct ResolverHandle *)cls;
506 rlh = (struct RecordLookupHandle *) rh->proc_cls;
507 nrb = (struct GNSNameRecordBlock*)data;
509 /* stop lookup and timeout task */
510 GNUNET_DHT_get_stop (rh->get_handle);
511 GNUNET_SCHEDULER_cancel(rh->dht_timeout_task);
513 rh->get_handle = NULL;
514 name = (char*)&nrb[1];
515 num_records = ntohl(nrb->rd_count);
517 struct GNUNET_NAMESTORE_RecordData rd[num_records];
519 rd_data += strlen(name) + 1 + sizeof(struct GNSNameRecordBlock);
520 rd_size = size - strlen(name) - 1 - sizeof(struct GNSNameRecordBlock);
522 if (GNUNET_SYSERR == GNUNET_NAMESTORE_records_deserialize (rd_size,
527 GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Error deserializing data!\n");
531 for (i=0; i<num_records; i++)
533 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
534 "Got name: %s (wanted %s)\n", name, rh->name);
535 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
538 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
539 "Got data length: %d\n", rd[i].data_size);
540 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
541 "Got flag %d\n", rd[i].flags);
543 if ((strcmp(name, rh->name) == 0) &&
544 (rd[i].record_type == rlh->record_type))
552 * FIXME check pubkey against existing key in namestore?
553 * https://gnunet.org/bugs/view.php?id=2179
556 /* Save to namestore */
557 GNUNET_NAMESTORE_record_put (namestore_handle,
564 &on_namestore_record_put_result, //cont
568 rh->proc(rh->proc_cls, rh, num_records, rd);
570 rh->proc(rh->proc_cls, rh, 0, NULL);
577 * Start DHT lookup for a (name -> query->record_type) record in
578 * rh->authority's zone
580 * @param rh the pending gns query context
583 resolve_record_dht(struct ResolverHandle *rh)
586 struct GNUNET_CRYPTO_ShortHashCode name_hash;
587 GNUNET_HashCode lookup_key;
588 GNUNET_HashCode name_hash_double;
589 GNUNET_HashCode zone_hash_double;
590 struct GNUNET_CRYPTO_HashAsciiEncoded lookup_key_string;
591 struct RecordLookupHandle *rlh = (struct RecordLookupHandle *)rh->proc_cls;
593 GNUNET_CRYPTO_short_hash(rh->name, strlen(rh->name), &name_hash);
594 GNUNET_CRYPTO_short_hash_double(&name_hash, &name_hash_double);
595 GNUNET_CRYPTO_short_hash_double(&rh->authority, &zone_hash_double);
596 GNUNET_CRYPTO_hash_xor(&name_hash_double, &zone_hash_double, &lookup_key);
597 GNUNET_CRYPTO_hash_to_enc (&lookup_key, &lookup_key_string);
599 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
600 "starting dht lookup for %s with key: %s\n",
601 rh->name, (char*)&lookup_key_string);
603 rh->dht_timeout_task = GNUNET_SCHEDULER_add_delayed(DHT_LOOKUP_TIMEOUT,
604 &dht_lookup_timeout, rh);
606 xquery = htonl(rlh->record_type);
607 rh->get_handle = GNUNET_DHT_get_start(dht_handle,
608 DHT_OPERATION_TIMEOUT,
609 GNUNET_BLOCK_TYPE_GNS_NAMERECORD,
611 DHT_GNS_REPLICATION_LEVEL,
615 &process_record_result_dht,
622 * Namestore calls this function if we have record for this name.
623 * (or with rd_count=0 to indicate no matches)
625 * @param cls the pending query
626 * @param key the key of the zone we did the lookup
627 * @param expiration expiration date of the namestore entry
628 * @param name the name for which we need an authority
629 * @param rd_count the number of records with 'name'
630 * @param rd the record data
631 * @param signature the signature of the authority for the record data
634 process_record_result_ns(void* cls,
635 const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *key,
636 struct GNUNET_TIME_Absolute expiration,
637 const char *name, unsigned int rd_count,
638 const struct GNUNET_NAMESTORE_RecordData *rd,
639 const struct GNUNET_CRYPTO_RsaSignature *signature)
641 struct ResolverHandle *rh;
642 struct RecordLookupHandle *rlh;
643 struct GNUNET_TIME_Relative remaining_time;
644 struct GNUNET_CRYPTO_ShortHashCode zone;
646 rh = (struct ResolverHandle *) cls;
647 rlh = (struct RecordLookupHandle *)rh->proc_cls;
648 GNUNET_CRYPTO_short_hash(key,
649 sizeof(struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded),
651 remaining_time = GNUNET_TIME_absolute_get_remaining (expiration);
657 rh->status |= EXISTS;
660 if (remaining_time.rel_value == 0)
662 rh->status |= EXPIRED;
668 * Lookup terminated and no results
670 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
671 "Namestore lookup for %s terminated without results\n", name);
673 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
674 "Record %s unknown in namestore\n",
677 * Our zone and no result? Cannot resolve TT
679 rh->proc(rh->proc_cls, rh, 0, NULL);
686 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
687 "Processing additional result %s from namestore\n", name);
689 for (i=0; i<rd_count;i++)
692 if (rd[i].record_type != rlh->record_type)
695 if ((GNUNET_TIME_absolute_get_remaining (rd[i].expiration)).rel_value
698 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
699 "This record is expired. Skipping\n");
710 if (rh->answered == 0)
712 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
713 "No answers found. This is odd!\n");
714 rh->proc(rh->proc_cls, rh, 0, NULL);
718 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Found %d answer(s) to query!\n",
721 rh->proc(rh->proc_cls, rh, rd_count, rd);
727 * The final phase of resolution.
728 * rh->name is a name that is canonical and we do not have a delegation.
729 * Query namestore for this record
731 * @param rh the pending lookup
734 resolve_record_ns(struct ResolverHandle *rh)
736 struct RecordLookupHandle *rlh = (struct RecordLookupHandle *)rh->proc_cls;
739 * Try to resolve this record in our namestore.
740 * The name to resolve is now in rh->authority_name
741 * since we tried to resolve it to an authority
744 GNUNET_NAMESTORE_lookup_record(namestore_handle,
748 &process_record_result_ns,
754 * Handle timeout for DHT requests
756 * @param cls the request handle as closure
757 * @param tc the task context
760 dht_authority_lookup_timeout(void *cls,
761 const struct GNUNET_SCHEDULER_TaskContext *tc)
763 struct ResolverHandle *rh = cls;
765 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
766 "dht lookup for query %s timed out.\n",
769 GNUNET_DHT_get_stop (rh->get_handle);
770 if (strcmp(rh->name, "") == 0)
773 * promote authority back to name and try to resolve record
775 strcpy(rh->name, rh->authority_name);
777 rh->proc(rh->proc_cls, rh, 0, NULL);
781 static void resolve_delegation_dht(struct ResolverHandle *rh);
784 * Function called when we get a result from the dht
785 * for our query. Recursively tries to resolve authorities
788 * @param cls the request handle
789 * @param exp lifetime
790 * @param key the key the record was stored under
791 * @param get_path get path
792 * @param get_path_length get path length
793 * @param put_path put path
794 * @param put_path_length put path length
795 * @param type the block type
796 * @param size the size of the record
797 * @param data the record data
800 process_delegation_result_dht(void* cls,
801 struct GNUNET_TIME_Absolute exp,
802 const GNUNET_HashCode * key,
803 const struct GNUNET_PeerIdentity *get_path,
804 unsigned int get_path_length,
805 const struct GNUNET_PeerIdentity *put_path,
806 unsigned int put_path_length,
807 enum GNUNET_BLOCK_Type type,
808 size_t size, const void *data)
810 struct ResolverHandle *rh;
811 struct GNSNameRecordBlock *nrb;
812 uint32_t num_records;
814 char* rd_data = (char*) data;
817 struct GNUNET_CRYPTO_ShortHashCode zone, name_hash;
818 GNUNET_HashCode zone_hash_double, name_hash_double;
820 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Got DHT result\n");
825 //FIXME check expiration?
827 rh = (struct ResolverHandle *)cls;
828 nrb = (struct GNSNameRecordBlock*)data;
830 /* stop dht lookup and timeout task */
831 GNUNET_DHT_get_stop (rh->get_handle);
832 GNUNET_SCHEDULER_cancel(rh->dht_timeout_task);
834 rh->get_handle = NULL;
835 num_records = ntohl(nrb->rd_count);
836 name = (char*)&nrb[1];
838 struct GNUNET_NAMESTORE_RecordData rd[num_records];
840 rd_data += strlen(name) + 1 + sizeof(struct GNSNameRecordBlock);
841 rd_size = size - strlen(name) - 1 - sizeof(struct GNSNameRecordBlock);
843 if (GNUNET_SYSERR == GNUNET_NAMESTORE_records_deserialize (rd_size,
848 GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Error deserializing data!\n");
852 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
853 "Got name: %s (wanted %s)\n", name, rh->authority_name);
854 for (i=0; i<num_records; i++)
857 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
858 "Got name: %s (wanted %s)\n", name, rh->authority_name);
859 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
860 "Got type: %d (wanted %d)\n",
861 rd[i].record_type, GNUNET_GNS_RECORD_PKEY);
862 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
863 "Got data length: %d\n", rd[i].data_size);
864 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
865 "Got flag %d\n", rd[i].flags);
867 if ((strcmp(name, rh->authority_name) == 0) &&
868 (rd[i].record_type == GNUNET_GNS_RECORD_PKEY))
870 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Authority found in DHT\n");
872 memcpy(&rh->authority, rd[i].data, sizeof(struct GNUNET_CRYPTO_ShortHashCode));
873 struct AuthorityChain *auth =
874 GNUNET_malloc(sizeof(struct AuthorityChain));
875 auth->zone = rh->authority;
876 memset(auth->name, 0, strlen(rh->authority_name)+1);
877 strcpy(auth->name, rh->authority_name);
878 GNUNET_CONTAINER_DLL_insert (rh->authority_chain_head,
879 rh->authority_chain_tail,
882 /** try to import pkey if private key available */
884 process_discovered_authority(name, auth->zone,
885 rh->authority_chain_tail->zone,
892 GNUNET_CRYPTO_short_hash(name, strlen(name), &name_hash);
893 GNUNET_CRYPTO_short_hash_double(&name_hash, &name_hash_double);
894 GNUNET_CRYPTO_hash_xor(key, &name_hash_double, &zone_hash_double);
895 GNUNET_CRYPTO_short_hash_from_truncation (&zone_hash_double, &zone);
897 /* Save to namestore */
898 if (0 != GNUNET_CRYPTO_short_hash_cmp(&rh->authority_chain_tail->zone,
901 GNUNET_NAMESTORE_record_put (namestore_handle,
908 &on_namestore_record_put_result, //cont
918 * FIXME in this case. should we ask namestore again?
920 if (strcmp(rh->name, "") == 0)
921 rh->proc(rh->proc_cls, rh, 0, NULL);
923 resolve_delegation_dht(rh);
928 * No pkey but name exists
930 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "DHT authority lookup found no match!\n");
931 rh->proc(rh->proc_cls, rh, 0, NULL);
938 finish_lookup(struct ResolverHandle *rh,
939 struct RecordLookupHandle* rlh,
940 unsigned int rd_count,
941 const struct GNUNET_NAMESTORE_RecordData *rd)
945 char new_s_value[256];
946 char new_mx_value[sizeof(struct GNUNET_DNSPARSER_MxRecord)+256];
948 struct GNUNET_NAMESTORE_RecordData p_rd[rd_count];
951 struct GNUNET_DNSPARSER_MxRecord *mx;
954 memcpy(p_rd, rd, rd_count*sizeof(struct GNUNET_NAMESTORE_RecordData));
956 for (i = 0; i < rd_count; i++)
959 if (rd[i].record_type != GNUNET_GNS_RECORD_TYPE_NS &&
960 rd[i].record_type != GNUNET_GNS_RECORD_TYPE_CNAME &&
961 rd[i].record_type != GNUNET_GNS_RECORD_MX)
963 p_rd[i].data = rd[i].data;
968 * for all those records we 'should'
969 * also try to resolve the A/AAAA records (RFC1035)
972 if (rd[i].record_type == GNUNET_GNS_RECORD_MX)
974 mx = (struct GNUNET_DNSPARSER_MxRecord*)rd[i].data;
975 s_value = (char*)&mx[1];
979 s_value = (char*)rd[i].data;
982 s_len = strlen(s_value)+1;
986 /* no postprocessing */
987 p_rd[i].data = rd[i].data;
991 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
992 "Postprocessing %s\n", s_value);
994 if (0 == strcmp(s_value+s_len-3, ".+"))
996 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
997 "Expanding .+ in %s\n", s_value);
998 if (strcmp(rh->name, "+") == 0)
1000 trailer = rlh->name;
1004 trailer = rlh->name+strlen(rh->name)+1;
1006 memset(new_s_value, 0, s_len+strlen(trailer)+strlen(GNUNET_GNS_TLD));
1007 strcpy(new_s_value, s_value);
1008 pos = new_s_value+s_len-2;
1009 strcpy(pos, trailer);
1010 pos += strlen(trailer);
1011 if (rd[i].record_type == GNUNET_GNS_RECORD_MX)
1014 p_rd[i].data_size = sizeof(struct GNUNET_DNSPARSER_MxRecord)
1015 +strlen(new_s_value)+1;
1017 p_rd[i].data = new_mx_value;
1018 mx = (struct GNUNET_DNSPARSER_MxRecord*)p_rd[i].data;
1020 ((struct GNUNET_DNSPARSER_MxRecord*)rd[i].data)->preference;
1021 memcpy((char*)&mx[1], new_s_value, strlen(new_s_value)+1);
1022 mx->mxhost = (char*)&mx[1];
1026 p_rd[i].data = new_s_value;
1027 p_rd[i].data_size = strlen(new_s_value)+1;
1029 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1030 "Expanded to %s\n", new_s_value);
1034 rlh->proc(rlh->proc_cls, rd_count, p_rd);
1040 * Process DHT lookup result for record.
1042 * @param cls the closure
1043 * @param rh resolver handle
1044 * @param rd_count number of results
1045 * @param rd record data
1048 handle_record_dht(void* cls, struct ResolverHandle *rh,
1049 unsigned int rd_count,
1050 const struct GNUNET_NAMESTORE_RecordData *rd)
1052 struct RecordLookupHandle* rlh;
1054 rlh = (struct RecordLookupHandle*)cls;
1057 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1058 "No records for %s found in DHT. Aborting\n",
1060 /* give up, cannot resolve */
1061 finish_lookup(rh, rlh, 0, NULL);
1062 free_resolver_handle(rh);
1066 /* results found yay */
1067 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1068 "Record resolved from DHT!");
1070 finish_lookup(rh, rlh, rd_count, rd);
1071 free_resolver_handle(rh);
1077 * Process namestore lookup result for record.
1079 * @param cls the closure
1080 * @param rh resolver handle
1081 * @param rd_count number of results
1082 * @param rd record data
1085 handle_record_ns(void* cls, struct ResolverHandle *rh,
1086 unsigned int rd_count,
1087 const struct GNUNET_NAMESTORE_RecordData *rd)
1089 struct RecordLookupHandle* rlh;
1090 rlh = (struct RecordLookupHandle*) cls;
1093 /* ns entry expired and not ours. try dht */
1094 if (rh->status & (EXPIRED | !EXISTS) &&
1095 GNUNET_CRYPTO_short_hash_cmp(&rh->authority_chain_head->zone,
1096 &rh->authority_chain_tail->zone))
1098 rh->proc = &handle_record_dht;
1099 resolve_record_dht(rh);
1102 /* give up, cannot resolve */
1103 finish_lookup(rh, rlh, 0, NULL);
1104 free_resolver_handle(rh);
1108 /* results found yay */
1109 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1110 "Record resolved from namestore!");
1112 finish_lookup(rh, rlh, rd_count, rd);
1113 free_resolver_handle(rh);
1119 * Determine if this name is canonical.
1121 * a.b.gnunet = not canonical
1124 * @param name the name to test
1125 * @return 1 if canonical
1128 is_canonical(char* name)
1130 uint32_t len = strlen(name);
1133 for (i=0; i<len; i++)
1135 if (*(name+i) == '.')
1142 * Move one level up in the domain hierarchy and return the
1143 * passed top level domain.
1145 * @param name the domain
1146 * @param dest the destination where the tld will be put
1149 pop_tld(char* name, char* dest)
1153 if (is_canonical(name))
1160 for (len = strlen(name); len > 0; len--)
1162 if (*(name+len) == '.')
1172 strcpy(dest, (name+len+1));
1176 * Checks if name is in tld
1178 * @param name the name to check
1179 * @return GNUNET_YES or GNUNET_NO
1182 is_tld(const char* name, const char* tld)
1186 if (strlen(name) <= strlen(tld))
1191 offset = strlen(name)-strlen(tld);
1192 if (strcmp(name+offset, tld) != 0)
1194 GNUNET_log(GNUNET_ERROR_TYPE_INFO,
1195 "%s is not in .%s TLD\n", name, tld);
1202 * DHT resolution for delegation finished. Processing result.
1204 * @param cls the closure
1205 * @param rh resolver handle
1206 * @param rd_count number of results (always 0)
1207 * @param rd record data (always NULL)
1210 handle_delegation_dht(void* cls, struct ResolverHandle *rh,
1211 unsigned int rd_count,
1212 const struct GNUNET_NAMESTORE_RecordData *rd)
1214 struct RecordLookupHandle* rlh;
1215 rlh = (struct RecordLookupHandle*) cls;
1217 if (strcmp(rh->name, "") == 0)
1219 if ((rlh->record_type == GNUNET_GNS_RECORD_PKEY))
1221 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1222 "Resolved queried PKEY via DHT.\n");
1223 finish_lookup(rh, rlh, rd_count, rd);
1224 free_resolver_handle(rh);
1227 /* We resolved full name for delegation. resolving record */
1228 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1229 "Resolved full name for delegation via DHT. resolving record '' in ns\n");
1230 strcpy(rh->name, "+\0");
1231 rh->proc = &handle_record_ns;
1232 resolve_record_ns(rh);
1237 * we still have some left
1239 if (is_canonical(rh->name))
1241 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1242 "Resolving canonical record %s in ns\n", rh->name);
1243 rh->proc = &handle_record_ns;
1244 resolve_record_ns(rh);
1247 /* give up, cannot resolve */
1248 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1249 "Cannot fully resolve delegation for %s via DHT!\n",
1251 finish_lookup(rh, rlh, 0, NULL);
1252 free_resolver_handle(rh);
1257 * Start DHT lookup for a name -> PKEY (compare NS) record in
1258 * rh->authority's zone
1260 * @param rh the pending gns query
1263 resolve_delegation_dht(struct ResolverHandle *rh)
1266 struct GNUNET_CRYPTO_ShortHashCode name_hash;
1267 GNUNET_HashCode name_hash_double;
1268 GNUNET_HashCode zone_hash_double;
1269 GNUNET_HashCode lookup_key;
1271 GNUNET_CRYPTO_short_hash(rh->authority_name,
1272 strlen(rh->authority_name),
1274 GNUNET_CRYPTO_short_hash_double(&name_hash, &name_hash_double);
1275 GNUNET_CRYPTO_short_hash_double(&rh->authority, &zone_hash_double);
1276 GNUNET_CRYPTO_hash_xor(&name_hash_double, &zone_hash_double, &lookup_key);
1278 rh->dht_timeout_task = GNUNET_SCHEDULER_add_delayed (DHT_LOOKUP_TIMEOUT,
1279 &dht_authority_lookup_timeout,
1282 xquery = htonl(GNUNET_GNS_RECORD_PKEY);
1284 rh->get_handle = GNUNET_DHT_get_start(dht_handle,
1285 DHT_OPERATION_TIMEOUT,
1286 GNUNET_BLOCK_TYPE_GNS_NAMERECORD,
1288 DHT_GNS_REPLICATION_LEVEL,
1292 &process_delegation_result_dht,
1299 * Namestore resolution for delegation finished. Processing result.
1301 * @param cls the closure
1302 * @param rh resolver handle
1303 * @param rd_count number of results (always 0)
1304 * @param rd record data (always NULL)
1307 handle_delegation_ns(void* cls, struct ResolverHandle *rh,
1308 unsigned int rd_count,
1309 const struct GNUNET_NAMESTORE_RecordData *rd)
1311 struct RecordLookupHandle* rlh;
1312 rlh = (struct RecordLookupHandle*) cls;
1314 if (strcmp(rh->name, "") == 0)
1316 if ((rlh->record_type == GNUNET_GNS_RECORD_PKEY))
1318 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1319 "Resolved queried PKEY in NS.\n");
1320 finish_lookup(rh, rlh, rd_count, rd);
1321 free_resolver_handle(rh);
1324 /* We resolved full name for delegation. resolving record */
1325 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1326 "Resolved full name for delegation. resolving record '+'\n");
1327 strcpy(rh->name, "+\0");
1328 rh->proc = &handle_record_ns;
1329 resolve_record_ns(rh);
1334 * we still have some left
1335 * check if authority in ns is fresh
1337 * or we are authority
1339 if ((rh->status & (EXISTS | !EXPIRED)) ||
1340 !GNUNET_CRYPTO_short_hash_cmp(&rh->authority_chain_head->zone,
1341 &rh->authority_chain_tail->zone))
1343 if (is_canonical(rh->name))
1345 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1346 "Resolving canonical record %s\n", rh->name);
1347 rh->proc = &handle_record_ns;
1348 resolve_record_ns(rh);
1352 /* give up, cannot resolve */
1353 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1354 "Cannot fully resolve delegation for %s!\n",
1356 rlh->proc(rlh->proc_cls, 0, NULL);
1361 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1362 "Trying to resolve delegation for %s via DHT\n",
1364 rh->proc = &handle_delegation_dht;
1365 resolve_delegation_dht(rh);
1369 static void resolve_delegation_ns(struct ResolverHandle *rh);
1373 * This is a callback function that should give us only PKEY
1374 * records. Used to query the namestore for the authority (PKEY)
1375 * for 'name'. It will recursively try to resolve the
1376 * authority for a given name from the namestore.
1378 * @param cls the pending query
1379 * @param key the key of the zone we did the lookup
1380 * @param expiration expiration date of the record data set in the namestore
1381 * @param name the name for which we need an authority
1382 * @param rd_count the number of records with 'name'
1383 * @param rd the record data
1384 * @param signature the signature of the authority for the record data
1387 process_delegation_result_ns(void* cls,
1388 const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *key,
1389 struct GNUNET_TIME_Absolute expiration,
1391 unsigned int rd_count,
1392 const struct GNUNET_NAMESTORE_RecordData *rd,
1393 const struct GNUNET_CRYPTO_RsaSignature *signature)
1395 struct ResolverHandle *rh;
1396 struct GNUNET_TIME_Relative remaining_time;
1397 struct GNUNET_CRYPTO_ShortHashCode zone;
1398 char new_name[MAX_DNS_NAME_LENGTH];
1400 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Got %d records from authority lookup\n",
1403 rh = (struct ResolverHandle *)cls;
1404 GNUNET_CRYPTO_short_hash(key,
1405 sizeof(struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded),
1407 remaining_time = GNUNET_TIME_absolute_get_remaining (expiration);
1413 rh->status |= EXISTS;
1416 if (remaining_time.rel_value == 0)
1418 rh->status |= EXPIRED;
1422 * No authority found in namestore.
1427 * We did not find an authority in the namestore
1432 * Promote this authority back to a name maybe it is
1435 if (strcmp(rh->name, "") == 0)
1437 /* simply promote back */
1438 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1439 "Promoting %s back to name\n", rh->authority_name);
1440 strcpy(rh->name, rh->authority_name);
1444 /* add back to existing name */
1445 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1446 "Adding %s back to %s\n",
1447 rh->authority_name, rh->name);
1448 memset(new_name, 0, strlen(rh->name) + strlen(rh->authority_name) + 2);
1449 strcpy(new_name, rh->name);
1450 strcpy(new_name+strlen(new_name)+1, ".");
1451 strcpy(new_name+strlen(new_name)+2, rh->authority_name);
1452 strcpy(rh->name, new_name);
1454 rh->proc(rh->proc_cls, rh, 0, NULL);
1459 * We found an authority that may be able to help us
1460 * move on with query
1461 * Note only 1 pkey should have been returned.. anything else would be strange
1464 for (i=0; i<rd_count;i++)
1467 if (rd[i].record_type != GNUNET_GNS_RECORD_PKEY)
1470 if ((GNUNET_TIME_absolute_get_remaining (rd[i].expiration)).rel_value
1473 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "This pkey is expired.\n");
1474 if (remaining_time.rel_value == 0)
1476 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1477 "This dht entry is expired.\n");
1478 rh->authority_chain_head->fresh = 0;
1479 rh->proc(rh->proc_cls, rh, 0, NULL);
1487 * Resolve rest of query with new authority
1489 GNUNET_assert(rd[i].record_type == GNUNET_GNS_RECORD_PKEY);
1490 memcpy(&rh->authority, rd[i].data, sizeof(struct GNUNET_CRYPTO_ShortHashCode));
1491 struct AuthorityChain *auth = GNUNET_malloc(sizeof(struct AuthorityChain));
1492 auth->zone = rh->authority;
1493 memset(auth->name, 0, strlen(rh->authority_name)+1);
1494 strcpy(auth->name, rh->authority_name);
1495 GNUNET_CONTAINER_DLL_insert (rh->authority_chain_head,
1496 rh->authority_chain_tail,
1500 * We are done with PKEY resolution if name is empty
1501 * else resolve again with new authority
1503 if (strcmp(rh->name, "") == 0)
1504 rh->proc(rh->proc_cls, rh, 0, NULL);
1506 resolve_delegation_ns(rh);
1513 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1514 "Authority lookup successful but no PKEY... never get here\n");
1515 rh->proc(rh->proc_cls, rh, 0, NULL);
1520 * Resolve the delegation chain for the request in our namestore
1522 * @param rh the resolver handle
1525 resolve_delegation_ns(struct ResolverHandle *rh)
1527 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1528 "Resolving delegation for %s\n", rh->name);
1529 pop_tld(rh->name, rh->authority_name);
1530 GNUNET_NAMESTORE_lookup_record(namestore_handle,
1533 GNUNET_GNS_RECORD_PKEY,
1534 &process_delegation_result_ns,
1541 * Lookup of a record in a specific zone
1542 * calls lookup result processor on result
1544 * @param zone the root zone
1545 * @param record_type the record type to look up
1546 * @param name the name to look up
1547 * @param proc the processor to call on result
1548 * @param cls the closure to pass to proc
1551 gns_resolver_lookup_record(struct GNUNET_CRYPTO_ShortHashCode zone,
1552 uint32_t record_type,
1554 struct GNUNET_CRYPTO_RsaPrivateKey *key,
1555 RecordLookupProcessor proc,
1558 struct ResolverHandle *rh;
1559 struct RecordLookupHandle* rlh;
1560 char string_hash[MAX_DNS_NAME_LENGTH]; //FIXME name len as soon as shorthash
1562 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1563 "Starting resolution for %s (type=%d)!\n",
1567 if (is_canonical((char*)name) && (strcmp(GNUNET_GNS_TLD, name) != 0))
1569 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1570 "%s is canonical and not gnunet -> cannot resolve!\n", name);
1575 rlh = GNUNET_malloc(sizeof(struct RecordLookupHandle));
1576 rh = GNUNET_malloc(sizeof (struct ResolverHandle));
1578 rh->authority = zone;
1582 if (strcmp(GNUNET_GNS_TLD, name) == 0)
1585 * Only 'gnunet' given
1587 strcpy(rh->name, "\0");
1591 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1592 "Checking for TLD...\n");
1593 if (is_zkey_tld(name) == GNUNET_YES)
1595 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1598 * This is a zkey tld
1599 * build hash and use as initial authority
1602 strlen(name)-strlen(GNUNET_GNS_TLD_ZKEY));
1603 memcpy(rh->name, name,
1604 strlen(name)-strlen(GNUNET_GNS_TLD_ZKEY) - 1);
1605 pop_tld(rh->name, string_hash);
1607 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1608 "ZKEY is %s!\n", string_hash);
1610 if (GNUNET_OK != GNUNET_CRYPTO_short_hash_from_string(string_hash,
1613 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1614 "Cannot convert ZKEY %s to hash!\n", string_hash);
1624 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1627 * Presumably GNUNET tld
1630 strlen(name)-strlen(GNUNET_GNS_TLD));
1631 memcpy(rh->name, name,
1632 strlen(name)-strlen(GNUNET_GNS_TLD) - 1);
1637 * Initialize authority chain
1639 rh->authority_chain_head = GNUNET_malloc(sizeof(struct AuthorityChain));
1640 rh->authority_chain_head->prev = NULL;
1641 rh->authority_chain_head->next = NULL;
1642 rh->authority_chain_tail = rh->authority_chain_head;
1643 rh->authority_chain_head->zone = rh->authority;
1646 * Copy original query into lookup handle
1648 rlh->record_type = record_type;
1649 memset(rlh->name, 0, strlen(name) + 1);
1650 strcpy(rlh->name, name);
1652 rlh->proc_cls = cls;
1654 rh->proc = &handle_delegation_ns;
1655 resolve_delegation_ns(rh);
1658 /******** END Record Resolver ***********/
1662 * Callback calles by namestore for a zone to name
1665 * @param cls the closure
1666 * @param zone_key the zone we queried
1667 * @param expire the expiration time of the name
1668 * @param name the name found or NULL
1669 * @param rd_len number of records for the name
1670 * @param rd the record data (PKEY) for the name
1671 * @param signature the signature for the record data
1674 process_zone_to_name_shorten(void *cls,
1675 const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *zone_key,
1676 struct GNUNET_TIME_Absolute expire,
1678 unsigned int rd_len,
1679 const struct GNUNET_NAMESTORE_RecordData *rd,
1680 const struct GNUNET_CRYPTO_RsaSignature *signature)
1682 struct ResolverHandle *rh = (struct ResolverHandle *)cls;
1683 struct NameShortenHandle* nsh = (struct NameShortenHandle*)rh->proc_cls;
1684 struct AuthorityChain *next_authority;
1686 char result[MAX_DNS_NAME_LENGTH];
1687 char next_authority_name[MAX_DNS_LABEL_LENGTH];
1690 /* we found a match in our own zone */
1693 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1694 "result strlen %d\n", strlen(name));
1695 answer_len = strlen(rh->name) + strlen(name) + strlen(GNUNET_GNS_TLD) + 3;
1696 memset(result, 0, answer_len);
1697 if (strlen(rh->name) > 0)
1699 strcpy(result, rh->name);
1700 strcpy(result+strlen(rh->name), ".");
1703 strcpy(result+strlen(result), name);
1704 strcpy(result+strlen(result), ".");
1705 strcpy(result+strlen(result), GNUNET_GNS_TLD);
1707 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1708 "Sending shorten result %s\n", result);
1710 nsh->proc(nsh->proc_cls, result);
1712 free_resolver_handle(rh);
1714 else if (GNUNET_CRYPTO_short_hash_cmp(&rh->authority_chain_head->zone,
1715 &rh->authority_chain_tail->zone))
1717 /* our zone, just append .gnunet */
1718 answer_len = strlen(rh->name) + strlen(GNUNET_GNS_TLD) + 2;
1719 memset(result, 0, answer_len);
1720 strcpy(result, rh->name);
1721 strcpy(result+strlen(rh->name), ".");
1722 strcpy(result+strlen(rh->name)+1, GNUNET_GNS_TLD);
1724 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1725 "Our zone: Sending name as shorten result %s\n", rh->name);
1727 nsh->proc(nsh->proc_cls, result);
1729 free_resolver_handle(rh);
1735 * continue with next authority
1737 next_authority = rh->authority_chain_head;
1738 // strlen(next_authority->name) + 2);
1739 memset(next_authority_name, 0, strlen(rh->name)+
1740 strlen(next_authority->name) + 2);
1741 strcpy(next_authority_name, rh->name);
1742 strcpy(next_authority_name+strlen(rh->name)+1, ".");
1743 strcpy(next_authority_name+strlen(rh->name)+2, next_authority->name);
1745 strcpy(rh->name, next_authority_name);
1746 GNUNET_CONTAINER_DLL_remove(rh->authority_chain_head,
1747 rh->authority_chain_tail,
1750 GNUNET_NAMESTORE_zone_to_name (namestore_handle,
1751 &rh->authority_chain_tail->zone,
1752 &rh->authority_chain_head->zone,
1753 &process_zone_to_name_shorten,
1760 * Process result from namestore delegation lookup
1761 * for shorten operation
1763 * @param cls the client shorten handle
1764 * @param rh the resolver handle
1765 * @param rd_count number of results (0)
1766 * @param rd data (NULL)
1769 handle_delegation_ns_shorten(void* cls,
1770 struct ResolverHandle *rh,
1772 const struct GNUNET_NAMESTORE_RecordData *rd)
1774 struct NameShortenHandle *nsh;
1775 char result[MAX_DNS_NAME_LENGTH];
1778 nsh = (struct NameShortenHandle *)cls;
1781 * At this point rh->name contains the part of the name
1782 * that we do not have a PKEY in our namestore to resolve.
1783 * The authority chain in the resolver handle is now
1784 * useful to backtrack if needed
1787 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1788 "PKEY resolved as far as possible in ns up to %s!\n", rh->name);
1790 if (GNUNET_CRYPTO_short_hash_cmp(&rh->authority_chain_head->zone,
1791 &rh->authority_chain_tail->zone) == 0)
1794 * This is our zone append .gnunet unless name is empty
1795 * (it shouldn't be, usually FIXME what happens if we
1796 * shorten to our zone to a "" record??)
1799 answer_len = strlen(rh->name) + strlen(GNUNET_GNS_TLD) + 2;
1800 memset(result, 0, answer_len);
1801 strcpy(result, rh->name);
1802 strcpy(result+strlen(rh->name), ".");
1803 strcpy(result+strlen(rh->name)+1, GNUNET_GNS_TLD);
1805 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1806 "Our zone: Sending name as shorten result %s\n", rh->name);
1808 nsh->proc(nsh->proc_cls, result);
1810 free_resolver_handle(rh);
1814 /* backtrack authorities for names */
1815 GNUNET_NAMESTORE_zone_to_name (namestore_handle,
1816 &rh->authority_chain_tail->zone, //ours
1817 &rh->authority_chain_head->zone,
1818 &process_zone_to_name_shorten,
1824 * Shorten api from resolver
1826 * @param zone the zone to use
1827 * @param name the name to shorten
1828 * @param proc the processor to call with result
1829 * @param cls closure to pass to proc
1832 gns_resolver_shorten_name(struct GNUNET_CRYPTO_ShortHashCode zone,
1834 ShortenResultProcessor proc,
1837 struct ResolverHandle *rh;
1838 struct NameShortenHandle *nsh;
1839 char string_hash[MAX_DNS_NAME_LENGTH]; //FIXME LABEL length when shorthash
1841 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1842 "Starting shorten for %s!\n", name);
1844 if (is_canonical((char*)name))
1846 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1847 "%s is canonical. Returning verbatim\n", name);
1852 nsh = GNUNET_malloc(sizeof (struct NameShortenHandle));
1856 nsh->proc_cls = cls;
1858 rh = GNUNET_malloc(sizeof (struct ResolverHandle));
1859 rh->authority = zone;
1861 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1862 "Checking for TLD...\n");
1863 if (is_zkey_tld(name) == GNUNET_YES)
1865 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1868 * This is a zkey tld
1869 * build hash and use as initial authority
1872 strlen(name)-strlen(GNUNET_GNS_TLD_ZKEY));
1873 memcpy(rh->name, name,
1874 strlen(name)-strlen(GNUNET_GNS_TLD_ZKEY) - 1);
1875 pop_tld(rh->name, string_hash);
1877 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1878 "ZKEY is %s!\n", string_hash);
1880 if (GNUNET_OK != GNUNET_CRYPTO_short_hash_from_string(string_hash,
1883 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1884 "Cannot convert ZKEY %s to hash!\n", string_hash);
1894 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1897 * Presumably GNUNET tld
1900 strlen(name)-strlen(GNUNET_GNS_TLD));
1901 memcpy(rh->name, name,
1902 strlen(name)-strlen(GNUNET_GNS_TLD) - 1);
1905 rh->authority_chain_head = GNUNET_malloc(sizeof(struct AuthorityChain));
1906 rh->authority_chain_tail = rh->authority_chain_head;
1907 rh->authority_chain_head->zone = zone;
1908 rh->proc = &handle_delegation_ns_shorten;
1911 /* Start delegation resolution in our namestore */
1912 resolve_delegation_ns(rh);
1915 /*********** END NAME SHORTEN ********************/
1919 * Process result from namestore delegation lookup
1920 * for get authority operation
1922 * @param cls the client get auth handle
1923 * @param rh the resolver handle
1924 * @param rd_count number of results (0)
1925 * @param rd data (NULL)
1928 handle_delegation_result_ns_get_auth(void* cls,
1929 struct ResolverHandle *rh,
1931 const struct GNUNET_NAMESTORE_RecordData *rd)
1933 struct GetNameAuthorityHandle* nah;
1934 char result[MAX_DNS_NAME_LENGTH];
1937 nah = (struct GetNameAuthorityHandle*) rh->proc_cls;
1940 * At this point rh->name contains the part of the name
1941 * that we do not have a PKEY in our namestore to resolve.
1942 * The authority chain in the resolver handle is now
1943 * useful to backtrack if needed
1946 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1947 "PKEY resolved as far as possible in ns up to %s!\n", rh->name);
1949 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1950 "Building response!\n");
1951 if (is_canonical(rh->name))
1954 * We successfully resolved the authority in the ns
1955 * FIXME for our purposes this is fine
1956 * but maybe we want to have an api that also looks
1957 * into the dht (i.e. option in message)
1959 if (strlen(rh->name) > strlen(nah->name))
1961 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1962 "Record name longer than original lookup name... odd!\n");
1966 answer_len = strlen(nah->name) - strlen(rh->name)
1967 + strlen(GNUNET_GNS_TLD) + 1;
1968 memset(result, 0, answer_len);
1969 strcpy(result, nah->name + strlen(rh->name) + 1);
1971 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1972 "Got authority result %s\n", result);
1974 nah->proc(nah->proc_cls, result);
1976 free_resolver_handle(rh);
1980 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1981 "Unable to resolve authority for remaining %s!\n", rh->name);
1982 nah->proc(nah->proc_cls, "");
1984 free_resolver_handle(rh);
1992 * Tries to resolve the authority for name
1995 * @param zone the root zone to look up for
1996 * @param name the name to lookup up
1997 * @param proc the processor to call when finished
1998 * @param cls the closure to pass to the processor
2001 gns_resolver_get_authority(struct GNUNET_CRYPTO_ShortHashCode zone,
2003 GetAuthorityResultProcessor proc,
2006 struct ResolverHandle *rh;
2007 struct GetNameAuthorityHandle *nah;
2009 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2010 "Starting authority resolution for %s!\n", name);
2012 nah = GNUNET_malloc(sizeof (struct GetNameAuthorityHandle));
2013 rh = GNUNET_malloc(sizeof (struct ResolverHandle));
2014 rh->authority = zone;
2016 if (strcmp(GNUNET_GNS_TLD, name) == 0)
2018 strcpy(rh->name, "\0");
2023 strlen(name)-strlen(GNUNET_GNS_TLD));
2024 memcpy(rh->name, name,
2025 strlen(name)-strlen(GNUNET_GNS_TLD) - 1);
2028 memset(nah->name, 0,
2030 strcpy(nah->name, name);
2032 rh->authority_chain_head = GNUNET_malloc(sizeof(struct AuthorityChain));
2033 rh->authority_chain_tail = rh->authority_chain_head;
2034 rh->authority_chain_head->zone = zone;
2035 rh->proc = &handle_delegation_result_ns_get_auth;
2036 rh->proc_cls = (void*)nah;
2039 nah->proc_cls = cls;
2041 /* Start delegation resolution in our namestore */
2042 resolve_delegation_ns(rh);
2046 /******** END GET AUTHORITY *************/
2048 /* end of gnunet-service-gns_resolver.c */