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