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