Merge branch 'master' of gnunet.org:gnunet
[oweals/gnunet.git] / src / gns / gnunet-service-gns_resolver.c
1 /*
2      This file is part of GNUnet.
3      Copyright (C) 2011-2013 GNUnet e.V.
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., 51 Franklin Street, Fifth Floor,
18      Boston, MA 02110-1301, 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 #include "platform.h"
28 #include "gnunet_util_lib.h"
29 #include "gnunet_dnsstub_lib.h"
30 #include "gnunet_dht_service.h"
31 #include "gnunet_gnsrecord_lib.h"
32 #include "gnunet_namecache_service.h"
33 #include "gnunet_dns_service.h"
34 #include "gnunet_resolver_service.h"
35 #include "gnunet_revocation_service.h"
36 #include "gnunet_dnsparser_lib.h"
37 #include "gnunet_tun_lib.h"
38 #include "gnunet_gns_service.h"
39 #include "gns.h"
40 #include "gnunet-service-gns.h"
41 #include "gnunet-service-gns_resolver.h"
42 #include "gnunet_vpn_service.h"
43
44
45 /**
46  * Default DHT timeout for lookups.
47  */
48 #define DHT_LOOKUP_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 60)
49
50 /**
51  * Default timeout for DNS lookups.
52  */
53 #define DNS_LOOKUP_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 15)
54
55 /**
56  * Default timeout for VPN redirections.
57  */
58 #define VPN_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 30)
59
60 /**
61  * DHT replication level
62  */
63 #define DHT_GNS_REPLICATION_LEVEL 5
64
65 /**
66  * How deep do we allow recursions to go before we abort?
67  */
68 #define MAX_RECURSION 256
69
70
71 /**
72  * DLL to hold the authority chain we had to pass in the resolution
73  * process.
74  */
75 struct AuthorityChain
76 {
77   /**
78    * This is a DLL.
79    */
80   struct AuthorityChain *prev;
81
82   /**
83    * This is a DLL.
84    */
85   struct AuthorityChain *next;
86
87   /**
88    * Resolver handle this entry in the chain belongs to.
89    */
90   struct GNS_ResolverHandle *rh;
91
92   /**
93    * label/name corresponding to the authority
94    */
95   char *label;
96
97   /**
98    * label/name suggested for shortening to the authority
99    */
100   char *suggested_shortening_label;
101
102   /**
103    * Do we already try to shorten this authority?
104    */
105   int shortening_started;
106
107   /**
108    * #GNUNET_YES if the authority was a GNS authority,
109    * #GNUNET_NO if the authority was a DNS authority.
110    */
111   int gns_authority;
112
113   /**
114    * Information about the resolver authority for this label.
115    */
116   union
117   {
118
119     /**
120      * The zone of the GNS authority
121      */
122     struct GNUNET_CRYPTO_EcdsaPublicKey gns_authority;
123
124     struct
125     {
126       /**
127        * Domain of the DNS resolver that is the authority.
128        * (appended to construct the DNS name to resolve;
129        * this is NOT the DNS name of the DNS server!).
130        */
131       char name[GNUNET_DNSPARSER_MAX_NAME_LENGTH + 1];
132
133       /**
134        * IP address of the DNS resolver that is authoritative.
135        * (this implementation currently only supports one
136        * IP at a time).
137        */
138       struct sockaddr_storage dns_ip;
139
140     } dns_authority;
141
142   } authority_info;
143
144 };
145
146
147 /**
148  * A result we got from DNS.
149  */
150 struct DnsResult
151 {
152
153   /**
154    * Kept in DLL.
155    */
156   struct DnsResult *next;
157
158   /**
159    * Kept in DLL.
160    */
161   struct DnsResult *prev;
162
163   /**
164    * Binary value stored in the DNS record (appended to this struct)
165    */
166   const void *data;
167
168   /**
169    * Expiration time for the DNS record, 0 if we didn't
170    * get anything useful (i.e. 'gethostbyname()' was used).
171    */
172   uint64_t expiration_time;
173
174   /**
175    * Number of bytes in @e data.
176    */
177   size_t data_size;
178
179   /**
180    * Type of the GNS/DNS record.
181    */
182   uint32_t record_type;
183
184 };
185
186
187 /**
188  * Closure for #vpn_allocation_cb.
189  */
190 struct VpnContext
191 {
192
193   /**
194    * Which resolution process are we processing.
195    */
196   struct GNS_ResolverHandle *rh;
197
198   /**
199    * Handle to the VPN request that we were performing.
200    */
201   struct GNUNET_VPN_RedirectionRequest *vpn_request;
202
203   /**
204    * Number of records serialized in @e rd_data.
205    */
206   unsigned int rd_count;
207
208   /**
209    * Serialized records.
210    */
211   char *rd_data;
212
213   /**
214    * Number of bytes in @e rd_data.
215    */
216   size_t rd_data_size;
217 };
218
219
220 /**
221  * Information we keep during the resolution of an
222  * IP address for a DNS server while handling a
223  * GNS2DNS record.
224  */
225 struct Gns2DnsContext
226 {
227
228   /**
229    * DNS domain in which the resolution will continue
230    * (first part of the GNS2DNS record).
231    */
232   char *ns;
233
234   /**
235    * Handle for the resolution of the IP part of the
236    * GNS2DNS record.  Will return to us the addresses
237    * of the DNS resolver to use.
238    */
239   struct GNS_ResolverHandle *rh;
240
241   /**
242    * Handle for DNS resolution of the DNS nameserver.
243    */
244   struct GNUNET_RESOLVER_RequestHandle *dns_rh;
245 };
246
247
248 /**
249  * Handle to a currenty pending resolution.  On result (positive or
250  * negative) the #GNS_ResultProcessor is called.
251  */
252 struct GNS_ResolverHandle
253 {
254
255   /**
256    * DLL
257    */
258   struct GNS_ResolverHandle *next;
259
260   /**
261    * DLL
262    */
263   struct GNS_ResolverHandle *prev;
264
265   /**
266    * The top-level GNS authoritative zone to query
267    */
268   struct GNUNET_CRYPTO_EcdsaPublicKey authority_zone;
269
270   /**
271    * called when resolution phase finishes
272    */
273   GNS_ResultProcessor proc;
274
275   /**
276    * closure passed to @e proc
277    */
278   void* proc_cls;
279
280   /**
281    * Handle used during GNS2DNS resolution for looking up the
282    * IP address of the DNS server.
283    */
284   struct Gns2DnsContext *g2dc;
285
286   /**
287    * Handle for DHT lookups. should be NULL if no lookups are in progress
288    */
289   struct GNUNET_DHT_GetHandle *get_handle;
290
291   /**
292    * Handle to a VPN request, NULL if none is active.
293    */
294   struct VpnContext *vpn_ctx;
295
296   /**
297    * Socket for a DNS request, NULL if none is active.
298    */
299   struct GNUNET_DNSSTUB_RequestSocket *dns_request;
300
301   /**
302    * Handle for standard DNS resolution, NULL if none is active.
303    */
304   struct GNUNET_RESOLVER_RequestHandle *std_resolve;
305
306   /**
307    * Pending Namecache lookup task
308    */
309   struct GNUNET_NAMECACHE_QueueEntry *namecache_qe;
310
311   /**
312    * Pending revocation check.
313    */
314   struct GNUNET_REVOCATION_Query *rev_check;
315
316   /**
317    * Heap node associated with this lookup.  Used to limit number of
318    * concurrent requests.
319    */
320   struct GNUNET_CONTAINER_HeapNode *dht_heap_node;
321
322   /**
323    * DLL to store the authority chain
324    */
325   struct AuthorityChain *ac_head;
326
327   /**
328    * DLL to store the authority chain
329    */
330   struct AuthorityChain *ac_tail;
331
332   /**
333    * ID of a task associated with the resolution process.
334    */
335   struct GNUNET_SCHEDULER_Task *task_id;
336
337   /**
338    * The name to resolve
339    */
340   char *name;
341
342   /**
343    * DLL of results we got from DNS.
344    */
345   struct DnsResult *dns_result_head;
346
347   /**
348    * DLL of results we got from DNS.
349    */
350   struct DnsResult *dns_result_tail;
351
352   /**
353    * Current offset in 'name' where we are resolving.
354    */
355   size_t name_resolution_pos;
356
357   /**
358    * Use only cache
359    */
360   enum GNUNET_GNS_LocalOptions options;
361
362   /**
363    * For SRV and TLSA records, the number of the
364    * protocol specified in the name.  0 if no protocol was given.
365    */
366   int protocol;
367
368   /**
369    * For SRV and TLSA records, the number of the
370    * service specified in the name.  0 if no service was given.
371    */
372   int service;
373
374   /**
375    * Desired type for the resolution.
376    */
377   int record_type;
378
379   /**
380    * We increment the loop limiter for each step in a recursive
381    * resolution.  If it passes our threshold (i.e. due to
382    * self-recursion in the resolution, i.e CNAME fun), we stop.
383    */
384   unsigned int loop_limiter;
385
386   /**
387    * 16 bit random ID we used in the @e dns_request.
388    */
389   uint16_t original_dns_id;
390
391 };
392
393
394 /**
395  * Active namestore caching operations.
396  */
397 struct CacheOps
398 {
399
400   /**
401    * Organized in a DLL.
402    */
403   struct CacheOps *next;
404
405   /**
406    * Organized in a DLL.
407    */
408   struct CacheOps *prev;
409
410   /**
411    * Pending Namestore caching task.
412    */
413   struct GNUNET_NAMECACHE_QueueEntry *namecache_qe_cache;
414
415 };
416
417
418 /**
419  * Our handle to the namecache service
420  */
421 static struct GNUNET_NAMECACHE_Handle *namecache_handle;
422
423 /**
424  * Our handle to the vpn service
425  */
426 static struct GNUNET_VPN_Handle *vpn_handle;
427
428 /**
429  * Resolver handle to the dht
430  */
431 static struct GNUNET_DHT_Handle *dht_handle;
432
433 /**
434  * Handle to perform DNS lookups.
435  */
436 static struct GNUNET_DNSSTUB_Context *dns_handle;
437
438 /**
439  * Heap for limiting parallel DHT lookups
440  */
441 static struct GNUNET_CONTAINER_Heap *dht_lookup_heap;
442
443 /**
444  * Maximum amount of parallel queries to the DHT
445  */
446 static unsigned long long max_allowed_background_queries;
447
448 /**
449  * Head of resolver lookup list
450  */
451 static struct GNS_ResolverHandle *rlh_head;
452
453 /**
454  * Tail of resolver lookup list
455  */
456 static struct GNS_ResolverHandle *rlh_tail;
457
458 /**
459  * Organized in a DLL.
460  */
461 static struct CacheOps *co_head;
462
463 /**
464  * Organized in a DLL.
465  */
466 static struct CacheOps *co_tail;
467
468 /**
469  * Use namecache
470  */
471 static int use_cache;
472
473 /**
474  * Global configuration.
475  */
476 static const struct GNUNET_CONFIGURATION_Handle *cfg;
477
478
479 /**
480  * Determine if this name is canonical (is a legal name in a zone, without delegation);
481  * note that we do not test that the name does not contain illegal characters, we only
482  * test for delegation.  Note that service records (i.e. _foo._srv) are canonical names
483  * even though they consist of multiple labels.
484  *
485  * Examples:
486  * a.b.gnu   = not canonical
487  * a         = canonical
488  * _foo._srv = canonical
489  * _f.bar    = not canonical
490  *
491  * @param name the name to test
492  * @return #GNUNET_YES if canonical
493  */
494 /* dead, but keep for now */ int
495 is_canonical (const char *name)
496 {
497   const char *pos;
498   const char *dot;
499
500   if (NULL == strchr (name,
501                       (unsigned char) '.'))
502     return GNUNET_YES;
503   if ('_' != name[0])
504     return GNUNET_NO;
505   pos = &name[1];
506   while (NULL != (dot = strchr (pos,
507                                 (unsigned char) '.')))
508     if ('_' != dot[1])
509       return GNUNET_NO;
510     else
511       pos = dot + 1;
512   return GNUNET_YES;
513 }
514
515 /* ************************** Resolution **************************** */
516
517 /**
518  * Expands a name ending in .+ with the zone of origin.
519  *
520  * @param rh resolution context
521  * @param name name to modify (to be free'd or returned)
522  * @return updated name
523  */
524 static char *
525 translate_dot_plus (struct GNS_ResolverHandle *rh,
526                     char *name)
527 {
528   char *ret;
529   size_t s_len = strlen (name);
530
531   if (0 != strcmp (&name[s_len - 2],
532                    ".+"))
533     return name; /* did not end in ".+" */
534   GNUNET_assert (GNUNET_YES == rh->ac_tail->gns_authority);
535   GNUNET_asprintf (&ret,
536                    "%.*s.%s",
537                    (int) (s_len - 2),
538                    name,
539                    GNUNET_GNSRECORD_pkey_to_zkey (&rh->ac_tail->authority_info.gns_authority));
540   GNUNET_free (name);
541   return ret;
542 }
543
544
545 /**
546  * Task scheduled to asynchronously fail a resolution.
547  *
548  * @param cls the 'struct GNS_ResolverHandle' of the resolution to fail
549  */
550 static void
551 fail_resolution (void *cls)
552 {
553   struct GNS_ResolverHandle *rh = cls;
554
555   rh->task_id = NULL;
556   rh->proc (rh->proc_cls, 0, NULL);
557   GNS_resolver_lookup_cancel (rh);
558 }
559
560
561 #if (defined WINDOWS) || (defined DARWIN)
562 /* Don't have this on W32, here's a naive implementation
563  * Was somehow removed on OS X ...  */
564 static void *
565 memrchr (const void *s,
566          int c,
567          size_t n)
568 {
569   const unsigned char *ucs = s;
570   ssize_t i;
571
572   for (i = n - 1; i >= 0; i--)
573     if (c == (int) ucs[i])
574       return (void *) &ucs[i];
575   return NULL;
576 }
577 #endif
578
579
580 /**
581  * Get the next, rightmost label from the name that we are trying to resolve,
582  * and update the resolution position accordingly.  Labels usually consist
583  * of up to 63 characters without a period ("."); however, we use a special
584  * convention to support SRV and TLSA records where the domain name
585  * includes an encoding for a service and protocol in the name.  The
586  * syntax (see RFC 2782) here is "_Service._Proto.Name" and in this
587  * special case we include the "_Service._Proto" in the rightmost label.
588  * Thus, for "_443._tcp.foo.bar" we first return the label "bar" and then
589  * the label "_443._tcp.foo".  The special case is detected by the
590  * presence of labels beginning with an underscore.  Whenever a label
591  * begins with an underscore, it is combined with the label to its right
592  * (and the "." is preserved).
593  *
594  * @param rh handle to the resolution operation to get the next label from
595  * @return NULL if there are no more labels
596  */
597 static char *
598 resolver_lookup_get_next_label (struct GNS_ResolverHandle *rh)
599 {
600   const char *rp;
601   const char *dot;
602   size_t len;
603   char *ret;
604   char *srv_name;
605   char *proto_name;
606   struct protoent *pe;
607   struct servent *se;
608
609   if (0 == rh->name_resolution_pos)
610     return NULL;
611   dot = memrchr (rh->name,
612                  (int) '.',
613                  rh->name_resolution_pos);
614   if (NULL == dot)
615   {
616     /* done, this was the last one */
617     len = rh->name_resolution_pos;
618     rp = rh->name;
619     rh->name_resolution_pos = 0;
620   }
621   else
622   {
623     /* advance by one label */
624     len = rh->name_resolution_pos - (dot - rh->name) - 1;
625     rp = dot + 1;
626     rh->name_resolution_pos = dot - rh->name;
627   }
628   rh->protocol = 0;
629   rh->service = 0;
630   ret = GNUNET_strndup (rp, len);
631   /* If we have labels starting with underscore with label on
632    * the right (SRV/DANE/BOX case), determine port/protocol;
633    * The format of `rh->name` must be "_PORT._PROTOCOL".
634    */
635   if ( ('_' == rh->name[0]) &&
636        (NULL != (dot = memrchr (rh->name,
637                                 (int) '.',
638                                 rh->name_resolution_pos))) &&
639        ('_' == dot[1]) &&
640        (NULL == memrchr (rh->name,
641                          (int) '.',
642                          dot - rh->name)) )
643   {
644     srv_name = GNUNET_strndup (&rh->name[1],
645                                (dot - rh->name) - 1);
646     proto_name = GNUNET_strndup (&dot[2],
647                                  rh->name_resolution_pos - (dot - rh->name) - 1);
648     rh->name_resolution_pos = 0;
649     pe = getprotobyname (proto_name);
650     if (NULL == pe)
651     {
652       GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
653                   _("Protocol `%s' unknown, skipping labels.\n"),
654                   proto_name);
655       GNUNET_free (proto_name);
656       GNUNET_free (srv_name);
657       return ret;
658     }
659     se = getservbyname (srv_name,
660                         proto_name);
661     if (NULL == se)
662     {
663       GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
664                   _("Service `%s' unknown for protocol `%s', skipping labels.\n"),
665                   srv_name,
666                   proto_name);
667       GNUNET_free (proto_name);
668       GNUNET_free (srv_name);
669       return ret;
670     }
671     rh->protocol = pe->p_proto;
672     rh->service = se->s_port;
673     GNUNET_free (proto_name);
674     GNUNET_free (srv_name);
675   }
676   return ret;
677 }
678
679
680 /**
681  * Gives the cummulative result obtained to the callback and clean up the request.
682  *
683  * @param rh resolution process that has culminated in a result
684  */
685 static void
686 transmit_lookup_dns_result (struct GNS_ResolverHandle *rh)
687 {
688   struct DnsResult *pos;
689   unsigned int n;
690   unsigned int i;
691
692   n = 0;
693   for (pos = rh->dns_result_head; NULL != pos; pos = pos->next)
694     n++;
695   {
696     struct GNUNET_GNSRECORD_Data rd[n];
697
698     i = 0;
699     for (pos = rh->dns_result_head; NULL != pos; pos = pos->next)
700     {
701       rd[i].data = pos->data;
702       rd[i].data_size = pos->data_size;
703       rd[i].record_type = pos->record_type;
704       if (0 == pos->expiration_time)
705       {
706         rd[i].flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION;
707         rd[i].expiration_time = 0;
708       }
709       else
710       {
711         rd[i].flags = GNUNET_GNSRECORD_RF_NONE;
712         rd[i].expiration_time = pos->expiration_time;
713       }
714       i++;
715     }
716     GNUNET_assert (i == n);
717     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
718                 "Transmitting standard DNS result with %u records\n",
719                 n);
720     rh->proc (rh->proc_cls,
721               n,
722               rd);
723   }
724   GNS_resolver_lookup_cancel (rh);
725 }
726
727
728 /**
729  * Add a result from DNS to the records to be returned to the application.
730  *
731  * @param rh resolution request to extend with a result
732  * @param expiration_time expiration time for the answer
733  * @param record_type DNS record type of the answer
734  * @param data_size number of bytes in @a data
735  * @param data binary data to return in DNS record
736  */
737 static void
738 add_dns_result (struct GNS_ResolverHandle *rh,
739                 uint64_t expiration_time,
740                 uint32_t record_type,
741                 size_t data_size,
742                 const void *data)
743 {
744   struct DnsResult *res;
745
746   res = GNUNET_malloc (sizeof (struct DnsResult) + data_size);
747   res->expiration_time = expiration_time;
748   res->data_size = data_size;
749   res->record_type = record_type;
750   res->data = &res[1];
751   GNUNET_memcpy (&res[1], data, data_size);
752   GNUNET_CONTAINER_DLL_insert (rh->dns_result_head,
753                                rh->dns_result_tail,
754                                res);
755 }
756
757
758 /**
759  * We had to do a DNS lookup.  Convert the result (if any) and return
760  * it.
761  *
762  * @param cls closure with the `struct GNS_ResolverHandle`
763  * @param addr one of the addresses of the host, NULL for the last address
764  * @param addrlen length of the address
765  */
766 static void
767 handle_dns_result (void *cls,
768                    const struct sockaddr *addr,
769                    socklen_t addrlen)
770 {
771   struct GNS_ResolverHandle *rh = cls;
772   const struct sockaddr_in *sa4;
773   const struct sockaddr_in6 *sa6;
774
775   if (NULL == addr)
776   {
777     rh->std_resolve = NULL;
778     transmit_lookup_dns_result (rh);
779     return;
780   }
781   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
782               "Received %u bytes of DNS IP data\n",
783               addrlen);
784   switch (addr->sa_family)
785   {
786   case AF_INET:
787     sa4 = (const struct sockaddr_in *) addr;
788     add_dns_result (rh,
789                     0 /* expiration time is unknown */,
790                     GNUNET_DNSPARSER_TYPE_A,
791                     sizeof (struct in_addr),
792                     &sa4->sin_addr);
793     break;
794   case AF_INET6:
795     sa6 = (const struct sockaddr_in6 *) addr;
796     add_dns_result (rh,
797                     0 /* expiration time is unknown */,
798                     GNUNET_DNSPARSER_TYPE_AAAA,
799                     sizeof (struct in6_addr),
800                     &sa6->sin6_addr);
801     break;
802   default:
803     GNUNET_break (0);
804     break;
805   }
806 }
807
808
809 /**
810  * Task scheduled to continue with the resolution process.
811  *
812  * @param cls the 'struct GNS_ResolverHandle' of the resolution
813  * @param tc task context
814  */
815 static void
816 recursive_resolution (void *cls);
817
818
819 /**
820  * Begin the resolution process from 'name', starting with
821  * the identification of the zone specified by 'name'.
822  *
823  * @param cls closure with `struct GNS_ResolverHandle *rh`
824  */
825 static void
826 start_resolver_lookup (void *cls);
827
828
829 /**
830  * Function called with the result of a DNS resolution.
831  *
832  * @param cls the request handle of the resolution that
833  *        we were attempting to make
834  * @param rs socket that received the response
835  * @param dns dns response, never NULL
836  * @param dns_len number of bytes in @a dns
837  */
838 static void
839 dns_result_parser (void *cls,
840                    struct GNUNET_DNSSTUB_RequestSocket *rs,
841                    const struct GNUNET_TUN_DnsHeader *dns,
842                    size_t dns_len)
843 {
844   struct GNS_ResolverHandle *rh = cls;
845   struct GNUNET_DNSPARSER_Packet *p;
846   const struct GNUNET_DNSPARSER_Record *rec;
847   unsigned int rd_count;
848   unsigned int i;
849
850   (void) rs;
851   if (NULL == dns)
852   {
853     rh->dns_request = NULL;
854     GNUNET_SCHEDULER_cancel (rh->task_id);
855     rh->task_id = NULL;
856     rh->proc (rh->proc_cls,
857               0,
858               NULL);
859     GNS_resolver_lookup_cancel (rh);
860     return;
861   }
862   if (rh->original_dns_id != dns->id)
863   {
864     /* DNS answer, but for another query */
865     return;
866   }
867   p = GNUNET_DNSPARSER_parse ((const char *) dns,
868                               dns_len);
869   if (NULL == p)
870   {
871     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
872                 _("Failed to parse DNS response\n"));
873     return;
874   }
875   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
876               "Received DNS response for `%s' with %u answers\n",
877               rh->ac_tail->label,
878               (unsigned int) p->num_answers);
879   if ( (p->num_answers > 0) &&
880        (GNUNET_DNSPARSER_TYPE_CNAME == p->answers[0].type) &&
881        (GNUNET_DNSPARSER_TYPE_CNAME != rh->record_type) )
882     {
883       int af;
884
885       GNUNET_free (rh->name);
886       rh->name = GNUNET_strdup (p->answers[0].data.hostname);
887       rh->name_resolution_pos = strlen (rh->name);
888       switch (rh->record_type)
889       {
890       case GNUNET_DNSPARSER_TYPE_A:
891         af = AF_INET;
892         break;
893       case GNUNET_DNSPARSER_TYPE_AAAA:
894         af = AF_INET6;
895         break;
896       default:
897         af = AF_UNSPEC;
898         break;
899       }
900       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
901                   "Doing standard DNS lookup for `%s'\n",
902                   rh->name);
903       rh->std_resolve = GNUNET_RESOLVER_ip_get (rh->name,
904                                                 af,
905                                                 DNS_LOOKUP_TIMEOUT,
906                                                 &handle_dns_result,
907                                                 rh);
908       GNUNET_DNSPARSER_free_packet (p);
909       return;
910     }
911
912   /* convert from (parsed) DNS to (binary) GNS format! */
913   rd_count = p->num_answers + p->num_authority_records + p->num_additional_records;
914   {
915     struct GNUNET_GNSRECORD_Data rd[rd_count];
916     unsigned int skip;
917     char buf[UINT16_MAX];
918     size_t buf_off;
919     size_t buf_start;
920
921     buf_off = 0;
922     skip = 0;
923     memset (rd, 0, sizeof (rd));
924     for (i=0;i<rd_count;i++)
925     {
926       if (i < p->num_answers)
927         rec = &p->answers[i];
928       else if (i < p->num_answers + p->num_authority_records)
929         rec = &p->authority_records[i - p->num_answers];
930       else
931         rec = &p->additional_records[i - p->num_answers - p->num_authority_records];
932       /* As we copied the full DNS name to 'rh->ac_tail->label', this
933          should be the correct check to see if this record is actually
934          a record for our label... */
935       if (0 != strcmp (rec->name,
936                        rh->ac_tail->label))
937       {
938         GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
939                     "Dropping record `%s', does not match desired name `%s'\n",
940                     rec->name,
941                     rh->ac_tail->label);
942         skip++;
943         continue;
944       }
945       rd[i - skip].record_type = rec->type;
946       rd[i - skip].expiration_time = rec->expiration_time.abs_value_us;
947       switch (rec->type)
948       {
949       case GNUNET_DNSPARSER_TYPE_A:
950         if (rec->data.raw.data_len != sizeof (struct in_addr))
951         {
952           GNUNET_break_op (0);
953           skip++;
954           continue;
955         }
956         rd[i - skip].data_size = rec->data.raw.data_len;
957         rd[i - skip].data = rec->data.raw.data;
958         break;
959       case GNUNET_DNSPARSER_TYPE_AAAA:
960         if (rec->data.raw.data_len != sizeof (struct in6_addr))
961         {
962           GNUNET_break_op (0);
963           skip++;
964           continue;
965         }
966         rd[i - skip].data_size = rec->data.raw.data_len;
967         rd[i - skip].data = rec->data.raw.data;
968         break;
969       case GNUNET_DNSPARSER_TYPE_CNAME:
970       case GNUNET_DNSPARSER_TYPE_PTR:
971       case GNUNET_DNSPARSER_TYPE_NS:
972         buf_start = buf_off;
973         if (GNUNET_OK !=
974             GNUNET_DNSPARSER_builder_add_name (buf,
975                                                sizeof (buf),
976                                                &buf_off,
977                                                rec->data.hostname))
978         {
979           GNUNET_break (0);
980           skip++;
981           continue;
982         }
983         rd[i - skip].data_size = buf_off - buf_start;
984         rd[i - skip].data = &buf[buf_start];
985         break;
986       case GNUNET_DNSPARSER_TYPE_SOA:
987         buf_start = buf_off;
988         if (GNUNET_OK !=
989             GNUNET_DNSPARSER_builder_add_soa (buf,
990                                               sizeof (buf),
991                                               &buf_off,
992                                               rec->data.soa))
993         {
994           GNUNET_break (0);
995           skip++;
996           continue;
997         }
998         rd[i - skip].data_size = buf_off - buf_start;
999         rd[i - skip].data = &buf[buf_start];
1000         break;
1001       case GNUNET_DNSPARSER_TYPE_MX:
1002         buf_start = buf_off;
1003         if (GNUNET_OK !=
1004             GNUNET_DNSPARSER_builder_add_mx (buf,
1005                                              sizeof (buf),
1006                                              &buf_off,
1007                                              rec->data.mx))
1008         {
1009           GNUNET_break (0);
1010           skip++;
1011           continue;
1012         }
1013         rd[i - skip].data_size = buf_off - buf_start;
1014         rd[i - skip].data = &buf[buf_start];
1015         break;
1016       case GNUNET_DNSPARSER_TYPE_SRV:
1017         buf_start = buf_off;
1018         if (GNUNET_OK !=
1019             GNUNET_DNSPARSER_builder_add_srv (buf,
1020                                               sizeof (buf),
1021                                               &buf_off,
1022                                               rec->data.srv))
1023         {
1024           GNUNET_break (0);
1025           skip++;
1026           continue;
1027         }
1028         rd[i - skip].data_size = buf_off - buf_start;
1029         rd[i - skip].data = &buf[buf_start];
1030         break;
1031       default:
1032         GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1033                     _("Skipping record of unsupported type %d\n"),
1034                     rec->type);
1035         skip++;
1036         continue;
1037       }
1038     }
1039     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1040                 "Returning DNS response for `%s' with %u answers\n",
1041                 rh->ac_tail->label,
1042                 (unsigned int) p->num_answers);
1043     rh->proc (rh->proc_cls,
1044               rd_count - skip,
1045               rd);
1046     GNS_resolver_lookup_cancel (rh);
1047   }
1048   GNUNET_DNSPARSER_free_packet (p);
1049 }
1050
1051
1052 /**
1053  * Perform recursive DNS resolution.  Asks the given DNS resolver to
1054  * resolve "rh->dns_name", possibly recursively proceeding following
1055  * NS delegations, CNAMES, etc., until 'rh->loop_limiter' bounds us or
1056  * we find the answer.
1057  *
1058  * @param rh resolution information
1059  */
1060 static void
1061 recursive_dns_resolution (struct GNS_ResolverHandle *rh)
1062 {
1063   struct AuthorityChain *ac;
1064   socklen_t sa_len;
1065   struct GNUNET_DNSPARSER_Query *query;
1066   struct GNUNET_DNSPARSER_Packet *p;
1067   char *dns_request;
1068   size_t dns_request_length;
1069   int ret;
1070
1071   ac = rh->ac_tail;
1072   GNUNET_assert (NULL != ac);
1073   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1074               "Starting DNS lookup for `%s'\n",
1075               ac->label);
1076   GNUNET_assert (GNUNET_NO == ac->gns_authority);
1077   switch (((const struct sockaddr *) &ac->authority_info.dns_authority.dns_ip)->sa_family)
1078   {
1079   case AF_INET:
1080     sa_len = sizeof (struct sockaddr_in);
1081     break;
1082   case AF_INET6:
1083     sa_len = sizeof (struct sockaddr_in6);
1084     break;
1085   default:
1086     GNUNET_break (0);
1087     rh->proc (rh->proc_cls, 0, NULL);
1088     GNS_resolver_lookup_cancel (rh);
1089     return;
1090   }
1091   query = GNUNET_new (struct GNUNET_DNSPARSER_Query);
1092   query->name = GNUNET_strdup (ac->label);
1093   query->type = rh->record_type;
1094   query->dns_traffic_class = GNUNET_TUN_DNS_CLASS_INTERNET;
1095   p = GNUNET_new (struct GNUNET_DNSPARSER_Packet);
1096   p->queries = query;
1097   p->num_queries = 1;
1098   p->id = (uint16_t) GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_NONCE,
1099                                                UINT16_MAX);
1100   p->flags.opcode = GNUNET_TUN_DNS_OPCODE_QUERY;
1101   p->flags.recursion_desired = 1;
1102   ret = GNUNET_DNSPARSER_pack (p,
1103                                1024,
1104                                &dns_request,
1105                                &dns_request_length);
1106   if (GNUNET_OK != ret)
1107   {
1108     GNUNET_break (0);
1109     rh->proc (rh->proc_cls,
1110               0,
1111               NULL);
1112     GNS_resolver_lookup_cancel (rh);
1113   }
1114   else
1115   {
1116     rh->original_dns_id = p->id;
1117     rh->dns_request = GNUNET_DNSSTUB_resolve (dns_handle,
1118                                               (const struct sockaddr *) &ac->authority_info.dns_authority.dns_ip,
1119                                               sa_len,
1120                                               dns_request,
1121                                               dns_request_length,
1122                                               &dns_result_parser,
1123                                               rh);
1124     rh->task_id = GNUNET_SCHEDULER_add_delayed (DNS_LOOKUP_TIMEOUT,
1125                                                 &fail_resolution,
1126                                                 rh);
1127   }
1128   if (GNUNET_SYSERR != ret)
1129     GNUNET_free (dns_request);
1130   GNUNET_DNSPARSER_free_packet (p);
1131 }
1132
1133
1134 /**
1135  * We encountered a CNAME record during our resolution.
1136  * Merge it into our chain.
1137  *
1138  * @param rh resolution we are performing
1139  * @param cname value of the cname record we got for the current
1140  *        authority chain tail
1141  */
1142 static void
1143 handle_gns_cname_result (struct GNS_ResolverHandle *rh,
1144                          const char *cname)
1145 {
1146   size_t nlen;
1147   char *res;
1148   struct AuthorityChain *ac;
1149   int af;
1150
1151   nlen = strlen (cname);
1152   if ( (nlen > 2) &&
1153        (0 == strcmp (".+",
1154                      &cname[nlen - 2])) )
1155   {
1156     /* CNAME resolution continues relative to current domain */
1157     if (0 == rh->name_resolution_pos)
1158     {
1159       res = GNUNET_strndup (cname, nlen - 2);
1160       rh->name_resolution_pos = nlen - 2;
1161     }
1162     else
1163     {
1164       GNUNET_asprintf (&res,
1165                        "%.*s.%.*s",
1166                        (int) rh->name_resolution_pos,
1167                        rh->name,
1168                        (int) (nlen - 2),
1169                        cname);
1170       rh->name_resolution_pos = strlen (res);
1171     }
1172     GNUNET_free (rh->name);
1173     rh->name = res;
1174     ac = GNUNET_new (struct AuthorityChain);
1175     ac->rh = rh;
1176     ac->gns_authority = GNUNET_YES;
1177     ac->authority_info.gns_authority = rh->ac_tail->authority_info.gns_authority;
1178     ac->label = resolver_lookup_get_next_label (rh);
1179     ac->suggested_shortening_label = NULL;
1180     ac->shortening_started = GNUNET_NO;
1181     /* add AC to tail */
1182     GNUNET_CONTAINER_DLL_insert_tail (rh->ac_head,
1183                                       rh->ac_tail,
1184                                       ac);
1185     rh->task_id = GNUNET_SCHEDULER_add_now (&recursive_resolution,
1186                                             rh);
1187     return;
1188   }
1189   /* name is absolute, go to DNS */
1190   GNUNET_free (rh->name);
1191   rh->name = GNUNET_strdup (cname);
1192   rh->name_resolution_pos = strlen (rh->name);
1193   switch (rh->record_type)
1194   {
1195   case GNUNET_DNSPARSER_TYPE_A:
1196     af = AF_INET;
1197     break;
1198   case GNUNET_DNSPARSER_TYPE_AAAA:
1199     af = AF_INET6;
1200     break;
1201   default:
1202     af = AF_UNSPEC;
1203     break;
1204   }
1205   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1206               "Doing standard DNS lookup for `%s'\n",
1207               rh->name);
1208   rh->std_resolve = GNUNET_RESOLVER_ip_get (rh->name,
1209                                             af,
1210                                             DNS_LOOKUP_TIMEOUT,
1211                                             &handle_dns_result,
1212                                             rh);
1213 }
1214
1215
1216 /**
1217  * Process a records that were decrypted from a block.
1218  *
1219  * @param cls closure with the 'struct GNS_ResolverHandle'
1220  * @param rd_count number of entries in @a rd array
1221  * @param rd array of records with data to store
1222  */
1223 static void
1224 handle_gns_resolution_result (void *cls,
1225                               unsigned int rd_count,
1226                               const struct GNUNET_GNSRECORD_Data *rd);
1227
1228
1229 /**
1230  * Callback invoked from the VPN service once a redirection is
1231  * available.  Provides the IP address that can now be used to
1232  * reach the requested destination.  Replaces the "VPN" record
1233  * with the respective A/AAAA record and continues processing.
1234  *
1235  * @param cls closure
1236  * @param af address family, AF_INET or AF_INET6; AF_UNSPEC on error;
1237  *                will match 'result_af' from the request
1238  * @param address IP address (struct in_addr or struct in_addr6, depending on 'af')
1239  *                that the VPN allocated for the redirection;
1240  *                traffic to this IP will now be redirected to the
1241  *                specified target peer; NULL on error
1242  */
1243 static void
1244 vpn_allocation_cb (void *cls,
1245                    int af,
1246                    const void *address)
1247 {
1248   struct VpnContext *vpn_ctx = cls;
1249   struct GNS_ResolverHandle *rh = vpn_ctx->rh;
1250   struct GNUNET_GNSRECORD_Data rd[vpn_ctx->rd_count];
1251   unsigned int i;
1252
1253   vpn_ctx->vpn_request = NULL;
1254   rh->vpn_ctx = NULL;
1255   GNUNET_assert (GNUNET_OK ==
1256                  GNUNET_GNSRECORD_records_deserialize (vpn_ctx->rd_data_size,
1257                                                        vpn_ctx->rd_data,
1258                                                        vpn_ctx->rd_count,
1259                                                        rd));
1260   for (i=0;i<vpn_ctx->rd_count;i++)
1261   {
1262     if (GNUNET_GNSRECORD_TYPE_VPN == rd[i].record_type)
1263     {
1264       switch (af)
1265       {
1266       case AF_INET:
1267         rd[i].record_type = GNUNET_DNSPARSER_TYPE_A;
1268         rd[i].data_size = sizeof (struct in_addr);
1269         rd[i].expiration_time = GNUNET_TIME_relative_to_absolute (VPN_TIMEOUT).abs_value_us;
1270         rd[i].flags = 0;
1271         rd[i].data = address;
1272         break;
1273       case AF_INET6:
1274         rd[i].record_type = GNUNET_DNSPARSER_TYPE_AAAA;
1275         rd[i].expiration_time = GNUNET_TIME_relative_to_absolute (VPN_TIMEOUT).abs_value_us;
1276         rd[i].flags = 0;
1277         rd[i].data = address;
1278         rd[i].data_size = sizeof (struct in6_addr);
1279         break;
1280       default:
1281         GNUNET_assert (0);
1282       }
1283       break;
1284     }
1285   }
1286   GNUNET_assert (i < vpn_ctx->rd_count);
1287   handle_gns_resolution_result (rh,
1288                                 vpn_ctx->rd_count,
1289                                 rd);
1290   GNUNET_free (vpn_ctx->rd_data);
1291   GNUNET_free (vpn_ctx);
1292 }
1293
1294
1295 /**
1296  * We've resolved the IP address for the DNS resolver to use
1297  * after encountering a GNS2DNS record.
1298  *
1299  * TODO: Right now we only foward the request to ONE DNS resolver,
1300  * even if we get multiple IP addresses back; a correct implementation
1301  * should try all DNS resolvers.
1302  *
1303  * @param cls the `struct GNS_ResolverHandle` where we encountered
1304  *            the GNS2DNS record
1305  * @param rd_count number of records in @a rd
1306  * @param rd addresses for the DNS resolver  (presumably)
1307  */
1308 static void
1309 handle_gns2dns_result (void *cls,
1310                        unsigned int rd_count,
1311                        const struct GNUNET_GNSRECORD_Data *rd)
1312 {
1313   struct GNS_ResolverHandle *rh = cls;
1314   struct AuthorityChain *ac;
1315   struct sockaddr *sa;
1316   struct sockaddr_in v4;
1317   struct sockaddr_in6 v6;
1318   size_t sa_len;
1319
1320   /* find suitable A/AAAA record */
1321   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1322               "Received %u results for IP address of DNS server for GNS2DNS transition\n",
1323               rd_count);
1324   /* enable cleanup of 'rh' handle that comes next... */
1325   if (NULL != rh->g2dc->rh)
1326   {
1327     GNUNET_CONTAINER_DLL_insert (rlh_head,
1328                                  rlh_tail,
1329                                  rh->g2dc->rh);
1330     rh->g2dc->rh = NULL;
1331   }
1332   sa = NULL;
1333   sa_len = 0;
1334   for (unsigned int j=0;j<rd_count;j++)
1335   {
1336     switch (rd[j].record_type)
1337     {
1338     case GNUNET_DNSPARSER_TYPE_A:
1339       if (sizeof (struct in_addr) != rd[j].data_size)
1340       {
1341         GNUNET_break_op (0);
1342         rh->proc (rh->proc_cls, 0, NULL);
1343         GNS_resolver_lookup_cancel (rh);
1344         return;
1345       }
1346       /* FIXME: might want to check if we support IPv4 here,
1347          and otherwise skip this one and hope we find another */
1348       memset (&v4, 0, sizeof (v4));
1349       sa_len = sizeof (v4);
1350       v4.sin_family = AF_INET;
1351       v4.sin_port = htons (53);
1352 #if HAVE_SOCKADDR_IN_SIN_LEN
1353       v4.sin_len = (u_char) sa_len;
1354 #endif
1355       GNUNET_memcpy (&v4.sin_addr,
1356               rd[j].data,
1357               sizeof (struct in_addr));
1358       sa = (struct sockaddr *) &v4;
1359       break;
1360     case GNUNET_DNSPARSER_TYPE_AAAA:
1361       if (sizeof (struct in6_addr) != rd[j].data_size)
1362       {
1363         GNUNET_break_op (0);
1364         rh->proc (rh->proc_cls, 0, NULL);
1365         GNS_resolver_lookup_cancel (rh);
1366         return;
1367       }
1368       /* FIXME: might want to check if we support IPv6 here,
1369          and otherwise skip this one and hope we find another */
1370       memset (&v6, 0, sizeof (v6));
1371       sa_len = sizeof (v6);
1372       v6.sin6_family = AF_INET6;
1373       v6.sin6_port = htons (53);
1374 #if HAVE_SOCKADDR_IN_SIN_LEN
1375       v6.sin6_len = (u_char) sa_len;
1376 #endif
1377       GNUNET_memcpy (&v6.sin6_addr,
1378               rd[j].data,
1379               sizeof (struct in6_addr));
1380       sa = (struct sockaddr *) &v6;
1381       break;
1382     default:
1383       break;
1384     }
1385     if (NULL != sa)
1386       break;
1387   }
1388   if (NULL == sa)
1389   {
1390     /* we cannot continue; NS without A/AAAA */
1391     rh->proc (rh->proc_cls, 0, NULL);
1392     GNS_resolver_lookup_cancel (rh);
1393     return;
1394   }
1395   /* expand authority chain */
1396   ac = GNUNET_new (struct AuthorityChain);
1397   ac->rh = rh;
1398   GNUNET_assert (strlen (rh->g2dc->ns) <= GNUNET_DNSPARSER_MAX_NAME_LENGTH);
1399   strcpy (ac->authority_info.dns_authority.name,
1400           rh->g2dc->ns);
1401   GNUNET_memcpy (&ac->authority_info.dns_authority.dns_ip,
1402           sa,
1403           sa_len);
1404   /* for DNS recursion, the label is the full DNS name,
1405      created from the remainder of the GNS name and the
1406      name in the NS record */
1407   GNUNET_asprintf (&ac->label,
1408                    "%.*s%s%s",
1409                    (int) rh->name_resolution_pos,
1410                    rh->name,
1411                    (0 != rh->name_resolution_pos) ? "." : "",
1412                    rh->g2dc->ns);
1413   GNUNET_free (rh->g2dc->ns);
1414   GNUNET_free (rh->g2dc);
1415   rh->g2dc = NULL;
1416   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1417               "Will continue resolution using DNS server `%s' to resolve `%s'\n",
1418               GNUNET_a2s (sa,
1419                           sa_len),
1420               ac->label);
1421   GNUNET_CONTAINER_DLL_insert_tail (rh->ac_head,
1422                                     rh->ac_tail,
1423                                     ac);
1424   if (strlen (ac->label) > GNUNET_DNSPARSER_MAX_NAME_LENGTH)
1425   {
1426     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1427                 _("GNS lookup resulted in DNS name that is too long (`%s')\n"),
1428                 ac->label);
1429     rh->proc (rh->proc_cls, 0, NULL);
1430     GNS_resolver_lookup_cancel (rh);
1431     return;
1432   }
1433   /* recurse */
1434   rh->task_id = GNUNET_SCHEDULER_add_now (&recursive_resolution,
1435                                           rh);
1436 }
1437
1438
1439 /**
1440  * Function called by the resolver for each address obtained from DNS.
1441  *
1442  * @param cls closure, a `struct Gns2DnsContext *`
1443  * @param addr one of the addresses of the host, NULL for the last address
1444  * @param addrlen length of @a addr
1445  */
1446 static void
1447 handle_gns2dns_ip (void *cls,
1448                    const struct sockaddr *addr,
1449                    socklen_t addrlen)
1450 {
1451   struct Gns2DnsContext *g2dc = cls;
1452   struct GNUNET_GNSRECORD_Data rd;
1453
1454   if (NULL == addr)
1455   {
1456     /* DNS resolution failed */
1457     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1458                 "Failed to use DNS to resolve name of DNS resolver\n");
1459     g2dc->rh->g2dc = NULL;
1460     fail_resolution (g2dc->rh);
1461     GNUNET_free (g2dc);
1462   }
1463   switch (addr->sa_family)
1464   {
1465   case AF_INET:
1466     {
1467       const struct sockaddr_in *v4 = (const struct sockaddr_in *) addr;
1468
1469       GNUNET_assert (sizeof (*v4) == addrlen);
1470       rd.data = v4;
1471       rd.data_size = sizeof (*v4);
1472       rd.expiration_time = UINT64_MAX;
1473       rd.record_type = GNUNET_DNSPARSER_TYPE_A;
1474       rd.flags = 0;
1475       break;
1476     }
1477   case AF_INET6:
1478     {
1479       const struct sockaddr_in6 *v6 = (const struct sockaddr_in6 *) addr;
1480
1481       GNUNET_assert (sizeof (*v6) == addrlen);
1482       rd.data = v6;
1483       rd.data_size = sizeof (v6);
1484       rd.expiration_time = UINT64_MAX;
1485       rd.record_type = GNUNET_DNSPARSER_TYPE_AAAA;
1486       rd.flags = 0;
1487       break;
1488     }
1489   default:
1490     return;
1491   }
1492   GNUNET_RESOLVER_request_cancel (g2dc->dns_rh);
1493   g2dc->dns_rh = NULL;
1494   handle_gns2dns_result (g2dc->rh,
1495                          1,
1496                          &rd);
1497
1498 }
1499
1500
1501
1502 /**
1503  * Process a records that were decrypted from a block.
1504  *
1505  * @param cls closure with the `struct GNS_ResolverHandle`
1506  * @param rd_count number of entries in @a rd array
1507  * @param rd array of records with data to store
1508  */
1509 static void
1510 handle_gns_resolution_result (void *cls,
1511                               unsigned int rd_count,
1512                               const struct GNUNET_GNSRECORD_Data *rd)
1513 {
1514   struct GNS_ResolverHandle *rh = cls;
1515   struct AuthorityChain *ac;
1516   struct AuthorityChain *shorten_ac;
1517   char *cname;
1518   struct VpnContext *vpn_ctx;
1519   const struct GNUNET_TUN_GnsVpnRecord *vpn;
1520   const char *vname;
1521   struct GNUNET_HashCode vhash;
1522   int af;
1523   char scratch[UINT16_MAX];
1524   size_t scratch_off;
1525   size_t scratch_start;
1526   size_t off;
1527   struct GNUNET_GNSRECORD_Data rd_new[rd_count];
1528   unsigned int rd_off;
1529
1530   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1531               "Resolution succeeded for `%s' in zone %s, got %u records\n",
1532               rh->ac_tail->label,
1533               GNUNET_GNSRECORD_z2s (&rh->ac_tail->authority_info.gns_authority),
1534               rd_count);
1535   if (0 == rh->name_resolution_pos)
1536   {
1537     /* top-level match, are we done yet? */
1538     if ( (rd_count > 0) &&
1539          (GNUNET_DNSPARSER_TYPE_CNAME == rd[0].record_type) &&
1540          (GNUNET_DNSPARSER_TYPE_CNAME != rh->record_type) )
1541     {
1542       off = 0;
1543       cname = GNUNET_DNSPARSER_parse_name (rd[0].data,
1544                                            rd[0].data_size,
1545                                            &off);
1546       if ( (NULL == cname) ||
1547            (off != rd[0].data_size) )
1548       {
1549         GNUNET_break_op (0);
1550         rh->proc (rh->proc_cls, 0, NULL);
1551         GNS_resolver_lookup_cancel (rh);
1552         GNUNET_free_non_null (cname);
1553         return;
1554       }
1555       handle_gns_cname_result (rh,
1556                                cname);
1557       GNUNET_free (cname);
1558       return;
1559     }
1560     /* If A/AAAA was requested, but we got a VPN
1561        record, we convert it to A/AAAA using GNUnet VPN */
1562     if ( (GNUNET_DNSPARSER_TYPE_A == rh->record_type) ||
1563          (GNUNET_DNSPARSER_TYPE_AAAA == rh->record_type) )
1564     {
1565       for (unsigned int i=0;i<rd_count;i++)
1566       {
1567         switch (rd[i].record_type)
1568         {
1569         case GNUNET_GNSRECORD_TYPE_VPN:
1570           {
1571             af = (GNUNET_DNSPARSER_TYPE_A == rh->record_type) ? AF_INET : AF_INET6;
1572             if (sizeof (struct GNUNET_TUN_GnsVpnRecord) >
1573                 rd[i].data_size)
1574             {
1575               GNUNET_break_op (0);
1576               rh->proc (rh->proc_cls, 0, NULL);
1577               GNS_resolver_lookup_cancel (rh);
1578               return;
1579             }
1580             vpn = (const struct GNUNET_TUN_GnsVpnRecord *) rd[i].data;
1581             vname = (const char *) &vpn[1];
1582             if ('\0' != vname[rd[i].data_size - 1 - sizeof (struct GNUNET_TUN_GnsVpnRecord)])
1583             {
1584               GNUNET_break_op (0);
1585               rh->proc (rh->proc_cls, 0, NULL);
1586               GNS_resolver_lookup_cancel (rh);
1587               return;
1588             }
1589             GNUNET_TUN_service_name_to_hash (vname,
1590                                              &vhash);
1591             GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1592                         "Attempting VPN allocation for %s-%s (AF: %d, proto %d)\n",
1593                         GNUNET_i2s (&vpn->peer),
1594                         vname,
1595                         (int) af,
1596                         (int) ntohs (vpn->proto));
1597             vpn_ctx = GNUNET_new (struct VpnContext);
1598             rh->vpn_ctx = vpn_ctx;
1599             vpn_ctx->rh = rh;
1600             vpn_ctx->rd_data_size = GNUNET_GNSRECORD_records_get_size (rd_count,
1601                                                                        rd);
1602             vpn_ctx->rd_data = GNUNET_malloc (vpn_ctx->rd_data_size);
1603             vpn_ctx->rd_count = rd_count;
1604             GNUNET_assert (vpn_ctx->rd_data_size ==
1605                            (size_t) GNUNET_GNSRECORD_records_serialize (rd_count,
1606                                                                         rd,
1607                                                                         vpn_ctx->rd_data_size,
1608                                                                         vpn_ctx->rd_data));
1609             vpn_ctx->vpn_request = GNUNET_VPN_redirect_to_peer (vpn_handle,
1610                                                                 af,
1611                                                                 ntohs (vpn->proto),
1612                                                                 &vpn->peer,
1613                                                                 &vhash,
1614                                                                 GNUNET_TIME_relative_to_absolute (VPN_TIMEOUT),
1615                                                                 &vpn_allocation_cb,
1616                                                                 vpn_ctx);
1617             return;
1618           }
1619         case GNUNET_GNSRECORD_TYPE_GNS2DNS:
1620           {
1621             /* delegation to DNS */
1622             GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1623                         "Found GNS2DNS record, delegating to DNS!\n");
1624             goto do_recurse;
1625           }
1626         default:
1627           break;
1628         } /* end: switch */
1629       } /* end: for rd */
1630     } /* end: name_resolution_pos */
1631     /* convert relative names in record values to absolute names,
1632        using 'scratch' array for memory allocations */
1633     scratch_off = 0;
1634     rd_off = 0;
1635     shorten_ac = rh->ac_tail;
1636     for (unsigned int i=0;i<rd_count;i++)
1637     {
1638       GNUNET_assert (rd_off <= i);
1639       if ( (0 != rh->protocol) &&
1640            (0 != rh->service) &&
1641            (GNUNET_GNSRECORD_TYPE_BOX != rd[i].record_type) )
1642         continue; /* we _only_ care about boxed records */
1643
1644       GNUNET_assert (rd_off < rd_count);
1645       rd_new[rd_off] = rd[i];
1646       /* Check if the embedded name(s) end in "+", and if so,
1647          replace the "+" with the zone at "ac_tail", changing the name
1648          to a ".ZONEKEY".  The name is allocated on the 'scratch' array,
1649          so we can free it afterwards. */
1650       switch (rd[i].record_type)
1651       {
1652       case GNUNET_DNSPARSER_TYPE_CNAME:
1653         {
1654           char *cname;
1655
1656           off = 0;
1657           cname = GNUNET_DNSPARSER_parse_name (rd[i].data,
1658                                                rd[i].data_size,
1659                                                &off);
1660           if ( (NULL == cname) ||
1661                (off != rd[i].data_size) )
1662           {
1663             GNUNET_break_op (0); /* record not well-formed */
1664           }
1665           else
1666           {
1667             cname = translate_dot_plus (rh, cname);
1668             GNUNET_break (NULL != cname);
1669             scratch_start = scratch_off;
1670             if (GNUNET_OK !=
1671                 GNUNET_DNSPARSER_builder_add_name (scratch,
1672                                                    sizeof (scratch),
1673                                                    &scratch_off,
1674                                                    cname))
1675             {
1676               GNUNET_break (0);
1677             }
1678             else
1679             {
1680               GNUNET_assert (rd_off < rd_count);
1681               rd_new[rd_off].data = &scratch[scratch_start];
1682               rd_new[rd_off].data_size = scratch_off - scratch_start;
1683               rd_off++;
1684             }
1685           }
1686           GNUNET_free_non_null (cname);
1687         }
1688         break;
1689       case GNUNET_DNSPARSER_TYPE_SOA:
1690         {
1691           struct GNUNET_DNSPARSER_SoaRecord *soa;
1692
1693           off = 0;
1694           soa = GNUNET_DNSPARSER_parse_soa (rd[i].data,
1695                                             rd[i].data_size,
1696                                             &off);
1697           if ( (NULL == soa) ||
1698                (off != rd[i].data_size) )
1699           {
1700             GNUNET_break_op (0); /* record not well-formed */
1701           }
1702           else
1703           {
1704             soa->mname = translate_dot_plus (rh, soa->mname);
1705             soa->rname = translate_dot_plus (rh, soa->rname);
1706             scratch_start = scratch_off;
1707             if (GNUNET_OK !=
1708                 GNUNET_DNSPARSER_builder_add_soa (scratch,
1709                                                   sizeof (scratch),
1710                                                   &scratch_off,
1711                                                   soa))
1712             {
1713               GNUNET_break (0);
1714             }
1715             else
1716             {
1717               GNUNET_assert (rd_off < rd_count);
1718               rd_new[rd_off].data = &scratch[scratch_start];
1719               rd_new[rd_off].data_size = scratch_off - scratch_start;
1720               rd_off++;
1721             }
1722           }
1723           if (NULL != soa)
1724             GNUNET_DNSPARSER_free_soa (soa);
1725         }
1726         break;
1727       case GNUNET_DNSPARSER_TYPE_MX:
1728         {
1729           struct GNUNET_DNSPARSER_MxRecord *mx;
1730
1731           off = 0;
1732           mx = GNUNET_DNSPARSER_parse_mx (rd[i].data,
1733                                           rd[i].data_size,
1734                                           &off);
1735           if ( (NULL == mx) ||
1736                (off != rd[i].data_size) )
1737           {
1738             GNUNET_break_op (0); /* record not well-formed */
1739           }
1740           else
1741           {
1742             mx->mxhost = translate_dot_plus (rh, mx->mxhost);
1743             scratch_start = scratch_off;
1744             if (GNUNET_OK !=
1745                 GNUNET_DNSPARSER_builder_add_mx (scratch,
1746                                                  sizeof (scratch),
1747                                                  &scratch_off,
1748                                                  mx))
1749             {
1750               GNUNET_break (0);
1751             }
1752             else
1753             {
1754               GNUNET_assert (rd_off < rd_count);
1755               rd_new[rd_off].data = &scratch[scratch_start];
1756               rd_new[rd_off].data_size = scratch_off - scratch_start;
1757               rd_off++;
1758             }
1759           }
1760           if (NULL != mx)
1761             GNUNET_DNSPARSER_free_mx (mx);
1762         }
1763         break;
1764       case GNUNET_DNSPARSER_TYPE_SRV:
1765         {
1766           struct GNUNET_DNSPARSER_SrvRecord *srv;
1767
1768           off = 0;
1769           srv = GNUNET_DNSPARSER_parse_srv (rd[i].data,
1770                                             rd[i].data_size,
1771                                             &off);
1772           if ( (NULL == srv) ||
1773                (off != rd[i].data_size) )
1774           {
1775             GNUNET_break_op (0); /* record not well-formed */
1776           }
1777           else
1778           {
1779             srv->target = translate_dot_plus (rh, srv->target);
1780             scratch_start = scratch_off;
1781             if (GNUNET_OK !=
1782                 GNUNET_DNSPARSER_builder_add_srv (scratch,
1783                                                   sizeof (scratch),
1784                                                   &scratch_off,
1785                                                   srv))
1786             {
1787               GNUNET_break (0);
1788             }
1789             else
1790             {
1791               GNUNET_assert (rd_off < rd_count);
1792               rd_new[rd_off].data = &scratch[scratch_start];
1793               rd_new[rd_off].data_size = scratch_off - scratch_start;
1794               rd_off++;
1795             }
1796           }
1797           if (NULL != srv)
1798             GNUNET_DNSPARSER_free_srv (srv);
1799         }
1800         break;
1801
1802       case GNUNET_GNSRECORD_TYPE_NICK:
1803         {
1804           const char *nick;
1805
1806           nick = rd[i].data;
1807           if ((rd[i].data_size > 0) &&
1808               (nick[rd[i].data_size -1] != '\0'))
1809           {
1810             GNUNET_break_op (0);
1811             break;
1812           }
1813           if (NULL == shorten_ac->suggested_shortening_label)
1814             shorten_ac->suggested_shortening_label = GNUNET_strdup (nick);
1815           break;
1816         }
1817       case GNUNET_GNSRECORD_TYPE_PKEY:
1818         {
1819           struct GNUNET_CRYPTO_EcdsaPublicKey pub;
1820
1821           if (rd[i].data_size != sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey))
1822           {
1823             GNUNET_break_op (0);
1824             break;
1825           }
1826           GNUNET_memcpy (&pub, rd[i].data, rd[i].data_size);
1827           rd_off++;
1828           if (GNUNET_GNSRECORD_TYPE_PKEY != rh->record_type)
1829           {
1830             /* try to resolve "+" */
1831             struct AuthorityChain *ac;
1832
1833             ac = GNUNET_new (struct AuthorityChain);
1834             ac->rh = rh;
1835             ac->gns_authority = GNUNET_YES;
1836             ac->authority_info.gns_authority = pub;
1837             ac->label = GNUNET_strdup (GNUNET_GNS_MASTERZONE_STR);
1838             ac->suggested_shortening_label = NULL;
1839             ac->shortening_started = GNUNET_NO;
1840             GNUNET_CONTAINER_DLL_insert_tail (rh->ac_head,
1841                                               rh->ac_tail,
1842                                               ac);
1843             rh->task_id = GNUNET_SCHEDULER_add_now (&recursive_resolution,
1844                                                     rh);
1845             return;
1846           }
1847         }
1848         break;
1849       case GNUNET_GNSRECORD_TYPE_GNS2DNS:
1850         {
1851           /* delegation to DNS */
1852           if (GNUNET_GNSRECORD_TYPE_GNS2DNS == rh->record_type)
1853           {
1854             rd_off++;
1855             break; /* do not follow to DNS, we wanted the GNS2DNS record! */
1856           }
1857           GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1858                       "Found GNS2DNS record, delegating to DNS!\n");
1859           goto do_recurse;
1860         }
1861       case GNUNET_GNSRECORD_TYPE_BOX:
1862         {
1863           /* unbox SRV/TLSA records if a specific one was requested */
1864           if ( (0 != rh->protocol) &&
1865                (0 != rh->service) &&
1866                (rd[i].data_size >= sizeof (struct GNUNET_GNSRECORD_BoxRecord)) )
1867           {
1868             const struct GNUNET_GNSRECORD_BoxRecord *box;
1869
1870             box = rd[i].data;
1871             if ( (ntohs (box->protocol) == rh->protocol) &&
1872                  (ntohs (box->service) == rh->service) )
1873             {
1874               /* Box matches, unbox! */
1875               GNUNET_assert (rd_off < rd_count);
1876               rd_new[rd_off].record_type = ntohl (box->record_type);
1877               rd_new[rd_off].data_size -= sizeof (struct GNUNET_GNSRECORD_BoxRecord);
1878               rd_new[rd_off].data = &box[1];
1879               rd_off++;
1880             }
1881           }
1882           else
1883           {
1884             /* no specific protocol/service specified, preserve all BOX
1885                records (for modern, GNS-enabled applications) */
1886             rd_off++;
1887           }
1888           break;
1889         }
1890       default:
1891         rd_off++;
1892         break;
1893       } /* end: switch */
1894     } /* end: for rd_count */
1895
1896     /* yes, we are done, return result */
1897     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1898                 "Returning GNS response for `%s' with %u answers\n",
1899                 rh->ac_tail->label,
1900                 rd_off);
1901     rh->proc (rh->proc_cls,
1902               rd_off,
1903               rd_new);
1904     GNS_resolver_lookup_cancel (rh);
1905     return;
1906   }
1907  do_recurse:
1908   /* need to recurse, check if we can */
1909   for (unsigned int i=0;i<rd_count;i++)
1910   {
1911     switch (rd[i].record_type)
1912     {
1913     case GNUNET_GNSRECORD_TYPE_PKEY:
1914       /* delegation to another zone */
1915       if (sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey) !=
1916           rd[i].data_size)
1917       {
1918         GNUNET_break_op (0);
1919         rh->proc (rh->proc_cls, 0, NULL);
1920         GNS_resolver_lookup_cancel (rh);
1921         return;
1922       }
1923       /* expand authority chain */
1924       ac = GNUNET_new (struct AuthorityChain);
1925       ac->rh = rh;
1926       ac->gns_authority = GNUNET_YES;
1927       ac->suggested_shortening_label = NULL;
1928       ac->shortening_started = GNUNET_NO;
1929       GNUNET_memcpy (&ac->authority_info.gns_authority,
1930               rd[i].data,
1931               sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
1932       ac->label = resolver_lookup_get_next_label (rh);
1933       /* add AC to tail */
1934       GNUNET_CONTAINER_DLL_insert_tail (rh->ac_head,
1935                                         rh->ac_tail,
1936                                         ac);
1937       /* recurse */
1938       rh->task_id = GNUNET_SCHEDULER_add_now (&recursive_resolution,
1939                                               rh);
1940       return;
1941     case GNUNET_GNSRECORD_TYPE_GNS2DNS:
1942       {
1943         /* TODO: Right now we only foward the request to ONE DNS resolver,
1944            even if we get multiple IP addresses back; a correct implementation
1945            should try all DNS resolvers. */
1946         /* resolution continues within DNS */
1947         struct Gns2DnsContext *g2dc;
1948         char *ip;
1949         char *ns;
1950         const char *tld;
1951         struct GNUNET_CRYPTO_EcdsaPublicKey zone;
1952         struct in_addr v4;
1953         struct in6_addr v6;
1954
1955         off = 0;
1956         ns = GNUNET_DNSPARSER_parse_name (rd[i].data,
1957                                           rd[i].data_size,
1958                                           &off);
1959         ip = GNUNET_DNSPARSER_parse_name (rd[i].data,
1960                                           rd[i].data_size,
1961                                           &off);
1962         if ( (NULL == ns) ||
1963              (NULL == ip) ||
1964              (off != rd[i].data_size) )
1965         {
1966           GNUNET_break_op (0);
1967           GNUNET_free_non_null (ns);
1968           GNUNET_free_non_null (ip);
1969           fail_resolution (rh);
1970           return;
1971         }
1972         /* resolve 'ip' to determine the IP(s) of the DNS
1973            resolver to use for lookup of 'ns' */
1974         g2dc = GNUNET_new (struct Gns2DnsContext);
1975         g2dc->ns = ns;
1976         rh->g2dc = g2dc;
1977
1978         /* check if 'ip' is already an IPv4/IPv6 address */
1979         if (1 == inet_pton (AF_INET,
1980                             ip,
1981                             &v4))
1982         {
1983           /* name is IPv4 address, pretend it's an A record */
1984           struct GNUNET_GNSRECORD_Data rd;
1985
1986           GNUNET_free (ip);
1987           rd.data = &v4;
1988           rd.data_size = sizeof (v4);
1989           rd.expiration_time = UINT64_MAX;
1990           rd.record_type = GNUNET_DNSPARSER_TYPE_A;
1991           rd.flags = 0;
1992           handle_gns2dns_result (rh,
1993                                  1,
1994                                  &rd);
1995           return;
1996         }
1997         if (1 == inet_pton (AF_INET6,
1998                             ip,
1999                             &v6))
2000         {
2001           /* name is IPv6 address, pretend it's an AAAA record */
2002           struct GNUNET_GNSRECORD_Data rd;
2003
2004           GNUNET_free (ip);
2005           rd.data = &v6;
2006           rd.data_size = sizeof (v6);
2007           rd.expiration_time = UINT64_MAX;
2008           rd.record_type = GNUNET_DNSPARSER_TYPE_AAAA;
2009           rd.flags = 0;
2010           handle_gns2dns_result (rh,
2011                                  1,
2012                                  &rd);
2013           return;
2014         }
2015
2016         tld = GNS_get_tld (ip);
2017         if (0 != strcmp (tld,
2018                          "+"))
2019         {
2020           /* 'ip' is a DNS name */
2021           g2dc->dns_rh = GNUNET_RESOLVER_ip_get (ip,
2022                                                  AF_UNSPEC,
2023                                                  GNUNET_TIME_UNIT_FOREVER_REL,
2024                                                  &handle_gns2dns_ip,
2025                                                  g2dc);
2026           GNUNET_free (ip);
2027           return;
2028         }
2029
2030         /* 'ip' should be a GNS name */
2031         g2dc->rh = GNUNET_new (struct GNS_ResolverHandle);
2032
2033         ip = translate_dot_plus (rh,
2034                                  ip);
2035         tld = GNS_get_tld (ip);
2036         if (GNUNET_OK !=
2037             GNUNET_GNSRECORD_zkey_to_pkey (tld,
2038                                            &zone))
2039         {
2040           GNUNET_break_op (0);
2041           GNUNET_free_non_null (ns);
2042           GNUNET_free_non_null (ip);
2043           GNUNET_free (g2dc);
2044           fail_resolution (rh);
2045           return;
2046         }
2047         g2dc->rh->authority_zone = zone;
2048         GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2049                     "Resolving `%s' to determine IP address of DNS server for GNS2DNS transition for `%s'\n",
2050                     ip,
2051                     ns);
2052         g2dc->rh->name = ip;
2053         g2dc->rh->name_resolution_pos = strlen (ip) - strlen (tld) - 1;
2054         g2dc->rh->proc = &handle_gns2dns_result;
2055         g2dc->rh->proc_cls = rh;
2056         g2dc->rh->record_type = GNUNET_GNSRECORD_TYPE_ANY;
2057         g2dc->rh->options = GNUNET_GNS_LO_DEFAULT;
2058         g2dc->rh->loop_limiter = rh->loop_limiter + 1;
2059         g2dc->rh->task_id
2060           = GNUNET_SCHEDULER_add_now (&start_resolver_lookup,
2061                                       g2dc->rh);
2062         return;
2063       }
2064     case GNUNET_DNSPARSER_TYPE_CNAME:
2065       {
2066         char *cname;
2067
2068         off = 0;
2069         cname = GNUNET_DNSPARSER_parse_name (rd[i].data,
2070                                              rd[i].data_size,
2071                                              &off);
2072         if ( (NULL == cname) ||
2073              (off != rd[i].data_size) )
2074         {
2075           GNUNET_break_op (0); /* record not well-formed */
2076           rh->proc (rh->proc_cls, 0, NULL);
2077           GNS_resolver_lookup_cancel (rh);
2078           GNUNET_free_non_null (cname);
2079           return;
2080         }
2081         handle_gns_cname_result (rh,
2082                                  cname);
2083         GNUNET_free (cname);
2084         return;
2085       }
2086       /* FIXME: handle DNAME */
2087     default:
2088       /* skip */
2089       break;
2090     }
2091   }
2092   GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
2093               _("GNS lookup recursion failed (no delegation record found)\n"));
2094   rh->proc (rh->proc_cls,
2095             0,
2096             NULL);
2097   GNS_resolver_lookup_cancel (rh);
2098 }
2099
2100
2101 /**
2102  * Function called once the namestore has completed the request for
2103  * caching a block.
2104  *
2105  * @param cls closure with the `struct CacheOps`
2106  * @param success #GNUNET_OK on success
2107  * @param emsg error message
2108  */
2109 static void
2110 namecache_cache_continuation (void *cls,
2111                               int32_t success,
2112                               const char *emsg)
2113 {
2114   struct CacheOps *co = cls;
2115
2116   co->namecache_qe_cache = NULL;
2117   if (GNUNET_OK != success)
2118     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
2119                 _("Failed to cache GNS resolution: %s\n"),
2120                 emsg);
2121   GNUNET_CONTAINER_DLL_remove (co_head,
2122                                co_tail,
2123                                co);
2124   GNUNET_free (co);
2125 }
2126
2127
2128 /**
2129  * Iterator called on each result obtained for a DHT
2130  * operation that expects a reply
2131  *
2132  * @param cls closure with the `struct GNS_ResolverHandle`
2133  * @param exp when will this value expire
2134  * @param key key of the result
2135  * @param get_path peers on reply path (or NULL if not recorded)
2136  *                 [0] = datastore's first neighbor, [length - 1] = local peer
2137  * @param get_path_length number of entries in @a get_path
2138  * @param put_path peers on the PUT path (or NULL if not recorded)
2139  *                 [0] = origin, [length - 1] = datastore
2140  * @param put_path_length number of entries in @a put_path
2141  * @param type type of the result
2142  * @param size number of bytes in data
2143  * @param data pointer to the result data
2144  */
2145 static void
2146 handle_dht_response (void *cls,
2147                      struct GNUNET_TIME_Absolute exp,
2148                      const struct GNUNET_HashCode *key,
2149                      const struct GNUNET_PeerIdentity *get_path,
2150                      unsigned int get_path_length,
2151                      const struct GNUNET_PeerIdentity *put_path,
2152                      unsigned int put_path_length,
2153                      enum GNUNET_BLOCK_Type type,
2154                      size_t size,
2155                      const void *data)
2156 {
2157   struct GNS_ResolverHandle *rh = cls;
2158   struct AuthorityChain *ac = rh->ac_tail;
2159   const struct GNUNET_GNSRECORD_Block *block;
2160   struct CacheOps *co;
2161
2162   (void) exp;
2163   (void) key;
2164   (void) get_path;
2165   (void) get_path_length;
2166   (void) put_path;
2167   (void) put_path_length;
2168   (void) type;
2169   GNUNET_DHT_get_stop (rh->get_handle);
2170   rh->get_handle = NULL;
2171   GNUNET_CONTAINER_heap_remove_node (rh->dht_heap_node);
2172   rh->dht_heap_node = NULL;
2173   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2174               "Handling response from the DHT\n");
2175   if (size < sizeof (struct GNUNET_GNSRECORD_Block))
2176   {
2177     /* how did this pass DHT block validation!? */
2178     GNUNET_break (0);
2179     rh->proc (rh->proc_cls, 0, NULL);
2180     GNS_resolver_lookup_cancel (rh);
2181     return;
2182   }
2183   block = data;
2184   if (size !=
2185       ntohl (block->purpose.size) +
2186       sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey) +
2187       sizeof (struct GNUNET_CRYPTO_EcdsaSignature))
2188   {
2189     /* how did this pass DHT block validation!? */
2190     GNUNET_break (0);
2191     rh->proc (rh->proc_cls, 0, NULL);
2192     GNS_resolver_lookup_cancel (rh);
2193     return;
2194   }
2195   if (GNUNET_OK !=
2196       GNUNET_GNSRECORD_block_decrypt (block,
2197                                       &ac->authority_info.gns_authority,
2198                                       ac->label,
2199                                       &handle_gns_resolution_result,
2200                                       rh))
2201   {
2202     GNUNET_break_op (0); /* block was ill-formed */
2203     rh->proc (rh->proc_cls, 0, NULL);
2204     GNS_resolver_lookup_cancel (rh);
2205     return;
2206   }
2207   if (0 == GNUNET_TIME_absolute_get_remaining (GNUNET_TIME_absolute_ntoh (block->expiration_time)).rel_value_us)
2208   {
2209     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2210                 "Received expired block from the DHT, will not cache it.\n");
2211     return;
2212   }
2213   /* Cache well-formed blocks */
2214   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2215               "Caching response from the DHT in namecache\n");
2216   co = GNUNET_new (struct CacheOps);
2217   co->namecache_qe_cache = GNUNET_NAMECACHE_block_cache (namecache_handle,
2218                                                          block,
2219                                                          &namecache_cache_continuation,
2220                                                          co);
2221   GNUNET_CONTAINER_DLL_insert (co_head,
2222                                co_tail,
2223                                co);
2224 }
2225
2226
2227 /**
2228  * Initiate a DHT query for a set of GNS records.
2229  *
2230  * @param rh resolution handle
2231  * @param query key to use in the DHT lookup
2232  */
2233 static void
2234 start_dht_request (struct GNS_ResolverHandle *rh,
2235                    const struct GNUNET_HashCode *query)
2236 {
2237   struct GNS_ResolverHandle *rx;
2238
2239   GNUNET_assert (NULL == rh->get_handle);
2240   rh->get_handle = GNUNET_DHT_get_start (dht_handle,
2241                                          GNUNET_BLOCK_TYPE_GNS_NAMERECORD,
2242                                          query,
2243                                          DHT_GNS_REPLICATION_LEVEL,
2244                                          GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE,
2245                                          NULL, 0,
2246                                          &handle_dht_response, rh);
2247   rh->dht_heap_node = GNUNET_CONTAINER_heap_insert (dht_lookup_heap,
2248                                                     rh,
2249                                                     GNUNET_TIME_absolute_get ().abs_value_us);
2250   if (GNUNET_CONTAINER_heap_get_size (dht_lookup_heap) > max_allowed_background_queries)
2251   {
2252     /* fail longest-standing DHT request */
2253     rx = GNUNET_CONTAINER_heap_peek (dht_lookup_heap);
2254     GNUNET_assert (NULL != rx);
2255     rx->proc (rx->proc_cls, 0, NULL);
2256     GNS_resolver_lookup_cancel (rx);
2257   }
2258 }
2259
2260
2261 /**
2262  * Process a records that were decrypted from a block that we got from
2263  * the namecache.  Simply calls #handle_gns_resolution_result().
2264  *
2265  * @param cls closure with the `struct GNS_ResolverHandle`
2266  * @param rd_count number of entries in @a rd array
2267  * @param rd array of records with data to store
2268  */
2269 static void
2270 handle_gns_namecache_resolution_result (void *cls,
2271                                         unsigned int rd_count,
2272                                         const struct GNUNET_GNSRECORD_Data *rd)
2273 {
2274   struct GNS_ResolverHandle *rh = cls;
2275
2276   handle_gns_resolution_result (rh,
2277                                 rd_count,
2278                                 rd);
2279 }
2280
2281
2282 /**
2283  * Process a record that was stored in the namecache.
2284  *
2285  * @param cls closure with the `struct GNS_ResolverHandle`
2286  * @param block block that was stored in the namecache
2287  */
2288 static void
2289 handle_namecache_block_response (void *cls,
2290                                  const struct GNUNET_GNSRECORD_Block *block)
2291 {
2292   struct GNS_ResolverHandle *rh = cls;
2293   struct AuthorityChain *ac = rh->ac_tail;
2294   const char *label = ac->label;
2295   const struct GNUNET_CRYPTO_EcdsaPublicKey *auth = &ac->authority_info.gns_authority;
2296   struct GNUNET_HashCode query;
2297
2298   GNUNET_assert (NULL != rh->namecache_qe);
2299   rh->namecache_qe = NULL;
2300   if ( ( (GNUNET_GNS_LO_DEFAULT == rh->options) ||
2301          ( (GNUNET_GNS_LO_LOCAL_MASTER == rh->options) &&
2302            (ac != rh->ac_head) ) ) &&
2303        ( (NULL == block) ||
2304          (0 == GNUNET_TIME_absolute_get_remaining (GNUNET_TIME_absolute_ntoh (block->expiration_time)).rel_value_us) ) )
2305   {
2306     /* namecache knows nothing; try DHT lookup */
2307     GNUNET_GNSRECORD_query_from_public_key (auth,
2308                                             label,
2309                                             &query);
2310     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2311                 "Starting DHT lookup for `%s' in zone `%s' under key `%s'\n",
2312                 ac->label,
2313                 GNUNET_GNSRECORD_z2s (&ac->authority_info.gns_authority),
2314                 GNUNET_h2s (&query));
2315     start_dht_request (rh, &query);
2316     return;
2317   }
2318
2319   if ( (NULL == block) ||
2320        (0 == GNUNET_TIME_absolute_get_remaining (GNUNET_TIME_absolute_ntoh (block->expiration_time)).rel_value_us) )
2321   {
2322     /* DHT not permitted and no local result, fail */
2323     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2324                 "Resolution failed for `%s' in zone %s (DHT lookup not permitted by configuration)\n",
2325                 ac->label,
2326                 GNUNET_GNSRECORD_z2s (&ac->authority_info.gns_authority));
2327     rh->proc (rh->proc_cls, 0, NULL);
2328     GNS_resolver_lookup_cancel (rh);
2329     return;
2330   }
2331   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2332               "Received result from namecache for label `%s'\n",
2333               ac->label);
2334
2335   if (GNUNET_OK !=
2336       GNUNET_GNSRECORD_block_decrypt (block,
2337                                       auth,
2338                                       label,
2339                                       &handle_gns_namecache_resolution_result,
2340                                       rh))
2341   {
2342     GNUNET_break_op (0); /* block was ill-formed */
2343     /* try DHT instead */
2344     GNUNET_GNSRECORD_query_from_public_key (auth,
2345                                             label,
2346                                             &query);
2347     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2348                 "Starting DHT lookup for `%s' in zone `%s' under key `%s'\n",
2349                 ac->label,
2350                 GNUNET_GNSRECORD_z2s (&ac->authority_info.gns_authority),
2351                 GNUNET_h2s (&query));
2352     start_dht_request (rh, &query);
2353     return;
2354   }
2355 }
2356
2357
2358 /**
2359  * Lookup tail of our authority chain in the namecache.
2360  *
2361  * @param rh query we are processing
2362  */
2363 static void
2364 recursive_gns_resolution_namecache (struct GNS_ResolverHandle *rh)
2365 {
2366   struct AuthorityChain *ac = rh->ac_tail;
2367   struct GNUNET_HashCode query;
2368
2369   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2370               "Starting GNS resolution for `%s' in zone %s\n",
2371               ac->label,
2372               GNUNET_GNSRECORD_z2s (&ac->authority_info.gns_authority));
2373   GNUNET_GNSRECORD_query_from_public_key (&ac->authority_info.gns_authority,
2374                                           ac->label,
2375                                           &query);
2376   if (GNUNET_YES == use_cache)
2377   {
2378     rh->namecache_qe
2379       = GNUNET_NAMECACHE_lookup_block (namecache_handle,
2380                                        &query,
2381                                        &handle_namecache_block_response,
2382                                        rh);
2383     GNUNET_assert (NULL != rh->namecache_qe);
2384   }
2385   else
2386   {
2387     start_dht_request (rh, &query);
2388   }
2389 }
2390
2391
2392 /**
2393  * Function called with the result from a revocation check.
2394  *
2395  * @param cls the `struct GNS_ResovlerHandle`
2396  * @param is_valid #GNUNET_YES if the zone was not yet revoked
2397  */
2398 static void
2399 handle_revocation_result (void *cls,
2400                           int is_valid)
2401 {
2402   struct GNS_ResolverHandle *rh = cls;
2403   struct AuthorityChain *ac = rh->ac_tail;
2404
2405   rh->rev_check = NULL;
2406   if (GNUNET_YES != is_valid)
2407   {
2408     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
2409                 _("Zone %s was revoked, resolution fails\n"),
2410                 GNUNET_GNSRECORD_z2s (&ac->authority_info.gns_authority));
2411     rh->proc (rh->proc_cls, 0, NULL);
2412     GNS_resolver_lookup_cancel (rh);
2413     return;
2414   }
2415   recursive_gns_resolution_namecache (rh);
2416 }
2417
2418
2419 /**
2420  * Perform revocation check on tail of our authority chain.
2421  *
2422  * @param rh query we are processing
2423  */
2424 static void
2425 recursive_gns_resolution_revocation (struct GNS_ResolverHandle *rh)
2426 {
2427   struct AuthorityChain *ac = rh->ac_tail;
2428
2429   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2430               "Starting revocation check for zone %s\n",
2431               GNUNET_GNSRECORD_z2s (&ac->authority_info.gns_authority));
2432   rh->rev_check = GNUNET_REVOCATION_query (cfg,
2433                                            &ac->authority_info.gns_authority,
2434                                            &handle_revocation_result,
2435                                            rh);
2436   GNUNET_assert (NULL != rh->rev_check);
2437 }
2438
2439
2440 /**
2441  * Task scheduled to continue with the resolution process.
2442  *
2443  * @param cls the `struct GNS_ResolverHandle` of the resolution
2444  */
2445 static void
2446 recursive_resolution (void *cls)
2447 {
2448   struct GNS_ResolverHandle *rh = cls;
2449
2450   rh->task_id = NULL;
2451   if (MAX_RECURSION < rh->loop_limiter++)
2452   {
2453     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
2454                 "Encountered unbounded recursion resolving `%s'\n",
2455                 rh->name);
2456     rh->proc (rh->proc_cls, 0, NULL);
2457     GNS_resolver_lookup_cancel (rh);
2458     return;
2459   }
2460   if (GNUNET_YES == rh->ac_tail->gns_authority)
2461     recursive_gns_resolution_revocation (rh);
2462   else
2463     recursive_dns_resolution (rh);
2464 }
2465
2466
2467 /**
2468  * Begin the resolution process from 'name', starting with
2469  * the identification of the zone specified by 'name'.
2470  *
2471  * @param cls the `struct GNS_ResolverHandle`
2472  */
2473 static void
2474 start_resolver_lookup (void *cls)
2475 {
2476   struct GNS_ResolverHandle *rh = cls;
2477   struct AuthorityChain *ac;
2478   struct in_addr v4;
2479   struct in6_addr v6;
2480
2481   rh->task_id = NULL;
2482   if (1 == inet_pton (AF_INET,
2483                       rh->name,
2484                       &v4))
2485   {
2486     /* name is IPv4 address, pretend it's an A record */
2487     struct GNUNET_GNSRECORD_Data rd;
2488
2489     rd.data = &v4;
2490     rd.data_size = sizeof (v4);
2491     rd.expiration_time = UINT64_MAX;
2492     rd.record_type = GNUNET_DNSPARSER_TYPE_A;
2493     rd.flags = 0;
2494     rh->proc (rh->proc_cls, 1, &rd);
2495     GNS_resolver_lookup_cancel (rh);
2496     return;
2497   }
2498   if (1 == inet_pton (AF_INET6,
2499                       rh->name,
2500                       &v6))
2501   {
2502     /* name is IPv6 address, pretend it's an AAAA record */
2503     struct GNUNET_GNSRECORD_Data rd;
2504
2505     rd.data = &v6;
2506     rd.data_size = sizeof (v6);
2507     rd.expiration_time = UINT64_MAX;
2508     rd.record_type = GNUNET_DNSPARSER_TYPE_AAAA;
2509     rd.flags = 0;
2510     rh->proc (rh->proc_cls, 1, &rd);
2511     GNS_resolver_lookup_cancel (rh);
2512     return;
2513   }
2514
2515   ac = GNUNET_new (struct AuthorityChain);
2516   ac->rh = rh;
2517   ac->label = resolver_lookup_get_next_label (rh);
2518   ac->suggested_shortening_label = NULL;
2519   if (NULL == ac->label)
2520     /* name was just the "TLD", so we default to label
2521        #GNUNET_GNS_MASTERZONE_STR */
2522     ac->label = GNUNET_strdup (GNUNET_GNS_MASTERZONE_STR);
2523   ac->gns_authority = GNUNET_YES;
2524   ac->authority_info.gns_authority = rh->authority_zone;
2525   GNUNET_CONTAINER_DLL_insert_tail (rh->ac_head,
2526                                     rh->ac_tail,
2527                                     ac);
2528   rh->task_id = GNUNET_SCHEDULER_add_now (&recursive_resolution,
2529                                           rh);
2530 }
2531
2532
2533 /**
2534  * Lookup of a record in a specific zone calls lookup result processor
2535  * on result.
2536  *
2537  * @param zone the zone to perform the lookup in
2538  * @param record_type the record type to look up
2539  * @param name the name to look up
2540  * @param options local options to control local lookup
2541  * @param proc the processor to call on result
2542  * @param proc_cls the closure to pass to @a proc
2543  * @return handle to cancel operation
2544  */
2545 struct GNS_ResolverHandle *
2546 GNS_resolver_lookup (const struct GNUNET_CRYPTO_EcdsaPublicKey *zone,
2547                      uint32_t record_type,
2548                      const char *name,
2549                      enum GNUNET_GNS_LocalOptions options,
2550                      GNS_ResultProcessor proc,
2551                      void *proc_cls)
2552 {
2553   struct GNS_ResolverHandle *rh;
2554
2555   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2556               "Starting lookup for `%s'\n",
2557               name);
2558   rh = GNUNET_new (struct GNS_ResolverHandle);
2559   GNUNET_CONTAINER_DLL_insert (rlh_head,
2560                                rlh_tail,
2561                                rh);
2562   rh->authority_zone = *zone;
2563   rh->proc = proc;
2564   rh->proc_cls = proc_cls;
2565   rh->options = options;
2566   rh->record_type = record_type;
2567   rh->name = GNUNET_strdup (name);
2568   rh->name_resolution_pos = strlen (name);
2569   rh->task_id = GNUNET_SCHEDULER_add_now (&start_resolver_lookup,
2570                                           rh);
2571   return rh;
2572 }
2573
2574
2575 /**
2576  * Cancel active resolution (i.e. client disconnected).
2577  *
2578  * @param rh resolution to abort
2579  */
2580 void
2581 GNS_resolver_lookup_cancel (struct GNS_ResolverHandle *rh)
2582 {
2583   struct DnsResult *dr;
2584   struct AuthorityChain *ac;
2585   struct VpnContext *vpn_ctx;
2586
2587   GNUNET_CONTAINER_DLL_remove (rlh_head,
2588                                rlh_tail,
2589                                rh);
2590   while (NULL != (ac = rh->ac_head))
2591   {
2592     GNUNET_CONTAINER_DLL_remove (rh->ac_head,
2593                                  rh->ac_tail,
2594                                  ac);
2595     GNUNET_free (ac->label);
2596     GNUNET_free_non_null (ac->suggested_shortening_label);
2597     GNUNET_free (ac);
2598   }
2599   if (NULL != rh->g2dc)
2600   {
2601     /* rh->g2dc->rh is NOT in the DLL yet, so to enable us
2602        using GNS_resolver_lookup_cancel here, we need to
2603        add it first... */
2604     if (NULL != rh->g2dc->rh)
2605     {
2606       GNUNET_CONTAINER_DLL_insert (rlh_head,
2607                                    rlh_tail,
2608                                    rh->g2dc->rh);
2609       GNS_resolver_lookup_cancel (rh->g2dc->rh);
2610       rh->g2dc->rh = NULL;
2611     }
2612     if (NULL != rh->g2dc->dns_rh)
2613     {
2614       GNUNET_RESOLVER_request_cancel (rh->g2dc->dns_rh);
2615       rh->g2dc->rh = NULL;
2616     }
2617     GNUNET_free (rh->g2dc->ns);
2618     GNUNET_free (rh->g2dc);
2619     rh->g2dc = NULL;
2620   }
2621   if (NULL != rh->task_id)
2622   {
2623     GNUNET_SCHEDULER_cancel (rh->task_id);
2624     rh->task_id = NULL;
2625   }
2626   if (NULL != rh->get_handle)
2627   {
2628     GNUNET_DHT_get_stop (rh->get_handle);
2629     rh->get_handle = NULL;
2630   }
2631   if (NULL != rh->dht_heap_node)
2632   {
2633     GNUNET_CONTAINER_heap_remove_node (rh->dht_heap_node);
2634     rh->dht_heap_node = NULL;
2635   }
2636   if (NULL != (vpn_ctx = rh->vpn_ctx))
2637   {
2638     GNUNET_VPN_cancel_request (vpn_ctx->vpn_request);
2639     GNUNET_free (vpn_ctx->rd_data);
2640     GNUNET_free (vpn_ctx);
2641   }
2642   if (NULL != rh->dns_request)
2643   {
2644     GNUNET_DNSSTUB_resolve_cancel (rh->dns_request);
2645     rh->dns_request = NULL;
2646   }
2647   if (NULL != rh->namecache_qe)
2648   {
2649     GNUNET_NAMECACHE_cancel (rh->namecache_qe);
2650     rh->namecache_qe = NULL;
2651   }
2652   if (NULL != rh->rev_check)
2653   {
2654     GNUNET_REVOCATION_query_cancel (rh->rev_check);
2655     rh->rev_check = NULL;
2656   }
2657   if (NULL != rh->std_resolve)
2658   {
2659     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2660                 "Canceling standard DNS resolution\n");
2661     GNUNET_RESOLVER_request_cancel (rh->std_resolve);
2662     rh->std_resolve = NULL;
2663   }
2664   while (NULL != (dr = rh->dns_result_head))
2665   {
2666     GNUNET_CONTAINER_DLL_remove (rh->dns_result_head,
2667                                  rh->dns_result_tail,
2668                                  dr);
2669     GNUNET_free (dr);
2670   }
2671   GNUNET_free (rh->name);
2672   GNUNET_free (rh);
2673 }
2674
2675
2676 /* ***************** Resolver initialization ********************* */
2677
2678
2679 /**
2680  * Initialize the resolver
2681  *
2682  * @param nc the namecache handle
2683  * @param dht the dht handle
2684  * @param c configuration handle
2685  * @param max_bg_queries maximum number of parallel background queries in dht
2686  */
2687 void
2688 GNS_resolver_init (struct GNUNET_NAMECACHE_Handle *nc,
2689                    struct GNUNET_DHT_Handle *dht,
2690                    const struct GNUNET_CONFIGURATION_Handle *c,
2691                    unsigned long long max_bg_queries)
2692 {
2693   char *dns_ip;
2694
2695   cfg = c;
2696   namecache_handle = nc;
2697   dht_handle = dht;
2698   dht_lookup_heap =
2699     GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN);
2700   max_allowed_background_queries = max_bg_queries;
2701   if (GNUNET_SYSERR == (use_cache =
2702                         GNUNET_CONFIGURATION_get_value_yesno (c,
2703                                                               "gns",
2704                                                               "USE_CACHE")))
2705     use_cache = GNUNET_YES;
2706   if (GNUNET_NO == use_cache)
2707     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2708                 "Namecache disabled\n");
2709
2710   if (GNUNET_OK !=
2711       GNUNET_CONFIGURATION_get_value_string (c,
2712                                              "gns",
2713                                              "DNS_RESOLVER",
2714                                              &dns_ip))
2715   {
2716     /* user did not specify DNS resolver, use 8.8.8.8 */
2717     dns_ip = GNUNET_strdup ("8.8.8.8");
2718   }
2719   dns_handle = GNUNET_DNSSTUB_start (dns_ip);
2720   GNUNET_free (dns_ip);
2721   vpn_handle = GNUNET_VPN_connect (cfg);
2722 }
2723
2724
2725 /**
2726  * Shutdown resolver
2727  */
2728 void
2729 GNS_resolver_done ()
2730 {
2731   struct GNS_ResolverHandle *rh;
2732   struct CacheOps *co;
2733
2734   /* abort active resolutions */
2735   while (NULL != (rh = rlh_head))
2736   {
2737     rh->proc (rh->proc_cls, 0, NULL);
2738     GNS_resolver_lookup_cancel (rh);
2739   }
2740   while (NULL != (co = co_head))
2741   {
2742     GNUNET_CONTAINER_DLL_remove (co_head,
2743                                  co_tail,
2744                                  co);
2745     GNUNET_NAMECACHE_cancel (co->namecache_qe_cache);
2746     GNUNET_free (co);
2747   }
2748   GNUNET_CONTAINER_heap_destroy (dht_lookup_heap);
2749   dht_lookup_heap = NULL;
2750   GNUNET_DNSSTUB_stop (dns_handle);
2751   dns_handle = NULL;
2752   GNUNET_VPN_disconnect (vpn_handle);
2753   vpn_handle = NULL;
2754   dht_handle = NULL;
2755   namecache_handle = NULL;
2756 }
2757
2758
2759 /* end of gnunet-service-gns_resolver.c */