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;
2761 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2762 "GNS_PHASE_DELEGATE_NS-%llu: Resolution status: %d.\n",
2763 rh->id, rh->status);
2765 if (rh->status & RSL_PKEY_REVOKED)
2767 finish_lookup (rh, rlh, 0, NULL);
2768 free_resolver_handle (rh);
2772 if (strcmp(rh->name, "") == 0)
2775 /* We resolved full name for delegation. resolving record */
2776 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2777 "GNS_PHASE_DELEGATE_NS-%llu: Resolved full name for delegation.\n",
2779 if (rh->status & RSL_CNAME_FOUND)
2781 if (rlh->record_type == GNUNET_GNS_RECORD_TYPE_CNAME)
2783 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2784 "GNS_PHASE_DELEGATE_NS-%llu: Resolved queried CNAME in NS.\n",
2786 finish_lookup(rh, rlh, rd_count, rd);
2787 free_resolver_handle(rh);
2791 /* A CNAME can only occur alone */
2792 GNUNET_assert (is_canonical ((char*)rd->data));
2793 strcpy (rh->name, rd->data);
2794 resolve_delegation_ns (rh);
2797 else if (rh->status & RSL_DELEGATE_VPN)
2799 if (rlh->record_type == GNUNET_GNS_RECORD_VPN)
2801 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2802 "GNS_PHASE_DELEGATE_NS-%llu: Resolved queried VPNRR in NS.\n",
2804 finish_lookup(rh, rlh, rd_count, rd);
2805 free_resolver_handle(rh);
2808 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2809 "GNS_PHASE_DELEGATE_NS-%llu: VPN delegation starting.\n",
2811 GNUNET_assert (NULL != rd);
2812 rh->proc = &handle_record_vpn;
2813 resolve_record_vpn (rh, rd_count, rd);
2816 else if (rh->status & RSL_DELEGATE_NS)
2818 if (rlh->record_type == GNUNET_GNS_RECORD_TYPE_NS)
2820 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2821 "GNS_PHASE_DELEGATE_NS-%llu: Resolved queried NSRR in NS.\n",
2823 finish_lookup(rh, rlh, rd_count, rd);
2824 free_resolver_handle(rh);
2828 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2829 "GNS_PHASE_DELEGATE_NS-%llu: NS delegation starting.\n",
2831 GNUNET_assert (NULL != rd);
2832 rh->proc = &handle_record_ns;
2833 resolve_record_dns (rh, rd_count, rd);
2836 else if (rh->status & RSL_DELEGATE_PKEY)
2838 if (rh->status & RSL_PKEY_REVOKED)
2840 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2841 "GNS_PHASE_DELEGATE_NS-%llu: Resolved PKEY is revoked.\n",
2843 finish_lookup (rh, rlh, 0, NULL);
2844 free_resolver_handle (rh);
2847 else if (rlh->record_type == GNUNET_GNS_RECORD_PKEY)
2849 GNUNET_assert(rd_count == 1);
2850 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2851 "GNS_PHASE_DELEGATE_NS-%llu: Resolved queried PKEY in NS.\n",
2853 finish_lookup(rh, rlh, rd_count, rd);
2854 free_resolver_handle(rh);
2858 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2859 "GNS_PHASE_DELEGATE_NS-%llu: Resolving record +\n",
2861 strcpy(rh->name, "+\0");
2862 rh->proc = &handle_record_ns;
2863 resolve_record_ns(rh);
2867 if (rh->status & RSL_DELEGATE_NS)
2869 if (rlh->record_type == GNUNET_GNS_RECORD_TYPE_NS)
2871 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2872 "GNS_PHASE_DELEGATE_NS-%llu: Resolved queried NSRR in NS.\n",
2874 finish_lookup(rh, rlh, rd_count, rd);
2875 free_resolver_handle(rh);
2879 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2880 "GNS_PHASE_DELEGATE_NS-%llu: NS delegation starting.\n",
2882 GNUNET_assert (NULL != rd);
2883 rh->proc = &handle_record_ns;
2884 resolve_record_dns (rh, rd_count, rd);
2889 * we still have some left
2890 * check if authority in ns is fresh
2892 * or we are authority
2894 if (((rh->status & RSL_RECORD_EXISTS) && (!(rh->status & RSL_RECORD_EXPIRED)))
2895 || !GNUNET_CRYPTO_short_hash_cmp(&rh->authority_chain_head->zone,
2896 &rh->private_local_zone))
2898 if (is_canonical(rh->name))
2900 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2901 "GNS_PHASE_DELEGATE_NS-%llu: Resolving canonical record %s\n",
2904 rh->proc = &handle_record_ns;
2905 resolve_record_ns(rh);
2909 /* give up, cannot resolve */
2910 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2911 "GNS_PHASE_DELEGATE_NS-%llu: Cannot fully resolve delegation for %s!\n",
2914 finish_lookup(rh, rlh, rd_count, rd);
2915 //rlh->proc(rlh->proc_cls, 0, NULL);
2920 if (rh->only_cached == GNUNET_YES)
2922 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2923 "GNS_PHASE_DELEGATE_NS-%llu: Only cache resolution, no result\n",
2925 finish_lookup(rh, rlh, rd_count, rd);
2929 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2930 "GNS_PHASE_DELEGATE_NS-%llu: Trying to resolve delegation for %s via DHT\n",
2932 rh->proc = &handle_delegation_dht;
2933 resolve_delegation_dht(rh);
2938 * This is a callback function that should give us only PKEY
2939 * records. Used to query the namestore for the authority (PKEY)
2940 * for 'name'. It will recursively try to resolve the
2941 * authority for a given name from the namestore.
2943 * @param cls the pending query
2944 * @param key the key of the zone we did the lookup
2945 * @param expiration expiration date of the record data set in the namestore
2946 * @param name the name for which we need an authority
2947 * @param rd_count the number of records with 'name'
2948 * @param rd the record data
2949 * @param signature the signature of the authority for the record data
2952 process_delegation_result_ns (void* cls,
2953 const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *key,
2954 struct GNUNET_TIME_Absolute expiration,
2956 unsigned int rd_count,
2957 const struct GNUNET_NAMESTORE_RecordData *rd,
2958 const struct GNUNET_CRYPTO_RsaSignature *signature)
2960 struct ResolverHandle *rh;
2961 struct GNUNET_TIME_Relative remaining_time;
2962 struct GNUNET_CRYPTO_ShortHashCode zone;
2963 char new_name[MAX_DNS_NAME_LENGTH];
2965 struct GNUNET_TIME_Absolute et;
2967 rh = (struct ResolverHandle *)cls;
2968 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2969 "GNS_PHASE_DELEGATE_NS-%llu: Got %d records from authority lookup\n",
2972 GNUNET_CRYPTO_short_hash(key,
2973 sizeof(struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded),
2975 remaining_time = GNUNET_TIME_absolute_get_remaining (expiration);
2981 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2982 "GNS_PHASE_DELEGATE_NS-%llu: Records with name %s exist.\n",
2984 rh->status |= RSL_RECORD_EXISTS;
2986 if (remaining_time.rel_value == 0)
2988 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2989 "GNS_PHASE_DELEGATE_NS-%llu: Record set %s expired.\n",
2991 rh->status |= RSL_RECORD_EXPIRED;
2996 * No authority found in namestore.
3001 * We did not find an authority in the namestore
3006 * Promote this authority back to a name maybe it is
3009 if (strcmp(rh->name, "") == 0)
3011 /* simply promote back */
3012 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
3013 "GNS_PHASE_DELEGATE_NS-%llu: Promoting %s back to name\n",
3014 rh->id, rh->authority_name);
3015 strcpy(rh->name, rh->authority_name);
3019 /* add back to existing name */
3020 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
3021 "GNS_PHASE_DELEGATE_NS-%llu: Adding %s back to %s\n",
3022 rh->id, rh->authority_name, rh->name);
3023 //memset(new_name, 0, strlen(rh->name) + strlen(rh->authority_name) + 2);
3024 GNUNET_snprintf(new_name, MAX_DNS_NAME_LENGTH, "%s.%s",
3025 rh->name, rh->authority_name);
3026 //strcpy(new_name, rh->name);
3027 //strcpy(new_name+strlen(new_name), ".");
3028 //strcpy(new_name+strlen(new_name), rh->authority_name);
3029 strcpy(rh->name, new_name);
3030 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
3031 "GNS_PHASE_DELEGATE_NS-%llu: %s restored\n", rh->id, rh->name);
3033 rh->proc(rh->proc_cls, rh, 0, NULL);
3038 * We found an authority that may be able to help us
3039 * move on with query
3040 * Note only 1 pkey should have been returned.. anything else would be strange
3042 for (i=0; i<rd_count;i++)
3046 * A CNAME. Like regular DNS this means the is no other record for this
3049 if (rd[i].record_type == GNUNET_GNS_RECORD_TYPE_CNAME)
3051 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
3052 "GNS_PHASE_DELEGATE_NS-%llu: CNAME found.\n",
3054 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
3055 "GNS_PHASE_DELEGATE_NS-%llu: new name to resolve: %s.\n",
3058 rh->status |= RSL_CNAME_FOUND;
3059 rh->proc (rh->proc_cls, rh, rd_count, rd);
3066 if (rd[i].record_type == GNUNET_GNS_RECORD_VPN)
3068 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
3069 "GNS_PHASE_DELEGATE_NS-%llu: VPN found.\n",
3071 rh->status |= RSL_DELEGATE_VPN;
3072 rh->proc (rh->proc_cls, rh, rd_count, rd);
3078 * FIXME make optional
3080 if (rd[i].record_type == GNUNET_GNS_RECORD_TYPE_NS)
3082 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
3083 "GNS_PHASE_DELEGATE_NS-%llu: NS found.\n",
3085 rh->status |= RSL_DELEGATE_NS;
3086 rh->proc (rh->proc_cls, rh, rd_count, rd);
3090 if (rd[i].record_type != GNUNET_GNS_RECORD_PKEY)
3093 rh->status |= RSL_DELEGATE_PKEY;
3095 if (ignore_pending_records &&
3096 (rd[i].flags & GNUNET_NAMESTORE_RF_PENDING))
3098 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
3099 "GNS_PHASE_DELEGATE_NS-%llu: PKEY for %s is pending user confirmation.\n",
3105 GNUNET_break (0 == (rd[i].flags & GNUNET_NAMESTORE_RF_RELATIVE_EXPIRATION));
3106 et.abs_value = rd[i].expiration_time;
3107 if ((GNUNET_TIME_absolute_get_remaining (et)).rel_value
3110 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
3111 "GNS_PHASE_DELEGATE_NS-%llu: This pkey is expired.\n",
3113 if (remaining_time.rel_value == 0)
3115 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
3116 "GNS_PHASE_DELEGATE_NS-%llu: This dht entry is expired.\n",
3118 rh->authority_chain_head->fresh = 0;
3119 rh->proc(rh->proc_cls, rh, 0, NULL);
3127 * Resolve rest of query with new authority
3129 GNUNET_assert(rd[i].record_type == GNUNET_GNS_RECORD_PKEY);
3130 memcpy(&rh->authority, rd[i].data,
3131 sizeof(struct GNUNET_CRYPTO_ShortHashCode));
3132 struct AuthorityChain *auth = GNUNET_malloc(sizeof(struct AuthorityChain));
3133 auth->zone = rh->authority;
3134 memset(auth->name, 0, strlen(rh->authority_name)+1);
3135 strcpy(auth->name, rh->authority_name);
3136 GNUNET_CONTAINER_DLL_insert (rh->authority_chain_head,
3137 rh->authority_chain_tail,
3140 /* Check for key revocation and delegate */
3141 GNUNET_NAMESTORE_lookup_record (namestore_handle,
3144 GNUNET_GNS_RECORD_REV,
3145 &process_pkey_revocation_result_ns,
3154 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
3155 "GNS_PHASE_DELEGATE_NS-%llu: Authority lookup and no PKEY...\n", rh->id);
3157 * If we have found some records for the LAST label
3158 * we return the results. Else null.
3160 if (strcmp(rh->name, "") == 0)
3162 /* Start shortening */
3163 if ((rh->priv_key != NULL) && is_canonical (rh->name))
3165 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3166 "GNS_PHASE_DELEGATE_NS-%llu: Trying to shorten authority chain\n",
3168 start_shorten (rh->authority_chain_tail,
3171 /* simply promote back */
3172 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
3173 "GNS_PHASE_DELEGATE_NS-%llu: Promoting %s back to name\n",
3174 rh->id, rh->authority_name);
3175 strcpy(rh->name, rh->authority_name);
3176 rh->proc(rh->proc_cls, rh, rd_count, rd);
3180 rh->proc(rh->proc_cls, rh, 0, NULL);
3186 * Resolve the delegation chain for the request in our namestore
3188 * @param rh the resolver handle
3191 resolve_delegation_ns (struct ResolverHandle *rh)
3193 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
3194 "GNS_PHASE_DELEGATE_NS-%llu: Resolving delegation for %s\n",
3196 pop_tld(rh->name, rh->authority_name);
3197 GNUNET_NAMESTORE_lookup_record(namestore_handle,
3200 GNUNET_GNS_RECORD_ANY,
3201 &process_delegation_result_ns,
3208 * Lookup of a record in a specific zone
3209 * calls lookup result processor on result
3211 * @param zone the root zone
3212 * @param pzone the private local zone
3213 * @param record_type the record type to look up
3214 * @param name the name to look up
3215 * @param key a private key for use with PSEU import (can be NULL)
3216 * @param timeout timeout for resolution
3217 * @param only_cached GNUNET_NO to only check locally not DHT for performance
3218 * @param proc the processor to call on result
3219 * @param cls the closure to pass to proc
3222 gns_resolver_lookup_record(struct GNUNET_CRYPTO_ShortHashCode zone,
3223 struct GNUNET_CRYPTO_ShortHashCode pzone,
3224 uint32_t record_type,
3226 struct GNUNET_CRYPTO_RsaPrivateKey *key,
3227 struct GNUNET_TIME_Relative timeout,
3229 RecordLookupProcessor proc,
3232 struct ResolverHandle *rh;
3233 struct RecordLookupHandle* rlh;
3234 char string_hash[MAX_DNS_LABEL_LENGTH];
3235 char nzkey[MAX_DNS_LABEL_LENGTH];
3236 char* nzkey_ptr = nzkey;
3238 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3239 "Starting resolution for %s (type=%d)!\n",
3243 if (is_canonical((char*)name) && (strcmp(GNUNET_GNS_TLD, name) != 0))
3245 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3246 "%s is canonical and not gnunet -> cannot resolve!\n", name);
3251 rlh = GNUNET_malloc(sizeof(struct RecordLookupHandle));
3252 rh = GNUNET_malloc(sizeof (struct ResolverHandle));
3254 rh->authority = zone;
3258 rh->timeout = timeout;
3259 rh->get_handle = NULL;
3260 rh->private_local_zone = pzone;
3261 rh->only_cached = only_cached;
3265 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3266 "No shorten key for resolution\n");
3269 if (timeout.rel_value != GNUNET_TIME_UNIT_FOREVER_REL.rel_value)
3272 * Set timeout for authority lookup phase to 1/2
3274 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3275 "Timeout for lookup set to %ds\n", rh->timeout.rel_value);
3276 rh->timeout_task = GNUNET_SCHEDULER_add_delayed(
3277 GNUNET_TIME_relative_divide(timeout, 2),
3278 &handle_lookup_timeout,
3280 rh->timeout_cont = &dht_authority_lookup_timeout;
3281 rh->timeout_cont_cls = rh;
3285 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "No timeout for query!\n");
3286 rh->timeout_task = GNUNET_SCHEDULER_NO_TASK;
3289 if (strcmp(GNUNET_GNS_TLD, name) == 0)
3292 * Only 'gnunet' given
3294 strcpy(rh->name, "\0");
3298 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3299 "Checking for TLD...\n");
3300 if (is_zkey_tld(name) == GNUNET_YES)
3302 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3305 * This is a zkey tld
3306 * build hash and use as initial authority
3309 strlen(name)-strlen(GNUNET_GNS_TLD_ZKEY));
3310 memcpy(rh->name, name,
3311 strlen(name)-strlen(GNUNET_GNS_TLD_ZKEY) - 1);
3312 pop_tld(rh->name, string_hash);
3314 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3315 "ZKEY is %s!\n", string_hash);
3317 GNUNET_STRINGS_utf8_toupper(string_hash, &nzkey_ptr);
3319 if (GNUNET_OK != GNUNET_CRYPTO_short_hash_from_string(nzkey,
3322 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
3323 "Cannot convert ZKEY %s to hash!\n", string_hash);
3333 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3336 * Presumably GNUNET tld
3339 strlen(name)-strlen(GNUNET_GNS_TLD));
3340 memcpy(rh->name, name,
3341 strlen(name)-strlen(GNUNET_GNS_TLD) - 1);
3346 * Initialize authority chain
3348 rh->authority_chain_head = GNUNET_malloc(sizeof(struct AuthorityChain));
3349 rh->authority_chain_head->prev = NULL;
3350 rh->authority_chain_head->next = NULL;
3351 rh->authority_chain_tail = rh->authority_chain_head;
3352 rh->authority_chain_head->zone = rh->authority;
3355 * Copy original query into lookup handle
3357 rlh->record_type = record_type;
3358 memset(rlh->name, 0, strlen(name) + 1);
3359 strcpy(rlh->name, name);
3361 rlh->proc_cls = cls;
3363 rh->proc = &handle_delegation_ns;
3364 resolve_delegation_ns(rh);
3367 /******** END Record Resolver ***********/
3370 * Callback calles by namestore for a zone to name
3373 * @param cls the closure
3374 * @param zone_key the zone we queried
3375 * @param expire the expiration time of the name
3376 * @param name the name found or NULL
3377 * @param rd_len number of records for the name
3378 * @param rd the record data (PKEY) for the name
3379 * @param signature the signature for the record data
3382 process_zone_to_name_shorten_root (void *cls,
3383 const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *zone_key,
3384 struct GNUNET_TIME_Absolute expire,
3386 unsigned int rd_len,
3387 const struct GNUNET_NAMESTORE_RecordData *rd,
3388 const struct GNUNET_CRYPTO_RsaSignature *signature);
3392 * Callback called by namestore for a zone to name
3395 * @param cls the closure
3396 * @param zone_key the zone we queried
3397 * @param expire the expiration time of the name
3398 * @param name the name found or NULL
3399 * @param rd_len number of records for the name
3400 * @param rd the record data (PKEY) for the name
3401 * @param signature the signature for the record data
3404 process_zone_to_name_shorten_shorten (void *cls,
3405 const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *zone_key,
3406 struct GNUNET_TIME_Absolute expire,
3408 unsigned int rd_len,
3409 const struct GNUNET_NAMESTORE_RecordData *rd,
3410 const struct GNUNET_CRYPTO_RsaSignature *signature)
3412 struct ResolverHandle *rh = (struct ResolverHandle *)cls;
3413 struct NameShortenHandle* nsh = (struct NameShortenHandle*)rh->proc_cls;
3414 struct AuthorityChain *next_authority;
3416 char result[MAX_DNS_NAME_LENGTH];
3417 char tmp_name[MAX_DNS_NAME_LENGTH];
3420 /* we found a match in our own root zone */
3423 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
3424 "result strlen %d\n", strlen(name));
3425 answer_len = strlen(rh->name) + strlen(name) + strlen(GNUNET_GNS_TLD) + 3;
3426 memset(result, 0, answer_len);
3428 if (strlen(rh->name) > 0)
3430 sprintf (result, "%s.%s.%s.%s.%s",
3432 nsh->shorten_zone_name, nsh->private_zone_name,
3437 sprintf (result, "%s.%s.%s.%s", name,
3438 nsh->shorten_zone_name, nsh->private_zone_name,
3442 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
3443 "Found shorten result %s\n", result);
3444 if (strlen (nsh->result) > strlen (result))
3445 strcpy (nsh->result, result);
3447 else if (GNUNET_CRYPTO_short_hash_cmp(&rh->authority_chain_head->zone,
3448 nsh->shorten_zone) == 0)
3451 * This is our zone append .gnunet unless name is empty
3452 * (it shouldn't be, usually FIXME what happens if we
3453 * shorten to our zone to a "" record??)
3456 sprintf (result, "%s.%s.%s.%s",
3458 nsh->shorten_zone_name, nsh->private_zone_name,
3460 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
3461 "Our zone: Found %s as shorten result\n", result);
3463 if (strlen (nsh->result) > strlen (result))
3464 strcpy (nsh->result, result);
3465 //nsh->proc(nsh->proc_cls, result);
3467 //free_resolver_handle(rh);
3474 * continue with next authority if exists
3476 if ((rh->authority_chain_head->next == NULL))
3478 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3479 "Sending %s as shorten result\n", nsh->result);
3480 nsh->proc(nsh->proc_cls, nsh->result);
3482 free_resolver_handle (rh);
3485 next_authority = rh->authority_chain_head;
3487 GNUNET_snprintf(tmp_name, MAX_DNS_NAME_LENGTH,
3488 "%s.%s", rh->name, next_authority->name);
3490 strcpy(rh->name, tmp_name);
3491 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
3492 "No PSEU found for authority %s. Promoting back: %s\n",
3493 next_authority->name, rh->name);
3495 GNUNET_CONTAINER_DLL_remove(rh->authority_chain_head,
3496 rh->authority_chain_tail,
3499 GNUNET_NAMESTORE_zone_to_name (namestore_handle,
3500 &rh->authority_chain_tail->zone,
3501 &rh->authority_chain_head->zone,
3502 &process_zone_to_name_shorten_root,
3507 * Callback calles by namestore for a zone to name
3510 * @param cls the closure
3511 * @param zone_key the zone we queried
3512 * @param expire the expiration time of the name
3513 * @param name the name found or NULL
3514 * @param rd_len number of records for the name
3515 * @param rd the record data (PKEY) for the name
3516 * @param signature the signature for the record data
3519 process_zone_to_name_shorten_private (void *cls,
3520 const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *zone_key,
3521 struct GNUNET_TIME_Absolute expire,
3523 unsigned int rd_len,
3524 const struct GNUNET_NAMESTORE_RecordData *rd,
3525 const struct GNUNET_CRYPTO_RsaSignature *signature)
3527 struct ResolverHandle *rh = (struct ResolverHandle *)cls;
3528 struct NameShortenHandle* nsh = (struct NameShortenHandle*)rh->proc_cls;
3529 struct AuthorityChain *next_authority;
3531 char result[MAX_DNS_NAME_LENGTH];
3532 char tmp_name[MAX_DNS_NAME_LENGTH];
3535 /* we found a match in our own root zone */
3538 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
3539 "result strlen %d\n", strlen(name));
3540 answer_len = strlen(rh->name) + strlen(name) + strlen(GNUNET_GNS_TLD) + 3;
3541 memset(result, 0, answer_len);
3543 if (strlen(rh->name) > 0)
3545 sprintf (result, "%s.%s.%s", rh->name, name, GNUNET_GNS_TLD);
3549 sprintf (result, "%s.%s", name, GNUNET_GNS_TLD);
3552 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
3553 "Found shorten result %s\n", result);
3554 if (strlen (nsh->result) > strlen (result))
3555 strcpy (nsh->result, result);
3557 else if (GNUNET_CRYPTO_short_hash_cmp(&rh->authority_chain_head->zone,
3558 nsh->private_zone) == 0)
3561 * This is our zone append .gnunet unless name is empty
3562 * (it shouldn't be, usually FIXME what happens if we
3563 * shorten to our zone to a "" record??)
3566 sprintf (result, "%s.%s.%s",
3567 rh->name, nsh->private_zone_name, GNUNET_GNS_TLD);
3568 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
3569 "Our private zone: Found %s as shorten result %s\n", result);
3570 if (strlen (nsh->result) > strlen (result))
3571 strcpy (nsh->result, result);
3574 if (nsh->shorten_zone != NULL)
3576 /* backtrack authorities for names in priv zone */
3577 GNUNET_NAMESTORE_zone_to_name (namestore_handle,
3579 &rh->authority_chain_head->zone,
3580 &process_zone_to_name_shorten_shorten,
3587 * continue with next authority if exists
3589 if ((rh->authority_chain_head->next == NULL))
3591 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
3592 "Sending %s as shorten result\n", nsh->result);
3593 nsh->proc(nsh->proc_cls, nsh->result);
3595 free_resolver_handle(rh);
3598 next_authority = rh->authority_chain_head;
3600 GNUNET_snprintf(tmp_name, MAX_DNS_NAME_LENGTH,
3601 "%s.%s", rh->name, next_authority->name);
3603 strcpy(rh->name, tmp_name);
3604 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
3605 "No PSEU found for authority %s. Promoting back: %s\n",
3606 next_authority->name, rh->name);
3608 GNUNET_CONTAINER_DLL_remove(rh->authority_chain_head,
3609 rh->authority_chain_tail,
3612 GNUNET_NAMESTORE_zone_to_name (namestore_handle,
3613 &rh->authority_chain_tail->zone,
3614 &rh->authority_chain_head->zone,
3615 &process_zone_to_name_shorten_root,
3621 * Callback calles by namestore for a zone to name
3624 * @param cls the closure
3625 * @param zone_key the zone we queried
3626 * @param expire the expiration time of the name
3627 * @param name the name found or NULL
3628 * @param rd_len number of records for the name
3629 * @param rd the record data (PKEY) for the name
3630 * @param signature the signature for the record data
3633 process_zone_to_name_shorten_root (void *cls,
3634 const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *zone_key,
3635 struct GNUNET_TIME_Absolute expire,
3637 unsigned int rd_len,
3638 const struct GNUNET_NAMESTORE_RecordData *rd,
3639 const struct GNUNET_CRYPTO_RsaSignature *signature)
3641 struct ResolverHandle *rh = (struct ResolverHandle *)cls;
3642 struct NameShortenHandle* nsh = (struct NameShortenHandle*)rh->proc_cls;
3643 struct AuthorityChain *next_authority;
3645 char result[MAX_DNS_NAME_LENGTH];
3646 char tmp_name[MAX_DNS_NAME_LENGTH];
3649 /* we found a match in our own root zone */
3652 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
3653 "result strlen %d\n", strlen(name));
3654 answer_len = strlen(rh->name) + strlen(name) + strlen(GNUNET_GNS_TLD) + 3;
3655 memset(result, 0, answer_len);
3657 if (strlen(rh->name) > 0)
3659 sprintf (result, "%s.%s.%s", rh->name, name, GNUNET_GNS_TLD);
3663 sprintf (result, "%s.%s", name, GNUNET_GNS_TLD);
3666 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
3667 "Found shorten result %s\n", result);
3668 if (strlen (nsh->result) > strlen (result))
3669 strcpy (nsh->result, result);
3671 else if (GNUNET_CRYPTO_short_hash_cmp(&rh->authority_chain_head->zone,
3672 nsh->root_zone) == 0)
3675 * This is our zone append .gnunet unless name is empty
3676 * (it shouldn't be, usually FIXME what happens if we
3677 * shorten to our zone to a "" record??)
3680 sprintf (result, "%s.%s", rh->name, GNUNET_GNS_TLD);
3681 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
3682 "Our zone: Found %s as shorten result\n", result);
3683 if (strlen (nsh->result) > strlen (result))
3684 strcpy (nsh->result, result);
3687 if (nsh->private_zone != NULL)
3689 /* backtrack authorities for names in priv zone */
3690 GNUNET_NAMESTORE_zone_to_name (namestore_handle,
3692 &rh->authority_chain_head->zone,
3693 &process_zone_to_name_shorten_private,
3700 * continue with next authority if exists
3702 if ((rh->authority_chain_head->next == NULL))
3704 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
3705 "Sending %s as shorten result\n", nsh->result);
3706 nsh->proc(nsh->proc_cls, nsh->result);
3708 free_resolver_handle(rh);
3711 next_authority = rh->authority_chain_head;
3713 GNUNET_snprintf(tmp_name, MAX_DNS_NAME_LENGTH,
3714 "%s.%s", rh->name, next_authority->name);
3716 strcpy(rh->name, tmp_name);
3717 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
3718 "No PSEU found for authority %s. Promoting back: %s\n",
3719 next_authority->name, rh->name);
3721 GNUNET_CONTAINER_DLL_remove(rh->authority_chain_head,
3722 rh->authority_chain_tail,
3725 GNUNET_NAMESTORE_zone_to_name (namestore_handle,
3726 &rh->authority_chain_tail->zone,
3727 &rh->authority_chain_head->zone,
3728 &process_zone_to_name_shorten_root,
3735 * Process result from namestore delegation lookup
3736 * for shorten operation
3738 * @param cls the client shorten handle
3739 * @param rh the resolver handle
3740 * @param rd_count number of results (0)
3741 * @param rd data (NULL)
3744 handle_delegation_ns_shorten (void* cls,
3745 struct ResolverHandle *rh,
3747 const struct GNUNET_NAMESTORE_RecordData *rd)
3749 struct NameShortenHandle *nsh;
3750 char result[MAX_DNS_NAME_LENGTH];
3752 nsh = (struct NameShortenHandle *)cls;
3755 * At this point rh->name contains the part of the name
3756 * that we do not have a PKEY in our namestore to resolve.
3757 * The authority chain in the resolver handle is now
3758 * useful to backtrack if needed
3761 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
3762 "PKEY resolved as far as possible in ns up to %s!\n", rh->name);
3763 memset(result, 0, sizeof (result));
3765 if (GNUNET_CRYPTO_short_hash_cmp(&rh->authority_chain_head->zone,
3766 nsh->root_zone) == 0)
3769 * This is our zone append .gnunet unless name is empty
3770 * (it shouldn't be, usually FIXME what happens if we
3771 * shorten to our zone to a "" record??)
3774 sprintf (result, "%s.%s", rh->name, GNUNET_GNS_TLD);
3775 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
3776 "Our zone: Found %s as shorten result\n", result);
3778 if (strlen (nsh->result) > strlen (result))
3779 strcpy (nsh->result, result);
3782 else if (GNUNET_CRYPTO_short_hash_cmp(&rh->authority_chain_head->zone,
3783 nsh->private_zone) == 0)
3786 * This is our zone append .gnunet unless name is empty
3787 * (it shouldn't be, usually FIXME what happens if we
3788 * shorten to our zone to a "" record??)
3791 sprintf (result, "%s.%s.%s",
3792 rh->name, nsh->private_zone_name, GNUNET_GNS_TLD);
3793 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
3794 "Our zone: Found %s as shorten result %s\n", result);
3796 if (strlen (nsh->result) > strlen (result))
3797 strcpy (nsh->result, result);
3799 else if (GNUNET_CRYPTO_short_hash_cmp(&rh->authority_chain_head->zone,
3800 nsh->shorten_zone) == 0)
3803 * This is our zone append .gnunet unless name is empty
3804 * (it shouldn't be, usually FIXME what happens if we
3805 * shorten to our zone to a "" record??)
3808 sprintf (result, "%s.%s.%s",
3809 rh->name, nsh->private_zone_name, GNUNET_GNS_TLD);
3810 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
3811 "Our zone: Found %s as shorten result\n", result);
3813 if (strlen (nsh->result) > strlen (result))
3814 strcpy (nsh->result, result);
3818 /* backtrack authorities for names */
3819 GNUNET_NAMESTORE_zone_to_name (namestore_handle,
3821 &rh->authority_chain_head->zone,
3822 &process_zone_to_name_shorten_root,
3829 * Callback calles by namestore for a zone to name
3832 * @param cls the closure
3833 * @param zone_key the zone we queried
3834 * @param expire the expiration time of the name
3835 * @param name the name found or NULL
3836 * @param rd_len number of records for the name
3837 * @param rd the record data (PKEY) for the name
3838 * @param signature the signature for the record data
3841 process_zone_to_name_zkey(void *cls,
3842 const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *zone_key,
3843 struct GNUNET_TIME_Absolute expire,
3845 unsigned int rd_len,
3846 const struct GNUNET_NAMESTORE_RecordData *rd,
3847 const struct GNUNET_CRYPTO_RsaSignature *signature)
3849 struct ResolverHandle *rh = cls;
3850 struct NameShortenHandle *nsh = rh->proc_cls;
3851 struct GNUNET_CRYPTO_ShortHashAsciiEncoded enc;
3852 char new_name[MAX_DNS_NAME_LENGTH];
3854 /* zkey not in our zone */
3858 * In this case we have not given this PKEY a name (yet)
3859 * It is either just not in our zone or not even cached
3860 * Since we do not know at this point we will not try to shorten
3861 * because PKEY import will happen if the user follows the zkey
3864 GNUNET_CRYPTO_short_hash_to_enc ((struct GNUNET_CRYPTO_ShortHashCode*)rd,
3866 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
3867 "No name found for zkey %s returning verbatim!\n", enc);
3868 if (strcmp(rh->name, "") != 0)
3869 GNUNET_snprintf(new_name, MAX_DNS_NAME_LENGTH, "%s.%s.%s",
3870 rh->name, enc, GNUNET_GNS_TLD_ZKEY);
3872 GNUNET_snprintf(new_name, MAX_DNS_NAME_LENGTH, "%s.%s",
3873 enc, GNUNET_GNS_TLD_ZKEY);
3875 strcpy (nsh->result, new_name);
3877 nsh->proc(nsh->proc_cls, new_name);
3879 free_resolver_handle(rh);
3883 if (strcmp(rh->name, "") != 0)
3884 GNUNET_snprintf(new_name, MAX_DNS_NAME_LENGTH, "%s.%s",
3887 strcpy(new_name, name);
3889 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
3890 "Continue shorten for %s!\n", new_name);
3892 strcpy(rh->name, new_name);
3894 rh->authority_chain_head = GNUNET_malloc(sizeof(struct AuthorityChain));
3895 rh->authority_chain_tail = rh->authority_chain_head;
3896 rh->authority_chain_head->zone = rh->authority;
3899 /* Start delegation resolution in our namestore */
3900 resolve_delegation_ns(rh);
3905 * Shorten api from resolver
3907 * @param zone the root zone to use
3908 * @param pzone the private zone to use
3909 * @param szone the shorten zone to use
3910 * @param name the name to shorten
3911 * @param private_zone_name name of the private zone
3912 * @param shorten_zone_name name of the shorten zone
3913 * @param proc the processor to call with result
3914 * @param proc_cls closure to pass to proc
3917 gns_resolver_shorten_name (struct GNUNET_CRYPTO_ShortHashCode *zone,
3918 struct GNUNET_CRYPTO_ShortHashCode *pzone,
3919 struct GNUNET_CRYPTO_ShortHashCode *szone,
3921 const char* private_zone_name,
3922 const char* shorten_zone_name,
3923 ShortenResultProcessor proc,
3926 struct ResolverHandle *rh;
3927 struct NameShortenHandle *nsh;
3928 char string_hash[MAX_DNS_LABEL_LENGTH];
3929 struct GNUNET_CRYPTO_ShortHashCode zkey;
3930 char nzkey[MAX_DNS_LABEL_LENGTH];
3931 char* nzkey_ptr = nzkey;
3934 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3935 "Starting shorten for %s!\n", name);
3937 if (is_canonical ((char*)name))
3939 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3940 "%s is canonical. Returning verbatim\n", name);
3941 proc (proc_cls, name);
3945 nsh = GNUNET_malloc (sizeof (struct NameShortenHandle));
3948 nsh->proc_cls = proc_cls;
3949 nsh->root_zone = zone;
3950 nsh->private_zone = pzone;
3951 nsh->shorten_zone = szone;
3952 strcpy (nsh->private_zone_name, private_zone_name);
3953 strcpy (nsh->shorten_zone_name, shorten_zone_name);
3954 strcpy (nsh->result, name);
3956 rh = GNUNET_malloc (sizeof (struct ResolverHandle));
3957 rh->authority = *zone;
3959 rh->priv_key = NULL;
3960 rh->proc = &handle_delegation_ns_shorten;
3963 rh->private_local_zone = *zone;
3965 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3966 "Checking for TLD...\n");
3967 if (is_zkey_tld (name) == GNUNET_YES)
3969 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3972 * This is a zkey tld
3973 * build hash and use as initial authority
3976 memset (rh->name, 0,
3977 strlen (name)-strlen (GNUNET_GNS_TLD_ZKEY));
3978 memcpy (rh->name, name,
3979 strlen(name)-strlen (GNUNET_GNS_TLD_ZKEY) - 1);
3980 pop_tld (rh->name, string_hash);
3982 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3983 "ZKEY is %s!\n", string_hash);
3985 GNUNET_STRINGS_utf8_toupper (string_hash, &nzkey_ptr);
3987 if (GNUNET_OK != GNUNET_CRYPTO_short_hash_from_string (nzkey,
3990 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
3991 "Cannot convert ZKEY %s to hash!\n", nzkey);
3994 proc (proc_cls, name);
3998 GNUNET_NAMESTORE_zone_to_name (namestore_handle,
4001 &process_zone_to_name_zkey,
4008 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
4011 * Presumably GNUNET tld
4013 memset (rh->name, 0,
4014 strlen (name)-strlen (GNUNET_GNS_TLD));
4015 memcpy (rh->name, name,
4016 strlen (name)-strlen (GNUNET_GNS_TLD) - 1);
4019 rh->authority_chain_head = GNUNET_malloc (sizeof (struct AuthorityChain));
4020 rh->authority_chain_tail = rh->authority_chain_head;
4021 rh->authority_chain_head->zone = *zone;
4024 /* Start delegation resolution in our namestore */
4025 resolve_delegation_ns (rh);
4028 /*********** END NAME SHORTEN ********************/
4032 * Process result from namestore delegation lookup
4033 * for get authority operation
4035 * @param cls the client get auth handle
4036 * @param rh the resolver handle
4037 * @param rd_count number of results (0)
4038 * @param rd data (NULL)
4041 handle_delegation_result_ns_get_auth(void* cls,
4042 struct ResolverHandle *rh,
4044 const struct GNUNET_NAMESTORE_RecordData *rd)
4046 struct GetNameAuthorityHandle* nah;
4047 char result[MAX_DNS_NAME_LENGTH];
4050 nah = (struct GetNameAuthorityHandle*) rh->proc_cls;
4053 * At this point rh->name contains the part of the name
4054 * that we do not have a PKEY in our namestore to resolve.
4055 * The authority chain in the resolver handle is now
4056 * useful to backtrack if needed
4059 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
4060 "PKEY resolved as far as possible in ns up to %s!\n", rh->name);
4062 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
4063 "Building response!\n");
4064 if (is_canonical(rh->name))
4067 * We successfully resolved the authority in the ns
4068 * FIXME for our purposes this is fine
4069 * but maybe we want to have an api that also looks
4070 * into the dht (i.e. option in message)
4072 if (strlen(rh->name) > strlen(nah->name))
4074 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
4075 "Record name longer than original lookup name... odd!\n");
4079 answer_len = strlen(nah->name) - strlen(rh->name)
4080 + strlen(GNUNET_GNS_TLD) + 1;
4081 memset(result, 0, answer_len);
4082 strcpy(result, nah->name + strlen(rh->name) + 1);
4084 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
4085 "Got authority result %s\n", result);
4087 nah->proc(nah->proc_cls, result);
4089 free_resolver_handle(rh);
4093 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
4094 "Unable to resolve authority for remaining %s!\n", rh->name);
4095 nah->proc(nah->proc_cls, "");
4097 free_resolver_handle(rh);
4105 * Tries to resolve the authority for name
4108 * @param zone the root zone to look up for
4109 * @param pzone the private local zone
4110 * @param name the name to lookup up
4111 * @param proc the processor to call when finished
4112 * @param proc_cls the closure to pass to the processor
4115 gns_resolver_get_authority(struct GNUNET_CRYPTO_ShortHashCode zone,
4116 struct GNUNET_CRYPTO_ShortHashCode pzone,
4118 GetAuthorityResultProcessor proc,
4121 struct ResolverHandle *rh;
4122 struct GetNameAuthorityHandle *nah;
4124 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
4125 "Starting authority resolution for %s!\n", name);
4127 nah = GNUNET_malloc(sizeof (struct GetNameAuthorityHandle));
4128 rh = GNUNET_malloc(sizeof (struct ResolverHandle));
4129 rh->authority = zone;
4131 rh->private_local_zone = pzone;
4133 if (strcmp(GNUNET_GNS_TLD, name) == 0)
4135 strcpy(rh->name, "\0");
4140 strlen(name)-strlen(GNUNET_GNS_TLD));
4141 memcpy(rh->name, name,
4142 strlen(name)-strlen(GNUNET_GNS_TLD) - 1);
4145 memset(nah->name, 0,
4147 strcpy(nah->name, name);
4149 rh->authority_chain_head = GNUNET_malloc(sizeof(struct AuthorityChain));
4150 rh->authority_chain_tail = rh->authority_chain_head;
4151 rh->authority_chain_head->zone = zone;
4152 rh->proc = &handle_delegation_result_ns_get_auth;
4153 rh->proc_cls = (void*)nah;
4156 nah->proc_cls = proc_cls;
4158 /* Start delegation resolution in our namestore */
4159 resolve_delegation_ns(rh);
4163 /******** END GET AUTHORITY *************/
4165 /* end of gnunet-service-gns_resolver.c */