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