cleaning up set handlers, eliminating 2nd level demultiplexing and improving use...
[oweals/gnunet.git] / src / vpn / gnunet-service-vpn.c
1 /*
2      This file is part of GNUnet.
3      Copyright (C) 2010, 2011, 2012, 2016, 2017 Christian Grothoff
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 vpn/gnunet-service-vpn.c
23  * @brief service that opens a virtual interface and allows its clients
24  *        to allocate IPs on the virtual interface and to then redirect
25  *        IP traffic received on those IPs via the GNUnet cadet
26  * @author Philipp Toelke
27  * @author Christian Grothoff
28  *
29  * TODO:
30  * - keep multiple peers/cadet channels ready as alternative exits /
31  *   detect & recover from channel-to-exit failure gracefully
32  */
33 #include "platform.h"
34 #include "gnunet_util_lib.h"
35 #include "gnunet_common.h"
36 #include "gnunet_protocols.h"
37 #include "gnunet_applications.h"
38 #include "gnunet_cadet_service.h"
39 #include "gnunet_statistics_service.h"
40 #include "gnunet_constants.h"
41 #include "gnunet_tun_lib.h"
42 #include "gnunet_regex_service.h"
43 #include "vpn.h"
44 #include "exit.h"
45
46
47 /**
48  * Maximum number of messages we allow in the queue for cadet.
49  */
50 #define MAX_MESSAGE_QUEUE_SIZE 4
51
52
53 /**
54  * State we keep for each of our channels.
55  */
56 struct ChannelState;
57
58 /**
59  * Information we track for each IP address to determine which channel
60  * to send the traffic over to the destination.
61  */
62 struct DestinationEntry;
63
64 /**
65  * List of channels we keep for each destination port for a given
66  * destination entry.
67  */
68 struct DestinationChannel
69 {
70
71   /**
72    * Kept in a DLL.
73    */
74   struct DestinationChannel *next;
75
76   /**
77    * Kept in a DLL.
78    */
79   struct DestinationChannel *prev;
80
81   /**
82    * Destination entry list this `struct DestinationChannel` belongs with.
83    */
84   struct DestinationEntry *destination;
85
86   /**
87    * Destination port this channel state is used for.
88    */
89   uint16_t destination_port;
90
91 };
92
93
94 /**
95  * Information we track for each IP address to determine which channel
96  * to send the traffic over to the destination.
97  */
98 struct DestinationEntry
99 {
100
101   /**
102    * Key under which this entry is in the 'destination_map' (only valid
103    * if 'heap_node != NULL').
104    */
105   struct GNUNET_HashCode key;
106
107   /**
108    * Head of DLL of channels associated with this destination.
109    */
110   struct DestinationChannel *dt_head;
111
112   /**
113    * Tail of DLL of channels associated with this destination.
114    */
115   struct DestinationChannel *dt_tail;
116
117   /**
118    * Entry for this entry in the destination_heap.
119    */
120   struct GNUNET_CONTAINER_HeapNode *heap_node;
121
122   /**
123    * #GNUNET_NO if this is a channel to an Internet-exit,
124    * #GNUNET_YES if this channel is to a service.
125    */
126   int is_service;
127
128   /**
129    * Details about the connection (depending on is_service).
130    */
131   union
132   {
133
134     struct
135     {
136       /**
137        * The description of the service (only used for service channels).
138        */
139       struct GNUNET_HashCode service_descriptor;
140
141       /**
142        * Peer offering the service.
143        */
144       struct GNUNET_PeerIdentity target;
145
146     } service_destination;
147
148     struct
149     {
150
151       /**
152        * Address family used (AF_INET or AF_INET6).
153        */
154       int af;
155
156       /**
157        * IP address of the ultimate destination (only used for exit channels).
158        */
159       union
160       {
161         /**
162          * Address if af is AF_INET.
163          */
164         struct in_addr v4;
165
166         /**
167          * Address if af is AF_INET6.
168          */
169         struct in6_addr v6;
170       } ip;
171
172     } exit_destination;
173
174   } details;
175
176 };
177
178
179 /**
180  * A messages we have in queue for a particular channel.
181  */
182 struct ChannelMessageQueueEntry
183 {
184   /**
185    * This is a doubly-linked list.
186    */
187   struct ChannelMessageQueueEntry *next;
188
189   /**
190    * This is a doubly-linked list.
191    */
192   struct ChannelMessageQueueEntry *prev;
193
194   /**
195    * Number of bytes in @e msg.
196    */
197   size_t len;
198
199   /**
200    * Message to transmit, allocated at the end of this struct.
201    */
202   const void *msg;
203 };
204
205
206 /**
207  * State we keep for each of our channels.
208  */
209 struct ChannelState
210 {
211
212   /**
213    * Information about the channel to use, NULL if no channel
214    * is available right now.
215    */
216   struct GNUNET_CADET_Channel *channel;
217
218   /**
219    * Active query with REGEX to locate exit.
220    */
221   struct GNUNET_REGEX_Search *search;
222
223   /**
224    * Entry for this entry in the channel_heap, NULL as long as this
225    * channel state is not fully bound.
226    */
227   struct GNUNET_CONTAINER_HeapNode *heap_node;
228
229   /**
230    * Head of list of messages scheduled for transmission.
231    */
232   struct ChannelMessageQueueEntry *tmq_head;
233
234   /**
235    * Tail of list of messages scheduled for transmission.
236    */
237   struct ChannelMessageQueueEntry *tmq_tail;
238
239   /**
240    * Destination to which this channel leads.  Note that
241    * this struct is NOT in the destination_map (but a
242    * local copy) and that the 'heap_node' should always
243    * be NULL.
244    */
245   struct DestinationEntry destination;
246
247   /**
248    * Addess family used for this channel on the local TUN interface.
249    */
250   int af;
251
252   /**
253    * Is this channel new (#GNUNET_NO), or did we exchange messages with the
254    * other side already (#GNUNET_YES)?
255    */
256   int is_established;
257
258   /**
259    * Length of the doubly linked 'tmq_head/tmq_tail' list.
260    */
261   unsigned int tmq_length;
262
263   /**
264    * IPPROTO_TCP or IPPROTO_UDP once bound.
265    */
266   uint8_t protocol;
267
268   /**
269    * IP address of the source on our end, initially uninitialized.
270    */
271   union
272   {
273     /**
274      * Address if af is AF_INET.
275      */
276     struct in_addr v4;
277
278     /**
279      * Address if af is AF_INET6.
280      */
281     struct in6_addr v6;
282
283   } source_ip;
284
285   /**
286    * Destination IP address used by the source on our end (this is the IP
287    * that we pick freely within the VPN's channel IP range).
288    */
289   union
290   {
291     /**
292      * Address if af is AF_INET.
293      */
294     struct in_addr v4;
295
296     /**
297      * Address if af is AF_INET6.
298      */
299     struct in6_addr v6;
300
301   } destination_ip;
302
303   /**
304    * Source port used by the sender on our end; 0 for uninitialized.
305    */
306   uint16_t source_port;
307
308   /**
309    * Destination port used by the sender on our end; 0 for uninitialized.
310    */
311   uint16_t destination_port;
312
313 };
314
315
316 /**
317  * Return value from #main().
318  */
319 static int global_ret;
320
321 /**
322  * Configuration we use.
323  */
324 static const struct GNUNET_CONFIGURATION_Handle *cfg;
325
326 /**
327  * Handle to the cadet service.
328  */
329 static struct GNUNET_CADET_Handle *cadet_handle;
330
331 /**
332  * Map from IP address to destination information (possibly with a
333  * CADET channel handle for fast setup).
334  */
335 static struct GNUNET_CONTAINER_MultiHashMap *destination_map;
336
337 /**
338  * Min-Heap sorted by activity time to expire old mappings.
339  */
340 static struct GNUNET_CONTAINER_Heap *destination_heap;
341
342 /**
343  * Map from source and destination address (IP+port) to connection
344  * information (mostly with the respective CADET channel handle).
345  */
346 static struct GNUNET_CONTAINER_MultiHashMap *channel_map;
347
348 /**
349  * Min-Heap sorted by activity time to expire old mappings; values are
350  * of type 'struct ChannelState'.
351  */
352 static struct GNUNET_CONTAINER_Heap *channel_heap;
353
354 /**
355  * Statistics.
356  */
357 static struct GNUNET_STATISTICS_Handle *stats;
358
359 /**
360  * The handle to the VPN helper process "gnunet-helper-vpn".
361  */
362 static struct GNUNET_HELPER_Handle *helper_handle;
363
364 /**
365  * Arguments to the vpn helper.
366  */
367 static char *vpn_argv[7];
368
369 /**
370  * Length of the prefix of the VPN's IPv6 network.
371  */
372 static unsigned long long ipv6prefix;
373
374 /**
375  * If there are more than this number of address-mappings, old ones
376  * will be removed
377  */
378 static unsigned long long max_destination_mappings;
379
380 /**
381  * If there are more than this number of open channels, old ones
382  * will be removed
383  */
384 static unsigned long long max_channel_mappings;
385
386
387 /**
388  * Compute the key under which we would store an entry in the
389  * #destination_map for the given IP address.
390  *
391  * @param af address family (AF_INET or AF_INET6)
392  * @param address IP address, struct in_addr or struct in6_addr
393  * @param key where to store the key
394  */
395 static void
396 get_destination_key_from_ip (int af,
397                              const void *address,
398                              struct GNUNET_HashCode *key)
399 {
400   switch (af)
401   {
402   case AF_INET:
403     GNUNET_CRYPTO_hash (address,
404                         sizeof (struct in_addr),
405                         key);
406     break;
407   case AF_INET6:
408     GNUNET_CRYPTO_hash (address,
409                         sizeof (struct in6_addr),
410                         key);
411     break;
412   default:
413     GNUNET_assert (0);
414     break;
415   }
416 }
417
418
419 /**
420  * Compute the key under which we would store an entry in the
421  * channel_map for the given socket address pair.
422  *
423  * @param af address family (AF_INET or AF_INET6)
424  * @param protocol IPPROTO_TCP or IPPROTO_UDP
425  * @param source_ip sender's source IP, struct in_addr or struct in6_addr
426  * @param source_port sender's source port
427  * @param destination_ip sender's destination IP, struct in_addr or struct in6_addr
428  * @param destination_port sender's destination port
429  * @param key where to store the key
430  */
431 static void
432 get_channel_key_from_ips (int af,
433                           uint8_t protocol,
434                           const void *source_ip,
435                           uint16_t source_port,
436                           const void *destination_ip,
437                           uint16_t destination_port,
438                           struct GNUNET_HashCode *key)
439 {
440   char *off;
441
442   memset (key, 0, sizeof (struct GNUNET_HashCode));
443   /* the GNUnet hashmap only uses the first sizeof(unsigned int) of the hash,
444      so we put the ports in there (and hope for few collisions) */
445   off = (char*) key;
446   GNUNET_memcpy (off, &source_port, sizeof (uint16_t));
447   off += sizeof (uint16_t);
448   GNUNET_memcpy (off, &destination_port, sizeof (uint16_t));
449   off += sizeof (uint16_t);
450   switch (af)
451   {
452   case AF_INET:
453     GNUNET_memcpy (off, source_ip, sizeof (struct in_addr));
454     off += sizeof (struct in_addr);
455     GNUNET_memcpy (off, destination_ip, sizeof (struct in_addr));
456     off += sizeof (struct in_addr);
457     break;
458   case AF_INET6:
459     GNUNET_memcpy (off, source_ip, sizeof (struct in6_addr));
460     off += sizeof (struct in6_addr);
461     GNUNET_memcpy (off, destination_ip, sizeof (struct in6_addr));
462     off += sizeof (struct in6_addr);
463     break;
464   default:
465     GNUNET_assert (0);
466     break;
467   }
468   GNUNET_memcpy (off, &protocol, sizeof (uint8_t));
469   /* off += sizeof (uint8_t);  */
470 }
471
472
473 /**
474  * Notify the client about the result of its request.
475  *
476  * @param client client to notify
477  * @param request_id original request ID to include in response
478  * @param result_af resulting address family
479  * @param addr resulting IP address
480  */
481 static void
482 send_client_reply (struct GNUNET_SERVICE_Client *client,
483                    uint64_t request_id,
484                    int result_af,
485                    const void *addr)
486 {
487   struct GNUNET_MQ_Envelope *env;
488   struct RedirectToIpResponseMessage *res;
489   size_t rlen;
490
491   switch (result_af)
492   {
493   case AF_INET:
494     rlen = sizeof (struct in_addr);
495     break;
496   case AF_INET6:
497     rlen = sizeof (struct in6_addr);
498     break;
499   case AF_UNSPEC:
500     rlen = 0;
501     break;
502   default:
503     GNUNET_assert (0);
504     return;
505   }
506   env = GNUNET_MQ_msg_extra (res,
507                              rlen,
508                              GNUNET_MESSAGE_TYPE_VPN_CLIENT_USE_IP);
509   res->result_af = htonl (result_af);
510   res->request_id = request_id;
511   GNUNET_memcpy (&res[1],
512                  addr,
513                  rlen);
514   GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq (client),
515                   env);
516 }
517
518
519 /**
520  * Free resources associated with a channel state.
521  *
522  * @param ts state to free
523  */
524 static void
525 free_channel_state (struct ChannelState *ts)
526 {
527   struct GNUNET_HashCode key;
528   struct ChannelMessageQueueEntry *tnq;
529   struct GNUNET_CADET_Channel *channel;
530
531   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
532               "Cleaning up channel state\n");
533   if (NULL != (channel = ts->channel))
534   {
535     ts->channel = NULL;
536     GNUNET_CADET_channel_destroy (channel);
537     return;
538   }
539   GNUNET_STATISTICS_update (stats,
540                             gettext_noop ("# Active channels"),
541                             -1, GNUNET_NO);
542   while (NULL != (tnq = ts->tmq_head))
543   {
544     GNUNET_CONTAINER_DLL_remove (ts->tmq_head,
545                                  ts->tmq_tail,
546                                  tnq);
547     ts->tmq_length--;
548     GNUNET_free (tnq);
549   }
550   GNUNET_assert (0 == ts->tmq_length);
551   GNUNET_assert (NULL == ts->destination.heap_node);
552   if (NULL != ts->search)
553   {
554     GNUNET_REGEX_search_cancel (ts->search);
555     ts->search = NULL;
556   }
557   if (NULL != ts->heap_node)
558   {
559     GNUNET_CONTAINER_heap_remove_node (ts->heap_node);
560     ts->heap_node = NULL;
561     get_channel_key_from_ips (ts->af,
562                              ts->protocol,
563                              &ts->source_ip,
564                              ts->source_port,
565                              &ts->destination_ip,
566                              ts->destination_port,
567                              &key);
568     GNUNET_assert (GNUNET_YES ==
569                    GNUNET_CONTAINER_multihashmap_remove (channel_map,
570                                                          &key,
571                                                          ts));
572   }
573   GNUNET_free (ts);
574 }
575
576
577 /**
578  * Add the given message to the given channel and trigger the
579  * transmission process.
580  *
581  * @param ts channel to queue the message for
582  * @param env message to queue
583  */
584 static void
585 send_to_channel (struct ChannelState *ts,
586                  struct GNUNET_MQ_Envelope *env)
587 {
588   struct GNUNET_MQ_Handle *mq;
589
590   GNUNET_assert (NULL != ts->channel);
591   mq = GNUNET_CADET_get_mq (ts->channel);
592   GNUNET_MQ_send (mq,
593                   env);
594   if (GNUNET_MQ_get_length (mq) > MAX_MESSAGE_QUEUE_SIZE)
595   {
596     env = GNUNET_MQ_unsent_head (mq);
597     GNUNET_assert (NULL != env);
598     GNUNET_STATISTICS_update (stats,
599                               gettext_noop ("# Messages dropped in cadet queue (overflow)"),
600                               1,
601                               GNUNET_NO);
602     GNUNET_MQ_discard (env);
603   }
604 }
605
606
607 /**
608  * Output destination of a channel for diagnostics.
609  *
610  * @param de destination to process
611  * @return diagnostic string describing destination
612  */
613 static const char *
614 print_channel_destination (const struct DestinationEntry *de)
615 {
616   static char dest[256];
617
618   if (de->is_service)
619   {
620     GNUNET_snprintf (dest,
621                      sizeof (dest),
622                      "HS: %s-%s",
623                      GNUNET_i2s (&de->details.service_destination.target),
624                      GNUNET_h2s (&de->details.service_destination.service_descriptor));
625   }
626   else
627   {
628     inet_ntop (de->details.exit_destination.af,
629                &de->details.exit_destination.ip,
630                dest,
631                sizeof (dest));
632   }
633   return dest;
634 }
635
636
637 /**
638  * Function called whenever a channel is destroyed.  Should clean up
639  * any associated state.
640  *
641  * @param cls our `struct ChannelState`
642  * @param channel connection to the other end (henceforth invalid)
643  */
644 static void
645 channel_cleaner (void *cls,
646                  const struct GNUNET_CADET_Channel *channel)
647 {
648   struct ChannelState *ts = cls;
649
650   ts->channel = NULL; /* we must not call GNUNET_CADET_channel_destroy() anymore */
651   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
652               "CADET notified us about death of channel to `%s'\n",
653               print_channel_destination (&ts->destination));
654   free_channel_state (ts);
655 }
656
657
658 /**
659  * Synthesize a plausible ICMP payload for an ICMP error
660  * response on the given channel.
661  *
662  * @param ts channel information
663  * @param ipp IPv4 header to fill in (ICMP payload)
664  * @param udp "UDP" header to fill in (ICMP payload); might actually
665  *            also be the first 8 bytes of the TCP header
666  */
667 static void
668 make_up_icmpv4_payload (struct ChannelState *ts,
669                         struct GNUNET_TUN_IPv4Header *ipp,
670                         struct GNUNET_TUN_UdpHeader *udp)
671 {
672   GNUNET_TUN_initialize_ipv4_header (ipp,
673                                      ts->protocol,
674                                      sizeof (struct GNUNET_TUN_TcpHeader),
675                                      &ts->source_ip.v4,
676                                      &ts->destination_ip.v4);
677   udp->source_port = htons (ts->source_port);
678   udp->destination_port = htons (ts->destination_port);
679   udp->len = htons (0);
680   udp->crc = htons (0);
681 }
682
683
684 /**
685  * Synthesize a plausible ICMP payload for an ICMP error
686  * response on the given channel.
687  *
688  * @param ts channel information
689  * @param ipp IPv6 header to fill in (ICMP payload)
690  * @param udp "UDP" header to fill in (ICMP payload); might actually
691  *            also be the first 8 bytes of the TCP header
692  */
693 static void
694 make_up_icmpv6_payload (struct ChannelState *ts,
695                         struct GNUNET_TUN_IPv6Header *ipp,
696                         struct GNUNET_TUN_UdpHeader *udp)
697 {
698   GNUNET_TUN_initialize_ipv6_header (ipp,
699                                      ts->protocol,
700                                      sizeof (struct GNUNET_TUN_TcpHeader),
701                                      &ts->source_ip.v6,
702                                      &ts->destination_ip.v6);
703   udp->source_port = htons (ts->source_port);
704   udp->destination_port = htons (ts->destination_port);
705   udp->len = htons (0);
706   udp->crc = htons (0);
707 }
708
709
710 /**
711  * We got an ICMP packet back from the CADET channel.  Check it is OK.
712  *
713  * @param cls our `struct ChannelState *`
714  * @param message the actual message
715  * @return #GNUNET_OK to keep the connection open,
716  *         #GNUNET_SYSERR to close it (signal serious error)
717  */
718 static int
719 check_icmp_back (void *cls,
720                  const struct GNUNET_EXIT_IcmpToVPNMessage *i2v)
721 {
722   struct ChannelState *ts = cls;
723
724   if (NULL == ts->heap_node)
725   {
726     GNUNET_break_op (0);
727     return GNUNET_SYSERR;
728   }
729   if (AF_UNSPEC == ts->af)
730   {
731     GNUNET_break_op (0);
732     return GNUNET_SYSERR;
733   }
734   return GNUNET_OK;
735 }
736
737
738 /**
739  * We got an ICMP packet back from the CADET channel.  Pass it on to the
740  * local virtual interface via the helper.
741  *
742  * @param cls our `struct ChannelState *`
743  * @param message the actual message
744  */
745 static void
746 handle_icmp_back (void *cls,
747                   const struct GNUNET_EXIT_IcmpToVPNMessage *i2v)
748 {
749   struct ChannelState *ts = cls;
750   size_t mlen;
751
752   GNUNET_STATISTICS_update (stats,
753                             gettext_noop ("# ICMP packets received from cadet"),
754                             1,
755                             GNUNET_NO);
756   mlen = ntohs (i2v->header.size) - sizeof (struct GNUNET_EXIT_IcmpToVPNMessage);
757   {
758     char sbuf[INET6_ADDRSTRLEN];
759     char dbuf[INET6_ADDRSTRLEN];
760
761     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
762                 "Received ICMP packet from cadet, sending %u bytes from %s -> %s via TUN\n",
763                 (unsigned int) mlen,
764                 inet_ntop (ts->af, &ts->destination_ip, sbuf, sizeof (sbuf)),
765                 inet_ntop (ts->af, &ts->source_ip, dbuf, sizeof (dbuf)));
766   }
767   switch (ts->af)
768   {
769   case AF_INET:
770     {
771       size_t size = sizeof (struct GNUNET_TUN_IPv4Header)
772         + sizeof (struct GNUNET_TUN_IcmpHeader)
773         + sizeof (struct GNUNET_MessageHeader) +
774         sizeof (struct GNUNET_TUN_Layer2PacketHeader) +
775         mlen;
776       {
777         /* reserve some extra space in case we have an ICMP type here where
778            we will need to make up the payload ourselves */
779         char buf[size + sizeof (struct GNUNET_TUN_IPv4Header) + 8] GNUNET_ALIGN;
780         struct GNUNET_MessageHeader *msg = (struct GNUNET_MessageHeader *) buf;
781         struct GNUNET_TUN_Layer2PacketHeader *tun = (struct GNUNET_TUN_Layer2PacketHeader*) &msg[1];
782         struct GNUNET_TUN_IPv4Header *ipv4 = (struct GNUNET_TUN_IPv4Header *) &tun[1];
783         struct GNUNET_TUN_IcmpHeader *icmp = (struct GNUNET_TUN_IcmpHeader *) &ipv4[1];
784         msg->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
785         tun->flags = htons (0);
786         tun->proto = htons (ETH_P_IPV4);
787         GNUNET_TUN_initialize_ipv4_header (ipv4,
788                                            IPPROTO_ICMP,
789                                            sizeof (struct GNUNET_TUN_IcmpHeader) + mlen,
790                                            &ts->destination_ip.v4,
791                                            &ts->source_ip.v4);
792         *icmp = i2v->icmp_header;
793         GNUNET_memcpy (&icmp[1],
794                        &i2v[1],
795                        mlen);
796         /* For some ICMP types, we need to adjust (make up) the payload here.
797            Also, depending on the AF used on the other side, we have to
798            do ICMP PT (translate ICMP types) */
799         switch (ntohl (i2v->af))
800         {
801         case AF_INET:
802           switch (icmp->type)
803           {
804           case GNUNET_TUN_ICMPTYPE_ECHO_REPLY:
805           case GNUNET_TUN_ICMPTYPE_ECHO_REQUEST:
806             break;
807           case GNUNET_TUN_ICMPTYPE_DESTINATION_UNREACHABLE:
808           case GNUNET_TUN_ICMPTYPE_SOURCE_QUENCH:
809           case GNUNET_TUN_ICMPTYPE_TIME_EXCEEDED:
810             {
811               struct GNUNET_TUN_IPv4Header *ipp = (struct GNUNET_TUN_IPv4Header *) &icmp[1];
812               struct GNUNET_TUN_UdpHeader *udp = (struct GNUNET_TUN_UdpHeader *) &ipp[1];
813
814               if (mlen != 0)
815                 {
816                   /* sender did not strip ICMP payload? */
817                   GNUNET_break_op (0);
818                   return;
819                 }
820               size += sizeof (struct GNUNET_TUN_IPv4Header) + 8;
821               GNUNET_assert (8 == sizeof (struct GNUNET_TUN_UdpHeader));
822               make_up_icmpv4_payload (ts, ipp, udp);
823             }
824             break;
825           default:
826             GNUNET_break_op (0);
827             GNUNET_STATISTICS_update (stats,
828                                       gettext_noop ("# ICMPv4 packets dropped (type not allowed)"),
829                                       1, GNUNET_NO);
830             return;
831           }
832           /* end AF_INET */
833           break;
834         case AF_INET6:
835           /* ICMP PT 6-to-4 and possibly making up payloads */
836           switch (icmp->type)
837           {
838           case GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE:
839             icmp->type = GNUNET_TUN_ICMPTYPE_DESTINATION_UNREACHABLE;
840             {
841               struct GNUNET_TUN_IPv4Header *ipp = (struct GNUNET_TUN_IPv4Header *) &icmp[1];
842               struct GNUNET_TUN_UdpHeader *udp = (struct GNUNET_TUN_UdpHeader *) &ipp[1];
843
844               if (mlen != 0)
845                 {
846                   /* sender did not strip ICMP payload? */
847                   GNUNET_break_op (0);
848                   return;
849                 }
850               size += sizeof (struct GNUNET_TUN_IPv4Header) + 8;
851               GNUNET_assert (8 == sizeof (struct GNUNET_TUN_UdpHeader));
852               make_up_icmpv4_payload (ts, ipp, udp);
853             }
854             break;
855           case GNUNET_TUN_ICMPTYPE6_TIME_EXCEEDED:
856             icmp->type = GNUNET_TUN_ICMPTYPE_TIME_EXCEEDED;
857             {
858               struct GNUNET_TUN_IPv4Header *ipp = (struct GNUNET_TUN_IPv4Header *) &icmp[1];
859               struct GNUNET_TUN_UdpHeader *udp = (struct GNUNET_TUN_UdpHeader *) &ipp[1];
860
861               if (mlen != 0)
862                 {
863                   /* sender did not strip ICMP payload? */
864                   GNUNET_break_op (0);
865                   return;
866                 }
867               size += sizeof (struct GNUNET_TUN_IPv4Header) + 8;
868               GNUNET_assert (8 == sizeof (struct GNUNET_TUN_UdpHeader));
869               make_up_icmpv4_payload (ts, ipp, udp);
870             }
871             break;
872           case GNUNET_TUN_ICMPTYPE6_PACKET_TOO_BIG:
873           case GNUNET_TUN_ICMPTYPE6_PARAMETER_PROBLEM:
874             GNUNET_STATISTICS_update (stats,
875                                       gettext_noop ("# ICMPv6 packets dropped (impossible PT to v4)"),
876                                       1, GNUNET_NO);
877             return;
878           case GNUNET_TUN_ICMPTYPE6_ECHO_REQUEST:
879             icmp->type = GNUNET_TUN_ICMPTYPE_ECHO_REQUEST;
880             break;
881           case GNUNET_TUN_ICMPTYPE6_ECHO_REPLY:
882             icmp->type = GNUNET_TUN_ICMPTYPE_ECHO_REPLY;
883             break;
884           default:
885             GNUNET_break_op (0);
886             GNUNET_STATISTICS_update (stats,
887                                       gettext_noop ("# ICMPv6 packets dropped (type not allowed)"),
888                                       1, GNUNET_NO);
889             return;
890           }
891           /* end AF_INET6 */
892           break;
893         default:
894           GNUNET_break_op (0);
895           return;
896         }
897         msg->size = htons (size);
898         GNUNET_TUN_calculate_icmp_checksum (icmp,
899                                             &i2v[1],
900                                             mlen);
901         (void) GNUNET_HELPER_send (helper_handle,
902                                    msg,
903                                    GNUNET_YES,
904                                    NULL, NULL);
905       }
906     }
907     break;
908   case AF_INET6:
909     {
910       size_t size = sizeof (struct GNUNET_TUN_IPv6Header)
911         + sizeof (struct GNUNET_TUN_IcmpHeader)
912         + sizeof (struct GNUNET_MessageHeader) +
913         sizeof (struct GNUNET_TUN_Layer2PacketHeader) +
914         mlen;
915       {
916         char buf[size + sizeof (struct GNUNET_TUN_IPv6Header) + 8] GNUNET_ALIGN;
917         struct GNUNET_MessageHeader *msg = (struct GNUNET_MessageHeader *) buf;
918         struct GNUNET_TUN_Layer2PacketHeader *tun = (struct GNUNET_TUN_Layer2PacketHeader*) &msg[1];
919         struct GNUNET_TUN_IPv6Header *ipv6 = (struct GNUNET_TUN_IPv6Header *) &tun[1];
920         struct GNUNET_TUN_IcmpHeader *icmp = (struct GNUNET_TUN_IcmpHeader *) &ipv6[1];
921         msg->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
922         tun->flags = htons (0);
923         tun->proto = htons (ETH_P_IPV6);
924         GNUNET_TUN_initialize_ipv6_header (ipv6,
925                                            IPPROTO_ICMPV6,
926                                            sizeof (struct GNUNET_TUN_IcmpHeader) + mlen,
927                                            &ts->destination_ip.v6,
928                                            &ts->source_ip.v6);
929         *icmp = i2v->icmp_header;
930         GNUNET_memcpy (&icmp[1],
931                 &i2v[1],
932                 mlen);
933
934         /* For some ICMP types, we need to adjust (make up) the payload here.
935            Also, depending on the AF used on the other side, we have to
936            do ICMP PT (translate ICMP types) */
937         switch (ntohl (i2v->af))
938         {
939         case AF_INET:
940           /* ICMP PT 4-to-6 and possibly making up payloads */
941           switch (icmp->type)
942           {
943           case GNUNET_TUN_ICMPTYPE_ECHO_REPLY:
944             icmp->type = GNUNET_TUN_ICMPTYPE6_ECHO_REPLY;
945             break;
946           case GNUNET_TUN_ICMPTYPE_ECHO_REQUEST:
947             icmp->type = GNUNET_TUN_ICMPTYPE6_ECHO_REQUEST;
948             break;
949           case GNUNET_TUN_ICMPTYPE_DESTINATION_UNREACHABLE:
950             icmp->type = GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE;
951             {
952               struct GNUNET_TUN_IPv6Header *ipp = (struct GNUNET_TUN_IPv6Header *) &icmp[1];
953               struct GNUNET_TUN_UdpHeader *udp = (struct GNUNET_TUN_UdpHeader *) &ipp[1];
954
955               if (mlen != 0)
956                 {
957                   /* sender did not strip ICMP payload? */
958                   GNUNET_break_op (0);
959                   return;
960                 }
961               size += sizeof (struct GNUNET_TUN_IPv6Header) + 8;
962               GNUNET_assert (8 == sizeof (struct GNUNET_TUN_UdpHeader));
963               make_up_icmpv6_payload (ts, ipp, udp);
964             }
965             break;
966           case GNUNET_TUN_ICMPTYPE_TIME_EXCEEDED:
967             icmp->type = GNUNET_TUN_ICMPTYPE6_TIME_EXCEEDED;
968             {
969               struct GNUNET_TUN_IPv6Header *ipp = (struct GNUNET_TUN_IPv6Header *) &icmp[1];
970               struct GNUNET_TUN_UdpHeader *udp = (struct GNUNET_TUN_UdpHeader *) &ipp[1];
971
972               if (mlen != 0)
973                 {
974                   /* sender did not strip ICMP payload? */
975                   GNUNET_break_op (0);
976                   return;
977                 }
978               size += sizeof (struct GNUNET_TUN_IPv6Header) + 8;
979               GNUNET_assert (8 == sizeof (struct GNUNET_TUN_UdpHeader));
980               make_up_icmpv6_payload (ts, ipp, udp);
981             }
982             break;
983           case GNUNET_TUN_ICMPTYPE_SOURCE_QUENCH:
984             GNUNET_STATISTICS_update (stats,
985                                       gettext_noop ("# ICMPv4 packets dropped (impossible PT to v6)"),
986                                       1, GNUNET_NO);
987             return;
988           default:
989             GNUNET_break_op (0);
990             GNUNET_STATISTICS_update (stats,
991                                       gettext_noop ("# ICMPv4 packets dropped (type not allowed)"),
992                                       1, GNUNET_NO);
993             return;
994           }
995           /* end AF_INET */
996           break;
997         case AF_INET6:
998           switch (icmp->type)
999           {
1000           case GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE:
1001           case GNUNET_TUN_ICMPTYPE6_TIME_EXCEEDED:
1002           case GNUNET_TUN_ICMPTYPE6_PACKET_TOO_BIG:
1003           case GNUNET_TUN_ICMPTYPE6_PARAMETER_PROBLEM:
1004             {
1005               struct GNUNET_TUN_IPv6Header *ipp = (struct GNUNET_TUN_IPv6Header *) &icmp[1];
1006               struct GNUNET_TUN_UdpHeader *udp = (struct GNUNET_TUN_UdpHeader *) &ipp[1];
1007
1008               if (mlen != 0)
1009                 {
1010                   /* sender did not strip ICMP payload? */
1011                   GNUNET_break_op (0);
1012                   return;
1013                 }
1014               size += sizeof (struct GNUNET_TUN_IPv6Header) + 8;
1015               GNUNET_assert (8 == sizeof (struct GNUNET_TUN_UdpHeader));
1016               make_up_icmpv6_payload (ts, ipp, udp);
1017             }
1018             break;
1019           case GNUNET_TUN_ICMPTYPE6_ECHO_REQUEST:
1020             break;
1021           default:
1022             GNUNET_break_op (0);
1023             GNUNET_STATISTICS_update (stats,
1024                                       gettext_noop ("# ICMPv6 packets dropped (type not allowed)"),
1025                                       1, GNUNET_NO);
1026             return;
1027           }
1028           /* end AF_INET6 */
1029           break;
1030         default:
1031           GNUNET_break_op (0);
1032           return;
1033         }
1034         msg->size = htons (size);
1035         GNUNET_TUN_calculate_icmp_checksum (icmp,
1036                                             &i2v[1], mlen);
1037         (void) GNUNET_HELPER_send (helper_handle,
1038                                    msg,
1039                                    GNUNET_YES,
1040                                    NULL, NULL);
1041       }
1042     }
1043     break;
1044   default:
1045     GNUNET_assert (0);
1046   }
1047   GNUNET_CONTAINER_heap_update_cost (ts->heap_node,
1048                                      GNUNET_TIME_absolute_get ().abs_value_us);
1049   GNUNET_CADET_receive_done (ts->channel);
1050 }
1051
1052
1053 /**
1054  * We got a UDP packet back from the CADET channel.  Check that it is OK.
1055  *
1056  * @param cls our `struct ChannelState *`
1057  * @param reply the actual message
1058  * @return #GNUNET_OK to keep the connection open,
1059  *         #GNUNET_SYSERR to close it (signal serious error)
1060  */
1061 static int
1062 check_udp_back (void *cls,
1063                   const struct GNUNET_EXIT_UdpReplyMessage *reply)
1064 {
1065   struct ChannelState *ts = cls;
1066
1067   if (NULL == ts->heap_node)
1068   {
1069     GNUNET_break_op (0);
1070     return GNUNET_SYSERR;
1071   }
1072   if (AF_UNSPEC == ts->af)
1073   {
1074     GNUNET_break_op (0);
1075     return GNUNET_SYSERR;
1076   }
1077   return GNUNET_OK;
1078 }
1079
1080
1081 /**
1082  * We got a UDP packet back from the CADET channel.  Pass it on to the
1083  * local virtual interface via the helper.
1084  *
1085  * @param cls our `struct ChannelState *`
1086  * @param reply the actual message
1087  */
1088 static void
1089 handle_udp_back (void *cls,
1090                  const struct GNUNET_EXIT_UdpReplyMessage *reply)
1091 {
1092   struct ChannelState *ts = cls;
1093   size_t mlen;
1094
1095   GNUNET_STATISTICS_update (stats,
1096                             gettext_noop ("# UDP packets received from cadet"),
1097                             1,
1098                             GNUNET_NO);
1099   mlen = ntohs (reply->header.size) - sizeof (struct GNUNET_EXIT_UdpReplyMessage);
1100   {
1101     char sbuf[INET6_ADDRSTRLEN];
1102     char dbuf[INET6_ADDRSTRLEN];
1103
1104     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1105                 "Received UDP reply from cadet, sending %u bytes from [%s]:%u -> [%s]:%u via TUN\n",
1106                 (unsigned int) mlen,
1107                 inet_ntop (ts->af, &ts->destination_ip, sbuf, sizeof (sbuf)),
1108                 ts->destination_port,
1109                 inet_ntop (ts->af, &ts->source_ip, dbuf, sizeof (dbuf)),
1110                 ts->source_port);
1111   }
1112   switch (ts->af)
1113   {
1114   case AF_INET:
1115     {
1116       size_t size = sizeof (struct GNUNET_TUN_IPv4Header)
1117         + sizeof (struct GNUNET_TUN_UdpHeader)
1118         + sizeof (struct GNUNET_MessageHeader) +
1119         sizeof (struct GNUNET_TUN_Layer2PacketHeader) +
1120         mlen;
1121       {
1122         char buf[size] GNUNET_ALIGN;
1123         struct GNUNET_MessageHeader *msg = (struct GNUNET_MessageHeader *) buf;
1124         struct GNUNET_TUN_Layer2PacketHeader *tun = (struct GNUNET_TUN_Layer2PacketHeader*) &msg[1];
1125         struct GNUNET_TUN_IPv4Header *ipv4 = (struct GNUNET_TUN_IPv4Header *) &tun[1];
1126         struct GNUNET_TUN_UdpHeader *udp = (struct GNUNET_TUN_UdpHeader *) &ipv4[1];
1127         msg->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
1128         msg->size = htons (size);
1129         tun->flags = htons (0);
1130         tun->proto = htons (ETH_P_IPV4);
1131         GNUNET_TUN_initialize_ipv4_header (ipv4,
1132                                            IPPROTO_UDP,
1133                                            sizeof (struct GNUNET_TUN_UdpHeader) + mlen,
1134                                            &ts->destination_ip.v4,
1135                                            &ts->source_ip.v4);
1136         if (0 == ntohs (reply->source_port))
1137           udp->source_port = htons (ts->destination_port);
1138         else
1139           udp->source_port = reply->source_port;
1140         if (0 == ntohs (reply->destination_port))
1141           udp->destination_port = htons (ts->source_port);
1142         else
1143           udp->destination_port = reply->destination_port;
1144         udp->len = htons (mlen + sizeof (struct GNUNET_TUN_UdpHeader));
1145         GNUNET_TUN_calculate_udp4_checksum (ipv4,
1146                                             udp,
1147                                             &reply[1],
1148                                             mlen);
1149         GNUNET_memcpy (&udp[1],
1150                 &reply[1],
1151                 mlen);
1152         (void) GNUNET_HELPER_send (helper_handle,
1153                                    msg,
1154                                    GNUNET_YES,
1155                                    NULL, NULL);
1156       }
1157     }
1158     break;
1159   case AF_INET6:
1160     {
1161       size_t size = sizeof (struct GNUNET_TUN_IPv6Header)
1162         + sizeof (struct GNUNET_TUN_UdpHeader)
1163         + sizeof (struct GNUNET_MessageHeader) +
1164         sizeof (struct GNUNET_TUN_Layer2PacketHeader) +
1165         mlen;
1166       {
1167         char buf[size] GNUNET_ALIGN;
1168         struct GNUNET_MessageHeader *msg = (struct GNUNET_MessageHeader *) buf;
1169         struct GNUNET_TUN_Layer2PacketHeader *tun = (struct GNUNET_TUN_Layer2PacketHeader*) &msg[1];
1170         struct GNUNET_TUN_IPv6Header *ipv6 = (struct GNUNET_TUN_IPv6Header *) &tun[1];
1171         struct GNUNET_TUN_UdpHeader *udp = (struct GNUNET_TUN_UdpHeader *) &ipv6[1];
1172         msg->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
1173         msg->size = htons (size);
1174         tun->flags = htons (0);
1175         tun->proto = htons (ETH_P_IPV6);
1176         GNUNET_TUN_initialize_ipv6_header (ipv6,
1177                                            IPPROTO_UDP,
1178                                            sizeof (struct GNUNET_TUN_UdpHeader) + mlen,
1179                                            &ts->destination_ip.v6,
1180                                            &ts->source_ip.v6);
1181         if (0 == ntohs (reply->source_port))
1182           udp->source_port = htons (ts->destination_port);
1183         else
1184           udp->source_port = reply->source_port;
1185         if (0 == ntohs (reply->destination_port))
1186           udp->destination_port = htons (ts->source_port);
1187         else
1188           udp->destination_port = reply->destination_port;
1189         udp->len = htons (mlen + sizeof (struct GNUNET_TUN_UdpHeader));
1190         GNUNET_TUN_calculate_udp6_checksum (ipv6,
1191                                             udp,
1192                                             &reply[1], mlen);
1193         GNUNET_memcpy (&udp[1],
1194                 &reply[1],
1195                 mlen);
1196         (void) GNUNET_HELPER_send (helper_handle,
1197                                    msg,
1198                                    GNUNET_YES,
1199                                    NULL, NULL);
1200       }
1201     }
1202     break;
1203   default:
1204     GNUNET_assert (0);
1205   }
1206   GNUNET_CONTAINER_heap_update_cost (ts->heap_node,
1207                                      GNUNET_TIME_absolute_get ().abs_value_us);
1208   GNUNET_CADET_receive_done (ts->channel);
1209 }
1210
1211
1212 /**
1213  * We got a TCP packet back from the CADET channel.  Check it is OK.
1214  *
1215  * @param cls our `struct ChannelState *`
1216  * @param data the actual message
1217  * @return #GNUNET_OK to keep the connection open,
1218  *         #GNUNET_SYSERR to close it (signal serious error)
1219  */
1220 static int
1221 check_tcp_back (void *cls,
1222                   const struct GNUNET_EXIT_TcpDataMessage *data)
1223 {
1224   struct ChannelState *ts = cls;
1225
1226   if (NULL == ts->heap_node)
1227   {
1228     GNUNET_break_op (0);
1229     return GNUNET_SYSERR;
1230   }
1231   if (data->tcp_header.off * 4 < sizeof (struct GNUNET_TUN_TcpHeader))
1232   {
1233     GNUNET_break_op (0);
1234     return GNUNET_SYSERR;
1235   }
1236   return GNUNET_OK;
1237 }
1238
1239
1240 /**
1241  * We got a TCP packet back from the CADET channel.  Pass it on to the
1242  * local virtual interface via the helper.
1243  *
1244  * @param cls our `struct ChannelState *`
1245  * @param data the actual message
1246  */
1247 static void
1248 handle_tcp_back (void *cls,
1249                  const struct GNUNET_EXIT_TcpDataMessage *data)
1250 {
1251   struct ChannelState *ts = cls;
1252   size_t mlen;
1253
1254   GNUNET_STATISTICS_update (stats,
1255                             gettext_noop ("# TCP packets received from cadet"),
1256                             1,
1257                             GNUNET_NO);
1258   mlen = ntohs (data->header.size) - sizeof (struct GNUNET_EXIT_TcpDataMessage);
1259   {
1260     char sbuf[INET6_ADDRSTRLEN];
1261     char dbuf[INET6_ADDRSTRLEN];
1262
1263     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1264                 "Received TCP reply from cadet, sending %u bytes from [%s]:%u -> [%s]:%u via TUN\n",
1265                 (unsigned int) mlen,
1266                 inet_ntop (ts->af, &ts->destination_ip, sbuf, sizeof (sbuf)),
1267                 ts->destination_port,
1268                 inet_ntop (ts->af, &ts->source_ip, dbuf, sizeof (dbuf)),
1269                 ts->source_port);
1270   }
1271   switch (ts->af)
1272   {
1273   case AF_INET:
1274     {
1275       size_t size = sizeof (struct GNUNET_TUN_IPv4Header)
1276         + sizeof (struct GNUNET_TUN_TcpHeader)
1277         + sizeof (struct GNUNET_MessageHeader) +
1278         sizeof (struct GNUNET_TUN_Layer2PacketHeader) +
1279         mlen;
1280       {
1281         char buf[size] GNUNET_ALIGN;
1282         struct GNUNET_MessageHeader *msg = (struct GNUNET_MessageHeader *) buf;
1283         struct GNUNET_TUN_Layer2PacketHeader *tun = (struct GNUNET_TUN_Layer2PacketHeader*) &msg[1];
1284         struct GNUNET_TUN_IPv4Header *ipv4 = (struct GNUNET_TUN_IPv4Header *) &tun[1];
1285         struct GNUNET_TUN_TcpHeader *tcp = (struct GNUNET_TUN_TcpHeader *) &ipv4[1];
1286         msg->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
1287         msg->size = htons (size);
1288         tun->flags = htons (0);
1289         tun->proto = htons (ETH_P_IPV4);
1290         GNUNET_TUN_initialize_ipv4_header (ipv4,
1291                                            IPPROTO_TCP,
1292                                            sizeof (struct GNUNET_TUN_TcpHeader) + mlen,
1293                                            &ts->destination_ip.v4,
1294                                            &ts->source_ip.v4);
1295         *tcp = data->tcp_header;
1296         tcp->source_port = htons (ts->destination_port);
1297         tcp->destination_port = htons (ts->source_port);
1298         GNUNET_TUN_calculate_tcp4_checksum (ipv4,
1299                                             tcp,
1300                                             &data[1],
1301                                             mlen);
1302         GNUNET_memcpy (&tcp[1],
1303                        &data[1],
1304                        mlen);
1305         (void) GNUNET_HELPER_send (helper_handle,
1306                                    msg,
1307                                    GNUNET_YES,
1308                                    NULL, NULL);
1309       }
1310     }
1311     break;
1312   case AF_INET6:
1313     {
1314       size_t size = sizeof (struct GNUNET_TUN_IPv6Header)
1315         + sizeof (struct GNUNET_TUN_TcpHeader)
1316         + sizeof (struct GNUNET_MessageHeader) +
1317         sizeof (struct GNUNET_TUN_Layer2PacketHeader) +
1318         mlen;
1319       {
1320         char buf[size] GNUNET_ALIGN;
1321         struct GNUNET_MessageHeader *msg = (struct GNUNET_MessageHeader *) buf;
1322         struct GNUNET_TUN_Layer2PacketHeader *tun = (struct GNUNET_TUN_Layer2PacketHeader*) &msg[1];
1323         struct GNUNET_TUN_IPv6Header *ipv6 = (struct GNUNET_TUN_IPv6Header *) &tun[1];
1324         struct GNUNET_TUN_TcpHeader *tcp = (struct GNUNET_TUN_TcpHeader *) &ipv6[1];
1325         msg->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
1326         msg->size = htons (size);
1327         tun->flags = htons (0);
1328         tun->proto = htons (ETH_P_IPV6);
1329         GNUNET_TUN_initialize_ipv6_header (ipv6,
1330                                            IPPROTO_TCP,
1331                                            sizeof (struct GNUNET_TUN_TcpHeader) + mlen,
1332                                            &ts->destination_ip.v6,
1333                                            &ts->source_ip.v6);
1334         *tcp = data->tcp_header;
1335         tcp->source_port = htons (ts->destination_port);
1336         tcp->destination_port = htons (ts->source_port);
1337         GNUNET_TUN_calculate_tcp6_checksum (ipv6,
1338                                             tcp,
1339                                             &data[1],
1340                                             mlen);
1341         GNUNET_memcpy (&tcp[1],
1342                        &data[1],
1343                        mlen);
1344         (void) GNUNET_HELPER_send (helper_handle,
1345                                    msg,
1346                                    GNUNET_YES,
1347                                    NULL, NULL);
1348       }
1349     }
1350     break;
1351   }
1352   GNUNET_CONTAINER_heap_update_cost (ts->heap_node,
1353                                      GNUNET_TIME_absolute_get ().abs_value_us);
1354   GNUNET_CADET_receive_done (ts->channel);
1355 }
1356
1357
1358 /**
1359  * Create a channel for @a ts to @a target at @a port
1360  *
1361  * @param ts channel state to create the channel for
1362  * @param target peer to connect to
1363  * @param port destination port
1364  * @return the channel handle
1365  */
1366 static struct GNUNET_CADET_Channel *
1367 create_channel (struct ChannelState *ts,
1368                 const struct GNUNET_PeerIdentity *target,
1369                 const struct GNUNET_HashCode *port)
1370 {
1371   struct GNUNET_MQ_MessageHandler cadet_handlers[] = {
1372     GNUNET_MQ_hd_var_size (udp_back,
1373                            GNUNET_MESSAGE_TYPE_VPN_UDP_REPLY,
1374                            struct GNUNET_EXIT_UdpReplyMessage,
1375                            ts),
1376     GNUNET_MQ_hd_var_size (tcp_back,
1377                            GNUNET_MESSAGE_TYPE_VPN_TCP_DATA_TO_VPN,
1378                            struct GNUNET_EXIT_TcpDataMessage,
1379                            ts),
1380     GNUNET_MQ_hd_var_size (icmp_back,
1381                            GNUNET_MESSAGE_TYPE_VPN_ICMP_TO_VPN,
1382                            struct GNUNET_EXIT_IcmpToVPNMessage,
1383                            ts),
1384     GNUNET_MQ_handler_end()
1385   };
1386
1387   return GNUNET_CADET_channel_creatE (cadet_handle,
1388                                       ts,
1389                                       target,
1390                                       port,
1391                                       GNUNET_CADET_OPTION_DEFAULT,
1392                                       NULL,
1393                                       &channel_cleaner,
1394                                       cadet_handlers);
1395 }
1396
1397
1398 /**
1399  * Regex has found a potential exit peer for us; consider using it.
1400  *
1401  * @param cls the `struct ChannelState`
1402  * @param id Peer providing a regex that matches the string.
1403  * @param get_path Path of the get request.
1404  * @param get_path_length Lenght of @a get_path.
1405  * @param put_path Path of the put request.
1406  * @param put_path_length Length of the @a put_path.
1407  */
1408 static void
1409 handle_regex_result (void *cls,
1410                      const struct GNUNET_PeerIdentity *id,
1411                      const struct GNUNET_PeerIdentity *get_path,
1412                      unsigned int get_path_length,
1413                      const struct GNUNET_PeerIdentity *put_path,
1414                      unsigned int put_path_length)
1415 {
1416   struct ChannelState *ts = cls;
1417   struct GNUNET_HashCode port;
1418
1419   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1420               "Exit %s found for destination %s!\n",
1421               GNUNET_i2s (id),
1422               print_channel_destination (&ts->destination));
1423   GNUNET_REGEX_search_cancel (ts->search);
1424   ts->search = NULL;
1425   switch (ts->af)
1426   {
1427   case AF_INET:
1428     /* these must match the strings used in gnunet-daemon-exit */
1429     GNUNET_CRYPTO_hash (GNUNET_APPLICATION_PORT_IPV4_GATEWAY,
1430                         strlen (GNUNET_APPLICATION_PORT_IPV4_GATEWAY),
1431                         &port);
1432     break;
1433   case AF_INET6:
1434     /* these must match the strings used in gnunet-daemon-exit */
1435     GNUNET_CRYPTO_hash (GNUNET_APPLICATION_PORT_IPV6_GATEWAY,
1436                         strlen (GNUNET_APPLICATION_PORT_IPV6_GATEWAY),
1437                         &port);
1438     break;
1439   default:
1440     GNUNET_break (0);
1441     return;
1442   }
1443   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1444               "Creating tunnel to %s for destination %s!\n",
1445               GNUNET_i2s (id),
1446               print_channel_destination (&ts->destination));
1447   ts->channel = create_channel (ts,
1448                                 id,
1449                                 &port);
1450 }
1451
1452
1453 /**
1454  * Initialize the given destination entry's cadet channel.
1455  *
1456  * @param dt destination channel for which we need to setup a channel
1457  * @param client_af address family of the address returned to the client
1458  * @return channel state of the channel that was created
1459  */
1460 static struct ChannelState *
1461 create_channel_to_destination (struct DestinationChannel *dt,
1462                                int client_af)
1463 {
1464   struct ChannelState *ts;
1465
1466   GNUNET_STATISTICS_update (stats,
1467                             gettext_noop ("# Cadet channels created"),
1468                             1,
1469                             GNUNET_NO);
1470   ts = GNUNET_new (struct ChannelState);
1471   ts->af = client_af;
1472   ts->destination = *dt->destination;
1473   ts->destination.heap_node = NULL; /* copy is NOT in destination heap */
1474   ts->destination_port = dt->destination_port;
1475   if (dt->destination->is_service)
1476   {
1477     struct GNUNET_HashCode cadet_port;
1478
1479     GNUNET_TUN_compute_service_cadet_port (&ts->destination.details.service_destination.service_descriptor,
1480                                            ts->destination_port,
1481                                            &cadet_port);
1482     ts->channel = create_channel (ts,
1483                                   &dt->destination->details.service_destination.target,
1484                                   &cadet_port);
1485
1486     if (NULL == ts->channel)
1487     {
1488       GNUNET_break (0);
1489       GNUNET_free (ts);
1490       return NULL;
1491     }
1492     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1493                 "Creating channel to peer %s offering service %s on port %u\n",
1494                 GNUNET_i2s (&dt->destination->details.service_destination.target),
1495                 GNUNET_h2s (&ts->destination.details.service_destination.service_descriptor),
1496                 (unsigned int) ts->destination_port);
1497   }
1498   else
1499   {
1500     char *policy;
1501
1502     switch (dt->destination->details.exit_destination.af)
1503     {
1504     case AF_INET:
1505     {
1506       char address[GNUNET_TUN_IPV4_REGEXLEN];
1507
1508       GNUNET_TUN_ipv4toregexsearch (&dt->destination->details.exit_destination.ip.v4,
1509                                     dt->destination_port,
1510                                     address);
1511       GNUNET_asprintf (&policy,
1512                        "%s%s",
1513                        GNUNET_APPLICATION_TYPE_EXIT_REGEX_PREFIX,
1514                        address);
1515       break;
1516     }
1517     case AF_INET6:
1518     {
1519       char address[GNUNET_TUN_IPV6_REGEXLEN];
1520
1521       GNUNET_TUN_ipv6toregexsearch (&dt->destination->details.exit_destination.ip.v6,
1522                                     dt->destination_port,
1523                                     address);
1524       GNUNET_asprintf (&policy,
1525                        "%s%s",
1526                        GNUNET_APPLICATION_TYPE_EXIT_REGEX_PREFIX,
1527                        address);
1528       break;
1529     }
1530     default:
1531       GNUNET_assert (0);
1532       break;
1533     }
1534
1535     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1536                 "Requesting connect by string: %s\n",
1537                 policy);
1538     ts->search = GNUNET_REGEX_search (cfg,
1539                                       policy,
1540                                       &handle_regex_result,
1541                                       ts);
1542     GNUNET_free (policy);
1543   }
1544   return ts;
1545 }
1546
1547
1548 /**
1549  * We have too many active channels.  Clean up the oldest channel.
1550  *
1551  * @param except channel that must NOT be cleaned up, even if it is the oldest
1552  */
1553 static void
1554 expire_channel (struct ChannelState *except)
1555 {
1556   struct ChannelState *ts;
1557
1558   ts = GNUNET_CONTAINER_heap_peek (channel_heap);
1559   GNUNET_assert (NULL != ts);
1560   if (except == ts)
1561     return; /* can't do this */
1562   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1563               "Tearing down expired channel to %s\n",
1564               print_channel_destination (&except->destination));
1565   free_channel_state (ts);
1566 }
1567
1568
1569 /**
1570  * Route a packet via cadet to the given destination.
1571  *
1572  * @param destination description of the destination
1573  * @param af address family on this end (AF_INET or AF_INET6)
1574  * @param protocol IPPROTO_TCP or IPPROTO_UDP or IPPROTO_ICMP or IPPROTO_ICMPV6
1575  * @param source_ip source IP used by the sender (struct in_addr or struct in6_addr)
1576  * @param destination_ip destination IP used by the sender (struct in_addr or struct in6_addr)
1577  * @param payload payload of the packet after the IP header
1578  * @param payload_length number of bytes in @a payload
1579  */
1580 static void
1581 route_packet (struct DestinationEntry *destination,
1582               int af,
1583               uint8_t protocol,
1584               const void *source_ip,
1585               const void *destination_ip,
1586               const void *payload,
1587               size_t payload_length)
1588 {
1589   struct GNUNET_HashCode key;
1590   struct ChannelState *ts;
1591   size_t alen;
1592   size_t mlen;
1593   struct GNUNET_MQ_Envelope *env;
1594   const struct GNUNET_TUN_UdpHeader *udp;
1595   const struct GNUNET_TUN_TcpHeader *tcp;
1596   const struct GNUNET_TUN_IcmpHeader *icmp;
1597   struct DestinationChannel *dt;
1598   uint16_t source_port;
1599   uint16_t destination_port;
1600
1601   switch (protocol)
1602   {
1603   case IPPROTO_UDP:
1604     {
1605       if (payload_length < sizeof (struct GNUNET_TUN_UdpHeader))
1606       {
1607         /* blame kernel? */
1608         GNUNET_break (0);
1609         return;
1610       }
1611       tcp = NULL; /* make compiler happy */
1612       icmp = NULL;  /* make compiler happy */
1613       udp = payload;
1614       if (udp->len < sizeof (struct GNUNET_TUN_UdpHeader))
1615       {
1616         GNUNET_break_op (0);
1617         return;
1618       }
1619       source_port = ntohs (udp->source_port);
1620       destination_port = ntohs (udp->destination_port);
1621       get_channel_key_from_ips (af,
1622                                 IPPROTO_UDP,
1623                                 source_ip,
1624                                 source_port,
1625                                 destination_ip,
1626                                 destination_port,
1627                                 &key);
1628     }
1629     break;
1630   case IPPROTO_TCP:
1631     {
1632       if (payload_length < sizeof (struct GNUNET_TUN_TcpHeader))
1633       {
1634         /* blame kernel? */
1635         GNUNET_break (0);
1636         return;
1637       }
1638       udp = NULL; /* make compiler happy */
1639       icmp = NULL;  /* make compiler happy */
1640       tcp = payload;
1641       if (tcp->off * 4 < sizeof (struct GNUNET_TUN_TcpHeader))
1642       {
1643         GNUNET_break_op (0);
1644         return;
1645       }
1646       source_port = ntohs (tcp->source_port);
1647       destination_port = ntohs (tcp->destination_port);
1648       get_channel_key_from_ips (af,
1649                                 IPPROTO_TCP,
1650                                 source_ip,
1651                                 source_port,
1652                                 destination_ip,
1653                                 destination_port,
1654                                 &key);
1655     }
1656     break;
1657   case IPPROTO_ICMP:
1658   case IPPROTO_ICMPV6:
1659     {
1660       if ( (AF_INET == af) ^ (protocol == IPPROTO_ICMP) )
1661       {
1662         GNUNET_break (0);
1663         return;
1664       }
1665       if (payload_length < sizeof (struct GNUNET_TUN_IcmpHeader))
1666       {
1667         /* blame kernel? */
1668         GNUNET_break (0);
1669         return;
1670       }
1671       tcp = NULL; /* make compiler happy */
1672       udp = NULL;  /* make compiler happy */
1673       icmp = payload;
1674       source_port = 0;
1675       destination_port = 0;
1676       get_channel_key_from_ips (af,
1677                                 protocol,
1678                                 source_ip,
1679                                 0,
1680                                 destination_ip,
1681                                 0,
1682                                 &key);
1683     }
1684     break;
1685   default:
1686     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1687                 _("Protocol %u not supported, dropping\n"),
1688                 (unsigned int) protocol);
1689     return;
1690   }
1691   alen = 0;
1692   if (! destination->is_service)
1693   {
1694     switch (destination->details.exit_destination.af)
1695     {
1696     case AF_INET:
1697       alen = sizeof (struct in_addr);
1698      break;
1699     case AF_INET6:
1700       alen = sizeof (struct in6_addr);
1701       break;
1702     default:
1703       GNUNET_assert (0);
1704     }
1705
1706     {
1707       char sbuf[INET6_ADDRSTRLEN];
1708       char dbuf[INET6_ADDRSTRLEN];
1709       char xbuf[INET6_ADDRSTRLEN];
1710
1711       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1712                   "Routing %s packet from [%s]:%u -> [%s]:%u to destination [%s]:%u\n",
1713                   (protocol == IPPROTO_TCP) ? "TCP" : "UDP",
1714                   inet_ntop (af,
1715                              source_ip,
1716                              sbuf,
1717                              sizeof (sbuf)),
1718                   source_port,
1719                   inet_ntop (af,
1720                              destination_ip,
1721                              dbuf,
1722                              sizeof (dbuf)),
1723                   destination_port,
1724                   inet_ntop (destination->details.exit_destination.af,
1725                              &destination->details.exit_destination.ip,
1726                              xbuf, sizeof (xbuf)),
1727                   destination_port);
1728     }
1729     for (dt = destination->dt_head; NULL != dt; dt = dt->next)
1730       if (dt->destination_port == destination_port)
1731         break;
1732   }
1733   else
1734   {
1735     {
1736       char sbuf[INET6_ADDRSTRLEN];
1737       char dbuf[INET6_ADDRSTRLEN];
1738
1739       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1740                   "Routing %s packet from [%s]:%u -> [%s]:%u to service %s at peer %s\n",
1741                   (protocol == IPPROTO_TCP) ? "TCP" : "UDP",
1742                   inet_ntop (af,
1743                              source_ip,
1744                              sbuf,
1745                              sizeof (sbuf)),
1746                   source_port,
1747                   inet_ntop (af,
1748                              destination_ip,
1749                              dbuf,
1750                              sizeof (dbuf)),
1751                   destination_port,
1752                   GNUNET_h2s (&destination->details.service_destination.service_descriptor),
1753                   GNUNET_i2s (&destination->details.service_destination.target));
1754     }
1755     for (dt = destination->dt_head; NULL != dt; dt = dt->next)
1756       if (dt->destination_port == destination_port)
1757         break;
1758   }
1759   if (NULL == dt)
1760   {
1761     dt = GNUNET_new (struct DestinationChannel);
1762     dt->destination = destination;
1763     GNUNET_CONTAINER_DLL_insert (destination->dt_head,
1764                                  destination->dt_tail,
1765                                  dt);
1766     dt->destination_port = destination_port;
1767   }
1768
1769   /* see if we have an existing channel for this destination */
1770   ts = GNUNET_CONTAINER_multihashmap_get (channel_map,
1771                                           &key);
1772   if (NULL == ts)
1773   {
1774     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1775                 "Creating new channel for key %s\n",
1776                 GNUNET_h2s (&key));
1777     /* need to either use the existing channel from the destination (if still
1778        available) or create a fresh one */
1779     ts = create_channel_to_destination (dt,
1780                                         af);
1781     if (NULL == ts)
1782       return;
1783     /* now bind existing "unbound" channel to our IP/port tuple */
1784     ts->protocol = protocol;
1785     ts->af = af;
1786     if (AF_INET == af)
1787     {
1788       ts->source_ip.v4 = * (const struct in_addr *) source_ip;
1789       ts->destination_ip.v4 = * (const struct in_addr *) destination_ip;
1790     }
1791     else
1792     {
1793       ts->source_ip.v6 = * (const struct in6_addr *) source_ip;
1794       ts->destination_ip.v6 = * (const struct in6_addr *) destination_ip;
1795     }
1796     ts->source_port = source_port;
1797     ts->destination_port = destination_port;
1798     ts->heap_node = GNUNET_CONTAINER_heap_insert (channel_heap,
1799                                                   ts,
1800                                                   GNUNET_TIME_absolute_get ().abs_value_us);
1801     GNUNET_assert (GNUNET_YES ==
1802                    GNUNET_CONTAINER_multihashmap_put (channel_map,
1803                                                       &key,
1804                                                       ts,
1805                                                       GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
1806     GNUNET_STATISTICS_update (stats,
1807                               gettext_noop ("# Active channels"),
1808                               1, GNUNET_NO);
1809     while (GNUNET_CONTAINER_multihashmap_size (channel_map) > max_channel_mappings)
1810       expire_channel (ts);
1811   }
1812   else
1813   {
1814     GNUNET_CONTAINER_heap_update_cost (ts->heap_node,
1815                                        GNUNET_TIME_absolute_get ().abs_value_us);
1816   }
1817   if (NULL == ts->channel)
1818   {
1819     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1820                 "Packet dropped, channel to %s not yet ready (%s)\n",
1821                 print_channel_destination (&ts->destination),
1822                 (NULL == ts->search)
1823                 ? "EXIT search failed"
1824                 : "EXIT search active");
1825     GNUNET_STATISTICS_update (stats,
1826                               gettext_noop ("# Packets dropped (channel not yet online)"),
1827                               1,
1828                               GNUNET_NO);
1829     return;
1830   }
1831
1832   /* send via channel */
1833   switch (protocol)
1834   {
1835   case IPPROTO_UDP:
1836     if (destination->is_service)
1837     {
1838       struct GNUNET_EXIT_UdpServiceMessage *usm;
1839
1840       mlen = sizeof (struct GNUNET_EXIT_UdpServiceMessage) +
1841         payload_length - sizeof (struct GNUNET_TUN_UdpHeader);
1842       if (mlen >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1843       {
1844         GNUNET_break (0);
1845         return;
1846       }
1847       env = GNUNET_MQ_msg_extra (usm,
1848                                  payload_length - sizeof (struct GNUNET_TUN_UdpHeader),
1849                                  GNUNET_MESSAGE_TYPE_VPN_UDP_TO_SERVICE);
1850       /* if the source port is below 32000, we assume it has a special
1851          meaning; if not, we pick a random port (this is a heuristic) */
1852       usm->source_port = (ntohs (udp->source_port) < 32000) ? udp->source_port : 0;
1853       usm->destination_port = udp->destination_port;
1854       GNUNET_memcpy (&usm[1],
1855                      &udp[1],
1856                      payload_length - sizeof (struct GNUNET_TUN_UdpHeader));
1857     }
1858     else
1859     {
1860       struct GNUNET_EXIT_UdpInternetMessage *uim;
1861       struct in_addr *ip4dst;
1862       struct in6_addr *ip6dst;
1863       void *payload;
1864
1865       mlen = sizeof (struct GNUNET_EXIT_UdpInternetMessage) +
1866         alen + payload_length - sizeof (struct GNUNET_TUN_UdpHeader);
1867       if (mlen >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1868       {
1869         GNUNET_break (0);
1870         return;
1871       }
1872       env = GNUNET_MQ_msg_extra (uim,
1873                                  payload_length + alen - sizeof (struct GNUNET_TUN_UdpHeader),
1874                                  GNUNET_MESSAGE_TYPE_VPN_UDP_TO_INTERNET);
1875       uim->af = htonl (destination->details.exit_destination.af);
1876       uim->source_port = (ntohs (udp->source_port) < 32000) ? udp->source_port : 0;
1877       uim->destination_port = udp->destination_port;
1878       switch (destination->details.exit_destination.af)
1879       {
1880       case AF_INET:
1881         ip4dst = (struct in_addr *) &uim[1];
1882         *ip4dst = destination->details.exit_destination.ip.v4;
1883         payload = &ip4dst[1];
1884         break;
1885       case AF_INET6:
1886         ip6dst = (struct in6_addr *) &uim[1];
1887         *ip6dst = destination->details.exit_destination.ip.v6;
1888         payload = &ip6dst[1];
1889         break;
1890       default:
1891         GNUNET_assert (0);
1892       }
1893       GNUNET_memcpy (payload,
1894                      &udp[1],
1895                      payload_length - sizeof (struct GNUNET_TUN_UdpHeader));
1896     }
1897     break;
1898   case IPPROTO_TCP:
1899     if (GNUNET_NO == ts->is_established)
1900     {
1901       if (destination->is_service)
1902       {
1903         struct GNUNET_EXIT_TcpServiceStartMessage *tsm;
1904
1905         mlen = sizeof (struct GNUNET_EXIT_TcpServiceStartMessage) +
1906           payload_length - sizeof (struct GNUNET_TUN_TcpHeader);
1907         if (mlen >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1908         {
1909           GNUNET_break (0);
1910           return;
1911         }
1912         env = GNUNET_MQ_msg_extra (tsm,
1913                                    payload_length - sizeof (struct GNUNET_TUN_TcpHeader),
1914                                    GNUNET_MESSAGE_TYPE_VPN_TCP_TO_SERVICE_START);
1915         tsm->reserved = htonl (0);
1916         tsm->tcp_header = *tcp;
1917         GNUNET_memcpy (&tsm[1],
1918                        &tcp[1],
1919                        payload_length - sizeof (struct GNUNET_TUN_TcpHeader));
1920       }
1921       else
1922       {
1923         struct GNUNET_EXIT_TcpInternetStartMessage *tim;
1924         struct in_addr *ip4dst;
1925         struct in6_addr *ip6dst;
1926         void *payload;
1927
1928         mlen = sizeof (struct GNUNET_EXIT_TcpInternetStartMessage) +
1929           alen + payload_length - sizeof (struct GNUNET_TUN_TcpHeader);
1930         if (mlen >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1931         {
1932           GNUNET_break (0);
1933           return;
1934         }
1935         env = GNUNET_MQ_msg_extra (tim,
1936                                    payload_length + alen - sizeof (struct GNUNET_TUN_TcpHeader),
1937                                    GNUNET_MESSAGE_TYPE_VPN_TCP_TO_INTERNET_START);
1938         tim->af = htonl (destination->details.exit_destination.af);
1939         tim->tcp_header = *tcp;
1940         switch (destination->details.exit_destination.af)
1941         {
1942         case AF_INET:
1943           ip4dst = (struct in_addr *) &tim[1];
1944           *ip4dst = destination->details.exit_destination.ip.v4;
1945           payload = &ip4dst[1];
1946           break;
1947         case AF_INET6:
1948           ip6dst = (struct in6_addr *) &tim[1];
1949           *ip6dst = destination->details.exit_destination.ip.v6;
1950           payload = &ip6dst[1];
1951           break;
1952         default:
1953           GNUNET_assert (0);
1954         }
1955         GNUNET_memcpy (payload,
1956                        &tcp[1],
1957                        payload_length - sizeof (struct GNUNET_TUN_TcpHeader));
1958       }
1959     }
1960     else
1961     {
1962       struct GNUNET_EXIT_TcpDataMessage *tdm;
1963
1964       mlen = sizeof (struct GNUNET_EXIT_TcpDataMessage) +
1965         payload_length - sizeof (struct GNUNET_TUN_TcpHeader);
1966       if (mlen >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1967       {
1968         GNUNET_break (0);
1969         return;
1970       }
1971       env = GNUNET_MQ_msg_extra (tdm,
1972                                  payload_length - sizeof (struct GNUNET_TUN_TcpHeader),
1973                                  GNUNET_MESSAGE_TYPE_VPN_TCP_DATA_TO_EXIT);
1974       tdm->reserved = htonl (0);
1975       tdm->tcp_header = *tcp;
1976       GNUNET_memcpy (&tdm[1],
1977                      &tcp[1],
1978                      payload_length - sizeof (struct GNUNET_TUN_TcpHeader));
1979      }
1980     break;
1981   case IPPROTO_ICMP:
1982   case IPPROTO_ICMPV6:
1983     if (destination->is_service)
1984     {
1985       struct GNUNET_EXIT_IcmpServiceMessage *ism;
1986
1987       /* ICMP protocol translation will be done by the receiver (as we don't know
1988          the target AF); however, we still need to possibly discard the payload
1989          depending on the ICMP type */
1990       switch (af)
1991       {
1992       case AF_INET:
1993         switch (icmp->type)
1994         {
1995         case GNUNET_TUN_ICMPTYPE_ECHO_REPLY:
1996         case GNUNET_TUN_ICMPTYPE_ECHO_REQUEST:
1997           break;
1998         case GNUNET_TUN_ICMPTYPE_DESTINATION_UNREACHABLE:
1999         case GNUNET_TUN_ICMPTYPE_SOURCE_QUENCH:
2000         case GNUNET_TUN_ICMPTYPE_TIME_EXCEEDED:
2001           /* throw away ICMP payload, won't be useful for the other side anyway */
2002           payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
2003           break;
2004         default:
2005           GNUNET_STATISTICS_update (stats,
2006                                     gettext_noop ("# ICMPv4 packets dropped (not allowed)"),
2007                                     1, GNUNET_NO);
2008           return;
2009         }
2010         /* end of AF_INET */
2011         break;
2012       case AF_INET6:
2013         switch (icmp->type)
2014         {
2015         case GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE:
2016         case GNUNET_TUN_ICMPTYPE6_PACKET_TOO_BIG:
2017         case GNUNET_TUN_ICMPTYPE6_TIME_EXCEEDED:
2018         case GNUNET_TUN_ICMPTYPE6_PARAMETER_PROBLEM:
2019           /* throw away ICMP payload, won't be useful for the other side anyway */
2020           payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
2021           break;
2022         case GNUNET_TUN_ICMPTYPE6_ECHO_REQUEST:
2023         case GNUNET_TUN_ICMPTYPE6_ECHO_REPLY:
2024           break;
2025         default:
2026           GNUNET_STATISTICS_update (stats,
2027                                     gettext_noop ("# ICMPv6 packets dropped (not allowed)"),
2028                                     1, GNUNET_NO);
2029           return;
2030         }
2031         /* end of AF_INET6 */
2032         break;
2033       default:
2034         GNUNET_assert (0);
2035         break;
2036       }
2037
2038       /* update length calculations, as payload_length may have changed */
2039       mlen = sizeof (struct GNUNET_EXIT_IcmpServiceMessage) +
2040         alen + payload_length - sizeof (struct GNUNET_TUN_IcmpHeader);
2041       if (mlen >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
2042       {
2043         GNUNET_break (0);
2044         return;
2045       }
2046
2047       env = GNUNET_MQ_msg_extra (ism,
2048                                  payload_length - sizeof (struct GNUNET_TUN_IcmpHeader),
2049                                  GNUNET_MESSAGE_TYPE_VPN_ICMP_TO_SERVICE);
2050       ism->af = htonl (af); /* need to tell destination ICMP protocol family! */
2051       ism->icmp_header = *icmp;
2052       GNUNET_memcpy (&ism[1],
2053                      &icmp[1],
2054                      payload_length - sizeof (struct GNUNET_TUN_IcmpHeader));
2055     }
2056     else
2057     {
2058       struct GNUNET_EXIT_IcmpInternetMessage *iim;
2059       struct in_addr *ip4dst;
2060       struct in6_addr *ip6dst;
2061       void *payload;
2062       uint8_t new_type;
2063
2064       new_type = icmp->type;
2065       /* Perform ICMP protocol-translation (depending on destination AF and source AF)
2066          and throw away ICMP payload depending on ICMP message type */
2067       switch (af)
2068       {
2069       case AF_INET:
2070         switch (icmp->type)
2071         {
2072         case GNUNET_TUN_ICMPTYPE_ECHO_REPLY:
2073           if (destination->details.exit_destination.af == AF_INET6)
2074             new_type = GNUNET_TUN_ICMPTYPE6_ECHO_REPLY;
2075           break;
2076         case GNUNET_TUN_ICMPTYPE_ECHO_REQUEST:
2077           if (destination->details.exit_destination.af == AF_INET6)
2078             new_type = GNUNET_TUN_ICMPTYPE6_ECHO_REQUEST;
2079           break;
2080         case GNUNET_TUN_ICMPTYPE_DESTINATION_UNREACHABLE:
2081           if (destination->details.exit_destination.af == AF_INET6)
2082             new_type = GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE;
2083           /* throw away IP-payload, exit will have to make it up anyway */
2084           payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
2085           break;
2086         case GNUNET_TUN_ICMPTYPE_TIME_EXCEEDED:
2087           if (destination->details.exit_destination.af == AF_INET6)
2088             new_type = GNUNET_TUN_ICMPTYPE6_TIME_EXCEEDED;
2089           /* throw away IP-payload, exit will have to make it up anyway */
2090           payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
2091           break;
2092         case GNUNET_TUN_ICMPTYPE_SOURCE_QUENCH:
2093           if (destination->details.exit_destination.af == AF_INET6)
2094             {
2095               GNUNET_STATISTICS_update (stats,
2096                                         gettext_noop ("# ICMPv4 packets dropped (impossible PT to v6)"),
2097                                         1, GNUNET_NO);
2098               return;
2099             }
2100           /* throw away IP-payload, exit will have to make it up anyway */
2101           payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
2102           break;
2103         default:
2104           GNUNET_STATISTICS_update (stats,
2105                                     gettext_noop ("# ICMPv4 packets dropped (type not allowed)"),
2106                                     1, GNUNET_NO);
2107           return;
2108         }
2109         /* end of AF_INET */
2110         break;
2111       case AF_INET6:
2112         switch (icmp->type)
2113           {
2114           case GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE:
2115             if (destination->details.exit_destination.af == AF_INET)
2116               new_type = GNUNET_TUN_ICMPTYPE_DESTINATION_UNREACHABLE;
2117             /* throw away IP-payload, exit will have to make it up anyway */
2118             payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
2119             break;
2120           case GNUNET_TUN_ICMPTYPE6_TIME_EXCEEDED:
2121             if (destination->details.exit_destination.af == AF_INET)
2122               new_type = GNUNET_TUN_ICMPTYPE_TIME_EXCEEDED;
2123             /* throw away IP-payload, exit will have to make it up anyway */
2124             payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
2125             break;
2126           case GNUNET_TUN_ICMPTYPE6_PACKET_TOO_BIG:
2127             if (destination->details.exit_destination.af == AF_INET)
2128             {
2129               GNUNET_STATISTICS_update (stats,
2130                                         gettext_noop ("# ICMPv6 packets dropped (impossible PT to v4)"),
2131                                         1, GNUNET_NO);
2132               return;
2133             }
2134             /* throw away IP-payload, exit will have to make it up anyway */
2135             payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
2136             break;
2137           case GNUNET_TUN_ICMPTYPE6_PARAMETER_PROBLEM:
2138             if (destination->details.exit_destination.af == AF_INET)
2139             {
2140               GNUNET_STATISTICS_update (stats,
2141                                         gettext_noop ("# ICMPv6 packets dropped (impossible PT to v4)"),
2142                                         1, GNUNET_NO);
2143               return;
2144             }
2145             /* throw away IP-payload, exit will have to make it up anyway */
2146             payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
2147             break;
2148           case GNUNET_TUN_ICMPTYPE6_ECHO_REQUEST:
2149             if (destination->details.exit_destination.af == AF_INET)
2150               new_type = GNUNET_TUN_ICMPTYPE_ECHO_REQUEST;
2151             break;
2152           case GNUNET_TUN_ICMPTYPE6_ECHO_REPLY:
2153             if (destination->details.exit_destination.af == AF_INET)
2154               new_type = GNUNET_TUN_ICMPTYPE_ECHO_REPLY;
2155             break;
2156           default:
2157             GNUNET_STATISTICS_update (stats,
2158                                       gettext_noop ("# ICMPv6 packets dropped (type not allowed)"),
2159                                       1, GNUNET_NO);
2160             return;
2161           }
2162         /* end of AF_INET6 */
2163         break;
2164       default:
2165         GNUNET_assert (0);
2166       }
2167
2168       /* update length calculations, as payload_length may have changed */
2169       mlen = sizeof (struct GNUNET_EXIT_IcmpInternetMessage) +
2170         alen + payload_length - sizeof (struct GNUNET_TUN_IcmpHeader);
2171       if (mlen >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
2172       {
2173         GNUNET_break (0);
2174         return;
2175       }
2176       env = GNUNET_MQ_msg_extra (iim,
2177                                  alen + payload_length - sizeof (struct GNUNET_TUN_IcmpHeader),
2178                                  GNUNET_MESSAGE_TYPE_VPN_ICMP_TO_INTERNET);
2179       iim->icmp_header = *icmp;
2180       iim->icmp_header.type = new_type;
2181       iim->af = htonl (destination->details.exit_destination.af);
2182       switch (destination->details.exit_destination.af)
2183       {
2184       case AF_INET:
2185         ip4dst = (struct in_addr *) &iim[1];
2186         *ip4dst = destination->details.exit_destination.ip.v4;
2187         payload = &ip4dst[1];
2188         break;
2189       case AF_INET6:
2190         ip6dst = (struct in6_addr *) &iim[1];
2191         *ip6dst = destination->details.exit_destination.ip.v6;
2192         payload = &ip6dst[1];
2193         break;
2194       default:
2195         GNUNET_assert (0);
2196       }
2197       GNUNET_memcpy (payload,
2198                      &icmp[1],
2199                      payload_length - sizeof (struct GNUNET_TUN_IcmpHeader));
2200     }
2201     break;
2202   default:
2203     /* not supported above, how can we get here !? */
2204     GNUNET_assert (0);
2205     break;
2206   }
2207   ts->is_established = GNUNET_YES;
2208   send_to_channel (ts,
2209                    env);
2210 }
2211
2212
2213 /**
2214  * Receive packets from the helper-process (someone send to the local
2215  * virtual channel interface).  Find the destination mapping, and if it
2216  * exists, identify the correct CADET channel (or possibly create it)
2217  * and forward the packet.
2218  *
2219  * @param cls closure, NULL
2220  * @param client NULL
2221  * @param message message we got from the client (VPN channel interface)
2222  */
2223 static int
2224 message_token (void *cls,
2225                void *client,
2226                const struct GNUNET_MessageHeader *message)
2227 {
2228   const struct GNUNET_TUN_Layer2PacketHeader *tun;
2229   size_t mlen;
2230   struct GNUNET_HashCode key;
2231   struct DestinationEntry *de;
2232
2233   GNUNET_STATISTICS_update (stats,
2234                             gettext_noop ("# Packets received from TUN interface"),
2235                             1, GNUNET_NO);
2236   mlen = ntohs (message->size);
2237   if ( (ntohs (message->type) != GNUNET_MESSAGE_TYPE_VPN_HELPER) ||
2238        (mlen < sizeof (struct GNUNET_MessageHeader) + sizeof (struct GNUNET_TUN_Layer2PacketHeader)) )
2239   {
2240     GNUNET_break (0);
2241     return GNUNET_OK;
2242   }
2243   tun = (const struct GNUNET_TUN_Layer2PacketHeader *) &message[1];
2244   mlen -= (sizeof (struct GNUNET_MessageHeader) + sizeof (struct GNUNET_TUN_Layer2PacketHeader));
2245   switch (ntohs (tun->proto))
2246   {
2247   case ETH_P_IPV6:
2248     {
2249       const struct GNUNET_TUN_IPv6Header *pkt6;
2250
2251       if (mlen < sizeof (struct GNUNET_TUN_IPv6Header))
2252       {
2253         /* blame kernel */
2254         GNUNET_break (0);
2255         return GNUNET_OK;
2256       }
2257       pkt6 = (const struct GNUNET_TUN_IPv6Header *) &tun[1];
2258       get_destination_key_from_ip (AF_INET6,
2259                                    &pkt6->destination_address,
2260                                    &key);
2261       de = GNUNET_CONTAINER_multihashmap_get (destination_map, &key);
2262       if (NULL == de)
2263       {
2264         char buf[INET6_ADDRSTRLEN];
2265
2266         GNUNET_log (GNUNET_ERROR_TYPE_INFO,
2267                     _("Packet received for unmapped destination `%s' (dropping it)\n"),
2268                     inet_ntop (AF_INET6,
2269                                &pkt6->destination_address,
2270                                buf,
2271                                sizeof (buf)));
2272         return GNUNET_OK;
2273       }
2274       route_packet (de,
2275                     AF_INET6,
2276                     pkt6->next_header,
2277                     &pkt6->source_address,
2278                     &pkt6->destination_address,
2279                     &pkt6[1],
2280                     mlen - sizeof (struct GNUNET_TUN_IPv6Header));
2281     }
2282     break;
2283   case ETH_P_IPV4:
2284     {
2285       struct GNUNET_TUN_IPv4Header *pkt4;
2286
2287       if (mlen < sizeof (struct GNUNET_TUN_IPv4Header))
2288       {
2289         /* blame kernel */
2290         GNUNET_break (0);
2291         return GNUNET_OK;
2292       }
2293       pkt4 = (struct GNUNET_TUN_IPv4Header *) &tun[1];
2294       get_destination_key_from_ip (AF_INET,
2295                                    &pkt4->destination_address,
2296                                    &key);
2297       de = GNUNET_CONTAINER_multihashmap_get (destination_map, &key);
2298       if (NULL == de)
2299       {
2300         char buf[INET_ADDRSTRLEN];
2301
2302         GNUNET_log (GNUNET_ERROR_TYPE_INFO,
2303                     _("Packet received for unmapped destination `%s' (dropping it)\n"),
2304                     inet_ntop (AF_INET,
2305                                &pkt4->destination_address,
2306                                buf,
2307                                sizeof (buf)));
2308         return GNUNET_OK;
2309       }
2310       if (pkt4->header_length * 4 != sizeof (struct GNUNET_TUN_IPv4Header))
2311       {
2312         GNUNET_log (GNUNET_ERROR_TYPE_INFO,
2313                     _("Received IPv4 packet with options (dropping it)\n"));
2314         return GNUNET_OK;
2315       }
2316       route_packet (de,
2317                     AF_INET,
2318                     pkt4->protocol,
2319                     &pkt4->source_address,
2320                     &pkt4->destination_address,
2321                     &pkt4[1],
2322                     mlen - sizeof (struct GNUNET_TUN_IPv4Header));
2323     }
2324     break;
2325   default:
2326     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
2327                 _("Received packet of unknown protocol %d from TUN (dropping it)\n"),
2328                 (unsigned int) ntohs (tun->proto));
2329     break;
2330   }
2331   return GNUNET_OK;
2332 }
2333
2334
2335 /**
2336  * Allocate an IPv4 address from the range of the channel
2337  * for a new redirection.
2338  *
2339  * @param v4 where to store the address
2340  * @return #GNUNET_OK on success,
2341  *         #GNUNET_SYSERR on error
2342  */
2343 static int
2344 allocate_v4_address (struct in_addr *v4)
2345 {
2346   const char *ipv4addr = vpn_argv[4];
2347   const char *ipv4mask = vpn_argv[5];
2348   struct in_addr addr;
2349   struct in_addr mask;
2350   struct in_addr rnd;
2351   struct GNUNET_HashCode key;
2352   unsigned int tries;
2353
2354   GNUNET_assert (1 == inet_pton (AF_INET, ipv4addr, &addr));
2355   GNUNET_assert (1 == inet_pton (AF_INET, ipv4mask, &mask));
2356   /* Given 192.168.0.1/255.255.0.0, we want a mask
2357      of '192.168.255.255', thus:  */
2358   mask.s_addr = addr.s_addr | ~mask.s_addr;
2359   tries = 0;
2360   do
2361     {
2362       tries++;
2363       if (tries > 16)
2364       {
2365         GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
2366                     _("Failed to find unallocated IPv4 address in VPN's range\n"));
2367         return GNUNET_SYSERR;
2368       }
2369       /* Pick random IPv4 address within the subnet, except 'addr' or 'mask' itself */
2370       rnd.s_addr = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
2371                                              UINT32_MAX);
2372       v4->s_addr = (addr.s_addr | rnd.s_addr) & mask.s_addr;
2373       get_destination_key_from_ip (AF_INET,
2374                                    v4,
2375                                    &key);
2376     }
2377   while ( (GNUNET_YES ==
2378            GNUNET_CONTAINER_multihashmap_contains (destination_map,
2379                                                    &key)) ||
2380           (v4->s_addr == addr.s_addr) ||
2381           (v4->s_addr == mask.s_addr) );
2382   return GNUNET_OK;
2383 }
2384
2385
2386 /**
2387  * Allocate an IPv6 address from the range of the channel
2388  * for a new redirection.
2389  *
2390  * @param v6 where to store the address
2391  * @return #GNUNET_OK on success,
2392  *         #GNUNET_SYSERR on error
2393  */
2394 static int
2395 allocate_v6_address (struct in6_addr *v6)
2396 {
2397   const char *ipv6addr = vpn_argv[2];
2398   struct in6_addr addr;
2399   struct in6_addr mask;
2400   struct in6_addr rnd;
2401   int i;
2402   struct GNUNET_HashCode key;
2403   unsigned int tries;
2404
2405   GNUNET_assert (1 == inet_pton (AF_INET6, ipv6addr, &addr));
2406   GNUNET_assert (ipv6prefix < 128);
2407   /* Given ABCD::/96, we want a mask of 'ABCD::FFFF:FFFF,
2408      thus: */
2409   mask = addr;
2410   for (i=127;i>=ipv6prefix;i--)
2411     mask.s6_addr[i / 8] |= (1 << (i % 8));
2412
2413   /* Pick random IPv6 address within the subnet, except 'addr' or 'mask' itself */
2414   tries = 0;
2415   do
2416     {
2417       tries++;
2418       if (tries > 16)
2419         {
2420           GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
2421                       _("Failed to find unallocated IPv6 address in VPN's range\n"));
2422           return GNUNET_SYSERR;
2423
2424         }
2425       for (i=0;i<16;i++)
2426         {
2427           rnd.s6_addr[i] = (unsigned char) GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
2428                                                                      256);
2429           v6->s6_addr[i]
2430             = (addr.s6_addr[i] | rnd.s6_addr[i]) & mask.s6_addr[i];
2431         }
2432       get_destination_key_from_ip (AF_INET6,
2433                                    v6,
2434                                    &key);
2435     }
2436   while ( (GNUNET_YES ==
2437            GNUNET_CONTAINER_multihashmap_contains (destination_map,
2438                                                    &key)) ||
2439           (0 == memcmp (v6,
2440                         &addr,
2441                         sizeof (struct in6_addr))) ||
2442           (0 == memcmp (v6,
2443                         &mask,
2444                         sizeof (struct in6_addr))) );
2445   return GNUNET_OK;
2446 }
2447
2448
2449 /**
2450  * Free resources occupied by a destination entry.
2451  *
2452  * @param de entry to free
2453  */
2454 static void
2455 free_destination_entry (struct DestinationEntry *de)
2456 {
2457   struct DestinationChannel *dt;
2458
2459   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2460               "Cleaning up destination entry `%s'\n",
2461               print_channel_destination (de));
2462   GNUNET_STATISTICS_update (stats,
2463                             gettext_noop ("# Active destinations"),
2464                             -1, GNUNET_NO);
2465   while (NULL != (dt = de->dt_head))
2466   {
2467     GNUNET_CONTAINER_DLL_remove (de->dt_head,
2468                                  de->dt_tail,
2469                                  dt);
2470     GNUNET_free (dt);
2471   }
2472   if (NULL != de->heap_node)
2473   {
2474     GNUNET_CONTAINER_heap_remove_node (de->heap_node);
2475     de->heap_node = NULL;
2476     GNUNET_assert (GNUNET_YES ==
2477                    GNUNET_CONTAINER_multihashmap_remove (destination_map,
2478                                                          &de->key,
2479                                                          de));
2480   }
2481   GNUNET_free (de);
2482 }
2483
2484
2485 /**
2486  * We have too many active destinations.  Clean up the oldest destination.
2487  *
2488  * @param except destination that must NOT be cleaned up, even if it is the oldest
2489  */
2490 static void
2491 expire_destination (struct DestinationEntry *except)
2492 {
2493   struct DestinationEntry *de;
2494
2495   de = GNUNET_CONTAINER_heap_peek (destination_heap);
2496   GNUNET_assert (NULL != de);
2497   if (except == de)
2498     return; /* can't do this */
2499   free_destination_entry (de);
2500 }
2501
2502
2503 /**
2504  * Allocate an IP address for the response.
2505  *
2506  * @param result_af desired address family; set to the actual
2507  *        address family; can initially be AF_UNSPEC if there
2508  *        is no preference; will be set to AF_UNSPEC if the
2509  *        allocation failed
2510  * @param addr set to either v4 or v6 depending on which
2511  *         storage location was used; set to NULL if allocation failed
2512  * @param v4 storage space for an IPv4 address
2513  * @param v6 storage space for an IPv6 address
2514  * @return #GNUNET_OK normally, #GNUNET_SYSERR if `* result_af` was
2515  *         an unsupported address family (not AF_INET, AF_INET6 or AF_UNSPEC)
2516  */
2517 static int
2518 allocate_response_ip (int *result_af,
2519                       void **addr,
2520                       struct in_addr *v4,
2521                       struct in6_addr *v6)
2522 {
2523   *addr = NULL;
2524   switch (*result_af)
2525   {
2526   case AF_INET:
2527     if (GNUNET_OK !=
2528         allocate_v4_address (v4))
2529       *result_af = AF_UNSPEC;
2530     else
2531       *addr = v4;
2532     break;
2533   case AF_INET6:
2534     if (GNUNET_OK !=
2535         allocate_v6_address (v6))
2536       *result_af = AF_UNSPEC;
2537     else
2538       *addr = v6;
2539     break;
2540   case AF_UNSPEC:
2541     if (GNUNET_OK ==
2542         allocate_v4_address (v4))
2543     {
2544       *addr = v4;
2545       *result_af = AF_INET;
2546     }
2547     else if (GNUNET_OK ==
2548         allocate_v6_address (v6))
2549     {
2550       *addr = v6;
2551       *result_af = AF_INET6;
2552     }
2553     break;
2554   default:
2555     GNUNET_break (0);
2556     return GNUNET_SYSERR;
2557   }
2558   return GNUNET_OK;
2559 }
2560
2561
2562 /**
2563  * A client asks us to setup a redirection via some exit node to a
2564  * particular IP.  Check if @a msg is well-formed.
2565  * allocated IP.
2566  *
2567  * @param cls client requesting client
2568  * @param msg redirection request
2569  * @return #GNUNET_OK if @a msg is well-formed
2570  */
2571 static int
2572 check_client_redirect_to_ip (void *cls,
2573                              const struct RedirectToIpRequestMessage *msg)
2574 {
2575   size_t alen;
2576   int addr_af;
2577
2578   alen = ntohs (msg->header.size) - sizeof (struct RedirectToIpRequestMessage);
2579   addr_af = (int) htonl (msg->addr_af);
2580   switch (addr_af)
2581   {
2582   case AF_INET:
2583     if (alen != sizeof (struct in_addr))
2584     {
2585       GNUNET_break (0);
2586       return GNUNET_SYSERR;
2587     }
2588     break;
2589   case AF_INET6:
2590     if (alen != sizeof (struct in6_addr))
2591     {
2592       GNUNET_break (0);
2593       return GNUNET_SYSERR;
2594     }
2595     break;
2596   default:
2597     GNUNET_break (0);
2598     return GNUNET_SYSERR;
2599   }
2600   return GNUNET_OK;
2601 }
2602
2603
2604 /**
2605  * A client asks us to setup a redirection via some exit node to a
2606  * particular IP.  Setup the redirection and give the client the
2607  * allocated IP.
2608  *
2609  * @param cls client requesting client
2610  * @param msg redirection request
2611  */
2612 static void
2613 handle_client_redirect_to_ip (void *cls,
2614                               const struct RedirectToIpRequestMessage *msg)
2615 {
2616   struct GNUNET_SERVICE_Client *client = cls;
2617   size_t alen;
2618   int addr_af;
2619   int result_af;
2620   struct in_addr v4;
2621   struct in6_addr v6;
2622   void *addr;
2623   struct DestinationEntry *de;
2624   struct GNUNET_HashCode key;
2625
2626   alen = ntohs (msg->header.size) - sizeof (struct RedirectToIpRequestMessage);
2627   addr_af = (int) htonl (msg->addr_af);
2628   /* allocate response IP */
2629   result_af = (int) htonl (msg->result_af);
2630   if (GNUNET_OK != allocate_response_ip (&result_af,
2631                                          &addr,
2632                                          &v4, &v6))
2633   {
2634     GNUNET_SERVICE_client_drop (client);
2635     return;
2636   }
2637   /* send reply with our IP address */
2638   send_client_reply (client,
2639                      msg->request_id,
2640                      result_af,
2641                      addr);
2642   if (result_af == AF_UNSPEC)
2643   {
2644     /* failure, we're done */
2645     GNUNET_SERVICE_client_continue (client);
2646     return;
2647   }
2648
2649   {
2650     char sbuf[INET6_ADDRSTRLEN];
2651     char dbuf[INET6_ADDRSTRLEN];
2652
2653     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2654                 "Allocated address %s for redirection via exit to %s\n",
2655                 inet_ntop (result_af,
2656                            addr,
2657                            sbuf,
2658                            sizeof (sbuf)),
2659                 inet_ntop (addr_af,
2660                            &msg[1],
2661                            dbuf,
2662                            sizeof (dbuf)));
2663   }
2664
2665   /* setup destination record */
2666   de = GNUNET_new (struct DestinationEntry);
2667   de->is_service = GNUNET_NO;
2668   de->details.exit_destination.af = addr_af;
2669   GNUNET_memcpy (&de->details.exit_destination.ip,
2670                  &msg[1],
2671                  alen);
2672   get_destination_key_from_ip (result_af,
2673                                addr,
2674                                &key);
2675   de->key = key;
2676   GNUNET_assert (GNUNET_OK ==
2677                  GNUNET_CONTAINER_multihashmap_put (destination_map,
2678                                                     &key,
2679                                                     de,
2680                                                     GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE));
2681   de->heap_node = GNUNET_CONTAINER_heap_insert (destination_heap,
2682                                                 de,
2683                                                 GNUNET_TIME_absolute_ntoh (msg->expiration_time).abs_value_us);
2684   GNUNET_STATISTICS_update (stats,
2685                             gettext_noop ("# Active destinations"),
2686                             1, GNUNET_NO);
2687   while (GNUNET_CONTAINER_multihashmap_size (destination_map) > max_destination_mappings)
2688     expire_destination (de);
2689   GNUNET_SERVICE_client_continue (client);
2690 }
2691
2692
2693 /**
2694  * A client asks us to setup a redirection to a particular peer
2695  * offering a service.  Setup the redirection and give the client the
2696  * allocated IP.
2697  *
2698  * @param cls requesting client
2699  * @param msg redirection request
2700  */
2701 static void
2702 handle_client_redirect_to_service (void *cls,
2703                                    const struct RedirectToServiceRequestMessage *msg)
2704 {
2705   struct GNUNET_SERVICE_Client *client = cls;
2706   int result_af;
2707   struct in_addr v4;
2708   struct in6_addr v6;
2709   void *addr;
2710   struct DestinationEntry *de;
2711   struct GNUNET_HashCode key;
2712   struct DestinationChannel *dt;
2713
2714   /* allocate response IP */
2715   result_af = (int) htonl (msg->result_af);
2716   if (GNUNET_OK !=
2717       allocate_response_ip (&result_af,
2718                             &addr,
2719                             &v4,
2720                             &v6))
2721   {
2722     GNUNET_break (0);
2723     GNUNET_SERVICE_client_drop (client);
2724     return;
2725   }
2726   send_client_reply (client,
2727                      msg->request_id,
2728                      result_af,
2729                      addr);
2730   if (result_af == AF_UNSPEC)
2731   {
2732     /* failure, we're done */
2733     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2734                 _("Failed to allocate IP address for new destination\n"));
2735     GNUNET_SERVICE_client_continue (client);
2736     return;
2737   }
2738
2739   {
2740     char sbuf[INET6_ADDRSTRLEN];
2741
2742     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2743                 "Allocated address %s for redirection to service %s on peer %s\n",
2744                 inet_ntop (result_af,
2745                            addr,
2746                            sbuf,
2747                            sizeof (sbuf)),
2748                 GNUNET_h2s (&msg->service_descriptor),
2749                 GNUNET_i2s (&msg->target));
2750   }
2751
2752   /* setup destination record */
2753   de = GNUNET_new (struct DestinationEntry);
2754   de->is_service = GNUNET_YES;
2755   de->details.service_destination.target = msg->target;
2756   de->details.service_destination.service_descriptor = msg->service_descriptor;
2757   get_destination_key_from_ip (result_af,
2758                                addr,
2759                                &key);
2760   de->key = key;
2761   GNUNET_assert (GNUNET_OK ==
2762                  GNUNET_CONTAINER_multihashmap_put (destination_map,
2763                                                     &key,
2764                                                     de,
2765                                                     GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE));
2766   de->heap_node
2767     = GNUNET_CONTAINER_heap_insert (destination_heap,
2768                                     de,
2769                                     GNUNET_TIME_absolute_ntoh (msg->expiration_time).abs_value_us);
2770   while (GNUNET_CONTAINER_multihashmap_size (destination_map) > max_destination_mappings)
2771     expire_destination (de);
2772
2773   dt = GNUNET_new (struct DestinationChannel);
2774   dt->destination = de;
2775   GNUNET_CONTAINER_DLL_insert (de->dt_head,
2776                                de->dt_tail,
2777                                dt);
2778   /* we're done */
2779   GNUNET_SERVICE_client_continue (client);
2780 }
2781
2782
2783
2784 /**
2785  * Free memory occupied by an entry in the destination map.
2786  *
2787  * @param cls unused
2788  * @param key unused
2789  * @param value a `struct DestinationEntry *`
2790  * @return #GNUNET_OK (continue to iterate)
2791  */
2792 static int
2793 cleanup_destination (void *cls,
2794                      const struct GNUNET_HashCode *key,
2795                      void *value)
2796 {
2797   struct DestinationEntry *de = value;
2798
2799   free_destination_entry (de);
2800   return GNUNET_OK;
2801 }
2802
2803
2804 /**
2805  * Free memory occupied by an entry in the channel map.
2806  *
2807  * @param cls unused
2808  * @param key unused
2809  * @param value a `struct ChannelState *`
2810  * @return #GNUNET_OK (continue to iterate)
2811  */
2812 static int
2813 cleanup_channel (void *cls,
2814                  const struct GNUNET_HashCode *key,
2815                  void *value)
2816 {
2817   struct ChannelState *ts = value;
2818
2819   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2820               "Tearing down channel to `%s' during cleanup\n",
2821               print_channel_destination (&ts->destination));
2822   free_channel_state (ts);
2823   return GNUNET_OK;
2824 }
2825
2826
2827 /**
2828  * Function scheduled as very last function, cleans up after us
2829  *
2830  * @param cls unused
2831  */
2832 static void
2833 cleanup (void *cls)
2834 {
2835   unsigned int i;
2836
2837   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2838               "VPN is shutting down\n");
2839   if (NULL != destination_map)
2840   {
2841     GNUNET_CONTAINER_multihashmap_iterate (destination_map,
2842                                            &cleanup_destination,
2843                                            NULL);
2844     GNUNET_CONTAINER_multihashmap_destroy (destination_map);
2845     destination_map = NULL;
2846   }
2847   if (NULL != destination_heap)
2848   {
2849     GNUNET_CONTAINER_heap_destroy (destination_heap);
2850     destination_heap = NULL;
2851   }
2852   if (NULL != channel_map)
2853   {
2854     GNUNET_CONTAINER_multihashmap_iterate (channel_map,
2855                                            &cleanup_channel,
2856                                            NULL);
2857     GNUNET_CONTAINER_multihashmap_destroy (channel_map);
2858     channel_map = NULL;
2859   }
2860   if (NULL != channel_heap)
2861   {
2862     GNUNET_CONTAINER_heap_destroy (channel_heap);
2863     channel_heap = NULL;
2864   }
2865   if (NULL != cadet_handle)
2866   {
2867     GNUNET_CADET_disconnect (cadet_handle);
2868     cadet_handle = NULL;
2869   }
2870   if (NULL != helper_handle)
2871   {
2872     GNUNET_HELPER_kill (helper_handle, GNUNET_NO);
2873     GNUNET_HELPER_wait (helper_handle);
2874     helper_handle = NULL;
2875   }
2876   if (NULL != stats)
2877   {
2878     GNUNET_STATISTICS_destroy (stats, GNUNET_NO);
2879     stats = NULL;
2880   }
2881   for (i=0;i<5;i++)
2882     GNUNET_free_non_null (vpn_argv[i]);
2883 }
2884
2885
2886 /**
2887  * Callback called when a client connects to the service.
2888  *
2889  * @param cls closure for the service
2890  * @param c the new client that connected to the service
2891  * @param mq the message queue used to send messages to the client
2892  * @return @a c
2893  */
2894 static void *
2895 client_connect_cb (void *cls,
2896                    struct GNUNET_SERVICE_Client *c,
2897                    struct GNUNET_MQ_Handle *mq)
2898 {
2899   return c;
2900 }
2901
2902
2903 /**
2904  * Callback called when a client disconnected from the service
2905  *
2906  * @param cls closure for the service
2907  * @param c the client that disconnected
2908  * @param internal_cls should be equal to @a c
2909  */
2910 static void
2911 client_disconnect_cb (void *cls,
2912                       struct GNUNET_SERVICE_Client *c,
2913                       void *internal_cls)
2914 {
2915   GNUNET_assert (c == internal_cls);
2916 }
2917
2918
2919 /**
2920  * Main function that will be run by the scheduler.
2921  *
2922  * @param cls closure
2923  * @param cfg_ configuration
2924  * @param service the initialized service
2925  */
2926 static void
2927 run (void *cls,
2928      const struct GNUNET_CONFIGURATION_Handle *cfg_,
2929      struct GNUNET_SERVICE_Handle *service)
2930 {
2931   char *ifname;
2932   char *ipv6addr;
2933   char *ipv6prefix_s;
2934   char *ipv4addr;
2935   char *ipv4mask;
2936   struct in_addr v4;
2937   struct in6_addr v6;
2938   char *binary;
2939
2940   binary = GNUNET_OS_get_libexec_binary_path ("gnunet-helper-vpn");
2941
2942   if (GNUNET_YES !=
2943       GNUNET_OS_check_helper_binary (binary,
2944                                      GNUNET_YES,
2945                                      "-d gnunet-vpn - - 169.1.3.3.7 255.255.255.0")) //ipv4 only please!
2946   {
2947     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2948                 "`%s' is not SUID, refusing to run.\n",
2949                 "gnunet-helper-vpn");
2950     GNUNET_free (binary);
2951     global_ret = 1;
2952     /* we won't "really" exit here, as the 'service' is still running;
2953        however, as no handlers are registered, the service won't do
2954        anything either */
2955     return;
2956   }
2957   GNUNET_free (binary);
2958   cfg = cfg_;
2959   stats = GNUNET_STATISTICS_create ("vpn", cfg);
2960   if (GNUNET_OK !=
2961       GNUNET_CONFIGURATION_get_value_number (cfg,
2962                                              "VPN",
2963                                              "MAX_MAPPING",
2964                                              &max_destination_mappings))
2965     max_destination_mappings = 200;
2966   if (GNUNET_OK !=
2967       GNUNET_CONFIGURATION_get_value_number (cfg,
2968                                              "VPN",
2969                                              "MAX_TUNNELS",
2970                                              &max_channel_mappings))
2971     max_channel_mappings = 200;
2972
2973   destination_map = GNUNET_CONTAINER_multihashmap_create (max_destination_mappings * 2, GNUNET_NO);
2974   destination_heap = GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN);
2975   channel_map = GNUNET_CONTAINER_multihashmap_create (max_channel_mappings * 2, GNUNET_NO);
2976   channel_heap = GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN);
2977
2978
2979   vpn_argv[0] = GNUNET_strdup ("vpn-gnunet");
2980   if (GNUNET_SYSERR ==
2981       GNUNET_CONFIGURATION_get_value_string (cfg, "VPN", "IFNAME", &ifname))
2982   {
2983     GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, "VPN", "IFNAME");
2984     GNUNET_SCHEDULER_shutdown ();
2985     return;
2986   }
2987   vpn_argv[1] = ifname;
2988   ipv6addr = NULL;
2989   if (GNUNET_OK == GNUNET_NETWORK_test_pf (PF_INET6))
2990   {
2991     if ( (GNUNET_SYSERR ==
2992           GNUNET_CONFIGURATION_get_value_string (cfg, "VPN", "IPV6ADDR",
2993                                                  &ipv6addr) ||
2994           (1 != inet_pton (AF_INET6, ipv6addr, &v6))) )
2995     {
2996       GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, "VPN", "IPV6ADDR",
2997                                  _("Must specify valid IPv6 address"));
2998       GNUNET_SCHEDULER_shutdown ();
2999       GNUNET_free_non_null (ipv6addr);
3000       return;
3001     }
3002     vpn_argv[2] = ipv6addr;
3003     ipv6prefix_s = NULL;
3004     if (GNUNET_SYSERR ==
3005         GNUNET_CONFIGURATION_get_value_string (cfg, "VPN", "IPV6PREFIX",
3006                                                &ipv6prefix_s))
3007     {
3008       GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, "VPN", "IPV6PREFIX");
3009       GNUNET_SCHEDULER_shutdown ();
3010       GNUNET_free_non_null (ipv6prefix_s);
3011       return;
3012     }
3013     vpn_argv[3] = ipv6prefix_s;
3014     if ( (GNUNET_OK !=
3015           GNUNET_CONFIGURATION_get_value_number (cfg, "VPN",
3016                                                  "IPV6PREFIX",
3017                                                  &ipv6prefix)) ||
3018          (ipv6prefix >= 127) )
3019     {
3020       GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, "VPN", "IPV4MASK",
3021                                  _("Must specify valid IPv6 mask"));
3022       GNUNET_SCHEDULER_shutdown ();
3023       return;
3024     }
3025   }
3026   else
3027   {
3028     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
3029                 _("IPv6 support disabled as this system does not support IPv6\n"));
3030     vpn_argv[2] = GNUNET_strdup ("-");
3031     vpn_argv[3] = GNUNET_strdup ("-");
3032   }
3033   if (GNUNET_OK == GNUNET_NETWORK_test_pf (PF_INET))
3034   {
3035     ipv4addr = NULL;
3036     if ( (GNUNET_SYSERR ==
3037           GNUNET_CONFIGURATION_get_value_string (cfg, "vpn", "IPV4ADDR",
3038                                                  &ipv4addr) ||
3039           (1 != inet_pton (AF_INET, ipv4addr, &v4))) )
3040     {
3041       GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, "VPN", "IPV4ADDR",
3042                                  _("Must specify valid IPv4 address"));
3043       GNUNET_SCHEDULER_shutdown ();
3044       GNUNET_free_non_null (ipv4addr);
3045       return;
3046     }
3047     vpn_argv[4] = ipv4addr;
3048     ipv4mask = NULL;
3049     if ( (GNUNET_SYSERR ==
3050           GNUNET_CONFIGURATION_get_value_string (cfg, "vpn", "IPV4MASK",
3051                                                  &ipv4mask) ||
3052           (1 != inet_pton (AF_INET, ipv4mask, &v4))) )
3053     {
3054       GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, "VPN", "IPV4MASK",
3055                                  _("Must specify valid IPv4 mask"));
3056       GNUNET_SCHEDULER_shutdown ();
3057       GNUNET_free_non_null (ipv4mask);
3058       return;
3059     }
3060     vpn_argv[5] = ipv4mask;
3061   }
3062   else
3063   {
3064     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
3065                 _("IPv4 support disabled as this system does not support IPv4\n"));
3066     vpn_argv[4] = GNUNET_strdup ("-");
3067     vpn_argv[5] = GNUNET_strdup ("-");
3068   }
3069   vpn_argv[6] = NULL;
3070
3071   cadet_handle = GNUNET_CADET_connecT (cfg_);
3072     // FIXME never opens ports???
3073   helper_handle = GNUNET_HELPER_start (GNUNET_NO,
3074                                        "gnunet-helper-vpn", vpn_argv,
3075                                        &message_token, NULL, NULL);
3076   GNUNET_SCHEDULER_add_shutdown (&cleanup,
3077                                  NULL);
3078 }
3079
3080
3081 /**
3082  * Define "main" method using service macro.
3083  */
3084 GNUNET_SERVICE_MAIN
3085 ("vpn",
3086  GNUNET_SERVICE_OPTION_NONE,
3087  &run,
3088  &client_connect_cb,
3089  &client_disconnect_cb,
3090  NULL,
3091  GNUNET_MQ_hd_var_size (client_redirect_to_ip,
3092                         GNUNET_MESSAGE_TYPE_VPN_CLIENT_REDIRECT_TO_IP,
3093                         struct RedirectToIpRequestMessage,
3094                         NULL),
3095  GNUNET_MQ_hd_fixed_size (client_redirect_to_service,
3096                           GNUNET_MESSAGE_TYPE_VPN_CLIENT_REDIRECT_TO_SERVICE,
3097                           struct RedirectToServiceRequestMessage,
3098                           NULL),
3099  GNUNET_MQ_handler_end ());
3100
3101
3102 /* end of gnunet-service-vpn.c */