-use different message types for different directions for TCP DATA
[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  * Basics:
31  * - test!
32  *
33  * Features:
34  * - add back ICMP support (especially needed for IPv6)
35  */
36 #include "platform.h"
37 #include "gnunet_util_lib.h"
38 #include "gnunet_common.h"
39 #include "gnunet_protocols.h"
40 #include "gnunet_applications.h"
41 #include "gnunet_mesh_service.h"
42 #include "gnunet_statistics_service.h"
43 #include "gnunet_constants.h"
44 #include "gnunet_tun_lib.h"
45 #include "vpn.h"
46 #include "exit.h"
47
48
49 /**
50  * Maximum number of messages we allow in the queue for mesh.
51  */
52 #define MAX_MESSAGE_QUEUE_SIZE 4
53
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   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       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 transmission handle, NULL for none.
182    */
183   struct GNUNET_MESH_TransmitHandle *th;
184
185   /**
186    * Entry for this entry in the tunnel_heap, NULL as long as this
187    * tunnel state is not fully bound.
188    */
189   struct GNUNET_CONTAINER_HeapNode *heap_node;
190
191   /**
192    * Head of list of messages scheduled for transmission.
193    */
194   struct TunnelMessageQueueEntry *tmq_head;
195
196   /**
197    * Tail of list of messages scheduled for transmission.
198    */
199   struct TunnelMessageQueueEntry *tmq_tail;  
200
201   /**
202    * Client that needs to be notified about the tunnel being
203    * up as soon as a peer is connected; NULL for none.
204    */
205   struct GNUNET_SERVER_Client *client;
206
207   /**
208    * Destination entry that has a pointer to this tunnel state;
209    * NULL if this tunnel state is in the tunnel map.
210    */
211   struct DestinationEntry *destination_container;
212
213   /**
214    * ID of the client request that caused us to setup this entry.
215    */ 
216   uint64_t request_id;
217
218   /**
219    * Destination to which this tunnel leads.  Note that
220    * this struct is NOT in the destination_map (but a
221    * local copy) and that the 'heap_node' should always
222    * be NULL.
223    */
224   struct DestinationEntry destination;
225
226   /**
227    * Task scheduled to destroy the tunnel (or NO_TASK).
228    */
229   GNUNET_SCHEDULER_TaskIdentifier destroy_task;
230
231   /**
232    * Addess family used for this tunnel on the local TUN interface.
233    */
234   int af;
235
236   /**
237    * Length of the doubly linked 'tmq_head/tmq_tail' list.
238    */
239   unsigned int tmq_length;
240
241   /**
242    * IPPROTO_TCP or IPPROTO_UDP once bound.
243    */
244   uint8_t protocol;
245
246   /**
247    * IP address of the source on our end, initially uninitialized.
248    */
249   union
250   {
251     /**
252      * Address if af is AF_INET.
253      */
254     struct in_addr v4;
255     
256     /**
257      * Address if af is AF_INET6.
258      */
259     struct in6_addr v6;
260
261   } source_ip;
262
263   /**
264    * Destination IP address used by the source on our end (this is the IP
265    * that we pick freely within the VPN's tunnel IP range).
266    */
267   union
268   {
269     /**
270      * Address if af is AF_INET.
271      */
272     struct in_addr v4;
273     
274     /**
275      * Address if af is AF_INET6.
276      */
277     struct in6_addr v6;
278
279   } destination_ip;
280
281   /**
282    * Source port used by the sender on our end; 0 for uninitialized.
283    */
284   uint16_t source_port;
285
286   /**
287    * Destination port used by the sender on our end; 0 for uninitialized.
288    */
289   uint16_t destination_port;
290
291 };
292
293
294 /**
295  * Configuration we use.
296  */
297 static const struct GNUNET_CONFIGURATION_Handle *cfg;
298
299 /**
300  * Handle to the mesh service.
301  */
302 static struct GNUNET_MESH_Handle *mesh_handle;
303
304 /**
305  * Map from IP address to destination information (possibly with a
306  * MESH tunnel handle for fast setup).
307  */
308 static struct GNUNET_CONTAINER_MultiHashMap *destination_map;
309
310 /**
311  * Min-Heap sorted by activity time to expire old mappings.
312  */
313 static struct GNUNET_CONTAINER_Heap *destination_heap;
314
315 /**
316  * Map from source and destination address (IP+port) to connection
317  * information (mostly with the respective MESH tunnel handle).
318  */
319 static struct GNUNET_CONTAINER_MultiHashMap *tunnel_map;
320
321 /**
322  * Min-Heap sorted by activity time to expire old mappings; values are
323  * of type 'struct TunnelState'.
324  */
325 static struct GNUNET_CONTAINER_Heap *tunnel_heap;
326
327 /**
328  * Statistics.
329  */
330 static struct GNUNET_STATISTICS_Handle *stats;
331
332 /**
333  * The handle to the VPN helper process "gnunet-helper-vpn".
334  */
335 static struct GNUNET_HELPER_Handle *helper_handle;
336
337 /**
338  * Arguments to the vpn helper.
339  */
340 static char *vpn_argv[7];
341
342 /**
343  * Length of the prefix of the VPN's IPv6 network.
344  */
345 static unsigned long long ipv6prefix;
346
347 /**
348  * Notification context for sending replies to clients.
349  */
350 static struct GNUNET_SERVER_NotificationContext *nc;
351
352 /**
353  * If there are more than this number of address-mappings, old ones
354  * will be removed
355  */
356 static unsigned long long max_destination_mappings;
357
358 /**
359  * If there are more than this number of open tunnels, old ones
360  * will be removed
361  */
362 static unsigned long long max_tunnel_mappings;
363
364
365 /**
366  * Compute the key under which we would store an entry in the
367  * destination_map for the given IP address.
368  *
369  * @param af address family (AF_INET or AF_INET6)
370  * @param address IP address, struct in_addr or struct in6_addr
371  * @param key where to store the key
372  */
373 static void
374 get_destination_key_from_ip (int af,
375                              const void *address,
376                              GNUNET_HashCode *key)
377 {
378   switch (af)
379   {
380   case AF_INET:
381     GNUNET_CRYPTO_hash (address,
382                         sizeof (struct in_addr),
383                         key);
384     break;
385   case AF_INET6:
386     GNUNET_CRYPTO_hash (address,
387                         sizeof (struct in6_addr),
388                         key);
389     break;
390   default:
391     GNUNET_assert (0);
392     break;
393   }
394 }
395
396
397 /**
398  * Compute the key under which we would store an entry in the
399  * tunnel_map for the given socket address pair.
400  *
401  * @param af address family (AF_INET or AF_INET6)
402  * @param protocol IPPROTO_TCP or IPPROTO_UDP
403  * @param source_ip sender's source IP, struct in_addr or struct in6_addr
404  * @param source_port sender's source port
405  * @param destination_ip sender's destination IP, struct in_addr or struct in6_addr
406  * @param destination_port sender's destination port
407  * @param key where to store the key
408  */
409 static void
410 get_tunnel_key_from_ips (int af,
411                          uint8_t protocol,
412                          const void *source_ip,
413                          uint16_t source_port,
414                          const void *destination_ip,
415                          uint16_t destination_port,
416                          GNUNET_HashCode *key)
417 {
418   char *off;
419
420   memset (key, 0, sizeof (GNUNET_HashCode));
421   /* the GNUnet hashmap only uses the first sizeof(unsigned int) of the hash,
422      so we put the ports in there (and hope for few collisions) */
423   off = (char*) key;
424   memcpy (off, &source_port, sizeof (uint16_t));
425   off += sizeof (uint16_t);
426   memcpy (off, &destination_port, sizeof (uint16_t));
427   off += sizeof (uint16_t);
428   switch (af)
429   {
430   case AF_INET:
431     memcpy (off, source_ip, sizeof (struct in_addr));
432     off += sizeof (struct in_addr);
433     memcpy (off, destination_ip, sizeof (struct in_addr));
434     off += sizeof (struct in_addr);
435     break;
436   case AF_INET6:
437     memcpy (off, source_ip, sizeof (struct in6_addr));
438     off += sizeof (struct in6_addr);
439     memcpy (off, destination_ip, sizeof (struct in6_addr));
440     off += sizeof (struct in6_addr);
441     break;
442   default:
443     GNUNET_assert (0);
444     break;
445   }
446   memcpy (off, &protocol, sizeof (uint8_t));
447   off += sizeof (uint8_t);  
448 }
449
450
451 /**
452  * Notify the client about the result of its request.
453  *
454  * @param client client to notify
455  * @param request_id original request ID to include in response
456  * @param result_af resulting address family
457  * @param addr resulting IP address
458  */
459 static void
460 send_client_reply (struct GNUNET_SERVER_Client *client,
461                    uint64_t request_id,
462                    int result_af,
463                    const void *addr)
464 {
465   char buf[sizeof (struct RedirectToIpResponseMessage) + sizeof (struct in6_addr)];
466   struct RedirectToIpResponseMessage *res;
467   size_t rlen;
468
469   switch (result_af)
470   {
471   case AF_INET:
472     rlen = sizeof (struct in_addr);    
473     break;
474   case AF_INET6:
475     rlen = sizeof (struct in6_addr);
476     break;
477   case AF_UNSPEC:
478     rlen = 0;
479     break;
480   default:
481     GNUNET_assert (0);
482     return;
483   }
484   res = (struct RedirectToIpResponseMessage *) buf;
485   res->header.size = htons (sizeof (struct RedirectToIpResponseMessage) + rlen);
486   res->header.type = htons (GNUNET_MESSAGE_TYPE_VPN_CLIENT_USE_IP);
487   res->result_af = htonl (result_af);
488   res->request_id = request_id;
489   memcpy (&res[1], addr, rlen);
490   GNUNET_SERVER_notification_context_add (nc, client);
491   GNUNET_SERVER_notification_context_unicast (nc,
492                                               client,
493                                               &res->header,
494                                               GNUNET_NO);
495 }
496
497
498 /**
499  * Free resources associated with a tunnel state.
500  *
501  * @param ts state to free
502  */
503 static void
504 free_tunnel_state (struct TunnelState *ts)
505 {
506   GNUNET_HashCode key;
507   struct TunnelMessageQueueEntry *tnq;
508   struct GNUNET_MESH_Tunnel *tunnel;
509
510   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
511               "Cleaning up tunnel state\n");
512   GNUNET_STATISTICS_update (stats,
513                             gettext_noop ("# Active tunnels"),
514                             -1, GNUNET_NO);
515   while (NULL != (tnq = ts->tmq_head))
516   {
517     GNUNET_CONTAINER_DLL_remove (ts->tmq_head,
518                                  ts->tmq_tail,
519                                  tnq);
520     ts->tmq_length--;
521     GNUNET_free (tnq);
522   }
523   GNUNET_assert (0 == ts->tmq_length);
524   if (NULL != ts->client)
525   {
526     GNUNET_SERVER_client_drop (ts->client);
527     ts->client = NULL;
528   }
529   if (NULL != ts->th)
530   {
531     GNUNET_MESH_notify_transmit_ready_cancel (ts->th);
532     ts->th = NULL;
533   }
534   GNUNET_assert (NULL == ts->destination.heap_node);
535   if (NULL != (tunnel = ts->tunnel))
536   {
537     ts->tunnel = NULL;
538     GNUNET_MESH_tunnel_destroy (tunnel);
539   }
540   if (GNUNET_SCHEDULER_NO_TASK != ts->destroy_task)
541   {
542     GNUNET_SCHEDULER_cancel (ts->destroy_task);
543     ts->destroy_task = GNUNET_SCHEDULER_NO_TASK;
544   }
545   if (NULL != ts->heap_node)
546   {
547     GNUNET_CONTAINER_heap_remove_node (ts->heap_node);
548     ts->heap_node = NULL;
549     get_tunnel_key_from_ips (ts->af,
550                              ts->protocol,
551                              &ts->source_ip,
552                              ts->source_port,
553                              &ts->destination_ip,
554                              ts->destination_port,
555                              &key);
556     GNUNET_assert (GNUNET_YES ==
557                    GNUNET_CONTAINER_multihashmap_remove (tunnel_map,
558                                                          &key,
559                                                          ts));
560   }
561   if (NULL != ts->destination_container)
562   {
563     GNUNET_assert (ts == ts->destination_container->ts);
564     ts->destination_container->ts = NULL;
565     ts->destination_container = NULL;
566   }
567   GNUNET_free (ts);
568 }
569
570
571 /**
572  * Destroy the mesh tunnel.
573  *
574  * @param cls the 'struct TunnelState' with the tunnel to destroy
575  * @param ts schedule context
576  */
577 static void
578 destroy_tunnel_task (void *cls,
579                      const struct GNUNET_SCHEDULER_TaskContext *tc)
580 {
581   struct TunnelState *ts = cls;
582   struct GNUNET_MESH_Tunnel *tunnel;
583
584   ts->destroy_task = GNUNET_SCHEDULER_NO_TASK;
585   GNUNET_assert (NULL != ts->tunnel);
586   tunnel = ts->tunnel;
587   ts->tunnel = NULL;
588   GNUNET_MESH_tunnel_destroy (tunnel);
589   free_tunnel_state (ts);
590 }
591
592
593 /**
594  * Method called whenever a peer has disconnected from the tunnel.
595  *
596  * @param cls closure
597  * @param peer peer identity the tunnel stopped working with
598  */
599 static void
600 tunnel_peer_disconnect_handler (void *cls,
601                                 const struct
602                                 GNUNET_PeerIdentity * peer)
603 {
604   struct TunnelState *ts = cls;
605
606   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
607               "Peer %s disconnected from tunnel.\n",
608               GNUNET_i2s (peer));
609   GNUNET_STATISTICS_update (stats,
610                             gettext_noop ("# Peers connected to mesh tunnels"),
611                             -1, GNUNET_NO);
612   if (NULL != ts->th)
613   {
614     GNUNET_MESH_notify_transmit_ready_cancel (ts->th);
615     ts->th = NULL;
616   }
617   if (ts->destination.is_service)
618     return; /* hope for reconnect eventually */
619   /* as we are most likely going to change the exit node now,
620      we should just destroy the tunnel entirely... */
621   if (GNUNET_SCHEDULER_NO_TASK == ts->destroy_task)
622     ts->destroy_task = GNUNET_SCHEDULER_add_now (&destroy_tunnel_task, ts);
623 }
624
625
626 /**
627  * Method called whenever a peer has connected to the tunnel.  Notifies
628  * the waiting client that the tunnel is now up.
629  *
630  * @param cls closure
631  * @param peer peer identity the tunnel was created to, NULL on timeout
632  * @param atsi performance data for the connection
633  */
634 static void
635 tunnel_peer_connect_handler (void *cls,
636                              const struct GNUNET_PeerIdentity
637                              * peer,
638                              const struct
639                              GNUNET_ATS_Information * atsi)
640 {
641   struct TunnelState *ts = cls;
642
643   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
644               "Peer %s connected to tunnel.\n",
645               GNUNET_i2s (peer));
646   GNUNET_STATISTICS_update (stats,
647                             gettext_noop ("# Peers connected to mesh tunnels"),
648                             1, GNUNET_NO);
649   if (NULL == ts->client)
650     return; /* nothing to do */
651   send_client_reply (ts->client,
652                      ts->request_id,
653                      ts->af,
654                      &ts->destination_ip);
655   GNUNET_SERVER_client_drop (ts->client);
656   ts->client = NULL;
657 }
658
659
660 /**
661  * Send a message from the message queue via mesh.
662  *
663  * @param cls the 'struct TunnelState' with the message queue
664  * @param size number of bytes available in buf
665  * @param buf where to copy the message
666  * @return number of bytes copied to buf
667  */
668 static size_t
669 send_to_peer_notify_callback (void *cls, size_t size, void *buf)
670 {
671   struct TunnelState *ts = cls;
672   struct TunnelMessageQueueEntry *tnq;
673   size_t ret;
674
675   ts->th = NULL;
676   if (NULL == buf)
677     return 0;
678   tnq = ts->tmq_head;
679   GNUNET_assert (NULL != tnq);
680   GNUNET_assert (size >= tnq->len);
681   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
682               "Sending %u bytes via mesh tunnel\n",
683               tnq->len);
684   GNUNET_CONTAINER_DLL_remove (ts->tmq_head,
685                                ts->tmq_tail,
686                                tnq);
687   ts->tmq_length--;
688   memcpy (buf, tnq->msg, tnq->len);
689   ret = tnq->len;
690   GNUNET_free (tnq);
691   if (NULL != (tnq = ts->tmq_head))
692     ts->th = GNUNET_MESH_notify_transmit_ready (ts->tunnel, 
693                                                 GNUNET_NO /* cork */, 
694                                                 42 /* priority */,
695                                                 GNUNET_TIME_UNIT_FOREVER_REL,
696                                                 NULL, 
697                                                 tnq->len,
698                                                 &send_to_peer_notify_callback,
699                                                 ts);
700   GNUNET_STATISTICS_update (stats,
701                             gettext_noop ("# Bytes given to mesh for transmission"),
702                             ret, GNUNET_NO);
703   return ret;
704 }
705
706
707 /**
708  * Add the given message to the given tunnel and trigger the
709  * transmission process.
710  *
711  * @param tnq message to queue
712  * @param ts tunnel to queue the message for
713  */
714 static void
715 send_to_tunnel (struct TunnelMessageQueueEntry *tnq,
716                 struct TunnelState *ts)
717 {
718   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
719               "Queueing %u bytes for transmission via mesh tunnel\n",
720               tnq->len);
721   GNUNET_assert (NULL != ts->tunnel);
722   GNUNET_CONTAINER_DLL_insert_tail (ts->tmq_head,
723                                     ts->tmq_tail,
724                                     tnq);
725   ts->tmq_length++;
726   if (ts->tmq_length > MAX_MESSAGE_QUEUE_SIZE)
727   {
728     struct TunnelMessageQueueEntry *dq;
729
730     dq = ts->tmq_head;
731     GNUNET_assert (dq != tnq);
732     GNUNET_CONTAINER_DLL_remove (ts->tmq_head,
733                                  ts->tmq_tail,
734                                  dq);
735     GNUNET_MESH_notify_transmit_ready_cancel (ts->th);
736     ts->th = NULL;
737     GNUNET_STATISTICS_update (stats,
738                               gettext_noop ("# Bytes dropped in mesh queue (overflow)"),
739                               dq->len, 
740                               GNUNET_NO);
741     GNUNET_free (dq);
742   }
743   if (NULL == ts->th)
744     ts->th = GNUNET_MESH_notify_transmit_ready (ts->tunnel, 
745                                                 GNUNET_NO /* cork */,
746                                                 42 /* priority */,
747                                                 GNUNET_TIME_UNIT_FOREVER_REL,
748                                                 NULL, 
749                                                 tnq->len,
750                                                 &send_to_peer_notify_callback,
751                                                 ts);
752 }
753
754
755 /**
756  * Initialize the given destination entry's mesh tunnel.
757  *
758  * @param de destination entry for which we need to setup a tunnel
759  * @param client client to notify on successful tunnel setup, or NULL for none
760  * @param request_id request ID to send in client notification (unused if client is NULL)
761  * @return tunnel state of the tunnel that was created
762  */
763 static struct TunnelState *
764 create_tunnel_to_destination (struct DestinationEntry *de,
765                               struct GNUNET_SERVER_Client *client,
766                               uint64_t request_id)
767 {
768   struct TunnelState *ts;
769
770   GNUNET_STATISTICS_update (stats,
771                             gettext_noop ("# Mesh tunnels created"),
772                             1, GNUNET_NO);
773   GNUNET_assert (NULL == de->ts);
774   ts = GNUNET_malloc (sizeof (struct TunnelState));
775   if (NULL != client)
776   {
777     ts->request_id = request_id;
778     ts->client = client;
779     GNUNET_SERVER_client_keep (client);
780   }
781   ts->destination = *de;
782   ts->destination.heap_node = NULL; /* copy is NOT in destination heap */
783   de->ts = ts;
784   ts->destination_container = de; /* we are referenced from de */
785   ts->af = AF_UNSPEC; /* so far, unknown */
786   ts->tunnel = GNUNET_MESH_tunnel_create (mesh_handle,
787                                           ts,
788                                           &tunnel_peer_connect_handler,
789                                           &tunnel_peer_disconnect_handler,
790                                           ts);
791   if (NULL == ts->tunnel)
792   {
793     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
794                 _("Failed to setup mesh tunnel!\n"));
795     if (NULL != client)
796       GNUNET_SERVER_client_drop (client);
797     GNUNET_free (ts);
798     return NULL;
799   }
800   if (de->is_service)
801   {
802     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
803                 "Creating tunnel to peer %s offering service %s\n",
804                 GNUNET_i2s (&de->details.service_destination.target),
805                 GNUNET_h2s (&de->details.service_destination.service_descriptor));
806     GNUNET_MESH_peer_request_connect_add (ts->tunnel,
807                                           &de->details.service_destination.target);  
808   }
809   else
810   {
811     switch (de->details.exit_destination.af)
812     {
813     case AF_INET:
814       GNUNET_MESH_peer_request_connect_by_type (ts->tunnel,
815                                                 GNUNET_APPLICATION_TYPE_IPV4_GATEWAY);
816       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
817                   "Creating tunnel to exit peer for %s\n",
818                   "IPv4");
819      break;
820     case AF_INET6:
821       GNUNET_MESH_peer_request_connect_by_type (ts->tunnel,
822                                                 GNUNET_APPLICATION_TYPE_IPV6_GATEWAY);
823       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
824                   "Creating tunnel to exit peer for %s\n",
825                   "IPv6");
826       break;
827     default:
828       GNUNET_assert (0);
829       break;
830     }
831   }  
832   return ts;
833 }
834
835
836 /**
837  * We have too many active tunnels.  Clean up the oldest tunnel.
838  *
839  * @param except tunnel that must NOT be cleaned up, even if it is the oldest
840  */
841 static void
842 expire_tunnel (struct TunnelState *except)
843 {
844   struct TunnelState *ts;
845
846   ts = GNUNET_CONTAINER_heap_peek (tunnel_heap);
847   if (except == ts)
848     return; /* can't do this */
849   free_tunnel_state (ts);
850 }
851
852
853 /**
854  * Route a packet via mesh to the given destination.  
855  *
856  * @param destination description of the destination
857  * @param af address family on this end (AF_INET or AF_INET6)
858  * @param protocol IPPROTO_TCP or IPPROTO_UDP
859  * @param source_ip source IP used by the sender (struct in_addr or struct in6_addr)
860  * @param destination_ip destination IP used by the sender (struct in_addr or struct in6_addr)
861  * @param payload payload of the packet after the IP header
862  * @param payload_length number of bytes in payload
863  */
864 static void
865 route_packet (struct DestinationEntry *destination,
866               int af,
867               uint8_t protocol,
868               const void *source_ip,
869               const void *destination_ip,
870               const void *payload,
871               size_t payload_length)
872 {
873   GNUNET_HashCode key;
874   struct TunnelState *ts;
875   struct TunnelMessageQueueEntry *tnq;
876   size_t alen;
877   size_t mlen;
878   int is_new;
879   const struct GNUNET_TUN_UdpHeader *udp;
880   const struct GNUNET_TUN_TcpHeader *tcp;
881   uint16_t spt;
882   uint16_t dpt;
883
884   switch (protocol)
885   {
886   case IPPROTO_UDP:
887     {
888       if (payload_length < sizeof (struct GNUNET_TUN_UdpHeader))
889       {
890         /* blame kernel? */
891         GNUNET_break (0);
892         return;
893       }
894       udp = payload;
895       spt = ntohs (udp->spt);
896       dpt = ntohs (udp->dpt);
897       get_tunnel_key_from_ips (af,
898                                IPPROTO_UDP,
899                                source_ip,
900                                spt,
901                                destination_ip,
902                                dpt,
903                                &key);
904     }
905     break;
906   case IPPROTO_TCP:
907     {
908       if (payload_length < sizeof (struct GNUNET_TUN_TcpHeader))
909       {
910         /* blame kernel? */
911         GNUNET_break (0);
912         return;
913       }
914       tcp = payload;
915       spt = ntohs (tcp->spt);
916       dpt = ntohs (tcp->dpt);
917       get_tunnel_key_from_ips (af,
918                                IPPROTO_TCP,
919                                source_ip,
920                                spt,
921                                destination_ip,
922                                dpt,
923                                &key);
924     }
925     break;
926   default:
927     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
928                 _("Protocol %u not supported, dropping\n"),
929                 (unsigned int) protocol);
930     return;
931   }
932   if (! destination->is_service)
933   {  
934     switch (destination->details.exit_destination.af)
935     {
936     case AF_INET:
937       alen = sizeof (struct in_addr);
938      break;
939     case AF_INET6:
940       alen = sizeof (struct in6_addr);
941       break;
942     default:
943       alen = 0;
944       GNUNET_assert (0);
945     }
946
947     {
948       char sbuf[INET6_ADDRSTRLEN];
949       char dbuf[INET6_ADDRSTRLEN];
950       char xbuf[INET6_ADDRSTRLEN];
951       
952       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
953                   "Routing %s packet from %s:%u -> %s:%u to destination %s:%u\n",
954                   (protocol == IPPROTO_TCP) ? "TCP" : "UDP",
955                   inet_ntop (af, source_ip, sbuf, sizeof (sbuf)),
956                   spt,
957                   inet_ntop (af, destination_ip, dbuf, sizeof (dbuf)),
958                   dpt,
959                   inet_ntop (destination->details.exit_destination.af,
960                              &destination->details.exit_destination.ip,
961                              xbuf, sizeof (xbuf)),
962                   dpt);
963     }
964   }
965   else
966   {
967     /* make compiler happy */
968     alen = 0;
969     {
970       char sbuf[INET6_ADDRSTRLEN];
971       char dbuf[INET6_ADDRSTRLEN];
972       
973       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
974                   "Routing %s packet from %s:%u -> %s:%u to service %s at peer %s\n",
975                   (protocol == IPPROTO_TCP) ? "TCP" : "UDP",
976                   inet_ntop (af, source_ip, sbuf, sizeof (sbuf)),
977                   spt,
978                   inet_ntop (af, destination_ip, dbuf, sizeof (dbuf)),
979                   dpt,
980                   GNUNET_h2s (&destination->details.service_destination.service_descriptor),
981                   GNUNET_i2s (&destination->details.service_destination.target));
982     }
983
984   }
985
986   /* see if we have an existing tunnel for this destination */
987   ts = GNUNET_CONTAINER_multihashmap_get (tunnel_map,
988                                           &key);
989   if (NULL == ts)
990   {
991     /* need to either use the existing tunnel from the destination (if still
992        available) or create a fresh one */
993     is_new = GNUNET_YES;
994     if (NULL == destination->ts)
995       ts = create_tunnel_to_destination (destination, NULL, 0);
996     else
997       ts = destination->ts;
998     if (NULL == ts)
999       return;
1000     destination->ts = NULL;
1001     ts->destination_container = NULL; /* no longer 'contained' */
1002     /* now bind existing "unbound" tunnel to our IP/port tuple */
1003     ts->protocol = protocol;
1004     ts->af = af; 
1005     if (af == AF_INET)
1006     {
1007       ts->source_ip.v4 = * (const struct in_addr *) source_ip;
1008       ts->destination_ip.v4 = * (const struct in_addr *) destination_ip;
1009     }
1010     else
1011     {
1012       ts->source_ip.v6 = * (const struct in6_addr *) source_ip;
1013       ts->destination_ip.v6 = * (const struct in6_addr *) destination_ip;
1014     }
1015     ts->source_port = spt;
1016     ts->destination_port = dpt;
1017     ts->heap_node = GNUNET_CONTAINER_heap_insert (tunnel_heap,
1018                                                   ts,
1019                                                   GNUNET_TIME_absolute_get ().abs_value);
1020     GNUNET_assert (GNUNET_YES ==
1021                    GNUNET_CONTAINER_multihashmap_put (tunnel_map,
1022                                                       &key,
1023                                                       ts,
1024                                                       GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); 
1025     GNUNET_STATISTICS_update (stats,
1026                               gettext_noop ("# Active tunnels"),
1027                               1, GNUNET_NO);
1028     while (GNUNET_CONTAINER_multihashmap_size (tunnel_map) > max_tunnel_mappings)
1029       expire_tunnel (ts);
1030   }
1031   else
1032   {
1033     is_new = GNUNET_NO;
1034     GNUNET_CONTAINER_heap_update_cost (tunnel_heap, 
1035                                        ts->heap_node,
1036                                        GNUNET_TIME_absolute_get ().abs_value);
1037   }
1038   GNUNET_assert (NULL != ts->tunnel);
1039   
1040   /* send via tunnel */
1041   switch (protocol)
1042   {
1043   case IPPROTO_UDP:
1044     if (destination->is_service)
1045     {
1046       struct GNUNET_EXIT_UdpServiceMessage *usm;
1047
1048       mlen = sizeof (struct GNUNET_EXIT_UdpServiceMessage) + 
1049         payload_length - sizeof (struct GNUNET_TUN_UdpHeader);
1050       if (mlen >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1051       {
1052         GNUNET_break (0);
1053         return;
1054       }
1055       tnq = GNUNET_malloc (sizeof (struct TunnelMessageQueueEntry) + mlen);
1056       tnq->len = mlen;
1057       tnq->msg = &tnq[1];
1058       usm = (struct GNUNET_EXIT_UdpServiceMessage *) &tnq[1];
1059       usm->header.size = htons ((uint16_t) mlen);
1060       usm->header.type = htons (GNUNET_MESSAGE_TYPE_VPN_UDP_TO_SERVICE);
1061       /* if the source port is below 32000, we assume it has a special
1062          meaning; if not, we pick a random port (this is a heuristic) */
1063       usm->source_port = (ntohs (udp->spt) < 32000) ? udp->spt : 0;
1064       usm->destination_port = udp->dpt;
1065       usm->service_descriptor = destination->details.service_destination.service_descriptor;
1066       memcpy (&usm[1],
1067               &udp[1],
1068               payload_length - sizeof (struct GNUNET_TUN_UdpHeader));
1069     }
1070     else
1071     {
1072       struct GNUNET_EXIT_UdpInternetMessage *uim;
1073       struct in_addr *ip4dst;
1074       struct in6_addr *ip6dst;
1075       void *payload;
1076
1077       mlen = sizeof (struct GNUNET_EXIT_UdpInternetMessage) + 
1078         alen + payload_length - sizeof (struct GNUNET_TUN_UdpHeader);
1079       if (mlen >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1080       {
1081         GNUNET_break (0);
1082         return;
1083       }
1084       tnq = GNUNET_malloc (sizeof (struct TunnelMessageQueueEntry) + 
1085                            mlen);
1086       tnq->len = mlen;
1087       tnq->msg = &tnq[1];
1088       uim = (struct GNUNET_EXIT_UdpInternetMessage *) &tnq[1];
1089       uim->header.size = htons ((uint16_t) mlen);
1090       uim->header.type = htons (GNUNET_MESSAGE_TYPE_VPN_UDP_TO_INTERNET); 
1091       uim->af = htonl (destination->details.exit_destination.af);
1092       uim->source_port = (ntohs (udp->spt) < 32000) ? udp->spt : 0;
1093       uim->destination_port = udp->dpt;
1094       switch (destination->details.exit_destination.af)
1095       {
1096       case AF_INET:
1097         ip4dst = (struct in_addr *) &uim[1];
1098         *ip4dst = destination->details.exit_destination.ip.v4;
1099         payload = &ip4dst[1];
1100         break;
1101       case AF_INET6:
1102         ip6dst = (struct in6_addr *) &uim[1];
1103         *ip6dst = destination->details.exit_destination.ip.v6;
1104         payload = &ip6dst[1];
1105         break;
1106       default:
1107         GNUNET_assert (0);
1108       }
1109       memcpy (payload,
1110               &udp[1],
1111               payload_length - sizeof (struct GNUNET_TUN_UdpHeader));
1112     }
1113     break;
1114   case IPPROTO_TCP:
1115     if (is_new)
1116     {
1117       if (destination->is_service)
1118       {
1119         struct GNUNET_EXIT_TcpServiceStartMessage *tsm;
1120
1121         mlen = sizeof (struct GNUNET_EXIT_TcpServiceStartMessage) + 
1122           payload_length - sizeof (struct GNUNET_TUN_TcpHeader);
1123         if (mlen >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1124         {
1125           GNUNET_break (0);
1126           return;
1127         }
1128         tnq = GNUNET_malloc (sizeof (struct TunnelMessageQueueEntry) + mlen);
1129         tnq->len = mlen;
1130         tnq->msg = &tnq[1];
1131         tsm = (struct  GNUNET_EXIT_TcpServiceStartMessage *) &tnq[1];
1132         tsm->header.size = htons ((uint16_t) mlen);
1133         tsm->header.type = htons (GNUNET_MESSAGE_TYPE_VPN_TCP_TO_SERVICE_START);
1134         tsm->reserved = htonl (0);
1135         tsm->service_descriptor = destination->details.service_destination.service_descriptor;
1136         tsm->tcp_header = *tcp;
1137         memcpy (&tsm[1],
1138                 &tcp[1],
1139                 payload_length - sizeof (struct GNUNET_TUN_TcpHeader));
1140       }
1141       else
1142       {
1143         struct GNUNET_EXIT_TcpInternetStartMessage *tim;
1144         struct in_addr *ip4dst;
1145         struct in6_addr *ip6dst;
1146         void *payload;
1147
1148         mlen = sizeof (struct GNUNET_EXIT_TcpInternetStartMessage) + 
1149           alen + payload_length - sizeof (struct GNUNET_TUN_TcpHeader);
1150         if (mlen >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1151         {
1152           GNUNET_break (0);
1153           return;
1154         }
1155         tnq = GNUNET_malloc (sizeof (struct TunnelMessageQueueEntry) + mlen);
1156         tnq->len = mlen;
1157         tnq->msg = &tnq[1];
1158         tim = (struct  GNUNET_EXIT_TcpInternetStartMessage *) &tnq[1];
1159         tim->header.size = htons ((uint16_t) mlen);
1160         tim->header.type = htons (GNUNET_MESSAGE_TYPE_VPN_TCP_TO_INTERNET_START);
1161         tim->af = htonl (destination->details.exit_destination.af);     
1162         tim->tcp_header = *tcp;
1163         switch (destination->details.exit_destination.af)
1164         {
1165         case AF_INET:
1166           ip4dst = (struct in_addr *) &tim[1];
1167           *ip4dst = destination->details.exit_destination.ip.v4;
1168           payload = &ip4dst[1];
1169           break;
1170         case AF_INET6:
1171           ip6dst = (struct in6_addr *) &tim[1];
1172           *ip6dst = destination->details.exit_destination.ip.v6;
1173           payload = &ip6dst[1];
1174           break;
1175         default:
1176           GNUNET_assert (0);
1177         }
1178         memcpy (payload,
1179                 &tcp[1],
1180                 payload_length - sizeof (struct GNUNET_TUN_TcpHeader));
1181       }
1182     }
1183     else
1184     {
1185       struct GNUNET_EXIT_TcpDataMessage *tdm;
1186
1187       mlen = sizeof (struct GNUNET_EXIT_TcpDataMessage) + 
1188         payload_length - sizeof (struct GNUNET_TUN_TcpHeader);
1189       if (mlen >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1190       {
1191         GNUNET_break (0);
1192         return;
1193       }
1194       tnq = GNUNET_malloc (sizeof (struct TunnelMessageQueueEntry) + mlen);
1195       tnq->len = mlen;
1196       tnq->msg = &tnq[1];
1197       tdm = (struct  GNUNET_EXIT_TcpDataMessage *) &tnq[1];
1198       tdm->header.size = htons ((uint16_t) mlen);
1199       tdm->header.type = htons (GNUNET_MESSAGE_TYPE_VPN_TCP_DATA_TO_EXIT);
1200       tdm->reserved = htonl (0);
1201       tdm->tcp_header = *tcp;
1202       memcpy (&tdm[1],
1203               &tcp[1],
1204               payload_length - sizeof (struct GNUNET_TUN_TcpHeader));
1205      }
1206     break;
1207   default:
1208     /* not supported above, how can we get here !? */
1209     GNUNET_assert (0);
1210     break;
1211   }
1212   send_to_tunnel (tnq, ts);
1213 }
1214
1215
1216 /**
1217  * Receive packets from the helper-process (someone send to the local
1218  * virtual tunnel interface).  Find the destination mapping, and if it
1219  * exists, identify the correct MESH tunnel (or possibly create it)
1220  * and forward the packet.
1221  *
1222  * @param cls closure, NULL
1223  * @param client NULL
1224  * @param message message we got from the client (VPN tunnel interface)
1225  */
1226 static void
1227 message_token (void *cls GNUNET_UNUSED, void *client GNUNET_UNUSED,
1228                const struct GNUNET_MessageHeader *message)
1229 {
1230   const struct GNUNET_TUN_Layer2PacketHeader *tun;
1231   size_t mlen;
1232   GNUNET_HashCode key;
1233   struct DestinationEntry *de;
1234
1235   GNUNET_STATISTICS_update (stats,
1236                             gettext_noop ("# Packets received from TUN interface"),
1237                             1, GNUNET_NO);
1238   mlen = ntohs (message->size);
1239   if ( (ntohs (message->type) != GNUNET_MESSAGE_TYPE_VPN_HELPER) ||
1240        (mlen < sizeof (struct GNUNET_MessageHeader) + sizeof (struct GNUNET_TUN_Layer2PacketHeader)) )
1241   {
1242     GNUNET_break (0);
1243     return;
1244   }
1245   tun = (const struct GNUNET_TUN_Layer2PacketHeader *) &message[1];
1246   mlen -= (sizeof (struct GNUNET_MessageHeader) + sizeof (struct GNUNET_TUN_Layer2PacketHeader));
1247   switch (ntohs (tun->proto))
1248   {
1249   case ETH_P_IPV6:
1250     {
1251       const struct GNUNET_TUN_IPv6Header *pkt6;
1252       
1253       if (mlen < sizeof (struct GNUNET_TUN_IPv6Header))
1254       {
1255         /* blame kernel */
1256         GNUNET_break (0);
1257         return;
1258       }
1259       pkt6 = (const struct GNUNET_TUN_IPv6Header *) &tun[1];
1260       get_destination_key_from_ip (AF_INET6,
1261                                    &pkt6->destination_address,
1262                                    &key);
1263       de = GNUNET_CONTAINER_multihashmap_get (destination_map, &key);
1264       /* FIXME: do we need to guard against hash collision? 
1265          (if so, we need to also store the local destination IP in the
1266          destination entry and then compare here; however, the risk
1267          of collision seems minimal AND the impact is unlikely to be
1268          super-problematic as well... */
1269       if (NULL == de)
1270       {
1271         char buf[INET6_ADDRSTRLEN];
1272         
1273         GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1274                     _("Packet received for unmapped destination `%s' (dropping it)\n"),
1275                     inet_ntop (AF_INET6,
1276                                &pkt6->destination_address,
1277                                buf,
1278                                sizeof (buf)));
1279         return;
1280       }
1281       route_packet (de,
1282                     AF_INET6,
1283                     pkt6->next_header,
1284                     &pkt6->source_address,                  
1285                     &pkt6->destination_address,             
1286                     &pkt6[1],
1287                     mlen - sizeof (struct GNUNET_TUN_IPv6Header));
1288     }
1289     break;
1290   case ETH_P_IPV4:
1291     {
1292       struct GNUNET_TUN_IPv4Header *pkt4;
1293
1294       if (mlen < sizeof (struct GNUNET_TUN_IPv4Header))
1295       {
1296         /* blame kernel */
1297         GNUNET_break (0);
1298         return;
1299       }
1300       pkt4 = (struct GNUNET_TUN_IPv4Header *) &tun[1];
1301       get_destination_key_from_ip (AF_INET,
1302                                    &pkt4->destination_address,
1303                                    &key);
1304       de = GNUNET_CONTAINER_multihashmap_get (destination_map, &key);
1305       /* FIXME: do we need to guard against hash collision? 
1306          (if so, we need to also store the local destination IP in the
1307          destination entry and then compare here; however, the risk
1308          of collision seems minimal AND the impact is unlikely to be
1309          super-problematic as well... */
1310       if (NULL == de)
1311       {
1312         char buf[INET_ADDRSTRLEN];
1313         
1314         GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1315                     _("Packet received for unmapped destination `%s' (dropping it)\n"),
1316                     inet_ntop (AF_INET,
1317                                &pkt4->destination_address,
1318                                buf,
1319                                sizeof (buf)));
1320         return;
1321       }
1322       if (pkt4->header_length * 4 != sizeof (struct GNUNET_TUN_IPv4Header))
1323       {
1324         GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1325                     _("Received IPv4 packet with options (dropping it)\n"));                
1326         return;
1327       }
1328       route_packet (de,
1329                     AF_INET,
1330                     pkt4->protocol,
1331                     &pkt4->source_address,                  
1332                     &pkt4->destination_address,             
1333                     &pkt4[1],
1334                     mlen - sizeof (struct GNUNET_TUN_IPv4Header));
1335     }
1336     break;
1337   default:
1338     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1339                 _("Received packet of unknown protocol %d from TUN (dropping it)\n"),
1340                 (unsigned int) ntohs (tun->proto));
1341     break;
1342   }
1343 }
1344
1345
1346 /**
1347  * We got a UDP packet back from the MESH tunnel.  Pass it on to the
1348  * local virtual interface via the helper.
1349  *
1350  * @param cls closure, NULL
1351  * @param tunnel connection to the other end
1352  * @param tunnel_ctx pointer to our 'struct TunnelState *'
1353  * @param sender who sent the message
1354  * @param message the actual message
1355  * @param atsi performance data for the connection
1356  * @return GNUNET_OK to keep the connection open,
1357  *         GNUNET_SYSERR to close it (signal serious error)
1358  */ 
1359 static int
1360 receive_udp_back (void *cls GNUNET_UNUSED, struct GNUNET_MESH_Tunnel *tunnel,
1361                   void **tunnel_ctx, const struct GNUNET_PeerIdentity *sender,
1362                   const struct GNUNET_MessageHeader *message,
1363                   const struct GNUNET_ATS_Information *atsi GNUNET_UNUSED)
1364 {
1365   struct TunnelState *ts = *tunnel_ctx;
1366   const struct GNUNET_EXIT_UdpReplyMessage *reply;
1367   size_t mlen;
1368
1369   GNUNET_STATISTICS_update (stats,
1370                             gettext_noop ("# UDP packets received from mesh"),
1371                             1, GNUNET_NO);
1372   mlen = ntohs (message->size);
1373   if (mlen < sizeof (struct GNUNET_EXIT_UdpReplyMessage))
1374   {
1375     GNUNET_break_op (0);
1376     return GNUNET_SYSERR;
1377   }
1378   if (NULL == ts->heap_node)
1379   {
1380     GNUNET_break_op (0);
1381     return GNUNET_SYSERR;
1382   }
1383   if (AF_UNSPEC == ts->af)
1384   {
1385     GNUNET_break_op (0);
1386     return GNUNET_SYSERR;
1387   }
1388   reply = (const struct GNUNET_EXIT_UdpReplyMessage *) message;
1389   mlen -= sizeof (struct GNUNET_EXIT_UdpReplyMessage);
1390   {
1391     char sbuf[INET6_ADDRSTRLEN];
1392     char dbuf[INET6_ADDRSTRLEN];
1393     
1394     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1395                 "Received UDP reply from mesh, sending %u bytes from %s:%u -> %s:%u via TUN\n",
1396                 (unsigned int) mlen,
1397                 inet_ntop (ts->af, &ts->destination_ip, sbuf, sizeof (sbuf)),
1398                 ts->destination_port,
1399                 inet_ntop (ts->af, &ts->source_ip, dbuf, sizeof (dbuf)),
1400                 ts->source_port);
1401   }
1402   switch (ts->af)
1403   {
1404   case AF_INET:
1405     {
1406       size_t size = sizeof (struct GNUNET_TUN_IPv4Header) 
1407         + sizeof (struct GNUNET_TUN_UdpHeader) 
1408         + sizeof (struct GNUNET_MessageHeader) +
1409         sizeof (struct GNUNET_TUN_Layer2PacketHeader) +
1410         mlen;
1411       {
1412         char buf[size];
1413         struct GNUNET_MessageHeader *msg = (struct GNUNET_MessageHeader *) buf;
1414         struct GNUNET_TUN_Layer2PacketHeader *tun = (struct GNUNET_TUN_Layer2PacketHeader*) &msg[1];
1415         struct GNUNET_TUN_IPv4Header *ipv4 = (struct GNUNET_TUN_IPv4Header *) &tun[1];
1416         struct GNUNET_TUN_UdpHeader *udp = (struct GNUNET_TUN_UdpHeader *) &ipv4[1];
1417         msg->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
1418         msg->size = htons (size);
1419         tun->flags = htons (0);
1420         tun->proto = htons (ETH_P_IPV4);
1421         GNUNET_TUN_initialize_ipv4_header (ipv4,
1422                                            IPPROTO_UDP,
1423                                            sizeof (struct GNUNET_TUN_UdpHeader) + mlen,
1424                                            &ts->destination_ip.v4,
1425                                            &ts->source_ip.v4);
1426         if (0 == ntohs (reply->source_port))
1427           udp->spt = htons (ts->destination_port);
1428         else
1429           udp->spt = reply->source_port;
1430         if (0 == ntohs (reply->destination_port))
1431           udp->dpt = htons (ts->source_port);
1432         else
1433           udp->dpt = reply->destination_port;
1434         udp->len = htons (mlen + sizeof (struct GNUNET_TUN_UdpHeader));
1435         GNUNET_TUN_calculate_udp4_checksum (ipv4,
1436                                             udp,
1437                                             &reply[1],
1438                                             mlen);
1439         memcpy (&udp[1],
1440                 &reply[1],
1441                 mlen);
1442         (void) GNUNET_HELPER_send (helper_handle,
1443                                    msg,
1444                                    GNUNET_YES,
1445                                    NULL, NULL);
1446       }
1447     }
1448     break;
1449   case AF_INET6:
1450     {
1451       size_t size = sizeof (struct GNUNET_TUN_IPv6Header) 
1452         + sizeof (struct GNUNET_TUN_UdpHeader) 
1453         + sizeof (struct GNUNET_MessageHeader) +
1454         sizeof (struct GNUNET_TUN_Layer2PacketHeader) +
1455         mlen;
1456       {
1457         char buf[size];
1458         struct GNUNET_MessageHeader *msg = (struct GNUNET_MessageHeader *) buf;
1459         struct GNUNET_TUN_Layer2PacketHeader *tun = (struct GNUNET_TUN_Layer2PacketHeader*) &msg[1];
1460         struct GNUNET_TUN_IPv6Header *ipv6 = (struct GNUNET_TUN_IPv6Header *) &tun[1];
1461         struct GNUNET_TUN_UdpHeader *udp = (struct GNUNET_TUN_UdpHeader *) &ipv6[1];
1462         msg->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
1463         msg->size = htons (size);
1464         tun->flags = htons (0);
1465         tun->proto = htons (ETH_P_IPV6);
1466         GNUNET_TUN_initialize_ipv6_header (ipv6,
1467                                            IPPROTO_UDP,
1468                                            sizeof (struct GNUNET_TUN_UdpHeader) + mlen,
1469                                            &ts->destination_ip.v6,
1470                                            &ts->source_ip.v6);
1471         if (0 == ntohs (reply->source_port))
1472           udp->spt = htons (ts->destination_port);
1473         else
1474           udp->spt = reply->source_port;
1475         if (0 == ntohs (reply->destination_port))
1476           udp->dpt = htons (ts->source_port);
1477         else
1478           udp->dpt = reply->destination_port;
1479         udp->len = htons (mlen + sizeof (struct GNUNET_TUN_UdpHeader));
1480         GNUNET_TUN_calculate_udp6_checksum (ipv6,
1481                                             udp,
1482                                             &reply[1], mlen);
1483         memcpy (&udp[1],
1484                 &reply[1],
1485                 mlen);
1486         (void) GNUNET_HELPER_send (helper_handle,
1487                                    msg,
1488                                    GNUNET_YES,
1489                                    NULL, NULL);
1490       }
1491     }
1492     break;
1493   default:
1494     GNUNET_assert (0);
1495   }
1496   GNUNET_CONTAINER_heap_update_cost (tunnel_heap, 
1497                                      ts->heap_node,
1498                                      GNUNET_TIME_absolute_get ().abs_value);
1499   return GNUNET_OK;
1500 }
1501
1502
1503 /**
1504  * We got a TCP packet back from the MESH tunnel.  Pass it on to the
1505  * local virtual interface via the helper.
1506  *
1507  * @param cls closure, NULL
1508  * @param tunnel connection to the other end
1509  * @param tunnel_ctx pointer to our 'struct TunnelState *'
1510  * @param sender who sent the message
1511  * @param message the actual message
1512  * @param atsi performance data for the connection
1513  * @return GNUNET_OK to keep the connection open,
1514  *         GNUNET_SYSERR to close it (signal serious error)
1515  */ 
1516 static int
1517 receive_tcp_back (void *cls GNUNET_UNUSED, struct GNUNET_MESH_Tunnel *tunnel,
1518                   void **tunnel_ctx,
1519                   const struct GNUNET_PeerIdentity *sender GNUNET_UNUSED,
1520                   const struct GNUNET_MessageHeader *message,
1521                   const struct GNUNET_ATS_Information *atsi GNUNET_UNUSED)
1522 {
1523   struct TunnelState *ts = *tunnel_ctx;
1524   const struct GNUNET_EXIT_TcpDataMessage *data;
1525   size_t mlen;
1526
1527   GNUNET_STATISTICS_update (stats,
1528                             gettext_noop ("# TCP packets received from mesh"),
1529                             1, GNUNET_NO);
1530   mlen = ntohs (message->size);
1531   if (mlen < sizeof (struct GNUNET_EXIT_TcpDataMessage))
1532   {
1533     GNUNET_break_op (0);
1534     return GNUNET_SYSERR;
1535   }
1536   if (NULL == ts->heap_node)
1537   {
1538     GNUNET_break_op (0);
1539     return GNUNET_SYSERR;
1540   }
1541   data = (const struct GNUNET_EXIT_TcpDataMessage *) message;
1542   mlen -= sizeof (struct GNUNET_EXIT_TcpDataMessage);
1543   {
1544     char sbuf[INET6_ADDRSTRLEN];
1545     char dbuf[INET6_ADDRSTRLEN];
1546     
1547     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1548                 "Received TCP reply from mesh, sending %u bytes from %s:%u -> %s:%u via TUN\n",
1549                 (unsigned int) mlen,
1550                 inet_ntop (ts->af, &ts->destination_ip, sbuf, sizeof (sbuf)),
1551                 ts->destination_port,
1552                 inet_ntop (ts->af, &ts->source_ip, dbuf, sizeof (dbuf)),
1553                 ts->source_port);
1554   }
1555   switch (ts->af)
1556   {
1557   case AF_INET:
1558     {
1559       size_t size = sizeof (struct GNUNET_TUN_IPv4Header) 
1560         + sizeof (struct GNUNET_TUN_TcpHeader) 
1561         + sizeof (struct GNUNET_MessageHeader) +
1562         sizeof (struct GNUNET_TUN_Layer2PacketHeader) +
1563         mlen;
1564       {
1565         char buf[size];
1566         struct GNUNET_MessageHeader *msg = (struct GNUNET_MessageHeader *) buf;
1567         struct GNUNET_TUN_Layer2PacketHeader *tun = (struct GNUNET_TUN_Layer2PacketHeader*) &msg[1];
1568         struct GNUNET_TUN_IPv4Header *ipv4 = (struct GNUNET_TUN_IPv4Header *) &tun[1];
1569         struct GNUNET_TUN_TcpHeader *tcp = (struct GNUNET_TUN_TcpHeader *) &ipv4[1];
1570         msg->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
1571         msg->size = htons (size);
1572         tun->flags = htons (0);
1573         tun->proto = htons (ETH_P_IPV4);
1574         GNUNET_TUN_initialize_ipv4_header (ipv4,
1575                                            IPPROTO_TCP,
1576                                            sizeof (struct GNUNET_TUN_TcpHeader) + mlen,
1577                                            &ts->destination_ip.v4,
1578                                            &ts->source_ip.v4);
1579         *tcp = data->tcp_header;
1580         tcp->spt = htons (ts->destination_port);
1581         tcp->dpt = htons (ts->source_port);
1582         GNUNET_TUN_calculate_tcp4_checksum (ipv4,
1583                                             tcp,
1584                                             &data[1],
1585                                             mlen);
1586         memcpy (&tcp[1],
1587                 &data[1],
1588                 mlen);
1589         (void) GNUNET_HELPER_send (helper_handle,
1590                                    msg,
1591                                    GNUNET_YES,
1592                                    NULL, NULL);
1593       }
1594     }
1595     break;
1596   case AF_INET6:
1597     {
1598       size_t size = sizeof (struct GNUNET_TUN_IPv6Header) 
1599         + sizeof (struct GNUNET_TUN_TcpHeader) 
1600         + sizeof (struct GNUNET_MessageHeader) +
1601         sizeof (struct GNUNET_TUN_Layer2PacketHeader) +
1602         mlen;
1603       {
1604         char buf[size];
1605         struct GNUNET_MessageHeader *msg = (struct GNUNET_MessageHeader *) buf;
1606         struct GNUNET_TUN_Layer2PacketHeader *tun = (struct GNUNET_TUN_Layer2PacketHeader*) &msg[1];
1607         struct GNUNET_TUN_IPv6Header *ipv6 = (struct GNUNET_TUN_IPv6Header *) &tun[1];
1608         struct GNUNET_TUN_TcpHeader *tcp = (struct GNUNET_TUN_TcpHeader *) &ipv6[1];
1609         msg->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
1610         msg->size = htons (size);
1611         tun->flags = htons (0);
1612         tun->proto = htons (ETH_P_IPV6);
1613         GNUNET_TUN_initialize_ipv6_header (ipv6,
1614                                            IPPROTO_TCP,
1615                                            sizeof (struct GNUNET_TUN_TcpHeader) + mlen,
1616                                            &ts->destination_ip.v6,
1617                                            &ts->source_ip.v6);
1618         tcp->spt = htons (ts->destination_port);
1619         tcp->dpt = htons (ts->source_port);
1620         GNUNET_TUN_calculate_tcp6_checksum (ipv6,
1621                                             tcp,
1622                                             &tcp[1],
1623                                             mlen);
1624         (void) GNUNET_HELPER_send (helper_handle,
1625                                    msg,
1626                                    GNUNET_YES,
1627                                    NULL, NULL);
1628       }
1629     }
1630     break;
1631   }
1632   GNUNET_CONTAINER_heap_update_cost (tunnel_heap, 
1633                                      ts->heap_node,
1634                                      GNUNET_TIME_absolute_get ().abs_value);
1635   return GNUNET_OK;
1636 }
1637
1638
1639 /**
1640  * Allocate an IPv4 address from the range of the tunnel
1641  * for a new redirection.
1642  *
1643  * @param v4 where to store the address
1644  * @return GNUNET_OK on success,
1645  *         GNUNET_SYSERR on error
1646  */
1647 static int
1648 allocate_v4_address (struct in_addr *v4)
1649 {
1650   const char *ipv4addr = vpn_argv[4];
1651   const char *ipv4mask = vpn_argv[5];
1652   struct in_addr addr;
1653   struct in_addr mask;
1654   struct in_addr rnd;
1655   GNUNET_HashCode key;
1656   unsigned int tries;
1657
1658   GNUNET_assert (1 == inet_pton (AF_INET, ipv4addr, &addr));
1659   GNUNET_assert (1 == inet_pton (AF_INET, ipv4mask, &mask));           
1660   /* Given 192.168.0.1/255.255.0.0, we want a mask 
1661      of '192.168.255.255', thus:  */
1662   mask.s_addr = addr.s_addr | ~mask.s_addr;  
1663   tries = 0;
1664   do
1665     {
1666       tries++;
1667       if (tries > 16)
1668       {
1669         GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1670                     _("Failed to find unallocated IPv4 address in VPN's range\n"));
1671         return GNUNET_SYSERR;
1672       }
1673       /* Pick random IPv4 address within the subnet, except 'addr' or 'mask' itself */
1674       rnd.s_addr = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, 
1675                                              UINT32_MAX);       
1676       v4->s_addr = (addr.s_addr | rnd.s_addr) & mask.s_addr;          
1677       get_destination_key_from_ip (AF_INET,
1678                                    v4,
1679                                    &key);
1680     }
1681   while ( (GNUNET_YES ==
1682            GNUNET_CONTAINER_multihashmap_contains (destination_map,
1683                                                    &key)) ||
1684           (v4->s_addr == addr.s_addr) ||
1685           (v4->s_addr == mask.s_addr) );
1686   return GNUNET_OK;
1687 }
1688
1689
1690 /**
1691  * Allocate an IPv6 address from the range of the tunnel
1692  * for a new redirection.
1693  *
1694  * @param v6 where to store the address
1695  * @return GNUNET_OK on success,
1696  *         GNUNET_SYSERR on error
1697  */
1698 static int
1699 allocate_v6_address (struct in6_addr *v6)
1700 {
1701   const char *ipv6addr = vpn_argv[2];
1702   struct in6_addr addr;
1703   struct in6_addr mask;
1704   struct in6_addr rnd;
1705   int i;
1706   GNUNET_HashCode key;
1707   unsigned int tries;
1708
1709   GNUNET_assert (1 == inet_pton (AF_INET6, ipv6addr, &addr));
1710   GNUNET_assert (ipv6prefix < 128);
1711   /* Given ABCD::/96, we want a mask of 'ABCD::FFFF:FFFF,
1712      thus: */
1713   mask = addr;
1714   for (i=127;i>=128-ipv6prefix;i--)
1715     mask.s6_addr[i / 8] |= (1 << (i % 8));
1716   
1717   /* Pick random IPv6 address within the subnet, except 'addr' or 'mask' itself */
1718   tries = 0;
1719   do
1720     {
1721       tries++;
1722       if (tries > 16)
1723         {
1724           GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1725                       _("Failed to find unallocated IPv6 address in VPN's range\n"));
1726           return GNUNET_SYSERR;
1727
1728         }
1729       for (i=0;i<16;i++)
1730         {
1731           rnd.s6_addr[i] = (unsigned char) GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, 
1732                                                                      256);
1733           v6->s6_addr[i]
1734             = (addr.s6_addr[i] | rnd.s6_addr[i]) & mask.s6_addr[i];
1735         }
1736       get_destination_key_from_ip (AF_INET6,
1737                                    v6,
1738                                    &key);
1739     }
1740   while ( (GNUNET_YES ==
1741            GNUNET_CONTAINER_multihashmap_contains (destination_map,
1742                                                    &key)) ||
1743           (0 == memcmp (v6,
1744                         &addr,
1745                         sizeof (struct in6_addr))) ||
1746           (0 == memcmp (v6,
1747                         &mask,
1748                         sizeof (struct in6_addr))) );
1749   return GNUNET_OK;
1750 }
1751
1752
1753 /**
1754  * Free resources occupied by a destination entry.
1755  *
1756  * @param de entry to free
1757  */
1758 static void
1759 free_destination_entry (struct DestinationEntry *de)
1760 {
1761   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1762               "Cleaning up destination entry\n");
1763   GNUNET_STATISTICS_update (stats,
1764                             gettext_noop ("# Active destinations"),
1765                             -1, GNUNET_NO);
1766   if (NULL != de->ts)
1767   {
1768     free_tunnel_state (de->ts);
1769     GNUNET_assert (NULL == de->ts);
1770   }
1771   if (NULL != de->heap_node)
1772   {
1773     GNUNET_CONTAINER_heap_remove_node (de->heap_node);
1774     de->heap_node = NULL;  
1775     GNUNET_assert (GNUNET_YES ==
1776                    GNUNET_CONTAINER_multihashmap_remove (destination_map,
1777                                                          &de->key,
1778                                                          de));
1779   }
1780   GNUNET_free (de);
1781 }
1782
1783
1784 /**
1785  * We have too many active destinations.  Clean up the oldest destination.
1786  *
1787  * @param except destination that must NOT be cleaned up, even if it is the oldest
1788  */
1789 static void 
1790 expire_destination (struct DestinationEntry *except)
1791 {
1792   struct DestinationEntry *de;
1793
1794   de = GNUNET_CONTAINER_heap_peek (destination_heap);
1795   if (except == de)
1796     return; /* can't do this */
1797   free_destination_entry (de);
1798 }
1799
1800
1801 /**
1802  * A client asks us to setup a redirection via some exit
1803  * node to a particular IP.  Setup the redirection and
1804  * give the client the allocated IP.
1805  *
1806  * @param cls unused
1807  * @param client requesting client
1808  * @param message redirection request (a 'struct RedirectToIpRequestMessage')
1809  */
1810 static void
1811 service_redirect_to_ip (void *cls GNUNET_UNUSED, struct GNUNET_SERVER_Client *client,
1812                         const struct GNUNET_MessageHeader *message)
1813 {
1814   size_t mlen;
1815   size_t alen;
1816   const struct RedirectToIpRequestMessage *msg;
1817   int addr_af;
1818   int result_af;
1819   struct in_addr v4;
1820   struct in6_addr v6;
1821   void *addr;
1822   struct DestinationEntry *de;
1823   GNUNET_HashCode key;
1824   
1825   /* validate and parse request */
1826   mlen = ntohs (message->size);
1827   if (mlen < sizeof (struct RedirectToIpRequestMessage))
1828   {
1829     GNUNET_break (0);
1830     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1831     return;
1832   }
1833   alen = mlen - sizeof (struct RedirectToIpRequestMessage);
1834   msg = (const struct RedirectToIpRequestMessage *) message;
1835   addr_af = (int) htonl (msg->addr_af);
1836   switch (addr_af)
1837   {
1838   case AF_INET:
1839     if (alen != sizeof (struct in_addr))
1840     {
1841       GNUNET_break (0);
1842       GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1843       return;      
1844     }
1845     break;
1846   case AF_INET6:
1847     if (alen != sizeof (struct in6_addr))
1848     {
1849       GNUNET_break (0);
1850       GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1851       return;      
1852     }
1853     break;
1854   default:
1855     GNUNET_break (0);
1856     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1857     return;      
1858   }
1859
1860   /* allocate response IP */
1861   addr = NULL;
1862   result_af = (int) htonl (msg->result_af);
1863   switch (result_af)
1864   {
1865   case AF_INET:
1866     if (GNUNET_OK !=
1867         allocate_v4_address (&v4))
1868       result_af = AF_UNSPEC;
1869     else
1870       addr = &v4;
1871     break;
1872   case AF_INET6:
1873     if (GNUNET_OK !=
1874         allocate_v6_address (&v6))
1875       result_af = AF_UNSPEC;
1876     else
1877       addr = &v6;
1878     break;
1879   case AF_UNSPEC:
1880     if (GNUNET_OK ==
1881         allocate_v4_address (&v4))
1882     {
1883       addr = &v4;
1884       result_af = AF_INET;
1885     }
1886     else if (GNUNET_OK ==
1887         allocate_v6_address (&v6))
1888     {
1889       addr = &v6;
1890       result_af = AF_INET6;
1891     }
1892     break;
1893   default:
1894     GNUNET_break (0);
1895     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1896     return;      
1897   }
1898   if ( (result_af == AF_UNSPEC) ||
1899        (GNUNET_NO == ntohl (msg->nac)) )
1900   {
1901     /* send reply "instantly" */
1902     send_client_reply (client,
1903                        msg->request_id,
1904                        result_af,
1905                        addr);
1906   }
1907   if (result_af == AF_UNSPEC)
1908   {
1909     /* failure, we're done */
1910     GNUNET_SERVER_receive_done (client, GNUNET_OK);
1911     return;
1912   }
1913
1914   {
1915     char sbuf[INET6_ADDRSTRLEN];
1916     char dbuf[INET6_ADDRSTRLEN];
1917     
1918     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1919                 "Allocated address %s for redirection via exit to %s\n",
1920                 inet_ntop (result_af, addr, sbuf, sizeof (sbuf)),
1921                 inet_ntop (addr_af,
1922                            &msg[1], dbuf, sizeof (dbuf)));
1923   }
1924   
1925   /* setup destination record */
1926   de = GNUNET_malloc (sizeof (struct DestinationEntry));
1927   de->is_service = GNUNET_NO;
1928   de->details.exit_destination.af = addr_af;
1929   memcpy (&de->details.exit_destination.ip,
1930           &msg[1],
1931           alen);
1932   get_destination_key_from_ip (result_af,
1933                                addr,
1934                                &key);
1935   de->key = key;
1936   GNUNET_assert (GNUNET_OK ==
1937                  GNUNET_CONTAINER_multihashmap_put (destination_map,
1938                                                     &key,
1939                                                     de,
1940                                                     GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE));
1941   de->heap_node = GNUNET_CONTAINER_heap_insert (destination_heap,
1942                                                 de,
1943                                                 GNUNET_TIME_absolute_ntoh (msg->expiration_time).abs_value);
1944   GNUNET_STATISTICS_update (stats,
1945                             gettext_noop ("# Active destinations"),
1946                             1, GNUNET_NO);
1947   while (GNUNET_CONTAINER_multihashmap_size (destination_map) > max_destination_mappings)
1948     expire_destination (de);
1949
1950   /* setup tunnel to destination */
1951   (void) create_tunnel_to_destination (de, 
1952                                        (GNUNET_NO == ntohl (msg->nac)) ? NULL : client,
1953                                        msg->request_id);
1954   /* we're done */
1955   GNUNET_SERVER_receive_done (client, GNUNET_OK);
1956 }
1957
1958
1959 /**
1960  * A client asks us to setup a redirection to a particular peer
1961  * offering a service.  Setup the redirection and give the client the
1962  * allocated IP.
1963  *
1964  * @param cls unused
1965  * @param client requesting client
1966  * @param message redirection request (a 'struct RedirectToPeerRequestMessage')
1967  */
1968 static void
1969 service_redirect_to_service (void *cls GNUNET_UNUSED, struct GNUNET_SERVER_Client *client,
1970                              const struct GNUNET_MessageHeader *message)
1971 {
1972   const struct RedirectToServiceRequestMessage *msg;
1973   int result_af;
1974   struct in_addr v4;
1975   struct in6_addr v6;
1976   void *addr;
1977   struct DestinationEntry *de;
1978   GNUNET_HashCode key;
1979   
1980   /*  parse request */
1981   msg = (const struct RedirectToServiceRequestMessage *) message;
1982
1983   /* allocate response IP */
1984   addr = NULL;
1985   result_af = (int) htonl (msg->result_af);
1986   switch (result_af)
1987   {
1988   case AF_INET:
1989     if (GNUNET_OK !=
1990         allocate_v4_address (&v4))
1991       result_af = AF_UNSPEC;
1992     else
1993       addr = &v4;
1994     break;
1995   case AF_INET6:
1996     if (GNUNET_OK !=
1997         allocate_v6_address (&v6))
1998       result_af = AF_UNSPEC;
1999     else
2000       addr = &v6;
2001     break;
2002   case AF_UNSPEC:
2003     if (GNUNET_OK ==
2004         allocate_v4_address (&v4))
2005     {
2006       addr = &v4;
2007       result_af = AF_INET;
2008     }
2009     else if (GNUNET_OK ==
2010         allocate_v6_address (&v6))
2011     {
2012       addr = &v6;
2013       result_af = AF_INET6;
2014     }
2015     break;
2016   default:
2017     GNUNET_break (0);
2018     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2019     return;      
2020   }
2021   if ( (result_af == AF_UNSPEC) ||
2022        (GNUNET_NO == ntohl (msg->nac)) )
2023   {
2024     /* send reply "instantly" */
2025     send_client_reply (client,
2026                        msg->request_id,
2027                        result_af,
2028                        addr);
2029   }
2030   if (result_af == AF_UNSPEC)
2031   {
2032     /* failure, we're done */
2033     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2034                 _("Failed to allocate IP address for new destination\n"));
2035     GNUNET_SERVER_receive_done (client, GNUNET_OK);
2036     return;
2037   }
2038
2039   {
2040     char sbuf[INET6_ADDRSTRLEN];
2041     
2042     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2043                 "Allocated address %s for redirection to service %s on peer %s\n",
2044                 inet_ntop (result_af, addr, sbuf, sizeof (sbuf)),
2045                 GNUNET_h2s (&msg->service_descriptor),
2046                 GNUNET_i2s (&msg->target));
2047   }
2048   
2049   /* setup destination record */
2050   de = GNUNET_malloc (sizeof (struct DestinationEntry));
2051   de->is_service = GNUNET_YES;
2052   de->details.service_destination.service_descriptor = msg->service_descriptor;
2053   de->details.service_destination.target = msg->target;
2054   get_destination_key_from_ip (result_af,
2055                                addr,
2056                                &key);
2057   de->key = key;
2058   GNUNET_assert (GNUNET_OK ==
2059                  GNUNET_CONTAINER_multihashmap_put (destination_map,
2060                                                     &key,
2061                                                     de,
2062                                                     GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE));
2063   de->heap_node = GNUNET_CONTAINER_heap_insert (destination_heap,
2064                                                 de,
2065                                                 GNUNET_TIME_absolute_ntoh (msg->expiration_time).abs_value);
2066   while (GNUNET_CONTAINER_multihashmap_size (destination_map) > max_destination_mappings)
2067     expire_destination (de);
2068   (void) create_tunnel_to_destination (de,
2069                                        (GNUNET_NO == ntohl (msg->nac)) ? NULL : client,
2070                                        msg->request_id);
2071   /* we're done */
2072   GNUNET_SERVER_receive_done (client, GNUNET_OK);
2073 }
2074
2075
2076
2077 /**
2078  * Function called for inbound tunnels.  As we don't offer
2079  * any mesh services, this function should never be called.
2080  *
2081  * @param cls closure
2082  * @param tunnel new handle to the tunnel
2083  * @param initiator peer that started the tunnel
2084  * @param atsi performance information for the tunnel
2085  * @return initial tunnel context for the tunnel
2086  *         (can be NULL -- that's not an error)
2087  */ 
2088 static void *
2089 inbound_tunnel_cb (void *cls, struct GNUNET_MESH_Tunnel *tunnel,
2090                    const struct GNUNET_PeerIdentity *initiator,
2091                    const struct GNUNET_ATS_Information *atsi)
2092 {
2093   /* How can and why should anyone open an inbound tunnel to vpn? */
2094   GNUNET_break (0);
2095   return NULL;
2096 }
2097
2098
2099 /**
2100  * Function called whenever an inbound tunnel is destroyed.  Should clean up
2101  * any associated state.
2102  *
2103  * @param cls closure (set from GNUNET_MESH_connect)
2104  * @param tunnel connection to the other end (henceforth invalid)
2105  * @param tunnel_ctx place where local state associated
2106  *                   with the tunnel is stored (our 'struct TunnelState')
2107  */ 
2108 static void
2109 tunnel_cleaner (void *cls, const struct GNUNET_MESH_Tunnel *tunnel, void *tunnel_ctx)
2110 {
2111   struct TunnelState *ts = tunnel_ctx;
2112
2113   if (NULL == ts)
2114   {
2115     GNUNET_break (0);
2116     return;     
2117   }
2118   GNUNET_assert (ts->tunnel == tunnel);
2119   ts->tunnel = NULL;
2120   free_tunnel_state (ts);
2121 }
2122
2123
2124 /**
2125  * Free memory occupied by an entry in the destination map.
2126  *
2127  * @param cls unused
2128  * @param key unused
2129  * @param value a 'struct DestinationEntry *'
2130  * @return GNUNET_OK (continue to iterate)
2131  */
2132 static int
2133 cleanup_destination (void *cls,
2134                      const GNUNET_HashCode *key,
2135                      void *value)
2136 {
2137   struct DestinationEntry *de = value;
2138
2139   free_destination_entry (de);
2140   return GNUNET_OK;
2141 }
2142
2143
2144 /**
2145  * Free memory occupied by an entry in the tunnel map.
2146  *
2147  * @param cls unused
2148  * @param key unused
2149  * @param value a 'struct TunnelState *'
2150  * @return GNUNET_OK (continue to iterate)
2151  */
2152 static int
2153 cleanup_tunnel (void *cls,
2154                 const GNUNET_HashCode *key,
2155                 void *value)
2156 {
2157   struct TunnelState *ts = value;
2158
2159   free_tunnel_state (ts);
2160   return GNUNET_OK;
2161 }
2162
2163
2164 /**
2165  * Function scheduled as very last function, cleans up after us
2166  *
2167  * @param cls unused
2168  * @param tc unused
2169  */
2170 static void
2171 cleanup (void *cls GNUNET_UNUSED,
2172          const struct GNUNET_SCHEDULER_TaskContext *tc)
2173 {
2174   unsigned int i;
2175
2176   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2177               "VPN is shutting down\n");
2178   if (NULL != destination_map)
2179   {  
2180     GNUNET_CONTAINER_multihashmap_iterate (destination_map,
2181                                            &cleanup_destination,
2182                                            NULL);
2183     GNUNET_CONTAINER_multihashmap_destroy (destination_map);
2184     destination_map = NULL;
2185   }
2186   if (NULL != destination_heap)
2187   {
2188     GNUNET_CONTAINER_heap_destroy (destination_heap);
2189     destination_heap = NULL;
2190   }
2191   if (NULL != tunnel_map)
2192   {  
2193     GNUNET_CONTAINER_multihashmap_iterate (tunnel_map,
2194                                            &cleanup_tunnel,
2195                                            NULL);
2196     GNUNET_CONTAINER_multihashmap_destroy (tunnel_map);
2197     tunnel_map = NULL;
2198   }
2199   if (NULL != tunnel_heap)
2200   {
2201     GNUNET_CONTAINER_heap_destroy (tunnel_heap);
2202     tunnel_heap = NULL;
2203   }
2204   if (NULL != mesh_handle)
2205   {
2206     GNUNET_MESH_disconnect (mesh_handle);
2207     mesh_handle = NULL;
2208   }
2209   if (NULL != helper_handle)
2210     {
2211     GNUNET_HELPER_stop (helper_handle);
2212     helper_handle = NULL;
2213   }
2214   if (NULL != nc)
2215   {
2216     GNUNET_SERVER_notification_context_destroy (nc);
2217     nc = NULL;
2218   }
2219   if (stats != NULL)
2220   {
2221     GNUNET_STATISTICS_destroy (stats, GNUNET_YES);
2222     stats = NULL;
2223   }
2224   for (i=0;i<5;i++)
2225     GNUNET_free_non_null (vpn_argv[i]);
2226 }
2227
2228
2229 /**
2230  * A client disconnected, clean up all references to it.
2231  *
2232  * @param cls the client that disconnected
2233  * @param key unused
2234  * @param value a 'struct TunnelState *'
2235  * @return GNUNET_OK (continue to iterate)
2236  */
2237 static int
2238 cleanup_tunnel_client (void *cls,
2239                        const GNUNET_HashCode *key,
2240                        void *value)
2241 {
2242   struct GNUNET_SERVER_Client *client = cls;
2243   struct TunnelState *ts = value;
2244
2245   if (client == ts->client)
2246   {
2247     GNUNET_SERVER_client_drop (ts->client);
2248     ts->client = NULL;
2249   }
2250   return GNUNET_OK;
2251 }
2252
2253
2254 /**
2255  * A client disconnected, clean up all references to it.
2256  *
2257  * @param cls the client that disconnected
2258  * @param key unused
2259  * @param value a 'struct DestinationEntry *'
2260  * @return GNUNET_OK (continue to iterate)
2261  */
2262 static int
2263 cleanup_destination_client (void *cls,
2264                             const GNUNET_HashCode *key,
2265                             void *value)
2266 {
2267   struct GNUNET_SERVER_Client *client = cls;
2268   struct DestinationEntry *de = value;
2269   struct TunnelState *ts;
2270
2271   if (NULL == (ts = de->ts))
2272     return GNUNET_OK;
2273   if (client == ts->client)
2274   {
2275     GNUNET_SERVER_client_drop (ts->client);
2276     ts->client = NULL;
2277   }
2278   return GNUNET_OK;
2279 }
2280
2281   
2282 /**
2283  * A client has disconnected from us.  If we are currently building
2284  * a tunnel for it, cancel the operation.
2285  *
2286  * @param cls unused
2287  * @param client handle to the client that disconnected
2288  */
2289 static void
2290 client_disconnect (void *cls, struct GNUNET_SERVER_Client *client)
2291 {
2292   if (NULL != tunnel_map)
2293     GNUNET_CONTAINER_multihashmap_iterate (tunnel_map,
2294                                            &cleanup_tunnel_client,
2295                                            client);
2296   if (NULL != destination_map)
2297     GNUNET_CONTAINER_multihashmap_iterate (destination_map,
2298                                            &cleanup_destination_client,
2299                                            client);
2300 }
2301
2302
2303 /**
2304  * Main function that will be run by the scheduler.
2305  *
2306  * @param cls closure
2307  * @param server the initialized server
2308  * @param cfg_ configuration
2309  */
2310 static void
2311 run (void *cls,
2312      struct GNUNET_SERVER_Handle *server,
2313      const struct GNUNET_CONFIGURATION_Handle *cfg_)
2314 {
2315   static const struct GNUNET_SERVER_MessageHandler service_handlers[] = {
2316     /* callback, cls, type, size */
2317     { &service_redirect_to_ip, NULL, GNUNET_MESSAGE_TYPE_VPN_CLIENT_REDIRECT_TO_IP, 0},
2318     { &service_redirect_to_service, NULL, 
2319      GNUNET_MESSAGE_TYPE_VPN_CLIENT_REDIRECT_TO_SERVICE, 
2320      sizeof (struct RedirectToServiceRequestMessage) },
2321     {NULL, NULL, 0, 0}
2322   };
2323   static const struct GNUNET_MESH_MessageHandler mesh_handlers[] = {
2324     { &receive_udp_back, GNUNET_MESSAGE_TYPE_VPN_UDP_REPLY, 0},
2325     { &receive_tcp_back, GNUNET_MESSAGE_TYPE_VPN_TCP_DATA_TO_VPN, 0},
2326     {NULL, 0, 0}
2327   };
2328   static const GNUNET_MESH_ApplicationType types[] = {
2329     GNUNET_APPLICATION_TYPE_END
2330   };
2331   char *ifname;
2332   char *ipv6addr;
2333   char *ipv6prefix_s;
2334   char *ipv4addr;
2335   char *ipv4mask;
2336   struct in_addr v4;
2337   struct in6_addr v6;
2338
2339   cfg = cfg_;
2340   stats = GNUNET_STATISTICS_create ("vpn", cfg);
2341   if (GNUNET_OK !=
2342       GNUNET_CONFIGURATION_get_value_number (cfg, "vpn", "MAX_MAPPING",
2343                                              &max_destination_mappings))
2344     max_destination_mappings = 200;
2345   if (GNUNET_OK !=
2346       GNUNET_CONFIGURATION_get_value_number (cfg, "vpn", "MAX_TUNNELS",
2347                                              &max_tunnel_mappings))
2348     max_tunnel_mappings = 200;
2349
2350   destination_map = GNUNET_CONTAINER_multihashmap_create (max_destination_mappings * 2);
2351   destination_heap = GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN);
2352   tunnel_map = GNUNET_CONTAINER_multihashmap_create (max_tunnel_mappings * 2);
2353   tunnel_heap = GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN);
2354
2355
2356   vpn_argv[0] = GNUNET_strdup ("vpn-gnunet");
2357   if (GNUNET_SYSERR ==
2358       GNUNET_CONFIGURATION_get_value_string (cfg, "vpn", "IFNAME", &ifname))
2359   {
2360     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2361                 "No entry 'IFNAME' in configuration!\n");
2362     GNUNET_SCHEDULER_shutdown ();
2363     return;
2364   }
2365   vpn_argv[1] = ifname;
2366   if ( (GNUNET_SYSERR ==
2367         GNUNET_CONFIGURATION_get_value_string (cfg, "vpn", "IPV6ADDR",
2368                                                &ipv6addr) ||
2369         (1 != inet_pton (AF_INET6, ipv6addr, &v6))) )
2370   {
2371     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2372                 "No valid entry 'IPV6ADDR' in configuration!\n");
2373     GNUNET_SCHEDULER_shutdown ();
2374     return;
2375   }
2376   vpn_argv[2] = ipv6addr;
2377   if (GNUNET_SYSERR ==
2378       GNUNET_CONFIGURATION_get_value_string (cfg, "vpn", "IPV6PREFIX",
2379                                              &ipv6prefix_s))
2380   {
2381     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2382                 "No entry 'IPV6PREFIX' in configuration!\n");
2383     GNUNET_SCHEDULER_shutdown ();
2384     return;
2385   }
2386   vpn_argv[3] = ipv6prefix_s;
2387   if ( (GNUNET_OK !=
2388         GNUNET_CONFIGURATION_get_value_number (cfg, "vpn",
2389                                                "IPV6PREFIX",
2390                                                &ipv6prefix)) ||
2391        (ipv6prefix >= 127) )
2392   {
2393     GNUNET_SCHEDULER_shutdown ();
2394     return;
2395   }
2396
2397   if ( (GNUNET_SYSERR ==
2398         GNUNET_CONFIGURATION_get_value_string (cfg, "vpn", "IPV4ADDR",
2399                                                &ipv4addr) ||
2400         (1 != inet_pton (AF_INET, ipv4addr, &v4))) )
2401   {
2402     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2403                 "No valid entry for 'IPV4ADDR' in configuration!\n");
2404     GNUNET_SCHEDULER_shutdown ();
2405     return;
2406   }
2407   vpn_argv[4] = ipv4addr;
2408   if ( (GNUNET_SYSERR ==
2409         GNUNET_CONFIGURATION_get_value_string (cfg, "vpn", "IPV4MASK",
2410                                                &ipv4mask) ||
2411         (1 != inet_pton (AF_INET, ipv4mask, &v4))) )
2412   {
2413     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2414                 "No valid entry 'IPV4MASK' in configuration!\n");
2415     GNUNET_SCHEDULER_shutdown ();
2416     return;
2417   }
2418   vpn_argv[5] = ipv4mask;
2419   vpn_argv[6] = NULL;
2420
2421   mesh_handle =
2422     GNUNET_MESH_connect (cfg_, 42 /* queue length */, NULL, 
2423                          &inbound_tunnel_cb, 
2424                          &tunnel_cleaner, 
2425                          mesh_handlers,
2426                          types);
2427   helper_handle = GNUNET_HELPER_start ("gnunet-helper-vpn", vpn_argv,
2428                                        &message_token, NULL);
2429   nc = GNUNET_SERVER_notification_context_create (server, 1);
2430   GNUNET_SERVER_add_handlers (server, service_handlers);
2431   GNUNET_SERVER_disconnect_notify (server, &client_disconnect, NULL);
2432   GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &cleanup, cls);
2433 }
2434
2435
2436 /**
2437  * The main function of the VPN service.
2438  *
2439  * @param argc number of arguments from the command line
2440  * @param argv command line arguments
2441  * @return 0 ok, 1 on error
2442  */
2443 int
2444 main (int argc, char *const *argv)
2445 {
2446   return (GNUNET_OK ==
2447           GNUNET_SERVICE_run (argc, argv, "vpn", 
2448                               GNUNET_SERVICE_OPTION_NONE,
2449                               &run, NULL)) ? 0 : 1;
2450 }
2451
2452 /* end of gnunet-service-vpn.c */