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