fix exit CADET port binding for services, remove redundant service/port descriptor...
[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 @e msg.
196    */
197   size_t len;
198
199   /**
200    * Message to transmit, allocated at the end of this struct.
201    */
202   const void *msg;
203 };
204
205
206 /**
207  * State we keep for each of our channels.
208  */
209 struct ChannelState
210 {
211
212   /**
213    * Information about the channel to use, NULL if no channel
214    * is available right now.
215    */
216   struct GNUNET_CADET_Channel *channel;
217
218   /**
219    * Active query with REGEX to locate exit.
220    */
221   struct GNUNET_REGEX_Search *search;
222
223   /**
224    * Active transmission handle, NULL for none.
225    */
226   struct GNUNET_CADET_TransmitHandle *th;
227
228   /**
229    * Entry for this entry in the channel_heap, NULL as long as this
230    * channel state is not fully bound.
231    */
232   struct GNUNET_CONTAINER_HeapNode *heap_node;
233
234   /**
235    * Head of list of messages scheduled for transmission.
236    */
237   struct ChannelMessageQueueEntry *tmq_head;
238
239   /**
240    * Tail of list of messages scheduled for transmission.
241    */
242   struct ChannelMessageQueueEntry *tmq_tail;
243
244   /**
245    * Destination to which this channel leads.  Note that
246    * this struct is NOT in the destination_map (but a
247    * local copy) and that the 'heap_node' should always
248    * be NULL.
249    */
250   struct DestinationEntry destination;
251
252   /**
253    * Addess family used for this channel on the local TUN interface.
254    */
255   int af;
256
257   /**
258    * Is this channel new (#GNUNET_NO), or did we exchange messages with the
259    * other side already (#GNUNET_YES)?
260    */
261   int is_established;
262
263   /**
264    * Length of the doubly linked 'tmq_head/tmq_tail' list.
265    */
266   unsigned int tmq_length;
267
268   /**
269    * IPPROTO_TCP or IPPROTO_UDP once bound.
270    */
271   uint8_t protocol;
272
273   /**
274    * IP address of the source on our end, initially uninitialized.
275    */
276   union
277   {
278     /**
279      * Address if af is AF_INET.
280      */
281     struct in_addr v4;
282
283     /**
284      * Address if af is AF_INET6.
285      */
286     struct in6_addr v6;
287
288   } source_ip;
289
290   /**
291    * Destination IP address used by the source on our end (this is the IP
292    * that we pick freely within the VPN's channel IP range).
293    */
294   union
295   {
296     /**
297      * Address if af is AF_INET.
298      */
299     struct in_addr v4;
300
301     /**
302      * Address if af is AF_INET6.
303      */
304     struct in6_addr v6;
305
306   } destination_ip;
307
308   /**
309    * Source port used by the sender on our end; 0 for uninitialized.
310    */
311   uint16_t source_port;
312
313   /**
314    * Destination port used by the sender on our end; 0 for uninitialized.
315    */
316   uint16_t destination_port;
317
318 };
319
320
321 /**
322  * Return value from #main().
323  */
324 static int global_ret;
325
326 /**
327  * Configuration we use.
328  */
329 static const struct GNUNET_CONFIGURATION_Handle *cfg;
330
331 /**
332  * Handle to the cadet service.
333  */
334 static struct GNUNET_CADET_Handle *cadet_handle;
335
336 /**
337  * Map from IP address to destination information (possibly with a
338  * CADET channel handle for fast setup).
339  */
340 static struct GNUNET_CONTAINER_MultiHashMap *destination_map;
341
342 /**
343  * Min-Heap sorted by activity time to expire old mappings.
344  */
345 static struct GNUNET_CONTAINER_Heap *destination_heap;
346
347 /**
348  * Map from source and destination address (IP+port) to connection
349  * information (mostly with the respective CADET channel handle).
350  */
351 static struct GNUNET_CONTAINER_MultiHashMap *channel_map;
352
353 /**
354  * Min-Heap sorted by activity time to expire old mappings; values are
355  * of type 'struct ChannelState'.
356  */
357 static struct GNUNET_CONTAINER_Heap *channel_heap;
358
359 /**
360  * Statistics.
361  */
362 static struct GNUNET_STATISTICS_Handle *stats;
363
364 /**
365  * The handle to the VPN helper process "gnunet-helper-vpn".
366  */
367 static struct GNUNET_HELPER_Handle *helper_handle;
368
369 /**
370  * Arguments to the vpn helper.
371  */
372 static char *vpn_argv[7];
373
374 /**
375  * Length of the prefix of the VPN's IPv6 network.
376  */
377 static unsigned long long ipv6prefix;
378
379 /**
380  * 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],
522                  addr,
523                  rlen);
524   GNUNET_SERVER_notification_context_add (nc, client);
525   GNUNET_SERVER_notification_context_unicast (nc,
526                                               client,
527                                               &res->header,
528                                               GNUNET_NO);
529 }
530
531
532 /**
533  * Free resources associated with a channel state.
534  *
535  * @param ts state to free
536  */
537 static void
538 free_channel_state (struct ChannelState *ts)
539 {
540   struct GNUNET_HashCode key;
541   struct ChannelMessageQueueEntry *tnq;
542   struct GNUNET_CADET_Channel *channel;
543
544   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
545               "Cleaning up channel state\n");
546   if (NULL != ts->th)
547   {
548     GNUNET_CADET_notify_transmit_ready_cancel (ts->th);
549     ts->th = NULL;
550   }
551   if (NULL != (channel = ts->channel))
552   {
553     ts->channel = NULL;
554     GNUNET_CADET_channel_destroy (channel);
555     return;
556   }
557   GNUNET_STATISTICS_update (stats,
558                             gettext_noop ("# Active channels"),
559                             -1, GNUNET_NO);
560   while (NULL != (tnq = ts->tmq_head))
561   {
562     GNUNET_CONTAINER_DLL_remove (ts->tmq_head,
563                                  ts->tmq_tail,
564                                  tnq);
565     ts->tmq_length--;
566     GNUNET_free (tnq);
567   }
568   GNUNET_assert (0 == ts->tmq_length);
569   GNUNET_assert (NULL == ts->destination.heap_node);
570   if (NULL != ts->search)
571   {
572     GNUNET_REGEX_search_cancel (ts->search);
573     ts->search = NULL;
574   }
575   if (NULL != ts->heap_node)
576   {
577     GNUNET_CONTAINER_heap_remove_node (ts->heap_node);
578     ts->heap_node = NULL;
579     get_channel_key_from_ips (ts->af,
580                              ts->protocol,
581                              &ts->source_ip,
582                              ts->source_port,
583                              &ts->destination_ip,
584                              ts->destination_port,
585                              &key);
586     GNUNET_assert (GNUNET_YES ==
587                    GNUNET_CONTAINER_multihashmap_remove (channel_map,
588                                                          &key,
589                                                          ts));
590   }
591   GNUNET_free (ts);
592 }
593
594
595 /**
596  * Send a message from the message queue via cadet.
597  *
598  * @param cls the `struct ChannelState` with the message queue
599  * @param size number of bytes available in @a buf
600  * @param buf where to copy the message
601  * @return number of bytes copied to @a buf
602  */
603 static size_t
604 send_to_peer_notify_callback (void *cls, size_t size, void *buf)
605 {
606   struct ChannelState *ts = cls;
607   struct ChannelMessageQueueEntry *tnq;
608   size_t ret;
609
610   ts->th = NULL;
611   if (NULL == buf)
612     return 0;
613   tnq = ts->tmq_head;
614   GNUNET_assert (NULL != tnq);
615   GNUNET_assert (size >= tnq->len);
616   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
617               "Sending %u bytes via cadet channel\n",
618               (unsigned int) tnq->len);
619   GNUNET_CONTAINER_DLL_remove (ts->tmq_head,
620                                ts->tmq_tail,
621                                tnq);
622   ts->tmq_length--;
623   GNUNET_memcpy (buf, tnq->msg, tnq->len);
624   ret = tnq->len;
625   GNUNET_free (tnq);
626   if (NULL != (tnq = ts->tmq_head))
627   {
628     if (NULL == ts->th)
629       ts->th = GNUNET_CADET_notify_transmit_ready (ts->channel,
630                                                    GNUNET_NO /* cork */,
631                                                    GNUNET_TIME_UNIT_FOREVER_REL,
632                                                    tnq->len,
633                                                    &send_to_peer_notify_callback,
634                                                    ts);
635   }
636   GNUNET_STATISTICS_update (stats,
637                             gettext_noop ("# Bytes given to cadet for transmission"),
638                             ret, GNUNET_NO);
639   return ret;
640 }
641
642
643 /**
644  * Add the given message to the given channel and trigger the
645  * transmission process.
646  *
647  * @param tnq message to queue
648  * @param ts channel to queue the message for
649  */
650 static void
651 send_to_channel (struct ChannelMessageQueueEntry *tnq,
652                 struct ChannelState *ts)
653 {
654   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
655               "Queueing %u bytes for transmission via cadet channel\n",
656               (unsigned int) tnq->len);
657   GNUNET_assert (NULL != ts->channel);
658   GNUNET_CONTAINER_DLL_insert_tail (ts->tmq_head,
659                                     ts->tmq_tail,
660                                     tnq);
661   ts->tmq_length++;
662   if (ts->tmq_length > MAX_MESSAGE_QUEUE_SIZE)
663   {
664     struct ChannelMessageQueueEntry *dq;
665
666     dq = ts->tmq_head;
667     GNUNET_assert (dq != tnq);
668     GNUNET_CONTAINER_DLL_remove (ts->tmq_head,
669                                  ts->tmq_tail,
670                                  dq);
671     ts->tmq_length--;
672     GNUNET_CADET_notify_transmit_ready_cancel (ts->th);
673     ts->th = NULL;
674     GNUNET_STATISTICS_update (stats,
675                               gettext_noop ("# Bytes dropped in cadet queue (overflow)"),
676                               dq->len,
677                               GNUNET_NO);
678     GNUNET_free (dq);
679   }
680   if (NULL == ts->th)
681     ts->th = GNUNET_CADET_notify_transmit_ready (ts->channel,
682                                                 GNUNET_NO /* cork */,
683                                                 GNUNET_TIME_UNIT_FOREVER_REL,
684                                                 tnq->len,
685                                                 &send_to_peer_notify_callback,
686                                                 ts);
687 }
688
689
690 /**
691  * Output destination of a channel for diagnostics.
692  *
693  * @param de destination to process
694  * @return diagnostic string describing destination
695  */
696 static const char *
697 print_channel_destination (const struct DestinationEntry *de)
698 {
699   static char dest[256];
700
701   if (de->is_service)
702   {
703     GNUNET_snprintf (dest,
704                      sizeof (dest),
705                      "HS: %s-%s",
706                      GNUNET_i2s (&de->details.service_destination.target),
707                      GNUNET_h2s (&de->details.service_destination.service_descriptor));
708   }
709   else
710   {
711     inet_ntop (de->details.exit_destination.af,
712                &de->details.exit_destination.ip,
713                dest,
714                sizeof (dest));
715   }
716   return dest;
717 }
718
719
720 /**
721  * Regex has found a potential exit peer for us; consider using it.
722  *
723  * @param cls the `struct ChannelState`
724  * @param id Peer providing a regex that matches the string.
725  * @param get_path Path of the get request.
726  * @param get_path_length Lenght of @a get_path.
727  * @param put_path Path of the put request.
728  * @param put_path_length Length of the @a put_path.
729  */
730 static void
731 handle_regex_result (void *cls,
732                      const struct GNUNET_PeerIdentity *id,
733                      const struct GNUNET_PeerIdentity *get_path,
734                      unsigned int get_path_length,
735                      const struct GNUNET_PeerIdentity *put_path,
736                      unsigned int put_path_length)
737 {
738   struct ChannelState *ts = cls;
739   struct GNUNET_HashCode port;
740
741   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
742               "Exit %s found for destination %s!\n",
743               GNUNET_i2s (id),
744               print_channel_destination (&ts->destination));
745   GNUNET_REGEX_search_cancel (ts->search);
746   ts->search = NULL;
747   switch (ts->af)
748   {
749   case AF_INET:
750     /* these must match the strings used in gnunet-daemon-exit */
751     GNUNET_CRYPTO_hash (GNUNET_APPLICATION_PORT_IPV4_GATEWAY,
752                         strlen (GNUNET_APPLICATION_PORT_IPV4_GATEWAY),
753                         &port);
754     break;
755   case AF_INET6:
756     /* these must match the strings used in gnunet-daemon-exit */
757     GNUNET_CRYPTO_hash (GNUNET_APPLICATION_PORT_IPV6_GATEWAY,
758                         strlen (GNUNET_APPLICATION_PORT_IPV6_GATEWAY),
759                         &port);
760     break;
761   default:
762     GNUNET_break (0);
763     return;
764   }
765   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
766               "Creating tunnel to %s for destination %s!\n",
767               GNUNET_i2s (id),
768               print_channel_destination (&ts->destination));
769   ts->channel = GNUNET_CADET_channel_create (cadet_handle,
770                                              ts,
771                                              id,
772                                              &port,
773                                              GNUNET_CADET_OPTION_DEFAULT);
774 }
775
776
777 /**
778  * Initialize the given destination entry's cadet channel.
779  *
780  * @param dt destination channel for which we need to setup a channel
781  * @param client_af address family of the address returned to the client
782  * @return channel state of the channel that was created
783  */
784 static struct ChannelState *
785 create_channel_to_destination (struct DestinationChannel *dt,
786                                int client_af)
787 {
788   struct ChannelState *ts;
789
790   GNUNET_STATISTICS_update (stats,
791                             gettext_noop ("# Cadet channels created"),
792                             1,
793                             GNUNET_NO);
794   ts = GNUNET_new (struct ChannelState);
795   ts->af = client_af;
796   ts->destination = *dt->destination;
797   ts->destination.heap_node = NULL; /* copy is NOT in destination heap */
798   if (dt->destination->is_service)
799   {
800     ts->channel
801       = GNUNET_CADET_channel_create (cadet_handle,
802                                      ts,
803                                      &dt->destination->details.service_destination.target,
804                                      &ts->destination.details.service_destination.service_descriptor,
805                                      GNUNET_CADET_OPTION_DEFAULT);
806     if (NULL == ts->channel)
807     {
808       GNUNET_break (0);
809       GNUNET_free (ts);
810       return NULL;
811     }
812     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
813                 "Creating channel %p to peer %s offering service %s\n",
814                 ts->channel,
815                 GNUNET_i2s (&dt->destination->details.service_destination.target),
816                 GNUNET_h2s (&ts->destination.details.service_destination.service_descriptor));
817   }
818   else
819   {
820     char *policy;
821
822     switch (dt->destination->details.exit_destination.af)
823     {
824     case AF_INET:
825     {
826       char address[GNUNET_TUN_IPV4_REGEXLEN];
827
828       GNUNET_TUN_ipv4toregexsearch (&dt->destination->details.exit_destination.ip.v4,
829                                     dt->destination_port,
830                                     address);
831       GNUNET_asprintf (&policy,
832                        "%s%s",
833                        GNUNET_APPLICATION_TYPE_EXIT_REGEX_PREFIX,
834                        address);
835       break;
836     }
837     case AF_INET6:
838     {
839       char address[GNUNET_TUN_IPV6_REGEXLEN];
840
841       GNUNET_TUN_ipv6toregexsearch (&dt->destination->details.exit_destination.ip.v6,
842                                     dt->destination_port,
843                                     address);
844       GNUNET_asprintf (&policy,
845                        "%s%s",
846                        GNUNET_APPLICATION_TYPE_EXIT_REGEX_PREFIX,
847                        address);
848       break;
849     }
850     default:
851       GNUNET_assert (0);
852       break;
853     }
854
855     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
856                 "Requesting connect by string: %s\n",
857                 policy);
858     ts->search = GNUNET_REGEX_search (cfg,
859                                       policy,
860                                       &handle_regex_result,
861                                       ts);
862     GNUNET_free (policy);
863   }
864   return ts;
865 }
866
867
868 /**
869  * We have too many active channels.  Clean up the oldest channel.
870  *
871  * @param except channel that must NOT be cleaned up, even if it is the oldest
872  */
873 static void
874 expire_channel (struct ChannelState *except)
875 {
876   struct ChannelState *ts;
877
878   ts = GNUNET_CONTAINER_heap_peek (channel_heap);
879   GNUNET_assert (NULL != ts);
880   if (except == ts)
881     return; /* can't do this */
882   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
883               "Tearing down expired channel to %s\n",
884               print_channel_destination (&except->destination));
885   free_channel_state (ts);
886 }
887
888
889 /**
890  * Route a packet via cadet to the given destination.
891  *
892  * @param destination description of the destination
893  * @param af address family on this end (AF_INET or AF_INET6)
894  * @param protocol IPPROTO_TCP or IPPROTO_UDP or IPPROTO_ICMP or IPPROTO_ICMPV6
895  * @param source_ip source IP used by the sender (struct in_addr or struct in6_addr)
896  * @param destination_ip destination IP used by the sender (struct in_addr or struct in6_addr)
897  * @param payload payload of the packet after the IP header
898  * @param payload_length number of bytes in @a payload
899  */
900 static void
901 route_packet (struct DestinationEntry *destination,
902               int af,
903               uint8_t protocol,
904               const void *source_ip,
905               const void *destination_ip,
906               const void *payload,
907               size_t payload_length)
908 {
909   struct GNUNET_HashCode key;
910   struct ChannelState *ts;
911   struct ChannelMessageQueueEntry *tnq;
912   size_t alen;
913   size_t mlen;
914   const struct GNUNET_TUN_UdpHeader *udp;
915   const struct GNUNET_TUN_TcpHeader *tcp;
916   const struct GNUNET_TUN_IcmpHeader *icmp;
917   struct DestinationChannel *dt;
918   uint16_t source_port;
919   uint16_t destination_port;
920
921   switch (protocol)
922   {
923   case IPPROTO_UDP:
924     {
925       if (payload_length < sizeof (struct GNUNET_TUN_UdpHeader))
926       {
927         /* blame kernel? */
928         GNUNET_break (0);
929         return;
930       }
931       tcp = NULL; /* make compiler happy */
932       icmp = NULL;  /* make compiler happy */
933       udp = payload;
934       if (udp->len < sizeof (struct GNUNET_TUN_UdpHeader))
935       {
936         GNUNET_break_op (0);
937         return;
938       }
939       source_port = ntohs (udp->source_port);
940       destination_port = ntohs (udp->destination_port);
941       get_channel_key_from_ips (af,
942                                 IPPROTO_UDP,
943                                 source_ip,
944                                 source_port,
945                                 destination_ip,
946                                 destination_port,
947                                 &key);
948     }
949     break;
950   case IPPROTO_TCP:
951     {
952       if (payload_length < sizeof (struct GNUNET_TUN_TcpHeader))
953       {
954         /* blame kernel? */
955         GNUNET_break (0);
956         return;
957       }
958       udp = NULL; /* make compiler happy */
959       icmp = NULL;  /* make compiler happy */
960       tcp = payload;
961       if (tcp->off * 4 < sizeof (struct GNUNET_TUN_TcpHeader))
962       {
963         GNUNET_break_op (0);
964         return;
965       }
966       source_port = ntohs (tcp->source_port);
967       destination_port = ntohs (tcp->destination_port);
968       get_channel_key_from_ips (af,
969                                 IPPROTO_TCP,
970                                 source_ip,
971                                 source_port,
972                                 destination_ip,
973                                 destination_port,
974                                 &key);
975     }
976     break;
977   case IPPROTO_ICMP:
978   case IPPROTO_ICMPV6:
979     {
980       if ( (AF_INET == af) ^ (protocol == IPPROTO_ICMP) )
981       {
982         GNUNET_break (0);
983         return;
984       }
985       if (payload_length < sizeof (struct GNUNET_TUN_IcmpHeader))
986       {
987         /* blame kernel? */
988         GNUNET_break (0);
989         return;
990       }
991       tcp = NULL; /* make compiler happy */
992       udp = NULL;  /* make compiler happy */
993       icmp = payload;
994       source_port = 0;
995       destination_port = 0;
996       get_channel_key_from_ips (af,
997                                 protocol,
998                                 source_ip,
999                                 0,
1000                                 destination_ip,
1001                                 0,
1002                                 &key);
1003     }
1004     break;
1005   default:
1006     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1007                 _("Protocol %u not supported, dropping\n"),
1008                 (unsigned int) protocol);
1009     return;
1010   }
1011   alen = 0;
1012   if (! destination->is_service)
1013   {
1014     switch (destination->details.exit_destination.af)
1015     {
1016     case AF_INET:
1017       alen = sizeof (struct in_addr);
1018      break;
1019     case AF_INET6:
1020       alen = sizeof (struct in6_addr);
1021       break;
1022     default:
1023       GNUNET_assert (0);
1024     }
1025
1026     {
1027       char sbuf[INET6_ADDRSTRLEN];
1028       char dbuf[INET6_ADDRSTRLEN];
1029       char xbuf[INET6_ADDRSTRLEN];
1030
1031       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1032                   "Routing %s packet from [%s]:%u -> [%s]:%u to destination [%s]:%u\n",
1033                   (protocol == IPPROTO_TCP) ? "TCP" : "UDP",
1034                   inet_ntop (af,
1035                              source_ip,
1036                              sbuf,
1037                              sizeof (sbuf)),
1038                   source_port,
1039                   inet_ntop (af,
1040                              destination_ip,
1041                              dbuf,
1042                              sizeof (dbuf)),
1043                   destination_port,
1044                   inet_ntop (destination->details.exit_destination.af,
1045                              &destination->details.exit_destination.ip,
1046                              xbuf, sizeof (xbuf)),
1047                   destination_port);
1048     }
1049     for (dt = destination->dt_head; NULL != dt; dt = dt->next)
1050       if (dt->destination_port == destination_port)
1051         break;
1052   }
1053   else
1054   {
1055     {
1056       char sbuf[INET6_ADDRSTRLEN];
1057       char dbuf[INET6_ADDRSTRLEN];
1058
1059       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1060                   "Routing %s packet from [%s]:%u -> [%s]:%u to service %s at peer %s\n",
1061                   (protocol == IPPROTO_TCP) ? "TCP" : "UDP",
1062                   inet_ntop (af,
1063                              source_ip,
1064                              sbuf,
1065                              sizeof (sbuf)),
1066                   source_port,
1067                   inet_ntop (af,
1068                              destination_ip,
1069                              dbuf,
1070                              sizeof (dbuf)),
1071                   destination_port,
1072                   GNUNET_h2s (&destination->details.service_destination.service_descriptor),
1073                   GNUNET_i2s (&destination->details.service_destination.target));
1074     }
1075     dt = destination->dt_head;
1076   }
1077   if (NULL == dt)
1078   {
1079     dt = GNUNET_new (struct DestinationChannel);
1080     dt->destination = destination;
1081     GNUNET_CONTAINER_DLL_insert (destination->dt_head,
1082                                  destination->dt_tail,
1083                                  dt);
1084     dt->destination_port = destination_port;
1085   }
1086
1087   /* see if we have an existing channel for this destination */
1088   ts = GNUNET_CONTAINER_multihashmap_get (channel_map,
1089                                           &key);
1090   if (NULL == ts)
1091   {
1092     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1093                 "Creating new channel for key %s\n",
1094                 GNUNET_h2s (&key));
1095     /* need to either use the existing channel from the destination (if still
1096        available) or create a fresh one */
1097     ts = create_channel_to_destination (dt, af);
1098     if (NULL == ts)
1099       return;
1100     /* now bind existing "unbound" channel to our IP/port tuple */
1101     ts->protocol = protocol;
1102     ts->af = af;
1103     if (AF_INET == af)
1104     {
1105       ts->source_ip.v4 = * (const struct in_addr *) source_ip;
1106       ts->destination_ip.v4 = * (const struct in_addr *) destination_ip;
1107     }
1108     else
1109     {
1110       ts->source_ip.v6 = * (const struct in6_addr *) source_ip;
1111       ts->destination_ip.v6 = * (const struct in6_addr *) destination_ip;
1112     }
1113     ts->source_port = source_port;
1114     ts->destination_port = destination_port;
1115     ts->heap_node = GNUNET_CONTAINER_heap_insert (channel_heap,
1116                                                   ts,
1117                                                   GNUNET_TIME_absolute_get ().abs_value_us);
1118     GNUNET_assert (GNUNET_YES ==
1119                    GNUNET_CONTAINER_multihashmap_put (channel_map,
1120                                                       &key,
1121                                                       ts,
1122                                                       GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
1123     GNUNET_STATISTICS_update (stats,
1124                               gettext_noop ("# Active channels"),
1125                               1, GNUNET_NO);
1126     while (GNUNET_CONTAINER_multihashmap_size (channel_map) > max_channel_mappings)
1127       expire_channel (ts);
1128   }
1129   else
1130   {
1131     GNUNET_CONTAINER_heap_update_cost (channel_heap,
1132                                        ts->heap_node,
1133                                        GNUNET_TIME_absolute_get ().abs_value_us);
1134   }
1135   if (NULL == ts->channel)
1136   {
1137     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1138                 "Packet dropped, channel to %s not yet ready (%s)\n",
1139                 print_channel_destination (&ts->destination),
1140                 (NULL == ts->search)
1141                 ? "EXIT search failed"
1142                 : "EXIT search active");
1143     GNUNET_STATISTICS_update (stats,
1144                               gettext_noop ("# Packets dropped (channel not yet online)"),
1145                               1,
1146                               GNUNET_NO);
1147     return;
1148   }
1149
1150   /* send via channel */
1151   switch (protocol)
1152   {
1153   case IPPROTO_UDP:
1154     if (destination->is_service)
1155     {
1156       struct GNUNET_EXIT_UdpServiceMessage *usm;
1157
1158       mlen = sizeof (struct GNUNET_EXIT_UdpServiceMessage) +
1159         payload_length - sizeof (struct GNUNET_TUN_UdpHeader);
1160       if (mlen >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1161       {
1162         GNUNET_break (0);
1163         return;
1164       }
1165       tnq = GNUNET_malloc (sizeof (struct ChannelMessageQueueEntry) + mlen);
1166       tnq->len = mlen;
1167       tnq->msg = &tnq[1];
1168       usm = (struct GNUNET_EXIT_UdpServiceMessage *) &tnq[1];
1169       usm->header.size = htons ((uint16_t) mlen);
1170       usm->header.type = htons (GNUNET_MESSAGE_TYPE_VPN_UDP_TO_SERVICE);
1171       /* if the source port is below 32000, we assume it has a special
1172          meaning; if not, we pick a random port (this is a heuristic) */
1173       usm->source_port = (ntohs (udp->source_port) < 32000) ? udp->source_port : 0;
1174       usm->destination_port = udp->destination_port;
1175       GNUNET_memcpy (&usm[1],
1176                      &udp[1],
1177                      payload_length - sizeof (struct GNUNET_TUN_UdpHeader));
1178     }
1179     else
1180     {
1181       struct GNUNET_EXIT_UdpInternetMessage *uim;
1182       struct in_addr *ip4dst;
1183       struct in6_addr *ip6dst;
1184       void *payload;
1185
1186       mlen = sizeof (struct GNUNET_EXIT_UdpInternetMessage) +
1187         alen + payload_length - sizeof (struct GNUNET_TUN_UdpHeader);
1188       if (mlen >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1189       {
1190         GNUNET_break (0);
1191         return;
1192       }
1193       tnq = GNUNET_malloc (sizeof (struct ChannelMessageQueueEntry) + mlen);
1194       tnq->len = mlen;
1195       tnq->msg = &tnq[1];
1196       uim = (struct GNUNET_EXIT_UdpInternetMessage *) &tnq[1];
1197       uim->header.size = htons ((uint16_t) mlen);
1198       uim->header.type = htons (GNUNET_MESSAGE_TYPE_VPN_UDP_TO_INTERNET);
1199       uim->af = htonl (destination->details.exit_destination.af);
1200       uim->source_port = (ntohs (udp->source_port) < 32000) ? udp->source_port : 0;
1201       uim->destination_port = udp->destination_port;
1202       switch (destination->details.exit_destination.af)
1203       {
1204       case AF_INET:
1205         ip4dst = (struct in_addr *) &uim[1];
1206         *ip4dst = destination->details.exit_destination.ip.v4;
1207         payload = &ip4dst[1];
1208         break;
1209       case AF_INET6:
1210         ip6dst = (struct in6_addr *) &uim[1];
1211         *ip6dst = destination->details.exit_destination.ip.v6;
1212         payload = &ip6dst[1];
1213         break;
1214       default:
1215         GNUNET_assert (0);
1216       }
1217       GNUNET_memcpy (payload,
1218               &udp[1],
1219               payload_length - sizeof (struct GNUNET_TUN_UdpHeader));
1220     }
1221     break;
1222   case IPPROTO_TCP:
1223     if (GNUNET_NO == ts->is_established)
1224     {
1225       if (destination->is_service)
1226       {
1227         struct GNUNET_EXIT_TcpServiceStartMessage *tsm;
1228
1229         mlen = sizeof (struct GNUNET_EXIT_TcpServiceStartMessage) +
1230           payload_length - sizeof (struct GNUNET_TUN_TcpHeader);
1231         if (mlen >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1232         {
1233           GNUNET_break (0);
1234           return;
1235         }
1236         tnq = GNUNET_malloc (sizeof (struct ChannelMessageQueueEntry) + mlen);
1237         tnq->len = mlen;
1238         tnq->msg = &tnq[1];
1239         tsm = (struct  GNUNET_EXIT_TcpServiceStartMessage *) &tnq[1];
1240         tsm->header.size = htons ((uint16_t) mlen);
1241         tsm->header.type = htons (GNUNET_MESSAGE_TYPE_VPN_TCP_TO_SERVICE_START);
1242         tsm->reserved = htonl (0);
1243         tsm->tcp_header = *tcp;
1244         GNUNET_memcpy (&tsm[1],
1245                        &tcp[1],
1246                        payload_length - sizeof (struct GNUNET_TUN_TcpHeader));
1247       }
1248       else
1249       {
1250         struct GNUNET_EXIT_TcpInternetStartMessage *tim;
1251         struct in_addr *ip4dst;
1252         struct in6_addr *ip6dst;
1253         void *payload;
1254
1255         mlen = sizeof (struct GNUNET_EXIT_TcpInternetStartMessage) +
1256           alen + payload_length - sizeof (struct GNUNET_TUN_TcpHeader);
1257         if (mlen >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1258         {
1259           GNUNET_break (0);
1260           return;
1261         }
1262         tnq = GNUNET_malloc (sizeof (struct ChannelMessageQueueEntry) + mlen);
1263         tnq->len = mlen;
1264         tnq->msg = &tnq[1];
1265         tim = (struct  GNUNET_EXIT_TcpInternetStartMessage *) &tnq[1];
1266         tim->header.size = htons ((uint16_t) mlen);
1267         tim->header.type = htons (GNUNET_MESSAGE_TYPE_VPN_TCP_TO_INTERNET_START);
1268         tim->af = htonl (destination->details.exit_destination.af);
1269         tim->tcp_header = *tcp;
1270         switch (destination->details.exit_destination.af)
1271         {
1272         case AF_INET:
1273           ip4dst = (struct in_addr *) &tim[1];
1274           *ip4dst = destination->details.exit_destination.ip.v4;
1275           payload = &ip4dst[1];
1276           break;
1277         case AF_INET6:
1278           ip6dst = (struct in6_addr *) &tim[1];
1279           *ip6dst = destination->details.exit_destination.ip.v6;
1280           payload = &ip6dst[1];
1281           break;
1282         default:
1283           GNUNET_assert (0);
1284         }
1285         GNUNET_memcpy (payload,
1286                 &tcp[1],
1287                 payload_length - sizeof (struct GNUNET_TUN_TcpHeader));
1288       }
1289     }
1290     else
1291     {
1292       struct GNUNET_EXIT_TcpDataMessage *tdm;
1293
1294       mlen = sizeof (struct GNUNET_EXIT_TcpDataMessage) +
1295         payload_length - sizeof (struct GNUNET_TUN_TcpHeader);
1296       if (mlen >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1297       {
1298         GNUNET_break (0);
1299         return;
1300       }
1301       tnq = GNUNET_malloc (sizeof (struct ChannelMessageQueueEntry) + mlen);
1302       tnq->len = mlen;
1303       tnq->msg = &tnq[1];
1304       tdm = (struct  GNUNET_EXIT_TcpDataMessage *) &tnq[1];
1305       tdm->header.size = htons ((uint16_t) mlen);
1306       tdm->header.type = htons (GNUNET_MESSAGE_TYPE_VPN_TCP_DATA_TO_EXIT);
1307       tdm->reserved = htonl (0);
1308       tdm->tcp_header = *tcp;
1309       GNUNET_memcpy (&tdm[1],
1310               &tcp[1],
1311               payload_length - sizeof (struct GNUNET_TUN_TcpHeader));
1312      }
1313     break;
1314   case IPPROTO_ICMP:
1315   case IPPROTO_ICMPV6:
1316     if (destination->is_service)
1317     {
1318       struct GNUNET_EXIT_IcmpServiceMessage *ism;
1319
1320       mlen = sizeof (struct GNUNET_EXIT_IcmpServiceMessage) +
1321         payload_length - sizeof (struct GNUNET_TUN_IcmpHeader);
1322       if (mlen >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1323       {
1324         GNUNET_break (0);
1325         return;
1326       }
1327       tnq = GNUNET_malloc (sizeof (struct ChannelMessageQueueEntry) + mlen);
1328       tnq->msg = &tnq[1];
1329       ism = (struct GNUNET_EXIT_IcmpServiceMessage *) &tnq[1];
1330       ism->header.type = htons (GNUNET_MESSAGE_TYPE_VPN_ICMP_TO_SERVICE);
1331       ism->af = htonl (af); /* need to tell destination ICMP protocol family! */
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 !=
2747       allocate_response_ip (&result_af,
2748                             &addr,
2749                             &v4,
2750                             &v6))
2751   {
2752     GNUNET_SERVER_receive_done (client,
2753                                 GNUNET_SYSERR);
2754     return;
2755   }
2756   send_client_reply (client,
2757                      msg->request_id,
2758                      result_af,
2759                      addr);
2760   if (result_af == AF_UNSPEC)
2761   {
2762     /* failure, we're done */
2763     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2764                 _("Failed to allocate IP address for new destination\n"));
2765     GNUNET_SERVER_receive_done (client, GNUNET_OK);
2766     return;
2767   }
2768
2769   {
2770     char sbuf[INET6_ADDRSTRLEN];
2771
2772     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2773                 "Allocated address %s for redirection to service %s on peer %s\n",
2774                 inet_ntop (result_af,
2775                            addr,
2776                            sbuf,
2777                            sizeof (sbuf)),
2778                 GNUNET_h2s (&msg->service_descriptor),
2779                 GNUNET_i2s (&msg->target));
2780   }
2781
2782   /* setup destination record */
2783   de = GNUNET_new (struct DestinationEntry);
2784   de->is_service = GNUNET_YES;
2785   de->details.service_destination.target = msg->target;
2786   de->details.service_destination.service_descriptor = msg->service_descriptor;
2787   get_destination_key_from_ip (result_af,
2788                                addr,
2789                                &key);
2790   de->key = key;
2791   GNUNET_assert (GNUNET_OK ==
2792                  GNUNET_CONTAINER_multihashmap_put (destination_map,
2793                                                     &key,
2794                                                     de,
2795                                                     GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE));
2796   de->heap_node
2797     = GNUNET_CONTAINER_heap_insert (destination_heap,
2798                                     de,
2799                                     GNUNET_TIME_absolute_ntoh (msg->expiration_time).abs_value_us);
2800   while (GNUNET_CONTAINER_multihashmap_size (destination_map) > max_destination_mappings)
2801     expire_destination (de);
2802
2803   dt = GNUNET_new (struct DestinationChannel);
2804   dt->destination = de;
2805   GNUNET_CONTAINER_DLL_insert (de->dt_head,
2806                                de->dt_tail,
2807                                dt);
2808   /* we're done */
2809   GNUNET_SERVER_receive_done (client,
2810                               GNUNET_OK);
2811 }
2812
2813
2814 /**
2815  * Function called whenever a channel is destroyed.  Should clean up
2816  * any associated state.
2817  *
2818  * @param cls closure (set from #GNUNET_CADET_connect)
2819  * @param channel connection to the other end (henceforth invalid)
2820  * @param channel_ctx place where local state associated
2821  *                   with the channel is stored (our `struct ChannelState`)
2822  */
2823 static void
2824 channel_cleaner (void *cls,
2825                  const struct GNUNET_CADET_Channel *channel,
2826                  void *channel_ctx)
2827 {
2828   struct ChannelState *ts = channel_ctx;
2829
2830   ts->channel = NULL; /* we must not call GNUNET_CADET_channel_destroy() anymore */
2831   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2832               "CADET notified us about death of channel to `%s'\n",
2833               print_channel_destination (&ts->destination));
2834   free_channel_state (ts);
2835 }
2836
2837
2838 /**
2839  * Free memory occupied by an entry in the destination map.
2840  *
2841  * @param cls unused
2842  * @param key unused
2843  * @param value a `struct DestinationEntry *`
2844  * @return #GNUNET_OK (continue to iterate)
2845  */
2846 static int
2847 cleanup_destination (void *cls,
2848                      const struct GNUNET_HashCode *key,
2849                      void *value)
2850 {
2851   struct DestinationEntry *de = value;
2852
2853   free_destination_entry (de);
2854   return GNUNET_OK;
2855 }
2856
2857
2858 /**
2859  * Free memory occupied by an entry in the channel map.
2860  *
2861  * @param cls unused
2862  * @param key unused
2863  * @param value a `struct ChannelState *`
2864  * @return #GNUNET_OK (continue to iterate)
2865  */
2866 static int
2867 cleanup_channel (void *cls,
2868                  const struct GNUNET_HashCode *key,
2869                  void *value)
2870 {
2871   struct ChannelState *ts = value;
2872
2873   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2874               "Tearing down channel to `%s' during cleanup\n",
2875               print_channel_destination (&ts->destination));
2876   free_channel_state (ts);
2877   return GNUNET_OK;
2878 }
2879
2880
2881 /**
2882  * Function scheduled as very last function, cleans up after us
2883  *
2884  * @param cls unused
2885  */
2886 static void
2887 cleanup (void *cls)
2888 {
2889   unsigned int i;
2890
2891   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2892               "VPN is shutting down\n");
2893   if (NULL != destination_map)
2894   {
2895     GNUNET_CONTAINER_multihashmap_iterate (destination_map,
2896                                            &cleanup_destination,
2897                                            NULL);
2898     GNUNET_CONTAINER_multihashmap_destroy (destination_map);
2899     destination_map = NULL;
2900   }
2901   if (NULL != destination_heap)
2902   {
2903     GNUNET_CONTAINER_heap_destroy (destination_heap);
2904     destination_heap = NULL;
2905   }
2906   if (NULL != channel_map)
2907   {
2908     GNUNET_CONTAINER_multihashmap_iterate (channel_map,
2909                                            &cleanup_channel,
2910                                            NULL);
2911     GNUNET_CONTAINER_multihashmap_destroy (channel_map);
2912     channel_map = NULL;
2913   }
2914   if (NULL != channel_heap)
2915   {
2916     GNUNET_CONTAINER_heap_destroy (channel_heap);
2917     channel_heap = NULL;
2918   }
2919   if (NULL != cadet_handle)
2920   {
2921     GNUNET_CADET_disconnect (cadet_handle);
2922     cadet_handle = NULL;
2923   }
2924   if (NULL != helper_handle)
2925   {
2926     GNUNET_HELPER_kill (helper_handle, GNUNET_NO);
2927     GNUNET_HELPER_wait (helper_handle);
2928     helper_handle = NULL;
2929   }
2930   if (NULL != nc)
2931   {
2932     GNUNET_SERVER_notification_context_destroy (nc);
2933     nc = NULL;
2934   }
2935   if (NULL != stats)
2936   {
2937     GNUNET_STATISTICS_destroy (stats, GNUNET_NO);
2938     stats = NULL;
2939   }
2940   for (i=0;i<5;i++)
2941     GNUNET_free_non_null (vpn_argv[i]);
2942 }
2943
2944
2945 /**
2946  * Main function that will be run by the scheduler.
2947  *
2948  * @param cls closure
2949  * @param server the initialized server
2950  * @param cfg_ configuration
2951  */
2952 static void
2953 run (void *cls,
2954      struct GNUNET_SERVER_Handle *server,
2955      const struct GNUNET_CONFIGURATION_Handle *cfg_)
2956 {
2957   static const struct GNUNET_SERVER_MessageHandler service_handlers[] = {
2958     /* callback, cls, type, size */
2959     { &service_redirect_to_ip, NULL, GNUNET_MESSAGE_TYPE_VPN_CLIENT_REDIRECT_TO_IP, 0},
2960     { &service_redirect_to_service, NULL,
2961      GNUNET_MESSAGE_TYPE_VPN_CLIENT_REDIRECT_TO_SERVICE,
2962      sizeof (struct RedirectToServiceRequestMessage) },
2963     {NULL, NULL, 0, 0}
2964   };
2965   static const struct GNUNET_CADET_MessageHandler cadet_handlers[] = {
2966     { &receive_udp_back, GNUNET_MESSAGE_TYPE_VPN_UDP_REPLY, 0},
2967     { &receive_tcp_back, GNUNET_MESSAGE_TYPE_VPN_TCP_DATA_TO_VPN, 0},
2968     { &receive_icmp_back, GNUNET_MESSAGE_TYPE_VPN_ICMP_TO_VPN, 0},
2969     {NULL, 0, 0}
2970   };
2971   char *ifname;
2972   char *ipv6addr;
2973   char *ipv6prefix_s;
2974   char *ipv4addr;
2975   char *ipv4mask;
2976   struct in_addr v4;
2977   struct in6_addr v6;
2978   char *binary;
2979
2980   binary = GNUNET_OS_get_libexec_binary_path ("gnunet-helper-vpn");
2981
2982   if (GNUNET_YES !=
2983       GNUNET_OS_check_helper_binary (binary,
2984                                      GNUNET_YES,
2985                                      "-d gnunet-vpn - - 169.1.3.3.7 255.255.255.0")) //ipv4 only please!
2986   {
2987     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2988                 "`%s' is not SUID, refusing to run.\n",
2989                 "gnunet-helper-vpn");
2990     GNUNET_free (binary);
2991     global_ret = 1;
2992     /* we won't "really" exit here, as the 'service' is still running;
2993        however, as no handlers are registered, the service won't do
2994        anything either */
2995     return;
2996   }
2997   GNUNET_free (binary);
2998   cfg = cfg_;
2999   stats = GNUNET_STATISTICS_create ("vpn", cfg);
3000   if (GNUNET_OK !=
3001       GNUNET_CONFIGURATION_get_value_number (cfg,
3002                                              "VPN",
3003                                              "MAX_MAPPING",
3004                                              &max_destination_mappings))
3005     max_destination_mappings = 200;
3006   if (GNUNET_OK !=
3007       GNUNET_CONFIGURATION_get_value_number (cfg,
3008                                              "VPN",
3009                                              "MAX_TUNNELS",
3010                                              &max_channel_mappings))
3011     max_channel_mappings = 200;
3012
3013   destination_map = GNUNET_CONTAINER_multihashmap_create (max_destination_mappings * 2, GNUNET_NO);
3014   destination_heap = GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN);
3015   channel_map = GNUNET_CONTAINER_multihashmap_create (max_channel_mappings * 2, GNUNET_NO);
3016   channel_heap = GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN);
3017
3018
3019   vpn_argv[0] = GNUNET_strdup ("vpn-gnunet");
3020   if (GNUNET_SYSERR ==
3021       GNUNET_CONFIGURATION_get_value_string (cfg, "VPN", "IFNAME", &ifname))
3022   {
3023     GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, "VPN", "IFNAME");
3024     GNUNET_SCHEDULER_shutdown ();
3025     return;
3026   }
3027   vpn_argv[1] = ifname;
3028   ipv6addr = NULL;
3029   if (GNUNET_OK == GNUNET_NETWORK_test_pf (PF_INET6))
3030   {
3031     if ( (GNUNET_SYSERR ==
3032           GNUNET_CONFIGURATION_get_value_string (cfg, "VPN", "IPV6ADDR",
3033                                                  &ipv6addr) ||
3034           (1 != inet_pton (AF_INET6, ipv6addr, &v6))) )
3035     {
3036       GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, "VPN", "IPV6ADDR",
3037                                  _("Must specify valid IPv6 address"));
3038       GNUNET_SCHEDULER_shutdown ();
3039       GNUNET_free_non_null (ipv6addr);
3040       return;
3041     }
3042     vpn_argv[2] = ipv6addr;
3043     ipv6prefix_s = NULL;
3044     if (GNUNET_SYSERR ==
3045         GNUNET_CONFIGURATION_get_value_string (cfg, "VPN", "IPV6PREFIX",
3046                                                &ipv6prefix_s))
3047     {
3048       GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, "VPN", "IPV6PREFIX");
3049       GNUNET_SCHEDULER_shutdown ();
3050       GNUNET_free_non_null (ipv6prefix_s);
3051       return;
3052     }
3053     vpn_argv[3] = ipv6prefix_s;
3054     if ( (GNUNET_OK !=
3055           GNUNET_CONFIGURATION_get_value_number (cfg, "VPN",
3056                                                  "IPV6PREFIX",
3057                                                  &ipv6prefix)) ||
3058          (ipv6prefix >= 127) )
3059     {
3060       GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, "VPN", "IPV4MASK",
3061                                  _("Must specify valid IPv6 mask"));
3062       GNUNET_SCHEDULER_shutdown ();
3063       return;
3064     }
3065   }
3066   else
3067   {
3068     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
3069                 _("IPv6 support disabled as this system does not support IPv6\n"));
3070     vpn_argv[2] = GNUNET_strdup ("-");
3071     vpn_argv[3] = GNUNET_strdup ("-");
3072   }
3073   if (GNUNET_OK == GNUNET_NETWORK_test_pf (PF_INET))
3074   {
3075     ipv4addr = NULL;
3076     if ( (GNUNET_SYSERR ==
3077           GNUNET_CONFIGURATION_get_value_string (cfg, "vpn", "IPV4ADDR",
3078                                                  &ipv4addr) ||
3079           (1 != inet_pton (AF_INET, ipv4addr, &v4))) )
3080     {
3081       GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, "VPN", "IPV4ADDR",
3082                                  _("Must specify valid IPv4 address"));
3083       GNUNET_SCHEDULER_shutdown ();
3084       GNUNET_free_non_null (ipv4addr);
3085       return;
3086     }
3087     vpn_argv[4] = ipv4addr;
3088     ipv4mask = NULL;
3089     if ( (GNUNET_SYSERR ==
3090           GNUNET_CONFIGURATION_get_value_string (cfg, "vpn", "IPV4MASK",
3091                                                  &ipv4mask) ||
3092           (1 != inet_pton (AF_INET, ipv4mask, &v4))) )
3093     {
3094       GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, "VPN", "IPV4MASK",
3095                                  _("Must specify valid IPv4 mask"));
3096       GNUNET_SCHEDULER_shutdown ();
3097       GNUNET_free_non_null (ipv4mask);
3098       return;
3099     }
3100     vpn_argv[5] = ipv4mask;
3101   }
3102   else
3103   {
3104     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
3105                 _("IPv4 support disabled as this system does not support IPv4\n"));
3106     vpn_argv[4] = GNUNET_strdup ("-");
3107     vpn_argv[5] = GNUNET_strdup ("-");
3108   }
3109   vpn_argv[6] = NULL;
3110
3111   cadet_handle
3112     = GNUNET_CADET_connect (cfg_,
3113                             NULL,
3114                             &channel_cleaner,
3115                             cadet_handlers);
3116     // FIXME never opens ports???
3117   helper_handle = GNUNET_HELPER_start (GNUNET_NO,
3118                                        "gnunet-helper-vpn", vpn_argv,
3119                                        &message_token, NULL, NULL);
3120   nc = GNUNET_SERVER_notification_context_create (server, 1);
3121   GNUNET_SERVER_add_handlers (server, service_handlers);
3122   GNUNET_SCHEDULER_add_shutdown (&cleanup,
3123                                  NULL);
3124 }
3125
3126
3127 /**
3128  * The main function of the VPN service.
3129  *
3130  * @param argc number of arguments from the command line
3131  * @param argv command line arguments
3132  * @return 0 ok, 1 on error
3133  */
3134 int
3135 main (int argc, char *const *argv)
3136 {
3137   return (GNUNET_OK ==
3138           GNUNET_SERVICE_run (argc, argv, "vpn",
3139                               GNUNET_SERVICE_OPTION_NONE,
3140                               &run, NULL)) ? global_ret : 1;
3141 }
3142
3143 /* end of gnunet-service-vpn.c */