-indent, wait for helper termination on shutdown, do not eagerly create tunnel
[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",
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 %p to peer %s offering service %s\n",
834                 ts->channel,
835                 GNUNET_i2s (&dt->destination->details.service_destination.target),
836                 GNUNET_h2s (&dt->destination->details.service_destination.service_descriptor));
837   }
838   else
839   {
840     char *policy;
841
842     switch (dt->destination->details.exit_destination.af)
843     {
844     case AF_INET:
845     {
846       char address[GNUNET_TUN_IPV4_REGEXLEN];
847
848       GNUNET_TUN_ipv4toregexsearch (&dt->destination->details.exit_destination.ip.v4,
849                                     dt->destination_port,
850                                     address);
851       GNUNET_asprintf (&policy,
852                        "%s%s",
853                        GNUNET_APPLICATION_TYPE_EXIT_REGEX_PREFIX,
854                        address);
855       break;
856     }
857     case AF_INET6:
858     {
859       char address[GNUNET_TUN_IPV6_REGEXLEN];
860
861       GNUNET_TUN_ipv6toregexsearch (&dt->destination->details.exit_destination.ip.v6,
862                                     dt->destination_port,
863                                     address);
864       GNUNET_asprintf (&policy,
865                        "%s%s",
866                        GNUNET_APPLICATION_TYPE_EXIT_REGEX_PREFIX,
867                        address);
868       break;
869     }
870     default:
871       GNUNET_assert (0);
872       break;
873     }
874
875     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
876                 "Requesting connect by string: %s\n",
877                 policy);
878     ts->search = GNUNET_REGEX_search (cfg,
879                                       policy,
880                                       &handle_regex_result,
881                                       ts);
882     GNUNET_free (policy);
883   }
884   return ts;
885 }
886
887
888 /**
889  * We have too many active channels.  Clean up the oldest channel.
890  *
891  * @param except channel that must NOT be cleaned up, even if it is the oldest
892  */
893 static void
894 expire_channel (struct ChannelState *except)
895 {
896   struct ChannelState *ts;
897
898   ts = GNUNET_CONTAINER_heap_peek (channel_heap);
899   GNUNET_assert (NULL != ts);
900   if (except == ts)
901     return; /* can't do this */
902   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
903               "Tearing down expired channel to %s\n",
904               print_channel_destination (&except->destination));
905   free_channel_state (ts);
906 }
907
908
909 /**
910  * Route a packet via cadet to the given destination.
911  *
912  * @param destination description of the destination
913  * @param af address family on this end (AF_INET or AF_INET6)
914  * @param protocol IPPROTO_TCP or IPPROTO_UDP or IPPROTO_ICMP or IPPROTO_ICMPV6
915  * @param source_ip source IP used by the sender (struct in_addr or struct in6_addr)
916  * @param destination_ip destination IP used by the sender (struct in_addr or struct in6_addr)
917  * @param payload payload of the packet after the IP header
918  * @param payload_length number of bytes in @a payload
919  */
920 static void
921 route_packet (struct DestinationEntry *destination,
922               int af,
923               uint8_t protocol,
924               const void *source_ip,
925               const void *destination_ip,
926               const void *payload,
927               size_t payload_length)
928 {
929   struct GNUNET_HashCode key;
930   struct ChannelState *ts;
931   struct ChannelMessageQueueEntry *tnq;
932   size_t alen;
933   size_t mlen;
934   const struct GNUNET_TUN_UdpHeader *udp;
935   const struct GNUNET_TUN_TcpHeader *tcp;
936   const struct GNUNET_TUN_IcmpHeader *icmp;
937   struct DestinationChannel *dt;
938   uint16_t source_port;
939   uint16_t destination_port;
940
941   switch (protocol)
942   {
943   case IPPROTO_UDP:
944     {
945       if (payload_length < sizeof (struct GNUNET_TUN_UdpHeader))
946       {
947         /* blame kernel? */
948         GNUNET_break (0);
949         return;
950       }
951       tcp = NULL; /* make compiler happy */
952       icmp = NULL;  /* make compiler happy */
953       udp = payload;
954       if (udp->len < sizeof (struct GNUNET_TUN_UdpHeader))
955       {
956         GNUNET_break_op (0);
957         return;
958       }
959       source_port = ntohs (udp->source_port);
960       destination_port = ntohs (udp->destination_port);
961       get_channel_key_from_ips (af,
962                                 IPPROTO_UDP,
963                                 source_ip,
964                                 source_port,
965                                 destination_ip,
966                                 destination_port,
967                                 &key);
968     }
969     break;
970   case IPPROTO_TCP:
971     {
972       if (payload_length < sizeof (struct GNUNET_TUN_TcpHeader))
973       {
974         /* blame kernel? */
975         GNUNET_break (0);
976         return;
977       }
978       udp = NULL; /* make compiler happy */
979       icmp = NULL;  /* make compiler happy */
980       tcp = payload;
981       if (tcp->off * 4 < sizeof (struct GNUNET_TUN_TcpHeader))
982       {
983         GNUNET_break_op (0);
984         return;
985       }
986       source_port = ntohs (tcp->source_port);
987       destination_port = ntohs (tcp->destination_port);
988       get_channel_key_from_ips (af,
989                                 IPPROTO_TCP,
990                                 source_ip,
991                                 source_port,
992                                 destination_ip,
993                                 destination_port,
994                                 &key);
995     }
996     break;
997   case IPPROTO_ICMP:
998   case IPPROTO_ICMPV6:
999     {
1000       if ( (AF_INET == af) ^ (protocol == IPPROTO_ICMP) )
1001       {
1002         GNUNET_break (0);
1003         return;
1004       }
1005       if (payload_length < sizeof (struct GNUNET_TUN_IcmpHeader))
1006       {
1007         /* blame kernel? */
1008         GNUNET_break (0);
1009         return;
1010       }
1011       tcp = NULL; /* make compiler happy */
1012       udp = NULL;  /* make compiler happy */
1013       icmp = payload;
1014       source_port = 0;
1015       destination_port = 0;
1016       get_channel_key_from_ips (af,
1017                                 protocol,
1018                                 source_ip,
1019                                 0,
1020                                 destination_ip,
1021                                 0,
1022                                 &key);
1023     }
1024     break;
1025   default:
1026     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1027                 _("Protocol %u not supported, dropping\n"),
1028                 (unsigned int) protocol);
1029     return;
1030   }
1031   alen = 0;
1032   if (! destination->is_service)
1033   {
1034     switch (destination->details.exit_destination.af)
1035     {
1036     case AF_INET:
1037       alen = sizeof (struct in_addr);
1038      break;
1039     case AF_INET6:
1040       alen = sizeof (struct in6_addr);
1041       break;
1042     default:
1043       GNUNET_assert (0);
1044     }
1045
1046     {
1047       char sbuf[INET6_ADDRSTRLEN];
1048       char dbuf[INET6_ADDRSTRLEN];
1049       char xbuf[INET6_ADDRSTRLEN];
1050
1051       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1052                   "Routing %s packet from [%s]:%u -> [%s]:%u to destination [%s]:%u\n",
1053                   (protocol == IPPROTO_TCP) ? "TCP" : "UDP",
1054                   inet_ntop (af, source_ip, sbuf, sizeof (sbuf)),
1055                   source_port,
1056                   inet_ntop (af, destination_ip, dbuf, sizeof (dbuf)),
1057                   destination_port,
1058                   inet_ntop (destination->details.exit_destination.af,
1059                              &destination->details.exit_destination.ip,
1060                              xbuf, sizeof (xbuf)),
1061                   destination_port);
1062     }
1063     for (dt = destination->dt_head; NULL != dt; dt = dt->next)
1064       if (dt->destination_port == destination_port)
1065         break;
1066   }
1067   else
1068   {
1069     {
1070       char sbuf[INET6_ADDRSTRLEN];
1071       char dbuf[INET6_ADDRSTRLEN];
1072
1073       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1074                   "Routing %s packet from [%s]:%u -> [%s]:%u to service %s at peer %s\n",
1075                   (protocol == IPPROTO_TCP) ? "TCP" : "UDP",
1076                   inet_ntop (af, source_ip, sbuf, sizeof (sbuf)),
1077                   source_port,
1078                   inet_ntop (af, destination_ip, dbuf, sizeof (dbuf)),
1079                   destination_port,
1080                   GNUNET_h2s (&destination->details.service_destination.service_descriptor),
1081                   GNUNET_i2s (&destination->details.service_destination.target));
1082     }
1083     dt = destination->dt_head;
1084   }
1085   if (NULL == dt)
1086   {
1087     dt = GNUNET_new (struct DestinationChannel);
1088     dt->destination = destination;
1089     GNUNET_CONTAINER_DLL_insert (destination->dt_head,
1090                                  destination->dt_tail,
1091                                  dt);
1092     dt->destination_port = destination_port;
1093   }
1094
1095   /* see if we have an existing channel for this destination */
1096   ts = GNUNET_CONTAINER_multihashmap_get (channel_map,
1097                                           &key);
1098   if (NULL == ts)
1099   {
1100     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1101                 "Creating new channel for key %s\n",
1102                 GNUNET_h2s (&key));
1103     /* need to either use the existing channel from the destination (if still
1104        available) or create a fresh one */
1105     if (NULL == dt->ts)
1106       ts = create_channel_to_destination (dt, af);
1107     else
1108       ts = dt->ts;
1109     if (NULL == ts)
1110       return;
1111     dt->ts = NULL;
1112     ts->destination_container = NULL; /* no longer 'contained' */
1113     /* now bind existing "unbound" channel to our IP/port tuple */
1114     ts->protocol = protocol;
1115     ts->af = af;
1116     if (AF_INET == af)
1117     {
1118       ts->source_ip.v4 = * (const struct in_addr *) source_ip;
1119       ts->destination_ip.v4 = * (const struct in_addr *) destination_ip;
1120     }
1121     else
1122     {
1123       ts->source_ip.v6 = * (const struct in6_addr *) source_ip;
1124       ts->destination_ip.v6 = * (const struct in6_addr *) destination_ip;
1125     }
1126     ts->source_port = source_port;
1127     ts->destination_port = destination_port;
1128     ts->heap_node = GNUNET_CONTAINER_heap_insert (channel_heap,
1129                                                   ts,
1130                                                   GNUNET_TIME_absolute_get ().abs_value_us);
1131     GNUNET_assert (GNUNET_YES ==
1132                    GNUNET_CONTAINER_multihashmap_put (channel_map,
1133                                                       &key,
1134                                                       ts,
1135                                                       GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
1136     GNUNET_STATISTICS_update (stats,
1137                               gettext_noop ("# Active channels"),
1138                               1, GNUNET_NO);
1139     while (GNUNET_CONTAINER_multihashmap_size (channel_map) > max_channel_mappings)
1140       expire_channel (ts);
1141   }
1142   else
1143   {
1144     GNUNET_CONTAINER_heap_update_cost (channel_heap,
1145                                        ts->heap_node,
1146                                        GNUNET_TIME_absolute_get ().abs_value_us);
1147   }
1148   if (NULL == ts->channel)
1149   {
1150     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1151                 "Packet dropped, channel to %s not yet ready (%s)\n",
1152                 print_channel_destination (&ts->destination),
1153                 (NULL == ts->search)
1154                 ? "EXIT search failed"
1155                 : "EXIT search active");
1156     GNUNET_STATISTICS_update (stats,
1157                               gettext_noop ("# Packets dropped (channel not yet online)"),
1158                               1,
1159                               GNUNET_NO);
1160     return;
1161   }
1162
1163   /* send via channel */
1164   switch (protocol)
1165   {
1166   case IPPROTO_UDP:
1167     if (destination->is_service)
1168     {
1169       struct GNUNET_EXIT_UdpServiceMessage *usm;
1170
1171       mlen = sizeof (struct GNUNET_EXIT_UdpServiceMessage) +
1172         payload_length - sizeof (struct GNUNET_TUN_UdpHeader);
1173       if (mlen >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1174       {
1175         GNUNET_break (0);
1176         return;
1177       }
1178       tnq = GNUNET_malloc (sizeof (struct ChannelMessageQueueEntry) + mlen);
1179       tnq->len = mlen;
1180       tnq->msg = &tnq[1];
1181       usm = (struct GNUNET_EXIT_UdpServiceMessage *) &tnq[1];
1182       usm->header.size = htons ((uint16_t) mlen);
1183       usm->header.type = htons (GNUNET_MESSAGE_TYPE_VPN_UDP_TO_SERVICE);
1184       /* if the source port is below 32000, we assume it has a special
1185          meaning; if not, we pick a random port (this is a heuristic) */
1186       usm->source_port = (ntohs (udp->source_port) < 32000) ? udp->source_port : 0;
1187       usm->destination_port = udp->destination_port;
1188       usm->service_descriptor = destination->details.service_destination.service_descriptor;
1189       memcpy (&usm[1],
1190               &udp[1],
1191               payload_length - sizeof (struct GNUNET_TUN_UdpHeader));
1192     }
1193     else
1194     {
1195       struct GNUNET_EXIT_UdpInternetMessage *uim;
1196       struct in_addr *ip4dst;
1197       struct in6_addr *ip6dst;
1198       void *payload;
1199
1200       mlen = sizeof (struct GNUNET_EXIT_UdpInternetMessage) +
1201         alen + payload_length - sizeof (struct GNUNET_TUN_UdpHeader);
1202       if (mlen >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1203       {
1204         GNUNET_break (0);
1205         return;
1206       }
1207       tnq = GNUNET_malloc (sizeof (struct ChannelMessageQueueEntry) + mlen);
1208       tnq->len = mlen;
1209       tnq->msg = &tnq[1];
1210       uim = (struct GNUNET_EXIT_UdpInternetMessage *) &tnq[1];
1211       uim->header.size = htons ((uint16_t) mlen);
1212       uim->header.type = htons (GNUNET_MESSAGE_TYPE_VPN_UDP_TO_INTERNET);
1213       uim->af = htonl (destination->details.exit_destination.af);
1214       uim->source_port = (ntohs (udp->source_port) < 32000) ? udp->source_port : 0;
1215       uim->destination_port = udp->destination_port;
1216       switch (destination->details.exit_destination.af)
1217       {
1218       case AF_INET:
1219         ip4dst = (struct in_addr *) &uim[1];
1220         *ip4dst = destination->details.exit_destination.ip.v4;
1221         payload = &ip4dst[1];
1222         break;
1223       case AF_INET6:
1224         ip6dst = (struct in6_addr *) &uim[1];
1225         *ip6dst = destination->details.exit_destination.ip.v6;
1226         payload = &ip6dst[1];
1227         break;
1228       default:
1229         GNUNET_assert (0);
1230       }
1231       memcpy (payload,
1232               &udp[1],
1233               payload_length - sizeof (struct GNUNET_TUN_UdpHeader));
1234     }
1235     break;
1236   case IPPROTO_TCP:
1237     if (GNUNET_NO == ts->is_established)
1238     {
1239       if (destination->is_service)
1240       {
1241         struct GNUNET_EXIT_TcpServiceStartMessage *tsm;
1242
1243         mlen = sizeof (struct GNUNET_EXIT_TcpServiceStartMessage) +
1244           payload_length - sizeof (struct GNUNET_TUN_TcpHeader);
1245         if (mlen >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1246         {
1247           GNUNET_break (0);
1248           return;
1249         }
1250         tnq = GNUNET_malloc (sizeof (struct ChannelMessageQueueEntry) + mlen);
1251         tnq->len = mlen;
1252         tnq->msg = &tnq[1];
1253         tsm = (struct  GNUNET_EXIT_TcpServiceStartMessage *) &tnq[1];
1254         tsm->header.size = htons ((uint16_t) mlen);
1255         tsm->header.type = htons (GNUNET_MESSAGE_TYPE_VPN_TCP_TO_SERVICE_START);
1256         tsm->reserved = htonl (0);
1257         tsm->service_descriptor = destination->details.service_destination.service_descriptor;
1258         tsm->tcp_header = *tcp;
1259         memcpy (&tsm[1],
1260                 &tcp[1],
1261                 payload_length - sizeof (struct GNUNET_TUN_TcpHeader));
1262       }
1263       else
1264       {
1265         struct GNUNET_EXIT_TcpInternetStartMessage *tim;
1266         struct in_addr *ip4dst;
1267         struct in6_addr *ip6dst;
1268         void *payload;
1269
1270         mlen = sizeof (struct GNUNET_EXIT_TcpInternetStartMessage) +
1271           alen + payload_length - sizeof (struct GNUNET_TUN_TcpHeader);
1272         if (mlen >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1273         {
1274           GNUNET_break (0);
1275           return;
1276         }
1277         tnq = GNUNET_malloc (sizeof (struct ChannelMessageQueueEntry) + mlen);
1278         tnq->len = mlen;
1279         tnq->msg = &tnq[1];
1280         tim = (struct  GNUNET_EXIT_TcpInternetStartMessage *) &tnq[1];
1281         tim->header.size = htons ((uint16_t) mlen);
1282         tim->header.type = htons (GNUNET_MESSAGE_TYPE_VPN_TCP_TO_INTERNET_START);
1283         tim->af = htonl (destination->details.exit_destination.af);
1284         tim->tcp_header = *tcp;
1285         switch (destination->details.exit_destination.af)
1286         {
1287         case AF_INET:
1288           ip4dst = (struct in_addr *) &tim[1];
1289           *ip4dst = destination->details.exit_destination.ip.v4;
1290           payload = &ip4dst[1];
1291           break;
1292         case AF_INET6:
1293           ip6dst = (struct in6_addr *) &tim[1];
1294           *ip6dst = destination->details.exit_destination.ip.v6;
1295           payload = &ip6dst[1];
1296           break;
1297         default:
1298           GNUNET_assert (0);
1299         }
1300         memcpy (payload,
1301                 &tcp[1],
1302                 payload_length - sizeof (struct GNUNET_TUN_TcpHeader));
1303       }
1304     }
1305     else
1306     {
1307       struct GNUNET_EXIT_TcpDataMessage *tdm;
1308
1309       mlen = sizeof (struct GNUNET_EXIT_TcpDataMessage) +
1310         payload_length - sizeof (struct GNUNET_TUN_TcpHeader);
1311       if (mlen >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1312       {
1313         GNUNET_break (0);
1314         return;
1315       }
1316       tnq = GNUNET_malloc (sizeof (struct ChannelMessageQueueEntry) + mlen);
1317       tnq->len = mlen;
1318       tnq->msg = &tnq[1];
1319       tdm = (struct  GNUNET_EXIT_TcpDataMessage *) &tnq[1];
1320       tdm->header.size = htons ((uint16_t) mlen);
1321       tdm->header.type = htons (GNUNET_MESSAGE_TYPE_VPN_TCP_DATA_TO_EXIT);
1322       tdm->reserved = htonl (0);
1323       tdm->tcp_header = *tcp;
1324       memcpy (&tdm[1],
1325               &tcp[1],
1326               payload_length - sizeof (struct GNUNET_TUN_TcpHeader));
1327      }
1328     break;
1329   case IPPROTO_ICMP:
1330   case IPPROTO_ICMPV6:
1331     if (destination->is_service)
1332     {
1333       struct GNUNET_EXIT_IcmpServiceMessage *ism;
1334
1335       mlen = sizeof (struct GNUNET_EXIT_IcmpServiceMessage) +
1336         payload_length - sizeof (struct GNUNET_TUN_IcmpHeader);
1337       if (mlen >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1338       {
1339         GNUNET_break (0);
1340         return;
1341       }
1342       tnq = GNUNET_malloc (sizeof (struct ChannelMessageQueueEntry) + mlen);
1343       tnq->msg = &tnq[1];
1344       ism = (struct GNUNET_EXIT_IcmpServiceMessage *) &tnq[1];
1345       ism->header.type = htons (GNUNET_MESSAGE_TYPE_VPN_ICMP_TO_SERVICE);
1346       ism->af = htonl (af); /* need to tell destination ICMP protocol family! */
1347       ism->service_descriptor = destination->details.service_destination.service_descriptor;
1348       ism->icmp_header = *icmp;
1349       /* ICMP protocol translation will be done by the receiver (as we don't know
1350          the target AF); however, we still need to possibly discard the payload
1351          depending on the ICMP type */
1352       switch (af)
1353       {
1354       case AF_INET:
1355         switch (icmp->type)
1356         {
1357         case GNUNET_TUN_ICMPTYPE_ECHO_REPLY:
1358         case GNUNET_TUN_ICMPTYPE_ECHO_REQUEST:
1359           break;
1360         case GNUNET_TUN_ICMPTYPE_DESTINATION_UNREACHABLE:
1361         case GNUNET_TUN_ICMPTYPE_SOURCE_QUENCH:
1362         case GNUNET_TUN_ICMPTYPE_TIME_EXCEEDED:
1363           /* throw away ICMP payload, won't be useful for the other side anyway */
1364           payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
1365           break;
1366         default:
1367           GNUNET_STATISTICS_update (stats,
1368                                     gettext_noop ("# ICMPv4 packets dropped (not allowed)"),
1369                                     1, GNUNET_NO);
1370           return;
1371         }
1372         /* end of AF_INET */
1373         break;
1374       case AF_INET6:
1375         switch (icmp->type)
1376         {
1377         case GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE:
1378         case GNUNET_TUN_ICMPTYPE6_PACKET_TOO_BIG:
1379         case GNUNET_TUN_ICMPTYPE6_TIME_EXCEEDED:
1380         case GNUNET_TUN_ICMPTYPE6_PARAMETER_PROBLEM:
1381           /* throw away ICMP payload, won't be useful for the other side anyway */
1382           payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
1383           break;
1384         case GNUNET_TUN_ICMPTYPE6_ECHO_REQUEST:
1385         case GNUNET_TUN_ICMPTYPE6_ECHO_REPLY:
1386           break;
1387         default:
1388           GNUNET_STATISTICS_update (stats,
1389                                     gettext_noop ("# ICMPv6 packets dropped (not allowed)"),
1390                                     1, GNUNET_NO);
1391           return;
1392         }
1393         /* end of AF_INET6 */
1394         break;
1395       default:
1396         GNUNET_assert (0);
1397         break;
1398       }
1399
1400       /* update length calculations, as payload_length may have changed */
1401       mlen = sizeof (struct GNUNET_EXIT_IcmpServiceMessage) +
1402         alen + payload_length - sizeof (struct GNUNET_TUN_IcmpHeader);
1403       tnq->len = mlen;
1404       ism->header.size = htons ((uint16_t) mlen);
1405       /* finally, copy payload (if there is any left...) */
1406       memcpy (&ism[1],
1407               &icmp[1],
1408               payload_length - sizeof (struct GNUNET_TUN_IcmpHeader));
1409     }
1410     else
1411     {
1412       struct GNUNET_EXIT_IcmpInternetMessage *iim;
1413       struct in_addr *ip4dst;
1414       struct in6_addr *ip6dst;
1415       void *payload;
1416
1417       mlen = sizeof (struct GNUNET_EXIT_IcmpInternetMessage) +
1418         alen + payload_length - sizeof (struct GNUNET_TUN_IcmpHeader);
1419       if (mlen >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1420       {
1421         GNUNET_break (0);
1422         return;
1423       }
1424       tnq = GNUNET_malloc (sizeof (struct ChannelMessageQueueEntry) + mlen);
1425       tnq->msg = &tnq[1];
1426       iim = (struct GNUNET_EXIT_IcmpInternetMessage *) &tnq[1];
1427       iim->header.type = htons (GNUNET_MESSAGE_TYPE_VPN_ICMP_TO_INTERNET);
1428       iim->icmp_header = *icmp;
1429       /* Perform ICMP protocol-translation (depending on destination AF and source AF)
1430          and throw away ICMP payload depending on ICMP message type */
1431       switch (af)
1432       {
1433       case AF_INET:
1434         switch (icmp->type)
1435         {
1436         case GNUNET_TUN_ICMPTYPE_ECHO_REPLY:
1437           if (destination->details.exit_destination.af == AF_INET6)
1438             iim->icmp_header.type = GNUNET_TUN_ICMPTYPE6_ECHO_REPLY;
1439           break;
1440         case GNUNET_TUN_ICMPTYPE_ECHO_REQUEST:
1441           if (destination->details.exit_destination.af == AF_INET6)
1442             iim->icmp_header.type = GNUNET_TUN_ICMPTYPE6_ECHO_REQUEST;
1443           break;
1444         case GNUNET_TUN_ICMPTYPE_DESTINATION_UNREACHABLE:
1445           if (destination->details.exit_destination.af == AF_INET6)
1446             iim->icmp_header.type = GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE;
1447           /* throw away IP-payload, exit will have to make it up anyway */
1448           payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
1449           break;
1450         case GNUNET_TUN_ICMPTYPE_TIME_EXCEEDED:
1451           if (destination->details.exit_destination.af == AF_INET6)
1452             iim->icmp_header.type = GNUNET_TUN_ICMPTYPE6_TIME_EXCEEDED;
1453           /* throw away IP-payload, exit will have to make it up anyway */
1454           payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
1455           break;
1456         case GNUNET_TUN_ICMPTYPE_SOURCE_QUENCH:
1457           if (destination->details.exit_destination.af == AF_INET6)
1458             {
1459               GNUNET_STATISTICS_update (stats,
1460                                         gettext_noop ("# ICMPv4 packets dropped (impossible PT to v6)"),
1461                                         1, GNUNET_NO);
1462               GNUNET_free (tnq);
1463               return;
1464             }
1465           /* throw away IP-payload, exit will have to make it up anyway */
1466           payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
1467           break;
1468         default:
1469           GNUNET_STATISTICS_update (stats,
1470                                     gettext_noop ("# ICMPv4 packets dropped (type not allowed)"),
1471                                     1, GNUNET_NO);
1472           GNUNET_free (tnq);
1473           return;
1474         }
1475         /* end of AF_INET */
1476         break;
1477       case AF_INET6:
1478         switch (icmp->type)
1479           {
1480           case GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE:
1481             if (destination->details.exit_destination.af == AF_INET6)
1482               iim->icmp_header.type = GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE;
1483             /* throw away IP-payload, exit will have to make it up anyway */
1484             payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
1485             break;
1486           case GNUNET_TUN_ICMPTYPE6_TIME_EXCEEDED:
1487             if (destination->details.exit_destination.af == AF_INET)
1488               iim->icmp_header.type = GNUNET_TUN_ICMPTYPE_TIME_EXCEEDED;
1489             /* throw away IP-payload, exit will have to make it up anyway */
1490             payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
1491             break;
1492           case GNUNET_TUN_ICMPTYPE6_PACKET_TOO_BIG:
1493             if (destination->details.exit_destination.af == AF_INET)
1494             {
1495               GNUNET_STATISTICS_update (stats,
1496                                         gettext_noop ("# ICMPv6 packets dropped (impossible PT to v4)"),
1497                                         1, GNUNET_NO);
1498               GNUNET_free (tnq);
1499               return;
1500             }
1501             /* throw away IP-payload, exit will have to make it up anyway */
1502             payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
1503             break;
1504           case GNUNET_TUN_ICMPTYPE6_PARAMETER_PROBLEM:
1505             if (destination->details.exit_destination.af == AF_INET)
1506             {
1507               GNUNET_STATISTICS_update (stats,
1508                                         gettext_noop ("# ICMPv6 packets dropped (impossible PT to v4)"),
1509                                         1, GNUNET_NO);
1510               GNUNET_free (tnq);
1511               return;
1512             }
1513             /* throw away IP-payload, exit will have to make it up anyway */
1514             payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
1515             break;
1516           case GNUNET_TUN_ICMPTYPE6_ECHO_REQUEST:
1517             if (destination->details.exit_destination.af == AF_INET)
1518               iim->icmp_header.type = GNUNET_TUN_ICMPTYPE_ECHO_REQUEST;
1519             break;
1520           case GNUNET_TUN_ICMPTYPE6_ECHO_REPLY:
1521             if (destination->details.exit_destination.af == AF_INET)
1522               iim->icmp_header.type = GNUNET_TUN_ICMPTYPE_ECHO_REPLY;
1523             break;
1524           default:
1525             GNUNET_STATISTICS_update (stats,
1526                                       gettext_noop ("# ICMPv6 packets dropped (type not allowed)"),
1527                                       1, GNUNET_NO);
1528             GNUNET_free (tnq);
1529             return;
1530           }
1531         /* end of AF_INET6 */
1532         break;
1533       default:
1534         GNUNET_assert (0);
1535       }
1536       /* update length calculations, as payload_length may have changed */
1537       mlen = sizeof (struct GNUNET_EXIT_IcmpInternetMessage) +
1538         alen + payload_length - sizeof (struct GNUNET_TUN_IcmpHeader);
1539       tnq->len = mlen;
1540       iim->header.size = htons ((uint16_t) mlen);
1541
1542       /* need to tell destination ICMP protocol family! */
1543       iim->af = htonl (destination->details.exit_destination.af);
1544       switch (destination->details.exit_destination.af)
1545       {
1546       case AF_INET:
1547         ip4dst = (struct in_addr *) &iim[1];
1548         *ip4dst = destination->details.exit_destination.ip.v4;
1549         payload = &ip4dst[1];
1550         break;
1551       case AF_INET6:
1552         ip6dst = (struct in6_addr *) &iim[1];
1553         *ip6dst = destination->details.exit_destination.ip.v6;
1554         payload = &ip6dst[1];
1555         break;
1556       default:
1557         GNUNET_assert (0);
1558       }
1559       memcpy (payload,
1560               &icmp[1],
1561               payload_length - sizeof (struct GNUNET_TUN_IcmpHeader));
1562     }
1563     break;
1564   default:
1565     /* not supported above, how can we get here !? */
1566     GNUNET_assert (0);
1567     break;
1568   }
1569   ts->is_established = GNUNET_YES;
1570   send_to_channel (tnq, ts);
1571 }
1572
1573
1574 /**
1575  * Receive packets from the helper-process (someone send to the local
1576  * virtual channel interface).  Find the destination mapping, and if it
1577  * exists, identify the correct CADET channel (or possibly create it)
1578  * and forward the packet.
1579  *
1580  * @param cls closure, NULL
1581  * @param client NULL
1582  * @param message message we got from the client (VPN channel interface)
1583  */
1584 static int
1585 message_token (void *cls,
1586                void *client,
1587                const struct GNUNET_MessageHeader *message)
1588 {
1589   const struct GNUNET_TUN_Layer2PacketHeader *tun;
1590   size_t mlen;
1591   struct GNUNET_HashCode key;
1592   struct DestinationEntry *de;
1593
1594   GNUNET_STATISTICS_update (stats,
1595                             gettext_noop ("# Packets received from TUN interface"),
1596                             1, GNUNET_NO);
1597   mlen = ntohs (message->size);
1598   if ( (ntohs (message->type) != GNUNET_MESSAGE_TYPE_VPN_HELPER) ||
1599        (mlen < sizeof (struct GNUNET_MessageHeader) + sizeof (struct GNUNET_TUN_Layer2PacketHeader)) )
1600   {
1601     GNUNET_break (0);
1602     return GNUNET_OK;
1603   }
1604   tun = (const struct GNUNET_TUN_Layer2PacketHeader *) &message[1];
1605   mlen -= (sizeof (struct GNUNET_MessageHeader) + sizeof (struct GNUNET_TUN_Layer2PacketHeader));
1606   switch (ntohs (tun->proto))
1607   {
1608   case ETH_P_IPV6:
1609     {
1610       const struct GNUNET_TUN_IPv6Header *pkt6;
1611
1612       if (mlen < sizeof (struct GNUNET_TUN_IPv6Header))
1613       {
1614         /* blame kernel */
1615         GNUNET_break (0);
1616         return GNUNET_OK;
1617       }
1618       pkt6 = (const struct GNUNET_TUN_IPv6Header *) &tun[1];
1619       get_destination_key_from_ip (AF_INET6,
1620                                    &pkt6->destination_address,
1621                                    &key);
1622       de = GNUNET_CONTAINER_multihashmap_get (destination_map, &key);
1623       if (NULL == de)
1624       {
1625         char buf[INET6_ADDRSTRLEN];
1626
1627         GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1628                     _("Packet received for unmapped destination `%s' (dropping it)\n"),
1629                     inet_ntop (AF_INET6,
1630                                &pkt6->destination_address,
1631                                buf,
1632                                sizeof (buf)));
1633         return GNUNET_OK;
1634       }
1635       route_packet (de,
1636                     AF_INET6,
1637                     pkt6->next_header,
1638                     &pkt6->source_address,
1639                     &pkt6->destination_address,
1640                     &pkt6[1],
1641                     mlen - sizeof (struct GNUNET_TUN_IPv6Header));
1642     }
1643     break;
1644   case ETH_P_IPV4:
1645     {
1646       struct GNUNET_TUN_IPv4Header *pkt4;
1647
1648       if (mlen < sizeof (struct GNUNET_TUN_IPv4Header))
1649       {
1650         /* blame kernel */
1651         GNUNET_break (0);
1652         return GNUNET_OK;
1653       }
1654       pkt4 = (struct GNUNET_TUN_IPv4Header *) &tun[1];
1655       get_destination_key_from_ip (AF_INET,
1656                                    &pkt4->destination_address,
1657                                    &key);
1658       de = GNUNET_CONTAINER_multihashmap_get (destination_map, &key);
1659       if (NULL == de)
1660       {
1661         char buf[INET_ADDRSTRLEN];
1662
1663         GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1664                     _("Packet received for unmapped destination `%s' (dropping it)\n"),
1665                     inet_ntop (AF_INET,
1666                                &pkt4->destination_address,
1667                                buf,
1668                                sizeof (buf)));
1669         return GNUNET_OK;
1670       }
1671       if (pkt4->header_length * 4 != sizeof (struct GNUNET_TUN_IPv4Header))
1672       {
1673         GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1674                     _("Received IPv4 packet with options (dropping it)\n"));
1675         return GNUNET_OK;
1676       }
1677       route_packet (de,
1678                     AF_INET,
1679                     pkt4->protocol,
1680                     &pkt4->source_address,
1681                     &pkt4->destination_address,
1682                     &pkt4[1],
1683                     mlen - sizeof (struct GNUNET_TUN_IPv4Header));
1684     }
1685     break;
1686   default:
1687     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1688                 _("Received packet of unknown protocol %d from TUN (dropping it)\n"),
1689                 (unsigned int) ntohs (tun->proto));
1690     break;
1691   }
1692   return GNUNET_OK;
1693 }
1694
1695
1696 /**
1697  * Synthesize a plausible ICMP payload for an ICMP error
1698  * response on the given channel.
1699  *
1700  * @param ts channel information
1701  * @param ipp IPv4 header to fill in (ICMP payload)
1702  * @param udp "UDP" header to fill in (ICMP payload); might actually
1703  *            also be the first 8 bytes of the TCP header
1704  */
1705 static void
1706 make_up_icmpv4_payload (struct ChannelState *ts,
1707                         struct GNUNET_TUN_IPv4Header *ipp,
1708                         struct GNUNET_TUN_UdpHeader *udp)
1709 {
1710   GNUNET_TUN_initialize_ipv4_header (ipp,
1711                                      ts->protocol,
1712                                      sizeof (struct GNUNET_TUN_TcpHeader),
1713                                      &ts->source_ip.v4,
1714                                      &ts->destination_ip.v4);
1715   udp->source_port = htons (ts->source_port);
1716   udp->destination_port = htons (ts->destination_port);
1717   udp->len = htons (0);
1718   udp->crc = htons (0);
1719 }
1720
1721
1722 /**
1723  * Synthesize a plausible ICMP payload for an ICMP error
1724  * response on the given channel.
1725  *
1726  * @param ts channel information
1727  * @param ipp IPv6 header to fill in (ICMP payload)
1728  * @param udp "UDP" header to fill in (ICMP payload); might actually
1729  *            also be the first 8 bytes of the TCP header
1730  */
1731 static void
1732 make_up_icmpv6_payload (struct ChannelState *ts,
1733                         struct GNUNET_TUN_IPv6Header *ipp,
1734                         struct GNUNET_TUN_UdpHeader *udp)
1735 {
1736   GNUNET_TUN_initialize_ipv6_header (ipp,
1737                                      ts->protocol,
1738                                      sizeof (struct GNUNET_TUN_TcpHeader),
1739                                      &ts->source_ip.v6,
1740                                      &ts->destination_ip.v6);
1741   udp->source_port = htons (ts->source_port);
1742   udp->destination_port = htons (ts->destination_port);
1743   udp->len = htons (0);
1744   udp->crc = htons (0);
1745 }
1746
1747
1748 /**
1749  * We got an ICMP packet back from the CADET channel.  Pass it on to the
1750  * local virtual interface via the helper.
1751  *
1752  * @param cls closure, NULL
1753  * @param channel connection to the other end
1754  * @param channel_ctx pointer to our 'struct ChannelState *'
1755  * @param message the actual message
1756  * @return #GNUNET_OK to keep the connection open,
1757  *         #GNUNET_SYSERR to close it (signal serious error)
1758  */
1759 static int
1760 receive_icmp_back (void *cls,
1761                    struct GNUNET_CADET_Channel *channel,
1762                    void **channel_ctx,
1763                    const struct GNUNET_MessageHeader *message)
1764 {
1765   struct ChannelState *ts = *channel_ctx;
1766   const struct GNUNET_EXIT_IcmpToVPNMessage *i2v;
1767   size_t mlen;
1768
1769   GNUNET_STATISTICS_update (stats,
1770                             gettext_noop ("# ICMP packets received from cadet"),
1771                             1, GNUNET_NO);
1772   mlen = ntohs (message->size);
1773   if (mlen < sizeof (struct GNUNET_EXIT_IcmpToVPNMessage))
1774   {
1775     GNUNET_break_op (0);
1776     return GNUNET_SYSERR;
1777   }
1778   if (NULL == ts->heap_node)
1779   {
1780     GNUNET_break_op (0);
1781     return GNUNET_SYSERR;
1782   }
1783   if (AF_UNSPEC == ts->af)
1784   {
1785     GNUNET_break_op (0);
1786     return GNUNET_SYSERR;
1787   }
1788   i2v = (const struct GNUNET_EXIT_IcmpToVPNMessage *) message;
1789   mlen -= sizeof (struct GNUNET_EXIT_IcmpToVPNMessage);
1790   {
1791     char sbuf[INET6_ADDRSTRLEN];
1792     char dbuf[INET6_ADDRSTRLEN];
1793
1794     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1795                 "Received ICMP packet from cadet, sending %u bytes from %s -> %s via TUN\n",
1796                 (unsigned int) mlen,
1797                 inet_ntop (ts->af, &ts->destination_ip, sbuf, sizeof (sbuf)),
1798                 inet_ntop (ts->af, &ts->source_ip, dbuf, sizeof (dbuf)));
1799   }
1800   switch (ts->af)
1801   {
1802   case AF_INET:
1803     {
1804       size_t size = sizeof (struct GNUNET_TUN_IPv4Header)
1805         + sizeof (struct GNUNET_TUN_IcmpHeader)
1806         + sizeof (struct GNUNET_MessageHeader) +
1807         sizeof (struct GNUNET_TUN_Layer2PacketHeader) +
1808         mlen;
1809       {
1810         /* reserve some extra space in case we have an ICMP type here where
1811            we will need to make up the payload ourselves */
1812         char buf[size + sizeof (struct GNUNET_TUN_IPv4Header) + 8] GNUNET_ALIGN;
1813         struct GNUNET_MessageHeader *msg = (struct GNUNET_MessageHeader *) buf;
1814         struct GNUNET_TUN_Layer2PacketHeader *tun = (struct GNUNET_TUN_Layer2PacketHeader*) &msg[1];
1815         struct GNUNET_TUN_IPv4Header *ipv4 = (struct GNUNET_TUN_IPv4Header *) &tun[1];
1816         struct GNUNET_TUN_IcmpHeader *icmp = (struct GNUNET_TUN_IcmpHeader *) &ipv4[1];
1817         msg->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
1818         tun->flags = htons (0);
1819         tun->proto = htons (ETH_P_IPV4);
1820         GNUNET_TUN_initialize_ipv4_header (ipv4,
1821                                            IPPROTO_ICMP,
1822                                            sizeof (struct GNUNET_TUN_IcmpHeader) + mlen,
1823                                            &ts->destination_ip.v4,
1824                                            &ts->source_ip.v4);
1825         *icmp = i2v->icmp_header;
1826         memcpy (&icmp[1],
1827                 &i2v[1],
1828                 mlen);
1829         /* For some ICMP types, we need to adjust (make up) the payload here.
1830            Also, depending on the AF used on the other side, we have to
1831            do ICMP PT (translate ICMP types) */
1832         switch (ntohl (i2v->af))
1833         {
1834         case AF_INET:
1835           switch (icmp->type)
1836           {
1837           case GNUNET_TUN_ICMPTYPE_ECHO_REPLY:
1838           case GNUNET_TUN_ICMPTYPE_ECHO_REQUEST:
1839             break;
1840           case GNUNET_TUN_ICMPTYPE_DESTINATION_UNREACHABLE:
1841           case GNUNET_TUN_ICMPTYPE_SOURCE_QUENCH:
1842           case GNUNET_TUN_ICMPTYPE_TIME_EXCEEDED:
1843             {
1844               struct GNUNET_TUN_IPv4Header *ipp = (struct GNUNET_TUN_IPv4Header *) &icmp[1];
1845               struct GNUNET_TUN_UdpHeader *udp = (struct GNUNET_TUN_UdpHeader *) &ipp[1];
1846
1847               if (mlen != 0)
1848                 {
1849                   /* sender did not strip ICMP payload? */
1850                   GNUNET_break_op (0);
1851                   return GNUNET_SYSERR;
1852                 }
1853               size += sizeof (struct GNUNET_TUN_IPv4Header) + 8;
1854               GNUNET_assert (8 == sizeof (struct GNUNET_TUN_UdpHeader));
1855               make_up_icmpv4_payload (ts, ipp, udp);
1856             }
1857             break;
1858           default:
1859             GNUNET_break_op (0);
1860             GNUNET_STATISTICS_update (stats,
1861                                       gettext_noop ("# ICMPv4 packets dropped (type not allowed)"),
1862                                       1, GNUNET_NO);
1863             return GNUNET_SYSERR;
1864           }
1865           /* end AF_INET */
1866           break;
1867         case AF_INET6:
1868           /* ICMP PT 6-to-4 and possibly making up payloads */
1869           switch (icmp->type)
1870           {
1871           case GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE:
1872             icmp->type = GNUNET_TUN_ICMPTYPE_DESTINATION_UNREACHABLE;
1873             {
1874               struct GNUNET_TUN_IPv4Header *ipp = (struct GNUNET_TUN_IPv4Header *) &icmp[1];
1875               struct GNUNET_TUN_UdpHeader *udp = (struct GNUNET_TUN_UdpHeader *) &ipp[1];
1876
1877               if (mlen != 0)
1878                 {
1879                   /* sender did not strip ICMP payload? */
1880                   GNUNET_break_op (0);
1881                   return GNUNET_SYSERR;
1882                 }
1883               size += sizeof (struct GNUNET_TUN_IPv4Header) + 8;
1884               GNUNET_assert (8 == sizeof (struct GNUNET_TUN_UdpHeader));
1885               make_up_icmpv4_payload (ts, ipp, udp);
1886             }
1887             break;
1888           case GNUNET_TUN_ICMPTYPE6_TIME_EXCEEDED:
1889             icmp->type = GNUNET_TUN_ICMPTYPE_TIME_EXCEEDED;
1890             {
1891               struct GNUNET_TUN_IPv4Header *ipp = (struct GNUNET_TUN_IPv4Header *) &icmp[1];
1892               struct GNUNET_TUN_UdpHeader *udp = (struct GNUNET_TUN_UdpHeader *) &ipp[1];
1893
1894               if (mlen != 0)
1895                 {
1896                   /* sender did not strip ICMP payload? */
1897                   GNUNET_break_op (0);
1898                   return GNUNET_SYSERR;
1899                 }
1900               size += sizeof (struct GNUNET_TUN_IPv4Header) + 8;
1901               GNUNET_assert (8 == sizeof (struct GNUNET_TUN_UdpHeader));
1902               make_up_icmpv4_payload (ts, ipp, udp);
1903             }
1904             break;
1905           case GNUNET_TUN_ICMPTYPE6_PACKET_TOO_BIG:
1906           case GNUNET_TUN_ICMPTYPE6_PARAMETER_PROBLEM:
1907             GNUNET_STATISTICS_update (stats,
1908                                       gettext_noop ("# ICMPv6 packets dropped (impossible PT to v4)"),
1909                                       1, GNUNET_NO);
1910             return GNUNET_OK;
1911           case GNUNET_TUN_ICMPTYPE6_ECHO_REQUEST:
1912             icmp->type = GNUNET_TUN_ICMPTYPE_ECHO_REQUEST;
1913             break;
1914           case GNUNET_TUN_ICMPTYPE6_ECHO_REPLY:
1915             icmp->type = GNUNET_TUN_ICMPTYPE_ECHO_REPLY;
1916             break;
1917           default:
1918             GNUNET_break_op (0);
1919             GNUNET_STATISTICS_update (stats,
1920                                       gettext_noop ("# ICMPv6 packets dropped (type not allowed)"),
1921                                       1, GNUNET_NO);
1922             return GNUNET_SYSERR;
1923           }
1924           /* end AF_INET6 */
1925           break;
1926         default:
1927           GNUNET_break_op (0);
1928           return GNUNET_SYSERR;
1929         }
1930         msg->size = htons (size);
1931         GNUNET_TUN_calculate_icmp_checksum (icmp,
1932                                             &i2v[1],
1933                                             mlen);
1934         (void) GNUNET_HELPER_send (helper_handle,
1935                                    msg,
1936                                    GNUNET_YES,
1937                                    NULL, NULL);
1938       }
1939     }
1940     break;
1941   case AF_INET6:
1942     {
1943       size_t size = sizeof (struct GNUNET_TUN_IPv6Header)
1944         + sizeof (struct GNUNET_TUN_IcmpHeader)
1945         + sizeof (struct GNUNET_MessageHeader) +
1946         sizeof (struct GNUNET_TUN_Layer2PacketHeader) +
1947         mlen;
1948       {
1949         char buf[size + sizeof (struct GNUNET_TUN_IPv6Header) + 8] GNUNET_ALIGN;
1950         struct GNUNET_MessageHeader *msg = (struct GNUNET_MessageHeader *) buf;
1951         struct GNUNET_TUN_Layer2PacketHeader *tun = (struct GNUNET_TUN_Layer2PacketHeader*) &msg[1];
1952         struct GNUNET_TUN_IPv6Header *ipv6 = (struct GNUNET_TUN_IPv6Header *) &tun[1];
1953         struct GNUNET_TUN_IcmpHeader *icmp = (struct GNUNET_TUN_IcmpHeader *) &ipv6[1];
1954         msg->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
1955         tun->flags = htons (0);
1956         tun->proto = htons (ETH_P_IPV6);
1957         GNUNET_TUN_initialize_ipv6_header (ipv6,
1958                                            IPPROTO_ICMPV6,
1959                                            sizeof (struct GNUNET_TUN_IcmpHeader) + mlen,
1960                                            &ts->destination_ip.v6,
1961                                            &ts->source_ip.v6);
1962         *icmp = i2v->icmp_header;
1963         memcpy (&icmp[1],
1964                 &i2v[1],
1965                 mlen);
1966
1967         /* For some ICMP types, we need to adjust (make up) the payload here.
1968            Also, depending on the AF used on the other side, we have to
1969            do ICMP PT (translate ICMP types) */
1970         switch (ntohl (i2v->af))
1971         {
1972         case AF_INET:
1973           /* ICMP PT 4-to-6 and possibly making up payloads */
1974           switch (icmp->type)
1975           {
1976           case GNUNET_TUN_ICMPTYPE_ECHO_REPLY:
1977             icmp->type = GNUNET_TUN_ICMPTYPE6_ECHO_REPLY;
1978             break;
1979           case GNUNET_TUN_ICMPTYPE_ECHO_REQUEST:
1980             icmp->type = GNUNET_TUN_ICMPTYPE6_ECHO_REQUEST;
1981             break;
1982           case GNUNET_TUN_ICMPTYPE_DESTINATION_UNREACHABLE:
1983             icmp->type = GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE;
1984             {
1985               struct GNUNET_TUN_IPv6Header *ipp = (struct GNUNET_TUN_IPv6Header *) &icmp[1];
1986               struct GNUNET_TUN_UdpHeader *udp = (struct GNUNET_TUN_UdpHeader *) &ipp[1];
1987
1988               if (mlen != 0)
1989                 {
1990                   /* sender did not strip ICMP payload? */
1991                   GNUNET_break_op (0);
1992                   return GNUNET_SYSERR;
1993                 }
1994               size += sizeof (struct GNUNET_TUN_IPv6Header) + 8;
1995               GNUNET_assert (8 == sizeof (struct GNUNET_TUN_UdpHeader));
1996               make_up_icmpv6_payload (ts, ipp, udp);
1997             }
1998             break;
1999           case GNUNET_TUN_ICMPTYPE_TIME_EXCEEDED:
2000             icmp->type = GNUNET_TUN_ICMPTYPE6_TIME_EXCEEDED;
2001             {
2002               struct GNUNET_TUN_IPv6Header *ipp = (struct GNUNET_TUN_IPv6Header *) &icmp[1];
2003               struct GNUNET_TUN_UdpHeader *udp = (struct GNUNET_TUN_UdpHeader *) &ipp[1];
2004
2005               if (mlen != 0)
2006                 {
2007                   /* sender did not strip ICMP payload? */
2008                   GNUNET_break_op (0);
2009                   return GNUNET_SYSERR;
2010                 }
2011               size += sizeof (struct GNUNET_TUN_IPv6Header) + 8;
2012               GNUNET_assert (8 == sizeof (struct GNUNET_TUN_UdpHeader));
2013               make_up_icmpv6_payload (ts, ipp, udp);
2014             }
2015             break;
2016           case GNUNET_TUN_ICMPTYPE_SOURCE_QUENCH:
2017             GNUNET_STATISTICS_update (stats,
2018                                       gettext_noop ("# ICMPv4 packets dropped (impossible PT to v6)"),
2019                                       1, GNUNET_NO);
2020             return GNUNET_OK;
2021           default:
2022             GNUNET_break_op (0);
2023             GNUNET_STATISTICS_update (stats,
2024                                       gettext_noop ("# ICMPv4 packets dropped (type not allowed)"),
2025                                       1, GNUNET_NO);
2026             return GNUNET_SYSERR;
2027           }
2028           /* end AF_INET */
2029           break;
2030         case AF_INET6:
2031           switch (icmp->type)
2032           {
2033           case GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE:
2034           case GNUNET_TUN_ICMPTYPE6_TIME_EXCEEDED:
2035           case GNUNET_TUN_ICMPTYPE6_PACKET_TOO_BIG:
2036           case GNUNET_TUN_ICMPTYPE6_PARAMETER_PROBLEM:
2037             {
2038               struct GNUNET_TUN_IPv6Header *ipp = (struct GNUNET_TUN_IPv6Header *) &icmp[1];
2039               struct GNUNET_TUN_UdpHeader *udp = (struct GNUNET_TUN_UdpHeader *) &ipp[1];
2040
2041               if (mlen != 0)
2042                 {
2043                   /* sender did not strip ICMP payload? */
2044                   GNUNET_break_op (0);
2045                   return GNUNET_SYSERR;
2046                 }
2047               size += sizeof (struct GNUNET_TUN_IPv6Header) + 8;
2048               GNUNET_assert (8 == sizeof (struct GNUNET_TUN_UdpHeader));
2049               make_up_icmpv6_payload (ts, ipp, udp);
2050             }
2051             break;
2052           case GNUNET_TUN_ICMPTYPE6_ECHO_REQUEST:
2053             break;
2054           default:
2055             GNUNET_break_op (0);
2056             GNUNET_STATISTICS_update (stats,
2057                                       gettext_noop ("# ICMPv6 packets dropped (type not allowed)"),
2058                                       1, GNUNET_NO);
2059             return GNUNET_SYSERR;
2060           }
2061           /* end AF_INET6 */
2062           break;
2063         default:
2064           GNUNET_break_op (0);
2065           return GNUNET_SYSERR;
2066         }
2067         msg->size = htons (size);
2068         GNUNET_TUN_calculate_icmp_checksum (icmp,
2069                                             &i2v[1], mlen);
2070         (void) GNUNET_HELPER_send (helper_handle,
2071                                    msg,
2072                                    GNUNET_YES,
2073                                    NULL, NULL);
2074       }
2075     }
2076     break;
2077   default:
2078     GNUNET_assert (0);
2079   }
2080   GNUNET_CONTAINER_heap_update_cost (channel_heap,
2081                                      ts->heap_node,
2082                                      GNUNET_TIME_absolute_get ().abs_value_us);
2083   GNUNET_CADET_receive_done (channel);
2084   return GNUNET_OK;
2085 }
2086
2087
2088 /**
2089  * We got a UDP packet back from the CADET channel.  Pass it on to the
2090  * local virtual interface via the helper.
2091  *
2092  * @param cls closure, NULL
2093  * @param channel connection to the other end
2094  * @param channel_ctx pointer to our 'struct ChannelState *'
2095  * @param message the actual message
2096  * @return #GNUNET_OK to keep the connection open,
2097  *         #GNUNET_SYSERR to close it (signal serious error)
2098  */
2099 static int
2100 receive_udp_back (void *cls,
2101                   struct GNUNET_CADET_Channel *channel,
2102                   void **channel_ctx,
2103                   const struct GNUNET_MessageHeader *message)
2104 {
2105   struct ChannelState *ts = *channel_ctx;
2106   const struct GNUNET_EXIT_UdpReplyMessage *reply;
2107   size_t mlen;
2108
2109   GNUNET_STATISTICS_update (stats,
2110                             gettext_noop ("# UDP packets received from cadet"),
2111                             1, GNUNET_NO);
2112   mlen = ntohs (message->size);
2113   if (mlen < sizeof (struct GNUNET_EXIT_UdpReplyMessage))
2114   {
2115     GNUNET_break_op (0);
2116     return GNUNET_SYSERR;
2117   }
2118   if (NULL == ts->heap_node)
2119   {
2120     GNUNET_break_op (0);
2121     return GNUNET_SYSERR;
2122   }
2123   if (AF_UNSPEC == ts->af)
2124   {
2125     GNUNET_break_op (0);
2126     return GNUNET_SYSERR;
2127   }
2128   reply = (const struct GNUNET_EXIT_UdpReplyMessage *) message;
2129   mlen -= sizeof (struct GNUNET_EXIT_UdpReplyMessage);
2130   {
2131     char sbuf[INET6_ADDRSTRLEN];
2132     char dbuf[INET6_ADDRSTRLEN];
2133
2134     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2135                 "Received UDP reply from cadet, sending %u bytes from [%s]:%u -> [%s]:%u via TUN\n",
2136                 (unsigned int) mlen,
2137                 inet_ntop (ts->af, &ts->destination_ip, sbuf, sizeof (sbuf)),
2138                 ts->destination_port,
2139                 inet_ntop (ts->af, &ts->source_ip, dbuf, sizeof (dbuf)),
2140                 ts->source_port);
2141   }
2142   switch (ts->af)
2143   {
2144   case AF_INET:
2145     {
2146       size_t size = sizeof (struct GNUNET_TUN_IPv4Header)
2147         + sizeof (struct GNUNET_TUN_UdpHeader)
2148         + sizeof (struct GNUNET_MessageHeader) +
2149         sizeof (struct GNUNET_TUN_Layer2PacketHeader) +
2150         mlen;
2151       {
2152         char buf[size] GNUNET_ALIGN;
2153         struct GNUNET_MessageHeader *msg = (struct GNUNET_MessageHeader *) buf;
2154         struct GNUNET_TUN_Layer2PacketHeader *tun = (struct GNUNET_TUN_Layer2PacketHeader*) &msg[1];
2155         struct GNUNET_TUN_IPv4Header *ipv4 = (struct GNUNET_TUN_IPv4Header *) &tun[1];
2156         struct GNUNET_TUN_UdpHeader *udp = (struct GNUNET_TUN_UdpHeader *) &ipv4[1];
2157         msg->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
2158         msg->size = htons (size);
2159         tun->flags = htons (0);
2160         tun->proto = htons (ETH_P_IPV4);
2161         GNUNET_TUN_initialize_ipv4_header (ipv4,
2162                                            IPPROTO_UDP,
2163                                            sizeof (struct GNUNET_TUN_UdpHeader) + mlen,
2164                                            &ts->destination_ip.v4,
2165                                            &ts->source_ip.v4);
2166         if (0 == ntohs (reply->source_port))
2167           udp->source_port = htons (ts->destination_port);
2168         else
2169           udp->source_port = reply->source_port;
2170         if (0 == ntohs (reply->destination_port))
2171           udp->destination_port = htons (ts->source_port);
2172         else
2173           udp->destination_port = reply->destination_port;
2174         udp->len = htons (mlen + sizeof (struct GNUNET_TUN_UdpHeader));
2175         GNUNET_TUN_calculate_udp4_checksum (ipv4,
2176                                             udp,
2177                                             &reply[1],
2178                                             mlen);
2179         memcpy (&udp[1],
2180                 &reply[1],
2181                 mlen);
2182         (void) GNUNET_HELPER_send (helper_handle,
2183                                    msg,
2184                                    GNUNET_YES,
2185                                    NULL, NULL);
2186       }
2187     }
2188     break;
2189   case AF_INET6:
2190     {
2191       size_t size = sizeof (struct GNUNET_TUN_IPv6Header)
2192         + sizeof (struct GNUNET_TUN_UdpHeader)
2193         + sizeof (struct GNUNET_MessageHeader) +
2194         sizeof (struct GNUNET_TUN_Layer2PacketHeader) +
2195         mlen;
2196       {
2197         char buf[size] GNUNET_ALIGN;
2198         struct GNUNET_MessageHeader *msg = (struct GNUNET_MessageHeader *) buf;
2199         struct GNUNET_TUN_Layer2PacketHeader *tun = (struct GNUNET_TUN_Layer2PacketHeader*) &msg[1];
2200         struct GNUNET_TUN_IPv6Header *ipv6 = (struct GNUNET_TUN_IPv6Header *) &tun[1];
2201         struct GNUNET_TUN_UdpHeader *udp = (struct GNUNET_TUN_UdpHeader *) &ipv6[1];
2202         msg->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
2203         msg->size = htons (size);
2204         tun->flags = htons (0);
2205         tun->proto = htons (ETH_P_IPV6);
2206         GNUNET_TUN_initialize_ipv6_header (ipv6,
2207                                            IPPROTO_UDP,
2208                                            sizeof (struct GNUNET_TUN_UdpHeader) + mlen,
2209                                            &ts->destination_ip.v6,
2210                                            &ts->source_ip.v6);
2211         if (0 == ntohs (reply->source_port))
2212           udp->source_port = htons (ts->destination_port);
2213         else
2214           udp->source_port = reply->source_port;
2215         if (0 == ntohs (reply->destination_port))
2216           udp->destination_port = htons (ts->source_port);
2217         else
2218           udp->destination_port = reply->destination_port;
2219         udp->len = htons (mlen + sizeof (struct GNUNET_TUN_UdpHeader));
2220         GNUNET_TUN_calculate_udp6_checksum (ipv6,
2221                                             udp,
2222                                             &reply[1], mlen);
2223         memcpy (&udp[1],
2224                 &reply[1],
2225                 mlen);
2226         (void) GNUNET_HELPER_send (helper_handle,
2227                                    msg,
2228                                    GNUNET_YES,
2229                                    NULL, NULL);
2230       }
2231     }
2232     break;
2233   default:
2234     GNUNET_assert (0);
2235   }
2236   GNUNET_CONTAINER_heap_update_cost (channel_heap,
2237                                      ts->heap_node,
2238                                      GNUNET_TIME_absolute_get ().abs_value_us);
2239   GNUNET_CADET_receive_done (channel);
2240   return GNUNET_OK;
2241 }
2242
2243
2244 /**
2245  * We got a TCP packet back from the CADET channel.  Pass it on to the
2246  * local virtual interface via the helper.
2247  *
2248  * @param cls closure, NULL
2249  * @param channel connection to the other end
2250  * @param channel_ctx pointer to our `struct ChannelState *`
2251  * @param message the actual message
2252  * @return #GNUNET_OK to keep the connection open,
2253  *         #GNUNET_SYSERR to close it (signal serious error)
2254  */
2255 static int
2256 receive_tcp_back (void *cls,
2257                   struct GNUNET_CADET_Channel *channel,
2258                   void **channel_ctx,
2259                   const struct GNUNET_MessageHeader *message)
2260 {
2261   struct ChannelState *ts = *channel_ctx;
2262   const struct GNUNET_EXIT_TcpDataMessage *data;
2263   size_t mlen;
2264
2265   GNUNET_STATISTICS_update (stats,
2266                             gettext_noop ("# TCP packets received from cadet"),
2267                             1, GNUNET_NO);
2268   mlen = ntohs (message->size);
2269   if (mlen < sizeof (struct GNUNET_EXIT_TcpDataMessage))
2270   {
2271     GNUNET_break_op (0);
2272     return GNUNET_SYSERR;
2273   }
2274   if (NULL == ts->heap_node)
2275   {
2276     GNUNET_break_op (0);
2277     return GNUNET_SYSERR;
2278   }
2279   data = (const struct GNUNET_EXIT_TcpDataMessage *) message;
2280   mlen -= sizeof (struct GNUNET_EXIT_TcpDataMessage);
2281   {
2282     char sbuf[INET6_ADDRSTRLEN];
2283     char dbuf[INET6_ADDRSTRLEN];
2284
2285     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2286                 "Received TCP reply from cadet, sending %u bytes from [%s]:%u -> [%s]:%u via TUN\n",
2287                 (unsigned int) mlen,
2288                 inet_ntop (ts->af, &ts->destination_ip, sbuf, sizeof (sbuf)),
2289                 ts->destination_port,
2290                 inet_ntop (ts->af, &ts->source_ip, dbuf, sizeof (dbuf)),
2291                 ts->source_port);
2292   }
2293   if (data->tcp_header.off * 4 < sizeof (struct GNUNET_TUN_TcpHeader))
2294   {
2295     GNUNET_break_op (0);
2296     return GNUNET_SYSERR;
2297   }
2298   switch (ts->af)
2299   {
2300   case AF_INET:
2301     {
2302       size_t size = sizeof (struct GNUNET_TUN_IPv4Header)
2303         + sizeof (struct GNUNET_TUN_TcpHeader)
2304         + sizeof (struct GNUNET_MessageHeader) +
2305         sizeof (struct GNUNET_TUN_Layer2PacketHeader) +
2306         mlen;
2307       {
2308         char buf[size] GNUNET_ALIGN;
2309         struct GNUNET_MessageHeader *msg = (struct GNUNET_MessageHeader *) buf;
2310         struct GNUNET_TUN_Layer2PacketHeader *tun = (struct GNUNET_TUN_Layer2PacketHeader*) &msg[1];
2311         struct GNUNET_TUN_IPv4Header *ipv4 = (struct GNUNET_TUN_IPv4Header *) &tun[1];
2312         struct GNUNET_TUN_TcpHeader *tcp = (struct GNUNET_TUN_TcpHeader *) &ipv4[1];
2313         msg->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
2314         msg->size = htons (size);
2315         tun->flags = htons (0);
2316         tun->proto = htons (ETH_P_IPV4);
2317         GNUNET_TUN_initialize_ipv4_header (ipv4,
2318                                            IPPROTO_TCP,
2319                                            sizeof (struct GNUNET_TUN_TcpHeader) + mlen,
2320                                            &ts->destination_ip.v4,
2321                                            &ts->source_ip.v4);
2322         *tcp = data->tcp_header;
2323         tcp->source_port = htons (ts->destination_port);
2324         tcp->destination_port = htons (ts->source_port);
2325         GNUNET_TUN_calculate_tcp4_checksum (ipv4,
2326                                             tcp,
2327                                             &data[1],
2328                                             mlen);
2329         memcpy (&tcp[1],
2330                 &data[1],
2331                 mlen);
2332         (void) GNUNET_HELPER_send (helper_handle,
2333                                    msg,
2334                                    GNUNET_YES,
2335                                    NULL, NULL);
2336       }
2337     }
2338     break;
2339   case AF_INET6:
2340     {
2341       size_t size = sizeof (struct GNUNET_TUN_IPv6Header)
2342         + sizeof (struct GNUNET_TUN_TcpHeader)
2343         + sizeof (struct GNUNET_MessageHeader) +
2344         sizeof (struct GNUNET_TUN_Layer2PacketHeader) +
2345         mlen;
2346       {
2347         char buf[size] GNUNET_ALIGN;
2348         struct GNUNET_MessageHeader *msg = (struct GNUNET_MessageHeader *) buf;
2349         struct GNUNET_TUN_Layer2PacketHeader *tun = (struct GNUNET_TUN_Layer2PacketHeader*) &msg[1];
2350         struct GNUNET_TUN_IPv6Header *ipv6 = (struct GNUNET_TUN_IPv6Header *) &tun[1];
2351         struct GNUNET_TUN_TcpHeader *tcp = (struct GNUNET_TUN_TcpHeader *) &ipv6[1];
2352         msg->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
2353         msg->size = htons (size);
2354         tun->flags = htons (0);
2355         tun->proto = htons (ETH_P_IPV6);
2356         GNUNET_TUN_initialize_ipv6_header (ipv6,
2357                                            IPPROTO_TCP,
2358                                            sizeof (struct GNUNET_TUN_TcpHeader) + mlen,
2359                                            &ts->destination_ip.v6,
2360                                            &ts->source_ip.v6);
2361         *tcp = data->tcp_header;
2362         tcp->source_port = htons (ts->destination_port);
2363         tcp->destination_port = htons (ts->source_port);
2364         GNUNET_TUN_calculate_tcp6_checksum (ipv6,
2365                                             tcp,
2366                                             &data[1],
2367                                             mlen);
2368         memcpy (&tcp[1],
2369                 &data[1],
2370                 mlen);
2371         (void) GNUNET_HELPER_send (helper_handle,
2372                                    msg,
2373                                    GNUNET_YES,
2374                                    NULL, NULL);
2375       }
2376     }
2377     break;
2378   }
2379   GNUNET_CONTAINER_heap_update_cost (channel_heap,
2380                                      ts->heap_node,
2381                                      GNUNET_TIME_absolute_get ().abs_value_us);
2382   GNUNET_CADET_receive_done (channel);
2383   return GNUNET_OK;
2384 }
2385
2386
2387 /**
2388  * Allocate an IPv4 address from the range of the channel
2389  * for a new redirection.
2390  *
2391  * @param v4 where to store the address
2392  * @return #GNUNET_OK on success,
2393  *         #GNUNET_SYSERR on error
2394  */
2395 static int
2396 allocate_v4_address (struct in_addr *v4)
2397 {
2398   const char *ipv4addr = vpn_argv[4];
2399   const char *ipv4mask = vpn_argv[5];
2400   struct in_addr addr;
2401   struct in_addr mask;
2402   struct in_addr rnd;
2403   struct GNUNET_HashCode key;
2404   unsigned int tries;
2405
2406   GNUNET_assert (1 == inet_pton (AF_INET, ipv4addr, &addr));
2407   GNUNET_assert (1 == inet_pton (AF_INET, ipv4mask, &mask));
2408   /* Given 192.168.0.1/255.255.0.0, we want a mask
2409      of '192.168.255.255', thus:  */
2410   mask.s_addr = addr.s_addr | ~mask.s_addr;
2411   tries = 0;
2412   do
2413     {
2414       tries++;
2415       if (tries > 16)
2416       {
2417         GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
2418                     _("Failed to find unallocated IPv4 address in VPN's range\n"));
2419         return GNUNET_SYSERR;
2420       }
2421       /* Pick random IPv4 address within the subnet, except 'addr' or 'mask' itself */
2422       rnd.s_addr = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
2423                                              UINT32_MAX);
2424       v4->s_addr = (addr.s_addr | rnd.s_addr) & mask.s_addr;
2425       get_destination_key_from_ip (AF_INET,
2426                                    v4,
2427                                    &key);
2428     }
2429   while ( (GNUNET_YES ==
2430            GNUNET_CONTAINER_multihashmap_contains (destination_map,
2431                                                    &key)) ||
2432           (v4->s_addr == addr.s_addr) ||
2433           (v4->s_addr == mask.s_addr) );
2434   return GNUNET_OK;
2435 }
2436
2437
2438 /**
2439  * Allocate an IPv6 address from the range of the channel
2440  * for a new redirection.
2441  *
2442  * @param v6 where to store the address
2443  * @return #GNUNET_OK on success,
2444  *         #GNUNET_SYSERR on error
2445  */
2446 static int
2447 allocate_v6_address (struct in6_addr *v6)
2448 {
2449   const char *ipv6addr = vpn_argv[2];
2450   struct in6_addr addr;
2451   struct in6_addr mask;
2452   struct in6_addr rnd;
2453   int i;
2454   struct GNUNET_HashCode key;
2455   unsigned int tries;
2456
2457   GNUNET_assert (1 == inet_pton (AF_INET6, ipv6addr, &addr));
2458   GNUNET_assert (ipv6prefix < 128);
2459   /* Given ABCD::/96, we want a mask of 'ABCD::FFFF:FFFF,
2460      thus: */
2461   mask = addr;
2462   for (i=127;i>=ipv6prefix;i--)
2463     mask.s6_addr[i / 8] |= (1 << (i % 8));
2464
2465   /* Pick random IPv6 address within the subnet, except 'addr' or 'mask' itself */
2466   tries = 0;
2467   do
2468     {
2469       tries++;
2470       if (tries > 16)
2471         {
2472           GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
2473                       _("Failed to find unallocated IPv6 address in VPN's range\n"));
2474           return GNUNET_SYSERR;
2475
2476         }
2477       for (i=0;i<16;i++)
2478         {
2479           rnd.s6_addr[i] = (unsigned char) GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
2480                                                                      256);
2481           v6->s6_addr[i]
2482             = (addr.s6_addr[i] | rnd.s6_addr[i]) & mask.s6_addr[i];
2483         }
2484       get_destination_key_from_ip (AF_INET6,
2485                                    v6,
2486                                    &key);
2487     }
2488   while ( (GNUNET_YES ==
2489            GNUNET_CONTAINER_multihashmap_contains (destination_map,
2490                                                    &key)) ||
2491           (0 == memcmp (v6,
2492                         &addr,
2493                         sizeof (struct in6_addr))) ||
2494           (0 == memcmp (v6,
2495                         &mask,
2496                         sizeof (struct in6_addr))) );
2497   return GNUNET_OK;
2498 }
2499
2500
2501 /**
2502  * Free resources occupied by a destination entry.
2503  *
2504  * @param de entry to free
2505  */
2506 static void
2507 free_destination_entry (struct DestinationEntry *de)
2508 {
2509   struct DestinationChannel *dt;
2510
2511   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2512               "Cleaning up destination entry `%s'\n",
2513               print_channel_destination (de));
2514   GNUNET_STATISTICS_update (stats,
2515                             gettext_noop ("# Active destinations"),
2516                             -1, GNUNET_NO);
2517   while (NULL != (dt = de->dt_head))
2518   {
2519     GNUNET_CONTAINER_DLL_remove (de->dt_head,
2520                                  de->dt_tail,
2521                                  dt);
2522     if (NULL != dt->ts)
2523     {
2524       free_channel_state (dt->ts);
2525       GNUNET_assert (NULL == dt->ts);
2526     }
2527     GNUNET_free (dt);
2528   }
2529   if (NULL != de->heap_node)
2530   {
2531     GNUNET_CONTAINER_heap_remove_node (de->heap_node);
2532     de->heap_node = NULL;
2533     GNUNET_assert (GNUNET_YES ==
2534                    GNUNET_CONTAINER_multihashmap_remove (destination_map,
2535                                                          &de->key,
2536                                                          de));
2537   }
2538   GNUNET_free (de);
2539 }
2540
2541
2542 /**
2543  * We have too many active destinations.  Clean up the oldest destination.
2544  *
2545  * @param except destination that must NOT be cleaned up, even if it is the oldest
2546  */
2547 static void
2548 expire_destination (struct DestinationEntry *except)
2549 {
2550   struct DestinationEntry *de;
2551
2552   de = GNUNET_CONTAINER_heap_peek (destination_heap);
2553   GNUNET_assert (NULL != de);
2554   if (except == de)
2555     return; /* can't do this */
2556   free_destination_entry (de);
2557 }
2558
2559
2560 /**
2561  * Allocate an IP address for the response.
2562  *
2563  * @param result_af desired address family; set to the actual
2564  *        address family; can initially be AF_UNSPEC if there
2565  *        is no preference; will be set to AF_UNSPEC if the
2566  *        allocation failed
2567  * @param addr set to either v4 or v6 depending on which
2568  *         storage location was used; set to NULL if allocation failed
2569  * @param v4 storage space for an IPv4 address
2570  * @param v6 storage space for an IPv6 address
2571  * @return #GNUNET_OK normally, #GNUNET_SYSERR if `* result_af` was
2572  *         an unsupported address family (not AF_INET, AF_INET6 or AF_UNSPEC)
2573  */
2574 static int
2575 allocate_response_ip (int *result_af,
2576                       void **addr,
2577                       struct in_addr *v4,
2578                       struct in6_addr *v6)
2579 {
2580   *addr = NULL;
2581   switch (*result_af)
2582   {
2583   case AF_INET:
2584     if (GNUNET_OK !=
2585         allocate_v4_address (v4))
2586       *result_af = AF_UNSPEC;
2587     else
2588       *addr = v4;
2589     break;
2590   case AF_INET6:
2591     if (GNUNET_OK !=
2592         allocate_v6_address (v6))
2593       *result_af = AF_UNSPEC;
2594     else
2595       *addr = v6;
2596     break;
2597   case AF_UNSPEC:
2598     if (GNUNET_OK ==
2599         allocate_v4_address (v4))
2600     {
2601       *addr = v4;
2602       *result_af = AF_INET;
2603     }
2604     else if (GNUNET_OK ==
2605         allocate_v6_address (v6))
2606     {
2607       *addr = v6;
2608       *result_af = AF_INET6;
2609     }
2610     break;
2611   default:
2612     GNUNET_break (0);
2613     return GNUNET_SYSERR;
2614   }
2615   return GNUNET_OK;
2616 }
2617
2618
2619 /**
2620  * A client asks us to setup a redirection via some exit node to a
2621  * particular IP.  Setup the redirection and give the client the
2622  * allocated IP.
2623  *
2624  * @param cls unused
2625  * @param client requesting client
2626  * @param message redirection request (a `struct RedirectToIpRequestMessage`)
2627  */
2628 static void
2629 service_redirect_to_ip (void *cls,
2630                         struct GNUNET_SERVER_Client *client,
2631                         const struct GNUNET_MessageHeader *message)
2632 {
2633   size_t mlen;
2634   size_t alen;
2635   const struct RedirectToIpRequestMessage *msg;
2636   int addr_af;
2637   int result_af;
2638   struct in_addr v4;
2639   struct in6_addr v6;
2640   void *addr;
2641   struct DestinationEntry *de;
2642   struct GNUNET_HashCode key;
2643
2644   /* validate and parse request */
2645   mlen = ntohs (message->size);
2646   if (mlen < sizeof (struct RedirectToIpRequestMessage))
2647   {
2648     GNUNET_break (0);
2649     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2650     return;
2651   }
2652   alen = mlen - sizeof (struct RedirectToIpRequestMessage);
2653   msg = (const struct RedirectToIpRequestMessage *) message;
2654   addr_af = (int) htonl (msg->addr_af);
2655   switch (addr_af)
2656   {
2657   case AF_INET:
2658     if (alen != sizeof (struct in_addr))
2659     {
2660       GNUNET_break (0);
2661       GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2662       return;
2663     }
2664     break;
2665   case AF_INET6:
2666     if (alen != sizeof (struct in6_addr))
2667     {
2668       GNUNET_break (0);
2669       GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2670       return;
2671     }
2672     break;
2673   default:
2674     GNUNET_break (0);
2675     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2676     return;
2677   }
2678
2679   /* allocate response IP */
2680   result_af = (int) htonl (msg->result_af);
2681   if (GNUNET_OK != allocate_response_ip (&result_af,
2682                                          &addr,
2683                                          &v4, &v6))
2684   {
2685     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2686     return;
2687   }
2688   /* send reply with our IP address */
2689   send_client_reply (client,
2690                      msg->request_id,
2691                      result_af,
2692                      addr);
2693   if (result_af == AF_UNSPEC)
2694   {
2695     /* failure, we're done */
2696     GNUNET_SERVER_receive_done (client, GNUNET_OK);
2697     return;
2698   }
2699
2700   {
2701     char sbuf[INET6_ADDRSTRLEN];
2702     char dbuf[INET6_ADDRSTRLEN];
2703
2704     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2705                 "Allocated address %s for redirection via exit to %s\n",
2706                 inet_ntop (result_af, addr, sbuf, sizeof (sbuf)),
2707                 inet_ntop (addr_af,
2708                            &msg[1], dbuf, sizeof (dbuf)));
2709   }
2710
2711   /* setup destination record */
2712   de = GNUNET_new (struct DestinationEntry);
2713   de->is_service = GNUNET_NO;
2714   de->details.exit_destination.af = addr_af;
2715   memcpy (&de->details.exit_destination.ip,
2716           &msg[1],
2717           alen);
2718   get_destination_key_from_ip (result_af,
2719                                addr,
2720                                &key);
2721   de->key = key;
2722   GNUNET_assert (GNUNET_OK ==
2723                  GNUNET_CONTAINER_multihashmap_put (destination_map,
2724                                                     &key,
2725                                                     de,
2726                                                     GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE));
2727   de->heap_node = GNUNET_CONTAINER_heap_insert (destination_heap,
2728                                                 de,
2729                                                 GNUNET_TIME_absolute_ntoh (msg->expiration_time).abs_value_us);
2730   GNUNET_STATISTICS_update (stats,
2731                             gettext_noop ("# Active destinations"),
2732                             1, GNUNET_NO);
2733   while (GNUNET_CONTAINER_multihashmap_size (destination_map) > max_destination_mappings)
2734     expire_destination (de);
2735   GNUNET_SERVER_receive_done (client, GNUNET_OK);
2736 }
2737
2738
2739 /**
2740  * A client asks us to setup a redirection to a particular peer
2741  * offering a service.  Setup the redirection and give the client the
2742  * allocated IP.
2743  *
2744  * @param cls unused
2745  * @param client requesting client
2746  * @param message redirection request (a `struct RedirectToPeerRequestMessage`)
2747  */
2748 static void
2749 service_redirect_to_service (void *cls,
2750                              struct GNUNET_SERVER_Client *client,
2751                              const struct GNUNET_MessageHeader *message)
2752 {
2753   const struct RedirectToServiceRequestMessage *msg;
2754   int result_af;
2755   struct in_addr v4;
2756   struct in6_addr v6;
2757   void *addr;
2758   struct DestinationEntry *de;
2759   struct GNUNET_HashCode key;
2760   struct DestinationChannel *dt;
2761
2762   /*  parse request */
2763   msg = (const struct RedirectToServiceRequestMessage *) message;
2764
2765   /* allocate response IP */
2766   result_af = (int) htonl (msg->result_af);
2767   if (GNUNET_OK != allocate_response_ip (&result_af,
2768                                          &addr,
2769                                          &v4, &v6))
2770   {
2771     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2772     return;
2773   }
2774   send_client_reply (client,
2775                      msg->request_id,
2776                      result_af,
2777                      addr);
2778   if (result_af == AF_UNSPEC)
2779   {
2780     /* failure, we're done */
2781     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2782                 _("Failed to allocate IP address for new destination\n"));
2783     GNUNET_SERVER_receive_done (client, GNUNET_OK);
2784     return;
2785   }
2786
2787   {
2788     char sbuf[INET6_ADDRSTRLEN];
2789
2790     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2791                 "Allocated address %s for redirection to service %s on peer %s\n",
2792                 inet_ntop (result_af, addr, sbuf, sizeof (sbuf)),
2793                 GNUNET_h2s (&msg->service_descriptor),
2794                 GNUNET_i2s (&msg->target));
2795   }
2796
2797   /* setup destination record */
2798   de = GNUNET_new (struct DestinationEntry);
2799   de->is_service = GNUNET_YES;
2800   de->details.service_destination.service_descriptor = msg->service_descriptor;
2801   de->details.service_destination.target = msg->target;
2802   get_destination_key_from_ip (result_af,
2803                                addr,
2804                                &key);
2805   de->key = key;
2806   GNUNET_assert (GNUNET_OK ==
2807                  GNUNET_CONTAINER_multihashmap_put (destination_map,
2808                                                     &key,
2809                                                     de,
2810                                                     GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE));
2811   de->heap_node = GNUNET_CONTAINER_heap_insert (destination_heap,
2812                                                 de,
2813                                                 GNUNET_TIME_absolute_ntoh (msg->expiration_time).abs_value_us);
2814   while (GNUNET_CONTAINER_multihashmap_size (destination_map) > max_destination_mappings)
2815     expire_destination (de);
2816
2817   dt = GNUNET_new (struct DestinationChannel);
2818   dt->destination = de;
2819   GNUNET_CONTAINER_DLL_insert (de->dt_head,
2820                                de->dt_tail,
2821                                dt);
2822   /* we're done */
2823   GNUNET_SERVER_receive_done (client, GNUNET_OK);
2824 }
2825
2826
2827 /**
2828  * Function called whenever a channel is destroyed.  Should clean up
2829  * any associated state.
2830  *
2831  * @param cls closure (set from #GNUNET_CADET_connect)
2832  * @param channel connection to the other end (henceforth invalid)
2833  * @param channel_ctx place where local state associated
2834  *                   with the channel is stored (our `struct ChannelState`)
2835  */
2836 static void
2837 channel_cleaner (void *cls,
2838                  const struct GNUNET_CADET_Channel *channel,
2839                  void *channel_ctx)
2840 {
2841   struct ChannelState *ts = channel_ctx;
2842
2843   ts->channel = NULL; /* we must not call GNUNET_CADET_channel_destroy() anymore */
2844   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2845               "CADET notified us about death of channel to `%s'\n",
2846               print_channel_destination (&ts->destination));
2847   free_channel_state (ts);
2848 }
2849
2850
2851 /**
2852  * Free memory occupied by an entry in the destination map.
2853  *
2854  * @param cls unused
2855  * @param key unused
2856  * @param value a `struct DestinationEntry *`
2857  * @return #GNUNET_OK (continue to iterate)
2858  */
2859 static int
2860 cleanup_destination (void *cls,
2861                      const struct GNUNET_HashCode *key,
2862                      void *value)
2863 {
2864   struct DestinationEntry *de = value;
2865
2866   free_destination_entry (de);
2867   return GNUNET_OK;
2868 }
2869
2870
2871 /**
2872  * Free memory occupied by an entry in the channel map.
2873  *
2874  * @param cls unused
2875  * @param key unused
2876  * @param value a `struct ChannelState *`
2877  * @return #GNUNET_OK (continue to iterate)
2878  */
2879 static int
2880 cleanup_channel (void *cls,
2881                  const struct GNUNET_HashCode *key,
2882                  void *value)
2883 {
2884   struct ChannelState *ts = value;
2885
2886   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2887               "Tearing down channel to `%s' during cleanup\n",
2888               print_channel_destination (&ts->destination));
2889   free_channel_state (ts);
2890   return GNUNET_OK;
2891 }
2892
2893
2894 /**
2895  * Function scheduled as very last function, cleans up after us
2896  *
2897  * @param cls unused
2898  * @param tc unused
2899  */
2900 static void
2901 cleanup (void *cls,
2902          const struct GNUNET_SCHEDULER_TaskContext *tc)
2903 {
2904   unsigned int i;
2905
2906   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2907               "VPN is shutting down\n");
2908   if (NULL != destination_map)
2909   {
2910     GNUNET_CONTAINER_multihashmap_iterate (destination_map,
2911                                            &cleanup_destination,
2912                                            NULL);
2913     GNUNET_CONTAINER_multihashmap_destroy (destination_map);
2914     destination_map = NULL;
2915   }
2916   if (NULL != destination_heap)
2917   {
2918     GNUNET_CONTAINER_heap_destroy (destination_heap);
2919     destination_heap = NULL;
2920   }
2921   if (NULL != channel_map)
2922   {
2923     GNUNET_CONTAINER_multihashmap_iterate (channel_map,
2924                                            &cleanup_channel,
2925                                            NULL);
2926     GNUNET_CONTAINER_multihashmap_destroy (channel_map);
2927     channel_map = NULL;
2928   }
2929   if (NULL != channel_heap)
2930   {
2931     GNUNET_CONTAINER_heap_destroy (channel_heap);
2932     channel_heap = NULL;
2933   }
2934   if (NULL != cadet_handle)
2935   {
2936     GNUNET_CADET_disconnect (cadet_handle);
2937     cadet_handle = NULL;
2938   }
2939   if (NULL != helper_handle)
2940   {
2941     GNUNET_HELPER_kill (helper_handle, GNUNET_NO);
2942     GNUNET_HELPER_wait (helper_handle);
2943     helper_handle = NULL;
2944   }
2945   if (NULL != nc)
2946   {
2947     GNUNET_SERVER_notification_context_destroy (nc);
2948     nc = NULL;
2949   }
2950   if (NULL != stats)
2951   {
2952     GNUNET_STATISTICS_destroy (stats, GNUNET_NO);
2953     stats = NULL;
2954   }
2955   for (i=0;i<5;i++)
2956     GNUNET_free_non_null (vpn_argv[i]);
2957 }
2958
2959
2960 /**
2961  * Main function that will be run by the scheduler.
2962  *
2963  * @param cls closure
2964  * @param server the initialized server
2965  * @param cfg_ configuration
2966  */
2967 static void
2968 run (void *cls,
2969      struct GNUNET_SERVER_Handle *server,
2970      const struct GNUNET_CONFIGURATION_Handle *cfg_)
2971 {
2972   static const struct GNUNET_SERVER_MessageHandler service_handlers[] = {
2973     /* callback, cls, type, size */
2974     { &service_redirect_to_ip, NULL, GNUNET_MESSAGE_TYPE_VPN_CLIENT_REDIRECT_TO_IP, 0},
2975     { &service_redirect_to_service, NULL,
2976      GNUNET_MESSAGE_TYPE_VPN_CLIENT_REDIRECT_TO_SERVICE,
2977      sizeof (struct RedirectToServiceRequestMessage) },
2978     {NULL, NULL, 0, 0}
2979   };
2980   static const struct GNUNET_CADET_MessageHandler cadet_handlers[] = {
2981     { &receive_udp_back, GNUNET_MESSAGE_TYPE_VPN_UDP_REPLY, 0},
2982     { &receive_tcp_back, GNUNET_MESSAGE_TYPE_VPN_TCP_DATA_TO_VPN, 0},
2983     { &receive_icmp_back, GNUNET_MESSAGE_TYPE_VPN_ICMP_TO_VPN, 0},
2984     {NULL, 0, 0}
2985   };
2986   char *ifname;
2987   char *ipv6addr;
2988   char *ipv6prefix_s;
2989   char *ipv4addr;
2990   char *ipv4mask;
2991   struct in_addr v4;
2992   struct in6_addr v6;
2993   char *binary;
2994
2995   binary = GNUNET_OS_get_libexec_binary_path ("gnunet-helper-vpn");
2996
2997   if (GNUNET_YES !=
2998       GNUNET_OS_check_helper_binary (binary,
2999                                      GNUNET_YES,
3000                                      "-d gnunet-vpn - - 169.1.3.3.7 255.255.255.0")) //ipv4 only please!
3001   {
3002     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
3003                 "`%s' is not SUID, refusing to run.\n",
3004                 "gnunet-helper-vpn");
3005     GNUNET_free (binary);
3006     global_ret = 1;
3007     /* we won't "really" exit here, as the 'service' is still running;
3008        however, as no handlers are registered, the service won't do
3009        anything either */
3010     return;
3011   }
3012   GNUNET_free (binary);
3013   cfg = cfg_;
3014   stats = GNUNET_STATISTICS_create ("vpn", cfg);
3015   if (GNUNET_OK !=
3016       GNUNET_CONFIGURATION_get_value_number (cfg, "VPN", "MAX_MAPPING",
3017                                              &max_destination_mappings))
3018     max_destination_mappings = 200;
3019   if (GNUNET_OK !=
3020       GNUNET_CONFIGURATION_get_value_number (cfg, "VPN", "MAX_TUNNELS",
3021                                              &max_channel_mappings))
3022     max_channel_mappings = 200;
3023
3024   destination_map = GNUNET_CONTAINER_multihashmap_create (max_destination_mappings * 2, GNUNET_NO);
3025   destination_heap = GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN);
3026   channel_map = GNUNET_CONTAINER_multihashmap_create (max_channel_mappings * 2, GNUNET_NO);
3027   channel_heap = GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN);
3028
3029
3030   vpn_argv[0] = GNUNET_strdup ("vpn-gnunet");
3031   if (GNUNET_SYSERR ==
3032       GNUNET_CONFIGURATION_get_value_string (cfg, "VPN", "IFNAME", &ifname))
3033   {
3034     GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, "VPN", "IFNAME");
3035     GNUNET_SCHEDULER_shutdown ();
3036     return;
3037   }
3038   vpn_argv[1] = ifname;
3039   ipv6addr = NULL;
3040   if (GNUNET_OK == GNUNET_NETWORK_test_pf (PF_INET6))
3041   {
3042     if ( (GNUNET_SYSERR ==
3043           GNUNET_CONFIGURATION_get_value_string (cfg, "VPN", "IPV6ADDR",
3044                                                  &ipv6addr) ||
3045           (1 != inet_pton (AF_INET6, ipv6addr, &v6))) )
3046     {
3047       GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, "VPN", "IPV6ADDR",
3048                                  _("Must specify valid IPv6 address"));
3049       GNUNET_SCHEDULER_shutdown ();
3050       GNUNET_free_non_null (ipv6addr);
3051       return;
3052     }
3053     vpn_argv[2] = ipv6addr;
3054     ipv6prefix_s = NULL;
3055     if (GNUNET_SYSERR ==
3056         GNUNET_CONFIGURATION_get_value_string (cfg, "VPN", "IPV6PREFIX",
3057                                                &ipv6prefix_s))
3058     {
3059       GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, "VPN", "IPV6PREFIX");
3060       GNUNET_SCHEDULER_shutdown ();
3061       GNUNET_free_non_null (ipv6prefix_s);
3062       return;
3063     }
3064     vpn_argv[3] = ipv6prefix_s;
3065     if ( (GNUNET_OK !=
3066           GNUNET_CONFIGURATION_get_value_number (cfg, "VPN",
3067                                                  "IPV6PREFIX",
3068                                                  &ipv6prefix)) ||
3069          (ipv6prefix >= 127) )
3070     {
3071       GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, "VPN", "IPV4MASK",
3072                                  _("Must specify valid IPv6 mask"));
3073       GNUNET_SCHEDULER_shutdown ();
3074       return;
3075     }
3076   }
3077   else
3078   {
3079     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
3080                 _("IPv6 support disabled as this system does not support IPv6\n"));
3081     vpn_argv[2] = GNUNET_strdup ("-");
3082     vpn_argv[3] = GNUNET_strdup ("-");
3083   }
3084   if (GNUNET_OK == GNUNET_NETWORK_test_pf (PF_INET))
3085   {
3086     ipv4addr = NULL;
3087     if ( (GNUNET_SYSERR ==
3088           GNUNET_CONFIGURATION_get_value_string (cfg, "vpn", "IPV4ADDR",
3089                                                  &ipv4addr) ||
3090           (1 != inet_pton (AF_INET, ipv4addr, &v4))) )
3091     {
3092       GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, "VPN", "IPV4ADDR",
3093                                  _("Must specify valid IPv4 address"));
3094       GNUNET_SCHEDULER_shutdown ();
3095       GNUNET_free_non_null (ipv4addr);
3096       return;
3097     }
3098     vpn_argv[4] = ipv4addr;
3099     ipv4mask = NULL;
3100     if ( (GNUNET_SYSERR ==
3101           GNUNET_CONFIGURATION_get_value_string (cfg, "vpn", "IPV4MASK",
3102                                                  &ipv4mask) ||
3103           (1 != inet_pton (AF_INET, ipv4mask, &v4))) )
3104     {
3105       GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, "VPN", "IPV4MASK",
3106                                  _("Must specify valid IPv4 mask"));
3107       GNUNET_SCHEDULER_shutdown ();
3108       GNUNET_free_non_null (ipv4mask);
3109       return;
3110     }
3111     vpn_argv[5] = ipv4mask;
3112   }
3113   else
3114   {
3115     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
3116                 _("IPv4 support disabled as this system does not support IPv4\n"));
3117     vpn_argv[4] = GNUNET_strdup ("-");
3118     vpn_argv[5] = GNUNET_strdup ("-");
3119   }
3120   vpn_argv[6] = NULL;
3121
3122   cadet_handle =
3123     GNUNET_CADET_connect (cfg_, NULL,
3124                           NULL,
3125                           &channel_cleaner,
3126                           cadet_handlers,
3127                           NULL);
3128   helper_handle = GNUNET_HELPER_start (GNUNET_NO,
3129                                        "gnunet-helper-vpn", vpn_argv,
3130                                        &message_token, NULL, NULL);
3131   nc = GNUNET_SERVER_notification_context_create (server, 1);
3132   GNUNET_SERVER_add_handlers (server, service_handlers);
3133   GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL,
3134                                 &cleanup,
3135                                 NULL);
3136 }
3137
3138
3139 /**
3140  * The main function of the VPN service.
3141  *
3142  * @param argc number of arguments from the command line
3143  * @param argv command line arguments
3144  * @return 0 ok, 1 on error
3145  */
3146 int
3147 main (int argc, char *const *argv)
3148 {
3149   return (GNUNET_OK ==
3150           GNUNET_SERVICE_run (argc, argv, "vpn",
3151                               GNUNET_SERVICE_OPTION_NONE,
3152                               &run, NULL)) ? global_ret : 1;
3153 }
3154
3155 /* end of gnunet-service-vpn.c */