-add support for sending ICMP packets to service/internet
[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  * Basics:
31  * - test!
32  *
33  * Features:
34  * - add back ICMP support (especially needed for IPv6)
35  */
36 #include "platform.h"
37 #include "gnunet_util_lib.h"
38 #include "gnunet_common.h"
39 #include "gnunet_protocols.h"
40 #include "gnunet_applications.h"
41 #include "gnunet_mesh_service.h"
42 #include "gnunet_statistics_service.h"
43 #include "gnunet_constants.h"
44 #include "gnunet_tun_lib.h"
45 #include "vpn.h"
46 #include "exit.h"
47
48
49 /**
50  * Maximum number of messages we allow in the queue for mesh.
51  */
52 #define MAX_MESSAGE_QUEUE_SIZE 4
53
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   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       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 transmission handle, NULL for none.
182    */
183   struct GNUNET_MESH_TransmitHandle *th;
184
185   /**
186    * Entry for this entry in the tunnel_heap, NULL as long as this
187    * tunnel state is not fully bound.
188    */
189   struct GNUNET_CONTAINER_HeapNode *heap_node;
190
191   /**
192    * Head of list of messages scheduled for transmission.
193    */
194   struct TunnelMessageQueueEntry *tmq_head;
195
196   /**
197    * Tail of list of messages scheduled for transmission.
198    */
199   struct TunnelMessageQueueEntry *tmq_tail;  
200
201   /**
202    * Client that needs to be notified about the tunnel being
203    * up as soon as a peer is connected; NULL for none.
204    */
205   struct GNUNET_SERVER_Client *client;
206
207   /**
208    * Destination entry that has a pointer to this tunnel state;
209    * NULL if this tunnel state is in the tunnel map.
210    */
211   struct DestinationEntry *destination_container;
212
213   /**
214    * ID of the client request that caused us to setup this entry.
215    */ 
216   uint64_t request_id;
217
218   /**
219    * Destination to which this tunnel leads.  Note that
220    * this struct is NOT in the destination_map (but a
221    * local copy) and that the 'heap_node' should always
222    * be NULL.
223    */
224   struct DestinationEntry destination;
225
226   /**
227    * Task scheduled to destroy the tunnel (or NO_TASK).
228    */
229   GNUNET_SCHEDULER_TaskIdentifier destroy_task;
230
231   /**
232    * Addess family used for this tunnel on the local TUN interface.
233    */
234   int af;
235
236   /**
237    * Length of the doubly linked 'tmq_head/tmq_tail' list.
238    */
239   unsigned int tmq_length;
240
241   /**
242    * IPPROTO_TCP or IPPROTO_UDP once bound.
243    */
244   uint8_t protocol;
245
246   /**
247    * IP address of the source on our end, initially uninitialized.
248    */
249   union
250   {
251     /**
252      * Address if af is AF_INET.
253      */
254     struct in_addr v4;
255     
256     /**
257      * Address if af is AF_INET6.
258      */
259     struct in6_addr v6;
260
261   } source_ip;
262
263   /**
264    * Destination IP address used by the source on our end (this is the IP
265    * that we pick freely within the VPN's tunnel IP range).
266    */
267   union
268   {
269     /**
270      * Address if af is AF_INET.
271      */
272     struct in_addr v4;
273     
274     /**
275      * Address if af is AF_INET6.
276      */
277     struct in6_addr v6;
278
279   } destination_ip;
280
281   /**
282    * Source port used by the sender on our end; 0 for uninitialized.
283    */
284   uint16_t source_port;
285
286   /**
287    * Destination port used by the sender on our end; 0 for uninitialized.
288    */
289   uint16_t destination_port;
290
291 };
292
293
294 /**
295  * Configuration we use.
296  */
297 static const struct GNUNET_CONFIGURATION_Handle *cfg;
298
299 /**
300  * Handle to the mesh service.
301  */
302 static struct GNUNET_MESH_Handle *mesh_handle;
303
304 /**
305  * Map from IP address to destination information (possibly with a
306  * MESH tunnel handle for fast setup).
307  */
308 static struct GNUNET_CONTAINER_MultiHashMap *destination_map;
309
310 /**
311  * Min-Heap sorted by activity time to expire old mappings.
312  */
313 static struct GNUNET_CONTAINER_Heap *destination_heap;
314
315 /**
316  * Map from source and destination address (IP+port) to connection
317  * information (mostly with the respective MESH tunnel handle).
318  */
319 static struct GNUNET_CONTAINER_MultiHashMap *tunnel_map;
320
321 /**
322  * Min-Heap sorted by activity time to expire old mappings; values are
323  * of type 'struct TunnelState'.
324  */
325 static struct GNUNET_CONTAINER_Heap *tunnel_heap;
326
327 /**
328  * Statistics.
329  */
330 static struct GNUNET_STATISTICS_Handle *stats;
331
332 /**
333  * The handle to the VPN helper process "gnunet-helper-vpn".
334  */
335 static struct GNUNET_HELPER_Handle *helper_handle;
336
337 /**
338  * Arguments to the vpn helper.
339  */
340 static char *vpn_argv[7];
341
342 /**
343  * Length of the prefix of the VPN's IPv6 network.
344  */
345 static unsigned long long ipv6prefix;
346
347 /**
348  * Notification context for sending replies to clients.
349  */
350 static struct GNUNET_SERVER_NotificationContext *nc;
351
352 /**
353  * If there are more than this number of address-mappings, old ones
354  * will be removed
355  */
356 static unsigned long long max_destination_mappings;
357
358 /**
359  * If there are more than this number of open tunnels, old ones
360  * will be removed
361  */
362 static unsigned long long max_tunnel_mappings;
363
364
365 /**
366  * Compute the key under which we would store an entry in the
367  * destination_map for the given IP address.
368  *
369  * @param af address family (AF_INET or AF_INET6)
370  * @param address IP address, struct in_addr or struct in6_addr
371  * @param key where to store the key
372  */
373 static void
374 get_destination_key_from_ip (int af,
375                              const void *address,
376                              GNUNET_HashCode *key)
377 {
378   switch (af)
379   {
380   case AF_INET:
381     GNUNET_CRYPTO_hash (address,
382                         sizeof (struct in_addr),
383                         key);
384     break;
385   case AF_INET6:
386     GNUNET_CRYPTO_hash (address,
387                         sizeof (struct in6_addr),
388                         key);
389     break;
390   default:
391     GNUNET_assert (0);
392     break;
393   }
394 }
395
396
397 /**
398  * Compute the key under which we would store an entry in the
399  * tunnel_map for the given socket address pair.
400  *
401  * @param af address family (AF_INET or AF_INET6)
402  * @param protocol IPPROTO_TCP or IPPROTO_UDP
403  * @param source_ip sender's source IP, struct in_addr or struct in6_addr
404  * @param source_port sender's source port
405  * @param destination_ip sender's destination IP, struct in_addr or struct in6_addr
406  * @param destination_port sender's destination port
407  * @param key where to store the key
408  */
409 static void
410 get_tunnel_key_from_ips (int af,
411                          uint8_t protocol,
412                          const void *source_ip,
413                          uint16_t source_port,
414                          const void *destination_ip,
415                          uint16_t destination_port,
416                          GNUNET_HashCode *key)
417 {
418   char *off;
419
420   memset (key, 0, sizeof (GNUNET_HashCode));
421   /* the GNUnet hashmap only uses the first sizeof(unsigned int) of the hash,
422      so we put the ports in there (and hope for few collisions) */
423   off = (char*) key;
424   memcpy (off, &source_port, sizeof (uint16_t));
425   off += sizeof (uint16_t);
426   memcpy (off, &destination_port, sizeof (uint16_t));
427   off += sizeof (uint16_t);
428   switch (af)
429   {
430   case AF_INET:
431     memcpy (off, source_ip, sizeof (struct in_addr));
432     off += sizeof (struct in_addr);
433     memcpy (off, destination_ip, sizeof (struct in_addr));
434     off += sizeof (struct in_addr);
435     break;
436   case AF_INET6:
437     memcpy (off, source_ip, sizeof (struct in6_addr));
438     off += sizeof (struct in6_addr);
439     memcpy (off, destination_ip, sizeof (struct in6_addr));
440     off += sizeof (struct in6_addr);
441     break;
442   default:
443     GNUNET_assert (0);
444     break;
445   }
446   memcpy (off, &protocol, sizeof (uint8_t));
447   off += sizeof (uint8_t);  
448 }
449
450
451 /**
452  * Notify the client about the result of its request.
453  *
454  * @param client client to notify
455  * @param request_id original request ID to include in response
456  * @param result_af resulting address family
457  * @param addr resulting IP address
458  */
459 static void
460 send_client_reply (struct GNUNET_SERVER_Client *client,
461                    uint64_t request_id,
462                    int result_af,
463                    const void *addr)
464 {
465   char buf[sizeof (struct RedirectToIpResponseMessage) + sizeof (struct in6_addr)];
466   struct RedirectToIpResponseMessage *res;
467   size_t rlen;
468
469   switch (result_af)
470   {
471   case AF_INET:
472     rlen = sizeof (struct in_addr);    
473     break;
474   case AF_INET6:
475     rlen = sizeof (struct in6_addr);
476     break;
477   case AF_UNSPEC:
478     rlen = 0;
479     break;
480   default:
481     GNUNET_assert (0);
482     return;
483   }
484   res = (struct RedirectToIpResponseMessage *) buf;
485   res->header.size = htons (sizeof (struct RedirectToIpResponseMessage) + rlen);
486   res->header.type = htons (GNUNET_MESSAGE_TYPE_VPN_CLIENT_USE_IP);
487   res->result_af = htonl (result_af);
488   res->request_id = request_id;
489   memcpy (&res[1], addr, rlen);
490   GNUNET_SERVER_notification_context_add (nc, client);
491   GNUNET_SERVER_notification_context_unicast (nc,
492                                               client,
493                                               &res->header,
494                                               GNUNET_NO);
495 }
496
497
498 /**
499  * Free resources associated with a tunnel state.
500  *
501  * @param ts state to free
502  */
503 static void
504 free_tunnel_state (struct TunnelState *ts)
505 {
506   GNUNET_HashCode key;
507   struct TunnelMessageQueueEntry *tnq;
508   struct GNUNET_MESH_Tunnel *tunnel;
509
510   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
511               "Cleaning up tunnel state\n");
512   GNUNET_STATISTICS_update (stats,
513                             gettext_noop ("# Active tunnels"),
514                             -1, GNUNET_NO);
515   while (NULL != (tnq = ts->tmq_head))
516   {
517     GNUNET_CONTAINER_DLL_remove (ts->tmq_head,
518                                  ts->tmq_tail,
519                                  tnq);
520     ts->tmq_length--;
521     GNUNET_free (tnq);
522   }
523   GNUNET_assert (0 == ts->tmq_length);
524   if (NULL != ts->client)
525   {
526     GNUNET_SERVER_client_drop (ts->client);
527     ts->client = NULL;
528   }
529   if (NULL != ts->th)
530   {
531     GNUNET_MESH_notify_transmit_ready_cancel (ts->th);
532     ts->th = NULL;
533   }
534   GNUNET_assert (NULL == ts->destination.heap_node);
535   if (NULL != (tunnel = ts->tunnel))
536   {
537     ts->tunnel = NULL;
538     GNUNET_MESH_tunnel_destroy (tunnel);
539   }
540   if (GNUNET_SCHEDULER_NO_TASK != ts->destroy_task)
541   {
542     GNUNET_SCHEDULER_cancel (ts->destroy_task);
543     ts->destroy_task = GNUNET_SCHEDULER_NO_TASK;
544   }
545   if (NULL != ts->heap_node)
546   {
547     GNUNET_CONTAINER_heap_remove_node (ts->heap_node);
548     ts->heap_node = NULL;
549     get_tunnel_key_from_ips (ts->af,
550                              ts->protocol,
551                              &ts->source_ip,
552                              ts->source_port,
553                              &ts->destination_ip,
554                              ts->destination_port,
555                              &key);
556     GNUNET_assert (GNUNET_YES ==
557                    GNUNET_CONTAINER_multihashmap_remove (tunnel_map,
558                                                          &key,
559                                                          ts));
560   }
561   if (NULL != ts->destination_container)
562   {
563     GNUNET_assert (ts == ts->destination_container->ts);
564     ts->destination_container->ts = NULL;
565     ts->destination_container = NULL;
566   }
567   GNUNET_free (ts);
568 }
569
570
571 /**
572  * Destroy the mesh tunnel.
573  *
574  * @param cls the 'struct TunnelState' with the tunnel to destroy
575  * @param ts schedule context
576  */
577 static void
578 destroy_tunnel_task (void *cls,
579                      const struct GNUNET_SCHEDULER_TaskContext *tc)
580 {
581   struct TunnelState *ts = cls;
582   struct GNUNET_MESH_Tunnel *tunnel;
583
584   ts->destroy_task = GNUNET_SCHEDULER_NO_TASK;
585   GNUNET_assert (NULL != ts->tunnel);
586   tunnel = ts->tunnel;
587   ts->tunnel = NULL;
588   GNUNET_MESH_tunnel_destroy (tunnel);
589   free_tunnel_state (ts);
590 }
591
592
593 /**
594  * Method called whenever a peer has disconnected from the tunnel.
595  *
596  * @param cls closure
597  * @param peer peer identity the tunnel stopped working with
598  */
599 static void
600 tunnel_peer_disconnect_handler (void *cls,
601                                 const struct
602                                 GNUNET_PeerIdentity * peer)
603 {
604   struct TunnelState *ts = cls;
605
606   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
607               "Peer %s disconnected from tunnel.\n",
608               GNUNET_i2s (peer));
609   GNUNET_STATISTICS_update (stats,
610                             gettext_noop ("# Peers connected to mesh tunnels"),
611                             -1, GNUNET_NO);
612   if (NULL != ts->th)
613   {
614     GNUNET_MESH_notify_transmit_ready_cancel (ts->th);
615     ts->th = NULL;
616   }
617   if (ts->destination.is_service)
618     return; /* hope for reconnect eventually */
619   /* as we are most likely going to change the exit node now,
620      we should just destroy the tunnel entirely... */
621   if (GNUNET_SCHEDULER_NO_TASK == ts->destroy_task)
622     ts->destroy_task = GNUNET_SCHEDULER_add_now (&destroy_tunnel_task, ts);
623 }
624
625
626 /**
627  * Method called whenever a peer has connected to the tunnel.  Notifies
628  * the waiting client that the tunnel is now up.
629  *
630  * @param cls closure
631  * @param peer peer identity the tunnel was created to, NULL on timeout
632  * @param atsi performance data for the connection
633  */
634 static void
635 tunnel_peer_connect_handler (void *cls,
636                              const struct GNUNET_PeerIdentity
637                              * peer,
638                              const struct
639                              GNUNET_ATS_Information * atsi)
640 {
641   struct TunnelState *ts = cls;
642
643   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
644               "Peer %s connected to tunnel.\n",
645               GNUNET_i2s (peer));
646   GNUNET_STATISTICS_update (stats,
647                             gettext_noop ("# Peers connected to mesh tunnels"),
648                             1, GNUNET_NO);
649   if (NULL == ts->client)
650     return; /* nothing to do */
651   send_client_reply (ts->client,
652                      ts->request_id,
653                      ts->af,
654                      &ts->destination_ip);
655   GNUNET_SERVER_client_drop (ts->client);
656   ts->client = NULL;
657 }
658
659
660 /**
661  * Send a message from the message queue via mesh.
662  *
663  * @param cls the 'struct TunnelState' with the message queue
664  * @param size number of bytes available in buf
665  * @param buf where to copy the message
666  * @return number of bytes copied to buf
667  */
668 static size_t
669 send_to_peer_notify_callback (void *cls, size_t size, void *buf)
670 {
671   struct TunnelState *ts = cls;
672   struct TunnelMessageQueueEntry *tnq;
673   size_t ret;
674
675   ts->th = NULL;
676   if (NULL == buf)
677     return 0;
678   tnq = ts->tmq_head;
679   GNUNET_assert (NULL != tnq);
680   GNUNET_assert (size >= tnq->len);
681   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
682               "Sending %u bytes via mesh tunnel\n",
683               tnq->len);
684   GNUNET_CONTAINER_DLL_remove (ts->tmq_head,
685                                ts->tmq_tail,
686                                tnq);
687   ts->tmq_length--;
688   memcpy (buf, tnq->msg, tnq->len);
689   ret = tnq->len;
690   GNUNET_free (tnq);
691   if (NULL != (tnq = ts->tmq_head))
692     ts->th = GNUNET_MESH_notify_transmit_ready (ts->tunnel, 
693                                                 GNUNET_NO /* cork */, 
694                                                 42 /* priority */,
695                                                 GNUNET_TIME_UNIT_FOREVER_REL,
696                                                 NULL, 
697                                                 tnq->len,
698                                                 &send_to_peer_notify_callback,
699                                                 ts);
700   GNUNET_STATISTICS_update (stats,
701                             gettext_noop ("# Bytes given to mesh for transmission"),
702                             ret, GNUNET_NO);
703   return ret;
704 }
705
706
707 /**
708  * Add the given message to the given tunnel and trigger the
709  * transmission process.
710  *
711  * @param tnq message to queue
712  * @param ts tunnel to queue the message for
713  */
714 static void
715 send_to_tunnel (struct TunnelMessageQueueEntry *tnq,
716                 struct TunnelState *ts)
717 {
718   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
719               "Queueing %u bytes for transmission via mesh tunnel\n",
720               tnq->len);
721   GNUNET_assert (NULL != ts->tunnel);
722   GNUNET_CONTAINER_DLL_insert_tail (ts->tmq_head,
723                                     ts->tmq_tail,
724                                     tnq);
725   ts->tmq_length++;
726   if (ts->tmq_length > MAX_MESSAGE_QUEUE_SIZE)
727   {
728     struct TunnelMessageQueueEntry *dq;
729
730     dq = ts->tmq_head;
731     GNUNET_assert (dq != tnq);
732     GNUNET_CONTAINER_DLL_remove (ts->tmq_head,
733                                  ts->tmq_tail,
734                                  dq);
735     GNUNET_MESH_notify_transmit_ready_cancel (ts->th);
736     ts->th = NULL;
737     GNUNET_STATISTICS_update (stats,
738                               gettext_noop ("# Bytes dropped in mesh queue (overflow)"),
739                               dq->len, 
740                               GNUNET_NO);
741     GNUNET_free (dq);
742   }
743   if (NULL == ts->th)
744     ts->th = GNUNET_MESH_notify_transmit_ready (ts->tunnel, 
745                                                 GNUNET_NO /* cork */,
746                                                 42 /* priority */,
747                                                 GNUNET_TIME_UNIT_FOREVER_REL,
748                                                 NULL, 
749                                                 tnq->len,
750                                                 &send_to_peer_notify_callback,
751                                                 ts);
752 }
753
754
755 /**
756  * Initialize the given destination entry's mesh tunnel.
757  *
758  * @param de destination entry for which we need to setup a tunnel
759  * @param client client to notify on successful tunnel setup, or NULL for none
760  * @param request_id request ID to send in client notification (unused if client is NULL)
761  * @return tunnel state of the tunnel that was created
762  */
763 static struct TunnelState *
764 create_tunnel_to_destination (struct DestinationEntry *de,
765                               struct GNUNET_SERVER_Client *client,
766                               uint64_t request_id)
767 {
768   struct TunnelState *ts;
769
770   GNUNET_STATISTICS_update (stats,
771                             gettext_noop ("# Mesh tunnels created"),
772                             1, GNUNET_NO);
773   GNUNET_assert (NULL == de->ts);
774   ts = GNUNET_malloc (sizeof (struct TunnelState));
775   if (NULL != client)
776   {
777     ts->request_id = request_id;
778     ts->client = client;
779     GNUNET_SERVER_client_keep (client);
780   }
781   ts->destination = *de;
782   ts->destination.heap_node = NULL; /* copy is NOT in destination heap */
783   de->ts = ts;
784   ts->destination_container = de; /* we are referenced from de */
785   ts->af = AF_UNSPEC; /* so far, unknown */
786   ts->tunnel = GNUNET_MESH_tunnel_create (mesh_handle,
787                                           ts,
788                                           &tunnel_peer_connect_handler,
789                                           &tunnel_peer_disconnect_handler,
790                                           ts);
791   if (NULL == ts->tunnel)
792   {
793     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
794                 _("Failed to setup mesh tunnel!\n"));
795     if (NULL != client)
796       GNUNET_SERVER_client_drop (client);
797     GNUNET_free (ts);
798     return NULL;
799   }
800   if (de->is_service)
801   {
802     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
803                 "Creating tunnel to peer %s offering service %s\n",
804                 GNUNET_i2s (&de->details.service_destination.target),
805                 GNUNET_h2s (&de->details.service_destination.service_descriptor));
806     GNUNET_MESH_peer_request_connect_add (ts->tunnel,
807                                           &de->details.service_destination.target);  
808   }
809   else
810   {
811     switch (de->details.exit_destination.af)
812     {
813     case AF_INET:
814       GNUNET_MESH_peer_request_connect_by_type (ts->tunnel,
815                                                 GNUNET_APPLICATION_TYPE_IPV4_GATEWAY);
816       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
817                   "Creating tunnel to exit peer for %s\n",
818                   "IPv4");
819      break;
820     case AF_INET6:
821       GNUNET_MESH_peer_request_connect_by_type (ts->tunnel,
822                                                 GNUNET_APPLICATION_TYPE_IPV6_GATEWAY);
823       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
824                   "Creating tunnel to exit peer for %s\n",
825                   "IPv6");
826       break;
827     default:
828       GNUNET_assert (0);
829       break;
830     }
831   }  
832   return ts;
833 }
834
835
836 /**
837  * We have too many active tunnels.  Clean up the oldest tunnel.
838  *
839  * @param except tunnel that must NOT be cleaned up, even if it is the oldest
840  */
841 static void
842 expire_tunnel (struct TunnelState *except)
843 {
844   struct TunnelState *ts;
845
846   ts = GNUNET_CONTAINER_heap_peek (tunnel_heap);
847   if (except == ts)
848     return; /* can't do this */
849   free_tunnel_state (ts);
850 }
851
852
853 /**
854  * Route a packet via mesh to the given destination.  
855  *
856  * @param destination description of the destination
857  * @param af address family on this end (AF_INET or AF_INET6)
858  * @param protocol IPPROTO_TCP or IPPROTO_UDP
859  * @param source_ip source IP used by the sender (struct in_addr or struct in6_addr)
860  * @param destination_ip destination IP used by the sender (struct in_addr or struct in6_addr)
861  * @param payload payload of the packet after the IP header
862  * @param payload_length number of bytes in payload
863  */
864 static void
865 route_packet (struct DestinationEntry *destination,
866               int af,
867               uint8_t protocol,
868               const void *source_ip,
869               const void *destination_ip,
870               const void *payload,
871               size_t payload_length)
872 {
873   GNUNET_HashCode key;
874   struct TunnelState *ts;
875   struct TunnelMessageQueueEntry *tnq;
876   size_t alen;
877   size_t mlen;
878   int is_new;
879   const struct GNUNET_TUN_UdpHeader *udp;
880   const struct GNUNET_TUN_TcpHeader *tcp;
881   const struct GNUNET_TUN_IcmpHeader *icmp;
882   uint16_t spt;
883   uint16_t dpt;
884
885   switch (protocol)
886   {
887   case IPPROTO_UDP:
888     {
889       if (payload_length < sizeof (struct GNUNET_TUN_UdpHeader))
890       {
891         /* blame kernel? */
892         GNUNET_break (0);
893         return;
894       }
895       udp = payload;
896       spt = ntohs (udp->spt);
897       dpt = ntohs (udp->dpt);
898       get_tunnel_key_from_ips (af,
899                                IPPROTO_UDP,
900                                source_ip,
901                                spt,
902                                destination_ip,
903                                dpt,
904                                &key);
905     }
906     break;
907   case IPPROTO_TCP:
908     {
909       if (payload_length < sizeof (struct GNUNET_TUN_TcpHeader))
910       {
911         /* blame kernel? */
912         GNUNET_break (0);
913         return;
914       }
915       tcp = payload;
916       spt = ntohs (tcp->spt);
917       dpt = ntohs (tcp->dpt);
918       get_tunnel_key_from_ips (af,
919                                IPPROTO_TCP,
920                                source_ip,
921                                spt,
922                                destination_ip,
923                                dpt,
924                                &key);
925     }
926     break;
927   case IPPROTO_ICMP:
928     {
929       if (payload_length < sizeof (struct GNUNET_TUN_IcmpHeader))
930       {
931         /* blame kernel? */
932         GNUNET_break (0);
933         return;
934       }
935       icmp = payload;
936       spt = 0;
937       dpt = 0;
938       get_tunnel_key_from_ips (af,
939                                IPPROTO_ICMP,
940                                source_ip,
941                                0,
942                                destination_ip,
943                                0,
944                                &key);
945     }
946     break;
947   default:
948     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
949                 _("Protocol %u not supported, dropping\n"),
950                 (unsigned int) protocol);
951     return;
952   }
953   if (! destination->is_service)
954   {  
955     switch (destination->details.exit_destination.af)
956     {
957     case AF_INET:
958       alen = sizeof (struct in_addr);
959      break;
960     case AF_INET6:
961       alen = sizeof (struct in6_addr);
962       break;
963     default:
964       alen = 0;
965       GNUNET_assert (0);
966     }
967
968     {
969       char sbuf[INET6_ADDRSTRLEN];
970       char dbuf[INET6_ADDRSTRLEN];
971       char xbuf[INET6_ADDRSTRLEN];
972       
973       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
974                   "Routing %s packet from %s:%u -> %s:%u to destination %s:%u\n",
975                   (protocol == IPPROTO_TCP) ? "TCP" : "UDP",
976                   inet_ntop (af, source_ip, sbuf, sizeof (sbuf)),
977                   spt,
978                   inet_ntop (af, destination_ip, dbuf, sizeof (dbuf)),
979                   dpt,
980                   inet_ntop (destination->details.exit_destination.af,
981                              &destination->details.exit_destination.ip,
982                              xbuf, sizeof (xbuf)),
983                   dpt);
984     }
985   }
986   else
987   {
988     /* make compiler happy */
989     alen = 0;
990     {
991       char sbuf[INET6_ADDRSTRLEN];
992       char dbuf[INET6_ADDRSTRLEN];
993       
994       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
995                   "Routing %s packet from %s:%u -> %s:%u to service %s at peer %s\n",
996                   (protocol == IPPROTO_TCP) ? "TCP" : "UDP",
997                   inet_ntop (af, source_ip, sbuf, sizeof (sbuf)),
998                   spt,
999                   inet_ntop (af, destination_ip, dbuf, sizeof (dbuf)),
1000                   dpt,
1001                   GNUNET_h2s (&destination->details.service_destination.service_descriptor),
1002                   GNUNET_i2s (&destination->details.service_destination.target));
1003     }
1004
1005   }
1006
1007   /* see if we have an existing tunnel for this destination */
1008   ts = GNUNET_CONTAINER_multihashmap_get (tunnel_map,
1009                                           &key);
1010   if (NULL == ts)
1011   {
1012     /* need to either use the existing tunnel from the destination (if still
1013        available) or create a fresh one */
1014     is_new = GNUNET_YES;
1015     if (NULL == destination->ts)
1016       ts = create_tunnel_to_destination (destination, NULL, 0);
1017     else
1018       ts = destination->ts;
1019     if (NULL == ts)
1020       return;
1021     destination->ts = NULL;
1022     ts->destination_container = NULL; /* no longer 'contained' */
1023     /* now bind existing "unbound" tunnel to our IP/port tuple */
1024     ts->protocol = protocol;
1025     ts->af = af; 
1026     if (af == AF_INET)
1027     {
1028       ts->source_ip.v4 = * (const struct in_addr *) source_ip;
1029       ts->destination_ip.v4 = * (const struct in_addr *) destination_ip;
1030     }
1031     else
1032     {
1033       ts->source_ip.v6 = * (const struct in6_addr *) source_ip;
1034       ts->destination_ip.v6 = * (const struct in6_addr *) destination_ip;
1035     }
1036     ts->source_port = spt;
1037     ts->destination_port = dpt;
1038     ts->heap_node = GNUNET_CONTAINER_heap_insert (tunnel_heap,
1039                                                   ts,
1040                                                   GNUNET_TIME_absolute_get ().abs_value);
1041     GNUNET_assert (GNUNET_YES ==
1042                    GNUNET_CONTAINER_multihashmap_put (tunnel_map,
1043                                                       &key,
1044                                                       ts,
1045                                                       GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); 
1046     GNUNET_STATISTICS_update (stats,
1047                               gettext_noop ("# Active tunnels"),
1048                               1, GNUNET_NO);
1049     while (GNUNET_CONTAINER_multihashmap_size (tunnel_map) > max_tunnel_mappings)
1050       expire_tunnel (ts);
1051   }
1052   else
1053   {
1054     is_new = GNUNET_NO;
1055     GNUNET_CONTAINER_heap_update_cost (tunnel_heap, 
1056                                        ts->heap_node,
1057                                        GNUNET_TIME_absolute_get ().abs_value);
1058   }
1059   GNUNET_assert (NULL != ts->tunnel);
1060   
1061   /* send via tunnel */
1062   switch (protocol)
1063   {
1064   case IPPROTO_UDP:
1065     if (destination->is_service)
1066     {
1067       struct GNUNET_EXIT_UdpServiceMessage *usm;
1068
1069       mlen = sizeof (struct GNUNET_EXIT_UdpServiceMessage) + 
1070         payload_length - sizeof (struct GNUNET_TUN_UdpHeader);
1071       if (mlen >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1072       {
1073         GNUNET_break (0);
1074         return;
1075       }
1076       tnq = GNUNET_malloc (sizeof (struct TunnelMessageQueueEntry) + mlen);
1077       tnq->len = mlen;
1078       tnq->msg = &tnq[1];
1079       usm = (struct GNUNET_EXIT_UdpServiceMessage *) &tnq[1];
1080       usm->header.size = htons ((uint16_t) mlen);
1081       usm->header.type = htons (GNUNET_MESSAGE_TYPE_VPN_UDP_TO_SERVICE);
1082       /* if the source port is below 32000, we assume it has a special
1083          meaning; if not, we pick a random port (this is a heuristic) */
1084       usm->source_port = (ntohs (udp->spt) < 32000) ? udp->spt : 0;
1085       usm->destination_port = udp->dpt;
1086       usm->service_descriptor = destination->details.service_destination.service_descriptor;
1087       memcpy (&usm[1],
1088               &udp[1],
1089               payload_length - sizeof (struct GNUNET_TUN_UdpHeader));
1090     }
1091     else
1092     {
1093       struct GNUNET_EXIT_UdpInternetMessage *uim;
1094       struct in_addr *ip4dst;
1095       struct in6_addr *ip6dst;
1096       void *payload;
1097
1098       mlen = sizeof (struct GNUNET_EXIT_UdpInternetMessage) + 
1099         alen + payload_length - sizeof (struct GNUNET_TUN_UdpHeader);
1100       if (mlen >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1101       {
1102         GNUNET_break (0);
1103         return;
1104       }
1105       tnq = GNUNET_malloc (sizeof (struct TunnelMessageQueueEntry) + 
1106                            mlen);
1107       tnq->len = mlen;
1108       tnq->msg = &tnq[1];
1109       uim = (struct GNUNET_EXIT_UdpInternetMessage *) &tnq[1];
1110       uim->header.size = htons ((uint16_t) mlen);
1111       uim->header.type = htons (GNUNET_MESSAGE_TYPE_VPN_UDP_TO_INTERNET); 
1112       uim->af = htonl (destination->details.exit_destination.af);
1113       uim->source_port = (ntohs (udp->spt) < 32000) ? udp->spt : 0;
1114       uim->destination_port = udp->dpt;
1115       switch (destination->details.exit_destination.af)
1116       {
1117       case AF_INET:
1118         ip4dst = (struct in_addr *) &uim[1];
1119         *ip4dst = destination->details.exit_destination.ip.v4;
1120         payload = &ip4dst[1];
1121         break;
1122       case AF_INET6:
1123         ip6dst = (struct in6_addr *) &uim[1];
1124         *ip6dst = destination->details.exit_destination.ip.v6;
1125         payload = &ip6dst[1];
1126         break;
1127       default:
1128         GNUNET_assert (0);
1129       }
1130       memcpy (payload,
1131               &udp[1],
1132               payload_length - sizeof (struct GNUNET_TUN_UdpHeader));
1133     }
1134     break;
1135   case IPPROTO_TCP:
1136     if (is_new)
1137     {
1138       if (destination->is_service)
1139       {
1140         struct GNUNET_EXIT_TcpServiceStartMessage *tsm;
1141
1142         mlen = sizeof (struct GNUNET_EXIT_TcpServiceStartMessage) + 
1143           payload_length - sizeof (struct GNUNET_TUN_TcpHeader);
1144         if (mlen >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1145         {
1146           GNUNET_break (0);
1147           return;
1148         }
1149         tnq = GNUNET_malloc (sizeof (struct TunnelMessageQueueEntry) + mlen);
1150         tnq->len = mlen;
1151         tnq->msg = &tnq[1];
1152         tsm = (struct  GNUNET_EXIT_TcpServiceStartMessage *) &tnq[1];
1153         tsm->header.size = htons ((uint16_t) mlen);
1154         tsm->header.type = htons (GNUNET_MESSAGE_TYPE_VPN_TCP_TO_SERVICE_START);
1155         tsm->reserved = htonl (0);
1156         tsm->service_descriptor = destination->details.service_destination.service_descriptor;
1157         tsm->tcp_header = *tcp;
1158         memcpy (&tsm[1],
1159                 &tcp[1],
1160                 payload_length - sizeof (struct GNUNET_TUN_TcpHeader));
1161       }
1162       else
1163       {
1164         struct GNUNET_EXIT_TcpInternetStartMessage *tim;
1165         struct in_addr *ip4dst;
1166         struct in6_addr *ip6dst;
1167         void *payload;
1168
1169         mlen = sizeof (struct GNUNET_EXIT_TcpInternetStartMessage) + 
1170           alen + payload_length - sizeof (struct GNUNET_TUN_TcpHeader);
1171         if (mlen >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1172         {
1173           GNUNET_break (0);
1174           return;
1175         }
1176         tnq = GNUNET_malloc (sizeof (struct TunnelMessageQueueEntry) + mlen);
1177         tnq->len = mlen;
1178         tnq->msg = &tnq[1];
1179         tim = (struct  GNUNET_EXIT_TcpInternetStartMessage *) &tnq[1];
1180         tim->header.size = htons ((uint16_t) mlen);
1181         tim->header.type = htons (GNUNET_MESSAGE_TYPE_VPN_TCP_TO_INTERNET_START);
1182         tim->af = htonl (destination->details.exit_destination.af);     
1183         tim->tcp_header = *tcp;
1184         switch (destination->details.exit_destination.af)
1185         {
1186         case AF_INET:
1187           ip4dst = (struct in_addr *) &tim[1];
1188           *ip4dst = destination->details.exit_destination.ip.v4;
1189           payload = &ip4dst[1];
1190           break;
1191         case AF_INET6:
1192           ip6dst = (struct in6_addr *) &tim[1];
1193           *ip6dst = destination->details.exit_destination.ip.v6;
1194           payload = &ip6dst[1];
1195           break;
1196         default:
1197           GNUNET_assert (0);
1198         }
1199         memcpy (payload,
1200                 &tcp[1],
1201                 payload_length - sizeof (struct GNUNET_TUN_TcpHeader));
1202       }
1203     }
1204     else
1205     {
1206       struct GNUNET_EXIT_TcpDataMessage *tdm;
1207
1208       mlen = sizeof (struct GNUNET_EXIT_TcpDataMessage) + 
1209         payload_length - sizeof (struct GNUNET_TUN_TcpHeader);
1210       if (mlen >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1211       {
1212         GNUNET_break (0);
1213         return;
1214       }
1215       tnq = GNUNET_malloc (sizeof (struct TunnelMessageQueueEntry) + mlen);
1216       tnq->len = mlen;
1217       tnq->msg = &tnq[1];
1218       tdm = (struct  GNUNET_EXIT_TcpDataMessage *) &tnq[1];
1219       tdm->header.size = htons ((uint16_t) mlen);
1220       tdm->header.type = htons (GNUNET_MESSAGE_TYPE_VPN_TCP_DATA_TO_EXIT);
1221       tdm->reserved = htonl (0);
1222       tdm->tcp_header = *tcp;
1223       memcpy (&tdm[1],
1224               &tcp[1],
1225               payload_length - sizeof (struct GNUNET_TUN_TcpHeader));
1226      }
1227     break;
1228   case IPPROTO_ICMP:
1229     if (destination->is_service)
1230     {
1231       struct GNUNET_EXIT_IcmpServiceMessage *ism;
1232
1233       mlen = sizeof (struct GNUNET_EXIT_IcmpServiceMessage) + 
1234         payload_length - sizeof (struct GNUNET_TUN_IcmpHeader);
1235       if (mlen >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1236       {
1237         GNUNET_break (0);
1238         return;
1239       }
1240       tnq = GNUNET_malloc (sizeof (struct TunnelMessageQueueEntry) + mlen);
1241       tnq->len = mlen;
1242       tnq->msg = &tnq[1];
1243       ism = (struct GNUNET_EXIT_IcmpServiceMessage *) &tnq[1];
1244       ism->header.size = htons ((uint16_t) mlen);
1245       ism->header.type = htons (GNUNET_MESSAGE_TYPE_VPN_ICMP_TO_SERVICE);
1246       ism->af = htonl (af); /* need to tell destination ICMP protocol family! */
1247       ism->service_descriptor = destination->details.service_destination.service_descriptor;
1248       ism->icmp_header = *icmp;
1249       memcpy (&ism[1],
1250               &icmp[1],
1251               payload_length - sizeof (struct GNUNET_TUN_IcmpHeader));
1252     }
1253     else
1254     {
1255       struct GNUNET_EXIT_IcmpInternetMessage *iim;
1256       struct in_addr *ip4dst;
1257       struct in6_addr *ip6dst;
1258       void *payload;
1259
1260       mlen = sizeof (struct GNUNET_EXIT_IcmpInternetMessage) + 
1261         alen + payload_length - sizeof (struct GNUNET_TUN_IcmpHeader);
1262       if (mlen >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1263       {
1264         GNUNET_break (0);
1265         return;
1266       }
1267       tnq = GNUNET_malloc (sizeof (struct TunnelMessageQueueEntry) + 
1268                            mlen);
1269       tnq->len = mlen;
1270       tnq->msg = &tnq[1];
1271       iim = (struct GNUNET_EXIT_IcmpInternetMessage *) &tnq[1];
1272       iim->header.size = htons ((uint16_t) mlen);
1273       iim->header.type = htons (GNUNET_MESSAGE_TYPE_VPN_ICMP_TO_INTERNET); 
1274       iim->af = htonl (af); /* need to tell destination ICMP protocol family! */
1275       iim->icmp_header = *icmp;
1276       if (af != destination->details.exit_destination.af)
1277       {
1278         GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1279                     _("AF-translation for ICMP not implemented\n"));
1280         return;
1281       }
1282       switch (destination->details.exit_destination.af)
1283       {
1284       case AF_INET:
1285         ip4dst = (struct in_addr *) &iim[1];
1286         *ip4dst = destination->details.exit_destination.ip.v4;
1287         payload = &ip4dst[1];
1288         break;
1289       case AF_INET6:
1290         ip6dst = (struct in6_addr *) &iim[1];
1291         *ip6dst = destination->details.exit_destination.ip.v6;
1292         payload = &ip6dst[1];
1293         break;
1294       default:
1295         GNUNET_assert (0);
1296       }
1297       memcpy (payload,
1298               &icmp[1],
1299               payload_length - sizeof (struct GNUNET_TUN_IcmpHeader));
1300     }
1301     break;
1302   default:
1303     /* not supported above, how can we get here !? */
1304     GNUNET_assert (0);
1305     break;
1306   }
1307   send_to_tunnel (tnq, ts);
1308 }
1309
1310
1311 /**
1312  * Receive packets from the helper-process (someone send to the local
1313  * virtual tunnel interface).  Find the destination mapping, and if it
1314  * exists, identify the correct MESH tunnel (or possibly create it)
1315  * and forward the packet.
1316  *
1317  * @param cls closure, NULL
1318  * @param client NULL
1319  * @param message message we got from the client (VPN tunnel interface)
1320  */
1321 static void
1322 message_token (void *cls GNUNET_UNUSED, void *client GNUNET_UNUSED,
1323                const struct GNUNET_MessageHeader *message)
1324 {
1325   const struct GNUNET_TUN_Layer2PacketHeader *tun;
1326   size_t mlen;
1327   GNUNET_HashCode key;
1328   struct DestinationEntry *de;
1329
1330   GNUNET_STATISTICS_update (stats,
1331                             gettext_noop ("# Packets received from TUN interface"),
1332                             1, GNUNET_NO);
1333   mlen = ntohs (message->size);
1334   if ( (ntohs (message->type) != GNUNET_MESSAGE_TYPE_VPN_HELPER) ||
1335        (mlen < sizeof (struct GNUNET_MessageHeader) + sizeof (struct GNUNET_TUN_Layer2PacketHeader)) )
1336   {
1337     GNUNET_break (0);
1338     return;
1339   }
1340   tun = (const struct GNUNET_TUN_Layer2PacketHeader *) &message[1];
1341   mlen -= (sizeof (struct GNUNET_MessageHeader) + sizeof (struct GNUNET_TUN_Layer2PacketHeader));
1342   switch (ntohs (tun->proto))
1343   {
1344   case ETH_P_IPV6:
1345     {
1346       const struct GNUNET_TUN_IPv6Header *pkt6;
1347       
1348       if (mlen < sizeof (struct GNUNET_TUN_IPv6Header))
1349       {
1350         /* blame kernel */
1351         GNUNET_break (0);
1352         return;
1353       }
1354       pkt6 = (const struct GNUNET_TUN_IPv6Header *) &tun[1];
1355       get_destination_key_from_ip (AF_INET6,
1356                                    &pkt6->destination_address,
1357                                    &key);
1358       de = GNUNET_CONTAINER_multihashmap_get (destination_map, &key);
1359       /* FIXME: do we need to guard against hash collision? 
1360          (if so, we need to also store the local destination IP in the
1361          destination entry and then compare here; however, the risk
1362          of collision seems minimal AND the impact is unlikely to be
1363          super-problematic as well... */
1364       if (NULL == de)
1365       {
1366         char buf[INET6_ADDRSTRLEN];
1367         
1368         GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1369                     _("Packet received for unmapped destination `%s' (dropping it)\n"),
1370                     inet_ntop (AF_INET6,
1371                                &pkt6->destination_address,
1372                                buf,
1373                                sizeof (buf)));
1374         return;
1375       }
1376       route_packet (de,
1377                     AF_INET6,
1378                     pkt6->next_header,
1379                     &pkt6->source_address,                  
1380                     &pkt6->destination_address,             
1381                     &pkt6[1],
1382                     mlen - sizeof (struct GNUNET_TUN_IPv6Header));
1383     }
1384     break;
1385   case ETH_P_IPV4:
1386     {
1387       struct GNUNET_TUN_IPv4Header *pkt4;
1388
1389       if (mlen < sizeof (struct GNUNET_TUN_IPv4Header))
1390       {
1391         /* blame kernel */
1392         GNUNET_break (0);
1393         return;
1394       }
1395       pkt4 = (struct GNUNET_TUN_IPv4Header *) &tun[1];
1396       get_destination_key_from_ip (AF_INET,
1397                                    &pkt4->destination_address,
1398                                    &key);
1399       de = GNUNET_CONTAINER_multihashmap_get (destination_map, &key);
1400       /* FIXME: do we need to guard against hash collision? 
1401          (if so, we need to also store the local destination IP in the
1402          destination entry and then compare here; however, the risk
1403          of collision seems minimal AND the impact is unlikely to be
1404          super-problematic as well... */
1405       if (NULL == de)
1406       {
1407         char buf[INET_ADDRSTRLEN];
1408         
1409         GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1410                     _("Packet received for unmapped destination `%s' (dropping it)\n"),
1411                     inet_ntop (AF_INET,
1412                                &pkt4->destination_address,
1413                                buf,
1414                                sizeof (buf)));
1415         return;
1416       }
1417       if (pkt4->header_length * 4 != sizeof (struct GNUNET_TUN_IPv4Header))
1418       {
1419         GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1420                     _("Received IPv4 packet with options (dropping it)\n"));                
1421         return;
1422       }
1423       route_packet (de,
1424                     AF_INET,
1425                     pkt4->protocol,
1426                     &pkt4->source_address,                  
1427                     &pkt4->destination_address,             
1428                     &pkt4[1],
1429                     mlen - sizeof (struct GNUNET_TUN_IPv4Header));
1430     }
1431     break;
1432   default:
1433     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1434                 _("Received packet of unknown protocol %d from TUN (dropping it)\n"),
1435                 (unsigned int) ntohs (tun->proto));
1436     break;
1437   }
1438 }
1439
1440
1441 /**
1442  * We got an ICMP packet back from the MESH tunnel.  Pass it on to the
1443  * local virtual interface via the helper.
1444  *
1445  * @param cls closure, NULL
1446  * @param tunnel connection to the other end
1447  * @param tunnel_ctx pointer to our 'struct TunnelState *'
1448  * @param sender who sent the message
1449  * @param message the actual message
1450  * @param atsi performance data for the connection
1451  * @return GNUNET_OK to keep the connection open,
1452  *         GNUNET_SYSERR to close it (signal serious error)
1453  */ 
1454 static int
1455 receive_icmp_back (void *cls GNUNET_UNUSED, struct GNUNET_MESH_Tunnel *tunnel,
1456                    void **tunnel_ctx, const struct GNUNET_PeerIdentity *sender,
1457                    const struct GNUNET_MessageHeader *message,
1458                    const struct GNUNET_ATS_Information *atsi GNUNET_UNUSED)
1459 {
1460   struct TunnelState *ts = *tunnel_ctx;
1461   const struct GNUNET_EXIT_IcmpToVPNMessage *i2v;
1462   size_t mlen;
1463
1464   GNUNET_STATISTICS_update (stats,
1465                             gettext_noop ("# ICMP packets received from mesh"),
1466                             1, GNUNET_NO);
1467   mlen = ntohs (message->size);
1468   if (mlen < sizeof (struct GNUNET_EXIT_IcmpToVPNMessage))
1469   {
1470     GNUNET_break_op (0);
1471     return GNUNET_SYSERR;
1472   }
1473   if (NULL == ts->heap_node)
1474   {
1475     GNUNET_break_op (0);
1476     return GNUNET_SYSERR;
1477   }
1478   if (AF_UNSPEC == ts->af)
1479   {
1480     GNUNET_break_op (0);
1481     return GNUNET_SYSERR;
1482   }
1483   i2v = (const struct GNUNET_EXIT_IcmpToVPNMessage *) message;
1484   mlen -= sizeof (struct GNUNET_EXIT_IcmpToVPNMessage);
1485   {
1486     char sbuf[INET6_ADDRSTRLEN];
1487     char dbuf[INET6_ADDRSTRLEN];
1488     
1489     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1490                 "Received ICMP packet from mesh, sending %u bytes from %s -> %s via TUN\n",
1491                 (unsigned int) mlen,
1492                 inet_ntop (ts->af, &ts->destination_ip, sbuf, sizeof (sbuf)),
1493                 inet_ntop (ts->af, &ts->source_ip, dbuf, sizeof (dbuf)));
1494   }
1495   switch (ts->af)
1496   {
1497   case AF_INET:
1498     {
1499       size_t size = sizeof (struct GNUNET_TUN_IPv4Header) 
1500         + sizeof (struct GNUNET_TUN_IcmpHeader) 
1501         + sizeof (struct GNUNET_MessageHeader) +
1502         sizeof (struct GNUNET_TUN_Layer2PacketHeader) +
1503         mlen;
1504       {
1505         char buf[size];
1506         struct GNUNET_MessageHeader *msg = (struct GNUNET_MessageHeader *) buf;
1507         struct GNUNET_TUN_Layer2PacketHeader *tun = (struct GNUNET_TUN_Layer2PacketHeader*) &msg[1];
1508         struct GNUNET_TUN_IPv4Header *ipv4 = (struct GNUNET_TUN_IPv4Header *) &tun[1];
1509         struct GNUNET_TUN_IcmpHeader *icmp = (struct GNUNET_TUN_IcmpHeader *) &ipv4[1];
1510         msg->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
1511         msg->size = htons (size);
1512         tun->flags = htons (0);
1513         tun->proto = htons (ETH_P_IPV4);
1514         GNUNET_TUN_initialize_ipv4_header (ipv4,
1515                                            IPPROTO_ICMP,
1516                                            sizeof (struct GNUNET_TUN_IcmpHeader) + mlen,
1517                                            &ts->destination_ip.v4,
1518                                            &ts->source_ip.v4);
1519         *icmp = i2v->icmp_header;
1520         memcpy (&icmp[1],
1521                 &i2v[1],
1522                 mlen);
1523         /* FIXME: for some ICMP types, we need to adjust the payload here... */
1524         GNUNET_TUN_calculate_icmp_checksum (icmp,
1525                                             &i2v[1],
1526                                             mlen);
1527         (void) GNUNET_HELPER_send (helper_handle,
1528                                    msg,
1529                                    GNUNET_YES,
1530                                    NULL, NULL);
1531       }
1532     }
1533     break;
1534   case AF_INET6:
1535     {
1536       size_t size = sizeof (struct GNUNET_TUN_IPv6Header) 
1537         + sizeof (struct GNUNET_TUN_IcmpHeader) 
1538         + sizeof (struct GNUNET_MessageHeader) +
1539         sizeof (struct GNUNET_TUN_Layer2PacketHeader) +
1540         mlen;
1541       {
1542         char buf[size];
1543         struct GNUNET_MessageHeader *msg = (struct GNUNET_MessageHeader *) buf;
1544         struct GNUNET_TUN_Layer2PacketHeader *tun = (struct GNUNET_TUN_Layer2PacketHeader*) &msg[1];
1545         struct GNUNET_TUN_IPv6Header *ipv6 = (struct GNUNET_TUN_IPv6Header *) &tun[1];
1546         struct GNUNET_TUN_IcmpHeader *icmp = (struct GNUNET_TUN_IcmpHeader *) &ipv6[1];
1547         msg->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
1548         msg->size = htons (size);
1549         tun->flags = htons (0);
1550         tun->proto = htons (ETH_P_IPV6);
1551         GNUNET_TUN_initialize_ipv6_header (ipv6,
1552                                            IPPROTO_ICMP,
1553                                            sizeof (struct GNUNET_TUN_IcmpHeader) + mlen,
1554                                            &ts->destination_ip.v6,
1555                                            &ts->source_ip.v6);
1556         *icmp = i2v->icmp_header;
1557         memcpy (&icmp[1],
1558                 &i2v[1],
1559                 mlen);
1560         /* FIXME: for some ICMP types, we need to adjust the payload here... */
1561         GNUNET_TUN_calculate_icmp_checksum (icmp,
1562                                             &i2v[1], mlen);
1563         (void) GNUNET_HELPER_send (helper_handle,
1564                                    msg,
1565                                    GNUNET_YES,
1566                                    NULL, NULL);
1567       }
1568     }
1569     break;
1570   default:
1571     GNUNET_assert (0);
1572   }
1573   GNUNET_CONTAINER_heap_update_cost (tunnel_heap, 
1574                                      ts->heap_node,
1575                                      GNUNET_TIME_absolute_get ().abs_value);
1576   return GNUNET_OK;
1577 }
1578
1579
1580 /**
1581  * We got a UDP packet back from the MESH tunnel.  Pass it on to the
1582  * local virtual interface via the helper.
1583  *
1584  * @param cls closure, NULL
1585  * @param tunnel connection to the other end
1586  * @param tunnel_ctx pointer to our 'struct TunnelState *'
1587  * @param sender who sent the message
1588  * @param message the actual message
1589  * @param atsi performance data for the connection
1590  * @return GNUNET_OK to keep the connection open,
1591  *         GNUNET_SYSERR to close it (signal serious error)
1592  */ 
1593 static int
1594 receive_udp_back (void *cls GNUNET_UNUSED, struct GNUNET_MESH_Tunnel *tunnel,
1595                   void **tunnel_ctx, const struct GNUNET_PeerIdentity *sender,
1596                   const struct GNUNET_MessageHeader *message,
1597                   const struct GNUNET_ATS_Information *atsi GNUNET_UNUSED)
1598 {
1599   struct TunnelState *ts = *tunnel_ctx;
1600   const struct GNUNET_EXIT_UdpReplyMessage *reply;
1601   size_t mlen;
1602
1603   GNUNET_STATISTICS_update (stats,
1604                             gettext_noop ("# UDP packets received from mesh"),
1605                             1, GNUNET_NO);
1606   mlen = ntohs (message->size);
1607   if (mlen < sizeof (struct GNUNET_EXIT_UdpReplyMessage))
1608   {
1609     GNUNET_break_op (0);
1610     return GNUNET_SYSERR;
1611   }
1612   if (NULL == ts->heap_node)
1613   {
1614     GNUNET_break_op (0);
1615     return GNUNET_SYSERR;
1616   }
1617   if (AF_UNSPEC == ts->af)
1618   {
1619     GNUNET_break_op (0);
1620     return GNUNET_SYSERR;
1621   }
1622   reply = (const struct GNUNET_EXIT_UdpReplyMessage *) message;
1623   mlen -= sizeof (struct GNUNET_EXIT_UdpReplyMessage);
1624   {
1625     char sbuf[INET6_ADDRSTRLEN];
1626     char dbuf[INET6_ADDRSTRLEN];
1627     
1628     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1629                 "Received UDP reply from mesh, sending %u bytes from %s:%u -> %s:%u via TUN\n",
1630                 (unsigned int) mlen,
1631                 inet_ntop (ts->af, &ts->destination_ip, sbuf, sizeof (sbuf)),
1632                 ts->destination_port,
1633                 inet_ntop (ts->af, &ts->source_ip, dbuf, sizeof (dbuf)),
1634                 ts->source_port);
1635   }
1636   switch (ts->af)
1637   {
1638   case AF_INET:
1639     {
1640       size_t size = sizeof (struct GNUNET_TUN_IPv4Header) 
1641         + sizeof (struct GNUNET_TUN_UdpHeader) 
1642         + sizeof (struct GNUNET_MessageHeader) +
1643         sizeof (struct GNUNET_TUN_Layer2PacketHeader) +
1644         mlen;
1645       {
1646         char buf[size];
1647         struct GNUNET_MessageHeader *msg = (struct GNUNET_MessageHeader *) buf;
1648         struct GNUNET_TUN_Layer2PacketHeader *tun = (struct GNUNET_TUN_Layer2PacketHeader*) &msg[1];
1649         struct GNUNET_TUN_IPv4Header *ipv4 = (struct GNUNET_TUN_IPv4Header *) &tun[1];
1650         struct GNUNET_TUN_UdpHeader *udp = (struct GNUNET_TUN_UdpHeader *) &ipv4[1];
1651         msg->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
1652         msg->size = htons (size);
1653         tun->flags = htons (0);
1654         tun->proto = htons (ETH_P_IPV4);
1655         GNUNET_TUN_initialize_ipv4_header (ipv4,
1656                                            IPPROTO_UDP,
1657                                            sizeof (struct GNUNET_TUN_UdpHeader) + mlen,
1658                                            &ts->destination_ip.v4,
1659                                            &ts->source_ip.v4);
1660         if (0 == ntohs (reply->source_port))
1661           udp->spt = htons (ts->destination_port);
1662         else
1663           udp->spt = reply->source_port;
1664         if (0 == ntohs (reply->destination_port))
1665           udp->dpt = htons (ts->source_port);
1666         else
1667           udp->dpt = reply->destination_port;
1668         udp->len = htons (mlen + sizeof (struct GNUNET_TUN_UdpHeader));
1669         GNUNET_TUN_calculate_udp4_checksum (ipv4,
1670                                             udp,
1671                                             &reply[1],
1672                                             mlen);
1673         memcpy (&udp[1],
1674                 &reply[1],
1675                 mlen);
1676         (void) GNUNET_HELPER_send (helper_handle,
1677                                    msg,
1678                                    GNUNET_YES,
1679                                    NULL, NULL);
1680       }
1681     }
1682     break;
1683   case AF_INET6:
1684     {
1685       size_t size = sizeof (struct GNUNET_TUN_IPv6Header) 
1686         + sizeof (struct GNUNET_TUN_UdpHeader) 
1687         + sizeof (struct GNUNET_MessageHeader) +
1688         sizeof (struct GNUNET_TUN_Layer2PacketHeader) +
1689         mlen;
1690       {
1691         char buf[size];
1692         struct GNUNET_MessageHeader *msg = (struct GNUNET_MessageHeader *) buf;
1693         struct GNUNET_TUN_Layer2PacketHeader *tun = (struct GNUNET_TUN_Layer2PacketHeader*) &msg[1];
1694         struct GNUNET_TUN_IPv6Header *ipv6 = (struct GNUNET_TUN_IPv6Header *) &tun[1];
1695         struct GNUNET_TUN_UdpHeader *udp = (struct GNUNET_TUN_UdpHeader *) &ipv6[1];
1696         msg->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
1697         msg->size = htons (size);
1698         tun->flags = htons (0);
1699         tun->proto = htons (ETH_P_IPV6);
1700         GNUNET_TUN_initialize_ipv6_header (ipv6,
1701                                            IPPROTO_UDP,
1702                                            sizeof (struct GNUNET_TUN_UdpHeader) + mlen,
1703                                            &ts->destination_ip.v6,
1704                                            &ts->source_ip.v6);
1705         if (0 == ntohs (reply->source_port))
1706           udp->spt = htons (ts->destination_port);
1707         else
1708           udp->spt = reply->source_port;
1709         if (0 == ntohs (reply->destination_port))
1710           udp->dpt = htons (ts->source_port);
1711         else
1712           udp->dpt = reply->destination_port;
1713         udp->len = htons (mlen + sizeof (struct GNUNET_TUN_UdpHeader));
1714         GNUNET_TUN_calculate_udp6_checksum (ipv6,
1715                                             udp,
1716                                             &reply[1], mlen);
1717         memcpy (&udp[1],
1718                 &reply[1],
1719                 mlen);
1720         (void) GNUNET_HELPER_send (helper_handle,
1721                                    msg,
1722                                    GNUNET_YES,
1723                                    NULL, NULL);
1724       }
1725     }
1726     break;
1727   default:
1728     GNUNET_assert (0);
1729   }
1730   GNUNET_CONTAINER_heap_update_cost (tunnel_heap, 
1731                                      ts->heap_node,
1732                                      GNUNET_TIME_absolute_get ().abs_value);
1733   return GNUNET_OK;
1734 }
1735
1736
1737 /**
1738  * We got a TCP packet back from the MESH tunnel.  Pass it on to the
1739  * local virtual interface via the helper.
1740  *
1741  * @param cls closure, NULL
1742  * @param tunnel connection to the other end
1743  * @param tunnel_ctx pointer to our 'struct TunnelState *'
1744  * @param sender who sent the message
1745  * @param message the actual message
1746  * @param atsi performance data for the connection
1747  * @return GNUNET_OK to keep the connection open,
1748  *         GNUNET_SYSERR to close it (signal serious error)
1749  */ 
1750 static int
1751 receive_tcp_back (void *cls GNUNET_UNUSED, struct GNUNET_MESH_Tunnel *tunnel,
1752                   void **tunnel_ctx,
1753                   const struct GNUNET_PeerIdentity *sender GNUNET_UNUSED,
1754                   const struct GNUNET_MessageHeader *message,
1755                   const struct GNUNET_ATS_Information *atsi GNUNET_UNUSED)
1756 {
1757   struct TunnelState *ts = *tunnel_ctx;
1758   const struct GNUNET_EXIT_TcpDataMessage *data;
1759   size_t mlen;
1760
1761   GNUNET_STATISTICS_update (stats,
1762                             gettext_noop ("# TCP packets received from mesh"),
1763                             1, GNUNET_NO);
1764   mlen = ntohs (message->size);
1765   if (mlen < sizeof (struct GNUNET_EXIT_TcpDataMessage))
1766   {
1767     GNUNET_break_op (0);
1768     return GNUNET_SYSERR;
1769   }
1770   if (NULL == ts->heap_node)
1771   {
1772     GNUNET_break_op (0);
1773     return GNUNET_SYSERR;
1774   }
1775   data = (const struct GNUNET_EXIT_TcpDataMessage *) message;
1776   mlen -= sizeof (struct GNUNET_EXIT_TcpDataMessage);
1777   {
1778     char sbuf[INET6_ADDRSTRLEN];
1779     char dbuf[INET6_ADDRSTRLEN];
1780     
1781     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1782                 "Received TCP reply from mesh, sending %u bytes from %s:%u -> %s:%u via TUN\n",
1783                 (unsigned int) mlen,
1784                 inet_ntop (ts->af, &ts->destination_ip, sbuf, sizeof (sbuf)),
1785                 ts->destination_port,
1786                 inet_ntop (ts->af, &ts->source_ip, dbuf, sizeof (dbuf)),
1787                 ts->source_port);
1788   }
1789   switch (ts->af)
1790   {
1791   case AF_INET:
1792     {
1793       size_t size = sizeof (struct GNUNET_TUN_IPv4Header) 
1794         + sizeof (struct GNUNET_TUN_TcpHeader) 
1795         + sizeof (struct GNUNET_MessageHeader) +
1796         sizeof (struct GNUNET_TUN_Layer2PacketHeader) +
1797         mlen;
1798       {
1799         char buf[size];
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_TcpHeader *tcp = (struct GNUNET_TUN_TcpHeader *) &ipv4[1];
1804         msg->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
1805         msg->size = htons (size);
1806         tun->flags = htons (0);
1807         tun->proto = htons (ETH_P_IPV4);
1808         GNUNET_TUN_initialize_ipv4_header (ipv4,
1809                                            IPPROTO_TCP,
1810                                            sizeof (struct GNUNET_TUN_TcpHeader) + mlen,
1811                                            &ts->destination_ip.v4,
1812                                            &ts->source_ip.v4);
1813         *tcp = data->tcp_header;
1814         tcp->spt = htons (ts->destination_port);
1815         tcp->dpt = htons (ts->source_port);
1816         GNUNET_TUN_calculate_tcp4_checksum (ipv4,
1817                                             tcp,
1818                                             &data[1],
1819                                             mlen);
1820         memcpy (&tcp[1],
1821                 &data[1],
1822                 mlen);
1823         (void) GNUNET_HELPER_send (helper_handle,
1824                                    msg,
1825                                    GNUNET_YES,
1826                                    NULL, NULL);
1827       }
1828     }
1829     break;
1830   case AF_INET6:
1831     {
1832       size_t size = sizeof (struct GNUNET_TUN_IPv6Header) 
1833         + sizeof (struct GNUNET_TUN_TcpHeader) 
1834         + sizeof (struct GNUNET_MessageHeader) +
1835         sizeof (struct GNUNET_TUN_Layer2PacketHeader) +
1836         mlen;
1837       {
1838         char buf[size];
1839         struct GNUNET_MessageHeader *msg = (struct GNUNET_MessageHeader *) buf;
1840         struct GNUNET_TUN_Layer2PacketHeader *tun = (struct GNUNET_TUN_Layer2PacketHeader*) &msg[1];
1841         struct GNUNET_TUN_IPv6Header *ipv6 = (struct GNUNET_TUN_IPv6Header *) &tun[1];
1842         struct GNUNET_TUN_TcpHeader *tcp = (struct GNUNET_TUN_TcpHeader *) &ipv6[1];
1843         msg->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
1844         msg->size = htons (size);
1845         tun->flags = htons (0);
1846         tun->proto = htons (ETH_P_IPV6);
1847         GNUNET_TUN_initialize_ipv6_header (ipv6,
1848                                            IPPROTO_TCP,
1849                                            sizeof (struct GNUNET_TUN_TcpHeader) + mlen,
1850                                            &ts->destination_ip.v6,
1851                                            &ts->source_ip.v6);
1852         tcp->spt = htons (ts->destination_port);
1853         tcp->dpt = htons (ts->source_port);
1854         GNUNET_TUN_calculate_tcp6_checksum (ipv6,
1855                                             tcp,
1856                                             &tcp[1],
1857                                             mlen);
1858         (void) GNUNET_HELPER_send (helper_handle,
1859                                    msg,
1860                                    GNUNET_YES,
1861                                    NULL, NULL);
1862       }
1863     }
1864     break;
1865   }
1866   GNUNET_CONTAINER_heap_update_cost (tunnel_heap, 
1867                                      ts->heap_node,
1868                                      GNUNET_TIME_absolute_get ().abs_value);
1869   return GNUNET_OK;
1870 }
1871
1872
1873 /**
1874  * Allocate an IPv4 address from the range of the tunnel
1875  * for a new redirection.
1876  *
1877  * @param v4 where to store the address
1878  * @return GNUNET_OK on success,
1879  *         GNUNET_SYSERR on error
1880  */
1881 static int
1882 allocate_v4_address (struct in_addr *v4)
1883 {
1884   const char *ipv4addr = vpn_argv[4];
1885   const char *ipv4mask = vpn_argv[5];
1886   struct in_addr addr;
1887   struct in_addr mask;
1888   struct in_addr rnd;
1889   GNUNET_HashCode key;
1890   unsigned int tries;
1891
1892   GNUNET_assert (1 == inet_pton (AF_INET, ipv4addr, &addr));
1893   GNUNET_assert (1 == inet_pton (AF_INET, ipv4mask, &mask));           
1894   /* Given 192.168.0.1/255.255.0.0, we want a mask 
1895      of '192.168.255.255', thus:  */
1896   mask.s_addr = addr.s_addr | ~mask.s_addr;  
1897   tries = 0;
1898   do
1899     {
1900       tries++;
1901       if (tries > 16)
1902       {
1903         GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1904                     _("Failed to find unallocated IPv4 address in VPN's range\n"));
1905         return GNUNET_SYSERR;
1906       }
1907       /* Pick random IPv4 address within the subnet, except 'addr' or 'mask' itself */
1908       rnd.s_addr = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, 
1909                                              UINT32_MAX);       
1910       v4->s_addr = (addr.s_addr | rnd.s_addr) & mask.s_addr;          
1911       get_destination_key_from_ip (AF_INET,
1912                                    v4,
1913                                    &key);
1914     }
1915   while ( (GNUNET_YES ==
1916            GNUNET_CONTAINER_multihashmap_contains (destination_map,
1917                                                    &key)) ||
1918           (v4->s_addr == addr.s_addr) ||
1919           (v4->s_addr == mask.s_addr) );
1920   return GNUNET_OK;
1921 }
1922
1923
1924 /**
1925  * Allocate an IPv6 address from the range of the tunnel
1926  * for a new redirection.
1927  *
1928  * @param v6 where to store the address
1929  * @return GNUNET_OK on success,
1930  *         GNUNET_SYSERR on error
1931  */
1932 static int
1933 allocate_v6_address (struct in6_addr *v6)
1934 {
1935   const char *ipv6addr = vpn_argv[2];
1936   struct in6_addr addr;
1937   struct in6_addr mask;
1938   struct in6_addr rnd;
1939   int i;
1940   GNUNET_HashCode key;
1941   unsigned int tries;
1942
1943   GNUNET_assert (1 == inet_pton (AF_INET6, ipv6addr, &addr));
1944   GNUNET_assert (ipv6prefix < 128);
1945   /* Given ABCD::/96, we want a mask of 'ABCD::FFFF:FFFF,
1946      thus: */
1947   mask = addr;
1948   for (i=127;i>=128-ipv6prefix;i--)
1949     mask.s6_addr[i / 8] |= (1 << (i % 8));
1950   
1951   /* Pick random IPv6 address within the subnet, except 'addr' or 'mask' itself */
1952   tries = 0;
1953   do
1954     {
1955       tries++;
1956       if (tries > 16)
1957         {
1958           GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1959                       _("Failed to find unallocated IPv6 address in VPN's range\n"));
1960           return GNUNET_SYSERR;
1961
1962         }
1963       for (i=0;i<16;i++)
1964         {
1965           rnd.s6_addr[i] = (unsigned char) GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, 
1966                                                                      256);
1967           v6->s6_addr[i]
1968             = (addr.s6_addr[i] | rnd.s6_addr[i]) & mask.s6_addr[i];
1969         }
1970       get_destination_key_from_ip (AF_INET6,
1971                                    v6,
1972                                    &key);
1973     }
1974   while ( (GNUNET_YES ==
1975            GNUNET_CONTAINER_multihashmap_contains (destination_map,
1976                                                    &key)) ||
1977           (0 == memcmp (v6,
1978                         &addr,
1979                         sizeof (struct in6_addr))) ||
1980           (0 == memcmp (v6,
1981                         &mask,
1982                         sizeof (struct in6_addr))) );
1983   return GNUNET_OK;
1984 }
1985
1986
1987 /**
1988  * Free resources occupied by a destination entry.
1989  *
1990  * @param de entry to free
1991  */
1992 static void
1993 free_destination_entry (struct DestinationEntry *de)
1994 {
1995   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1996               "Cleaning up destination entry\n");
1997   GNUNET_STATISTICS_update (stats,
1998                             gettext_noop ("# Active destinations"),
1999                             -1, GNUNET_NO);
2000   if (NULL != de->ts)
2001   {
2002     free_tunnel_state (de->ts);
2003     GNUNET_assert (NULL == de->ts);
2004   }
2005   if (NULL != de->heap_node)
2006   {
2007     GNUNET_CONTAINER_heap_remove_node (de->heap_node);
2008     de->heap_node = NULL;  
2009     GNUNET_assert (GNUNET_YES ==
2010                    GNUNET_CONTAINER_multihashmap_remove (destination_map,
2011                                                          &de->key,
2012                                                          de));
2013   }
2014   GNUNET_free (de);
2015 }
2016
2017
2018 /**
2019  * We have too many active destinations.  Clean up the oldest destination.
2020  *
2021  * @param except destination that must NOT be cleaned up, even if it is the oldest
2022  */
2023 static void 
2024 expire_destination (struct DestinationEntry *except)
2025 {
2026   struct DestinationEntry *de;
2027
2028   de = GNUNET_CONTAINER_heap_peek (destination_heap);
2029   if (except == de)
2030     return; /* can't do this */
2031   free_destination_entry (de);
2032 }
2033
2034
2035 /**
2036  * A client asks us to setup a redirection via some exit
2037  * node to a particular IP.  Setup the redirection and
2038  * give the client the allocated IP.
2039  *
2040  * @param cls unused
2041  * @param client requesting client
2042  * @param message redirection request (a 'struct RedirectToIpRequestMessage')
2043  */
2044 static void
2045 service_redirect_to_ip (void *cls GNUNET_UNUSED, struct GNUNET_SERVER_Client *client,
2046                         const struct GNUNET_MessageHeader *message)
2047 {
2048   size_t mlen;
2049   size_t alen;
2050   const struct RedirectToIpRequestMessage *msg;
2051   int addr_af;
2052   int result_af;
2053   struct in_addr v4;
2054   struct in6_addr v6;
2055   void *addr;
2056   struct DestinationEntry *de;
2057   GNUNET_HashCode key;
2058   
2059   /* validate and parse request */
2060   mlen = ntohs (message->size);
2061   if (mlen < sizeof (struct RedirectToIpRequestMessage))
2062   {
2063     GNUNET_break (0);
2064     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2065     return;
2066   }
2067   alen = mlen - sizeof (struct RedirectToIpRequestMessage);
2068   msg = (const struct RedirectToIpRequestMessage *) message;
2069   addr_af = (int) htonl (msg->addr_af);
2070   switch (addr_af)
2071   {
2072   case AF_INET:
2073     if (alen != sizeof (struct in_addr))
2074     {
2075       GNUNET_break (0);
2076       GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2077       return;      
2078     }
2079     break;
2080   case AF_INET6:
2081     if (alen != sizeof (struct in6_addr))
2082     {
2083       GNUNET_break (0);
2084       GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2085       return;      
2086     }
2087     break;
2088   default:
2089     GNUNET_break (0);
2090     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2091     return;      
2092   }
2093
2094   /* allocate response IP */
2095   addr = NULL;
2096   result_af = (int) htonl (msg->result_af);
2097   switch (result_af)
2098   {
2099   case AF_INET:
2100     if (GNUNET_OK !=
2101         allocate_v4_address (&v4))
2102       result_af = AF_UNSPEC;
2103     else
2104       addr = &v4;
2105     break;
2106   case AF_INET6:
2107     if (GNUNET_OK !=
2108         allocate_v6_address (&v6))
2109       result_af = AF_UNSPEC;
2110     else
2111       addr = &v6;
2112     break;
2113   case AF_UNSPEC:
2114     if (GNUNET_OK ==
2115         allocate_v4_address (&v4))
2116     {
2117       addr = &v4;
2118       result_af = AF_INET;
2119     }
2120     else if (GNUNET_OK ==
2121         allocate_v6_address (&v6))
2122     {
2123       addr = &v6;
2124       result_af = AF_INET6;
2125     }
2126     break;
2127   default:
2128     GNUNET_break (0);
2129     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2130     return;      
2131   }
2132   if ( (result_af == AF_UNSPEC) ||
2133        (GNUNET_NO == ntohl (msg->nac)) )
2134   {
2135     /* send reply "instantly" */
2136     send_client_reply (client,
2137                        msg->request_id,
2138                        result_af,
2139                        addr);
2140   }
2141   if (result_af == AF_UNSPEC)
2142   {
2143     /* failure, we're done */
2144     GNUNET_SERVER_receive_done (client, GNUNET_OK);
2145     return;
2146   }
2147
2148   {
2149     char sbuf[INET6_ADDRSTRLEN];
2150     char dbuf[INET6_ADDRSTRLEN];
2151     
2152     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2153                 "Allocated address %s for redirection via exit to %s\n",
2154                 inet_ntop (result_af, addr, sbuf, sizeof (sbuf)),
2155                 inet_ntop (addr_af,
2156                            &msg[1], dbuf, sizeof (dbuf)));
2157   }
2158   
2159   /* setup destination record */
2160   de = GNUNET_malloc (sizeof (struct DestinationEntry));
2161   de->is_service = GNUNET_NO;
2162   de->details.exit_destination.af = addr_af;
2163   memcpy (&de->details.exit_destination.ip,
2164           &msg[1],
2165           alen);
2166   get_destination_key_from_ip (result_af,
2167                                addr,
2168                                &key);
2169   de->key = key;
2170   GNUNET_assert (GNUNET_OK ==
2171                  GNUNET_CONTAINER_multihashmap_put (destination_map,
2172                                                     &key,
2173                                                     de,
2174                                                     GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE));
2175   de->heap_node = GNUNET_CONTAINER_heap_insert (destination_heap,
2176                                                 de,
2177                                                 GNUNET_TIME_absolute_ntoh (msg->expiration_time).abs_value);
2178   GNUNET_STATISTICS_update (stats,
2179                             gettext_noop ("# Active destinations"),
2180                             1, GNUNET_NO);
2181   while (GNUNET_CONTAINER_multihashmap_size (destination_map) > max_destination_mappings)
2182     expire_destination (de);
2183
2184   /* setup tunnel to destination */
2185   (void) create_tunnel_to_destination (de, 
2186                                        (GNUNET_NO == ntohl (msg->nac)) ? NULL : client,
2187                                        msg->request_id);
2188   /* we're done */
2189   GNUNET_SERVER_receive_done (client, GNUNET_OK);
2190 }
2191
2192
2193 /**
2194  * A client asks us to setup a redirection to a particular peer
2195  * offering a service.  Setup the redirection and give the client the
2196  * allocated IP.
2197  *
2198  * @param cls unused
2199  * @param client requesting client
2200  * @param message redirection request (a 'struct RedirectToPeerRequestMessage')
2201  */
2202 static void
2203 service_redirect_to_service (void *cls GNUNET_UNUSED, struct GNUNET_SERVER_Client *client,
2204                              const struct GNUNET_MessageHeader *message)
2205 {
2206   const struct RedirectToServiceRequestMessage *msg;
2207   int result_af;
2208   struct in_addr v4;
2209   struct in6_addr v6;
2210   void *addr;
2211   struct DestinationEntry *de;
2212   GNUNET_HashCode key;
2213   
2214   /*  parse request */
2215   msg = (const struct RedirectToServiceRequestMessage *) message;
2216
2217   /* allocate response IP */
2218   addr = NULL;
2219   result_af = (int) htonl (msg->result_af);
2220   switch (result_af)
2221   {
2222   case AF_INET:
2223     if (GNUNET_OK !=
2224         allocate_v4_address (&v4))
2225       result_af = AF_UNSPEC;
2226     else
2227       addr = &v4;
2228     break;
2229   case AF_INET6:
2230     if (GNUNET_OK !=
2231         allocate_v6_address (&v6))
2232       result_af = AF_UNSPEC;
2233     else
2234       addr = &v6;
2235     break;
2236   case AF_UNSPEC:
2237     if (GNUNET_OK ==
2238         allocate_v4_address (&v4))
2239     {
2240       addr = &v4;
2241       result_af = AF_INET;
2242     }
2243     else if (GNUNET_OK ==
2244         allocate_v6_address (&v6))
2245     {
2246       addr = &v6;
2247       result_af = AF_INET6;
2248     }
2249     break;
2250   default:
2251     GNUNET_break (0);
2252     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2253     return;      
2254   }
2255   if ( (result_af == AF_UNSPEC) ||
2256        (GNUNET_NO == ntohl (msg->nac)) )
2257   {
2258     /* send reply "instantly" */
2259     send_client_reply (client,
2260                        msg->request_id,
2261                        result_af,
2262                        addr);
2263   }
2264   if (result_af == AF_UNSPEC)
2265   {
2266     /* failure, we're done */
2267     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2268                 _("Failed to allocate IP address for new destination\n"));
2269     GNUNET_SERVER_receive_done (client, GNUNET_OK);
2270     return;
2271   }
2272
2273   {
2274     char sbuf[INET6_ADDRSTRLEN];
2275     
2276     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2277                 "Allocated address %s for redirection to service %s on peer %s\n",
2278                 inet_ntop (result_af, addr, sbuf, sizeof (sbuf)),
2279                 GNUNET_h2s (&msg->service_descriptor),
2280                 GNUNET_i2s (&msg->target));
2281   }
2282   
2283   /* setup destination record */
2284   de = GNUNET_malloc (sizeof (struct DestinationEntry));
2285   de->is_service = GNUNET_YES;
2286   de->details.service_destination.service_descriptor = msg->service_descriptor;
2287   de->details.service_destination.target = msg->target;
2288   get_destination_key_from_ip (result_af,
2289                                addr,
2290                                &key);
2291   de->key = key;
2292   GNUNET_assert (GNUNET_OK ==
2293                  GNUNET_CONTAINER_multihashmap_put (destination_map,
2294                                                     &key,
2295                                                     de,
2296                                                     GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE));
2297   de->heap_node = GNUNET_CONTAINER_heap_insert (destination_heap,
2298                                                 de,
2299                                                 GNUNET_TIME_absolute_ntoh (msg->expiration_time).abs_value);
2300   while (GNUNET_CONTAINER_multihashmap_size (destination_map) > max_destination_mappings)
2301     expire_destination (de);
2302   (void) create_tunnel_to_destination (de,
2303                                        (GNUNET_NO == ntohl (msg->nac)) ? NULL : client,
2304                                        msg->request_id);
2305   /* we're done */
2306   GNUNET_SERVER_receive_done (client, GNUNET_OK);
2307 }
2308
2309
2310
2311 /**
2312  * Function called for inbound tunnels.  As we don't offer
2313  * any mesh services, this function should never be called.
2314  *
2315  * @param cls closure
2316  * @param tunnel new handle to the tunnel
2317  * @param initiator peer that started the tunnel
2318  * @param atsi performance information for the tunnel
2319  * @return initial tunnel context for the tunnel
2320  *         (can be NULL -- that's not an error)
2321  */ 
2322 static void *
2323 inbound_tunnel_cb (void *cls, struct GNUNET_MESH_Tunnel *tunnel,
2324                    const struct GNUNET_PeerIdentity *initiator,
2325                    const struct GNUNET_ATS_Information *atsi)
2326 {
2327   /* How can and why should anyone open an inbound tunnel to vpn? */
2328   GNUNET_break (0);
2329   return NULL;
2330 }
2331
2332
2333 /**
2334  * Function called whenever an inbound tunnel is destroyed.  Should clean up
2335  * any associated state.
2336  *
2337  * @param cls closure (set from GNUNET_MESH_connect)
2338  * @param tunnel connection to the other end (henceforth invalid)
2339  * @param tunnel_ctx place where local state associated
2340  *                   with the tunnel is stored (our 'struct TunnelState')
2341  */ 
2342 static void
2343 tunnel_cleaner (void *cls, const struct GNUNET_MESH_Tunnel *tunnel, void *tunnel_ctx)
2344 {
2345   /* we don't have inbound tunnels, so this function should never be called */
2346   GNUNET_break (0);
2347 }
2348
2349
2350 /**
2351  * Free memory occupied by an entry in the destination map.
2352  *
2353  * @param cls unused
2354  * @param key unused
2355  * @param value a 'struct DestinationEntry *'
2356  * @return GNUNET_OK (continue to iterate)
2357  */
2358 static int
2359 cleanup_destination (void *cls,
2360                      const GNUNET_HashCode *key,
2361                      void *value)
2362 {
2363   struct DestinationEntry *de = value;
2364
2365   free_destination_entry (de);
2366   return GNUNET_OK;
2367 }
2368
2369
2370 /**
2371  * Free memory occupied by an entry in the tunnel map.
2372  *
2373  * @param cls unused
2374  * @param key unused
2375  * @param value a 'struct TunnelState *'
2376  * @return GNUNET_OK (continue to iterate)
2377  */
2378 static int
2379 cleanup_tunnel (void *cls,
2380                 const GNUNET_HashCode *key,
2381                 void *value)
2382 {
2383   struct TunnelState *ts = value;
2384
2385   free_tunnel_state (ts);
2386   return GNUNET_OK;
2387 }
2388
2389
2390 /**
2391  * Function scheduled as very last function, cleans up after us
2392  *
2393  * @param cls unused
2394  * @param tc unused
2395  */
2396 static void
2397 cleanup (void *cls GNUNET_UNUSED,
2398          const struct GNUNET_SCHEDULER_TaskContext *tc)
2399 {
2400   unsigned int i;
2401
2402   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2403               "VPN is shutting down\n");
2404   if (NULL != destination_map)
2405   {  
2406     GNUNET_CONTAINER_multihashmap_iterate (destination_map,
2407                                            &cleanup_destination,
2408                                            NULL);
2409     GNUNET_CONTAINER_multihashmap_destroy (destination_map);
2410     destination_map = NULL;
2411   }
2412   if (NULL != destination_heap)
2413   {
2414     GNUNET_CONTAINER_heap_destroy (destination_heap);
2415     destination_heap = NULL;
2416   }
2417   if (NULL != tunnel_map)
2418   {  
2419     GNUNET_CONTAINER_multihashmap_iterate (tunnel_map,
2420                                            &cleanup_tunnel,
2421                                            NULL);
2422     GNUNET_CONTAINER_multihashmap_destroy (tunnel_map);
2423     tunnel_map = NULL;
2424   }
2425   if (NULL != tunnel_heap)
2426   {
2427     GNUNET_CONTAINER_heap_destroy (tunnel_heap);
2428     tunnel_heap = NULL;
2429   }
2430   if (NULL != mesh_handle)
2431   {
2432     GNUNET_MESH_disconnect (mesh_handle);
2433     mesh_handle = NULL;
2434   }
2435   if (NULL != helper_handle)
2436     {
2437     GNUNET_HELPER_stop (helper_handle);
2438     helper_handle = NULL;
2439   }
2440   if (NULL != nc)
2441   {
2442     GNUNET_SERVER_notification_context_destroy (nc);
2443     nc = NULL;
2444   }
2445   if (stats != NULL)
2446   {
2447     GNUNET_STATISTICS_destroy (stats, GNUNET_YES);
2448     stats = NULL;
2449   }
2450   for (i=0;i<5;i++)
2451     GNUNET_free_non_null (vpn_argv[i]);
2452 }
2453
2454
2455 /**
2456  * A client disconnected, clean up all references to it.
2457  *
2458  * @param cls the client that disconnected
2459  * @param key unused
2460  * @param value a 'struct TunnelState *'
2461  * @return GNUNET_OK (continue to iterate)
2462  */
2463 static int
2464 cleanup_tunnel_client (void *cls,
2465                        const GNUNET_HashCode *key,
2466                        void *value)
2467 {
2468   struct GNUNET_SERVER_Client *client = cls;
2469   struct TunnelState *ts = value;
2470
2471   if (client == ts->client)
2472   {
2473     GNUNET_SERVER_client_drop (ts->client);
2474     ts->client = NULL;
2475   }
2476   return GNUNET_OK;
2477 }
2478
2479
2480 /**
2481  * A client disconnected, clean up all references to it.
2482  *
2483  * @param cls the client that disconnected
2484  * @param key unused
2485  * @param value a 'struct DestinationEntry *'
2486  * @return GNUNET_OK (continue to iterate)
2487  */
2488 static int
2489 cleanup_destination_client (void *cls,
2490                             const GNUNET_HashCode *key,
2491                             void *value)
2492 {
2493   struct GNUNET_SERVER_Client *client = cls;
2494   struct DestinationEntry *de = value;
2495   struct TunnelState *ts;
2496
2497   if (NULL == (ts = de->ts))
2498     return GNUNET_OK;
2499   if (client == ts->client)
2500   {
2501     GNUNET_SERVER_client_drop (ts->client);
2502     ts->client = NULL;
2503   }
2504   return GNUNET_OK;
2505 }
2506
2507   
2508 /**
2509  * A client has disconnected from us.  If we are currently building
2510  * a tunnel for it, cancel the operation.
2511  *
2512  * @param cls unused
2513  * @param client handle to the client that disconnected
2514  */
2515 static void
2516 client_disconnect (void *cls, struct GNUNET_SERVER_Client *client)
2517 {
2518   if (NULL != tunnel_map)
2519     GNUNET_CONTAINER_multihashmap_iterate (tunnel_map,
2520                                            &cleanup_tunnel_client,
2521                                            client);
2522   if (NULL != destination_map)
2523     GNUNET_CONTAINER_multihashmap_iterate (destination_map,
2524                                            &cleanup_destination_client,
2525                                            client);
2526 }
2527
2528
2529 /**
2530  * Main function that will be run by the scheduler.
2531  *
2532  * @param cls closure
2533  * @param server the initialized server
2534  * @param cfg_ configuration
2535  */
2536 static void
2537 run (void *cls,
2538      struct GNUNET_SERVER_Handle *server,
2539      const struct GNUNET_CONFIGURATION_Handle *cfg_)
2540 {
2541   static const struct GNUNET_SERVER_MessageHandler service_handlers[] = {
2542     /* callback, cls, type, size */
2543     { &service_redirect_to_ip, NULL, GNUNET_MESSAGE_TYPE_VPN_CLIENT_REDIRECT_TO_IP, 0},
2544     { &service_redirect_to_service, NULL, 
2545      GNUNET_MESSAGE_TYPE_VPN_CLIENT_REDIRECT_TO_SERVICE, 
2546      sizeof (struct RedirectToServiceRequestMessage) },
2547     {NULL, NULL, 0, 0}
2548   };
2549   static const struct GNUNET_MESH_MessageHandler mesh_handlers[] = {
2550     { &receive_udp_back, GNUNET_MESSAGE_TYPE_VPN_UDP_REPLY, 0},
2551     { &receive_tcp_back, GNUNET_MESSAGE_TYPE_VPN_TCP_DATA_TO_VPN, 0},
2552     { &receive_icmp_back, GNUNET_MESSAGE_TYPE_VPN_ICMP_TO_VPN, 0},
2553     {NULL, 0, 0}
2554   };
2555   static const GNUNET_MESH_ApplicationType types[] = {
2556     GNUNET_APPLICATION_TYPE_END
2557   };
2558   char *ifname;
2559   char *ipv6addr;
2560   char *ipv6prefix_s;
2561   char *ipv4addr;
2562   char *ipv4mask;
2563   struct in_addr v4;
2564   struct in6_addr v6;
2565
2566   cfg = cfg_;
2567   stats = GNUNET_STATISTICS_create ("vpn", cfg);
2568   if (GNUNET_OK !=
2569       GNUNET_CONFIGURATION_get_value_number (cfg, "vpn", "MAX_MAPPING",
2570                                              &max_destination_mappings))
2571     max_destination_mappings = 200;
2572   if (GNUNET_OK !=
2573       GNUNET_CONFIGURATION_get_value_number (cfg, "vpn", "MAX_TUNNELS",
2574                                              &max_tunnel_mappings))
2575     max_tunnel_mappings = 200;
2576
2577   destination_map = GNUNET_CONTAINER_multihashmap_create (max_destination_mappings * 2);
2578   destination_heap = GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN);
2579   tunnel_map = GNUNET_CONTAINER_multihashmap_create (max_tunnel_mappings * 2);
2580   tunnel_heap = GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN);
2581
2582
2583   vpn_argv[0] = GNUNET_strdup ("vpn-gnunet");
2584   if (GNUNET_SYSERR ==
2585       GNUNET_CONFIGURATION_get_value_string (cfg, "vpn", "IFNAME", &ifname))
2586   {
2587     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2588                 "No entry 'IFNAME' in configuration!\n");
2589     GNUNET_SCHEDULER_shutdown ();
2590     return;
2591   }
2592   vpn_argv[1] = ifname;
2593   if ( (GNUNET_SYSERR ==
2594         GNUNET_CONFIGURATION_get_value_string (cfg, "vpn", "IPV6ADDR",
2595                                                &ipv6addr) ||
2596         (1 != inet_pton (AF_INET6, ipv6addr, &v6))) )
2597   {
2598     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2599                 "No valid entry 'IPV6ADDR' in configuration!\n");
2600     GNUNET_SCHEDULER_shutdown ();
2601     return;
2602   }
2603   vpn_argv[2] = ipv6addr;
2604   if (GNUNET_SYSERR ==
2605       GNUNET_CONFIGURATION_get_value_string (cfg, "vpn", "IPV6PREFIX",
2606                                              &ipv6prefix_s))
2607   {
2608     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2609                 "No entry 'IPV6PREFIX' in configuration!\n");
2610     GNUNET_SCHEDULER_shutdown ();
2611     return;
2612   }
2613   vpn_argv[3] = ipv6prefix_s;
2614   if ( (GNUNET_OK !=
2615         GNUNET_CONFIGURATION_get_value_number (cfg, "vpn",
2616                                                "IPV6PREFIX",
2617                                                &ipv6prefix)) ||
2618        (ipv6prefix >= 127) )
2619   {
2620     GNUNET_SCHEDULER_shutdown ();
2621     return;
2622   }
2623
2624   if ( (GNUNET_SYSERR ==
2625         GNUNET_CONFIGURATION_get_value_string (cfg, "vpn", "IPV4ADDR",
2626                                                &ipv4addr) ||
2627         (1 != inet_pton (AF_INET, ipv4addr, &v4))) )
2628   {
2629     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2630                 "No valid entry for 'IPV4ADDR' in configuration!\n");
2631     GNUNET_SCHEDULER_shutdown ();
2632     return;
2633   }
2634   vpn_argv[4] = ipv4addr;
2635   if ( (GNUNET_SYSERR ==
2636         GNUNET_CONFIGURATION_get_value_string (cfg, "vpn", "IPV4MASK",
2637                                                &ipv4mask) ||
2638         (1 != inet_pton (AF_INET, ipv4mask, &v4))) )
2639   {
2640     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2641                 "No valid entry 'IPV4MASK' in configuration!\n");
2642     GNUNET_SCHEDULER_shutdown ();
2643     return;
2644   }
2645   vpn_argv[5] = ipv4mask;
2646   vpn_argv[6] = NULL;
2647
2648   mesh_handle =
2649     GNUNET_MESH_connect (cfg_, 42 /* queue length */, NULL, 
2650                          &inbound_tunnel_cb, 
2651                          &tunnel_cleaner, 
2652                          mesh_handlers,
2653                          types);
2654   helper_handle = GNUNET_HELPER_start ("gnunet-helper-vpn", vpn_argv,
2655                                        &message_token, NULL);
2656   nc = GNUNET_SERVER_notification_context_create (server, 1);
2657   GNUNET_SERVER_add_handlers (server, service_handlers);
2658   GNUNET_SERVER_disconnect_notify (server, &client_disconnect, NULL);
2659   GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &cleanup, cls);
2660 }
2661
2662
2663 /**
2664  * The main function of the VPN service.
2665  *
2666  * @param argc number of arguments from the command line
2667  * @param argv command line arguments
2668  * @return 0 ok, 1 on error
2669  */
2670 int
2671 main (int argc, char *const *argv)
2672 {
2673   return (GNUNET_OK ==
2674           GNUNET_SERVICE_run (argc, argv, "vpn", 
2675                               GNUNET_SERVICE_OPTION_NONE,
2676                               &run, NULL)) ? 0 : 1;
2677 }
2678
2679 /* end of gnunet-service-vpn.c */