2 This file is part of GNUnet.
3 (C) 2009, 2010, 2011 Christian Grothoff (and other contributing authors)
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
24 * @file gns/gnunet-service-gns_resolver.c
25 * @brief GNUnet GNS resolver logic
26 * @author Martin Schanzenbach
29 #include "gnunet_util_lib.h"
30 #include "gnunet_transport_service.h"
31 #include "gnunet_dns_service.h"
32 #include "gnunet_dht_service.h"
33 #include "gnunet_namestore_service.h"
34 #include "gnunet_dns_service.h"
35 #include "gnunet_dnsparser_lib.h"
36 #include "gnunet_gns_service.h"
37 #include "block_gns.h"
39 #include "gnunet-service-gns_resolver.h"
41 #define DHT_OPERATION_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 3)
42 #define DHT_LOOKUP_TIMEOUT DHT_OPERATION_TIMEOUT
43 #define DHT_GNS_REPLICATION_LEVEL 5
44 #define MAX_DNS_LABEL_LENGTH 63
48 * Our handle to the namestore service
50 static struct GNUNET_NAMESTORE_Handle *namestore_handle;
53 * Resolver handle to the dht
55 static struct GNUNET_DHT_Handle *dht_handle;
58 * Namestore calls this function if we have record for this name.
59 * (or with rd_count=0 to indicate no matches)
61 * @param cls the pending query
62 * @param key the key of the zone we did the lookup
63 * @param expiration expiration date of the namestore entry
64 * @param name the name for which we need an authority
65 * @param rd_count the number of records with 'name'
66 * @param rd the record data
67 * @param signature the signature of the authority for the record data
70 process_pseu_lookup_ns(void* cls,
71 const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *key,
72 struct GNUNET_TIME_Absolute expiration,
73 const char *name, unsigned int rd_count,
74 const struct GNUNET_NAMESTORE_RecordData *rd,
75 const struct GNUNET_CRYPTO_RsaSignature *signature)
77 struct GetPseuAuthorityHandle* gph = (struct GetPseuAuthorityHandle*)cls;
78 struct GNUNET_NAMESTORE_RecordData new_pkey;
82 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
83 "Name %s already taken in NS!\n", name);
84 if (0 == strcmp(gph->name, name))
86 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
87 "Intelligent replacement not implemented\n", name);
88 GNUNET_free(gph->new_name);
89 GNUNET_free(gph->name);
94 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
95 "Trying delegated name %s\n", gph->name);
96 GNUNET_free(gph->new_name);
97 gph->new_name = GNUNET_malloc(strlen(gph->name)+1);
98 memcpy(gph->new_name, gph->name, strlen(gph->name)+1);
99 GNUNET_NAMESTORE_lookup_record(namestore_handle,
102 GNUNET_GNS_RECORD_PSEU,
103 &process_pseu_lookup_ns,
109 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
110 "Name %s not taken in NS! Adding\n", gph->new_name);
112 new_pkey.expiration = GNUNET_TIME_absolute_get_forever ();
113 new_pkey.data_size = sizeof(GNUNET_HashCode);
114 new_pkey.data = &gph->new_zone;
115 new_pkey.record_type = GNUNET_GNS_RECORD_PKEY;
116 GNUNET_NAMESTORE_record_create (namestore_handle,
122 GNUNET_free(gph->new_name);
123 GNUNET_free(gph->name);
129 * process result of a dht pseu lookup
131 * @param gph the handle
132 * @param name the pseu result or NULL
135 process_pseu_result(struct GetPseuAuthorityHandle* gph, char* name)
139 gph->new_name = GNUNET_malloc(strlen(gph->name)+1);
140 memcpy(gph->new_name, name, strlen(gph->name)+1);
144 gph->new_name = GNUNET_malloc(strlen(name)+1);
145 memcpy(gph->new_name, name, strlen(name)+1);
148 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
149 "Checking %s for collision in NS\n", gph->new_name);
152 * Check for collision
154 GNUNET_NAMESTORE_lookup_record(namestore_handle,
157 GNUNET_GNS_RECORD_PSEU,
158 &process_pseu_lookup_ns,
163 * Handle timeout for dht request
165 * @param cls the request handle as closure
166 * @param tc the task context
169 handle_auth_discovery_timeout(void *cls,
170 const struct GNUNET_SCHEDULER_TaskContext *tc)
172 struct GetPseuAuthorityHandle* gph = (struct GetPseuAuthorityHandle*)cls;
174 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
175 "dht lookup for query PSEU timed out.\n");
176 GNUNET_DHT_get_stop (gph->get_handle);
177 process_pseu_result(gph, NULL);
181 * Function called when we find a PSEU entry in the DHT
183 * @param cls the request handle
184 * @param exp lifetime
185 * @param key the key the record was stored under
186 * @param get_path get path
187 * @param get_path_length get path length
188 * @param put_path put path
189 * @param put_path_length put path length
190 * @param type the block type
191 * @param size the size of the record
192 * @param data the record data
195 process_auth_discovery_dht_result(void* cls,
196 struct GNUNET_TIME_Absolute exp,
197 const GNUNET_HashCode * key,
198 const struct GNUNET_PeerIdentity *get_path,
199 unsigned int get_path_length,
200 const struct GNUNET_PeerIdentity *put_path,
201 unsigned int put_path_length,
202 enum GNUNET_BLOCK_Type type,
203 size_t size, const void *data)
205 struct GetPseuAuthorityHandle* gph = (struct GetPseuAuthorityHandle*)cls;
206 struct GNSNameRecordBlock *nrb;
207 char* rd_data = (char*)data;
213 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "got dht result (size=%d)\n", size);
217 GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "got dht result null!\n", size);
219 GNUNET_free(gph->new_name);
220 GNUNET_free(gph->name);
225 nrb = (struct GNSNameRecordBlock*)data;
227 /* stop lookup and timeout task */
228 GNUNET_DHT_get_stop (gph->get_handle);
229 GNUNET_SCHEDULER_cancel(gph->dht_timeout);
231 gph->get_handle = NULL;
233 nrb = (struct GNSNameRecordBlock*)data;
235 name = (char*)&nrb[1];
236 num_records = ntohl(nrb->rd_count);
238 struct GNUNET_NAMESTORE_RecordData rd[num_records];
240 rd_data += strlen(name) + 1 + sizeof(struct GNSNameRecordBlock);
241 rd_size = size - strlen(name) - 1 - sizeof(struct GNSNameRecordBlock);
243 if (GNUNET_SYSERR == GNUNET_NAMESTORE_records_deserialize (rd_size,
248 GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Error deserializing data!\n");
250 GNUNET_free(gph->new_name);
251 GNUNET_free(gph->name);
256 for (i=0; i<num_records; i++)
258 if ((strcmp(name, "+") == 0) &&
259 (rd[i].record_type == GNUNET_GNS_RECORD_PSEU))
262 process_pseu_result(gph, (char*)rd[i].data);
268 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "no pseu in dht!\n");
269 process_pseu_result(gph, NULL);
273 * Callback called by namestore for a zone to name
276 * @param cls the closure
277 * @param zone_key the zone we queried
278 * @param expire the expiration time of the name
279 * @param name the name found or NULL
280 * @param rd_len number of records for the name
281 * @param rd the record data (PKEY) for the name
282 * @param signature the signature for the record data
285 process_zone_to_name_discover(void *cls,
286 const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *zone_key,
287 struct GNUNET_TIME_Absolute expire,
290 const struct GNUNET_NAMESTORE_RecordData *rd,
291 const struct GNUNET_CRYPTO_RsaSignature *signature)
293 struct GetPseuAuthorityHandle* gph = (struct GetPseuAuthorityHandle*)cls;
295 /* we found a match in our own zone */
298 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
299 "name for zone in our root %d\n", strlen(name));
300 GNUNET_free(gph->new_name);
301 GNUNET_free(gph->name);
311 GNUNET_HashCode name_hash;
312 GNUNET_HashCode lookup_key;
313 struct GNUNET_CRYPTO_HashAsciiEncoded lookup_key_string;
315 GNUNET_CRYPTO_hash("+", strlen("+"), &name_hash);
316 GNUNET_CRYPTO_hash_xor(&name_hash, &gph->new_zone, &lookup_key);
317 GNUNET_CRYPTO_hash_to_enc (&lookup_key, &lookup_key_string);
319 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
320 "starting dht lookup for %s with key: %s\n",
321 "+", (char*)&lookup_key_string);
323 gph->dht_timeout = GNUNET_SCHEDULER_add_delayed(DHT_LOOKUP_TIMEOUT,
324 &handle_auth_discovery_timeout, gph);
326 xquery = htonl(GNUNET_GNS_RECORD_PSEU);
328 gph->get_handle = GNUNET_DHT_get_start(dht_handle,
329 DHT_OPERATION_TIMEOUT,
330 GNUNET_BLOCK_TYPE_GNS_NAMERECORD,
332 DHT_GNS_REPLICATION_LEVEL,
336 &process_auth_discovery_dht_result,
344 * Callback for new authories
346 * @param name the name given by delegation
347 * @param zone the authority
348 * @param the private key of our authority
350 static void process_discovered_authority(char* name, GNUNET_HashCode zone,
351 GNUNET_HashCode our_zone,
352 struct GNUNET_CRYPTO_RsaPrivateKey *key)
354 struct GetPseuAuthorityHandle *gph;
357 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "New authority %s discovered\n",
360 gph = GNUNET_malloc(sizeof(struct GetPseuAuthorityHandle));
361 namelen = strlen(name) + 1;
362 gph->name = GNUNET_malloc(namelen);
363 memcpy(gph->name, name, namelen);
365 gph->new_zone = zone;
366 gph->zone = our_zone;
369 GNUNET_NAMESTORE_zone_to_name (namestore_handle,
372 &process_zone_to_name_discover,
378 * Initialize the resolver
380 * @param nh the namestore handle
381 * @param dh the dht handle
382 * @return GNUNET_OK on success
385 gns_resolver_init(struct GNUNET_NAMESTORE_Handle *nh,
386 struct GNUNET_DHT_Handle *dh)
388 namestore_handle = nh;
390 if ((namestore_handle != NULL) && (dht_handle != NULL))
394 return GNUNET_SYSERR;
399 * Helper function to free resolver handle
401 * @rh the handle to free
404 free_resolver_handle(struct ResolverHandle* rh)
406 struct AuthorityChain *ac;
407 struct AuthorityChain *ac_next;
412 GNUNET_free_non_null (rh->name);
413 GNUNET_free_non_null (rh->authority_name);
415 ac = rh->authority_chain_head;
420 GNUNET_free_non_null (ac->name);
429 * Callback when record data is put into namestore
431 * @param cls the closure
432 * @param success GNUNET_OK on success
433 * @param emsg the error message. NULL if SUCCESS==GNUNET_OK
436 on_namestore_record_put_result(void *cls,
440 if (GNUNET_NO == success)
442 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "records already in namestore\n");
445 else if (GNUNET_YES == success)
447 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
448 "records successfully put in namestore\n");
452 GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
453 "Error putting records into namestore: %s\n", emsg);
458 * Handle timeout for DHT requests
460 * @param cls the request handle as closure
461 * @param tc the task context
464 dht_lookup_timeout(void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
466 struct ResolverHandle *rh = cls;
468 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
469 "dht lookup for query %s timed out.\n",
472 GNUNET_DHT_get_stop (rh->get_handle);
473 rh->proc(rh->proc_cls, rh, 0, NULL);
478 * Function called when we get a result from the dht
479 * for our record query
481 * @param cls the request handle
482 * @param exp lifetime
483 * @param key the key the record was stored under
484 * @param get_path get path
485 * @param get_path_length get path length
486 * @param put_path put path
487 * @param put_path_length put path length
488 * @param type the block type
489 * @param size the size of the record
490 * @param data the record data
493 process_record_result_dht(void* cls,
494 struct GNUNET_TIME_Absolute exp,
495 const GNUNET_HashCode * key,
496 const struct GNUNET_PeerIdentity *get_path,
497 unsigned int get_path_length,
498 const struct GNUNET_PeerIdentity *put_path,
499 unsigned int put_path_length,
500 enum GNUNET_BLOCK_Type type,
501 size_t size, const void *data)
503 struct ResolverHandle *rh;
504 struct RecordLookupHandle *rlh;
505 struct GNSNameRecordBlock *nrb;
506 uint32_t num_records;
508 char* rd_data = (char*)data;
512 GNUNET_HashCode zone, name_hash;
513 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "got dht result (size=%d)\n", size);
518 //FIXME maybe check expiration here, check block type
520 rh = (struct ResolverHandle *)cls;
521 rlh = (struct RecordLookupHandle *) rh->proc_cls;
522 nrb = (struct GNSNameRecordBlock*)data;
524 /* stop lookup and timeout task */
525 GNUNET_DHT_get_stop (rh->get_handle);
526 GNUNET_SCHEDULER_cancel(rh->dht_timeout_task);
528 rh->get_handle = NULL;
529 name = (char*)&nrb[1];
530 num_records = ntohl(nrb->rd_count);
532 struct GNUNET_NAMESTORE_RecordData rd[num_records];
534 rd_data += strlen(name) + 1 + sizeof(struct GNSNameRecordBlock);
535 rd_size = size - strlen(name) - 1 - sizeof(struct GNSNameRecordBlock);
537 if (GNUNET_SYSERR == GNUNET_NAMESTORE_records_deserialize (rd_size,
542 GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Error deserializing data!\n");
546 for (i=0; i<num_records; i++)
548 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
549 "Got name: %s (wanted %s)\n", name, rh->name);
550 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
553 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
554 "Got data length: %d\n", rd[i].data_size);
555 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
556 "Got flag %d\n", rd[i].flags);
558 if ((strcmp(name, rh->name) == 0) &&
559 (rd[i].record_type == rlh->record_type))
566 GNUNET_CRYPTO_hash(name, strlen(name), &name_hash);
567 GNUNET_CRYPTO_hash_xor(key, &name_hash, &zone);
570 * FIXME check pubkey against existing key in namestore?
571 * https://gnunet.org/bugs/view.php?id=2179
574 /* Save to namestore */
575 GNUNET_NAMESTORE_record_put (namestore_handle,
582 &on_namestore_record_put_result, //cont
586 rh->proc(rh->proc_cls, rh, num_records, rd);
588 rh->proc(rh->proc_cls, rh, 0, NULL);
595 * Start DHT lookup for a (name -> query->record_type) record in
596 * rh->authority's zone
598 * @param rh the pending gns query context
601 resolve_record_dht(struct ResolverHandle *rh)
604 GNUNET_HashCode name_hash;
605 GNUNET_HashCode lookup_key;
606 struct GNUNET_CRYPTO_HashAsciiEncoded lookup_key_string;
607 struct RecordLookupHandle *rlh = (struct RecordLookupHandle *)rh->proc_cls;
609 GNUNET_CRYPTO_hash(rh->name, strlen(rh->name), &name_hash);
610 GNUNET_CRYPTO_hash_xor(&name_hash, &rh->authority, &lookup_key);
611 GNUNET_CRYPTO_hash_to_enc (&lookup_key, &lookup_key_string);
613 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
614 "starting dht lookup for %s with key: %s\n",
615 rh->name, (char*)&lookup_key_string);
617 rh->dht_timeout_task = GNUNET_SCHEDULER_add_delayed(DHT_LOOKUP_TIMEOUT,
618 &dht_lookup_timeout, rh);
620 xquery = htonl(rlh->record_type);
621 rh->get_handle = GNUNET_DHT_get_start(dht_handle,
622 DHT_OPERATION_TIMEOUT,
623 GNUNET_BLOCK_TYPE_GNS_NAMERECORD,
625 DHT_GNS_REPLICATION_LEVEL,
629 &process_record_result_dht,
636 * Namestore calls this function if we have record for this name.
637 * (or with rd_count=0 to indicate no matches)
639 * @param cls the pending query
640 * @param key the key of the zone we did the lookup
641 * @param expiration expiration date of the namestore entry
642 * @param name the name for which we need an authority
643 * @param rd_count the number of records with 'name'
644 * @param rd the record data
645 * @param signature the signature of the authority for the record data
648 process_record_result_ns(void* cls,
649 const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *key,
650 struct GNUNET_TIME_Absolute expiration,
651 const char *name, unsigned int rd_count,
652 const struct GNUNET_NAMESTORE_RecordData *rd,
653 const struct GNUNET_CRYPTO_RsaSignature *signature)
655 struct ResolverHandle *rh;
656 struct RecordLookupHandle *rlh;
657 struct GNUNET_TIME_Relative remaining_time;
658 GNUNET_HashCode zone;
660 rh = (struct ResolverHandle *) cls;
661 rlh = (struct RecordLookupHandle *)rh->proc_cls;
662 GNUNET_CRYPTO_hash(key,
663 sizeof(struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded),
665 remaining_time = GNUNET_TIME_absolute_get_remaining (expiration);
671 rh->status |= EXISTS;
674 if (remaining_time.rel_value == 0)
676 rh->status |= EXPIRED;
682 * Lookup terminated and no results
684 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
685 "Namestore lookup for %s terminated without results\n", name);
687 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
688 "Record %s unknown in namestore\n",
691 * Our zone and no result? Cannot resolve TT
693 rh->proc(rh->proc_cls, rh, 0, NULL);
700 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
701 "Processing additional result %s from namestore\n", name);
703 for (i=0; i<rd_count;i++)
706 if (rd[i].record_type != rlh->record_type)
709 if ((GNUNET_TIME_absolute_get_remaining (rd[i].expiration)).rel_value
712 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
713 "This record is expired. Skipping\n");
724 if (rh->answered == 0)
726 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
727 "No answers found. This is odd!\n");
728 rh->proc(rh->proc_cls, rh, 0, NULL);
732 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Found %d answer(s) to query!\n",
735 rh->proc(rh->proc_cls, rh, rd_count, rd);
741 * The final phase of resolution.
742 * rh->name is a name that is canonical and we do not have a delegation.
743 * Query namestore for this record
745 * @param rh the pending lookup
748 resolve_record_ns(struct ResolverHandle *rh)
750 struct RecordLookupHandle *rlh = (struct RecordLookupHandle *)rh->proc_cls;
753 * Try to resolve this record in our namestore.
754 * The name to resolve is now in rh->authority_name
755 * since we tried to resolve it to an authority
758 GNUNET_NAMESTORE_lookup_record(namestore_handle,
762 &process_record_result_ns,
768 * Handle timeout for DHT requests
770 * @param cls the request handle as closure
771 * @param tc the task context
774 dht_authority_lookup_timeout(void *cls,
775 const struct GNUNET_SCHEDULER_TaskContext *tc)
777 struct ResolverHandle *rh = cls;
779 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
780 "dht lookup for query %s timed out.\n",
783 GNUNET_DHT_get_stop (rh->get_handle);
784 if (strcmp(rh->name, "") == 0)
787 * promote authority back to name and try to resolve record
789 strcpy(rh->name, rh->authority_name);
791 rh->proc(rh->proc_cls, rh, 0, NULL);
795 static void resolve_delegation_dht(struct ResolverHandle *rh);
798 * Function called when we get a result from the dht
799 * for our query. Recursively tries to resolve authorities
802 * @param cls the request handle
803 * @param exp lifetime
804 * @param key the key the record was stored under
805 * @param get_path get path
806 * @param get_path_length get path length
807 * @param put_path put path
808 * @param put_path_length put path length
809 * @param type the block type
810 * @param size the size of the record
811 * @param data the record data
814 process_delegation_result_dht(void* cls,
815 struct GNUNET_TIME_Absolute exp,
816 const GNUNET_HashCode * key,
817 const struct GNUNET_PeerIdentity *get_path,
818 unsigned int get_path_length,
819 const struct GNUNET_PeerIdentity *put_path,
820 unsigned int put_path_length,
821 enum GNUNET_BLOCK_Type type,
822 size_t size, const void *data)
824 struct ResolverHandle *rh;
825 struct GNSNameRecordBlock *nrb;
826 uint32_t num_records;
828 char* rd_data = (char*) data;
831 GNUNET_HashCode zone, name_hash;
833 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Got DHT result\n");
838 //FIXME check expiration?
840 rh = (struct ResolverHandle *)cls;
841 nrb = (struct GNSNameRecordBlock*)data;
843 /* stop dht lookup and timeout task */
844 GNUNET_DHT_get_stop (rh->get_handle);
845 GNUNET_SCHEDULER_cancel(rh->dht_timeout_task);
847 rh->get_handle = NULL;
848 num_records = ntohl(nrb->rd_count);
849 name = (char*)&nrb[1];
851 struct GNUNET_NAMESTORE_RecordData rd[num_records];
853 rd_data += strlen(name) + 1 + sizeof(struct GNSNameRecordBlock);
854 rd_size = size - strlen(name) - 1 - sizeof(struct GNSNameRecordBlock);
856 if (GNUNET_SYSERR == GNUNET_NAMESTORE_records_deserialize (rd_size,
861 GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Error deserializing data!\n");
865 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
866 "Got name: %s (wanted %s)\n", name, rh->authority_name);
867 for (i=0; i<num_records; i++)
870 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
871 "Got name: %s (wanted %s)\n", name, rh->authority_name);
872 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
873 "Got type: %d (wanted %d)\n",
874 rd[i].record_type, GNUNET_GNS_RECORD_PKEY);
875 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
876 "Got data length: %d\n", rd[i].data_size);
877 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
878 "Got flag %d\n", rd[i].flags);
880 if ((strcmp(name, rh->authority_name) == 0) &&
881 (rd[i].record_type == GNUNET_GNS_RECORD_PKEY))
883 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Authority found in DHT\n");
885 memcpy(&rh->authority, rd[i].data, sizeof(GNUNET_HashCode));
886 struct AuthorityChain *auth =
887 GNUNET_malloc(sizeof(struct AuthorityChain));
888 auth->zone = rh->authority;
889 auth->name = GNUNET_malloc(strlen(rh->authority_name)+1);
890 memset(auth->name, 0, strlen(rh->authority_name)+1);
891 strcpy(auth->name, rh->authority_name);
892 GNUNET_CONTAINER_DLL_insert (rh->authority_chain_head,
893 rh->authority_chain_tail,
896 /** call process new authority */
898 process_discovered_authority(name, auth->zone,
899 rh->authority_chain_tail->zone,
906 GNUNET_CRYPTO_hash(name, strlen(name), &name_hash);
907 GNUNET_CRYPTO_hash_xor(key, &name_hash, &zone);
909 /* Save to namestore */
910 if (0 != GNUNET_CRYPTO_hash_cmp(&rh->authority_chain_tail->zone, &zone))
912 GNUNET_NAMESTORE_record_put (namestore_handle,
919 &on_namestore_record_put_result, //cont
929 * FIXME in this case. should we ask namestore again?
931 if (strcmp(rh->name, "") == 0)
932 rh->proc(rh->proc_cls, rh, 0, NULL);
934 resolve_delegation_dht(rh);
939 * No pkey but name exists
941 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "DHT authority lookup found no match!\n");
942 rh->proc(rh->proc_cls, rh, 0, NULL);
949 finish_lookup(struct ResolverHandle *rh,
950 struct RecordLookupHandle* rlh,
951 unsigned int rd_count,
952 const struct GNUNET_NAMESTORE_RecordData *rd)
956 char new_s_value[256];
957 char new_mx_value[sizeof(struct GNUNET_DNSPARSER_MxRecord)+256];
959 struct GNUNET_NAMESTORE_RecordData p_rd[rd_count];
962 struct GNUNET_DNSPARSER_MxRecord *mx;
965 memcpy(p_rd, rd, rd_count*sizeof(struct GNUNET_NAMESTORE_RecordData));
967 for (i = 0; i < rd_count; i++)
970 if (rd[i].record_type != GNUNET_GNS_RECORD_TYPE_NS &&
971 rd[i].record_type != GNUNET_GNS_RECORD_TYPE_CNAME &&
972 rd[i].record_type != GNUNET_GNS_RECORD_MX)
974 p_rd[i].data = rd[i].data;
979 * for all those records we 'should'
980 * also try to resolve the A/AAAA records (RFC1035)
983 if (rd[i].record_type == GNUNET_GNS_RECORD_MX)
985 mx = (struct GNUNET_DNSPARSER_MxRecord*)rd[i].data;
986 s_value = (char*)&mx[1];
990 s_value = (char*)rd[i].data;
993 s_len = strlen(s_value)+1;
997 /* no postprocessing */
998 p_rd[i].data = rd[i].data;
1002 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1003 "Postprocessing %s\n", s_value);
1005 if (0 == strcmp(s_value+s_len-3, ".+"))
1007 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1008 "Expanding .+ in %s\n", s_value);
1009 if (strcmp(rh->name, "+") == 0)
1011 trailer = rlh->name;
1015 trailer = rlh->name+strlen(rh->name)+1;
1017 memset(new_s_value, 0, s_len+strlen(trailer)+strlen(GNUNET_GNS_TLD));
1018 strcpy(new_s_value, s_value);
1019 pos = new_s_value+s_len-2;
1020 strcpy(pos, trailer);
1021 pos += strlen(trailer);
1022 if (rd[i].record_type == GNUNET_GNS_RECORD_MX)
1025 p_rd[i].data_size = sizeof(struct GNUNET_DNSPARSER_MxRecord)
1026 +strlen(new_s_value)+1;
1028 p_rd[i].data = new_mx_value;
1029 mx = (struct GNUNET_DNSPARSER_MxRecord*)p_rd[i].data;
1031 ((struct GNUNET_DNSPARSER_MxRecord*)rd[i].data)->preference;
1032 memcpy((char*)&mx[1], new_s_value, strlen(new_s_value)+1);
1033 mx->mxhost = (char*)&mx[1];
1037 p_rd[i].data = new_s_value;
1038 p_rd[i].data_size = strlen(new_s_value)+1;
1040 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1041 "Expanded to %s\n", new_s_value);
1045 rlh->proc(rlh->proc_cls, rd_count, p_rd);
1046 GNUNET_free(rlh->name);
1052 * Process DHT lookup result for record.
1054 * @param cls the closure
1055 * @param rh resolver handle
1056 * @param rd_count number of results
1057 * @param rd record data
1060 handle_record_dht(void* cls, struct ResolverHandle *rh,
1061 unsigned int rd_count,
1062 const struct GNUNET_NAMESTORE_RecordData *rd)
1064 struct RecordLookupHandle* rlh;
1066 rlh = (struct RecordLookupHandle*)cls;
1069 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1070 "No records for %s found in DHT. Aborting\n",
1072 /* give up, cannot resolve */
1073 finish_lookup(rh, rlh, 0, NULL);
1074 free_resolver_handle(rh);
1078 /* results found yay */
1079 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1080 "Record resolved from DHT!");
1082 finish_lookup(rh, rlh, rd_count, rd);
1083 free_resolver_handle(rh);
1089 * Process namestore lookup result for record.
1091 * @param cls the closure
1092 * @param rh resolver handle
1093 * @param rd_count number of results
1094 * @param rd record data
1097 handle_record_ns(void* cls, struct ResolverHandle *rh,
1098 unsigned int rd_count,
1099 const struct GNUNET_NAMESTORE_RecordData *rd)
1101 struct RecordLookupHandle* rlh;
1102 rlh = (struct RecordLookupHandle*) cls;
1105 /* ns entry expired and not ours. try dht */
1106 if (rh->status & (EXPIRED | !EXISTS) &&
1107 GNUNET_CRYPTO_hash_cmp(&rh->authority_chain_head->zone,
1108 &rh->authority_chain_tail->zone))
1110 rh->proc = &handle_record_dht;
1111 resolve_record_dht(rh);
1114 /* give up, cannot resolve */
1115 finish_lookup(rh, rlh, 0, NULL);
1116 free_resolver_handle(rh);
1120 /* results found yay */
1121 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1122 "Record resolved from namestore!");
1124 finish_lookup(rh, rlh, rd_count, rd);
1125 free_resolver_handle(rh);
1131 * Determine if this name is canonical.
1133 * a.b.gnunet = not canonical
1136 * @param name the name to test
1137 * @return 1 if canonical
1140 is_canonical(char* name)
1142 uint32_t len = strlen(name);
1145 for (i=0; i<len; i++)
1147 if (*(name+i) == '.')
1154 * Move one level up in the domain hierarchy and return the
1155 * passed top level domain.
1157 * @param name the domain
1158 * @param dest the destination where the tld will be put
1161 pop_tld(char* name, char* dest)
1165 if (is_canonical(name))
1172 for (len = strlen(name); len > 0; len--)
1174 if (*(name+len) == '.')
1184 strcpy(dest, (name+len+1));
1188 * DHT resolution for delegation finished. Processing result.
1190 * @param cls the closure
1191 * @param rh resolver handle
1192 * @param rd_count number of results (always 0)
1193 * @param rd record data (always NULL)
1196 handle_delegation_dht(void* cls, struct ResolverHandle *rh,
1197 unsigned int rd_count,
1198 const struct GNUNET_NAMESTORE_RecordData *rd)
1200 struct RecordLookupHandle* rlh;
1201 rlh = (struct RecordLookupHandle*) cls;
1203 if (strcmp(rh->name, "") == 0)
1205 if ((rlh->record_type == GNUNET_GNS_RECORD_PKEY))
1207 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1208 "Resolved queried PKEY via DHT.\n");
1209 finish_lookup(rh, rlh, rd_count, rd);
1210 free_resolver_handle(rh);
1213 /* We resolved full name for delegation. resolving record */
1214 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1215 "Resolved full name for delegation via DHT. resolving record '' in ns\n");
1216 GNUNET_free(rh->name);
1217 rh->name = GNUNET_malloc(strlen("+")+1);
1218 strcpy(rh->name, "+\0");
1219 rh->proc = &handle_record_ns;
1220 resolve_record_ns(rh);
1225 * we still have some left
1227 if (is_canonical(rh->name))
1229 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1230 "Resolving canonical record %s in ns\n", rh->name);
1231 rh->proc = &handle_record_ns;
1232 resolve_record_ns(rh);
1235 /* give up, cannot resolve */
1236 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1237 "Cannot fully resolve delegation for %s via DHT!\n",
1239 finish_lookup(rh, rlh, 0, NULL);
1240 free_resolver_handle(rh);
1245 * Start DHT lookup for a name -> PKEY (compare NS) record in
1246 * rh->authority's zone
1248 * @param rh the pending gns query
1251 resolve_delegation_dht(struct ResolverHandle *rh)
1254 GNUNET_HashCode name_hash;
1255 GNUNET_HashCode lookup_key;
1257 GNUNET_CRYPTO_hash(rh->authority_name,
1258 strlen(rh->authority_name),
1260 GNUNET_CRYPTO_hash_xor(&name_hash, &rh->authority, &lookup_key);
1262 rh->dht_timeout_task = GNUNET_SCHEDULER_add_delayed (DHT_LOOKUP_TIMEOUT,
1263 &dht_authority_lookup_timeout,
1266 xquery = htonl(GNUNET_GNS_RECORD_PKEY);
1268 rh->get_handle = GNUNET_DHT_get_start(dht_handle,
1269 DHT_OPERATION_TIMEOUT,
1270 GNUNET_BLOCK_TYPE_GNS_NAMERECORD,
1272 DHT_GNS_REPLICATION_LEVEL,
1276 &process_delegation_result_dht,
1283 * Namestore resolution for delegation finished. Processing result.
1285 * @param cls the closure
1286 * @param rh resolver handle
1287 * @param rd_count number of results (always 0)
1288 * @param rd record data (always NULL)
1291 handle_delegation_ns(void* cls, struct ResolverHandle *rh,
1292 unsigned int rd_count,
1293 const struct GNUNET_NAMESTORE_RecordData *rd)
1295 struct RecordLookupHandle* rlh;
1296 rlh = (struct RecordLookupHandle*) cls;
1298 if (strcmp(rh->name, "") == 0)
1300 if ((rlh->record_type == GNUNET_GNS_RECORD_PKEY))
1302 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1303 "Resolved queried PKEY in NS.\n");
1304 finish_lookup(rh, rlh, rd_count, rd);
1305 free_resolver_handle(rh);
1308 /* We resolved full name for delegation. resolving record */
1309 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1310 "Resolved full name for delegation. resolving record '+'\n");
1311 GNUNET_free(rh->name);
1312 rh->name = GNUNET_malloc(strlen("+")+1);
1313 strcpy(rh->name, "+\0");
1314 rh->proc = &handle_record_ns;
1315 resolve_record_ns(rh);
1320 * we still have some left
1321 * check if authority in ns is fresh
1323 * or we are authority
1325 if ((rh->status & (EXISTS | !EXPIRED)) ||
1326 !GNUNET_CRYPTO_hash_cmp(&rh->authority_chain_head->zone,
1327 &rh->authority_chain_tail->zone))
1329 if (is_canonical(rh->name))
1331 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1332 "Resolving canonical record %s\n", rh->name);
1333 rh->proc = &handle_record_ns;
1334 resolve_record_ns(rh);
1338 /* give up, cannot resolve */
1339 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1340 "Cannot fully resolve delegation for %s!\n",
1342 rlh->proc(rlh->proc_cls, 0, NULL);
1347 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1348 "Trying to resolve delegation for %s via DHT\n",
1350 rh->proc = &handle_delegation_dht;
1351 resolve_delegation_dht(rh);
1355 static void resolve_delegation_ns(struct ResolverHandle *rh);
1359 * This is a callback function that should give us only PKEY
1360 * records. Used to query the namestore for the authority (PKEY)
1361 * for 'name'. It will recursively try to resolve the
1362 * authority for a given name from the namestore.
1364 * @param cls the pending query
1365 * @param key the key of the zone we did the lookup
1366 * @param expiration expiration date of the record data set in the namestore
1367 * @param name the name for which we need an authority
1368 * @param rd_count the number of records with 'name'
1369 * @param rd the record data
1370 * @param signature the signature of the authority for the record data
1373 process_delegation_result_ns(void* cls,
1374 const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *key,
1375 struct GNUNET_TIME_Absolute expiration,
1377 unsigned int rd_count,
1378 const struct GNUNET_NAMESTORE_RecordData *rd,
1379 const struct GNUNET_CRYPTO_RsaSignature *signature)
1381 struct ResolverHandle *rh;
1382 struct GNUNET_TIME_Relative remaining_time;
1383 GNUNET_HashCode zone;
1386 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Got %d records from authority lookup\n",
1389 rh = (struct ResolverHandle *)cls;
1390 GNUNET_CRYPTO_hash(key,
1391 sizeof(struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded),
1393 remaining_time = GNUNET_TIME_absolute_get_remaining (expiration);
1399 rh->status |= EXISTS;
1402 if (remaining_time.rel_value == 0)
1404 rh->status |= EXPIRED;
1408 * No authority found in namestore.
1413 * We did not find an authority in the namestore
1418 * Promote this authority back to a name maybe it is
1421 if (strcmp(rh->name, "") == 0)
1423 /* simply promote back */
1424 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1425 "Promoting %s back to name\n", rh->authority_name);
1426 strcpy(rh->name, rh->authority_name);
1430 /* add back to existing name */
1431 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1432 "Adding %s back to %s\n",
1433 rh->authority_name, rh->name);
1434 new_name = GNUNET_malloc(strlen(rh->name)
1435 + strlen(rh->authority_name) + 2);
1436 memset(new_name, 0, strlen(rh->name) + strlen(rh->authority_name) + 2);
1437 strcpy(new_name, rh->name);
1438 strcpy(new_name+strlen(new_name)+1, ".");
1439 strcpy(new_name+strlen(new_name)+2, rh->authority_name);
1440 GNUNET_free(rh->name);
1441 rh->name = new_name;
1443 rh->proc(rh->proc_cls, rh, 0, NULL);
1448 * We found an authority that may be able to help us
1449 * move on with query
1450 * Note only 1 pkey should have been returned.. anything else would be strange
1453 for (i=0; i<rd_count;i++)
1456 if (rd[i].record_type != GNUNET_GNS_RECORD_PKEY)
1459 if ((GNUNET_TIME_absolute_get_remaining (rd[i].expiration)).rel_value
1462 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "This pkey is expired.\n");
1463 if (remaining_time.rel_value == 0)
1465 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1466 "This dht entry is expired.\n");
1467 rh->authority_chain_head->fresh = 0;
1468 rh->proc(rh->proc_cls, rh, 0, NULL);
1476 * Resolve rest of query with new authority
1478 GNUNET_assert(rd[i].record_type == GNUNET_GNS_RECORD_PKEY);
1479 memcpy(&rh->authority, rd[i].data, sizeof(GNUNET_HashCode));
1480 struct AuthorityChain *auth = GNUNET_malloc(sizeof(struct AuthorityChain));
1481 auth->zone = rh->authority;
1482 auth->name = GNUNET_malloc(strlen(rh->authority_name)+1);
1483 memset(auth->name, 0, strlen(rh->authority_name)+1);
1484 strcpy(auth->name, rh->authority_name);
1485 GNUNET_CONTAINER_DLL_insert (rh->authority_chain_head,
1486 rh->authority_chain_tail,
1490 * We are done with PKEY resolution if name is empty
1491 * else resolve again with new authority
1493 if (strcmp(rh->name, "") == 0)
1494 rh->proc(rh->proc_cls, rh, 0, NULL);
1496 resolve_delegation_ns(rh);
1503 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1504 "Authority lookup successful but no PKEY... never get here\n");
1505 rh->proc(rh->proc_cls, rh, 0, NULL);
1510 * Resolve the delegation chain for the request in our namestore
1512 * @param rh the resolver handle
1515 resolve_delegation_ns(struct ResolverHandle *rh)
1517 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1518 "Resolving delegation for %s\n", rh->name);
1519 pop_tld(rh->name, rh->authority_name);
1520 GNUNET_NAMESTORE_lookup_record(namestore_handle,
1523 GNUNET_GNS_RECORD_PKEY,
1524 &process_delegation_result_ns,
1531 * Lookup of a record in a specific zone
1532 * calls lookup result processor on result
1534 * @param zone the root zone
1535 * @param record_type the record type to look up
1536 * @param name the name to look up
1537 * @param proc the processor to call on result
1538 * @param cls the closure to pass to proc
1541 gns_resolver_lookup_record(GNUNET_HashCode zone,
1542 uint32_t record_type,
1544 struct GNUNET_CRYPTO_RsaPrivateKey *key,
1545 RecordLookupProcessor proc,
1548 struct ResolverHandle *rh;
1549 struct RecordLookupHandle* rlh;
1551 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1552 "Starting resolution for %s (type=%d)!\n",
1556 if (is_canonical((char*)name) && (strcmp(GNUNET_GNS_TLD, name) != 0))
1558 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1559 "%s is canonical and gnunet not our TLD!\n", name);
1564 rlh = GNUNET_malloc(sizeof(struct RecordLookupHandle));
1565 rh = GNUNET_malloc(sizeof (struct ResolverHandle));
1567 rh->authority = zone;
1571 if (strcmp(GNUNET_GNS_TLD, name) == 0)
1573 rh->name = GNUNET_malloc(2);
1574 strcpy(rh->name, "");
1578 rh->name = GNUNET_malloc(strlen(name)
1579 - strlen(GNUNET_GNS_TLD));
1581 strlen(name)-strlen(GNUNET_GNS_TLD));
1582 memcpy(rh->name, name,
1583 strlen(name)-strlen(GNUNET_GNS_TLD) - 1);
1586 rh->authority_name = GNUNET_malloc(sizeof(char)*MAX_DNS_LABEL_LENGTH);
1587 rh->authority_chain_head = GNUNET_malloc(sizeof(struct AuthorityChain));
1588 rh->authority_chain_head->prev = NULL;
1589 rh->authority_chain_head->next = NULL;
1590 rh->authority_chain_tail = rh->authority_chain_head;
1591 rh->authority_chain_head->zone = zone;
1593 rlh->record_type = record_type;
1594 rlh->name = GNUNET_malloc(strlen(name) + 1);
1595 memset(rlh->name, 0, strlen(name) + 1);
1596 strcpy(rlh->name, name); //FIXME
1598 rlh->proc_cls = cls;
1600 rh->proc = &handle_delegation_ns;
1601 resolve_delegation_ns(rh);
1604 /******** END Record Resolver ***********/
1608 * Callback calles by namestore for a zone to name
1611 * @param cls the closure
1612 * @param zone_key the zone we queried
1613 * @param expire the expiration time of the name
1614 * @param name the name found or NULL
1615 * @param rd_len number of records for the name
1616 * @param rd the record data (PKEY) for the name
1617 * @param signature the signature for the record data
1620 process_zone_to_name_shorten(void *cls,
1621 const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *zone_key,
1622 struct GNUNET_TIME_Absolute expire,
1624 unsigned int rd_len,
1625 const struct GNUNET_NAMESTORE_RecordData *rd,
1626 const struct GNUNET_CRYPTO_RsaSignature *signature)
1628 struct ResolverHandle *rh = (struct ResolverHandle *)cls;
1629 struct NameShortenHandle* nsh = (struct NameShortenHandle*)rh->proc_cls;
1630 struct AuthorityChain *next_authority;
1633 char* next_authority_name;
1636 /* we found a match in our own zone */
1639 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1640 "result strlen %d\n", strlen(name));
1641 answer_len = strlen(rh->name) + strlen(name) + strlen(GNUNET_GNS_TLD) + 3;
1642 result = GNUNET_malloc(answer_len);
1643 memset(result, 0, answer_len);
1644 if (strlen(rh->name) > 0)
1646 strcpy(result, rh->name);
1647 strcpy(result+strlen(rh->name), ".");
1650 strcpy(result+strlen(result), name);
1651 strcpy(result+strlen(result), ".");
1652 strcpy(result+strlen(result), GNUNET_GNS_TLD);
1654 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1655 "Sending shorten result %s\n", result);
1657 nsh->proc(nsh->proc_cls, result);
1659 free_resolver_handle(rh);
1660 GNUNET_free(result);
1662 else if (GNUNET_CRYPTO_hash_cmp(&rh->authority_chain_head->zone,
1663 &rh->authority_chain_tail->zone))
1665 /* our zone, just append .gnunet */
1666 answer_len = strlen(rh->name) + strlen(GNUNET_GNS_TLD) + 2;
1667 result = GNUNET_malloc(answer_len);
1668 memset(result, 0, answer_len);
1669 strcpy(result, rh->name);
1670 strcpy(result+strlen(rh->name), ".");
1671 strcpy(result+strlen(rh->name)+1, GNUNET_GNS_TLD);
1673 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1674 "Our zone: Sending name as shorten result %s\n", rh->name);
1676 nsh->proc(nsh->proc_cls, result);
1678 free_resolver_handle(rh);
1679 GNUNET_free(result);
1685 * continue with next authority
1687 next_authority = rh->authority_chain_head;
1688 next_authority_name = GNUNET_malloc(strlen(rh->name)+
1689 strlen(next_authority->name) + 2);
1690 memset(next_authority_name, 0, strlen(rh->name)+
1691 strlen(next_authority->name) + 2);
1692 strcpy(next_authority_name, rh->name);
1693 strcpy(next_authority_name+strlen(rh->name)+1, ".");
1694 strcpy(next_authority_name+strlen(rh->name)+2, next_authority->name);
1696 GNUNET_free(rh->name);
1697 rh->name = next_authority_name;
1698 GNUNET_CONTAINER_DLL_remove(rh->authority_chain_head,
1699 rh->authority_chain_tail,
1702 GNUNET_NAMESTORE_zone_to_name (namestore_handle,
1703 &rh->authority_chain_tail->zone,
1704 &rh->authority_chain_head->zone,
1705 &process_zone_to_name_shorten,
1712 * Process result from namestore delegation lookup
1713 * for shorten operation
1715 * @param cls the client shorten handle
1716 * @param rh the resolver handle
1717 * @param rd_count number of results (0)
1718 * @param rd data (NULL)
1721 handle_delegation_ns_shorten(void* cls,
1722 struct ResolverHandle *rh,
1724 const struct GNUNET_NAMESTORE_RecordData *rd)
1726 struct NameShortenHandle *nsh;
1730 nsh = (struct NameShortenHandle *)cls;
1733 * At this point rh->name contains the part of the name
1734 * that we do not have a PKEY in our namestore to resolve.
1735 * The authority chain in the resolver handle is now
1736 * useful to backtrack if needed
1739 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1740 "PKEY resolved as far as possible in ns up to %s!\n", rh->name);
1742 if (GNUNET_CRYPTO_hash_cmp(&rh->authority_chain_head->zone,
1743 &rh->authority_chain_tail->zone) == 0)
1746 * This is our zone append .gnunet unless name is empty
1747 * (it shouldn't be, usually FIXME what happens if we
1748 * shorten to our zone to a "" record??)
1751 answer_len = strlen(rh->name) + strlen(GNUNET_GNS_TLD) + 2;
1752 result = GNUNET_malloc(answer_len);
1753 memset(result, 0, answer_len);
1754 strcpy(result, rh->name);
1755 strcpy(result+strlen(rh->name), ".");
1756 strcpy(result+strlen(rh->name)+1, GNUNET_GNS_TLD);
1758 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1759 "Our zone: Sending name as shorten result %s\n", rh->name);
1761 nsh->proc(nsh->proc_cls, result);
1763 free_resolver_handle(rh);
1764 GNUNET_free(result);
1768 /* backtrack authorities for names */
1769 GNUNET_NAMESTORE_zone_to_name (namestore_handle,
1770 &rh->authority_chain_tail->zone, //ours
1771 &rh->authority_chain_head->zone,
1772 &process_zone_to_name_shorten,
1778 * Shorten api from resolver
1780 * @param zone the zone to use
1781 * @param name the name to shorten
1782 * @param proc the processor to call with result
1783 * @param cls closure to pass to proc
1786 gns_resolver_shorten_name(GNUNET_HashCode zone,
1788 ShortenResultProcessor proc,
1791 struct ResolverHandle *rh;
1792 struct NameShortenHandle *nsh;
1794 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1795 "Starting shorten for %s!\n", name);
1797 if (is_canonical((char*)name))
1799 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1800 "%s is canonical. Returning verbatim\n", name);
1805 nsh = GNUNET_malloc(sizeof (struct NameShortenHandle));
1809 nsh->proc_cls = cls;
1811 rh = GNUNET_malloc(sizeof (struct ResolverHandle));
1812 rh->authority = zone;
1813 rh->name = GNUNET_malloc(strlen(name)
1814 - strlen(GNUNET_GNS_TLD));
1816 strlen(name)-strlen(GNUNET_GNS_TLD));
1817 memcpy(rh->name, name,
1818 strlen(name)-strlen(GNUNET_GNS_TLD)-1);
1820 rh->authority_name = GNUNET_malloc(sizeof(char)*MAX_DNS_LABEL_LENGTH);
1821 rh->authority_chain_head = GNUNET_malloc(sizeof(struct AuthorityChain));
1822 rh->authority_chain_tail = rh->authority_chain_head;
1823 rh->authority_chain_head->zone = zone;
1824 rh->proc = &handle_delegation_ns_shorten;
1827 /* Start delegation resolution in our namestore */
1828 resolve_delegation_ns(rh);
1831 /*********** END NAME SHORTEN ********************/
1835 * Process result from namestore delegation lookup
1836 * for get authority operation
1838 * @param cls the client get auth handle
1839 * @param rh the resolver handle
1840 * @param rd_count number of results (0)
1841 * @param rd data (NULL)
1844 handle_delegation_result_ns_get_auth(void* cls,
1845 struct ResolverHandle *rh,
1847 const struct GNUNET_NAMESTORE_RecordData *rd)
1849 struct GetNameAuthorityHandle* nah;
1853 nah = (struct GetNameAuthorityHandle*) rh->proc_cls;
1856 * At this point rh->name contains the part of the name
1857 * that we do not have a PKEY in our namestore to resolve.
1858 * The authority chain in the resolver handle is now
1859 * useful to backtrack if needed
1862 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1863 "PKEY resolved as far as possible in ns up to %s!\n", rh->name);
1865 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1866 "Building response!\n");
1867 if (is_canonical(rh->name))
1870 * We successfully resolved the authority in the ns
1871 * FIXME for our purposes this is fine
1872 * but maybe we want to have an api that also looks
1873 * into the dht (i.e. option in message)
1875 if (strlen(rh->name) > strlen(nah->name))
1877 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1878 "Record name longer than original lookup name... odd!\n");
1882 answer_len = strlen(nah->name) - strlen(rh->name)
1883 + strlen(GNUNET_GNS_TLD) + 1;
1884 result = GNUNET_malloc(answer_len);
1885 memset(result, 0, answer_len);
1886 strcpy(result, nah->name + strlen(rh->name) + 1);
1888 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1889 "Got authority result %s\n", result);
1891 nah->proc(nah->proc_cls, result);
1892 GNUNET_free(nah->name);
1894 free_resolver_handle(rh);
1895 GNUNET_free(result);
1899 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1900 "Unable to resolve authority for remaining %s!\n", rh->name);
1901 nah->proc(nah->proc_cls, "");
1902 GNUNET_free(nah->name);
1904 free_resolver_handle(rh);
1912 * Tries to resolve the authority for name
1915 * @param zone the root zone to look up for
1916 * @param name the name to lookup up
1917 * @param proc the processor to call when finished
1918 * @param cls the closure to pass to the processor
1921 gns_resolver_get_authority(GNUNET_HashCode zone,
1923 GetAuthorityResultProcessor proc,
1926 struct ResolverHandle *rh;
1927 struct GetNameAuthorityHandle *nah;
1929 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1930 "Starting authority resolution for %s!\n", name);
1932 nah = GNUNET_malloc(sizeof (struct GetNameAuthorityHandle));
1933 rh = GNUNET_malloc(sizeof (struct ResolverHandle));
1934 rh->authority = zone;
1936 if (strcmp(GNUNET_GNS_TLD, name) == 0)
1938 rh->name = GNUNET_malloc(2);
1939 strcpy(rh->name, "");
1943 rh->name = GNUNET_malloc(strlen(name)
1944 - strlen(GNUNET_GNS_TLD));
1946 strlen(name)-strlen(GNUNET_GNS_TLD));
1947 memcpy(rh->name, name,
1948 strlen(name)-strlen(GNUNET_GNS_TLD) - 1);
1951 nah->name = GNUNET_malloc(strlen(name)+1);
1952 memset(nah->name, 0,
1954 strcpy(nah->name, name);
1956 rh->authority_name = GNUNET_malloc(MAX_DNS_LABEL_LENGTH);
1958 rh->authority_chain_head = GNUNET_malloc(sizeof(struct AuthorityChain));
1959 rh->authority_chain_tail = rh->authority_chain_head;
1960 rh->authority_chain_head->zone = zone;
1961 rh->proc = &handle_delegation_result_ns_get_auth;
1962 rh->proc_cls = (void*)nah;
1965 nah->proc_cls = cls;
1967 /* Start delegation resolution in our namestore */
1968 resolve_delegation_ns(rh);
1972 /******** END GET AUTHORITY *************/
1974 /* end of gnunet-service-gns_resolver.c */