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