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