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