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