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