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