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