458e21b9d7d4845f78bfc69edf33bd100de0065c
[oweals/gnunet.git] / src / gns / gnunet-service-gns_resolver.c
1 /*
2      This file is part of GNUnet.
3      (C) 2011-2013 Christian Grothoff (and other contributing authors)
4
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.
9
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.
14
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.
19 */
20
21 /**
22  * @file gns/gnunet-service-gns_resolver.c
23  * @brief GNU Name System resolver logic
24  * @author Martin Schanzenbach
25  * @author Christian Grothoff
26  *
27  * TODO:
28  * - GNS: handle special SRV names --- no delegation, direct lookup;
29  *        can likely be done in 'resolver_lookup_get_next_label'. (#3003)
30  * - revocation checks (use CORE-level broadcasts!), (#3004)
31  * - DNAME support (#3005)
32  */
33 #include "platform.h"
34 #include "gnunet_util_lib.h"
35 #include "gnunet_dnsstub_lib.h"
36 #include "gnunet_dht_service.h"
37 #include "gnunet_namestore_service.h"
38 #include "gnunet_dns_service.h"
39 #include "gnunet_resolver_service.h"
40 #include "gnunet_dnsparser_lib.h"
41 #include "gnunet_gns_service.h"
42 #include "gns.h"
43 #include "gnunet-service-gns_resolver.h"
44 #include "gnunet-service-gns_shorten.h"
45 #include "gnunet_vpn_service.h"
46
47
48 /**
49  * Default DHT timeout for lookups.
50  */
51 #define DHT_LOOKUP_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 60)
52
53 /**
54  * Default timeout for DNS lookups.
55  */
56 #define DNS_LOOKUP_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5)
57
58 /**
59  * Default timeout for VPN redirections.
60  */
61 #define VPN_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 30)
62
63 /**
64  * DHT replication level
65  */
66 #define DHT_GNS_REPLICATION_LEVEL 5
67
68 /**
69  * How deep do we allow recursions to go before we abort?
70  */
71 #define MAX_RECURSION 256
72
73
74 /**
75  * DLL to hold the authority chain we had to pass in the resolution
76  * process.
77  */
78 struct AuthorityChain
79 {
80   /**
81    * This is a DLL.
82    */
83   struct AuthorityChain *prev;
84
85   /**
86    * This is a DLL.
87    */
88   struct AuthorityChain *next;
89
90   /**
91    * Resolver handle this entry in the chain belongs to.
92    */
93   struct GNS_ResolverHandle *rh;
94
95   /**
96    * label/name corresponding to the authority 
97    */
98   char *label;
99   
100   /**
101    * #GNUNET_YES if the authority was a GNS authority,
102    * #GNUNET_NO if the authority was a DNS authority.
103    */
104   int gns_authority;
105
106   /**
107    * Information about the resolver authority for this label.
108    */
109   union
110   {
111
112     /**
113      * The zone of the GNS authority 
114      */
115     struct GNUNET_CRYPTO_EccPublicKey gns_authority;
116
117     struct
118     {
119       /**
120        * Domain of the DNS resolver that is the authority.
121        * (appended to construct the DNS name to resolve;
122        * this is NOT the DNS name of the DNS server!).
123        */
124       char name[GNUNET_DNSPARSER_MAX_NAME_LENGTH + 1];
125
126       /**
127        * IP address of the DNS resolver that is authoritative.
128        * (this implementation currently only supports one
129        * IP at a time).
130        */
131       struct sockaddr_storage dns_ip;
132
133     } dns_authority;
134
135   } authority_info;
136   
137 };
138
139
140 /**
141  * A result we got from DNS.
142  */
143 struct DnsResult
144 {
145
146   /**
147    * Kept in DLL.
148    */
149   struct DnsResult *next;
150
151   /**
152    * Kept in DLL.
153    */
154   struct DnsResult *prev;
155
156   /**
157    * Binary value stored in the DNS record (appended to this struct)
158    */
159   const void *data;
160
161   /**
162    * Expiration time for the DNS record, 0 if we didn't
163    * get anything useful (i.e. 'gethostbyname' was used).
164    */
165   uint64_t expiration_time;
166
167   /**
168    * Number of bytes in 'data'.
169    */
170   size_t data_size;
171
172   /**
173    * Type of the GNS/DNS record.
174    */
175   uint32_t record_type;
176
177 };
178
179
180 /**
181  * Closure for #vpn_allocation_cb.
182  */
183 struct VpnContext 
184 {
185
186   /** 
187    * Which resolution process are we processing.
188    */
189   struct GNS_ResolverHandle *rh;
190
191   /**
192    * Handle to the VPN request that we were performing.
193    */
194   struct GNUNET_VPN_RedirectionRequest *vpn_request;
195
196   /**
197    * Number of records serialized in 'rd_data'.
198    */
199   unsigned int rd_count;
200   
201   /**
202    * Serialized records.
203    */
204   char *rd_data;
205   
206   /**
207    * Number of bytes in 'rd_data'.
208    */
209   size_t rd_data_size;
210 };
211
212
213 /**
214  * Handle to a currenty pending resolution.  On result (positive or
215  * negative) the #GNS_ResultProcessor is called.  
216  */
217 struct GNS_ResolverHandle
218 {
219
220   /**
221    * DLL 
222    */
223   struct GNS_ResolverHandle *next;
224
225   /**
226    * DLL 
227    */
228   struct GNS_ResolverHandle *prev;
229
230   /**
231    * The top-level GNS authoritative zone to query 
232    */
233   struct GNUNET_CRYPTO_EccPublicKey authority_zone;
234
235   /**
236    * called when resolution phase finishes 
237    */
238   GNS_ResultProcessor proc;
239   
240   /**
241    * closure passed to proc 
242    */
243   void* proc_cls;
244
245   /**
246    * Handle for DHT lookups. should be NULL if no lookups are in progress 
247    */
248   struct GNUNET_DHT_GetHandle *get_handle;
249
250   /**
251    * Handle to a VPN request, NULL if none is active.
252    */
253   struct VpnContext *vpn_ctx;
254
255   /**
256    * Socket for a DNS request, NULL if none is active.
257    */
258   struct GNUNET_DNSSTUB_RequestSocket *dns_request;
259
260   /**
261    * Handle for standard DNS resolution, NULL if none is active.
262    */
263   struct GNUNET_RESOLVER_RequestHandle *std_resolve;
264
265   /**
266    * Pending Namestore task
267    */
268   struct GNUNET_NAMESTORE_QueueEntry *namestore_qe;
269
270   /**
271    * Heap node associated with this lookup.  Used to limit number of
272    * concurrent requests.
273    */
274   struct GNUNET_CONTAINER_HeapNode *dht_heap_node;
275
276   /**
277    * DLL to store the authority chain 
278    */
279   struct AuthorityChain *ac_head;
280
281   /**
282    * DLL to store the authority chain 
283    */
284   struct AuthorityChain *ac_tail;
285
286   /**
287    * Private key of the shorten zone, NULL to not shorten.
288    */
289   struct GNUNET_CRYPTO_EccPrivateKey *shorten_key;
290
291   /**
292    * ID of a task associated with the resolution process.
293    */
294   GNUNET_SCHEDULER_TaskIdentifier task_id;
295
296   /**
297    * The name to resolve 
298    */
299   char *name;
300
301   /**
302    * DLL of results we got from DNS.
303    */
304   struct DnsResult *dns_result_head;
305
306   /**
307    * DLL of results we got from DNS.
308    */
309   struct DnsResult *dns_result_tail;
310
311   /**
312    * Current offset in 'name' where we are resolving.
313    */
314   size_t name_resolution_pos;
315
316   /**
317    * Use only cache 
318    */
319   int only_cached;
320
321   /**
322    * Desired type for the resolution.
323    */
324   int record_type;
325
326   /**
327    * We increment the loop limiter for each step in a recursive
328    * resolution.  If it passes our threshold (i.e. due to 
329    * self-recursion in the resolution, i.e CNAME fun), we stop.
330    */
331   unsigned int loop_limiter;
332
333 };
334
335
336 /**
337  * Our handle to the namestore service
338  */
339 static struct GNUNET_NAMESTORE_Handle *namestore_handle;
340
341 /**
342  * Our handle to the vpn service
343  */
344 static struct GNUNET_VPN_Handle *vpn_handle;
345
346 /**
347  * Resolver handle to the dht
348  */
349 static struct GNUNET_DHT_Handle *dht_handle;
350
351 /**
352  * Handle to perform DNS lookups.
353  */
354 static struct GNUNET_DNSSTUB_Context *dns_handle;
355
356 /**
357  * Heap for limiting parallel DHT lookups
358  */
359 static struct GNUNET_CONTAINER_Heap *dht_lookup_heap;
360
361 /**
362  * Maximum amount of parallel queries to the DHT
363  */
364 static unsigned long long max_allowed_background_queries;
365
366 /**
367  * Head of resolver lookup list
368  */
369 static struct GNS_ResolverHandle *rlh_head;
370
371 /**
372  * Tail of resolver lookup list
373  */
374 static struct GNS_ResolverHandle *rlh_tail;
375
376 /**
377  * Global configuration.
378  */
379 static const struct GNUNET_CONFIGURATION_Handle *cfg;
380
381
382 /**
383  * Check if name is in srv format (_x._y.xxx)
384  *
385  * @param name
386  * @return #GNUNET_YES if true
387  */
388 static int
389 is_srv (const char *name)
390 {
391   char *ndup;
392   int ret;
393
394   if (*name != '_')
395     return GNUNET_NO;
396   if (NULL == strstr (name, "._"))
397     return GNUNET_NO;
398   ret = GNUNET_YES;
399   ndup = GNUNET_strdup (name);
400   strtok (ndup, ".");
401   if (NULL == strtok (NULL, "."))
402     ret = GNUNET_NO;
403   if (NULL == strtok (NULL, "."))
404     ret = GNUNET_NO;
405   if (NULL != strtok (NULL, "."))
406     ret = GNUNET_NO;
407   GNUNET_free (ndup);
408   return ret;
409 }
410
411
412 /**
413  * Determine if this name is canonical (is a legal name in a zone, without delegation);
414  * note that we do not test that the name does not contain illegal characters, we only
415  * test for delegation.  Note that service records (i.e. _foo._srv) are canonical names
416  * even though they consist of multiple labels.
417  *
418  * Examples:
419  * a.b.gnu  = not canonical
420  * a         = canonical
421  * _foo._srv = canonical
422  * _f.bar    = not canonical
423  *
424  * @param name the name to test
425  * @return #GNUNET_YES if canonical
426  */
427 static int
428 is_canonical (const char *name)
429 {
430   const char *pos;
431   const char *dot;
432
433   if (NULL == strchr (name, '.'))
434     return GNUNET_YES;
435   if ('_' != name[0])
436     return GNUNET_NO;
437   pos = &name[1];
438   while (NULL != (dot = strchr (pos, '.')))    
439     if ('_' != dot[1])
440       return GNUNET_NO;
441     else
442       pos = dot + 1;
443   return GNUNET_YES;
444 }
445
446 /* ************************** Resolution **************************** */
447
448 /**
449  * Exands a name ending in .+ with the zone of origin.
450  *
451  * @param rh resolution context
452  * @param name name to modify (to be free'd or returned)
453  * @return updated name
454  */
455 static char *
456 translate_dot_plus (struct GNS_ResolverHandle *rh,
457                     char *name)
458 {
459   char *ret;
460   size_t s_len = strlen (name);
461
462   if (0 != strcmp (&name[s_len - 2],
463                    ".+"))
464     return name; /* did not end in ".+" */
465   GNUNET_assert (GNUNET_YES == rh->ac_tail->gns_authority);
466   GNUNET_asprintf (&ret,
467                    "%.*s.%s",
468                    (int) (s_len - 2),
469                    name,
470                    GNUNET_NAMESTORE_pkey_to_zkey (&rh->ac_tail->authority_info.gns_authority));
471   GNUNET_free (name);
472   return ret;
473 }
474
475
476 /**
477  * Task scheduled to asynchronously fail a resolution.
478  *
479  * @param cls the 'struct GNS_ResolverHandle' of the resolution to fail
480  * @param tc task context
481  */
482 static void
483 fail_resolution (void *cls,
484                  const struct GNUNET_SCHEDULER_TaskContext *tc)
485 {
486   struct GNS_ResolverHandle *rh = cls;
487
488   rh->task_id = GNUNET_SCHEDULER_NO_TASK;
489   rh->proc (rh->proc_cls, 0, NULL);
490   GNS_resolver_lookup_cancel (rh);
491 }
492
493
494 #if (defined WINDOWS) || (defined DARWIN)
495 /* Don't have this on W32, here's a naive implementation
496  * Was somehow removed on OS X ...  */
497 void *
498 memrchr (const void *s, int c, size_t n)
499 {
500   size_t i;
501   unsigned char *ucs = (unsigned char *) s;
502
503   for (i = n - 1; i >= 0; i--)
504     if (ucs[i] == c)
505       return (void *) &ucs[i];
506   return NULL;
507 }
508 #endif
509
510
511 /**
512  * Get the next, rightmost label from the name that we are trying to resolve,
513  * and update the resolution position accordingly.
514  *
515  * @param rh handle to the resolution operation to get the next label from
516  * @return NULL if there are no more labels
517  */
518 static char *
519 resolver_lookup_get_next_label (struct GNS_ResolverHandle *rh)
520 {
521   const char *rp;
522   const char *dot;
523   size_t len;
524
525   if (0 == rh->name_resolution_pos)
526     return NULL;
527   dot = memrchr (rh->name, (int) '.', rh->name_resolution_pos);
528   if (NULL == dot)
529   {
530     /* done, this was the last one */
531     len = rh->name_resolution_pos;
532     rp = rh->name;
533     rh->name_resolution_pos = 0; 
534   }
535   else
536   {
537     /* advance by one label */
538     len = rh->name_resolution_pos - (dot - rh->name) - 1;
539     rp = dot + 1;
540     rh->name_resolution_pos = dot - rh->name;
541   }  
542   return GNUNET_strndup (rp, len);  
543 }
544
545
546 /**
547  * Gives the cummulative result obtained to the callback and clean up the request.
548  *
549  * @param rh resolution process that has culminated in a result
550  */
551 static void
552 transmit_lookup_dns_result (struct GNS_ResolverHandle *rh)
553 {
554   struct DnsResult *pos;
555   unsigned int n;
556   unsigned int i;
557
558   n = 0;
559   for (pos = rh->dns_result_head; NULL != pos; pos = pos->next)
560     n++;
561   {
562     struct GNUNET_NAMESTORE_RecordData rd[n];
563
564     i = 0;
565     for (pos = rh->dns_result_head; NULL != pos; pos = pos->next)
566     {
567       rd[i].data = pos->data;
568       rd[i].data_size = pos->data_size;
569       rd[i].record_type = pos->record_type;
570       if (0 == pos->expiration_time)
571       {
572         rd[i].flags = GNUNET_NAMESTORE_RF_RELATIVE_EXPIRATION;
573         rd[i].expiration_time = 0;
574       }
575       else
576       {
577         rd[i].flags = GNUNET_NAMESTORE_RF_NONE;
578         rd[i].expiration_time = pos->expiration_time;
579       }
580     }      
581     rh->proc (rh->proc_cls,
582               n,
583               rd);
584   }
585   GNS_resolver_lookup_cancel (rh);
586 }
587
588
589 /**
590  * Add a result from DNS to the records to be returned to the application.
591  *
592  * @param rh resolution request to extend with a result
593  * @param expiration_time expiration time for the answer
594  * @param record_type DNS record type of the answer
595  * @param data_size number of bytes in @a data
596  * @param data binary data to return in DNS record
597  */
598 static void
599 add_dns_result (struct GNS_ResolverHandle *rh,
600                 uint64_t expiration_time,
601                 uint32_t record_type,
602                 size_t data_size,
603                 const void *data)
604 {
605   struct DnsResult *res;
606
607   res = GNUNET_malloc (sizeof (struct DnsResult) + data_size);
608   res->expiration_time = expiration_time;
609   res->data_size = data_size;
610   res->record_type = record_type;
611   res->data = &res[1];
612   memcpy (&res[1], data, data_size);
613   GNUNET_CONTAINER_DLL_insert (rh->dns_result_head,
614                                rh->dns_result_tail,
615                                res);
616 }
617
618
619 /**
620  * We had to do a DNS lookup.  Convert the result (if any) and return
621  * it.
622  *
623  * @param cls closure with the 'struct GNS_ResolverHandle'
624  * @param addr one of the addresses of the host, NULL for the last address
625  * @param addrlen length of the address
626  */
627 static void
628 handle_dns_result (void *cls,
629                    const struct sockaddr *addr,
630                    socklen_t addrlen)
631 {
632   struct GNS_ResolverHandle *rh = cls;
633   const struct sockaddr_in *sa4;
634   const struct sockaddr_in6 *sa6;
635
636   rh->std_resolve = NULL;
637   if (NULL == addr)
638   {
639     transmit_lookup_dns_result (rh);
640     return;
641   }
642   switch (addr->sa_family)
643   {
644   case AF_INET:
645     sa4 = (const struct sockaddr_in *) addr;
646     add_dns_result (rh,
647                     0 /* expiration time is unknown */,
648                     GNUNET_DNSPARSER_TYPE_A,
649                     sizeof (struct in_addr),
650                     &sa4->sin_addr);
651     break;
652   case AF_INET6:
653     sa6 = (const struct sockaddr_in6 *) addr;
654     add_dns_result (rh,
655                     0 /* expiration time is unknown */,
656                     GNUNET_DNSPARSER_TYPE_AAAA,
657                     sizeof (struct in6_addr),
658                     &sa6->sin6_addr);
659     break;
660   default:
661     GNUNET_break (0);
662     break;
663   }
664 }
665
666
667 /**
668  * Task scheduled to continue with the resolution process.
669  *
670  * @param cls the 'struct GNS_ResolverHandle' of the resolution
671  * @param tc task context
672  */
673 static void
674 recursive_resolution (void *cls,
675                       const struct GNUNET_SCHEDULER_TaskContext *tc);
676
677
678 /**
679  * Begin the resolution process from 'name', starting with
680  * the identification of the zone specified by 'name'.
681  *
682  * @param rh resolution to perform
683  */
684 static void
685 start_resolver_lookup (struct GNS_ResolverHandle *rh);
686
687
688 /**
689  * Function called with the result of a DNS resolution.
690  *
691  * @param cls the request handle of the resolution that
692  *        we were attempting to make
693  * @param rs socket that received the response
694  * @param dns dns response, never NULL
695  * @param dns_len number of bytes in @a dns
696  */
697 static void
698 dns_result_parser (void *cls,
699                    struct GNUNET_DNSSTUB_RequestSocket *rs,
700                    const struct GNUNET_TUN_DnsHeader *dns,
701                    size_t dns_len)
702 {
703   struct GNS_ResolverHandle *rh = cls;
704   struct GNUNET_DNSPARSER_Packet *p;
705   const struct GNUNET_DNSPARSER_Record *rec;
706   unsigned int rd_count;
707   unsigned int i;
708
709   rh->dns_request = NULL;
710   GNUNET_SCHEDULER_cancel (rh->task_id);
711   rh->task_id = GNUNET_SCHEDULER_NO_TASK;
712   p = GNUNET_DNSPARSER_parse ((const char *) dns, 
713                               dns_len);
714   if (NULL == p)
715   {
716     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
717                 _("Failed to parse DNS response\n"));
718     rh->proc (rh->proc_cls, 0, NULL);
719     GNS_resolver_lookup_cancel (rh);
720     return;
721   }
722
723   if ( (p->num_answers > 0) &&
724        (GNUNET_DNSPARSER_TYPE_CNAME == p->answers[0].type) &&
725        (GNUNET_DNSPARSER_TYPE_CNAME != rh->record_type) )
726     {
727       GNUNET_free (rh->name);
728       rh->name = GNUNET_strdup (p->answers[0].data.hostname);
729       start_resolver_lookup (rh);
730       GNUNET_DNSPARSER_free_packet (p);
731       return;     
732     }
733   /* FIXME: add DNAME support */
734
735   /* convert from (parsed) DNS to (binary) GNS format! */
736   rd_count = p->num_answers + p->num_authority_records + p->num_additional_records;
737   {
738     struct GNUNET_NAMESTORE_RecordData rd[rd_count];
739     unsigned int skip;
740     char buf[UINT16_MAX];
741     size_t buf_off;
742
743     buf_off = 0;
744     skip = 0;
745     memset (rd, 0, sizeof (rd));
746     for (i=0;i<rd_count;i++)
747     {
748       if (i < p->num_answers)
749         rec = &p->answers[i];
750       else if (i < p->num_answers + p->num_authority_records)
751         rec = &p->authority_records[i - p->num_answers];
752       else 
753         rec = &p->authority_records[i - p->num_answers - p->num_authority_records];
754       /* As we copied the full DNS name to 'rh->ac_tail->label', this
755          should be the correct check to see if this record is actually
756          a record for our label... */
757       if (0 != strcmp (rec->name,
758                        rh->ac_tail->label))
759       {
760         GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
761                     "Dropping record `%s', does not match desired name `%s'\n",
762                     rec->name,
763                     rh->ac_tail->label);
764         skip++;
765         continue;
766       }
767       rd[i - skip].record_type = rec->type;
768       rd[i - skip].expiration_time = rec->expiration_time.abs_value_us;
769       switch (rec->type)
770       {
771       case GNUNET_DNSPARSER_TYPE_A:
772         if (rec->data.raw.data_len != sizeof (struct in_addr))
773         {
774           GNUNET_break_op (0);
775           skip++;
776           continue;
777         }
778         rd[i - skip].data_size = rec->data.raw.data_len;
779         rd[i - skip].data = rec->data.raw.data;
780         break;
781       case GNUNET_DNSPARSER_TYPE_AAAA:
782         if (rec->data.raw.data_len != sizeof (struct in6_addr))
783         {
784           GNUNET_break_op (0);
785           skip++;
786           continue;
787         }
788         rd[i - skip].data_size = rec->data.raw.data_len;
789         rd[i - skip].data = rec->data.raw.data;
790         break;
791       case GNUNET_DNSPARSER_TYPE_CNAME:
792       case GNUNET_DNSPARSER_TYPE_PTR:
793       case GNUNET_DNSPARSER_TYPE_NS:
794         if (GNUNET_OK !=
795             GNUNET_DNSPARSER_builder_add_name (buf,
796                                                sizeof (buf),
797                                                &buf_off,
798                                                rec->data.hostname))
799         {
800           GNUNET_break (0);
801           skip++;
802           continue;
803         }
804         break;
805       case GNUNET_DNSPARSER_TYPE_SOA:
806         if (GNUNET_OK !=
807             GNUNET_DNSPARSER_builder_add_soa (buf,
808                                                sizeof (buf),
809                                                &buf_off,
810                                                rec->data.soa))
811         {
812           GNUNET_break (0);
813           skip++;
814           continue;
815         }
816         break;
817       case GNUNET_DNSPARSER_TYPE_MX:
818         if (GNUNET_OK !=
819             GNUNET_DNSPARSER_builder_add_mx (buf,
820                                              sizeof (buf),
821                                              &buf_off,
822                                              rec->data.mx))
823         {
824           GNUNET_break (0);
825           skip++;
826           continue;
827         }
828         break;
829       case GNUNET_DNSPARSER_TYPE_SRV:
830         if (GNUNET_OK !=
831             GNUNET_DNSPARSER_builder_add_srv (buf,
832                                               sizeof (buf),
833                                               &buf_off,
834                                               rec->data.srv))
835         {
836           GNUNET_break (0);
837           skip++;
838           continue;
839         }
840         break;
841       default:
842         GNUNET_log (GNUNET_ERROR_TYPE_INFO,
843                     _("Skipping record of unsupported type %d\n"),
844                     rec->type);
845         skip++;
846         continue;
847       }
848     }
849     rh->proc (rh->proc_cls, rd_count - skip, rd);
850     GNS_resolver_lookup_cancel (rh);
851   }  
852   GNUNET_DNSPARSER_free_packet (p);
853 }
854
855
856 /**
857  * Perform recursive DNS resolution.  Asks the given DNS resolver to
858  * resolve "rh->dns_name", possibly recursively proceeding following
859  * NS delegations, CNAMES, etc., until 'rh->loop_limiter' bounds us or
860  * we find the answer.
861  *
862  * @param rh resolution information
863  */
864 static void
865 recursive_dns_resolution (struct GNS_ResolverHandle *rh)
866 {
867   struct AuthorityChain *ac;
868   socklen_t sa_len;
869   struct GNUNET_DNSPARSER_Query *query;
870   struct GNUNET_DNSPARSER_Packet *p;
871   char *dns_request;
872   size_t dns_request_length;
873
874   ac = rh->ac_tail;
875   GNUNET_assert (NULL != ac);
876   GNUNET_assert (GNUNET_NO == ac->gns_authority);
877   switch (((const struct sockaddr *) &ac->authority_info.dns_authority.dns_ip)->sa_family)
878   {
879   case AF_INET:
880     sa_len = sizeof (struct sockaddr_in);
881     break;
882   case AF_INET6:
883     sa_len = sizeof (struct sockaddr_in6);
884     break;
885   default:
886     GNUNET_break (0);
887     rh->proc (rh->proc_cls, 0, NULL);
888     GNS_resolver_lookup_cancel (rh);
889     return;
890   }
891   query = GNUNET_new (struct GNUNET_DNSPARSER_Query);
892   query->name = GNUNET_strdup (ac->label);
893   query->type = rh->record_type;
894   query->class = GNUNET_TUN_DNS_CLASS_INTERNET;
895   p = GNUNET_new (struct GNUNET_DNSPARSER_Packet);
896   p->queries = query;
897   p->num_queries = 1;
898   p->id = (uint16_t) GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_NONCE,
899                                                UINT16_MAX);
900   p->flags.opcode = GNUNET_TUN_DNS_OPCODE_QUERY;
901   p->flags.recursion_desired = 1;
902   if (GNUNET_OK != 
903       GNUNET_DNSPARSER_pack (p, 1024, &dns_request, &dns_request_length))
904   {
905     GNUNET_break (0);
906     rh->proc (rh->proc_cls, 0, NULL);
907     GNS_resolver_lookup_cancel (rh);
908   }
909   else
910   {
911     rh->dns_request = GNUNET_DNSSTUB_resolve (dns_handle,
912                                               (const struct sockaddr *) &ac->authority_info.dns_authority.dns_ip,
913                                               sa_len,
914                                               dns_request,
915                                               dns_request_length,
916                                               &dns_result_parser,
917                                               rh);
918     rh->task_id = GNUNET_SCHEDULER_add_delayed (DNS_LOOKUP_TIMEOUT,
919                                                 &fail_resolution,
920                                                 rh);
921   }
922   GNUNET_free (dns_request);
923   GNUNET_DNSPARSER_free_packet (p);
924 }
925
926
927 /**
928  * We encountered a CNAME record during our resolution.
929  * Merge it into our chain.
930  *
931  * @param rh resolution we are performing
932  * @param cname value of the cname record we got for the current 
933  *        authority chain tail
934  */
935 static void
936 handle_gns_cname_result (struct GNS_ResolverHandle *rh,
937                          const char *cname)
938 {
939   size_t nlen;
940   char *res;
941
942   nlen = strlen (cname);
943   if ( (nlen > 2) &&
944        (0 == strcmp (".+",
945                      &cname[nlen - 2])) )
946   {
947     /* CNAME resolution continues relative to current domain */
948     if (0 == rh->name_resolution_pos)
949     {
950       res = GNUNET_strndup (cname, nlen - 2);
951       rh->name_resolution_pos = nlen - 2;
952     }
953     else
954     {
955       GNUNET_asprintf (&res,
956                        "%.*s.%.*s",
957                        (int) rh->name_resolution_pos,
958                        rh->name,
959                        (int) (nlen - 2),
960                        cname);
961       rh->name_resolution_pos = strlen (res);
962     }
963     GNUNET_free (rh->name);
964     rh->name = res;
965     rh->task_id = GNUNET_SCHEDULER_add_now (&recursive_resolution,
966                                             rh);
967     return;
968   }
969   /* name is absolute, start from the beginning */
970   GNUNET_free (rh->name);
971   rh->name = GNUNET_strdup (cname);
972   start_resolver_lookup (rh);
973 }
974
975
976 /**
977  * Process a records that were decrypted from a block.
978  *
979  * @param cls closure with the 'struct GNS_ResolverHandle'
980  * @param rd_count number of entries in @a rd array
981  * @param rd array of records with data to store
982  */
983 static void
984 handle_gns_resolution_result (void *cls,
985                               unsigned int rd_count,
986                               const struct GNUNET_NAMESTORE_RecordData *rd);
987
988
989 /**
990  * Callback invoked from the VPN service once a redirection is
991  * available.  Provides the IP address that can now be used to
992  * reach the requested destination.  Replaces the "VPN" record
993  * with the respective A/AAAA record and continues processing.
994  *
995  * @param cls closure
996  * @param af address family, AF_INET or AF_INET6; AF_UNSPEC on error;
997  *                will match 'result_af' from the request
998  * @param address IP address (struct in_addr or struct in_addr6, depending on 'af')
999  *                that the VPN allocated for the redirection;
1000  *                traffic to this IP will now be redirected to the 
1001  *                specified target peer; NULL on error
1002  */
1003 static void
1004 vpn_allocation_cb (void *cls,
1005                    int af,
1006                    const void *address)
1007 {
1008   struct VpnContext *vpn_ctx = cls;
1009   struct GNS_ResolverHandle *rh = vpn_ctx->rh;
1010   struct GNUNET_NAMESTORE_RecordData rd[vpn_ctx->rd_count];
1011   unsigned int i;
1012
1013   vpn_ctx->vpn_request = NULL;
1014   rh->vpn_ctx = NULL;
1015   GNUNET_assert (GNUNET_OK ==
1016                  GNUNET_NAMESTORE_records_deserialize (vpn_ctx->rd_data_size,
1017                                                        vpn_ctx->rd_data,
1018                                                        vpn_ctx->rd_count,
1019                                                        rd));
1020   for (i=0;i<vpn_ctx->rd_count;i++)
1021   {
1022     if (GNUNET_NAMESTORE_TYPE_VPN == rd[i].record_type)
1023     {
1024       switch (af)
1025       {
1026       case AF_INET: 
1027         rd[i].record_type = GNUNET_DNSPARSER_TYPE_A;
1028         rd[i].data_size = sizeof (struct in_addr);
1029         rd[i].expiration_time = GNUNET_TIME_relative_to_absolute (VPN_TIMEOUT).abs_value_us;
1030         rd[i].flags = 0;
1031         rd[i].data = address;
1032         break;
1033       case AF_INET6:
1034         rd[i].record_type = GNUNET_DNSPARSER_TYPE_AAAA;
1035         rd[i].expiration_time = GNUNET_TIME_relative_to_absolute (VPN_TIMEOUT).abs_value_us;
1036         rd[i].flags = 0;
1037         rd[i].data = address;
1038         rd[i].data_size = sizeof (struct in6_addr);
1039         break;
1040       default:
1041         GNUNET_assert (0);
1042       }     
1043       break;
1044     }
1045   }
1046   GNUNET_assert (i < vpn_ctx->rd_count);
1047   handle_gns_resolution_result (rh, 
1048                                 vpn_ctx->rd_count,
1049                                 rd);
1050   GNUNET_free (vpn_ctx->rd_data);
1051   GNUNET_free (vpn_ctx);
1052 }
1053
1054
1055 /**
1056  * Process a records that were decrypted from a block.
1057  *
1058  * @param cls closure with the 'struct GNS_ResolverHandle'
1059  * @param rd_count number of entries in @a rd array
1060  * @param rd array of records with data to store
1061  */
1062 static void
1063 handle_gns_resolution_result (void *cls,
1064                               unsigned int rd_count,
1065                               const struct GNUNET_NAMESTORE_RecordData *rd)
1066 {
1067   struct GNS_ResolverHandle *rh = cls;
1068   struct AuthorityChain *ac;
1069   unsigned int i;
1070   unsigned int j;
1071   struct sockaddr *sa;
1072   struct sockaddr_in v4;
1073   struct sockaddr_in6 v6;
1074   size_t sa_len;
1075   char *cname;
1076   struct VpnContext *vpn_ctx;
1077   const struct GNUNET_TUN_GnsVpnRecord *vpn;
1078   const char *vname;
1079   struct GNUNET_HashCode vhash;
1080   int af;
1081   char scratch[UINT16_MAX];
1082   size_t scratch_off;
1083   size_t scratch_start;
1084   size_t off;
1085   struct GNUNET_NAMESTORE_RecordData rd_new[rd_count];
1086   unsigned int rd_off;
1087   
1088   if (0 == rh->name_resolution_pos)
1089   {
1090     /* top-level match, are we done yet? */
1091     if ( (rd_count > 0) &&
1092          (GNUNET_DNSPARSER_TYPE_CNAME == rd[0].record_type) &&
1093          (GNUNET_DNSPARSER_TYPE_CNAME != rh->record_type) )
1094     {
1095       cname = GNUNET_strndup (rd[0].data,
1096                               rd[0].data_size);
1097       handle_gns_cname_result (rh, 
1098                                cname);
1099       GNUNET_free (cname);
1100       return;     
1101     }
1102     /* If A/AAAA was requested, but we got a VPN
1103        record, we convert it to A/AAAA using GNUnet VPN */
1104     if ( (GNUNET_DNSPARSER_TYPE_A == rh->record_type) ||
1105          (GNUNET_DNSPARSER_TYPE_AAAA == rh->record_type) )
1106     {
1107       for (i=0;i<rd_count;i++)
1108       {
1109         if (GNUNET_NAMESTORE_TYPE_VPN == rd[i].record_type)
1110         {
1111           af = (GNUNET_DNSPARSER_TYPE_A == rh->record_type) ? AF_INET : AF_INET6;
1112           if (sizeof (struct GNUNET_TUN_GnsVpnRecord) <
1113               rd[i].data_size)
1114           {
1115             GNUNET_break_op (0);
1116             rh->proc (rh->proc_cls, 0, NULL);
1117             GNS_resolver_lookup_cancel (rh);
1118             return;         
1119           }
1120           vpn = (const struct GNUNET_TUN_GnsVpnRecord *) rd[i].data;
1121           vname = (const char *) &vpn[1];
1122           if ('\0' != vname[rd[i].data_size - 1 - sizeof (struct GNUNET_TUN_GnsVpnRecord)])
1123           {
1124             GNUNET_break_op (0);
1125             rh->proc (rh->proc_cls, 0, NULL);
1126             GNS_resolver_lookup_cancel (rh);
1127             return;
1128           }
1129           GNUNET_CRYPTO_hash (vname,
1130                               strlen (vname), // FIXME: +1?
1131                               &vhash);
1132           vpn_ctx = GNUNET_new (struct VpnContext);
1133           rh->vpn_ctx = vpn_ctx;
1134           vpn_ctx->rh = rh;
1135           vpn_ctx->rd_data_size = GNUNET_NAMESTORE_records_get_size (rd_count,
1136                                                                      rd);
1137           vpn_ctx->rd_data = GNUNET_malloc (vpn_ctx->rd_data_size);
1138           (void) GNUNET_NAMESTORE_records_serialize (rd_count,
1139                                                      rd,
1140                                                      vpn_ctx->rd_data_size,
1141                                                      vpn_ctx->rd_data);
1142           vpn_ctx->vpn_request = GNUNET_VPN_redirect_to_peer (vpn_handle,
1143                                                               af,
1144                                                               ntohs (vpn->proto),
1145                                                               &vpn->peer,
1146                                                               &vhash,
1147                                                               GNUNET_NO,
1148                                                               GNUNET_TIME_relative_to_absolute (VPN_TIMEOUT),
1149                                                               &vpn_allocation_cb,
1150                                                               rh);
1151           return;
1152         }
1153       }
1154     }
1155     /* convert relative names in record values to absolute names,
1156        using 'scratch' array for memory allocations */
1157     scratch_off = 0;
1158     rd_off = 0;
1159     for (i=0;i<rd_count;i++)
1160     {
1161       rd_new[rd_off] = rd[i];
1162       /* Check if the embedded name(s) end in "+", and if so,
1163          replace the "+" with the zone at "ac_tail", changing the name
1164          to a ".zkey".  The name is allocated on the 'scratch' array,
1165          so we can free it afterwards. */
1166       switch (rd[i].record_type)
1167       {
1168       case GNUNET_DNSPARSER_TYPE_CNAME:
1169         {
1170           char *cname;
1171
1172           off = 0;
1173           cname = GNUNET_DNSPARSER_parse_name (rd[i].data,
1174                                                rd[i].data_size,
1175                                                &off);
1176           if ( (NULL == cname) ||
1177                (off != rd[i].data_size) )
1178           {
1179             GNUNET_break_op (0); /* record not well-formed */
1180           }
1181           else
1182           {
1183             cname = translate_dot_plus (rh, cname);
1184             scratch_start = scratch_off;
1185             if (GNUNET_OK !=
1186                 GNUNET_DNSPARSER_builder_add_name (scratch,
1187                                                    sizeof (scratch),
1188                                                    &scratch_off,
1189                                                    cname))
1190             {
1191               GNUNET_break (0);
1192             }
1193             else
1194             {
1195               rd_new[rd_off].data = &scratch[scratch_start];
1196               rd_new[rd_off].data_size = scratch_off - scratch_start;
1197               rd_off++;
1198             }
1199           }
1200           GNUNET_free_non_null (cname);   
1201         }
1202         break;
1203       case GNUNET_DNSPARSER_TYPE_SOA:
1204         {
1205           struct GNUNET_DNSPARSER_SoaRecord *soa;
1206
1207           off = 0;
1208           soa = GNUNET_DNSPARSER_parse_soa (rd[i].data,
1209                                             rd[i].data_size,
1210                                             &off);
1211           if ( (NULL == soa) ||
1212                (off != rd[i].data_size) )
1213           {
1214             GNUNET_break_op (0); /* record not well-formed */
1215           }
1216           else
1217           {
1218             soa->mname = translate_dot_plus (rh, soa->mname);
1219             soa->rname = translate_dot_plus (rh, soa->rname);
1220             scratch_start = scratch_off;
1221             if (GNUNET_OK !=
1222                 GNUNET_DNSPARSER_builder_add_soa (scratch,
1223                                                   sizeof (scratch),
1224                                                   &scratch_off,
1225                                                   soa))
1226             {
1227               GNUNET_break (0);
1228             }
1229             else
1230             {
1231               rd_new[rd_off].data = &scratch[scratch_start];
1232               rd_new[rd_off].data_size = scratch_off - scratch_start;
1233               rd_off++;
1234             }
1235           }
1236           if (NULL != soa)
1237             GNUNET_DNSPARSER_free_soa (soa);      
1238         }
1239         break;
1240       case GNUNET_DNSPARSER_TYPE_MX:
1241         {
1242           struct GNUNET_DNSPARSER_MxRecord *mx;
1243
1244           off = 0;
1245           mx = GNUNET_DNSPARSER_parse_mx (rd[i].data,
1246                                           rd[i].data_size,
1247                                           &off);
1248           if ( (NULL == mx) ||
1249                (off != rd[i].data_size) )
1250           {
1251             GNUNET_break_op (0); /* record not well-formed */
1252           }
1253           else
1254           {
1255             mx->mxhost = translate_dot_plus (rh, mx->mxhost);
1256             scratch_start = scratch_off;
1257             if (GNUNET_OK !=
1258                 GNUNET_DNSPARSER_builder_add_mx (scratch,
1259                                                  sizeof (scratch),
1260                                                  &scratch_off,
1261                                                  mx))
1262             {
1263               GNUNET_break (0);
1264             }
1265             else
1266             {
1267               rd_new[rd_off].data = &scratch[scratch_start];
1268               rd_new[rd_off].data_size = scratch_off - scratch_start;
1269               rd_off++;
1270             }
1271           }
1272           if (NULL != mx)
1273             GNUNET_DNSPARSER_free_mx (mx);        
1274         }       
1275         break;
1276       case GNUNET_DNSPARSER_TYPE_SRV:
1277         {
1278           struct GNUNET_DNSPARSER_SrvRecord *srv;
1279
1280           off = 0;
1281           /* FIXME: passing rh->name here is is not necessarily what we want 
1282              (SRV support not finished) */
1283           srv = GNUNET_DNSPARSER_parse_srv (rh->name,
1284                                             rd[i].data,
1285                                             rd[i].data_size,
1286                                             &off);
1287           if ( (NULL == srv) ||
1288                (off != rd[i].data_size) )
1289           {
1290             GNUNET_break_op (0); /* record not well-formed */
1291           }
1292           else
1293           {
1294             srv->domain_name = translate_dot_plus (rh, srv->domain_name);
1295             srv->target = translate_dot_plus (rh, srv->target);
1296             scratch_start = scratch_off;
1297             if (GNUNET_OK !=
1298                 GNUNET_DNSPARSER_builder_add_srv (scratch,
1299                                                   sizeof (scratch),
1300                                                   &scratch_off,
1301                                                   srv))
1302             {
1303               GNUNET_break (0);
1304             }
1305             else
1306             {
1307               rd_new[rd_off].data = &scratch[scratch_start];
1308               rd_new[rd_off].data_size = scratch_off - scratch_start;
1309               rd_off++;
1310             }
1311           }
1312           if (NULL != srv)
1313             GNUNET_DNSPARSER_free_srv (srv);      
1314         }
1315         break;
1316       case GNUNET_NAMESTORE_TYPE_PKEY:
1317         /* tigger shortening */
1318         if (NULL != rh->shorten_key)
1319         {
1320           struct GNUNET_CRYPTO_EccPublicKey pub;
1321           
1322           if (rd[i].data_size != sizeof (struct GNUNET_CRYPTO_EccPublicKey))
1323           {
1324             GNUNET_break_op (0);
1325             break;
1326           }
1327           memcpy (&pub, rd[i].data, rd[i].data_size);
1328           GNS_shorten_start (rh->ac_tail->label,
1329                              &pub,
1330                              rh->shorten_key);
1331         }
1332       default:
1333         break;
1334       }
1335     }
1336     
1337     /* yes, we are done, return result */
1338     rh->proc (rh->proc_cls, rd_off, rd_new);
1339     GNS_resolver_lookup_cancel (rh);
1340     return;         
1341   }
1342   /* need to recurse, check if we can */
1343   for (i=0;i<rd_count;i++)
1344   {
1345     switch (rd[i].record_type)
1346     {
1347     case GNUNET_NAMESTORE_TYPE_PKEY:
1348       /* delegation to another zone */
1349       if (sizeof (struct GNUNET_CRYPTO_EccPublicKey) !=
1350           rd[i].data_size)
1351       {
1352         GNUNET_break_op (0);
1353         rh->proc (rh->proc_cls, 0, NULL);
1354         GNS_resolver_lookup_cancel (rh);
1355         return;     
1356       }
1357       /* expand authority chain */
1358       ac = GNUNET_new (struct AuthorityChain);
1359       ac->rh = rh;
1360       ac->gns_authority = GNUNET_YES;
1361       memcpy (&ac->authority_info.gns_authority,
1362               rd[i].data,
1363               sizeof (struct GNUNET_CRYPTO_EccPublicKey));
1364       ac->label = resolver_lookup_get_next_label (rh);
1365       /* tigger shortening */
1366       if (NULL != rh->shorten_key)      
1367         GNS_shorten_start (rh->ac_tail->label,
1368                            &ac->authority_info.gns_authority,
1369                            rh->shorten_key);      
1370       /* add AC to tail */
1371       GNUNET_CONTAINER_DLL_insert_tail (rh->ac_head,
1372                                         rh->ac_tail,
1373                                         ac);
1374       /* recurse */
1375       rh->task_id = GNUNET_SCHEDULER_add_now (&recursive_resolution,
1376                                               rh);
1377       break;
1378     case GNUNET_DNSPARSER_TYPE_NS:
1379       /* resolution continues within DNS */
1380       if (GNUNET_DNSPARSER_MAX_NAME_LENGTH < rd[i].data_size)
1381       {
1382         GNUNET_break_op (0);
1383         rh->proc (rh->proc_cls, 0, NULL);
1384         GNS_resolver_lookup_cancel (rh);
1385         return;     
1386       }
1387       /* find associated A/AAAA record */
1388       sa = NULL;
1389       sa_len = 0;
1390       for (j=0;j<rd_count;j++)
1391       {
1392         switch (rd[j].record_type)
1393         {
1394         case GNUNET_DNSPARSER_TYPE_A:
1395           if (sizeof (struct in_addr) != rd[i].data_size)
1396           {
1397             GNUNET_break_op (0);
1398             rh->proc (rh->proc_cls, 0, NULL);
1399             GNS_resolver_lookup_cancel (rh);
1400             return;     
1401           }
1402           /* FIXME: might want to check if we support IPv4 here,
1403              and otherwise skip this one and hope we find another */
1404           memset (&v4, 0, sizeof (v4));
1405           sa_len = sizeof (v4);
1406           v4.sin_family = AF_INET;
1407           v4.sin_port = htons (53);
1408 #if HAVE_SOCKADDR_IN_SIN_LEN
1409           v4.sin_len = (u_char) sa_len;
1410 #endif
1411           memcpy (&v4.sin_addr,
1412                   rd[j].data,
1413                   sizeof (struct in_addr));
1414           sa = (struct sockaddr *) &v4;
1415           break;
1416         case GNUNET_DNSPARSER_TYPE_AAAA:
1417           if (sizeof (struct in6_addr) != rd[i].data_size)
1418           {
1419             GNUNET_break_op (0);
1420             rh->proc (rh->proc_cls, 0, NULL);
1421             GNS_resolver_lookup_cancel (rh);
1422             return;     
1423           }
1424           /* FIXME: might want to check if we support IPv6 here,
1425              and otherwise skip this one and hope we find another */
1426           memset (&v6, 0, sizeof (v6));
1427           sa_len = sizeof (v6);
1428           v6.sin6_family = AF_INET6;
1429           v6.sin6_port = htons (53);
1430 #if HAVE_SOCKADDR_IN_SIN_LEN
1431           v6.sin6_len = (u_char) sa_len;
1432 #endif
1433           memcpy (&v6.sin6_addr,
1434                   rd[j].data,
1435                   sizeof (struct in6_addr));
1436           sa = (struct sockaddr *) &v6;
1437           break;
1438         default:
1439           break;
1440         }
1441         if (NULL != sa)
1442           break;
1443       }
1444       if (NULL == sa)
1445       {
1446         /* we cannot continue; NS without A/AAAA */
1447         rh->proc (rh->proc_cls, 0, NULL);
1448         GNS_resolver_lookup_cancel (rh);
1449         return;
1450       }
1451       /* expand authority chain */
1452       ac = GNUNET_new (struct AuthorityChain);
1453       ac->rh = rh;
1454       strncpy (ac->authority_info.dns_authority.name,
1455                rd[i].data,
1456                rd[i].data_size);
1457       ac->authority_info.dns_authority.name[rd[i].data_size] = '\0';
1458       memcpy (&ac->authority_info.dns_authority.dns_ip,
1459               sa,
1460               sa_len);
1461       /* for DNS recursion, the label is the full DNS name,
1462          created from the remainder of the GNS name and the
1463          name in the NS record */
1464       GNUNET_asprintf (&ac->label,
1465                        "%.*s%s",
1466                        (int) rh->name_resolution_pos,
1467                        rh->name,
1468                        ac->authority_info.dns_authority.name);
1469       GNUNET_CONTAINER_DLL_insert_tail (rh->ac_head,
1470                                         rh->ac_tail,
1471                                         ac);
1472       if (strlen (ac->label) > GNUNET_DNSPARSER_MAX_NAME_LENGTH)
1473       {
1474         GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1475                     _("GNS lookup resulted in DNS name that is too long (`%s')\n"),
1476                     ac->label);
1477         rh->proc (rh->proc_cls, 0, NULL);
1478         GNS_resolver_lookup_cancel (rh);
1479         return;
1480       }
1481       /* recurse */
1482       rh->task_id = GNUNET_SCHEDULER_add_now (&recursive_resolution,
1483                                               rh);
1484       return;
1485     case GNUNET_DNSPARSER_TYPE_CNAME:
1486       cname = GNUNET_strndup (rd[i].data,
1487                               rd[i].data_size);
1488       handle_gns_cname_result (rh, 
1489                                cname);
1490       GNUNET_free (cname);
1491       return;
1492       /* FIXME: handle DNAME */
1493     default:
1494       /* skip */
1495       break;
1496     }
1497   }
1498   GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1499               _("GNS lookup recursion failed (no delegation record found)\n"));
1500   rh->proc (rh->proc_cls, 0, NULL);
1501   GNS_resolver_lookup_cancel (rh);
1502 }
1503
1504
1505 /**
1506  * Function called once the namestore has completed the request for
1507  * caching a block.
1508  *
1509  * @param cls closure with the 'struct GNS_ResolverHandle'
1510  * @param success #GNUNET_OK on success
1511  * @param emsg error message
1512  */
1513 static void
1514 namestore_cache_continuation (void *cls,
1515                               int32_t success,
1516                               const char *emsg)
1517 {
1518   struct GNS_ResolverHandle *rh = cls;
1519
1520   rh->namestore_qe = NULL;
1521   if (NULL != emsg)
1522     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1523                 _("Failed to cache GNS resolution: %s\n"),
1524                 emsg);
1525 }
1526
1527
1528 /**
1529  * Iterator called on each result obtained for a DHT
1530  * operation that expects a reply
1531  *
1532  * @param cls closure with the 'struct GNS_ResolverHandle'
1533  * @param exp when will this value expire
1534  * @param key key of the result
1535  * @param get_path peers on reply path (or NULL if not recorded)
1536  *                 [0] = datastore's first neighbor, [length - 1] = local peer
1537  * @param get_path_length number of entries in get_path
1538  * @param put_path peers on the PUT path (or NULL if not recorded)
1539  *                 [0] = origin, [length - 1] = datastore
1540  * @param put_path_length number of entries in get_path
1541  * @param type type of the result
1542  * @param size number of bytes in data
1543  * @param data pointer to the result data
1544  */
1545 static void
1546 handle_dht_response (void *cls,
1547                      struct GNUNET_TIME_Absolute exp,
1548                      const struct GNUNET_HashCode * key,
1549                      const struct GNUNET_PeerIdentity *get_path,
1550                      unsigned int get_path_length,
1551                      const struct GNUNET_PeerIdentity *put_path, 
1552                      unsigned int put_path_length,
1553                      enum GNUNET_BLOCK_Type type,
1554                      size_t size, const void *data)
1555 {
1556   struct GNS_ResolverHandle *rh = cls;
1557   struct AuthorityChain *ac = rh->ac_tail;
1558   const struct GNUNET_NAMESTORE_Block *block;
1559   
1560   GNUNET_DHT_get_stop (rh->get_handle);
1561   rh->get_handle = NULL;
1562   GNUNET_CONTAINER_heap_remove_node (rh->dht_heap_node);
1563   rh->dht_heap_node = NULL;  
1564   if (size < sizeof (struct GNUNET_NAMESTORE_Block))
1565   {
1566     /* how did this pass DHT block validation!? */
1567     GNUNET_break (0);
1568     rh->proc (rh->proc_cls, 0, NULL);
1569     GNS_resolver_lookup_cancel (rh);
1570     return;   
1571   }
1572   block = data; 
1573   if (size !=
1574       ntohs (block->purpose.size) + 
1575       sizeof (struct GNUNET_CRYPTO_EccPublicKey) +
1576       sizeof (struct GNUNET_CRYPTO_EccSignature))
1577   {
1578     /* how did this pass DHT block validation!? */
1579     GNUNET_break (0);
1580     rh->proc (rh->proc_cls, 0, NULL);
1581     GNS_resolver_lookup_cancel (rh);
1582     return;   
1583   }
1584   if (GNUNET_OK !=
1585       GNUNET_NAMESTORE_block_decrypt (block,
1586                                       &ac->authority_info.gns_authority,
1587                                       ac->label,
1588                                       &handle_gns_resolution_result,
1589                                       rh))
1590   {
1591     GNUNET_break_op (0); /* block was ill-formed */
1592     rh->proc (rh->proc_cls, 0, NULL);
1593     GNS_resolver_lookup_cancel (rh);
1594     return;
1595   }
1596   /* Cache well-formed blocks */
1597   rh->namestore_qe = GNUNET_NAMESTORE_block_cache (namestore_handle,
1598                                                    block,
1599                                                    &namestore_cache_continuation,
1600                                                    rh);
1601 }
1602
1603
1604 /**
1605  * Process a record that was stored in the namestore.
1606  *
1607  * @param cls closure with the `struct GNS_ResolverHandle`
1608  * @param block block that was stored in the namestore
1609  */
1610 static void 
1611 handle_namestore_block_response (void *cls,
1612                                  const struct GNUNET_NAMESTORE_Block *block)
1613 {
1614   struct GNS_ResolverHandle *rh = cls;
1615   struct GNS_ResolverHandle *rx;
1616   struct AuthorityChain *ac = rh->ac_tail;
1617   const char *label = ac->label;
1618   const struct GNUNET_CRYPTO_EccPublicKey *auth = &ac->authority_info.gns_authority;
1619   struct GNUNET_HashCode query;
1620
1621   GNUNET_NAMESTORE_query_from_public_key (auth,
1622                                           label,
1623                                           &query);
1624   rh->namestore_qe = NULL;
1625   if ( (GNUNET_NO == rh->only_cached) &&
1626        ( (NULL == block) ||
1627          (0 == GNUNET_TIME_absolute_get_remaining (GNUNET_TIME_absolute_ntoh (block->expiration_time)).rel_value_us) ) )
1628   {
1629     /* Namestore knows nothing; try DHT lookup */
1630     rh->get_handle = GNUNET_DHT_get_start (dht_handle,
1631                                            GNUNET_BLOCK_TYPE_GNS_NAMERECORD,
1632                                            &query,
1633                                            DHT_GNS_REPLICATION_LEVEL,
1634                                            GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE,
1635                                            NULL, 0,
1636                                            &handle_dht_response, rh);
1637     rh->dht_heap_node = GNUNET_CONTAINER_heap_insert (dht_lookup_heap,
1638                                                       rh,
1639                                                       GNUNET_TIME_absolute_get ().abs_value_us);
1640     if (GNUNET_CONTAINER_heap_get_size (dht_lookup_heap) > max_allowed_background_queries)
1641     {
1642       /* fail longest-standing DHT request */
1643       rx = GNUNET_CONTAINER_heap_peek (dht_lookup_heap);
1644       rx->proc (rx->proc_cls, 0, NULL);
1645       GNS_resolver_lookup_cancel (rx);
1646     }
1647     return;
1648   }
1649   if ( (NULL == block) ||
1650        (0 == GNUNET_TIME_absolute_get_remaining (GNUNET_TIME_absolute_ntoh (block->expiration_time)).rel_value_us) )
1651   {
1652     /* DHT not permitted and no local result, fail */
1653     rh->proc (rh->proc_cls, 0, NULL);
1654     GNS_resolver_lookup_cancel (rh);
1655     return;
1656   }
1657   if (GNUNET_OK !=
1658       GNUNET_NAMESTORE_block_decrypt (block,
1659                                       auth,
1660                                       label,
1661                                       &handle_gns_resolution_result,
1662                                       rh))
1663   {
1664     GNUNET_break_op (0); /* block was ill-formed */
1665     rh->proc (rh->proc_cls, 0, NULL);
1666     GNS_resolver_lookup_cancel (rh);
1667     return;
1668   }
1669 }
1670
1671
1672 /**
1673  * Lookup tail of our authority chain in the namestore.
1674  *
1675  * @param rh query we are processing
1676  */
1677 static void
1678 recursive_gns_resolution_namestore (struct GNS_ResolverHandle *rh)
1679 {
1680   struct AuthorityChain *ac = rh->ac_tail;
1681   struct GNUNET_HashCode query;
1682
1683   GNUNET_NAMESTORE_query_from_public_key (&ac->authority_info.gns_authority,
1684                                           ac->label,
1685                                           &query);
1686   rh->namestore_qe = GNUNET_NAMESTORE_lookup_block (namestore_handle,
1687                                                     &query,
1688                                                     &handle_namestore_block_response,
1689                                                     rh);
1690 }
1691
1692
1693 /**
1694  * Task scheduled to continue with the resolution process.
1695  *
1696  * @param cls the `struct GNS_ResolverHandle` of the resolution
1697  * @param tc task context
1698  */
1699 static void
1700 recursive_resolution (void *cls,
1701                       const struct GNUNET_SCHEDULER_TaskContext *tc)
1702 {
1703   struct GNS_ResolverHandle *rh = cls;
1704
1705   rh->task_id = GNUNET_SCHEDULER_NO_TASK;
1706   if (MAX_RECURSION < rh->loop_limiter++)
1707   {
1708     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1709                 "Encountered unbounded recursion resolving `%s'\n",
1710                 rh->name);
1711     rh->proc (rh->proc_cls, 0, NULL);
1712     GNS_resolver_lookup_cancel (rh);
1713     return;
1714   }
1715   if (GNUNET_YES == rh->ac_tail->gns_authority)
1716     recursive_gns_resolution_namestore (rh);
1717   else
1718     recursive_dns_resolution (rh);
1719 }
1720
1721
1722 /**
1723  * Begin the resolution process from 'name', starting with
1724  * the identification of the zone specified by 'name'.
1725  *
1726  * @param rh resolution to perform
1727  */
1728 static void
1729 start_resolver_lookup (struct GNS_ResolverHandle *rh)
1730 {
1731   struct AuthorityChain *ac;
1732   char *x;
1733   char *y;
1734   char *pkey;
1735
1736   if ( ( (GNUNET_YES == is_canonical (rh->name)) &&
1737          (0 != strcmp (GNUNET_GNS_TLD, rh->name)) ) ||
1738        ( (GNUNET_YES != is_gnu_tld (rh->name)) &&
1739          (GNUNET_YES != is_zkey_tld (rh->name)) ) )
1740   {
1741     /* use standard DNS lookup */
1742     int af;
1743
1744     switch (rh->record_type)
1745     {
1746     case GNUNET_DNSPARSER_TYPE_A:
1747       af = AF_INET;
1748       break;
1749     case GNUNET_DNSPARSER_TYPE_AAAA:
1750       af = AF_INET6;
1751       break;
1752     default:
1753       af = AF_UNSPEC;
1754       break;
1755     }
1756     rh->std_resolve = GNUNET_RESOLVER_ip_get (rh->name, 
1757                                               af,
1758                                               DNS_LOOKUP_TIMEOUT,
1759                                               &handle_dns_result,
1760                                               rh);
1761     return;
1762   }
1763   if (is_zkey_tld (rh->name))
1764   {
1765     /* Name ends with ".zkey", try to replace authority zone with zkey
1766        authority */
1767     GNUNET_free (resolver_lookup_get_next_label (rh)); /* will return "zkey" */
1768     x = resolver_lookup_get_next_label (rh); /* will return 'x' coordinate */
1769     y = resolver_lookup_get_next_label (rh); /* will return 'y' coordinate */
1770     GNUNET_asprintf (&pkey,
1771                      "%s%s",
1772                      x, y);
1773     if ( (NULL == x) ||
1774          (NULL == y) ||
1775          (GNUNET_OK !=
1776           GNUNET_CRYPTO_ecc_public_key_from_string (pkey,
1777                                                     strlen (pkey),
1778                                                     &rh->authority_zone)) )
1779     {
1780       GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1781                   _("Hostname `%s' is not well-formed, resolution fails\n"),
1782                   rh->name);
1783       rh->task_id = GNUNET_SCHEDULER_add_now (&fail_resolution, rh);
1784     }
1785     GNUNET_free_non_null (x);
1786     GNUNET_free_non_null (y);
1787     GNUNET_free (pkey);
1788   }
1789   else
1790   {
1791     /* Name ends with ".gnu", eat ".gnu" and continue with resolution */
1792     GNUNET_free (resolver_lookup_get_next_label (rh));
1793   }
1794   ac = GNUNET_new (struct AuthorityChain);
1795   ac->rh = rh;
1796   ac->label = resolver_lookup_get_next_label (rh);
1797   if (NULL == ac->label)
1798     /* name was just "gnu", so we default to label '+' */
1799     ac->label = GNUNET_strdup (GNUNET_GNS_MASTERZONE_STR);
1800   ac->gns_authority = GNUNET_YES;
1801   ac->authority_info.gns_authority = rh->authority_zone;
1802   GNUNET_CONTAINER_DLL_insert_tail (rh->ac_head,
1803                                     rh->ac_tail,
1804                                     ac);
1805   rh->task_id = GNUNET_SCHEDULER_add_now (&recursive_resolution,
1806                                           rh);
1807 }
1808
1809
1810 /**
1811  * Lookup of a record in a specific zone calls lookup result processor
1812  * on result.
1813  *
1814  * @param zone the zone to perform the lookup in
1815  * @param record_type the record type to look up
1816  * @param name the name to look up
1817  * @param shorten_key a private key for use with PSEU import (can be NULL)
1818  * @param only_cached #GNUNET_NO to only check locally not DHT for performance
1819  * @param proc the processor to call on result
1820  * @param proc_cls the closure to pass to @a proc
1821  * @return handle to cancel operation
1822  */
1823 struct GNS_ResolverHandle *
1824 GNS_resolver_lookup (const struct GNUNET_CRYPTO_EccPublicKey *zone,
1825                      uint32_t record_type,
1826                      const char *name,
1827                      const struct GNUNET_CRYPTO_EccPrivateKey *shorten_key,
1828                      int only_cached,
1829                      GNS_ResultProcessor proc, void *proc_cls)
1830 {
1831   struct GNS_ResolverHandle *rh;
1832
1833   rh = GNUNET_new (struct GNS_ResolverHandle);
1834   GNUNET_CONTAINER_DLL_insert (rlh_head,
1835                                rlh_tail,
1836                                rh);
1837   rh->authority_zone = *zone;
1838   rh->proc = proc;
1839   rh->proc_cls = proc_cls;
1840   rh->only_cached = only_cached;
1841   rh->record_type = record_type;
1842   rh->name = GNUNET_strdup (name);
1843   rh->name_resolution_pos = strlen (name);
1844   if (NULL != shorten_key)
1845   {
1846     rh->shorten_key = GNUNET_new (struct GNUNET_CRYPTO_EccPrivateKey);
1847     *rh->shorten_key = *shorten_key;
1848   }
1849   start_resolver_lookup (rh);
1850   return rh;
1851 }
1852
1853
1854 /**
1855  * Cancel active resolution (i.e. client disconnected).
1856  *
1857  * @param rh resolution to abort
1858  */
1859 void
1860 GNS_resolver_lookup_cancel (struct GNS_ResolverHandle *rh)
1861 {
1862   struct DnsResult *dr;
1863   struct AuthorityChain *ac;
1864   struct VpnContext *vpn_ctx;
1865
1866   GNUNET_CONTAINER_DLL_remove (rlh_head,
1867                                rlh_tail,
1868                                rh);
1869   while (NULL != (ac = rh->ac_head))
1870   {
1871     GNUNET_CONTAINER_DLL_remove (rh->ac_head,
1872                                  rh->ac_tail,
1873                                  ac);
1874     GNUNET_free (ac->label);
1875     GNUNET_free (ac);
1876   }
1877   if (GNUNET_SCHEDULER_NO_TASK != rh->task_id)
1878   {
1879     GNUNET_SCHEDULER_cancel (rh->task_id);
1880     rh->task_id = GNUNET_SCHEDULER_NO_TASK;
1881   }
1882   if (NULL != rh->get_handle)
1883   {
1884     GNUNET_DHT_get_stop (rh->get_handle);
1885     rh->get_handle = NULL;
1886   }
1887   if (NULL != rh->dht_heap_node)
1888   {
1889     GNUNET_CONTAINER_heap_remove_node (rh->dht_heap_node);
1890     rh->dht_heap_node = NULL;
1891   }
1892   if (NULL != (vpn_ctx = rh->vpn_ctx))
1893   {
1894     GNUNET_VPN_cancel_request (vpn_ctx->vpn_request);
1895     GNUNET_free (vpn_ctx->rd_data);
1896     GNUNET_free (vpn_ctx);
1897   }
1898   if (NULL != rh->dns_request)
1899   {
1900     GNUNET_DNSSTUB_resolve_cancel (rh->dns_request);
1901     rh->dns_request = NULL;
1902   }
1903   if (NULL != rh->namestore_qe)
1904   {
1905     GNUNET_NAMESTORE_cancel (rh->namestore_qe);
1906     rh->namestore_qe = NULL;
1907   }
1908   if (NULL != rh->std_resolve)
1909   {
1910     GNUNET_RESOLVER_request_cancel (rh->std_resolve);
1911     rh->std_resolve = NULL;
1912   }
1913   while (NULL != (dr = rh->dns_result_head))
1914   {
1915     GNUNET_CONTAINER_DLL_remove (rh->dns_result_head,
1916                                  rh->dns_result_tail,
1917                                  dr);
1918     GNUNET_free (dr);
1919   }
1920   GNUNET_free_non_null (rh->shorten_key);
1921   GNUNET_free (rh->name);
1922   GNUNET_free (rh);
1923 }
1924
1925
1926 /* ***************** Resolver initialization ********************* */
1927
1928
1929 /**
1930  * Initialize the resolver
1931  *
1932  * @param nh the namestore handle
1933  * @param dht the dht handle
1934  * @param c configuration handle
1935  * @param max_bg_queries maximum number of parallel background queries in dht
1936  */
1937 void
1938 GNS_resolver_init (struct GNUNET_NAMESTORE_Handle *nh,
1939                    struct GNUNET_DHT_Handle *dht,
1940                    const struct GNUNET_CONFIGURATION_Handle *c,
1941                    unsigned long long max_bg_queries)
1942 {
1943   char *dns_ip;
1944
1945   cfg = c;
1946   namestore_handle = nh;
1947   dht_handle = dht;
1948   dht_lookup_heap =
1949     GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN);
1950   max_allowed_background_queries = max_bg_queries;
1951   if (GNUNET_OK !=
1952       GNUNET_CONFIGURATION_get_value_string (c,
1953                                              "gns",
1954                                              "DNS_RESOLVER",
1955                                              &dns_ip))
1956   {
1957     /* user did not specify DNS resolver, use 8.8.8.8 */
1958     dns_ip = GNUNET_strdup ("8.8.8.8");
1959   }
1960   dns_handle = GNUNET_DNSSTUB_start (dns_ip);
1961   GNUNET_free (dns_ip);
1962   vpn_handle = GNUNET_VPN_connect (cfg);
1963 }
1964
1965
1966 /**
1967  * Shutdown resolver
1968  */
1969 void
1970 GNS_resolver_done ()
1971 {
1972   struct GNS_ResolverHandle *rh;
1973
1974   /* abort active resolutions */
1975   while (NULL != (rh = rlh_head))
1976   {
1977     rh->proc (rh->proc_cls, 0, NULL);
1978     GNS_resolver_lookup_cancel (rh);    
1979   }
1980   GNUNET_CONTAINER_heap_destroy (dht_lookup_heap);
1981   dht_lookup_heap = NULL;
1982   GNUNET_DNSSTUB_stop (dns_handle);
1983   dns_handle = NULL;
1984   GNUNET_VPN_disconnect (vpn_handle);
1985   vpn_handle = NULL;
1986   dht_handle = NULL;
1987   namestore_handle = NULL;
1988 }
1989
1990
1991 /* *************** common helper functions (do not really belong here) *********** */
1992
1993 /**
1994  * Checks if @a name ends in ".TLD"
1995  *
1996  * @param name the name to check
1997  * @param tld the TLD to check for
1998  * @return GNUNET_YES or GNUNET_NO
1999  */
2000 int
2001 is_tld (const char* name, const char* tld)
2002 {
2003   size_t offset = 0;
2004
2005   if (strlen (name) <= strlen (tld))
2006     return GNUNET_NO;
2007   offset = strlen (name) - strlen (tld);
2008   if (0 != strcmp (name + offset, tld))
2009     return GNUNET_NO;
2010   return GNUNET_YES;
2011 }
2012
2013
2014 /* end of gnunet-service-gns_resolver.c */