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