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