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