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_vpn_service.h"
35 #include "gnunet_dns_service.h"
36 #include "gnunet_resolver_service.h"
37 #include "gnunet_dnsparser_lib.h"
38 #include "gnunet_gns_service.h"
39 #include "block_gns.h"
41 #include "gnunet-service-gns_resolver.h"
43 #define DHT_LOOKUP_TIMEOUT DHT_OPERATION_TIMEOUT
44 #define DHT_GNS_REPLICATION_LEVEL 5
45 #define MAX_DNS_LABEL_LENGTH 63
49 * Our handle to the namestore service
51 static struct GNUNET_NAMESTORE_Handle *namestore_handle;
54 * Our handle to the vpn service
56 static struct GNUNET_VPN_Handle *vpn_handle;
59 * Resolver handle to the dht
61 static struct GNUNET_DHT_Handle *dht_handle;
64 * Heap for parallel DHT lookups
66 static struct GNUNET_CONTAINER_Heap *dht_lookup_heap;
69 * Maximum amount of parallel queries in background
71 static unsigned long long max_allowed_background_queries;
74 * Wheather or not to ignore pending records
76 static int ignore_pending_records;
81 static struct GNUNET_CRYPTO_ShortHashCode local_zone;
84 * Background shortening handles
86 static struct GetPseuAuthorityHandle *gph_head;
89 * Background shortening handles
91 static struct GetPseuAuthorityHandle *gph_tail;
94 * a resolution identifier pool variable
96 * This is a non critical identifier useful for debugging
98 static unsigned long long rid = 0;
102 * Determine if this name is canonical.
104 * a.b.gnunet = not canonical
107 * @param name the name to test
108 * @return 1 if canonical
111 is_canonical(char* name)
113 uint32_t len = strlen(name);
116 for (i=0; i<len; i++)
118 if (*(name+i) == '.')
126 * Callback that shortens authorities
128 * @param gph the handle containing the name to shorten
131 shorten_authority_chain (struct GetPseuAuthorityHandle *gph);
135 * Namestore calls this function if we have record for this name.
136 * (or with rd_count=0 to indicate no matches)
138 * @param cls the pending query
139 * @param key the key of the zone we did the lookup
140 * @param expiration expiration date of the namestore entry
141 * @param name the name for which we need an authority
142 * @param rd_count the number of records with 'name'
143 * @param rd the record data
144 * @param signature the signature of the authority for the record data
147 process_pseu_lookup_ns (void* cls,
148 const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *key,
149 struct GNUNET_TIME_Absolute expiration,
150 const char *name, unsigned int rd_count,
151 const struct GNUNET_NAMESTORE_RecordData *rd,
152 const struct GNUNET_CRYPTO_RsaSignature *signature)
154 struct GetPseuAuthorityHandle* gph = (struct GetPseuAuthorityHandle*)cls;
155 struct GNUNET_NAMESTORE_RecordData new_pkey;
156 struct AuthorityChain *iter;
160 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
161 "GNS_AUTO_PSEU: Name %s already taken in NS!\n", name);
162 if (0 == strcmp (gph->name, name))
164 if (gph->ahead->next != NULL)
166 if (GNUNET_CRYPTO_short_hash_cmp (&gph->ahead->next->zone,
169 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "GNS_GET_AUTH: trying next!\n");
170 iter = gph->ahead->next;
171 GNUNET_free (gph->ahead);
173 shorten_authority_chain (gph);
181 iter = gph->ahead->next;
182 GNUNET_free (gph->ahead);
184 } while (iter != NULL);
185 GNUNET_CRYPTO_rsa_key_free (gph->key);
186 GNUNET_CONTAINER_DLL_remove (gph_head, gph_tail, gph);
191 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
192 "GNS_AUTO_PSEU: Trying delegated name %s\n", gph->name);
193 memcpy (gph->test_name, gph->name, strlen (gph->name)+1);
194 GNUNET_NAMESTORE_lookup_record (namestore_handle,
197 GNUNET_NAMESTORE_TYPE_ANY,
198 &process_pseu_lookup_ns,
204 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
205 "GNS_AUTO_PSEU: Name %s not taken in NS! Adding\n", gph->test_name);
207 new_pkey.expiration_time = UINT64_MAX;
208 new_pkey.data_size = sizeof (struct GNUNET_CRYPTO_ShortHashCode);
209 new_pkey.data = &gph->ahead->zone;
210 new_pkey.record_type = GNUNET_GNS_RECORD_PKEY;
211 new_pkey.flags = GNUNET_NAMESTORE_RF_AUTHORITY
212 | GNUNET_NAMESTORE_RF_PRIVATE
213 | GNUNET_NAMESTORE_RF_PENDING;
214 GNUNET_NAMESTORE_record_create (namestore_handle,
222 iter = gph->ahead->next;
223 GNUNET_free (gph->ahead);
225 } while (iter != NULL);
226 GNUNET_CRYPTO_rsa_key_free (gph->key);
227 GNUNET_CONTAINER_DLL_remove (gph_head, gph_tail, gph);
233 * process result of a dht pseu lookup
235 * @param gph the handle
236 * @param name the pseu result or NULL
239 process_pseu_result (struct GetPseuAuthorityHandle* gph, char* name)
243 memcpy (gph->test_name, gph->ahead->name, strlen (gph->ahead->name)+1);
247 memcpy (gph->test_name, name, strlen(name)+1);
250 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
251 "GNS_AUTO_PSEU: Checking %s for collision in NS\n",
255 * Check for collision
257 GNUNET_NAMESTORE_lookup_record (namestore_handle,
260 GNUNET_NAMESTORE_TYPE_ANY,
261 &process_pseu_lookup_ns,
266 * Handle timeout for dht request
268 * @param cls the request handle as closure
269 * @param tc the task context
272 handle_auth_discovery_timeout(void *cls,
273 const struct GNUNET_SCHEDULER_TaskContext *tc)
275 struct GetPseuAuthorityHandle* gph = (struct GetPseuAuthorityHandle*)cls;
276 struct AuthorityChain *iter;
278 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
279 "GNS_GET_AUTH: dht lookup for query PSEU timed out.\n");
280 GNUNET_DHT_get_stop (gph->get_handle);
281 gph->get_handle = NULL;
283 if (gph->ahead->next != NULL)
285 if (GNUNET_CRYPTO_short_hash_cmp (&gph->ahead->next->zone,
288 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "GNS_GET_AUTH: trying next!\n");
289 iter = gph->ahead->next;
290 GNUNET_free (gph->ahead);
292 shorten_authority_chain (gph);
297 process_pseu_result (gph, NULL);
301 * Function called when we find a PSEU entry in the DHT
303 * @param cls the request handle
304 * @param exp lifetime
305 * @param key the key the record was stored under
306 * @param get_path get path
307 * @param get_path_length get path length
308 * @param put_path put path
309 * @param put_path_length put path length
310 * @param type the block type
311 * @param size the size of the record
312 * @param data the record data
315 process_auth_discovery_dht_result(void* cls,
316 struct GNUNET_TIME_Absolute exp,
317 const struct GNUNET_HashCode * key,
318 const struct GNUNET_PeerIdentity *get_path,
319 unsigned int get_path_length,
320 const struct GNUNET_PeerIdentity *put_path,
321 unsigned int put_path_length,
322 enum GNUNET_BLOCK_Type type,
323 size_t size, const void *data)
325 struct GetPseuAuthorityHandle* gph = (struct GetPseuAuthorityHandle*)cls;
326 struct AuthorityChain *iter;
327 struct GNSNameRecordBlock *nrb;
328 char* rd_data = (char*)data;
334 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
335 "GNS_GET_AUTH: got dht result (size=%d)\n", size);
338 /* stop lookup and timeout task */
339 GNUNET_DHT_get_stop (gph->get_handle);
340 gph->get_handle = NULL;
341 GNUNET_SCHEDULER_cancel (gph->timeout);
345 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
346 "GNS_GET_AUTH: got dht result null!\n", size);
350 iter = gph->ahead->next;
351 GNUNET_free (gph->ahead);
353 } while (iter != NULL);
354 GNUNET_CRYPTO_rsa_key_free (gph->key);
355 GNUNET_CONTAINER_DLL_remove (gph_head, gph_tail, gph);
360 nrb = (struct GNSNameRecordBlock*)data;
364 nrb = (struct GNSNameRecordBlock*)data;
366 name = (char*)&nrb[1];
367 num_records = ntohl (nrb->rd_count);
369 struct GNUNET_NAMESTORE_RecordData rd[num_records];
371 rd_data += strlen (name) + 1 + sizeof (struct GNSNameRecordBlock);
372 rd_size = size - strlen (name) - 1 - sizeof (struct GNSNameRecordBlock);
374 if (GNUNET_SYSERR == GNUNET_NAMESTORE_records_deserialize (rd_size,
379 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
380 "GNS_GET_AUTH: Error deserializing data!\n");
384 for (i=0; i < num_records; i++)
386 if ((strcmp (name, "+") == 0) &&
387 (rd[i].record_type == GNUNET_GNS_RECORD_PSEU))
390 process_pseu_result (gph, (char*)rd[i].data);
397 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "GNS_GET_AUTH: no pseu in dht!\n");
399 if (gph->ahead->next != NULL)
401 if (GNUNET_CRYPTO_short_hash_cmp (&gph->ahead->next->zone,
404 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "GNS_GET_AUTH: trying next!\n");
405 iter = gph->ahead->next;
406 GNUNET_free (gph->ahead);
408 shorten_authority_chain (gph);
412 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
413 "GNS_GET_AUTH: finished shorten, no results!\n");
414 process_pseu_result (gph, NULL);
418 * Process PSEU discovery for shorten via namestore
420 * @param cls the GetPseuAuthorityHandle
421 * @param key the public key
422 * @param expiration recorddata expiration
423 * @param name the looked up name
424 * @param rd_count number of records in set
425 * @param rd record data
426 * @param signature the signature
429 process_auth_discovery_ns_result(void* cls,
430 const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *key,
431 struct GNUNET_TIME_Absolute expiration,
433 unsigned int rd_count,
434 const struct GNUNET_NAMESTORE_RecordData *rd,
435 const struct GNUNET_CRYPTO_RsaSignature *signature)
438 struct GNUNET_CRYPTO_ShortHashCode name_hash;
439 struct GNUNET_HashCode lookup_key;
440 struct GNUNET_CRYPTO_HashAsciiEncoded lookup_key_string;
441 struct GNUNET_HashCode name_hash_double;
442 struct GNUNET_HashCode zone_hash_double;
444 struct GetPseuAuthorityHandle* gph = (struct GetPseuAuthorityHandle*)cls;
445 struct AuthorityChain *iter;
453 GNUNET_CRYPTO_short_hash ("+", strlen ("+"), &name_hash);
454 GNUNET_CRYPTO_short_hash_double (&name_hash, &name_hash_double);
455 GNUNET_CRYPTO_short_hash_double (&gph->ahead->zone, &zone_hash_double);
456 GNUNET_CRYPTO_hash_xor (&name_hash_double, &zone_hash_double, &lookup_key);
457 GNUNET_CRYPTO_hash_to_enc (&lookup_key, &lookup_key_string);
459 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
460 "GNS_AUTO_PSEU: starting dht lookup for %s with key: %s\n",
461 "+", (char*)&lookup_key_string);
463 gph->timeout = GNUNET_SCHEDULER_add_delayed (DHT_LOOKUP_TIMEOUT,
464 &handle_auth_discovery_timeout, gph);
466 xquery = htonl (GNUNET_GNS_RECORD_PSEU);
468 GNUNET_assert (gph->get_handle == NULL);
470 gph->get_handle = GNUNET_DHT_get_start(dht_handle,
471 GNUNET_BLOCK_TYPE_GNS_NAMERECORD,
473 DHT_GNS_REPLICATION_LEVEL,
477 &process_auth_discovery_dht_result,
482 for (i=0; i < rd_count; i++)
484 if ((strcmp (name, "+") == 0) &&
485 (rd[i].record_type == GNUNET_GNS_RECORD_PSEU))
488 process_pseu_result (gph, (char*)rd[i].data);
493 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "GNS_GET_AUTH: no pseu in namestore!\n");
495 if (gph->ahead->next != NULL)
497 if (GNUNET_CRYPTO_short_hash_cmp (&gph->ahead->next->zone,
500 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "GNS_GET_AUTH: trying next!\n");
501 iter = gph->ahead->next;
502 GNUNET_free (gph->ahead);
504 shorten_authority_chain (gph);
509 process_pseu_result (gph, NULL);
513 * Callback called by namestore for a zone to name
516 * @param cls the closure
517 * @param zone_key the zone we queried
518 * @param expire the expiration time of the name
519 * @param name the name found or NULL
520 * @param rd_len number of records for the name
521 * @param rd the record data (PKEY) for the name
522 * @param signature the signature for the record data
525 process_zone_to_name_discover (void *cls,
526 const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *zone_key,
527 struct GNUNET_TIME_Absolute expire,
530 const struct GNUNET_NAMESTORE_RecordData *rd,
531 const struct GNUNET_CRYPTO_RsaSignature *signature)
533 struct GetPseuAuthorityHandle* gph = (struct GetPseuAuthorityHandle*)cls;
534 struct AuthorityChain *iter;
536 /* we found a match in our own zone */
539 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
540 "GNS_AUTO_PSEU: name for zone in our root %s\n", name);
545 iter = gph->ahead->next;
546 GNUNET_free (gph->ahead);
548 } while (iter != NULL);
549 GNUNET_CRYPTO_rsa_key_free (gph->key);
550 GNUNET_CONTAINER_DLL_remove (gph_head, gph_tail, gph);
556 GNUNET_NAMESTORE_lookup_record (namestore_handle,
559 GNUNET_GNS_RECORD_PSEU,
560 &process_auth_discovery_ns_result,
568 * Callback that shortens authorities
570 * @param gph the handle to the shorten request
573 shorten_authority_chain (struct GetPseuAuthorityHandle *gph)
576 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
577 "GNS_AUTO_PSEU: New authority %s discovered\n",
580 GNUNET_NAMESTORE_zone_to_name (namestore_handle,
583 &process_zone_to_name_discover,
589 start_shorten (struct AuthorityChain *atail,
590 struct GNUNET_CRYPTO_RsaPrivateKey *key)
592 struct AuthorityChain *new_head = NULL;
593 struct AuthorityChain *new_tail = NULL;
594 struct AuthorityChain *iter;
595 struct AuthorityChain *acopy;
596 struct GetPseuAuthorityHandle *gph;
597 struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded pkey;
598 struct GNUNET_CRYPTO_RsaPrivateKeyBinaryEncoded *pb_key;
600 /* First copy the authority chain in reverse order */
601 for (iter = atail; iter != NULL; iter = iter->prev)
603 acopy = GNUNET_malloc (sizeof (struct AuthorityChain));
604 memcpy (acopy, iter, sizeof (struct AuthorityChain));
607 GNUNET_CONTAINER_DLL_insert (new_head, new_tail, acopy);
610 gph = GNUNET_malloc (sizeof (struct GetPseuAuthorityHandle));
612 GNUNET_CRYPTO_rsa_key_get_public (key, &pkey);
613 pb_key = GNUNET_CRYPTO_rsa_encode_key (key);
614 gph->key = GNUNET_CRYPTO_rsa_decode_key ((char*)pb_key, ntohs (pb_key->len));
615 //gph->key = key;//GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_RsaPrivateKey));
616 //memcpy (gph->key, key, sizeof (struct GNUNET_CRYPTO_RsaPrivateKey));
618 GNUNET_CRYPTO_short_hash (&pkey,
619 sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded),
621 gph->ahead = new_head;
623 GNUNET_CONTAINER_DLL_insert (gph_head, gph_tail, gph);
625 shorten_authority_chain (gph);
629 * Initialize the resolver
631 * @param nh the namestore handle
632 * @param dh the dht handle
633 * @param lz the local zone's hash
634 * @param cfg configuration handle
635 * @param max_bg_queries maximum number of parallel background queries in dht
636 * @param ignore_pending ignore records that still require user confirmation
638 * @return GNUNET_OK on success
641 gns_resolver_init(struct GNUNET_NAMESTORE_Handle *nh,
642 struct GNUNET_DHT_Handle *dh,
643 struct GNUNET_CRYPTO_ShortHashCode lz,
644 const struct GNUNET_CONFIGURATION_Handle *cfg,
645 unsigned long long max_bg_queries,
648 namestore_handle = nh;
652 GNUNET_CONTAINER_heap_create(GNUNET_CONTAINER_HEAP_ORDER_MIN);
653 max_allowed_background_queries = max_bg_queries;
654 ignore_pending_records = ignore_pending;
659 GNUNET_RESOLVER_connect (cfg);
661 if (NULL == vpn_handle)
663 vpn_handle = GNUNET_VPN_connect (cfg);
664 if (NULL == vpn_handle)
666 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
667 "GNS_PHASE_INIT: Error connecting to VPN!\n");
669 return GNUNET_SYSERR;
673 if ((namestore_handle != NULL) && (dht_handle != NULL))
678 return GNUNET_SYSERR;
682 * Cleanup background lookups
684 * @param cls closure to iterator
685 * @param node heap nodes
686 * @param element the resolver handle
687 * @param cost heap cost
688 * @return always GNUNET_YES
691 cleanup_pending_background_queries(void* cls,
692 struct GNUNET_CONTAINER_HeapNode *node,
694 GNUNET_CONTAINER_HeapCostType cost)
696 struct ResolverHandle *rh = (struct ResolverHandle *)element;
697 ResolverCleanupContinuation cont = cls;
699 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
700 "GNS_CLEANUP-%llu: Terminating background lookup for %s\n",
702 GNUNET_DHT_get_stop(rh->get_handle);
703 rh->get_handle = NULL;
704 rh->proc(rh->proc_cls, rh, 0, NULL);
706 GNUNET_CONTAINER_heap_remove_node(node);
708 if (GNUNET_CONTAINER_heap_get_size(dht_lookup_heap) == 0)
720 gns_resolver_cleanup(ResolverCleanupContinuation cont)
722 unsigned int s = GNUNET_CONTAINER_heap_get_size(dht_lookup_heap);
723 struct GetPseuAuthorityHandle *tmp;
724 struct AuthorityChain *iter;
726 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
727 "GNS_CLEANUP: %d pending background queries to terminate\n", s);
730 for (tmp = gph_head; tmp != NULL; tmp = gph_head)
732 if (tmp->get_handle != NULL)
733 GNUNET_DHT_get_stop (tmp->get_handle);
734 tmp->get_handle = NULL;
735 if (tmp->timeout != GNUNET_SCHEDULER_NO_TASK)
736 GNUNET_SCHEDULER_cancel (tmp->timeout);
737 tmp->timeout = GNUNET_SCHEDULER_NO_TASK;
742 iter = tmp->ahead->next;
743 GNUNET_free (tmp->ahead);
745 } while (iter != NULL);
747 GNUNET_CRYPTO_rsa_key_free (tmp->key);
748 GNUNET_CONTAINER_DLL_remove (gph_head, gph_tail, tmp);
754 GNUNET_CONTAINER_heap_iterate (dht_lookup_heap,
755 &cleanup_pending_background_queries,
763 * Helper function to free resolver handle
765 * @param rh the handle to free
768 free_resolver_handle(struct ResolverHandle* rh)
770 struct AuthorityChain *ac;
771 struct AuthorityChain *ac_next;
776 ac = rh->authority_chain_head;
785 if (NULL != rh->dns_raw_packet)
786 GNUNET_free (rh->dns_raw_packet);
793 * Callback when record data is put into namestore
795 * @param cls the closure
796 * @param success GNUNET_OK on success
797 * @param emsg the error message. NULL if SUCCESS==GNUNET_OK
800 on_namestore_record_put_result(void *cls,
804 if (GNUNET_NO == success)
806 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
807 "GNS_NS: records already in namestore\n");
810 else if (GNUNET_YES == success)
812 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
813 "GNS_NS: records successfully put in namestore\n");
817 GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
818 "GNS_NS: Error putting records into namestore: %s\n", emsg);
822 handle_lookup_timeout(void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
824 struct ResolverHandle *rh = cls;
826 if (rh->timeout_cont)
827 rh->timeout_cont(rh->timeout_cont_cls, tc);
831 * Processor for background lookups in the DHT
833 * @param cls closure (NULL)
834 * @param rd_count number of records found (not 0)
835 * @param rd record data
838 background_lookup_result_processor(void *cls,
840 const struct GNUNET_NAMESTORE_RecordData *rd)
842 //We could do sth verbose/more useful here but it doesn't make any difference
843 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
844 "GNS_BG: background dht lookup finished. (%d results)\n",
849 * Handle timeout for DHT requests
851 * @param cls the request handle as closure
852 * @param tc the task context
855 dht_lookup_timeout(void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
857 struct ResolverHandle *rh = cls;
858 struct RecordLookupHandle *rlh = (struct RecordLookupHandle *)rh->proc_cls;
859 char new_name[MAX_DNS_NAME_LENGTH];
861 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
862 "GNS_PHASE_REC-%d: dht lookup for query %s (%ds)timed out.\n",
863 rh->id, rh->name, rh->timeout.rel_value);
865 * Start resolution in bg
867 //strcpy(new_name, rh->name);
868 //memcpy(new_name+strlen(new_name), GNUNET_GNS_TLD, strlen(GNUNET_GNS_TLD));
869 GNUNET_snprintf(new_name, MAX_DNS_NAME_LENGTH, "%s.%s",
870 rh->name, GNUNET_GNS_TLD);
872 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
873 "GNS_PHASE_REC-%d: Starting background lookup for %s type %d\n",
874 rh->id, new_name, rlh->record_type);
876 gns_resolver_lookup_record(rh->authority,
877 rh->private_local_zone,
881 GNUNET_TIME_UNIT_FOREVER_REL,
883 &background_lookup_result_processor,
885 rh->timeout_task = GNUNET_SCHEDULER_NO_TASK;
887 GNUNET_DHT_get_stop (rh->get_handle);
888 rh->get_handle = NULL;
889 rh->proc(rh->proc_cls, rh, 0, NULL);
894 * Function called when we get a result from the dht
895 * for our record query
897 * @param cls the request handle
898 * @param exp lifetime
899 * @param key the key the record was stored under
900 * @param get_path get path
901 * @param get_path_length get path length
902 * @param put_path put path
903 * @param put_path_length put path length
904 * @param type the block type
905 * @param size the size of the record
906 * @param data the record data
909 process_record_result_dht(void* cls,
910 struct GNUNET_TIME_Absolute exp,
911 const struct GNUNET_HashCode * key,
912 const struct GNUNET_PeerIdentity *get_path,
913 unsigned int get_path_length,
914 const struct GNUNET_PeerIdentity *put_path,
915 unsigned int put_path_length,
916 enum GNUNET_BLOCK_Type type,
917 size_t size, const void *data)
919 struct ResolverHandle *rh;
920 struct RecordLookupHandle *rlh;
921 struct GNSNameRecordBlock *nrb;
922 uint32_t num_records;
924 char* rd_data = (char*)data;
928 rh = (struct ResolverHandle *)cls;
929 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
930 "GNS_PHASE_REC-%d: got dht result (size=%d)\n", rh->id, size);
932 //FIXME maybe check expiration here, check block type
935 rlh = (struct RecordLookupHandle *) rh->proc_cls;
936 nrb = (struct GNSNameRecordBlock*)data;
938 /* stop lookup and timeout task */
939 GNUNET_DHT_get_stop (rh->get_handle);
940 rh->get_handle = NULL;
942 if (rh->dht_heap_node != NULL)
944 GNUNET_CONTAINER_heap_remove_node(rh->dht_heap_node);
945 rh->dht_heap_node = NULL;
948 if (rh->timeout_task != GNUNET_SCHEDULER_NO_TASK)
950 GNUNET_SCHEDULER_cancel(rh->timeout_task);
951 rh->timeout_task = GNUNET_SCHEDULER_NO_TASK;
954 rh->get_handle = NULL;
955 name = (char*)&nrb[1];
956 num_records = ntohl(nrb->rd_count);
958 struct GNUNET_NAMESTORE_RecordData rd[num_records];
960 rd_data += strlen(name) + 1 + sizeof(struct GNSNameRecordBlock);
961 rd_size = size - strlen(name) - 1 - sizeof(struct GNSNameRecordBlock);
963 if (GNUNET_SYSERR == GNUNET_NAMESTORE_records_deserialize (rd_size,
968 GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
969 "GNS_PHASE_REC-%d: Error deserializing data!\n", rh->id);
973 for (i=0; i<num_records; i++)
975 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
976 "GNS_PHASE_REC-%d: Got name: %s (wanted %s)\n",
977 rh->id, name, rh->name);
978 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
979 "GNS_PHASE_REC-%d: Got type: %d (wanted %d)\n",
980 rh->id, rd[i].record_type, rlh->record_type);
981 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
982 "GNS_PHASE_REC-%d: Got data length: %d\n",
983 rh->id, rd[i].data_size);
984 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
985 "GNS_PHASE_REC-%d: Got flag %d\n",
986 rh->id, rd[i].flags);
988 if ((strcmp(name, rh->name) == 0) &&
989 (rd[i].record_type == rlh->record_type))
997 * FIXME check pubkey against existing key in namestore?
998 * https://gnunet.org/bugs/view.php?id=2179
1001 /* Save to namestore */
1002 GNUNET_NAMESTORE_record_put (namestore_handle,
1009 &on_namestore_record_put_result, //cont
1014 rh->proc(rh->proc_cls, rh, num_records, rd);
1016 rh->proc(rh->proc_cls, rh, 0, NULL);
1023 * Start DHT lookup for a (name -> query->record_type) record in
1024 * rh->authority's zone
1026 * @param rh the pending gns query context
1029 resolve_record_dht (struct ResolverHandle *rh)
1032 struct GNUNET_CRYPTO_ShortHashCode name_hash;
1033 struct GNUNET_HashCode lookup_key;
1034 struct GNUNET_HashCode name_hash_double;
1035 struct GNUNET_HashCode zone_hash_double;
1036 struct GNUNET_CRYPTO_HashAsciiEncoded lookup_key_string;
1037 struct RecordLookupHandle *rlh = (struct RecordLookupHandle *)rh->proc_cls;
1038 struct ResolverHandle *rh_heap_root;
1040 GNUNET_CRYPTO_short_hash(rh->name, strlen(rh->name), &name_hash);
1041 GNUNET_CRYPTO_short_hash_double(&name_hash, &name_hash_double);
1042 GNUNET_CRYPTO_short_hash_double(&rh->authority, &zone_hash_double);
1043 GNUNET_CRYPTO_hash_xor(&name_hash_double, &zone_hash_double, &lookup_key);
1044 GNUNET_CRYPTO_hash_to_enc (&lookup_key, &lookup_key_string);
1046 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1047 "GNS_PHASE_REC-%d: starting dht lookup for %s with key: %s\n",
1048 rh->id, rh->name, (char*)&lookup_key_string);
1050 //rh->timeout_task = GNUNET_SCHEDULER_NO_TASK;
1051 rh->dht_heap_node = NULL;
1053 if (rh->timeout.rel_value != GNUNET_TIME_UNIT_FOREVER_REL.rel_value)
1056 * Update timeout if necessary
1058 if (rh->timeout_task == GNUNET_SCHEDULER_NO_TASK)
1061 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1062 "GNS_PHASE_REC-%d: Adjusting timeout\n", rh->id);
1064 * Set timeout for authority lookup phase to 1/2
1066 rh->timeout_task = GNUNET_SCHEDULER_add_delayed(
1067 GNUNET_TIME_relative_divide(rh->timeout, 2),
1068 &handle_lookup_timeout,
1071 //rh->timeout_task = GNUNET_SCHEDULER_add_delayed (DHT_LOOKUP_TIMEOUT,
1072 // &dht_lookup_timeout,
1074 rh->timeout_cont = &dht_lookup_timeout;
1075 rh->timeout_cont_cls = rh;
1079 if (max_allowed_background_queries <=
1080 GNUNET_CONTAINER_heap_get_size (dht_lookup_heap))
1082 rh_heap_root = GNUNET_CONTAINER_heap_remove_root (dht_lookup_heap);
1083 GNUNET_DHT_get_stop(rh_heap_root->get_handle);
1084 rh_heap_root->get_handle = NULL;
1085 rh_heap_root->dht_heap_node = NULL;
1087 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1088 "GNS_PHASE_REC-%d: Replacing oldest background query for %s\n",
1089 rh->id, rh_heap_root->name);
1090 rh_heap_root->proc(rh_heap_root->proc_cls,
1095 rh->dht_heap_node = GNUNET_CONTAINER_heap_insert (dht_lookup_heap,
1097 GNUNET_TIME_absolute_get().abs_value);
1100 xquery = htonl(rlh->record_type);
1102 GNUNET_assert(rh->get_handle == NULL);
1103 rh->get_handle = GNUNET_DHT_get_start(dht_handle,
1104 GNUNET_BLOCK_TYPE_GNS_NAMERECORD,
1106 DHT_GNS_REPLICATION_LEVEL,
1110 &process_record_result_dht,
1117 * Namestore calls this function if we have record for this name.
1118 * (or with rd_count=0 to indicate no matches)
1120 * @param cls the pending query
1121 * @param key the key of the zone we did the lookup
1122 * @param expiration expiration date of the namestore entry
1123 * @param name the name for which we need an authority
1124 * @param rd_count the number of records with 'name'
1125 * @param rd the record data
1126 * @param signature the signature of the authority for the record data
1129 process_record_result_ns(void* cls,
1130 const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *key,
1131 struct GNUNET_TIME_Absolute expiration,
1132 const char *name, unsigned int rd_count,
1133 const struct GNUNET_NAMESTORE_RecordData *rd,
1134 const struct GNUNET_CRYPTO_RsaSignature *signature)
1136 struct ResolverHandle *rh;
1137 struct RecordLookupHandle *rlh;
1138 struct GNUNET_TIME_Relative remaining_time;
1139 struct GNUNET_CRYPTO_ShortHashCode zone;
1140 struct GNUNET_TIME_Absolute et;
1143 rh = (struct ResolverHandle *) cls;
1144 rlh = (struct RecordLookupHandle *)rh->proc_cls;
1145 GNUNET_CRYPTO_short_hash(key,
1146 sizeof(struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded),
1148 remaining_time = GNUNET_TIME_absolute_get_remaining (expiration);
1156 rh->status |= RSL_RECORD_EXISTS;
1158 if (remaining_time.rel_value == 0)
1160 rh->status |= RSL_RECORD_EXPIRED;
1167 * Lookup terminated and no results
1169 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1170 "GNS_PHASE_REC-%d: Namestore lookup for %s terminated without results\n",
1173 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1174 "GNS_PHASE_REC-%d: Record %s unknown in namestore\n",
1177 * Our zone and no result? Cannot resolve TT
1179 rh->proc(rh->proc_cls, rh, 0, NULL);
1185 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1186 "GNS_PHASE_REC-%d: Processing additional result %s from namestore\n",
1188 for (i=0; i<rd_count;i++)
1190 if (rd[i].record_type != rlh->record_type)
1193 if (ignore_pending_records &&
1194 (rd[i].flags & GNUNET_NAMESTORE_RF_PENDING))
1196 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1197 "GNS_PHASE_REC-%d: Record %s is awaiting user confirmation. Skipping\n",
1202 GNUNET_break (0 == (rd[i].flags & GNUNET_NAMESTORE_RF_RELATIVE_EXPIRATION));
1203 et.abs_value = rd[i].expiration_time;
1204 if ((GNUNET_TIME_absolute_get_remaining (et)).rel_value
1207 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1208 "GNS_PHASE_REC-%d: This record is expired. Skipping\n",
1218 if (rh->answered == 0)
1220 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1221 "GNS_PHASE_REC-%d: No answers found. This is odd!\n", rh->id);
1222 rh->proc(rh->proc_cls, rh, 0, NULL);
1226 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1227 "GNS_PHASE_REC-%d: Found %d answer(s) to query in %d records!\n",
1228 rh->id, rh->answered, rd_count);
1230 rh->proc(rh->proc_cls, rh, rd_count, rd);
1236 * VPN redirect result callback
1238 * @param cls the resolver handle
1239 * @param af the requested address family
1240 * @param address in_addr(6) respectively
1243 process_record_result_vpn (void* cls, int af, const void *address)
1245 struct ResolverHandle *rh = cls;
1246 struct RecordLookupHandle *rlh;
1247 struct GNUNET_NAMESTORE_RecordData rd;
1249 rlh = (struct RecordLookupHandle *)rh->proc_cls;
1251 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1252 "GNS_PHASE_REC_VPN-%d: Got answer from VPN to query!\n",
1256 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1257 "GNS_PHASE_REC-%d: Answer is IPv4!\n",
1259 if (rlh->record_type != GNUNET_GNS_RECORD_TYPE_A)
1261 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1262 "GNS_PHASE_REC-%d: Requested record is not IPv4!\n",
1264 rh->proc (rh->proc_cls, rh, 0, NULL);
1267 rd.record_type = GNUNET_GNS_RECORD_TYPE_A;
1268 rd.expiration_time = UINT64_MAX; /* FIXME: should probably pick something shorter... */
1270 rd.data_size = sizeof (struct in_addr);
1272 rh->proc (rh->proc_cls, rh, 1, &rd);
1275 else if (af == AF_INET6)
1277 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1278 "GNS_PHASE_REC-%d: Answer is IPv6!\n",
1280 if (rlh->record_type != GNUNET_GNS_RECORD_AAAA)
1282 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1283 "GNS_PHASE_REC-%d: Requested record is not IPv6!\n",
1285 rh->proc (rh->proc_cls, rh, 0, NULL);
1288 rd.record_type = GNUNET_GNS_RECORD_AAAA;
1289 rd.expiration_time = UINT64_MAX; /* FIXME: should probably pick something shorter... */
1291 rd.data_size = sizeof (struct in6_addr);
1293 rh->proc (rh->proc_cls, rh, 1, &rd);
1297 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1298 "GNS_PHASE_REC-%d: Got garbage from VPN!\n",
1300 rh->proc (rh->proc_cls, rh, 0, NULL);
1307 * @param rh resolver handle
1308 * @param rlh record lookup handle
1309 * @param rd_count number of results
1313 finish_lookup(struct ResolverHandle *rh,
1314 struct RecordLookupHandle* rlh,
1315 unsigned int rd_count,
1316 const struct GNUNET_NAMESTORE_RecordData *rd);
1319 * Process VPN lookup result for record
1321 * @param cls the record lookup handle
1322 * @param rh resolver handle
1323 * @param rd_count number of results (1)
1324 * @param rd record data containing the result
1327 handle_record_vpn (void* cls, struct ResolverHandle *rh,
1328 unsigned int rd_count,
1329 const struct GNUNET_NAMESTORE_RecordData *rd)
1331 struct RecordLookupHandle* rlh = (struct RecordLookupHandle*) cls;
1335 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1336 "GNS_PHASE_REC_VPN-%d: VPN returned no records. (status: %d)!\n",
1339 /* give up, cannot resolve */
1340 finish_lookup(rh, rlh, 0, NULL);
1341 free_resolver_handle(rh);
1345 /* results found yay */
1346 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1347 "GNS_PHASE_REC_VPN-%d: Record resolved from VPN!", rh->id);
1349 finish_lookup(rh, rlh, rd_count, rd);
1351 free_resolver_handle(rh);
1356 * Sends a UDP dns query to a nameserver specified in the rh
1358 * @param rh the resolver handle
1361 send_dns_packet (struct ResolverHandle *rh);
1365 handle_dns_resolver (void *cls,
1366 const struct sockaddr *addr,
1369 struct ResolverHandle *rh = cls;
1370 struct RecordLookupHandle *rlh = rh->proc_cls;
1371 struct GNUNET_NAMESTORE_RecordData rd;
1372 struct sockaddr_in *sai;
1373 struct sockaddr_in6 *sai6;
1377 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1378 "No address found in DNS!\n");
1379 finish_lookup (rh, rlh, 0, NULL);
1380 free_resolver_handle (rh);
1384 if (addrlen == sizeof (struct sockaddr_in))
1386 sai = (struct sockaddr_in*) addr;
1387 rd.record_type = GNUNET_GNS_RECORD_TYPE_A;
1388 rd.data_size = sizeof (struct in_addr);
1389 rd.data = &sai->sin_addr;
1393 sai6 = (struct sockaddr_in6*) addr;
1394 rd.record_type = GNUNET_GNS_RECORD_AAAA;
1395 rd.data_size = sizeof (struct in6_addr);
1396 rd.data = &sai6->sin6_addr;
1399 rd.expiration_time = UINT64_MAX; /* FIXME: should probably pick something shorter */
1402 finish_lookup (rh, rlh, 1, &rd);
1403 GNUNET_RESOLVER_request_cancel (rh->dns_resolver_handle);
1404 free_resolver_handle (rh);
1408 * Resolve DNS name via local stub resolver
1410 * @param rh the resolver handle
1413 resolve_dns_name (struct ResolverHandle *rh)
1415 struct RecordLookupHandle *rlh = rh->proc_cls;
1418 if ((rlh->record_type != GNUNET_GNS_RECORD_TYPE_A) &&
1419 (rlh->record_type != GNUNET_GNS_RECORD_AAAA))
1421 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1422 "Can only resolve A/AAAA via stub... abort\n");
1423 finish_lookup (rh, rlh, 0, NULL);
1424 free_resolver_handle (rh);
1428 if (rlh->record_type == GNUNET_GNS_RECORD_TYPE_A)
1433 //GNUNET_RESOLVER_connect (cfg); FIXME into init
1435 rh->dns_resolver_handle = GNUNET_RESOLVER_ip_get (rh->dns_name,
1438 &handle_dns_resolver,
1444 * Read DNS udp packet from socket
1446 * @param cls the resolver handle
1447 * @param tc task context
1450 read_dns_response (void *cls,
1451 const struct GNUNET_SCHEDULER_TaskContext *tc)
1453 struct ResolverHandle *rh = cls;
1454 struct RecordLookupHandle *rlh = rh->proc_cls;
1455 char buf[UINT16_MAX];
1457 struct sockaddr_in addr;
1459 struct GNUNET_DNSPARSER_Packet *packet;
1460 struct GNUNET_NAMESTORE_RecordData rd;
1461 int found_delegation = GNUNET_NO;
1462 int found_cname = GNUNET_NO;
1463 char* delegation_name = NULL;
1464 int zone_offset = 0;
1467 rh->dns_read_task = GNUNET_SCHEDULER_NO_TASK;
1468 if (0 == (tc->reason & GNUNET_SCHEDULER_REASON_READ_READY))
1470 /* timeout or shutdown */
1471 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1472 "Terminating DNS query\n");
1473 finish_lookup (rh, rlh, 0, NULL);
1474 GNUNET_NETWORK_socket_close (rh->dns_sock);
1475 free_resolver_handle (rh);
1479 addrlen = sizeof (addr);
1480 r = GNUNET_NETWORK_socket_recvfrom (rh->dns_sock,
1482 (struct sockaddr*) &addr,
1487 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "recvfrom");
1488 finish_lookup (rh, rlh, 0, NULL);
1489 GNUNET_NETWORK_socket_close (rh->dns_sock);
1490 free_resolver_handle (rh);
1494 packet = GNUNET_DNSPARSER_parse (buf, r);
1498 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1499 "Failed to parse DNS reply!\n");
1500 finish_lookup (rh, rlh, 0, NULL);
1501 GNUNET_NETWORK_socket_close (rh->dns_sock);
1502 free_resolver_handle (rh);
1506 for (i = 0; i < packet->num_answers; i++)
1508 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1509 "Got record type %d (want %d)\n",
1510 packet->answers[i].type,
1512 /* http://tools.ietf.org/html/rfc1034#section-3.6.2 */
1513 if (packet->answers[i].type == GNUNET_GNS_RECORD_TYPE_CNAME)
1515 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1516 "CNAME... restarting query with %s\n",
1517 packet->answers[i].data.hostname
1519 strcpy (rh->dns_name, packet->answers[i].data.hostname);
1520 found_cname = GNUNET_YES;
1521 //send_dns_packet (rh);
1522 //GNUNET_DNSPARSER_free_packet (packet);
1526 if ((packet->answers[i].type == rlh->record_type) &&
1527 (0 == strcmp (packet->answers[i].name, rh->dns_name)))
1529 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1531 rd.data = packet->answers[i].data.raw.data;
1532 rd.data_size = packet->answers[i].data.raw.data_len;
1533 rd.record_type = packet->answers[i].type;
1535 rd.expiration_time = packet->answers[i].expiration_time.abs_value;
1536 finish_lookup (rh, rlh, 1, &rd);
1537 GNUNET_NETWORK_socket_close (rh->dns_sock);
1538 GNUNET_DNSPARSER_free_packet (packet);
1539 free_resolver_handle (rh);
1544 if (GNUNET_YES == found_cname)
1546 zone_offset = strlen (rh->dns_name) - strlen (rh->dns_zone) - 1;
1548 if (0 > zone_offset)
1551 /* restart query with CNAME */
1552 if (0 == strcmp (rh->dns_name+zone_offset, rh->dns_zone))
1554 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1555 "Asking same server for %s\n", rh->dns_name);
1556 send_dns_packet (rh);
1560 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1561 "Trying system resolver for %s\n", rh->dns_name);
1562 resolve_dns_name (rh);
1565 GNUNET_DNSPARSER_free_packet (packet);
1569 for (i = 0; i < packet->num_authority_records; i++)
1572 if (packet->authority_records[i].type == GNUNET_GNS_RECORD_TYPE_NS)
1574 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1575 "Found NS delegation!\n");
1576 found_delegation = GNUNET_YES;
1577 delegation_name = packet->authority_records[i].data.hostname;
1582 for (i = 0; i < packet->num_additional_records; i++)
1584 if (found_delegation == GNUNET_NO)
1587 if ((packet->additional_records[i].type == GNUNET_GNS_RECORD_TYPE_A) &&
1588 (0 == strcmp (packet->additional_records[i].name, delegation_name)))
1590 GNUNET_assert (sizeof (struct in_addr) ==
1591 packet->authority_records[i].data.raw.data_len);
1593 rh->dns_addr.sin_addr =
1594 *((struct in_addr*)packet->authority_records[i].data.raw.data);
1595 send_dns_packet (rh);
1596 GNUNET_DNSPARSER_free_packet (packet);
1601 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1602 "Nothing useful in DNS reply!\n");
1603 finish_lookup (rh, rlh, 0, NULL);
1604 GNUNET_NETWORK_socket_close (rh->dns_sock);
1605 free_resolver_handle (rh);
1606 GNUNET_DNSPARSER_free_packet (packet);
1611 * Sends a UDP dns query to a nameserver specified in the rh
1613 * @param rh the request handle
1616 send_dns_packet (struct ResolverHandle *rh)
1618 struct GNUNET_NETWORK_FDSet *rset = GNUNET_NETWORK_fdset_create ();
1619 GNUNET_NETWORK_fdset_set (rset, rh->dns_sock);
1621 GNUNET_NETWORK_socket_sendto (rh->dns_sock,
1623 rh->dns_raw_packet_size,
1624 (struct sockaddr*)&rh->dns_addr,
1625 sizeof (struct sockaddr_in));
1627 rh->dns_read_task = GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_DEFAULT,
1628 rh->timeout, //FIXME less?
1634 GNUNET_NETWORK_fdset_destroy (rset);
1639 * The final phase of resoution.
1640 * We found a NS RR and want to resolve via DNS
1642 * @param rh the pending lookup handle
1643 * @param rd_count length of record data
1644 * @param rd record data containing VPN RR
1647 resolve_record_dns (struct ResolverHandle *rh,
1649 const struct GNUNET_NAMESTORE_RecordData *rd)
1651 struct GNUNET_DNSPARSER_Query query;
1652 struct GNUNET_DNSPARSER_Packet packet;
1653 struct GNUNET_DNSPARSER_Flags flags;
1654 struct in_addr dnsip;
1655 struct sockaddr_in addr;
1656 struct sockaddr *sa;
1658 struct RecordLookupHandle *rlh = rh->proc_cls;
1660 memset (&packet, 0, sizeof (struct GNUNET_DNSPARSER_Packet));
1662 /* We cancel here as to not include the ns lookup in the timeout */
1663 if (rh->timeout_task != GNUNET_SCHEDULER_NO_TASK)
1665 GNUNET_SCHEDULER_cancel(rh->timeout_task);
1666 rh->timeout_task = GNUNET_SCHEDULER_NO_TASK;
1668 /* Start shortening */
1669 if ((rh->priv_key != NULL) && is_canonical (rh->name))
1671 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1672 "GNS_PHASE_REC_DNS-%llu: Trying to shorten authority chain\n",
1674 start_shorten (rh->authority_chain_tail,
1678 for (i = 0; i < rd_count; i++)
1680 /* Synthesize dns name */
1681 if (rd[i].record_type == GNUNET_GNS_RECORD_TYPE_NS)
1683 strcpy (rh->dns_zone, (char*)rd[i].data);
1684 if (0 == strcmp (rh->name, ""))
1685 strcpy (rh->dns_name, (char*)rd[i].data);
1687 sprintf (rh->dns_name, "%s.%s", rh->name, (char*)rd[i].data);
1690 if (rd[i].record_type == GNUNET_GNS_RECORD_TYPE_A)
1691 dnsip = *((struct in_addr*)rd[i].data);
1694 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1695 "GNS_PHASE_REC_DNS-%llu: Looking up %s from %s\n",
1699 rh->dns_sock = GNUNET_NETWORK_socket_create (AF_INET, SOCK_DGRAM, 0);
1700 if (rh->dns_sock == NULL)
1702 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1703 "GNS_PHASE_REC_DNS-%llu: Error creating udp socket for dns!\n",
1705 finish_lookup (rh, rlh, 0, NULL);
1706 free_resolver_handle (rh);
1710 memset (&addr, 0, sizeof (struct sockaddr_in));
1711 sa = (struct sockaddr *) &addr;
1712 sa->sa_family = AF_INET;
1713 if (GNUNET_OK != GNUNET_NETWORK_socket_bind (rh->dns_sock,
1715 sizeof (struct sockaddr_in)))
1717 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1718 "GNS_PHASE_REC_DNS-%llu: Error binding udp socket for dns!\n",
1720 GNUNET_NETWORK_socket_close (rh->dns_sock);
1721 finish_lookup (rh, rlh, 0, NULL);
1722 free_resolver_handle (rh);
1726 /*TODO create dnsparser query, serialize, sendto, handle reply*/
1727 query.name = rh->dns_name;
1728 query.type = rlh->record_type;
1729 query.class = GNUNET_DNSPARSER_CLASS_INTERNET;
1730 memset (&flags, 0, sizeof (flags));
1731 flags.recursion_desired = 1;
1732 flags.checking_disabled = 1;
1733 packet.queries = &query;
1734 packet.answers = NULL;
1735 packet.authority_records = NULL;
1736 packet.num_queries = 1;
1737 packet.num_answers = 0;
1738 packet.num_authority_records = 0;
1739 packet.num_additional_records = 0;
1740 packet.flags = flags;
1742 if (GNUNET_OK != GNUNET_DNSPARSER_pack (&packet,
1744 &rh->dns_raw_packet,
1745 &rh->dns_raw_packet_size))
1747 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1748 "GNS_PHASE_REC_DNS-%llu: Creating raw dns packet!\n",
1750 GNUNET_NETWORK_socket_close (rh->dns_sock);
1751 finish_lookup (rh, rlh, 0, NULL);
1752 free_resolver_handle (rh);
1756 rh->dns_addr.sin_family = AF_INET;
1757 rh->dns_addr.sin_port = htons (53); //domain
1758 rh->dns_addr.sin_addr = dnsip;
1759 #if HAVE_SOCKADDR_IN_SIN_LEN
1760 rh->dns_addr.sin_len = (u_char) sizeof (struct sockaddr_in);
1763 send_dns_packet (rh);
1768 * The final phase of resoution.
1769 * We found a VPN RR and want to request an IPv4/6 address
1771 * @param rh the pending lookup handle
1772 * @param rd_count length of record data
1773 * @param rd record data containing VPN RR
1776 resolve_record_vpn (struct ResolverHandle *rh,
1778 const struct GNUNET_NAMESTORE_RecordData *rd)
1782 struct GNUNET_HashCode peer_id;
1783 struct GNUNET_CRYPTO_HashAsciiEncoded s_pid;
1784 struct GNUNET_HashCode serv_desc;
1785 struct GNUNET_CRYPTO_HashAsciiEncoded s_sd;
1787 size_t len = (sizeof (uint32_t) * 2) + (sizeof (struct GNUNET_HashCode) * 2);
1789 /* We cancel here as to not include the ns lookup in the timeout */
1790 if (rh->timeout_task != GNUNET_SCHEDULER_NO_TASK)
1792 GNUNET_SCHEDULER_cancel(rh->timeout_task);
1793 rh->timeout_task = GNUNET_SCHEDULER_NO_TASK;
1795 /* Start shortening */
1796 if ((rh->priv_key != NULL) && is_canonical (rh->name))
1798 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1799 "GNS_PHASE_REC_VPN-%llu: Trying to shorten authority chain\n",
1801 start_shorten (rh->authority_chain_tail,
1805 /* Extracting VPN information FIXME rd parsing with NS API?*/
1806 if (len != rd->data_size)
1808 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1809 "GNS_PHASE_REC_VPN-%llu: Error parsing VPN RR!\n",
1811 finish_lookup (rh, rh->proc_cls, 0, NULL);
1812 free_resolver_handle (rh);
1817 memcpy (&af, pos, sizeof (uint32_t));
1818 pos += sizeof (uint32_t);
1819 memcpy (&proto, pos, sizeof (uint32_t));
1820 pos += sizeof (uint32_t);
1821 memcpy (&s_pid, pos, sizeof (struct GNUNET_HashCode));
1822 pos += sizeof (struct GNUNET_HashCode);
1823 memcpy (&s_sd, pos, sizeof (struct GNUNET_HashCode));
1826 if ((GNUNET_OK != GNUNET_CRYPTO_hash_from_string ((char*)&s_pid, &peer_id)) ||
1827 (GNUNET_OK != GNUNET_CRYPTO_hash_from_string ((char*)&s_sd, &serv_desc)))
1829 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1830 "GNS_PHASE_REC_VPN-%llu: Error parsing VPN RR hashes!\n",
1832 finish_lookup (rh, rh->proc_cls, 0, NULL);
1833 free_resolver_handle (rh);
1837 rh->proc = &handle_record_vpn;
1839 if (NULL == vpn_handle)
1841 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1842 "GNS_PHASE_REC_VPN-%llu: VPN not connected!\n",
1844 finish_lookup (rh, rh->proc_cls, 0, NULL);
1845 free_resolver_handle (rh);
1850 rh->vpn_handle = GNUNET_VPN_redirect_to_peer (vpn_handle,
1852 (struct GNUNET_PeerIdentity*)&peer_id,
1855 GNUNET_TIME_UNIT_FOREVER_ABS, //FIXME
1856 &process_record_result_vpn,
1862 * The final phase of resolution.
1863 * rh->name is a name that is canonical and we do not have a delegation.
1864 * Query namestore for this record
1866 * @param rh the pending lookup handle
1869 resolve_record_ns(struct ResolverHandle *rh)
1871 struct RecordLookupHandle *rlh = (struct RecordLookupHandle *)rh->proc_cls;
1873 /* We cancel here as to not include the ns lookup in the timeout */
1874 if (rh->timeout_task != GNUNET_SCHEDULER_NO_TASK)
1876 GNUNET_SCHEDULER_cancel(rh->timeout_task);
1877 rh->timeout_task = GNUNET_SCHEDULER_NO_TASK;
1879 /* Start shortening */
1880 if ((rh->priv_key != NULL) && is_canonical (rh->name))
1882 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1883 "GNS_PHASE_REC-%llu: Trying to shorten authority chain\n",
1885 start_shorten (rh->authority_chain_tail,
1890 * Try to resolve this record in our namestore.
1891 * The name to resolve is now in rh->authority_name
1892 * since we tried to resolve it to an authority
1895 GNUNET_NAMESTORE_lookup_record(namestore_handle,
1899 &process_record_result_ns,
1906 * Handle timeout for DHT requests
1908 * @param cls the request handle as closure
1909 * @param tc the task context
1912 dht_authority_lookup_timeout(void *cls,
1913 const struct GNUNET_SCHEDULER_TaskContext *tc)
1915 struct ResolverHandle *rh = cls;
1916 struct RecordLookupHandle *rlh = rh->proc_cls;
1917 char new_name[MAX_DNS_NAME_LENGTH];
1919 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1920 "GNS_PHASE_DELEGATE_DHT-%llu: dht lookup for query %s (%ds)timed out.\n",
1921 rh->id, rh->authority_name, rh->timeout.rel_value);
1923 rh->status |= RSL_TIMED_OUT;
1925 rh->timeout_task = GNUNET_SCHEDULER_NO_TASK;
1927 GNUNET_DHT_get_stop (rh->get_handle);
1928 rh->get_handle = NULL;
1930 if (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)
1932 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1933 "GNS_PHASE_DELEGATE_DHT-%llu: Got shutdown\n",
1935 rh->proc(rh->proc_cls, rh, 0, NULL);
1939 if (strcmp(rh->name, "") == 0)
1942 * promote authority back to name and try to resolve record
1944 strcpy(rh->name, rh->authority_name);
1945 rh->proc(rh->proc_cls, rh, 0, NULL);
1950 * Start resolution in bg
1952 GNUNET_snprintf(new_name, MAX_DNS_NAME_LENGTH,
1953 "%s.%s.%s", rh->name, rh->authority_name, GNUNET_GNS_TLD);
1954 //strcpy(new_name, rh->name);
1955 //strcpy(new_name+strlen(new_name), ".");
1956 //memcpy(new_name+strlen(new_name), GNUNET_GNS_TLD, strlen(GNUNET_GNS_TLD));
1958 strcpy(rh->name, new_name);
1960 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1961 "GNS_PHASE_DELEGATE_DHT-%llu: Starting background query for %s type %d\n",
1962 rh->id, rh->name, rlh->record_type);
1964 gns_resolver_lookup_record(rh->authority,
1965 rh->private_local_zone,
1969 GNUNET_TIME_UNIT_FOREVER_REL,
1971 &background_lookup_result_processor,
1974 rh->proc(rh->proc_cls, rh, 0, NULL);
1978 static void resolve_delegation_dht(struct ResolverHandle *rh);
1981 static void resolve_delegation_ns(struct ResolverHandle *rh);
1985 * Namestore resolution for delegation finished. Processing result.
1987 * @param cls the closure
1988 * @param rh resolver handle
1989 * @param rd_count number of results (always 0)
1990 * @param rd record data (always NULL)
1993 handle_delegation_ns(void* cls, struct ResolverHandle *rh,
1994 unsigned int rd_count,
1995 const struct GNUNET_NAMESTORE_RecordData *rd);
1999 * This is a callback function that checks for key revocation
2001 * @param cls the pending query
2002 * @param key the key of the zone we did the lookup
2003 * @param expiration expiration date of the record data set in the namestore
2004 * @param name the name for which we need an authority
2005 * @param rd_count the number of records with 'name'
2006 * @param rd the record data
2007 * @param signature the signature of the authority for the record data
2010 process_pkey_revocation_result_ns (void *cls,
2011 const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *key,
2012 struct GNUNET_TIME_Absolute expiration,
2014 unsigned int rd_count,
2015 const struct GNUNET_NAMESTORE_RecordData *rd,
2016 const struct GNUNET_CRYPTO_RsaSignature *signature)
2018 struct ResolverHandle *rh = cls;
2019 struct GNUNET_TIME_Relative remaining_time;
2022 remaining_time = GNUNET_TIME_absolute_get_remaining (expiration);
2024 for (i = 0; i < rd_count; i++)
2026 if (rd[i].record_type == GNUNET_GNS_RECORD_REV)
2028 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2029 "GNS_PHASE_DELEGATE_REV-%llu: Zone has been revoked.\n",
2031 rh->status |= RSL_PKEY_REVOKED;
2032 rh->proc (rh->proc_cls, rh, 0, NULL);
2037 if ((name == NULL) ||
2038 (remaining_time.rel_value == 0))
2040 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2041 "GNS_PHASE_DELEGATE_REV-%llu: + Records don't exist or are expired.\n",
2044 if (rh->timeout.rel_value != GNUNET_TIME_UNIT_FOREVER_REL.rel_value)
2046 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2047 "GNS_PHASE_DELEGATE_REV-%d: Starting background lookup for %s type %d\n",
2048 rh->id, "+.gnunet", GNUNET_GNS_RECORD_REV);
2050 gns_resolver_lookup_record(rh->authority,
2051 rh->private_local_zone,
2052 GNUNET_GNS_RECORD_REV,
2055 GNUNET_TIME_UNIT_FOREVER_REL,
2057 &background_lookup_result_processor,
2061 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2062 "GNS_PHASE_DELEGATE_REV-%llu: Revocation checkpassed\n",
2065 * We are done with PKEY resolution if name is empty
2066 * else resolve again with new authority
2068 if (strcmp (rh->name, "") == 0)
2069 rh->proc (rh->proc_cls, rh, 0, NULL);
2071 resolve_delegation_ns (rh);
2077 * Function called when we get a result from the dht
2078 * for our query. Recursively tries to resolve authorities
2081 * @param cls the request handle
2082 * @param exp lifetime
2083 * @param key the key the record was stored under
2084 * @param get_path get path
2085 * @param get_path_length get path length
2086 * @param put_path put path
2087 * @param put_path_length put path length
2088 * @param type the block type
2089 * @param size the size of the record
2090 * @param data the record data
2093 process_delegation_result_dht(void* cls,
2094 struct GNUNET_TIME_Absolute exp,
2095 const struct GNUNET_HashCode * key,
2096 const struct GNUNET_PeerIdentity *get_path,
2097 unsigned int get_path_length,
2098 const struct GNUNET_PeerIdentity *put_path,
2099 unsigned int put_path_length,
2100 enum GNUNET_BLOCK_Type type,
2101 size_t size, const void *data)
2103 struct ResolverHandle *rh;
2104 struct GNSNameRecordBlock *nrb;
2105 uint32_t num_records;
2107 char* rd_data = (char*) data;
2110 struct GNUNET_CRYPTO_ShortHashCode zone, name_hash;
2111 struct GNUNET_HashCode zone_hash_double, name_hash_double;
2113 rh = (struct ResolverHandle *)cls;
2115 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2116 "GNS_PHASE_DELEGATE_DHT-%llu: Got DHT result\n", rh->id);
2121 nrb = (struct GNSNameRecordBlock*)data;
2123 /* stop dht lookup and timeout task */
2124 GNUNET_DHT_get_stop (rh->get_handle);
2126 rh->get_handle = NULL;
2128 if (rh->dht_heap_node != NULL)
2130 GNUNET_CONTAINER_heap_remove_node(rh->dht_heap_node);
2131 rh->dht_heap_node = NULL;
2134 num_records = ntohl(nrb->rd_count);
2135 name = (char*)&nrb[1];
2137 struct GNUNET_NAMESTORE_RecordData rd[num_records];
2139 rd_data += strlen(name) + 1 + sizeof(struct GNSNameRecordBlock);
2140 rd_size = size - strlen(name) - 1 - sizeof(struct GNSNameRecordBlock);
2142 if (GNUNET_SYSERR == GNUNET_NAMESTORE_records_deserialize (rd_size,
2147 GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
2148 "GNS_PHASE_DELEGATE_DHT-%llu: Error deserializing data!\n",
2153 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2154 "GNS_PHASE_DELEGATE_DHT-%llu: Got name: %s (wanted %s)\n",
2155 rh->id, name, rh->authority_name);
2156 for (i=0; i<num_records; i++)
2159 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2160 "GNS_PHASE_DELEGATE_DHT-%llu: Got name: %s (wanted %s)\n",
2161 rh->id, name, rh->authority_name);
2162 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2163 "GNS_PHASE_DELEGATE_DHT-%llu: Got type: %d (wanted %d)\n",
2164 rh->id, rd[i].record_type, GNUNET_GNS_RECORD_PKEY);
2165 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2166 "GNS_PHASE_DELEGATE_DHT-%llu: Got data length: %d\n",
2167 rh->id, rd[i].data_size);
2168 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2169 "GNS_PHASE_DELEGATE_DHT-%llu: Got flag %d\n",
2170 rh->id, rd[i].flags);
2172 if ((rd[i].record_type == GNUNET_GNS_RECORD_VPN) ||
2173 (rd[i].record_type == GNUNET_GNS_RECORD_TYPE_NS) ||
2174 (rd[i].record_type == GNUNET_GNS_RECORD_TYPE_CNAME))
2177 * This is a VPN,NS,CNAME entry. Let namestore handle this after caching
2179 if (strcmp(rh->name, "") == 0)
2180 strcpy(rh->name, rh->authority_name);
2182 GNUNET_snprintf(rh->name, MAX_DNS_NAME_LENGTH, "%s.%s",
2183 rh->name, rh->authority_name); //FIXME ret
2188 if ((strcmp(name, rh->authority_name) == 0) &&
2189 (rd[i].record_type == GNUNET_GNS_RECORD_PKEY))
2191 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2192 "GNS_PHASE_DELEGATE_DHT-%llu: Authority found in DHT\n",
2195 memcpy(&rh->authority, rd[i].data, sizeof(struct GNUNET_CRYPTO_ShortHashCode));
2196 struct AuthorityChain *auth =
2197 GNUNET_malloc(sizeof(struct AuthorityChain));
2198 auth->zone = rh->authority;
2199 memset(auth->name, 0, strlen(rh->authority_name)+1);
2200 strcpy(auth->name, rh->authority_name);
2201 GNUNET_CONTAINER_DLL_insert (rh->authority_chain_head,
2202 rh->authority_chain_tail,
2205 /** try to import pkey if private key available */
2206 //if (rh->priv_key && is_canonical (rh->name))
2207 // process_discovered_authority(name, auth->zone,
2208 // rh->authority_chain_tail->zone,
2215 GNUNET_CRYPTO_short_hash(name, strlen(name), &name_hash);
2216 GNUNET_CRYPTO_short_hash_double(&name_hash, &name_hash_double);
2217 GNUNET_CRYPTO_hash_xor(key, &name_hash_double, &zone_hash_double);
2218 GNUNET_CRYPTO_short_hash_from_truncation (&zone_hash_double, &zone);
2220 /* Save to namestore */
2221 if (0 != GNUNET_CRYPTO_short_hash_cmp(&rh->authority_chain_tail->zone,
2224 GNUNET_NAMESTORE_record_put (namestore_handle,
2231 &on_namestore_record_put_result, //cont
2241 * FIXME in this case. should we ask namestore again?
2243 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2244 "GNS_PHASE_DELEGATE_DHT-%llu: Answer from DHT for %s. Yet to resolve: %s\n",
2245 rh->id, rh->authority_name, rh->name);
2247 if (strcmp(rh->name, "") == 0)
2249 /* Start shortening */
2250 if ((rh->priv_key != NULL) && is_canonical (rh->name))
2252 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2253 "GNS_PHASE_DELEGATE_DHT-%llu: Trying to shorten authority chain\n",
2255 start_shorten (rh->authority_chain_tail,
2260 rh->proc = &handle_delegation_ns;
2262 /* Check for key revocation and delegate */
2263 GNUNET_NAMESTORE_lookup_record (namestore_handle,
2266 GNUNET_GNS_RECORD_REV,
2267 &process_pkey_revocation_result_ns,
2270 /*if (strcmp(rh->name, "") == 0)
2272 if ((rh->priv_key != NULL) && is_canonical (rh->name))
2274 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2275 "GNS_PHASE_DELEGATE_DHT-%llu: Trying to shorten authority chain\n",
2277 start_shorten (rh->authority_chain_tail,
2281 rh->proc(rh->proc_cls, rh, 0, NULL);
2285 rh->proc = &handle_delegation_ns;
2286 resolve_delegation_ns (rh);
2293 * No pkey but name exists
2296 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2297 "GNS_PHASE_DELEGATE_DHT-%llu: Adding %s back to %s\n",
2298 rh->id, rh->authority_name, rh->name);
2299 if (strcmp(rh->name, "") == 0)
2300 strcpy(rh->name, rh->authority_name);
2302 GNUNET_snprintf(rh->name, MAX_DNS_NAME_LENGTH, "%s.%s",
2303 rh->name, rh->authority_name); //FIXME ret
2305 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2306 "GNS_PHASE_DELEGATE_DHT-%llu: %s restored\n", rh->id, rh->name);
2307 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2308 "GNS_PHASE_DELEGATE_DHT-%llu: DHT authority lookup found no match!\n",
2310 rh->proc(rh->proc_cls, rh, 0, NULL);
2313 #define MAX_SOA_LENGTH sizeof(uint32_t)+sizeof(uint32_t)+sizeof(uint32_t)+sizeof(uint32_t)\
2314 +(MAX_DNS_NAME_LENGTH*2)
2315 #define MAX_MX_LENGTH sizeof(uint16_t)+MAX_DNS_NAME_LENGTH
2319 expand_plus(char** dest, char* src, char* repl)
2322 unsigned int s_len = strlen(src)+1;
2324 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2325 "GNS_POSTPROCESS: Got %s to expand with %s\n", src, repl);
2329 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2330 "GNS_POSTPROCESS: %s to short\n", src);
2332 /* no postprocessing */
2333 memcpy(*dest, src, s_len+1);
2337 if (0 == strcmp(src+s_len-3, ".+"))
2339 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2340 "GNS_POSTPROCESS: Expanding .+ in %s\n", src);
2341 memset(*dest, 0, s_len+strlen(repl)+strlen(GNUNET_GNS_TLD));
2343 pos = *dest+s_len-2;
2345 pos += strlen(repl);
2346 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2347 "GNS_POSTPROCESS: Expanded to %s\n", *dest);
2351 memcpy(*dest, src, s_len+1);
2359 finish_lookup(struct ResolverHandle *rh,
2360 struct RecordLookupHandle* rlh,
2361 unsigned int rd_count,
2362 const struct GNUNET_NAMESTORE_RecordData *rd)
2365 char new_rr_data[MAX_DNS_NAME_LENGTH];
2366 char new_mx_data[MAX_MX_LENGTH];
2367 char new_soa_data[MAX_SOA_LENGTH];
2368 struct GNUNET_NAMESTORE_RecordData p_rd[rd_count];
2371 unsigned int offset;
2373 if (rh->timeout_task != GNUNET_SCHEDULER_NO_TASK)
2375 GNUNET_SCHEDULER_cancel(rh->timeout_task);
2376 rh->timeout_task = GNUNET_SCHEDULER_NO_TASK;
2380 memcpy(p_rd, rd, rd_count*sizeof(struct GNUNET_NAMESTORE_RecordData));
2382 for (i = 0; i < rd_count; i++)
2385 if (rd[i].record_type != GNUNET_GNS_RECORD_TYPE_NS &&
2386 rd[i].record_type != GNUNET_GNS_RECORD_TYPE_CNAME &&
2387 rd[i].record_type != GNUNET_GNS_RECORD_MX &&
2388 rd[i].record_type != GNUNET_GNS_RECORD_TYPE_SOA)
2390 p_rd[i].data = rd[i].data;
2395 * for all those records we 'should'
2396 * also try to resolve the A/AAAA records (RFC1035)
2397 * This is a feature and not important
2400 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2401 "GNS_POSTPROCESS: Postprocessing\n");
2403 if (strcmp(rh->name, "+") == 0)
2404 repl_string = rlh->name;
2406 repl_string = rlh->name+strlen(rh->name)+1;
2409 if (rd[i].record_type == GNUNET_GNS_RECORD_MX)
2411 memcpy(new_mx_data, (char*)rd[i].data, sizeof(uint16_t));
2412 offset = sizeof(uint16_t);
2413 pos = new_mx_data+offset;
2414 expand_plus(&pos, (char*)rd[i].data+sizeof(uint16_t),
2416 offset += strlen(new_mx_data+sizeof(uint16_t))+1;
2417 p_rd[i].data = new_mx_data;
2418 p_rd[i].data_size = offset;
2420 else if (rd[i].record_type == GNUNET_GNS_RECORD_TYPE_SOA)
2422 /* expand mname and rname */
2424 expand_plus(&pos, (char*)rd[i].data, repl_string);
2425 offset = strlen(new_soa_data)+1;
2426 pos = new_soa_data+offset;
2427 expand_plus(&pos, (char*)rd[i].data+offset, repl_string);
2428 offset += strlen(new_soa_data+offset)+1;
2429 /* cpy the 4 numbers serial refresh retry and expire */
2430 memcpy(new_soa_data+offset, (char*)rd[i].data+offset, sizeof(uint32_t)*5);
2431 offset += sizeof(uint32_t)*5;
2432 p_rd[i].data_size = offset;
2433 p_rd[i].data = new_soa_data;
2438 expand_plus(&pos, (char*)rd[i].data, repl_string);
2439 p_rd[i].data_size = strlen(new_rr_data)+1;
2440 p_rd[i].data = new_rr_data;
2445 rlh->proc(rlh->proc_cls, rd_count, p_rd);
2451 * Process DHT lookup result for record.
2453 * @param cls the closure
2454 * @param rh resolver handle
2455 * @param rd_count number of results
2456 * @param rd record data
2459 handle_record_dht(void* cls, struct ResolverHandle *rh,
2460 unsigned int rd_count,
2461 const struct GNUNET_NAMESTORE_RecordData *rd)
2463 struct RecordLookupHandle* rlh;
2465 rlh = (struct RecordLookupHandle*)cls;
2468 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2469 "GNS_PHASE_REC-%d: No records for %s found in DHT. Aborting\n",
2471 /* give up, cannot resolve */
2472 finish_lookup(rh, rlh, 0, NULL);
2473 free_resolver_handle(rh);
2477 /* results found yay */
2478 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2479 "GNS_PHASE_REC-%d: Record resolved from DHT!", rh->id);
2481 finish_lookup(rh, rlh, rd_count, rd);
2482 free_resolver_handle(rh);
2490 * Process namestore lookup result for record.
2492 * @param cls the closure
2493 * @param rh resolver handle
2494 * @param rd_count number of results
2495 * @param rd record data
2498 handle_record_ns (void* cls, struct ResolverHandle *rh,
2499 unsigned int rd_count,
2500 const struct GNUNET_NAMESTORE_RecordData *rd)
2502 struct RecordLookupHandle* rlh;
2503 rlh = (struct RecordLookupHandle*) cls;
2506 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2507 "GNS_PHASE_REC-%d: NS returned no records. (status: %d)!\n",
2512 * There are 5 conditions that have to met for us to consult the DHT:
2513 * 1. The entry in the DHT is RSL_RECORD_EXPIRED OR
2514 * 2. No entry in the NS existed AND
2515 * 3. The zone queried is not the local resolver's zone AND
2516 * 4. The name that was looked up is '+'
2517 * because if it was any other canonical name we either already queried
2518 * the DHT for the authority in the authority lookup phase (and thus
2519 * would already have an entry in the NS for the record)
2520 * 5. We are not in cache only mode
2522 if (( ((rh->status & RSL_RECORD_EXPIRED) != 0) ||
2523 ((rh->status & RSL_RECORD_EXISTS) == 0) ) &&
2524 GNUNET_CRYPTO_short_hash_cmp(&rh->authority_chain_head->zone,
2525 &rh->private_local_zone) &&
2526 (strcmp(rh->name, "+") == 0) &&
2527 (rh->only_cached == GNUNET_NO))
2529 rh->proc = &handle_record_dht;
2530 resolve_record_dht(rh);
2533 /* give up, cannot resolve */
2534 finish_lookup(rh, rlh, 0, NULL);
2535 free_resolver_handle(rh);
2539 /* results found yay */
2540 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2541 "GNS_PHASE_REC-%d: Record resolved from namestore!", rh->id);
2543 finish_lookup(rh, rlh, rd_count, rd);
2545 free_resolver_handle(rh);
2551 * Move one level up in the domain hierarchy and return the
2552 * passed top level domain.
2554 * @param name the domain
2555 * @param dest the destination where the tld will be put
2558 pop_tld(char* name, char* dest)
2562 if (is_canonical(name))
2569 for (len = strlen(name); len > 0; len--)
2571 if (*(name+len) == '.')
2581 strcpy(dest, (name+len+1));
2585 * Checks if name is in tld
2587 * @param name the name to check
2588 * @param tld the TLD to check for
2589 * @return GNUNET_YES or GNUNET_NO
2592 is_tld(const char* name, const char* tld)
2596 if (strlen(name) <= strlen(tld))
2601 offset = strlen(name)-strlen(tld);
2602 if (strcmp(name+offset, tld) != 0)
2604 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2605 "%s is not in .%s TLD\n", name, tld);
2612 * DHT resolution for delegation finished. Processing result.
2614 * @param cls the closure
2615 * @param rh resolver handle
2616 * @param rd_count number of results (always 0)
2617 * @param rd record data (always NULL)
2620 handle_delegation_dht(void* cls, struct ResolverHandle *rh,
2621 unsigned int rd_count,
2622 const struct GNUNET_NAMESTORE_RecordData *rd)
2624 struct RecordLookupHandle* rlh;
2625 rlh = (struct RecordLookupHandle*) cls;
2628 if (strcmp(rh->name, "") == 0)
2630 if ((rlh->record_type == GNUNET_GNS_RECORD_PKEY))
2632 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2633 "GNS_PHASE_DELEGATE_DHT-%llu: Resolved queried PKEY via DHT.\n",
2635 finish_lookup(rh, rlh, rd_count, rd);
2636 free_resolver_handle(rh);
2639 /* We resolved full name for delegation. resolving record */
2640 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2641 "GNS_PHASE_DELEGATE_DHT-%llu: Resolved full name for delegation via DHT.\n",
2643 strcpy(rh->name, "+\0");
2644 rh->proc = &handle_record_ns;
2645 resolve_record_ns(rh);
2650 * we still have some left
2652 if (is_canonical(rh->name))
2654 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2655 "GNS_PHASE_DELEGATE_DHT-%llu: Resolving canonical record %s in ns\n",
2658 rh->proc = &handle_record_ns;
2659 resolve_record_ns(rh);
2662 /* give up, cannot resolve */
2663 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2664 "GNS_PHASE_DELEGATE_DHT-%llu: Cannot fully resolve delegation for %s via DHT!\n",
2666 finish_lookup(rh, rlh, 0, NULL);
2667 free_resolver_handle(rh);
2672 * Start DHT lookup for a name -> PKEY (compare NS) record in
2673 * rh->authority's zone
2675 * @param rh the pending gns query
2678 resolve_delegation_dht(struct ResolverHandle *rh)
2681 struct GNUNET_CRYPTO_ShortHashCode name_hash;
2682 struct GNUNET_HashCode name_hash_double;
2683 struct GNUNET_HashCode zone_hash_double;
2684 struct GNUNET_HashCode lookup_key;
2685 struct ResolverHandle *rh_heap_root;
2687 pop_tld(rh->name, rh->authority_name);
2688 GNUNET_CRYPTO_short_hash(rh->authority_name,
2689 strlen(rh->authority_name),
2691 GNUNET_CRYPTO_short_hash_double(&name_hash, &name_hash_double);
2692 GNUNET_CRYPTO_short_hash_double(&rh->authority, &zone_hash_double);
2693 GNUNET_CRYPTO_hash_xor(&name_hash_double, &zone_hash_double, &lookup_key);
2695 rh->dht_heap_node = NULL;
2697 if (rh->timeout.rel_value != GNUNET_TIME_UNIT_FOREVER_REL.rel_value)
2699 //rh->timeout_task = GNUNET_SCHEDULER_add_delayed (DHT_LOOKUP_TIMEOUT,
2700 // &dht_authority_lookup_timeout,
2702 rh->timeout_cont = &dht_authority_lookup_timeout;
2703 rh->timeout_cont_cls = rh;
2707 if (max_allowed_background_queries <=
2708 GNUNET_CONTAINER_heap_get_size (dht_lookup_heap))
2710 /* terminate oldest lookup */
2711 rh_heap_root = GNUNET_CONTAINER_heap_remove_root (dht_lookup_heap);
2712 GNUNET_DHT_get_stop(rh_heap_root->get_handle);
2713 rh_heap_root->dht_heap_node = NULL;
2715 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2716 "GNS_PHASE_DELEGATE_DHT-%llu: Replacing oldest background query for %s\n",
2717 rh->id, rh_heap_root->authority_name);
2719 rh_heap_root->proc(rh_heap_root->proc_cls,
2724 rh->dht_heap_node = GNUNET_CONTAINER_heap_insert (dht_lookup_heap,
2726 GNUNET_TIME_absolute_get().abs_value);
2729 xquery = htonl(GNUNET_GNS_RECORD_PKEY);
2731 GNUNET_assert(rh->get_handle == NULL);
2732 rh->get_handle = GNUNET_DHT_get_start(dht_handle,
2733 GNUNET_BLOCK_TYPE_GNS_NAMERECORD,
2735 DHT_GNS_REPLICATION_LEVEL,
2739 &process_delegation_result_dht,
2746 * Namestore resolution for delegation finished. Processing result.
2748 * @param cls the closure
2749 * @param rh resolver handle
2750 * @param rd_count number of results (always 0)
2751 * @param rd record data (always NULL)
2754 handle_delegation_ns (void* cls, struct ResolverHandle *rh,
2755 unsigned int rd_count,
2756 const struct GNUNET_NAMESTORE_RecordData *rd)
2758 struct RecordLookupHandle* rlh;
2759 rlh = (struct RecordLookupHandle*) cls;
2762 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2763 "GNS_PHASE_DELEGATE_NS-%llu: Resolution status: %d.\n",
2764 rh->id, rh->status);
2766 if (rh->status & RSL_PKEY_REVOKED)
2768 finish_lookup (rh, rlh, 0, NULL);
2769 free_resolver_handle (rh);
2773 if (strcmp(rh->name, "") == 0)
2776 /* We resolved full name for delegation. resolving record */
2777 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2778 "GNS_PHASE_DELEGATE_NS-%llu: Resolved full name for delegation.\n",
2780 if (rh->status & RSL_CNAME_FOUND)
2782 if (rlh->record_type == GNUNET_GNS_RECORD_TYPE_CNAME)
2784 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2785 "GNS_PHASE_DELEGATE_NS-%llu: Resolved queried CNAME in NS.\n",
2787 strcpy (rh->name, rh->authority_name);
2788 finish_lookup (rh, rlh, rd_count, rd);
2789 free_resolver_handle (rh);
2794 if (is_tld ((char*)rd->data, GNUNET_GNS_TLD_PLUS))
2796 s_len = strlen (rd->data) - 2;
2797 memcpy (rh->name, rd->data, s_len);
2798 rh->name[s_len] = '\0';
2799 resolve_delegation_ns (rh);
2802 else if (is_tld ((char*)rd->data, GNUNET_GNS_TLD_ZKEY))
2804 gns_resolver_lookup_record (rh->authority,
2805 rh->private_local_zone,
2814 free_resolver_handle (rh);
2820 strcpy (rh->dns_name, (char*)rd->data);
2821 resolve_dns_name (rh);
2826 else if (rh->status & RSL_DELEGATE_VPN)
2828 if (rlh->record_type == GNUNET_GNS_RECORD_VPN)
2830 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2831 "GNS_PHASE_DELEGATE_NS-%llu: Resolved queried VPNRR in NS.\n",
2833 finish_lookup(rh, rlh, rd_count, rd);
2834 free_resolver_handle(rh);
2837 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2838 "GNS_PHASE_DELEGATE_NS-%llu: VPN delegation starting.\n",
2840 GNUNET_assert (NULL != rd);
2841 rh->proc = &handle_record_vpn;
2842 resolve_record_vpn (rh, rd_count, rd);
2845 else if (rh->status & RSL_DELEGATE_NS)
2847 if (rlh->record_type == GNUNET_GNS_RECORD_TYPE_NS)
2849 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2850 "GNS_PHASE_DELEGATE_NS-%llu: Resolved queried NSRR in NS.\n",
2852 finish_lookup(rh, rlh, rd_count, rd);
2853 free_resolver_handle(rh);
2857 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2858 "GNS_PHASE_DELEGATE_NS-%llu: NS delegation starting.\n",
2860 GNUNET_assert (NULL != rd);
2861 rh->proc = &handle_record_ns;
2862 resolve_record_dns (rh, rd_count, rd);
2865 else if (rh->status & RSL_DELEGATE_PKEY)
2867 if (rh->status & RSL_PKEY_REVOKED)
2869 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2870 "GNS_PHASE_DELEGATE_NS-%llu: Resolved PKEY is revoked.\n",
2872 finish_lookup (rh, rlh, 0, NULL);
2873 free_resolver_handle (rh);
2876 else if (rlh->record_type == GNUNET_GNS_RECORD_PKEY)
2878 GNUNET_assert(rd_count == 1);
2879 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2880 "GNS_PHASE_DELEGATE_NS-%llu: Resolved queried PKEY in NS.\n",
2882 finish_lookup(rh, rlh, rd_count, rd);
2883 free_resolver_handle(rh);
2887 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2888 "GNS_PHASE_DELEGATE_NS-%llu: Resolving record +\n",
2890 strcpy(rh->name, "+\0");
2891 rh->proc = &handle_record_ns;
2892 resolve_record_ns(rh);
2896 if (rh->status & RSL_DELEGATE_NS)
2898 if (rlh->record_type == GNUNET_GNS_RECORD_TYPE_NS)
2900 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2901 "GNS_PHASE_DELEGATE_NS-%llu: Resolved queried NSRR in NS.\n",
2903 finish_lookup(rh, rlh, rd_count, rd);
2904 free_resolver_handle(rh);
2908 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2909 "GNS_PHASE_DELEGATE_NS-%llu: NS delegation starting.\n",
2911 GNUNET_assert (NULL != rd);
2912 rh->proc = &handle_record_ns;
2913 resolve_record_dns (rh, rd_count, rd);
2918 * we still have some left
2919 * check if authority in ns is fresh
2921 * or we are authority
2923 if (((rh->status & RSL_RECORD_EXISTS) && (!(rh->status & RSL_RECORD_EXPIRED)))
2924 || !GNUNET_CRYPTO_short_hash_cmp(&rh->authority_chain_head->zone,
2925 &rh->private_local_zone))
2927 if (is_canonical(rh->name))
2929 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2930 "GNS_PHASE_DELEGATE_NS-%llu: Resolving canonical record %s\n",
2933 rh->proc = &handle_record_ns;
2934 resolve_record_ns(rh);
2938 /* give up, cannot resolve */
2939 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2940 "GNS_PHASE_DELEGATE_NS-%llu: Cannot fully resolve delegation for %s!\n",
2943 finish_lookup(rh, rlh, rd_count, rd);
2944 //rlh->proc(rlh->proc_cls, 0, NULL);
2949 if (rh->only_cached == GNUNET_YES)
2951 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2952 "GNS_PHASE_DELEGATE_NS-%llu: Only cache resolution, no result\n",
2954 finish_lookup(rh, rlh, rd_count, rd);
2958 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2959 "GNS_PHASE_DELEGATE_NS-%llu: Trying to resolve delegation for %s via DHT\n",
2961 rh->proc = &handle_delegation_dht;
2962 resolve_delegation_dht(rh);
2967 * This is a callback function that should give us only PKEY
2968 * records. Used to query the namestore for the authority (PKEY)
2969 * for 'name'. It will recursively try to resolve the
2970 * authority for a given name from the namestore.
2972 * @param cls the pending query
2973 * @param key the key of the zone we did the lookup
2974 * @param expiration expiration date of the record data set in the namestore
2975 * @param name the name for which we need an authority
2976 * @param rd_count the number of records with 'name'
2977 * @param rd the record data
2978 * @param signature the signature of the authority for the record data
2981 process_delegation_result_ns (void* cls,
2982 const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *key,
2983 struct GNUNET_TIME_Absolute expiration,
2985 unsigned int rd_count,
2986 const struct GNUNET_NAMESTORE_RecordData *rd,
2987 const struct GNUNET_CRYPTO_RsaSignature *signature)
2989 struct ResolverHandle *rh;
2990 struct GNUNET_TIME_Relative remaining_time;
2991 struct GNUNET_CRYPTO_ShortHashCode zone;
2992 char new_name[MAX_DNS_NAME_LENGTH];
2994 struct GNUNET_TIME_Absolute et;
2996 rh = (struct ResolverHandle *)cls;
2997 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2998 "GNS_PHASE_DELEGATE_NS-%llu: Got %d records from authority lookup\n",
3001 GNUNET_CRYPTO_short_hash(key,
3002 sizeof(struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded),
3004 remaining_time = GNUNET_TIME_absolute_get_remaining (expiration);
3010 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
3011 "GNS_PHASE_DELEGATE_NS-%llu: Records with name %s exist.\n",
3013 rh->status |= RSL_RECORD_EXISTS;
3015 if (remaining_time.rel_value == 0)
3017 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
3018 "GNS_PHASE_DELEGATE_NS-%llu: Record set %s expired.\n",
3020 rh->status |= RSL_RECORD_EXPIRED;
3025 * No authority found in namestore.
3030 * We did not find an authority in the namestore
3035 * Promote this authority back to a name maybe it is
3038 if (strcmp(rh->name, "") == 0)
3040 /* simply promote back */
3041 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
3042 "GNS_PHASE_DELEGATE_NS-%llu: Promoting %s back to name\n",
3043 rh->id, rh->authority_name);
3044 strcpy(rh->name, rh->authority_name);
3048 /* add back to existing name */
3049 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
3050 "GNS_PHASE_DELEGATE_NS-%llu: Adding %s back to %s\n",
3051 rh->id, rh->authority_name, rh->name);
3052 //memset(new_name, 0, strlen(rh->name) + strlen(rh->authority_name) + 2);
3053 GNUNET_snprintf(new_name, MAX_DNS_NAME_LENGTH, "%s.%s",
3054 rh->name, rh->authority_name);
3055 //strcpy(new_name, rh->name);
3056 //strcpy(new_name+strlen(new_name), ".");
3057 //strcpy(new_name+strlen(new_name), rh->authority_name);
3058 strcpy(rh->name, new_name);
3059 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
3060 "GNS_PHASE_DELEGATE_NS-%llu: %s restored\n", rh->id, rh->name);
3062 rh->proc(rh->proc_cls, rh, 0, NULL);
3067 * We found an authority that may be able to help us
3068 * move on with query
3069 * Note only 1 pkey should have been returned.. anything else would be strange
3071 for (i=0; i<rd_count;i++)
3075 * A CNAME. Like regular DNS this means the is no other record for this
3078 if (rd[i].record_type == GNUNET_GNS_RECORD_TYPE_CNAME)
3080 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
3081 "GNS_PHASE_DELEGATE_NS-%llu: CNAME found.\n",
3084 rh->status |= RSL_CNAME_FOUND;
3085 rh->proc (rh->proc_cls, rh, rd_count, rd);
3092 if (rd[i].record_type == GNUNET_GNS_RECORD_VPN)
3094 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
3095 "GNS_PHASE_DELEGATE_NS-%llu: VPN found.\n",
3097 rh->status |= RSL_DELEGATE_VPN;
3098 rh->proc (rh->proc_cls, rh, rd_count, rd);
3104 * FIXME make optional
3106 if (rd[i].record_type == GNUNET_GNS_RECORD_TYPE_NS)
3108 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
3109 "GNS_PHASE_DELEGATE_NS-%llu: NS found.\n",
3111 rh->status |= RSL_DELEGATE_NS;
3112 rh->proc (rh->proc_cls, rh, rd_count, rd);
3116 if (rd[i].record_type != GNUNET_GNS_RECORD_PKEY)
3119 rh->status |= RSL_DELEGATE_PKEY;
3121 if (ignore_pending_records &&
3122 (rd[i].flags & GNUNET_NAMESTORE_RF_PENDING))
3124 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
3125 "GNS_PHASE_DELEGATE_NS-%llu: PKEY for %s is pending user confirmation.\n",
3131 GNUNET_break (0 == (rd[i].flags & GNUNET_NAMESTORE_RF_RELATIVE_EXPIRATION));
3132 et.abs_value = rd[i].expiration_time;
3133 if ((GNUNET_TIME_absolute_get_remaining (et)).rel_value
3136 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
3137 "GNS_PHASE_DELEGATE_NS-%llu: This pkey is expired.\n",
3139 if (remaining_time.rel_value == 0)
3141 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
3142 "GNS_PHASE_DELEGATE_NS-%llu: This dht entry is expired.\n",
3144 rh->authority_chain_head->fresh = 0;
3145 rh->proc(rh->proc_cls, rh, 0, NULL);
3153 * Resolve rest of query with new authority
3155 GNUNET_assert(rd[i].record_type == GNUNET_GNS_RECORD_PKEY);
3156 memcpy(&rh->authority, rd[i].data,
3157 sizeof(struct GNUNET_CRYPTO_ShortHashCode));
3158 struct AuthorityChain *auth = GNUNET_malloc(sizeof(struct AuthorityChain));
3159 auth->zone = rh->authority;
3160 memset(auth->name, 0, strlen(rh->authority_name)+1);
3161 strcpy(auth->name, rh->authority_name);
3162 GNUNET_CONTAINER_DLL_insert (rh->authority_chain_head,
3163 rh->authority_chain_tail,
3166 /* Check for key revocation and delegate */
3167 GNUNET_NAMESTORE_lookup_record (namestore_handle,
3170 GNUNET_GNS_RECORD_REV,
3171 &process_pkey_revocation_result_ns,
3180 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
3181 "GNS_PHASE_DELEGATE_NS-%llu: Authority lookup and no PKEY...\n", rh->id);
3183 * If we have found some records for the LAST label
3184 * we return the results. Else null.
3186 if (strcmp(rh->name, "") == 0)
3188 /* Start shortening */
3189 if ((rh->priv_key != NULL) && is_canonical (rh->name))
3191 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3192 "GNS_PHASE_DELEGATE_NS-%llu: Trying to shorten authority chain\n",
3194 start_shorten (rh->authority_chain_tail,
3197 /* simply promote back */
3198 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
3199 "GNS_PHASE_DELEGATE_NS-%llu: Promoting %s back to name\n",
3200 rh->id, rh->authority_name);
3201 strcpy(rh->name, rh->authority_name);
3202 rh->proc(rh->proc_cls, rh, rd_count, rd);
3206 rh->proc(rh->proc_cls, rh, 0, NULL);
3212 * Resolve the delegation chain for the request in our namestore
3214 * @param rh the resolver handle
3217 resolve_delegation_ns (struct ResolverHandle *rh)
3219 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
3220 "GNS_PHASE_DELEGATE_NS-%llu: Resolving delegation for %s\n",
3222 pop_tld(rh->name, rh->authority_name);
3223 GNUNET_NAMESTORE_lookup_record(namestore_handle,
3226 GNUNET_GNS_RECORD_ANY,
3227 &process_delegation_result_ns,
3234 * Lookup of a record in a specific zone
3235 * calls lookup result processor on result
3237 * @param zone the root zone
3238 * @param pzone the private local zone
3239 * @param record_type the record type to look up
3240 * @param name the name to look up
3241 * @param key a private key for use with PSEU import (can be NULL)
3242 * @param timeout timeout for resolution
3243 * @param only_cached GNUNET_NO to only check locally not DHT for performance
3244 * @param proc the processor to call on result
3245 * @param cls the closure to pass to proc
3248 gns_resolver_lookup_record (struct GNUNET_CRYPTO_ShortHashCode zone,
3249 struct GNUNET_CRYPTO_ShortHashCode pzone,
3250 uint32_t record_type,
3252 struct GNUNET_CRYPTO_RsaPrivateKey *key,
3253 struct GNUNET_TIME_Relative timeout,
3255 RecordLookupProcessor proc,
3258 struct ResolverHandle *rh;
3259 struct RecordLookupHandle* rlh;
3260 char string_hash[MAX_DNS_LABEL_LENGTH];
3261 char nzkey[MAX_DNS_LABEL_LENGTH];
3262 char* nzkey_ptr = nzkey;
3264 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3265 "Starting resolution for %s (type=%d)!\n",
3269 if (is_canonical((char*)name) && (strcmp(GNUNET_GNS_TLD, name) != 0))
3271 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3272 "%s is canonical and not gnunet -> cannot resolve!\n", name);
3277 rlh = GNUNET_malloc(sizeof(struct RecordLookupHandle));
3278 rh = GNUNET_malloc(sizeof (struct ResolverHandle));
3280 rh->authority = zone;
3284 rh->timeout = timeout;
3285 rh->get_handle = NULL;
3286 rh->private_local_zone = pzone;
3287 rh->only_cached = only_cached;
3291 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3292 "No shorten key for resolution\n");
3295 if (timeout.rel_value != GNUNET_TIME_UNIT_FOREVER_REL.rel_value)
3298 * Set timeout for authority lookup phase to 1/2
3300 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3301 "Timeout for lookup set to %ds\n", rh->timeout.rel_value);
3302 rh->timeout_task = GNUNET_SCHEDULER_add_delayed(
3303 GNUNET_TIME_relative_divide(timeout, 2),
3304 &handle_lookup_timeout,
3306 rh->timeout_cont = &dht_authority_lookup_timeout;
3307 rh->timeout_cont_cls = rh;
3311 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "No timeout for query!\n");
3312 rh->timeout_task = GNUNET_SCHEDULER_NO_TASK;
3315 if (strcmp(GNUNET_GNS_TLD, name) == 0)
3318 * Only 'gnunet' given
3320 strcpy(rh->name, "\0");
3324 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3325 "Checking for TLD...\n");
3326 if (is_zkey_tld(name) == GNUNET_YES)
3328 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3331 * This is a zkey tld
3332 * build hash and use as initial authority
3335 strlen(name)-strlen(GNUNET_GNS_TLD_ZKEY));
3336 memcpy(rh->name, name,
3337 strlen(name)-strlen(GNUNET_GNS_TLD_ZKEY) - 1);
3338 pop_tld(rh->name, string_hash);
3340 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3341 "ZKEY is %s!\n", string_hash);
3343 GNUNET_STRINGS_utf8_toupper(string_hash, &nzkey_ptr);
3345 if (GNUNET_OK != GNUNET_CRYPTO_short_hash_from_string(nzkey,
3348 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
3349 "Cannot convert ZKEY %s to hash!\n", string_hash);
3359 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3362 * Presumably GNUNET tld
3365 strlen(name)-strlen(GNUNET_GNS_TLD));
3366 memcpy(rh->name, name,
3367 strlen(name)-strlen(GNUNET_GNS_TLD) - 1);
3372 * Initialize authority chain
3374 rh->authority_chain_head = GNUNET_malloc(sizeof(struct AuthorityChain));
3375 rh->authority_chain_head->prev = NULL;
3376 rh->authority_chain_head->next = NULL;
3377 rh->authority_chain_tail = rh->authority_chain_head;
3378 rh->authority_chain_head->zone = rh->authority;
3381 * Copy original query into lookup handle
3383 rlh->record_type = record_type;
3384 memset(rlh->name, 0, strlen(name) + 1);
3385 strcpy(rlh->name, name);
3387 rlh->proc_cls = cls;
3389 rh->proc = &handle_delegation_ns;
3390 resolve_delegation_ns(rh);
3393 /******** END Record Resolver ***********/
3396 * Callback calles by namestore for a zone to name
3399 * @param cls the closure
3400 * @param zone_key the zone we queried
3401 * @param expire the expiration time of the name
3402 * @param name the name found or NULL
3403 * @param rd_len number of records for the name
3404 * @param rd the record data (PKEY) for the name
3405 * @param signature the signature for the record data
3408 process_zone_to_name_shorten_root (void *cls,
3409 const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *zone_key,
3410 struct GNUNET_TIME_Absolute expire,
3412 unsigned int rd_len,
3413 const struct GNUNET_NAMESTORE_RecordData *rd,
3414 const struct GNUNET_CRYPTO_RsaSignature *signature);
3418 * Callback called by namestore for a zone to name
3421 * @param cls the closure
3422 * @param zone_key the zone we queried
3423 * @param expire the expiration time of the name
3424 * @param name the name found or NULL
3425 * @param rd_len number of records for the name
3426 * @param rd the record data (PKEY) for the name
3427 * @param signature the signature for the record data
3430 process_zone_to_name_shorten_shorten (void *cls,
3431 const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *zone_key,
3432 struct GNUNET_TIME_Absolute expire,
3434 unsigned int rd_len,
3435 const struct GNUNET_NAMESTORE_RecordData *rd,
3436 const struct GNUNET_CRYPTO_RsaSignature *signature)
3438 struct ResolverHandle *rh = (struct ResolverHandle *)cls;
3439 struct NameShortenHandle* nsh = (struct NameShortenHandle*)rh->proc_cls;
3440 struct AuthorityChain *next_authority;
3442 char result[MAX_DNS_NAME_LENGTH];
3443 char tmp_name[MAX_DNS_NAME_LENGTH];
3446 /* we found a match in our own root zone */
3449 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
3450 "result strlen %d\n", strlen(name));
3451 answer_len = strlen(rh->name) + strlen(name) + strlen(GNUNET_GNS_TLD) + 3;
3452 memset(result, 0, answer_len);
3454 if (strlen(rh->name) > 0)
3456 sprintf (result, "%s.%s.%s.%s.%s",
3458 nsh->shorten_zone_name, nsh->private_zone_name,
3463 sprintf (result, "%s.%s.%s.%s", name,
3464 nsh->shorten_zone_name, nsh->private_zone_name,
3468 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
3469 "Found shorten result %s\n", result);
3470 if (strlen (nsh->result) > strlen (result))
3471 strcpy (nsh->result, result);
3473 else if (GNUNET_CRYPTO_short_hash_cmp(&rh->authority_chain_head->zone,
3474 nsh->shorten_zone) == 0)
3477 * This is our zone append .gnunet unless name is empty
3478 * (it shouldn't be, usually FIXME what happens if we
3479 * shorten to our zone to a "" record??)
3482 sprintf (result, "%s.%s.%s.%s",
3484 nsh->shorten_zone_name, nsh->private_zone_name,
3486 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
3487 "Our zone: Found %s as shorten result\n", result);
3489 if (strlen (nsh->result) > strlen (result))
3490 strcpy (nsh->result, result);
3491 //nsh->proc(nsh->proc_cls, result);
3493 //free_resolver_handle(rh);
3500 * continue with next authority if exists
3502 if ((rh->authority_chain_head->next == NULL))
3504 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3505 "Sending %s as shorten result\n", nsh->result);
3506 nsh->proc(nsh->proc_cls, nsh->result);
3508 free_resolver_handle (rh);
3511 next_authority = rh->authority_chain_head;
3513 GNUNET_snprintf(tmp_name, MAX_DNS_NAME_LENGTH,
3514 "%s.%s", rh->name, next_authority->name);
3516 strcpy(rh->name, tmp_name);
3517 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
3518 "No PSEU found for authority %s. Promoting back: %s\n",
3519 next_authority->name, rh->name);
3521 GNUNET_CONTAINER_DLL_remove(rh->authority_chain_head,
3522 rh->authority_chain_tail,
3525 GNUNET_NAMESTORE_zone_to_name (namestore_handle,
3526 &rh->authority_chain_tail->zone,
3527 &rh->authority_chain_head->zone,
3528 &process_zone_to_name_shorten_root,
3533 * Callback calles by namestore for a zone to name
3536 * @param cls the closure
3537 * @param zone_key the zone we queried
3538 * @param expire the expiration time of the name
3539 * @param name the name found or NULL
3540 * @param rd_len number of records for the name
3541 * @param rd the record data (PKEY) for the name
3542 * @param signature the signature for the record data
3545 process_zone_to_name_shorten_private (void *cls,
3546 const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *zone_key,
3547 struct GNUNET_TIME_Absolute expire,
3549 unsigned int rd_len,
3550 const struct GNUNET_NAMESTORE_RecordData *rd,
3551 const struct GNUNET_CRYPTO_RsaSignature *signature)
3553 struct ResolverHandle *rh = (struct ResolverHandle *)cls;
3554 struct NameShortenHandle* nsh = (struct NameShortenHandle*)rh->proc_cls;
3555 struct AuthorityChain *next_authority;
3557 char result[MAX_DNS_NAME_LENGTH];
3558 char tmp_name[MAX_DNS_NAME_LENGTH];
3561 /* we found a match in our own root zone */
3564 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
3565 "result strlen %d\n", strlen(name));
3566 answer_len = strlen(rh->name) + strlen(name) + strlen(GNUNET_GNS_TLD) + 3;
3567 memset(result, 0, answer_len);
3569 if (strlen(rh->name) > 0)
3571 sprintf (result, "%s.%s.%s", rh->name, name, GNUNET_GNS_TLD);
3575 sprintf (result, "%s.%s", name, GNUNET_GNS_TLD);
3578 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
3579 "Found shorten result %s\n", result);
3580 if (strlen (nsh->result) > strlen (result))
3581 strcpy (nsh->result, result);
3583 else if (GNUNET_CRYPTO_short_hash_cmp(&rh->authority_chain_head->zone,
3584 nsh->private_zone) == 0)
3587 * This is our zone append .gnunet unless name is empty
3588 * (it shouldn't be, usually FIXME what happens if we
3589 * shorten to our zone to a "" record??)
3592 sprintf (result, "%s.%s.%s",
3593 rh->name, nsh->private_zone_name, GNUNET_GNS_TLD);
3594 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
3595 "Our private zone: Found %s as shorten result %s\n", result);
3596 if (strlen (nsh->result) > strlen (result))
3597 strcpy (nsh->result, result);
3600 if (nsh->shorten_zone != NULL)
3602 /* backtrack authorities for names in priv zone */
3603 GNUNET_NAMESTORE_zone_to_name (namestore_handle,
3605 &rh->authority_chain_head->zone,
3606 &process_zone_to_name_shorten_shorten,
3613 * continue with next authority if exists
3615 if ((rh->authority_chain_head->next == NULL))
3617 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
3618 "Sending %s as shorten result\n", nsh->result);
3619 nsh->proc(nsh->proc_cls, nsh->result);
3621 free_resolver_handle(rh);
3624 next_authority = rh->authority_chain_head;
3626 GNUNET_snprintf(tmp_name, MAX_DNS_NAME_LENGTH,
3627 "%s.%s", rh->name, next_authority->name);
3629 strcpy(rh->name, tmp_name);
3630 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
3631 "No PSEU found for authority %s. Promoting back: %s\n",
3632 next_authority->name, rh->name);
3634 GNUNET_CONTAINER_DLL_remove(rh->authority_chain_head,
3635 rh->authority_chain_tail,
3638 GNUNET_NAMESTORE_zone_to_name (namestore_handle,
3639 &rh->authority_chain_tail->zone,
3640 &rh->authority_chain_head->zone,
3641 &process_zone_to_name_shorten_root,
3647 * Callback calles by namestore for a zone to name
3650 * @param cls the closure
3651 * @param zone_key the zone we queried
3652 * @param expire the expiration time of the name
3653 * @param name the name found or NULL
3654 * @param rd_len number of records for the name
3655 * @param rd the record data (PKEY) for the name
3656 * @param signature the signature for the record data
3659 process_zone_to_name_shorten_root (void *cls,
3660 const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *zone_key,
3661 struct GNUNET_TIME_Absolute expire,
3663 unsigned int rd_len,
3664 const struct GNUNET_NAMESTORE_RecordData *rd,
3665 const struct GNUNET_CRYPTO_RsaSignature *signature)
3667 struct ResolverHandle *rh = (struct ResolverHandle *)cls;
3668 struct NameShortenHandle* nsh = (struct NameShortenHandle*)rh->proc_cls;
3669 struct AuthorityChain *next_authority;
3671 char result[MAX_DNS_NAME_LENGTH];
3672 char tmp_name[MAX_DNS_NAME_LENGTH];
3675 /* we found a match in our own root zone */
3678 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
3679 "result strlen %d\n", strlen(name));
3680 answer_len = strlen(rh->name) + strlen(name) + strlen(GNUNET_GNS_TLD) + 3;
3681 memset(result, 0, answer_len);
3683 if (strlen(rh->name) > 0)
3685 sprintf (result, "%s.%s.%s", rh->name, name, GNUNET_GNS_TLD);
3689 sprintf (result, "%s.%s", name, GNUNET_GNS_TLD);
3692 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
3693 "Found shorten result %s\n", result);
3694 if (strlen (nsh->result) > strlen (result))
3695 strcpy (nsh->result, result);
3697 else if (GNUNET_CRYPTO_short_hash_cmp(&rh->authority_chain_head->zone,
3698 nsh->root_zone) == 0)
3701 * This is our zone append .gnunet unless name is empty
3702 * (it shouldn't be, usually FIXME what happens if we
3703 * shorten to our zone to a "" record??)
3706 sprintf (result, "%s.%s", rh->name, GNUNET_GNS_TLD);
3707 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
3708 "Our zone: Found %s as shorten result\n", result);
3709 if (strlen (nsh->result) > strlen (result))
3710 strcpy (nsh->result, result);
3713 if (nsh->private_zone != NULL)
3715 /* backtrack authorities for names in priv zone */
3716 GNUNET_NAMESTORE_zone_to_name (namestore_handle,
3718 &rh->authority_chain_head->zone,
3719 &process_zone_to_name_shorten_private,
3726 * continue with next authority if exists
3728 if ((rh->authority_chain_head->next == NULL))
3730 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
3731 "Sending %s as shorten result\n", nsh->result);
3732 nsh->proc(nsh->proc_cls, nsh->result);
3734 free_resolver_handle(rh);
3737 next_authority = rh->authority_chain_head;
3739 GNUNET_snprintf(tmp_name, MAX_DNS_NAME_LENGTH,
3740 "%s.%s", rh->name, next_authority->name);
3742 strcpy(rh->name, tmp_name);
3743 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
3744 "No PSEU found for authority %s. Promoting back: %s\n",
3745 next_authority->name, rh->name);
3747 GNUNET_CONTAINER_DLL_remove(rh->authority_chain_head,
3748 rh->authority_chain_tail,
3751 GNUNET_NAMESTORE_zone_to_name (namestore_handle,
3752 &rh->authority_chain_tail->zone,
3753 &rh->authority_chain_head->zone,
3754 &process_zone_to_name_shorten_root,
3761 * Process result from namestore delegation lookup
3762 * for shorten operation
3764 * @param cls the client shorten handle
3765 * @param rh the resolver handle
3766 * @param rd_count number of results (0)
3767 * @param rd data (NULL)
3770 handle_delegation_ns_shorten (void* cls,
3771 struct ResolverHandle *rh,
3773 const struct GNUNET_NAMESTORE_RecordData *rd)
3775 struct NameShortenHandle *nsh;
3776 char result[MAX_DNS_NAME_LENGTH];
3778 nsh = (struct NameShortenHandle *)cls;
3781 * At this point rh->name contains the part of the name
3782 * that we do not have a PKEY in our namestore to resolve.
3783 * The authority chain in the resolver handle is now
3784 * useful to backtrack if needed
3787 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
3788 "PKEY resolved as far as possible in ns up to %s!\n", rh->name);
3789 memset(result, 0, sizeof (result));
3791 if (GNUNET_CRYPTO_short_hash_cmp(&rh->authority_chain_head->zone,
3792 nsh->root_zone) == 0)
3795 * This is our zone append .gnunet unless name is empty
3796 * (it shouldn't be, usually FIXME what happens if we
3797 * shorten to our zone to a "" record??)
3800 sprintf (result, "%s.%s", rh->name, GNUNET_GNS_TLD);
3801 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
3802 "Our zone: Found %s as shorten result\n", result);
3804 if (strlen (nsh->result) > strlen (result))
3805 strcpy (nsh->result, result);
3808 else if (GNUNET_CRYPTO_short_hash_cmp(&rh->authority_chain_head->zone,
3809 nsh->private_zone) == 0)
3812 * This is our zone append .gnunet unless name is empty
3813 * (it shouldn't be, usually FIXME what happens if we
3814 * shorten to our zone to a "" record??)
3817 sprintf (result, "%s.%s.%s",
3818 rh->name, nsh->private_zone_name, GNUNET_GNS_TLD);
3819 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
3820 "Our zone: Found %s as shorten result %s\n", result);
3822 if (strlen (nsh->result) > strlen (result))
3823 strcpy (nsh->result, result);
3825 else if (GNUNET_CRYPTO_short_hash_cmp(&rh->authority_chain_head->zone,
3826 nsh->shorten_zone) == 0)
3829 * This is our zone append .gnunet unless name is empty
3830 * (it shouldn't be, usually FIXME what happens if we
3831 * shorten to our zone to a "" record??)
3834 sprintf (result, "%s.%s.%s",
3835 rh->name, nsh->private_zone_name, GNUNET_GNS_TLD);
3836 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
3837 "Our zone: Found %s as shorten result\n", result);
3839 if (strlen (nsh->result) > strlen (result))
3840 strcpy (nsh->result, result);
3844 /* backtrack authorities for names */
3845 GNUNET_NAMESTORE_zone_to_name (namestore_handle,
3847 &rh->authority_chain_head->zone,
3848 &process_zone_to_name_shorten_root,
3855 * Callback calles by namestore for a zone to name
3858 * @param cls the closure
3859 * @param zone_key the zone we queried
3860 * @param expire the expiration time of the name
3861 * @param name the name found or NULL
3862 * @param rd_len number of records for the name
3863 * @param rd the record data (PKEY) for the name
3864 * @param signature the signature for the record data
3867 process_zone_to_name_zkey(void *cls,
3868 const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *zone_key,
3869 struct GNUNET_TIME_Absolute expire,
3871 unsigned int rd_len,
3872 const struct GNUNET_NAMESTORE_RecordData *rd,
3873 const struct GNUNET_CRYPTO_RsaSignature *signature)
3875 struct ResolverHandle *rh = cls;
3876 struct NameShortenHandle *nsh = rh->proc_cls;
3877 struct GNUNET_CRYPTO_ShortHashAsciiEncoded enc;
3878 char new_name[MAX_DNS_NAME_LENGTH];
3880 /* zkey not in our zone */
3884 * In this case we have not given this PKEY a name (yet)
3885 * It is either just not in our zone or not even cached
3886 * Since we do not know at this point we will not try to shorten
3887 * because PKEY import will happen if the user follows the zkey
3890 GNUNET_CRYPTO_short_hash_to_enc ((struct GNUNET_CRYPTO_ShortHashCode*)rd,
3892 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
3893 "No name found for zkey %s returning verbatim!\n", enc);
3894 if (strcmp(rh->name, "") != 0)
3895 GNUNET_snprintf(new_name, MAX_DNS_NAME_LENGTH, "%s.%s.%s",
3896 rh->name, enc, GNUNET_GNS_TLD_ZKEY);
3898 GNUNET_snprintf(new_name, MAX_DNS_NAME_LENGTH, "%s.%s",
3899 enc, GNUNET_GNS_TLD_ZKEY);
3901 strcpy (nsh->result, new_name);
3903 nsh->proc(nsh->proc_cls, new_name);
3905 free_resolver_handle(rh);
3909 if (strcmp(rh->name, "") != 0)
3910 GNUNET_snprintf(new_name, MAX_DNS_NAME_LENGTH, "%s.%s",
3913 strcpy(new_name, name);
3915 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
3916 "Continue shorten for %s!\n", new_name);
3918 strcpy(rh->name, new_name);
3920 rh->authority_chain_head = GNUNET_malloc(sizeof(struct AuthorityChain));
3921 rh->authority_chain_tail = rh->authority_chain_head;
3922 rh->authority_chain_head->zone = rh->authority;
3925 /* Start delegation resolution in our namestore */
3926 resolve_delegation_ns(rh);
3931 * Shorten api from resolver
3933 * @param zone the root zone to use
3934 * @param pzone the private zone to use
3935 * @param szone the shorten zone to use
3936 * @param name the name to shorten
3937 * @param private_zone_name name of the private zone
3938 * @param shorten_zone_name name of the shorten zone
3939 * @param proc the processor to call with result
3940 * @param proc_cls closure to pass to proc
3943 gns_resolver_shorten_name (struct GNUNET_CRYPTO_ShortHashCode *zone,
3944 struct GNUNET_CRYPTO_ShortHashCode *pzone,
3945 struct GNUNET_CRYPTO_ShortHashCode *szone,
3947 const char* private_zone_name,
3948 const char* shorten_zone_name,
3949 ShortenResultProcessor proc,
3952 struct ResolverHandle *rh;
3953 struct NameShortenHandle *nsh;
3954 char string_hash[MAX_DNS_LABEL_LENGTH];
3955 struct GNUNET_CRYPTO_ShortHashCode zkey;
3956 char nzkey[MAX_DNS_LABEL_LENGTH];
3957 char* nzkey_ptr = nzkey;
3960 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3961 "Starting shorten for %s!\n", name);
3963 if (is_canonical ((char*)name))
3965 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3966 "%s is canonical. Returning verbatim\n", name);
3967 proc (proc_cls, name);
3971 nsh = GNUNET_malloc (sizeof (struct NameShortenHandle));
3974 nsh->proc_cls = proc_cls;
3975 nsh->root_zone = zone;
3976 nsh->private_zone = pzone;
3977 nsh->shorten_zone = szone;
3978 strcpy (nsh->private_zone_name, private_zone_name);
3979 strcpy (nsh->shorten_zone_name, shorten_zone_name);
3980 strcpy (nsh->result, name);
3982 rh = GNUNET_malloc (sizeof (struct ResolverHandle));
3983 rh->authority = *zone;
3985 rh->priv_key = NULL;
3986 rh->proc = &handle_delegation_ns_shorten;
3989 rh->private_local_zone = *zone;
3991 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3992 "Checking for TLD...\n");
3993 if (is_zkey_tld (name) == GNUNET_YES)
3995 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3998 * This is a zkey tld
3999 * build hash and use as initial authority
4002 memset (rh->name, 0,
4003 strlen (name)-strlen (GNUNET_GNS_TLD_ZKEY));
4004 memcpy (rh->name, name,
4005 strlen(name)-strlen (GNUNET_GNS_TLD_ZKEY) - 1);
4006 pop_tld (rh->name, string_hash);
4008 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
4009 "ZKEY is %s!\n", string_hash);
4011 GNUNET_STRINGS_utf8_toupper (string_hash, &nzkey_ptr);
4013 if (GNUNET_OK != GNUNET_CRYPTO_short_hash_from_string (nzkey,
4016 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
4017 "Cannot convert ZKEY %s to hash!\n", nzkey);
4020 proc (proc_cls, name);
4024 GNUNET_NAMESTORE_zone_to_name (namestore_handle,
4027 &process_zone_to_name_zkey,
4034 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
4037 * Presumably GNUNET tld
4039 memset (rh->name, 0,
4040 strlen (name)-strlen (GNUNET_GNS_TLD));
4041 memcpy (rh->name, name,
4042 strlen (name)-strlen (GNUNET_GNS_TLD) - 1);
4045 rh->authority_chain_head = GNUNET_malloc (sizeof (struct AuthorityChain));
4046 rh->authority_chain_tail = rh->authority_chain_head;
4047 rh->authority_chain_head->zone = *zone;
4050 /* Start delegation resolution in our namestore */
4051 resolve_delegation_ns (rh);
4054 /*********** END NAME SHORTEN ********************/
4058 * Process result from namestore delegation lookup
4059 * for get authority operation
4061 * @param cls the client get auth handle
4062 * @param rh the resolver handle
4063 * @param rd_count number of results (0)
4064 * @param rd data (NULL)
4067 handle_delegation_result_ns_get_auth(void* cls,
4068 struct ResolverHandle *rh,
4070 const struct GNUNET_NAMESTORE_RecordData *rd)
4072 struct GetNameAuthorityHandle* nah;
4073 char result[MAX_DNS_NAME_LENGTH];
4076 nah = (struct GetNameAuthorityHandle*) rh->proc_cls;
4079 * At this point rh->name contains the part of the name
4080 * that we do not have a PKEY in our namestore to resolve.
4081 * The authority chain in the resolver handle is now
4082 * useful to backtrack if needed
4085 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
4086 "PKEY resolved as far as possible in ns up to %s!\n", rh->name);
4088 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
4089 "Building response!\n");
4090 if (is_canonical(rh->name))
4093 * We successfully resolved the authority in the ns
4094 * FIXME for our purposes this is fine
4095 * but maybe we want to have an api that also looks
4096 * into the dht (i.e. option in message)
4098 if (strlen(rh->name) > strlen(nah->name))
4100 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
4101 "Record name longer than original lookup name... odd!\n");
4105 answer_len = strlen(nah->name) - strlen(rh->name)
4106 + strlen(GNUNET_GNS_TLD) + 1;
4107 memset(result, 0, answer_len);
4108 strcpy(result, nah->name + strlen(rh->name) + 1);
4110 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
4111 "Got authority result %s\n", result);
4113 nah->proc(nah->proc_cls, result);
4115 free_resolver_handle(rh);
4119 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
4120 "Unable to resolve authority for remaining %s!\n", rh->name);
4121 nah->proc(nah->proc_cls, "");
4123 free_resolver_handle(rh);
4131 * Tries to resolve the authority for name
4134 * @param zone the root zone to look up for
4135 * @param pzone the private local zone
4136 * @param name the name to lookup up
4137 * @param proc the processor to call when finished
4138 * @param proc_cls the closure to pass to the processor
4141 gns_resolver_get_authority(struct GNUNET_CRYPTO_ShortHashCode zone,
4142 struct GNUNET_CRYPTO_ShortHashCode pzone,
4144 GetAuthorityResultProcessor proc,
4147 struct ResolverHandle *rh;
4148 struct GetNameAuthorityHandle *nah;
4150 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
4151 "Starting authority resolution for %s!\n", name);
4153 nah = GNUNET_malloc(sizeof (struct GetNameAuthorityHandle));
4154 rh = GNUNET_malloc(sizeof (struct ResolverHandle));
4155 rh->authority = zone;
4157 rh->private_local_zone = pzone;
4159 if (strcmp(GNUNET_GNS_TLD, name) == 0)
4161 strcpy(rh->name, "\0");
4166 strlen(name)-strlen(GNUNET_GNS_TLD));
4167 memcpy(rh->name, name,
4168 strlen(name)-strlen(GNUNET_GNS_TLD) - 1);
4171 memset(nah->name, 0,
4173 strcpy(nah->name, name);
4175 rh->authority_chain_head = GNUNET_malloc(sizeof(struct AuthorityChain));
4176 rh->authority_chain_tail = rh->authority_chain_head;
4177 rh->authority_chain_head->zone = zone;
4178 rh->proc = &handle_delegation_result_ns_get_auth;
4179 rh->proc_cls = (void*)nah;
4182 nah->proc_cls = proc_cls;
4184 /* Start delegation resolution in our namestore */
4185 resolve_delegation_ns(rh);
4189 /******** END GET AUTHORITY *************/
4191 /* end of gnunet-service-gns_resolver.c */