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