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