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