notify cadet when we are done - for flow control and to get next packet
[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   GNUNET_CADET_receive_done (channel);
2080   return GNUNET_OK;
2081 }
2082
2083
2084 /**
2085  * We got a UDP packet back from the CADET channel.  Pass it on to the
2086  * local virtual interface via the helper.
2087  *
2088  * @param cls closure, NULL
2089  * @param channel connection to the other end
2090  * @param channel_ctx pointer to our 'struct ChannelState *'
2091  * @param message the actual message
2092  * @return #GNUNET_OK to keep the connection open,
2093  *         #GNUNET_SYSERR to close it (signal serious error)
2094  */
2095 static int
2096 receive_udp_back (void *cls,
2097                   struct GNUNET_CADET_Channel *channel,
2098                   void **channel_ctx,
2099                   const struct GNUNET_MessageHeader *message)
2100 {
2101   struct ChannelState *ts = *channel_ctx;
2102   const struct GNUNET_EXIT_UdpReplyMessage *reply;
2103   size_t mlen;
2104
2105   GNUNET_STATISTICS_update (stats,
2106                             gettext_noop ("# UDP packets received from cadet"),
2107                             1, GNUNET_NO);
2108   mlen = ntohs (message->size);
2109   if (mlen < sizeof (struct GNUNET_EXIT_UdpReplyMessage))
2110   {
2111     GNUNET_break_op (0);
2112     return GNUNET_SYSERR;
2113   }
2114   if (NULL == ts->heap_node)
2115   {
2116     GNUNET_break_op (0);
2117     return GNUNET_SYSERR;
2118   }
2119   if (AF_UNSPEC == ts->af)
2120   {
2121     GNUNET_break_op (0);
2122     return GNUNET_SYSERR;
2123   }
2124   reply = (const struct GNUNET_EXIT_UdpReplyMessage *) message;
2125   mlen -= sizeof (struct GNUNET_EXIT_UdpReplyMessage);
2126   {
2127     char sbuf[INET6_ADDRSTRLEN];
2128     char dbuf[INET6_ADDRSTRLEN];
2129
2130     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2131                 "Received UDP reply from cadet, sending %u bytes from %s:%u -> %s:%u via TUN\n",
2132                 (unsigned int) mlen,
2133                 inet_ntop (ts->af, &ts->destination_ip, sbuf, sizeof (sbuf)),
2134                 ts->destination_port,
2135                 inet_ntop (ts->af, &ts->source_ip, dbuf, sizeof (dbuf)),
2136                 ts->source_port);
2137   }
2138   switch (ts->af)
2139   {
2140   case AF_INET:
2141     {
2142       size_t size = sizeof (struct GNUNET_TUN_IPv4Header)
2143         + sizeof (struct GNUNET_TUN_UdpHeader)
2144         + sizeof (struct GNUNET_MessageHeader) +
2145         sizeof (struct GNUNET_TUN_Layer2PacketHeader) +
2146         mlen;
2147       {
2148         char buf[size] GNUNET_ALIGN;
2149         struct GNUNET_MessageHeader *msg = (struct GNUNET_MessageHeader *) buf;
2150         struct GNUNET_TUN_Layer2PacketHeader *tun = (struct GNUNET_TUN_Layer2PacketHeader*) &msg[1];
2151         struct GNUNET_TUN_IPv4Header *ipv4 = (struct GNUNET_TUN_IPv4Header *) &tun[1];
2152         struct GNUNET_TUN_UdpHeader *udp = (struct GNUNET_TUN_UdpHeader *) &ipv4[1];
2153         msg->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
2154         msg->size = htons (size);
2155         tun->flags = htons (0);
2156         tun->proto = htons (ETH_P_IPV4);
2157         GNUNET_TUN_initialize_ipv4_header (ipv4,
2158                                            IPPROTO_UDP,
2159                                            sizeof (struct GNUNET_TUN_UdpHeader) + mlen,
2160                                            &ts->destination_ip.v4,
2161                                            &ts->source_ip.v4);
2162         if (0 == ntohs (reply->source_port))
2163           udp->source_port = htons (ts->destination_port);
2164         else
2165           udp->source_port = reply->source_port;
2166         if (0 == ntohs (reply->destination_port))
2167           udp->destination_port = htons (ts->source_port);
2168         else
2169           udp->destination_port = reply->destination_port;
2170         udp->len = htons (mlen + sizeof (struct GNUNET_TUN_UdpHeader));
2171         GNUNET_TUN_calculate_udp4_checksum (ipv4,
2172                                             udp,
2173                                             &reply[1],
2174                                             mlen);
2175         memcpy (&udp[1],
2176                 &reply[1],
2177                 mlen);
2178         (void) GNUNET_HELPER_send (helper_handle,
2179                                    msg,
2180                                    GNUNET_YES,
2181                                    NULL, NULL);
2182       }
2183     }
2184     break;
2185   case AF_INET6:
2186     {
2187       size_t size = sizeof (struct GNUNET_TUN_IPv6Header)
2188         + sizeof (struct GNUNET_TUN_UdpHeader)
2189         + sizeof (struct GNUNET_MessageHeader) +
2190         sizeof (struct GNUNET_TUN_Layer2PacketHeader) +
2191         mlen;
2192       {
2193         char buf[size] GNUNET_ALIGN;
2194         struct GNUNET_MessageHeader *msg = (struct GNUNET_MessageHeader *) buf;
2195         struct GNUNET_TUN_Layer2PacketHeader *tun = (struct GNUNET_TUN_Layer2PacketHeader*) &msg[1];
2196         struct GNUNET_TUN_IPv6Header *ipv6 = (struct GNUNET_TUN_IPv6Header *) &tun[1];
2197         struct GNUNET_TUN_UdpHeader *udp = (struct GNUNET_TUN_UdpHeader *) &ipv6[1];
2198         msg->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
2199         msg->size = htons (size);
2200         tun->flags = htons (0);
2201         tun->proto = htons (ETH_P_IPV6);
2202         GNUNET_TUN_initialize_ipv6_header (ipv6,
2203                                            IPPROTO_UDP,
2204                                            sizeof (struct GNUNET_TUN_UdpHeader) + mlen,
2205                                            &ts->destination_ip.v6,
2206                                            &ts->source_ip.v6);
2207         if (0 == ntohs (reply->source_port))
2208           udp->source_port = htons (ts->destination_port);
2209         else
2210           udp->source_port = reply->source_port;
2211         if (0 == ntohs (reply->destination_port))
2212           udp->destination_port = htons (ts->source_port);
2213         else
2214           udp->destination_port = reply->destination_port;
2215         udp->len = htons (mlen + sizeof (struct GNUNET_TUN_UdpHeader));
2216         GNUNET_TUN_calculate_udp6_checksum (ipv6,
2217                                             udp,
2218                                             &reply[1], mlen);
2219         memcpy (&udp[1],
2220                 &reply[1],
2221                 mlen);
2222         (void) GNUNET_HELPER_send (helper_handle,
2223                                    msg,
2224                                    GNUNET_YES,
2225                                    NULL, NULL);
2226       }
2227     }
2228     break;
2229   default:
2230     GNUNET_assert (0);
2231   }
2232   GNUNET_CONTAINER_heap_update_cost (channel_heap,
2233                                      ts->heap_node,
2234                                      GNUNET_TIME_absolute_get ().abs_value_us);
2235   GNUNET_CADET_receive_done (channel);
2236   return GNUNET_OK;
2237 }
2238
2239
2240 /**
2241  * We got a TCP packet back from the CADET channel.  Pass it on to the
2242  * local virtual interface via the helper.
2243  *
2244  * @param cls closure, NULL
2245  * @param channel connection to the other end
2246  * @param channel_ctx pointer to our `struct ChannelState *`
2247  * @param message the actual message
2248  * @return #GNUNET_OK to keep the connection open,
2249  *         #GNUNET_SYSERR to close it (signal serious error)
2250  */
2251 static int
2252 receive_tcp_back (void *cls,
2253                   struct GNUNET_CADET_Channel *channel,
2254                   void **channel_ctx,
2255                   const struct GNUNET_MessageHeader *message)
2256 {
2257   struct ChannelState *ts = *channel_ctx;
2258   const struct GNUNET_EXIT_TcpDataMessage *data;
2259   size_t mlen;
2260
2261   GNUNET_STATISTICS_update (stats,
2262                             gettext_noop ("# TCP packets received from cadet"),
2263                             1, GNUNET_NO);
2264   mlen = ntohs (message->size);
2265   if (mlen < sizeof (struct GNUNET_EXIT_TcpDataMessage))
2266   {
2267     GNUNET_break_op (0);
2268     return GNUNET_SYSERR;
2269   }
2270   if (NULL == ts->heap_node)
2271   {
2272     GNUNET_break_op (0);
2273     return GNUNET_SYSERR;
2274   }
2275   data = (const struct GNUNET_EXIT_TcpDataMessage *) message;
2276   mlen -= sizeof (struct GNUNET_EXIT_TcpDataMessage);
2277   {
2278     char sbuf[INET6_ADDRSTRLEN];
2279     char dbuf[INET6_ADDRSTRLEN];
2280
2281     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2282                 "Received TCP reply from cadet, sending %u bytes from %s:%u -> %s:%u via TUN\n",
2283                 (unsigned int) mlen,
2284                 inet_ntop (ts->af, &ts->destination_ip, sbuf, sizeof (sbuf)),
2285                 ts->destination_port,
2286                 inet_ntop (ts->af, &ts->source_ip, dbuf, sizeof (dbuf)),
2287                 ts->source_port);
2288   }
2289   if (data->tcp_header.off * 4 < sizeof (struct GNUNET_TUN_TcpHeader))
2290   {
2291     GNUNET_break_op (0);
2292     return GNUNET_SYSERR;
2293   }
2294   switch (ts->af)
2295   {
2296   case AF_INET:
2297     {
2298       size_t size = sizeof (struct GNUNET_TUN_IPv4Header)
2299         + sizeof (struct GNUNET_TUN_TcpHeader)
2300         + sizeof (struct GNUNET_MessageHeader) +
2301         sizeof (struct GNUNET_TUN_Layer2PacketHeader) +
2302         mlen;
2303       {
2304         char buf[size] GNUNET_ALIGN;
2305         struct GNUNET_MessageHeader *msg = (struct GNUNET_MessageHeader *) buf;
2306         struct GNUNET_TUN_Layer2PacketHeader *tun = (struct GNUNET_TUN_Layer2PacketHeader*) &msg[1];
2307         struct GNUNET_TUN_IPv4Header *ipv4 = (struct GNUNET_TUN_IPv4Header *) &tun[1];
2308         struct GNUNET_TUN_TcpHeader *tcp = (struct GNUNET_TUN_TcpHeader *) &ipv4[1];
2309         msg->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
2310         msg->size = htons (size);
2311         tun->flags = htons (0);
2312         tun->proto = htons (ETH_P_IPV4);
2313         GNUNET_TUN_initialize_ipv4_header (ipv4,
2314                                            IPPROTO_TCP,
2315                                            sizeof (struct GNUNET_TUN_TcpHeader) + mlen,
2316                                            &ts->destination_ip.v4,
2317                                            &ts->source_ip.v4);
2318         *tcp = data->tcp_header;
2319         tcp->source_port = htons (ts->destination_port);
2320         tcp->destination_port = htons (ts->source_port);
2321         GNUNET_TUN_calculate_tcp4_checksum (ipv4,
2322                                             tcp,
2323                                             &data[1],
2324                                             mlen);
2325         memcpy (&tcp[1],
2326                 &data[1],
2327                 mlen);
2328         (void) GNUNET_HELPER_send (helper_handle,
2329                                    msg,
2330                                    GNUNET_YES,
2331                                    NULL, NULL);
2332       }
2333     }
2334     break;
2335   case AF_INET6:
2336     {
2337       size_t size = sizeof (struct GNUNET_TUN_IPv6Header)
2338         + sizeof (struct GNUNET_TUN_TcpHeader)
2339         + sizeof (struct GNUNET_MessageHeader) +
2340         sizeof (struct GNUNET_TUN_Layer2PacketHeader) +
2341         mlen;
2342       {
2343         char buf[size] GNUNET_ALIGN;
2344         struct GNUNET_MessageHeader *msg = (struct GNUNET_MessageHeader *) buf;
2345         struct GNUNET_TUN_Layer2PacketHeader *tun = (struct GNUNET_TUN_Layer2PacketHeader*) &msg[1];
2346         struct GNUNET_TUN_IPv6Header *ipv6 = (struct GNUNET_TUN_IPv6Header *) &tun[1];
2347         struct GNUNET_TUN_TcpHeader *tcp = (struct GNUNET_TUN_TcpHeader *) &ipv6[1];
2348         msg->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
2349         msg->size = htons (size);
2350         tun->flags = htons (0);
2351         tun->proto = htons (ETH_P_IPV6);
2352         GNUNET_TUN_initialize_ipv6_header (ipv6,
2353                                            IPPROTO_TCP,
2354                                            sizeof (struct GNUNET_TUN_TcpHeader) + mlen,
2355                                            &ts->destination_ip.v6,
2356                                            &ts->source_ip.v6);
2357         *tcp = data->tcp_header;
2358         tcp->source_port = htons (ts->destination_port);
2359         tcp->destination_port = htons (ts->source_port);
2360         GNUNET_TUN_calculate_tcp6_checksum (ipv6,
2361                                             tcp,
2362                                             &data[1],
2363                                             mlen);
2364         memcpy (&tcp[1],
2365                 &data[1],
2366                 mlen);
2367         (void) GNUNET_HELPER_send (helper_handle,
2368                                    msg,
2369                                    GNUNET_YES,
2370                                    NULL, NULL);
2371       }
2372     }
2373     break;
2374   }
2375   GNUNET_CONTAINER_heap_update_cost (channel_heap,
2376                                      ts->heap_node,
2377                                      GNUNET_TIME_absolute_get ().abs_value_us);
2378   GNUNET_CADET_receive_done (channel);
2379   return GNUNET_OK;
2380 }
2381
2382
2383 /**
2384  * Allocate an IPv4 address from the range of the channel
2385  * for a new redirection.
2386  *
2387  * @param v4 where to store the address
2388  * @return #GNUNET_OK on success,
2389  *         #GNUNET_SYSERR on error
2390  */
2391 static int
2392 allocate_v4_address (struct in_addr *v4)
2393 {
2394   const char *ipv4addr = vpn_argv[4];
2395   const char *ipv4mask = vpn_argv[5];
2396   struct in_addr addr;
2397   struct in_addr mask;
2398   struct in_addr rnd;
2399   struct GNUNET_HashCode key;
2400   unsigned int tries;
2401
2402   GNUNET_assert (1 == inet_pton (AF_INET, ipv4addr, &addr));
2403   GNUNET_assert (1 == inet_pton (AF_INET, ipv4mask, &mask));
2404   /* Given 192.168.0.1/255.255.0.0, we want a mask
2405      of '192.168.255.255', thus:  */
2406   mask.s_addr = addr.s_addr | ~mask.s_addr;
2407   tries = 0;
2408   do
2409     {
2410       tries++;
2411       if (tries > 16)
2412       {
2413         GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
2414                     _("Failed to find unallocated IPv4 address in VPN's range\n"));
2415         return GNUNET_SYSERR;
2416       }
2417       /* Pick random IPv4 address within the subnet, except 'addr' or 'mask' itself */
2418       rnd.s_addr = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
2419                                              UINT32_MAX);
2420       v4->s_addr = (addr.s_addr | rnd.s_addr) & mask.s_addr;
2421       get_destination_key_from_ip (AF_INET,
2422                                    v4,
2423                                    &key);
2424     }
2425   while ( (GNUNET_YES ==
2426            GNUNET_CONTAINER_multihashmap_contains (destination_map,
2427                                                    &key)) ||
2428           (v4->s_addr == addr.s_addr) ||
2429           (v4->s_addr == mask.s_addr) );
2430   return GNUNET_OK;
2431 }
2432
2433
2434 /**
2435  * Allocate an IPv6 address from the range of the channel
2436  * for a new redirection.
2437  *
2438  * @param v6 where to store the address
2439  * @return #GNUNET_OK on success,
2440  *         #GNUNET_SYSERR on error
2441  */
2442 static int
2443 allocate_v6_address (struct in6_addr *v6)
2444 {
2445   const char *ipv6addr = vpn_argv[2];
2446   struct in6_addr addr;
2447   struct in6_addr mask;
2448   struct in6_addr rnd;
2449   int i;
2450   struct GNUNET_HashCode key;
2451   unsigned int tries;
2452
2453   GNUNET_assert (1 == inet_pton (AF_INET6, ipv6addr, &addr));
2454   GNUNET_assert (ipv6prefix < 128);
2455   /* Given ABCD::/96, we want a mask of 'ABCD::FFFF:FFFF,
2456      thus: */
2457   mask = addr;
2458   for (i=127;i>=ipv6prefix;i--)
2459     mask.s6_addr[i / 8] |= (1 << (i % 8));
2460
2461   /* Pick random IPv6 address within the subnet, except 'addr' or 'mask' itself */
2462   tries = 0;
2463   do
2464     {
2465       tries++;
2466       if (tries > 16)
2467         {
2468           GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
2469                       _("Failed to find unallocated IPv6 address in VPN's range\n"));
2470           return GNUNET_SYSERR;
2471
2472         }
2473       for (i=0;i<16;i++)
2474         {
2475           rnd.s6_addr[i] = (unsigned char) GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
2476                                                                      256);
2477           v6->s6_addr[i]
2478             = (addr.s6_addr[i] | rnd.s6_addr[i]) & mask.s6_addr[i];
2479         }
2480       get_destination_key_from_ip (AF_INET6,
2481                                    v6,
2482                                    &key);
2483     }
2484   while ( (GNUNET_YES ==
2485            GNUNET_CONTAINER_multihashmap_contains (destination_map,
2486                                                    &key)) ||
2487           (0 == memcmp (v6,
2488                         &addr,
2489                         sizeof (struct in6_addr))) ||
2490           (0 == memcmp (v6,
2491                         &mask,
2492                         sizeof (struct in6_addr))) );
2493   return GNUNET_OK;
2494 }
2495
2496
2497 /**
2498  * Free resources occupied by a destination entry.
2499  *
2500  * @param de entry to free
2501  */
2502 static void
2503 free_destination_entry (struct DestinationEntry *de)
2504 {
2505   struct DestinationChannel *dt;
2506
2507   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2508               "Cleaning up destination entry `%s'\n",
2509               print_channel_destination (de));
2510   GNUNET_STATISTICS_update (stats,
2511                             gettext_noop ("# Active destinations"),
2512                             -1, GNUNET_NO);
2513   while (NULL != (dt = de->dt_head))
2514   {
2515     GNUNET_CONTAINER_DLL_remove (de->dt_head,
2516                                  de->dt_tail,
2517                                  dt);
2518     if (NULL != dt->ts)
2519     {
2520       free_channel_state (dt->ts);
2521       GNUNET_assert (NULL == dt->ts);
2522     }
2523     GNUNET_free (dt);
2524   }
2525   if (NULL != de->heap_node)
2526   {
2527     GNUNET_CONTAINER_heap_remove_node (de->heap_node);
2528     de->heap_node = NULL;
2529     GNUNET_assert (GNUNET_YES ==
2530                    GNUNET_CONTAINER_multihashmap_remove (destination_map,
2531                                                          &de->key,
2532                                                          de));
2533   }
2534   GNUNET_free (de);
2535 }
2536
2537
2538 /**
2539  * We have too many active destinations.  Clean up the oldest destination.
2540  *
2541  * @param except destination that must NOT be cleaned up, even if it is the oldest
2542  */
2543 static void
2544 expire_destination (struct DestinationEntry *except)
2545 {
2546   struct DestinationEntry *de;
2547
2548   de = GNUNET_CONTAINER_heap_peek (destination_heap);
2549   GNUNET_assert (NULL != de);
2550   if (except == de)
2551     return; /* can't do this */
2552   free_destination_entry (de);
2553 }
2554
2555
2556 /**
2557  * Allocate an IP address for the response.
2558  *
2559  * @param result_af desired address family; set to the actual
2560  *        address family; can initially be AF_UNSPEC if there
2561  *        is no preference; will be set to AF_UNSPEC if the
2562  *        allocation failed
2563  * @param addr set to either v4 or v6 depending on which
2564  *         storage location was used; set to NULL if allocation failed
2565  * @param v4 storage space for an IPv4 address
2566  * @param v6 storage space for an IPv6 address
2567  * @return #GNUNET_OK normally, #GNUNET_SYSERR if `* result_af` was
2568  *         an unsupported address family (not AF_INET, AF_INET6 or AF_UNSPEC)
2569  */
2570 static int
2571 allocate_response_ip (int *result_af,
2572                       void **addr,
2573                       struct in_addr *v4,
2574                       struct in6_addr *v6)
2575 {
2576   *addr = NULL;
2577   switch (*result_af)
2578   {
2579   case AF_INET:
2580     if (GNUNET_OK !=
2581         allocate_v4_address (v4))
2582       *result_af = AF_UNSPEC;
2583     else
2584       *addr = v4;
2585     break;
2586   case AF_INET6:
2587     if (GNUNET_OK !=
2588         allocate_v6_address (v6))
2589       *result_af = AF_UNSPEC;
2590     else
2591       *addr = v6;
2592     break;
2593   case AF_UNSPEC:
2594     if (GNUNET_OK ==
2595         allocate_v4_address (v4))
2596     {
2597       *addr = v4;
2598       *result_af = AF_INET;
2599     }
2600     else if (GNUNET_OK ==
2601         allocate_v6_address (v6))
2602     {
2603       *addr = v6;
2604       *result_af = AF_INET6;
2605     }
2606     break;
2607   default:
2608     GNUNET_break (0);
2609     return GNUNET_SYSERR;
2610   }
2611   return GNUNET_OK;
2612 }
2613
2614
2615 /**
2616  * A client asks us to setup a redirection via some exit node to a
2617  * particular IP.  Setup the redirection and give the client the
2618  * allocated IP.
2619  *
2620  * @param cls unused
2621  * @param client requesting client
2622  * @param message redirection request (a `struct RedirectToIpRequestMessage`)
2623  */
2624 static void
2625 service_redirect_to_ip (void *cls,
2626                         struct GNUNET_SERVER_Client *client,
2627                         const struct GNUNET_MessageHeader *message)
2628 {
2629   size_t mlen;
2630   size_t alen;
2631   const struct RedirectToIpRequestMessage *msg;
2632   int addr_af;
2633   int result_af;
2634   struct in_addr v4;
2635   struct in6_addr v6;
2636   void *addr;
2637   struct DestinationEntry *de;
2638   struct GNUNET_HashCode key;
2639
2640   /* validate and parse request */
2641   mlen = ntohs (message->size);
2642   if (mlen < sizeof (struct RedirectToIpRequestMessage))
2643   {
2644     GNUNET_break (0);
2645     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2646     return;
2647   }
2648   alen = mlen - sizeof (struct RedirectToIpRequestMessage);
2649   msg = (const struct RedirectToIpRequestMessage *) message;
2650   addr_af = (int) htonl (msg->addr_af);
2651   switch (addr_af)
2652   {
2653   case AF_INET:
2654     if (alen != sizeof (struct in_addr))
2655     {
2656       GNUNET_break (0);
2657       GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2658       return;
2659     }
2660     break;
2661   case AF_INET6:
2662     if (alen != sizeof (struct in6_addr))
2663     {
2664       GNUNET_break (0);
2665       GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2666       return;
2667     }
2668     break;
2669   default:
2670     GNUNET_break (0);
2671     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2672     return;
2673   }
2674
2675   /* allocate response IP */
2676   result_af = (int) htonl (msg->result_af);
2677   if (GNUNET_OK != allocate_response_ip (&result_af,
2678                                          &addr,
2679                                          &v4, &v6))
2680   {
2681     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2682     return;
2683   }
2684   /* send reply with our IP address */
2685   send_client_reply (client,
2686                      msg->request_id,
2687                      result_af,
2688                      addr);
2689   if (result_af == AF_UNSPEC)
2690   {
2691     /* failure, we're done */
2692     GNUNET_SERVER_receive_done (client, GNUNET_OK);
2693     return;
2694   }
2695
2696   {
2697     char sbuf[INET6_ADDRSTRLEN];
2698     char dbuf[INET6_ADDRSTRLEN];
2699
2700     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2701                 "Allocated address %s for redirection via exit to %s\n",
2702                 inet_ntop (result_af, addr, sbuf, sizeof (sbuf)),
2703                 inet_ntop (addr_af,
2704                            &msg[1], dbuf, sizeof (dbuf)));
2705   }
2706
2707   /* setup destination record */
2708   de = GNUNET_new (struct DestinationEntry);
2709   de->is_service = GNUNET_NO;
2710   de->details.exit_destination.af = addr_af;
2711   memcpy (&de->details.exit_destination.ip,
2712           &msg[1],
2713           alen);
2714   get_destination_key_from_ip (result_af,
2715                                addr,
2716                                &key);
2717   de->key = key;
2718   GNUNET_assert (GNUNET_OK ==
2719                  GNUNET_CONTAINER_multihashmap_put (destination_map,
2720                                                     &key,
2721                                                     de,
2722                                                     GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE));
2723   de->heap_node = GNUNET_CONTAINER_heap_insert (destination_heap,
2724                                                 de,
2725                                                 GNUNET_TIME_absolute_ntoh (msg->expiration_time).abs_value_us);
2726   GNUNET_STATISTICS_update (stats,
2727                             gettext_noop ("# Active destinations"),
2728                             1, GNUNET_NO);
2729   while (GNUNET_CONTAINER_multihashmap_size (destination_map) > max_destination_mappings)
2730     expire_destination (de);
2731   GNUNET_SERVER_receive_done (client, GNUNET_OK);
2732 }
2733
2734
2735 /**
2736  * A client asks us to setup a redirection to a particular peer
2737  * offering a service.  Setup the redirection and give the client the
2738  * allocated IP.
2739  *
2740  * @param cls unused
2741  * @param client requesting client
2742  * @param message redirection request (a `struct RedirectToPeerRequestMessage`)
2743  */
2744 static void
2745 service_redirect_to_service (void *cls,
2746                              struct GNUNET_SERVER_Client *client,
2747                              const struct GNUNET_MessageHeader *message)
2748 {
2749   const struct RedirectToServiceRequestMessage *msg;
2750   int result_af;
2751   struct in_addr v4;
2752   struct in6_addr v6;
2753   void *addr;
2754   struct DestinationEntry *de;
2755   struct GNUNET_HashCode key;
2756   struct ChannelState *ts;
2757   struct DestinationChannel *dt;
2758
2759   /*  parse request */
2760   msg = (const struct RedirectToServiceRequestMessage *) message;
2761
2762   /* allocate response IP */
2763   result_af = (int) htonl (msg->result_af);
2764   if (GNUNET_OK != allocate_response_ip (&result_af,
2765                                          &addr,
2766                                          &v4, &v6))
2767   {
2768     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2769     return;
2770   }
2771   send_client_reply (client,
2772                      msg->request_id,
2773                      result_af,
2774                      addr);
2775   if (result_af == AF_UNSPEC)
2776   {
2777     /* failure, we're done */
2778     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2779                 _("Failed to allocate IP address for new destination\n"));
2780     GNUNET_SERVER_receive_done (client, GNUNET_OK);
2781     return;
2782   }
2783
2784   {
2785     char sbuf[INET6_ADDRSTRLEN];
2786
2787     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2788                 "Allocated address %s for redirection to service %s on peer %s\n",
2789                 inet_ntop (result_af, addr, sbuf, sizeof (sbuf)),
2790                 GNUNET_h2s (&msg->service_descriptor),
2791                 GNUNET_i2s (&msg->target));
2792   }
2793
2794   /* setup destination record */
2795   de = GNUNET_new (struct DestinationEntry);
2796   de->is_service = GNUNET_YES;
2797   de->details.service_destination.service_descriptor = msg->service_descriptor;
2798   de->details.service_destination.target = msg->target;
2799   get_destination_key_from_ip (result_af,
2800                                addr,
2801                                &key);
2802   de->key = key;
2803   GNUNET_assert (GNUNET_OK ==
2804                  GNUNET_CONTAINER_multihashmap_put (destination_map,
2805                                                     &key,
2806                                                     de,
2807                                                     GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE));
2808   de->heap_node = GNUNET_CONTAINER_heap_insert (destination_heap,
2809                                                 de,
2810                                                 GNUNET_TIME_absolute_ntoh (msg->expiration_time).abs_value_us);
2811   while (GNUNET_CONTAINER_multihashmap_size (destination_map) > max_destination_mappings)
2812     expire_destination (de);
2813
2814   dt = GNUNET_new (struct DestinationChannel);
2815   dt->destination = de;
2816   GNUNET_CONTAINER_DLL_insert (de->dt_head,
2817                                de->dt_tail,
2818                                dt);
2819   ts = create_channel_to_destination (dt,
2820                                       result_af);
2821   switch (result_af)
2822   {
2823   case AF_INET:
2824     ts->destination_ip.v4 = v4;
2825     break;
2826   case AF_INET6:
2827     ts->destination_ip.v6 = v6;
2828     break;
2829   default:
2830     GNUNET_assert (0);
2831   }
2832   /* we're done */
2833   GNUNET_SERVER_receive_done (client, GNUNET_OK);
2834 }
2835
2836
2837 /**
2838  * Function called whenever a channel is destroyed.  Should clean up
2839  * any associated state.
2840  *
2841  * @param cls closure (set from #GNUNET_CADET_connect)
2842  * @param channel connection to the other end (henceforth invalid)
2843  * @param channel_ctx place where local state associated
2844  *                   with the channel is stored (our `struct ChannelState`)
2845  */
2846 static void
2847 channel_cleaner (void *cls,
2848                  const struct GNUNET_CADET_Channel *channel,
2849                  void *channel_ctx)
2850 {
2851   struct ChannelState *ts = channel_ctx;
2852
2853   ts->channel = NULL; /* we must not call GNUNET_CADET_channel_destroy() anymore */
2854   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2855               "CADET notified us about death of channel to `%s'\n",
2856               print_channel_destination (&ts->destination));
2857   free_channel_state (ts);
2858 }
2859
2860
2861 /**
2862  * Free memory occupied by an entry in the destination map.
2863  *
2864  * @param cls unused
2865  * @param key unused
2866  * @param value a `struct DestinationEntry *`
2867  * @return #GNUNET_OK (continue to iterate)
2868  */
2869 static int
2870 cleanup_destination (void *cls,
2871                      const struct GNUNET_HashCode *key,
2872                      void *value)
2873 {
2874   struct DestinationEntry *de = value;
2875
2876   free_destination_entry (de);
2877   return GNUNET_OK;
2878 }
2879
2880
2881 /**
2882  * Free memory occupied by an entry in the channel map.
2883  *
2884  * @param cls unused
2885  * @param key unused
2886  * @param value a `struct ChannelState *`
2887  * @return #GNUNET_OK (continue to iterate)
2888  */
2889 static int
2890 cleanup_channel (void *cls,
2891                  const struct GNUNET_HashCode *key,
2892                  void *value)
2893 {
2894   struct ChannelState *ts = value;
2895
2896   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2897               "Tearing down channel to `%s' during cleanup\n",
2898               print_channel_destination (&ts->destination));
2899   free_channel_state (ts);
2900   return GNUNET_OK;
2901 }
2902
2903
2904 /**
2905  * Function scheduled as very last function, cleans up after us
2906  *
2907  * @param cls unused
2908  * @param tc unused
2909  */
2910 static void
2911 cleanup (void *cls,
2912          const struct GNUNET_SCHEDULER_TaskContext *tc)
2913 {
2914   unsigned int i;
2915
2916   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2917               "VPN is shutting down\n");
2918   if (NULL != destination_map)
2919   {
2920     GNUNET_CONTAINER_multihashmap_iterate (destination_map,
2921                                            &cleanup_destination,
2922                                            NULL);
2923     GNUNET_CONTAINER_multihashmap_destroy (destination_map);
2924     destination_map = NULL;
2925   }
2926   if (NULL != destination_heap)
2927   {
2928     GNUNET_CONTAINER_heap_destroy (destination_heap);
2929     destination_heap = NULL;
2930   }
2931   if (NULL != channel_map)
2932   {
2933     GNUNET_CONTAINER_multihashmap_iterate (channel_map,
2934                                            &cleanup_channel,
2935                                            NULL);
2936     GNUNET_CONTAINER_multihashmap_destroy (channel_map);
2937     channel_map = NULL;
2938   }
2939   if (NULL != channel_heap)
2940   {
2941     GNUNET_CONTAINER_heap_destroy (channel_heap);
2942     channel_heap = NULL;
2943   }
2944   if (NULL != cadet_handle)
2945   {
2946     GNUNET_CADET_disconnect (cadet_handle);
2947     cadet_handle = NULL;
2948   }
2949   if (NULL != helper_handle)
2950   {
2951     GNUNET_HELPER_stop (helper_handle, GNUNET_NO);
2952     helper_handle = NULL;
2953   }
2954   if (NULL != nc)
2955   {
2956     GNUNET_SERVER_notification_context_destroy (nc);
2957     nc = NULL;
2958   }
2959   if (NULL != stats)
2960   {
2961     GNUNET_STATISTICS_destroy (stats, GNUNET_NO);
2962     stats = NULL;
2963   }
2964   for (i=0;i<5;i++)
2965     GNUNET_free_non_null (vpn_argv[i]);
2966 }
2967
2968
2969 /**
2970  * Main function that will be run by the scheduler.
2971  *
2972  * @param cls closure
2973  * @param server the initialized server
2974  * @param cfg_ configuration
2975  */
2976 static void
2977 run (void *cls,
2978      struct GNUNET_SERVER_Handle *server,
2979      const struct GNUNET_CONFIGURATION_Handle *cfg_)
2980 {
2981   static const struct GNUNET_SERVER_MessageHandler service_handlers[] = {
2982     /* callback, cls, type, size */
2983     { &service_redirect_to_ip, NULL, GNUNET_MESSAGE_TYPE_VPN_CLIENT_REDIRECT_TO_IP, 0},
2984     { &service_redirect_to_service, NULL,
2985      GNUNET_MESSAGE_TYPE_VPN_CLIENT_REDIRECT_TO_SERVICE,
2986      sizeof (struct RedirectToServiceRequestMessage) },
2987     {NULL, NULL, 0, 0}
2988   };
2989   static const struct GNUNET_CADET_MessageHandler cadet_handlers[] = {
2990     { &receive_udp_back, GNUNET_MESSAGE_TYPE_VPN_UDP_REPLY, 0},
2991     { &receive_tcp_back, GNUNET_MESSAGE_TYPE_VPN_TCP_DATA_TO_VPN, 0},
2992     { &receive_icmp_back, GNUNET_MESSAGE_TYPE_VPN_ICMP_TO_VPN, 0},
2993     {NULL, 0, 0}
2994   };
2995   char *ifname;
2996   char *ipv6addr;
2997   char *ipv6prefix_s;
2998   char *ipv4addr;
2999   char *ipv4mask;
3000   struct in_addr v4;
3001   struct in6_addr v6;
3002   char *binary;
3003
3004   binary = GNUNET_OS_get_libexec_binary_path ("gnunet-helper-vpn");
3005
3006   if (GNUNET_YES !=
3007       GNUNET_OS_check_helper_binary (binary,
3008                                      GNUNET_YES,
3009                                      "-d gnunet-vpn - - 169.1.3.3.7 255.255.255.0")) //ipv4 only please!
3010   {
3011     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
3012                 "`%s' is not SUID, refusing to run.\n",
3013                 "gnunet-helper-vpn");
3014     GNUNET_free (binary);
3015     global_ret = 1;
3016     /* we won't "really" exit here, as the 'service' is still running;
3017        however, as no handlers are registered, the service won't do
3018        anything either */
3019     return;
3020   }
3021   GNUNET_free (binary);
3022   cfg = cfg_;
3023   stats = GNUNET_STATISTICS_create ("vpn", cfg);
3024   if (GNUNET_OK !=
3025       GNUNET_CONFIGURATION_get_value_number (cfg, "VPN", "MAX_MAPPING",
3026                                              &max_destination_mappings))
3027     max_destination_mappings = 200;
3028   if (GNUNET_OK !=
3029       GNUNET_CONFIGURATION_get_value_number (cfg, "VPN", "MAX_TUNNELS",
3030                                              &max_channel_mappings))
3031     max_channel_mappings = 200;
3032
3033   destination_map = GNUNET_CONTAINER_multihashmap_create (max_destination_mappings * 2, GNUNET_NO);
3034   destination_heap = GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN);
3035   channel_map = GNUNET_CONTAINER_multihashmap_create (max_channel_mappings * 2, GNUNET_NO);
3036   channel_heap = GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN);
3037
3038
3039   vpn_argv[0] = GNUNET_strdup ("vpn-gnunet");
3040   if (GNUNET_SYSERR ==
3041       GNUNET_CONFIGURATION_get_value_string (cfg, "VPN", "IFNAME", &ifname))
3042   {
3043     GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, "VPN", "IFNAME");
3044     GNUNET_SCHEDULER_shutdown ();
3045     return;
3046   }
3047   vpn_argv[1] = ifname;
3048   ipv6addr = NULL;
3049   if (GNUNET_OK == GNUNET_NETWORK_test_pf (PF_INET6))
3050   {
3051     if ( (GNUNET_SYSERR ==
3052           GNUNET_CONFIGURATION_get_value_string (cfg, "VPN", "IPV6ADDR",
3053                                                  &ipv6addr) ||
3054           (1 != inet_pton (AF_INET6, ipv6addr, &v6))) )
3055     {
3056       GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, "VPN", "IPV6ADDR",
3057                                  _("Must specify valid IPv6 address"));
3058       GNUNET_SCHEDULER_shutdown ();
3059       GNUNET_free_non_null (ipv6addr);
3060       return;
3061     }
3062     vpn_argv[2] = ipv6addr;
3063     ipv6prefix_s = NULL;
3064     if (GNUNET_SYSERR ==
3065         GNUNET_CONFIGURATION_get_value_string (cfg, "VPN", "IPV6PREFIX",
3066                                                &ipv6prefix_s))
3067     {
3068       GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, "VPN", "IPV6PREFIX");
3069       GNUNET_SCHEDULER_shutdown ();
3070       GNUNET_free_non_null (ipv6prefix_s);
3071       return;
3072     }
3073     vpn_argv[3] = ipv6prefix_s;
3074     if ( (GNUNET_OK !=
3075           GNUNET_CONFIGURATION_get_value_number (cfg, "VPN",
3076                                                  "IPV6PREFIX",
3077                                                  &ipv6prefix)) ||
3078          (ipv6prefix >= 127) )
3079     {
3080       GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, "VPN", "IPV4MASK",
3081                                  _("Must specify valid IPv6 mask"));
3082       GNUNET_SCHEDULER_shutdown ();
3083       return;
3084     }
3085   }
3086   else
3087   {
3088     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
3089                 _("IPv6 support disabled as this system does not support IPv6\n"));
3090     vpn_argv[2] = GNUNET_strdup ("-");
3091     vpn_argv[3] = GNUNET_strdup ("-");
3092   }
3093   if (GNUNET_OK == GNUNET_NETWORK_test_pf (PF_INET))
3094   {
3095     ipv4addr = NULL;
3096     if ( (GNUNET_SYSERR ==
3097           GNUNET_CONFIGURATION_get_value_string (cfg, "vpn", "IPV4ADDR",
3098                                                  &ipv4addr) ||
3099           (1 != inet_pton (AF_INET, ipv4addr, &v4))) )
3100     {
3101       GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, "VPN", "IPV4ADDR",
3102                                  _("Must specify valid IPv4 address"));
3103       GNUNET_SCHEDULER_shutdown ();
3104       GNUNET_free_non_null (ipv4addr);
3105       return;
3106     }
3107     vpn_argv[4] = ipv4addr;
3108     ipv4mask = NULL;
3109     if ( (GNUNET_SYSERR ==
3110           GNUNET_CONFIGURATION_get_value_string (cfg, "vpn", "IPV4MASK",
3111                                                  &ipv4mask) ||
3112           (1 != inet_pton (AF_INET, ipv4mask, &v4))) )
3113     {
3114       GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, "VPN", "IPV4MASK",
3115                                  _("Must specify valid IPv4 mask"));
3116       GNUNET_SCHEDULER_shutdown ();
3117       GNUNET_free_non_null (ipv4mask);
3118       return;
3119     }
3120     vpn_argv[5] = ipv4mask;
3121   }
3122   else
3123   {
3124     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
3125                 _("IPv4 support disabled as this system does not support IPv4\n"));
3126     vpn_argv[4] = GNUNET_strdup ("-");
3127     vpn_argv[5] = GNUNET_strdup ("-");
3128   }
3129   vpn_argv[6] = NULL;
3130
3131   cadet_handle =
3132     GNUNET_CADET_connect (cfg_, NULL,
3133                           NULL,
3134                           &channel_cleaner,
3135                           cadet_handlers,
3136                           NULL);
3137   helper_handle = GNUNET_HELPER_start (GNUNET_NO,
3138                                        "gnunet-helper-vpn", vpn_argv,
3139                                        &message_token, NULL, NULL);
3140   nc = GNUNET_SERVER_notification_context_create (server, 1);
3141   GNUNET_SERVER_add_handlers (server, service_handlers);
3142   GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL,
3143                                 &cleanup,
3144                                 NULL);
3145 }
3146
3147
3148 /**
3149  * The main function of the VPN service.
3150  *
3151  * @param argc number of arguments from the command line
3152  * @param argv command line arguments
3153  * @return 0 ok, 1 on error
3154  */
3155 int
3156 main (int argc, char *const *argv)
3157 {
3158   return (GNUNET_OK ==
3159           GNUNET_SERVICE_run (argc, argv, "vpn",
3160                               GNUNET_SERVICE_OPTION_NONE,
3161                               &run, NULL)) ? global_ret : 1;
3162 }
3163
3164 /* end of gnunet-service-vpn.c */