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