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