-adding statistics to VPN
[oweals/gnunet.git] / src / vpn / gnunet-service-vpn.c
1 /*
2      This file is part of GNUnet.
3      (C) 2010, 2011, 2012 Christian Grothoff
4
5      GNUnet is free software; you can redistribute it and/or modify
6      it under the terms of the GNU General Public License as published
7      by the Free Software Foundation; either version 3, or (at your
8      option) any later version.
9
10      GNUnet is distributed in the hope that it will be useful, but
11      WITHOUT ANY WARRANTY; without even the implied warranty of
12      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13      General Public License for more details.
14
15      You should have received a copy of the GNU General Public License
16      along with GNUnet; see the file COPYING.  If not, write to the
17      Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18      Boston, MA 02111-1307, USA.
19 */
20
21 /**
22  * @file vpn/gnunet-service-vpn.c
23  * @brief service that opens a virtual interface and allows its clients
24  *        to allocate IPs on the virtual interface and to then redirect
25  *        IP traffic received on those IPs via the GNUnet mesh 
26  * @author Philipp Toelke
27  * @author Christian Grothoff
28  *
29  * TODO:
30  * 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       usm = (struct GNUNET_EXIT_UdpServiceMessage *) &tnq[1];
901       usm->header.size = htons ((uint16_t) mlen);
902       usm->header.type = htons (GNUNET_MESSAGE_TYPE_VPN_UDP_TO_SERVICE);
903       /* if the source port is below 32000, we assume it has a special
904          meaning; if not, we pick a random port (this is a heuristic) */
905       usm->source_port = (ntohs (udp->spt) < 32000) ? udp->spt : 0;
906       usm->destination_port = udp->dpt;
907       usm->service_descriptor = destination->details.service_destination.service_descriptor;
908       memcpy (&usm[1],
909               &udp[1],
910               payload_length - sizeof (struct udp_packet));
911     }
912     else
913     {
914       struct GNUNET_EXIT_UdpInternetMessage *uim;
915       struct in_addr *ip4dst;
916       struct in6_addr *ip6dst;
917       void *payload;
918
919       mlen = sizeof (struct GNUNET_EXIT_UdpInternetMessage) + 
920         alen + payload_length - sizeof (struct udp_packet);
921       if (mlen >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
922       {
923         GNUNET_break (0);
924         return;
925       }
926       tnq = GNUNET_malloc (sizeof (struct TunnelMessageQueueEntry) + 
927                            mlen);
928       uim = (struct GNUNET_EXIT_UdpInternetMessage *) &tnq[1];
929       uim->header.size = htons ((uint16_t) mlen);
930       uim->header.type = htons (GNUNET_MESSAGE_TYPE_VPN_UDP_TO_INTERNET); 
931       uim->af = htonl (destination->details.exit_destination.af);
932       uim->source_port = (ntohs (udp->spt) < 32000) ? udp->spt : 0;
933       uim->destination_port = udp->dpt;
934       switch (destination->details.exit_destination.af)
935       {
936       case AF_INET:
937         ip4dst = (struct in_addr *) &uim[1];
938         *ip4dst = destination->details.exit_destination.ip.v4;
939         payload = &ip4dst[1];
940         break;
941       case AF_INET6:
942         ip6dst = (struct in6_addr *) &uim[1];
943         *ip6dst = destination->details.exit_destination.ip.v6;
944         payload = &ip6dst[1];
945         break;
946       default:
947         GNUNET_assert (0);
948       }
949       memcpy (payload,
950               &udp[1],
951               payload_length - sizeof (struct udp_packet));
952     }
953     break;
954   case IPPROTO_TCP:
955     if (is_new)
956     {
957       if (destination->is_service)
958       {
959         struct GNUNET_EXIT_TcpServiceStartMessage *tsm;
960
961         mlen = sizeof (struct GNUNET_EXIT_TcpServiceStartMessage) + 
962           payload_length - sizeof (struct tcp_packet);
963         if (mlen >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
964         {
965           GNUNET_break (0);
966           return;
967         }
968         tnq = GNUNET_malloc (sizeof (struct TunnelMessageQueueEntry) + mlen);
969         tsm = (struct  GNUNET_EXIT_TcpServiceStartMessage *) &tnq[1];
970         tsm->header.size = htons ((uint16_t) mlen);
971         tsm->header.type = htons (GNUNET_MESSAGE_TYPE_VPN_TCP_TO_SERVICE_START);
972         tsm->reserved = htonl (0);
973         tsm->service_descriptor = destination->details.service_destination.service_descriptor;
974         tsm->tcp_header = *tcp;
975         memcpy (&tsm[1],
976                 &tcp[1],
977                 payload_length - sizeof (struct tcp_packet));
978       }
979       else
980       {
981         struct GNUNET_EXIT_TcpInternetStartMessage *tim;
982         struct in_addr *ip4dst;
983         struct in6_addr *ip6dst;
984         void *payload;
985
986         mlen = sizeof (struct GNUNET_EXIT_TcpInternetStartMessage) + 
987           alen + payload_length - sizeof (struct tcp_packet);
988         if (mlen >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
989         {
990           GNUNET_break (0);
991           return;
992         }
993         tnq = GNUNET_malloc (sizeof (struct TunnelMessageQueueEntry) + mlen);
994         tim = (struct  GNUNET_EXIT_TcpInternetStartMessage *) &tnq[1];
995         tim->header.size = htons ((uint16_t) mlen);
996         tim->header.type = htons (GNUNET_MESSAGE_TYPE_VPN_TCP_TO_INTERNET_START);
997         tim->af = htonl (destination->details.exit_destination.af);     
998         tim->tcp_header = *tcp;
999         switch (destination->details.exit_destination.af)
1000         {
1001         case AF_INET:
1002           ip4dst = (struct in_addr *) &tim[1];
1003           *ip4dst = destination->details.exit_destination.ip.v4;
1004           payload = &ip4dst[1];
1005           break;
1006         case AF_INET6:
1007           ip6dst = (struct in6_addr *) &tim[1];
1008           *ip6dst = destination->details.exit_destination.ip.v6;
1009           payload = &ip6dst[1];
1010           break;
1011         default:
1012           GNUNET_assert (0);
1013         }
1014         memcpy (payload,
1015                 &tcp[1],
1016                 payload_length - sizeof (struct tcp_packet));
1017       }
1018     }
1019     else
1020     {
1021       struct GNUNET_EXIT_TcpDataMessage *tdm;
1022
1023       mlen = sizeof (struct GNUNET_EXIT_TcpDataMessage) + 
1024         alen + payload_length - sizeof (struct tcp_packet);
1025       if (mlen >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1026       {
1027         GNUNET_break (0);
1028         return;
1029       }
1030       tnq = GNUNET_malloc (sizeof (struct TunnelMessageQueueEntry) + mlen);
1031       tdm = (struct  GNUNET_EXIT_TcpDataMessage *) &tnq[1];
1032       tdm->header.size = htons ((uint16_t) mlen);
1033       tdm->header.type = htons (GNUNET_MESSAGE_TYPE_VPN_TCP_DATA);
1034       tdm->reserved = htonl (0);
1035       tdm->tcp_header = *tcp;
1036       memcpy (&tdm[1],
1037               &tcp[1],
1038               payload_length - sizeof (struct tcp_packet));
1039      }
1040     break;
1041   default:
1042     /* not supported above, how can we get here !? */
1043     GNUNET_assert (0);
1044     break;
1045   }
1046   send_to_tunnel (tnq, ts);
1047 }
1048
1049
1050 /**
1051  * Receive packets from the helper-process (someone send to the local
1052  * virtual tunnel interface).  Find the destination mapping, and if it
1053  * exists, identify the correct MESH tunnel (or possibly create it)
1054  * and forward the packet.
1055  *
1056  * @param cls closure, NULL
1057  * @param client NULL
1058  * @param message message we got from the client (VPN tunnel interface)
1059  */
1060 static void
1061 message_token (void *cls GNUNET_UNUSED, void *client GNUNET_UNUSED,
1062                const struct GNUNET_MessageHeader *message)
1063 {
1064   const struct tun_header *tun;
1065   size_t mlen;
1066   GNUNET_HashCode key;
1067   struct DestinationEntry *de;
1068
1069   GNUNET_STATISTICS_update (stats,
1070                             gettext_noop ("# Packets received from TUN interface"),
1071                             1, GNUNET_NO);
1072   mlen = ntohs (message->size);
1073   if ( (ntohs (message->type) != GNUNET_MESSAGE_TYPE_VPN_HELPER) ||
1074        (mlen < sizeof (struct GNUNET_MessageHeader) + sizeof (struct tun_header)) )
1075   {
1076     GNUNET_break (0);
1077     return;
1078   }
1079   tun = (const struct tun_header *) &message[1];
1080   mlen -= (sizeof (struct GNUNET_MessageHeader) + sizeof (struct tun_header));
1081   switch (ntohs (tun->proto))
1082   {
1083   case ETH_P_IPV6:
1084     {
1085       const struct ip6_header *pkt6;
1086       
1087       if (mlen < sizeof (struct ip6_header))
1088       {
1089         /* blame kernel */
1090         GNUNET_break (0);
1091         return;
1092       }
1093       pkt6 = (const struct ip6_header *) &tun[1];
1094       get_destination_key_from_ip (AF_INET6,
1095                                    &pkt6->destination_address,
1096                                    &key);
1097       de = GNUNET_CONTAINER_multihashmap_get (destination_map, &key);
1098       /* FIXME: do we need to guard against hash collision? 
1099          (if so, we need to also store the local destination IP in the
1100          destination entry and then compare here; however, the risk
1101          of collision seems minimal AND the impact is unlikely to be
1102          super-problematic as well... */
1103       if (NULL == de)
1104       {
1105         char buf[INET6_ADDRSTRLEN];
1106         
1107         GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1108                     _("Packet received for unmapped destination `%s' (dropping it)\n"),
1109                     inet_ntop (AF_INET6,
1110                                &pkt6->destination_address,
1111                                buf,
1112                                sizeof (buf)));
1113         return;
1114       }
1115       route_packet (de,
1116                     AF_INET6,
1117                     pkt6->next_header,
1118                     &pkt6->source_address,                  
1119                     &pkt6->destination_address,             
1120                     &pkt6[1],
1121                     mlen - sizeof (struct ip6_header));
1122     }
1123     break;
1124   case ETH_P_IPV4:
1125     {
1126       struct ip4_header *pkt4;
1127
1128       if (mlen < sizeof (struct ip4_header))
1129       {
1130         /* blame kernel */
1131         GNUNET_break (0);
1132         return;
1133       }
1134       pkt4 = (struct ip4_header *) &tun[1];
1135       get_destination_key_from_ip (AF_INET,
1136                                    &pkt4->destination_address,
1137                                    &key);
1138       de = GNUNET_CONTAINER_multihashmap_get (destination_map, &key);
1139       /* FIXME: do we need to guard against hash collision? 
1140          (if so, we need to also store the local destination IP in the
1141          destination entry and then compare here; however, the risk
1142          of collision seems minimal AND the impact is unlikely to be
1143          super-problematic as well... */
1144       if (NULL == de)
1145       {
1146         char buf[INET_ADDRSTRLEN];
1147         
1148         GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1149                     _("Packet received for unmapped destination `%s' (dropping it)\n"),
1150                     inet_ntop (AF_INET,
1151                                &pkt4->destination_address,
1152                                buf,
1153                                sizeof (buf)));
1154         return;
1155       }
1156       if (pkt4->header_length * 4 != sizeof (struct ip4_header))
1157       {
1158         GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1159                     _("Received IPv4 packet with options (dropping it)\n"));                
1160         return;
1161       }
1162       route_packet (de,
1163                     AF_INET,
1164                     pkt4->protocol,
1165                     &pkt4->source_address,                  
1166                     &pkt4->destination_address,             
1167                     &pkt4[1],
1168                     mlen - sizeof (struct ip4_header));
1169     }
1170     break;
1171   default:
1172     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1173                 _("Received packet of unknown protocol %d from TUN (dropping it)\n"),
1174                 (unsigned int) ntohs (tun->proto));
1175     break;
1176   }
1177 }
1178
1179
1180 /**
1181  * We got a UDP packet back from the MESH tunnel.  Pass it on to the
1182  * local virtual interface via the helper.
1183  *
1184  * @param cls closure, NULL
1185  * @param tunnel connection to the other end
1186  * @param tunnel_ctx pointer to our 'struct TunnelState *'
1187  * @param sender who sent the message
1188  * @param message the actual message
1189  * @param atsi performance data for the connection
1190  * @return GNUNET_OK to keep the connection open,
1191  *         GNUNET_SYSERR to close it (signal serious error)
1192  */ 
1193 static int
1194 receive_udp_back (void *cls GNUNET_UNUSED, struct GNUNET_MESH_Tunnel *tunnel,
1195                   void **tunnel_ctx, const struct GNUNET_PeerIdentity *sender,
1196                   const struct GNUNET_MessageHeader *message,
1197                   const struct GNUNET_ATS_Information *atsi GNUNET_UNUSED)
1198 {
1199   struct TunnelState *ts = *tunnel_ctx;
1200   const struct GNUNET_EXIT_UdpReplyMessage *reply;
1201   size_t mlen;
1202
1203   GNUNET_STATISTICS_update (stats,
1204                             gettext_noop ("# UDP packets received from mesh"),
1205                             1, GNUNET_NO);
1206   mlen = ntohs (message->size);
1207   if (mlen < sizeof (struct GNUNET_EXIT_UdpReplyMessage))
1208   {
1209     GNUNET_break_op (0);
1210     return GNUNET_SYSERR;
1211   }
1212   if (NULL == ts->heap_node)
1213   {
1214     GNUNET_break_op (0);
1215     return GNUNET_SYSERR;
1216   }
1217   if (AF_UNSPEC == ts->af)
1218   {
1219     GNUNET_break_op (0);
1220     return GNUNET_SYSERR;
1221   }
1222   reply = (const struct GNUNET_EXIT_UdpReplyMessage *) message;
1223   mlen -= sizeof (struct GNUNET_EXIT_UdpReplyMessage);
1224   {
1225     char sbuf[INET6_ADDRSTRLEN];
1226     char dbuf[INET6_ADDRSTRLEN];
1227     
1228     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1229                 "Received UDP reply from mesh, sending %u bytes from %s:%u -> %s:%u via TUN\n",
1230                 (unsigned int) mlen,
1231                 inet_ntop (ts->af, &ts->destination_ip, sbuf, sizeof (sbuf)),
1232                 ts->destination_port,
1233                 inet_ntop (ts->af, &ts->source_ip, dbuf, sizeof (dbuf)),
1234                 ts->source_port);
1235   }
1236   switch (ts->af)
1237   {
1238   case AF_INET:
1239     {
1240       size_t size = sizeof (struct ip4_header) 
1241         + sizeof (struct udp_packet) 
1242         + sizeof (struct GNUNET_MessageHeader) +
1243         sizeof (struct tun_header) +
1244         mlen;
1245       {
1246         char buf[size];
1247         struct GNUNET_MessageHeader *msg = (struct GNUNET_MessageHeader *) buf;
1248         struct tun_header *tun = (struct tun_header*) &msg[1];
1249         struct ip4_header *ipv4 = (struct ip4_header *) &tun[1];
1250         struct udp_packet *udp = (struct udp_packet *) &ipv4[1];
1251         msg->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
1252         msg->size = htons (size);
1253         tun->flags = htons (0);
1254         tun->proto = htons (ETH_P_IPV4);
1255         ipv4->version = 4;
1256         ipv4->header_length = sizeof (struct ip4_header) / 4;
1257         ipv4->diff_serv = 0;
1258         ipv4->total_length = htons (sizeof (struct ip4_header) +
1259                                     sizeof (struct udp_packet) +
1260                                     mlen);
1261         ipv4->identification = (uint16_t) GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, 
1262                                                                     UINT16_MAX + 1);
1263         ipv4->flags = 0;
1264         ipv4->fragmentation_offset = 0;
1265         ipv4->ttl = 255;
1266         ipv4->protocol = IPPROTO_UDP;
1267         ipv4->checksum = 0; 
1268         ipv4->source_address = ts->destination_ip.v4;
1269         ipv4->destination_address = ts->source_ip.v4;
1270         ipv4->checksum =
1271           GNUNET_CRYPTO_crc16_n (ipv4, sizeof (struct ip4_header));
1272         if (0 == ntohs (reply->source_port))
1273           udp->spt = htons (ts->destination_port);
1274         else
1275           udp->spt = reply->source_port;
1276         if (0 == ntohs (reply->destination_port))
1277           udp->dpt = htons (ts->source_port);
1278         else
1279           udp->dpt = reply->destination_port;
1280         udp->len = htons (mlen + sizeof (struct udp_packet));
1281         udp->crc = 0; // FIXME: optional, but we might want to calculate this one anyway
1282         memcpy (&udp[1],
1283                 &reply[1],
1284                 mlen);
1285         (void) GNUNET_HELPER_send (helper_handle,
1286                                    msg,
1287                                    GNUNET_YES,
1288                                    NULL, NULL);
1289       }
1290     }
1291     break;
1292   case AF_INET6:
1293     {
1294       size_t size = sizeof (struct ip6_header) 
1295         + sizeof (struct udp_packet) 
1296         + sizeof (struct GNUNET_MessageHeader) +
1297         sizeof (struct tun_header) +
1298         mlen;
1299       {
1300         char buf[size];
1301         struct GNUNET_MessageHeader *msg = (struct GNUNET_MessageHeader *) buf;
1302         struct tun_header *tun = (struct tun_header*) &msg[1];
1303         struct ip6_header *ipv6 = (struct ip6_header *) &tun[1];
1304         struct udp_packet *udp = (struct udp_packet *) &ipv6[1];
1305         msg->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
1306         msg->size = htons (size);
1307         tun->flags = htons (0);
1308         tun->proto = htons (ETH_P_IPV6);
1309         ipv6->traffic_class_h = 0;
1310         ipv6->version = 6;
1311         ipv6->traffic_class_l = 0;
1312         ipv6->flow_label = 0;
1313         ipv6->payload_length = htons (sizeof (struct udp_packet) + sizeof (struct ip6_header) + mlen);
1314         ipv6->next_header = IPPROTO_UDP;
1315         ipv6->hop_limit = 255;
1316         ipv6->source_address = ts->destination_ip.v6;
1317         ipv6->destination_address = ts->source_ip.v6;
1318         if (0 == ntohs (reply->source_port))
1319           udp->spt = htons (ts->destination_port);
1320         else
1321           udp->spt = reply->source_port;
1322         if (0 == ntohs (reply->destination_port))
1323           udp->dpt = htons (ts->source_port);
1324         else
1325           udp->dpt = reply->destination_port;
1326         udp->len = htons (mlen + sizeof (struct udp_packet));
1327         udp->crc = 0;
1328         memcpy (&udp[1],
1329                 &reply[1],
1330                 mlen);
1331         {
1332           uint32_t sum = 0;
1333           sum =
1334             GNUNET_CRYPTO_crc16_step (sum, &ipv6->source_address, 
1335                                       sizeof (struct in6_addr) * 2);
1336           uint32_t tmp = udp->len;
1337           sum = GNUNET_CRYPTO_crc16_step (sum, &tmp, sizeof (uint32_t));
1338           tmp = htons (IPPROTO_UDP);
1339           sum = GNUNET_CRYPTO_crc16_step (sum, &tmp, sizeof (uint32_t));
1340           sum = GNUNET_CRYPTO_crc16_step (sum, 
1341                                           udp,
1342                                           ntohs (udp->len));
1343           udp->crc = GNUNET_CRYPTO_crc16_finish (sum);
1344         }
1345         (void) GNUNET_HELPER_send (helper_handle,
1346                                    msg,
1347                                    GNUNET_YES,
1348                                    NULL, NULL);
1349       }
1350     }
1351     break;
1352   default:
1353     GNUNET_assert (0);
1354   }
1355   GNUNET_CONTAINER_heap_update_cost (tunnel_heap, 
1356                                      ts->heap_node,
1357                                      GNUNET_TIME_absolute_get ().abs_value);
1358   return GNUNET_OK;
1359 }
1360
1361
1362 /**
1363  * We got a TCP packet back from the MESH tunnel.  Pass it on to the
1364  * local virtual interface via the helper.
1365  *
1366  * @param cls closure, NULL
1367  * @param tunnel connection to the other end
1368  * @param tunnel_ctx pointer to our 'struct TunnelState *'
1369  * @param sender who sent the message
1370  * @param message the actual message
1371  * @param atsi performance data for the connection
1372  * @return GNUNET_OK to keep the connection open,
1373  *         GNUNET_SYSERR to close it (signal serious error)
1374  */ 
1375 static int
1376 receive_tcp_back (void *cls GNUNET_UNUSED, struct GNUNET_MESH_Tunnel *tunnel,
1377                   void **tunnel_ctx,
1378                   const struct GNUNET_PeerIdentity *sender GNUNET_UNUSED,
1379                   const struct GNUNET_MessageHeader *message,
1380                   const struct GNUNET_ATS_Information *atsi GNUNET_UNUSED)
1381 {
1382   struct TunnelState *ts = *tunnel_ctx;
1383   const struct GNUNET_EXIT_TcpDataMessage *data;
1384   size_t mlen;
1385
1386   GNUNET_STATISTICS_update (stats,
1387                             gettext_noop ("# TCP packets received from mesh"),
1388                             1, GNUNET_NO);
1389   mlen = ntohs (message->size);
1390   if (mlen < sizeof (struct GNUNET_EXIT_TcpDataMessage))
1391   {
1392     GNUNET_break_op (0);
1393     return GNUNET_SYSERR;
1394   }
1395   if (NULL == ts->heap_node)
1396   {
1397     GNUNET_break_op (0);
1398     return GNUNET_SYSERR;
1399   }
1400   data = (const struct GNUNET_EXIT_TcpDataMessage *) message;
1401   mlen -= sizeof (struct GNUNET_EXIT_TcpDataMessage);
1402   {
1403     char sbuf[INET6_ADDRSTRLEN];
1404     char dbuf[INET6_ADDRSTRLEN];
1405     
1406     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1407                 "Received TCP reply from mesh, sending %u bytes from %s:%u -> %s:%u via TUN\n",
1408                 (unsigned int) mlen,
1409                 inet_ntop (ts->af, &ts->destination_ip, sbuf, sizeof (sbuf)),
1410                 ts->destination_port,
1411                 inet_ntop (ts->af, &ts->source_ip, dbuf, sizeof (dbuf)),
1412                 ts->source_port);
1413   }
1414   switch (ts->af)
1415   {
1416   case AF_INET:
1417     {
1418       size_t size = sizeof (struct ip4_header) 
1419         + sizeof (struct tcp_packet) 
1420         + sizeof (struct GNUNET_MessageHeader) +
1421         sizeof (struct tun_header) +
1422         mlen;
1423       {
1424         char buf[size];
1425         struct GNUNET_MessageHeader *msg = (struct GNUNET_MessageHeader *) buf;
1426         struct tun_header *tun = (struct tun_header*) &msg[1];
1427         struct ip4_header *ipv4 = (struct ip4_header *) &tun[1];
1428         struct tcp_packet *tcp = (struct tcp_packet *) &ipv4[1];
1429         msg->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
1430         msg->size = htons (size);
1431         tun->flags = htons (0);
1432         tun->proto = htons (ETH_P_IPV4);
1433         ipv4->version = 4;
1434         ipv4->header_length = sizeof (struct ip4_header) / 4;
1435         ipv4->diff_serv = 0;
1436         ipv4->total_length = htons (sizeof (struct ip4_header) +
1437                                     sizeof (struct tcp_packet) +
1438                                     mlen);
1439         ipv4->identification = (uint16_t) GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, 
1440                                                                     UINT16_MAX + 1);
1441         ipv4->flags = 0;
1442         ipv4->fragmentation_offset = 0;
1443         ipv4->ttl = 255;
1444         ipv4->protocol = IPPROTO_TCP;
1445         ipv4->checksum = 0; 
1446         ipv4->source_address = ts->destination_ip.v4;
1447         ipv4->destination_address = ts->source_ip.v4;
1448         ipv4->checksum =
1449           GNUNET_CRYPTO_crc16_n (ipv4, sizeof (struct ip4_header));
1450         *tcp = data->tcp_header;
1451         tcp->spt = htons (ts->destination_port);
1452         tcp->dpt = htons (ts->source_port);
1453         tcp->crc = 0;
1454         memcpy (&tcp[1],
1455                 &data[1],
1456                 mlen);
1457         {
1458           uint32_t sum = 0;
1459           uint32_t tmp;
1460           
1461           sum = GNUNET_CRYPTO_crc16_step (sum, 
1462                                           &ipv4->source_address,
1463                                           2 * sizeof (struct in_addr));   
1464           tmp = htonl ((IPPROTO_TCP << 16) | (mlen + sizeof (struct tcp_packet)));
1465           sum = GNUNET_CRYPTO_crc16_step (sum, &tmp, sizeof (uint32_t));
1466           sum = GNUNET_CRYPTO_crc16_step (sum, tcp, mlen + sizeof (struct tcp_packet));
1467           tcp->crc = GNUNET_CRYPTO_crc16_finish (sum);
1468         }
1469         (void) GNUNET_HELPER_send (helper_handle,
1470                                    msg,
1471                                    GNUNET_YES,
1472                                    NULL, NULL);
1473       }
1474     }
1475     break;
1476   case AF_INET6:
1477     {
1478       size_t size = sizeof (struct ip6_header) 
1479         + sizeof (struct tcp_packet) 
1480         + sizeof (struct GNUNET_MessageHeader) +
1481         sizeof (struct tun_header) +
1482         mlen;
1483       {
1484         char buf[size];
1485         struct GNUNET_MessageHeader *msg = (struct GNUNET_MessageHeader *) buf;
1486         struct tun_header *tun = (struct tun_header*) &msg[1];
1487         struct ip6_header *ipv6 = (struct ip6_header *) &tun[1];
1488         struct tcp_packet *tcp = (struct tcp_packet *) &ipv6[1];
1489         msg->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
1490         msg->size = htons (size);
1491         tun->flags = htons (0);
1492         tun->proto = htons (ETH_P_IPV6);
1493         ipv6->traffic_class_h = 0;
1494         ipv6->version = 6;
1495         ipv6->traffic_class_l = 0;
1496         ipv6->flow_label = 0;
1497         ipv6->payload_length = htons (sizeof (struct tcp_packet) + sizeof (struct ip6_header) + mlen);
1498         ipv6->next_header = IPPROTO_TCP;
1499         ipv6->hop_limit = 255;
1500         ipv6->source_address = ts->destination_ip.v6;
1501         ipv6->destination_address = ts->source_ip.v6;
1502         tcp->spt = htons (ts->destination_port);
1503         tcp->dpt = htons (ts->source_port);
1504         tcp->crc = 0;
1505         {
1506           uint32_t sum = 0;
1507           uint32_t tmp;
1508
1509           sum = GNUNET_CRYPTO_crc16_step (sum, &ipv6->source_address, 2 * sizeof (struct in6_addr));
1510           tmp = htonl (sizeof (struct tcp_packet) + mlen);
1511           sum = GNUNET_CRYPTO_crc16_step (sum, &tmp, sizeof (uint32_t));
1512           tmp = htonl (IPPROTO_TCP);
1513           sum = GNUNET_CRYPTO_crc16_step (sum, &tmp, sizeof (uint32_t));
1514           sum = GNUNET_CRYPTO_crc16_step (sum, tcp,
1515                                           sizeof (struct tcp_packet) + mlen);
1516           tcp->crc = GNUNET_CRYPTO_crc16_finish (sum);
1517         }
1518         (void) GNUNET_HELPER_send (helper_handle,
1519                                    msg,
1520                                    GNUNET_YES,
1521                                    NULL, NULL);
1522       }
1523     }
1524     break;
1525   }
1526   GNUNET_CONTAINER_heap_update_cost (tunnel_heap, 
1527                                      ts->heap_node,
1528                                      GNUNET_TIME_absolute_get ().abs_value);
1529   return GNUNET_OK;
1530 }
1531
1532
1533 /**
1534  * Allocate an IPv4 address from the range of the tunnel
1535  * for a new redirection.
1536  *
1537  * @param v4 where to store the address
1538  * @return GNUNET_OK on success,
1539  *         GNUNET_SYSERR on error
1540  */
1541 static int
1542 allocate_v4_address (struct in_addr *v4)
1543 {
1544   const char *ipv4addr = vpn_argv[4];
1545   const char *ipv4mask = vpn_argv[5];
1546   struct in_addr addr;
1547   struct in_addr mask;
1548   struct in_addr rnd;
1549   GNUNET_HashCode key;
1550   unsigned int tries;
1551
1552   GNUNET_assert (1 == inet_pton (AF_INET, ipv4addr, &addr));
1553   GNUNET_assert (1 == inet_pton (AF_INET, ipv4mask, &mask));           
1554   /* Given 192.168.0.1/255.255.0.0, we want a mask 
1555      of '192.168.255.255', thus:  */
1556   mask.s_addr = addr.s_addr | ~mask.s_addr;  
1557   tries = 0;
1558   do
1559     {
1560       tries++;
1561       if (tries > 16)
1562       {
1563         GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1564                     _("Failed to find unallocated IPv4 address in VPN's range\n"));
1565         return GNUNET_SYSERR;
1566       }
1567       /* Pick random IPv4 address within the subnet, except 'addr' or 'mask' itself */
1568       rnd.s_addr = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, 
1569                                              UINT32_MAX);       
1570       v4->s_addr = (addr.s_addr | rnd.s_addr) & mask.s_addr;          
1571       get_destination_key_from_ip (AF_INET,
1572                                    v4,
1573                                    &key);
1574     }
1575   while ( (GNUNET_YES ==
1576            GNUNET_CONTAINER_multihashmap_contains (destination_map,
1577                                                    &key)) ||
1578           (v4->s_addr == addr.s_addr) ||
1579           (v4->s_addr == mask.s_addr) );
1580   return GNUNET_OK;
1581 }
1582
1583
1584 /**
1585  * Allocate an IPv6 address from the range of the tunnel
1586  * for a new redirection.
1587  *
1588  * @param v6 where to store the address
1589  * @return GNUNET_OK on success,
1590  *         GNUNET_SYSERR on error
1591  */
1592 static int
1593 allocate_v6_address (struct in6_addr *v6)
1594 {
1595   const char *ipv6addr = vpn_argv[2];
1596   struct in6_addr addr;
1597   struct in6_addr mask;
1598   struct in6_addr rnd;
1599   int i;
1600   GNUNET_HashCode key;
1601   unsigned int tries;
1602
1603   GNUNET_assert (1 == inet_pton (AF_INET6, ipv6addr, &addr));
1604   GNUNET_assert (ipv6prefix < 128);
1605   /* Given ABCD::/96, we want a mask of 'ABCD::FFFF:FFFF,
1606      thus: */
1607   mask = addr;
1608   for (i=127;i>=128-ipv6prefix;i--)
1609     mask.s6_addr[i / 8] |= (1 << (i % 8));
1610   
1611   /* Pick random IPv6 address within the subnet, except 'addr' or 'mask' itself */
1612   tries = 0;
1613   do
1614     {
1615       tries++;
1616       if (tries > 16)
1617         {
1618           GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1619                       _("Failed to find unallocated IPv6 address in VPN's range\n"));
1620           return GNUNET_SYSERR;
1621
1622         }
1623       for (i=0;i<16;i++)
1624         {
1625           rnd.s6_addr[i] = (unsigned char) GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, 
1626                                                                      256);
1627           v6->s6_addr[i]
1628             = (addr.s6_addr[i] | rnd.s6_addr[i]) & mask.s6_addr[i];
1629         }
1630       get_destination_key_from_ip (AF_INET6,
1631                                    v6,
1632                                    &key);
1633     }
1634   while ( (GNUNET_YES ==
1635            GNUNET_CONTAINER_multihashmap_contains (destination_map,
1636                                                    &key)) ||
1637           (0 == memcmp (v6,
1638                         &addr,
1639                         sizeof (struct in6_addr))) ||
1640           (0 == memcmp (v6,
1641                         &mask,
1642                         sizeof (struct in6_addr))) );
1643   return GNUNET_OK;
1644 }
1645
1646
1647 /**
1648  * A client asks us to setup a redirection via some exit
1649  * node to a particular IP.  Setup the redirection and
1650  * give the client the allocated IP.
1651  *
1652  * @param cls unused
1653  * @param client requesting client
1654  * @param message redirection request (a 'struct RedirectToIpRequestMessage')
1655  */
1656 static void
1657 service_redirect_to_ip (void *cls GNUNET_UNUSED, struct GNUNET_SERVER_Client *client,
1658                         const struct GNUNET_MessageHeader *message)
1659 {
1660   size_t mlen;
1661   size_t alen;
1662   const struct RedirectToIpRequestMessage *msg;
1663   int addr_af;
1664   int result_af;
1665   struct in_addr v4;
1666   struct in6_addr v6;
1667   void *addr;
1668   struct DestinationEntry *de;
1669   GNUNET_HashCode key;
1670   
1671   /* validate and parse request */
1672   mlen = ntohs (message->size);
1673   if (mlen < sizeof (struct RedirectToIpRequestMessage))
1674   {
1675     GNUNET_break (0);
1676     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1677     return;
1678   }
1679   alen = mlen - sizeof (struct RedirectToIpRequestMessage);
1680   msg = (const struct RedirectToIpRequestMessage *) message;
1681   addr_af = (int) htonl (msg->addr_af);
1682   switch (addr_af)
1683   {
1684   case AF_INET:
1685     if (alen != sizeof (struct in_addr))
1686     {
1687       GNUNET_break (0);
1688       GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1689       return;      
1690     }
1691     break;
1692   case AF_INET6:
1693     if (alen != sizeof (struct in6_addr))
1694     {
1695       GNUNET_break (0);
1696       GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1697       return;      
1698     }
1699     break;
1700   default:
1701     GNUNET_break (0);
1702     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1703     return;      
1704   }
1705
1706   /* allocate response IP */
1707   addr = NULL;
1708   result_af = (int) htonl (msg->result_af);
1709   switch (result_af)
1710   {
1711   case AF_INET:
1712     if (GNUNET_OK !=
1713         allocate_v4_address (&v4))
1714       result_af = AF_UNSPEC;
1715     else
1716       addr = &v4;
1717     break;
1718   case AF_INET6:
1719     if (GNUNET_OK !=
1720         allocate_v6_address (&v6))
1721       result_af = AF_UNSPEC;
1722     else
1723       addr = &v6;
1724     break;
1725   case AF_UNSPEC:
1726     if (GNUNET_OK ==
1727         allocate_v4_address (&v4))
1728     {
1729       addr = &v4;
1730       result_af = AF_INET;
1731     }
1732     else if (GNUNET_OK ==
1733         allocate_v6_address (&v6))
1734     {
1735       addr = &v6;
1736       result_af = AF_INET6;
1737     }
1738     break;
1739   default:
1740     GNUNET_break (0);
1741     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1742     return;      
1743   }
1744   if ( (result_af == AF_UNSPEC) ||
1745        (GNUNET_NO == ntohl (msg->nac)) )
1746   {
1747     /* send reply "instantly" */
1748     send_client_reply (client,
1749                        msg->request_id,
1750                        result_af,
1751                        addr);
1752   }
1753   if (result_af == AF_UNSPEC)
1754   {
1755     /* failure, we're done */
1756     GNUNET_SERVER_receive_done (client, GNUNET_OK);
1757     return;
1758   }
1759
1760   {
1761     char sbuf[INET6_ADDRSTRLEN];
1762     char dbuf[INET6_ADDRSTRLEN];
1763     
1764     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1765                 "Allocated address %s for redirection via exit to %s\n",
1766                 inet_ntop (result_af, addr, sbuf, sizeof (sbuf)),
1767                 inet_ntop (addr_af,
1768                            &msg[1], dbuf, sizeof (dbuf)));
1769   }
1770   
1771   /* setup destination record */
1772   de = GNUNET_malloc (sizeof (struct DestinationEntry));
1773   de->is_service = GNUNET_NO;
1774   de->details.exit_destination.af = addr_af;
1775   memcpy (&de->details.exit_destination.ip,
1776           &msg[1],
1777           alen);
1778   get_destination_key_from_ip (result_af,
1779                                addr,
1780                                &key);
1781   de->key = key;
1782   GNUNET_assert (GNUNET_OK ==
1783                  GNUNET_CONTAINER_multihashmap_put (destination_map,
1784                                                     &key,
1785                                                     de,
1786                                                     GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE));
1787   de->heap_node = GNUNET_CONTAINER_heap_insert (destination_heap,
1788                                                 de,
1789                                                 GNUNET_TIME_absolute_ntoh (msg->expiration_time).abs_value);
1790   GNUNET_STATISTICS_update (stats,
1791                             gettext_noop ("# Active destinations"),
1792                             1, GNUNET_NO);
1793
1794   /* FIXME: expire OLD destinations if we have too many! */
1795   /* setup tunnel to destination */
1796   (void) create_tunnel_to_destination (de, 
1797                                        (GNUNET_NO == ntohl (msg->nac)) ? NULL : client,
1798                                        msg->request_id);
1799   GNUNET_assert (NULL != de->ts);
1800   /* we're done */
1801   GNUNET_SERVER_receive_done (client, GNUNET_OK);
1802 }
1803
1804
1805 /**
1806  * A client asks us to setup a redirection to a particular peer
1807  * offering a service.  Setup the redirection and give the client the
1808  * allocated IP.
1809  *
1810  * @param cls unused
1811  * @param client requesting client
1812  * @param message redirection request (a 'struct RedirectToPeerRequestMessage')
1813  */
1814 static void
1815 service_redirect_to_service (void *cls GNUNET_UNUSED, struct GNUNET_SERVER_Client *client,
1816                              const struct GNUNET_MessageHeader *message)
1817 {
1818   const struct RedirectToServiceRequestMessage *msg;
1819   int result_af;
1820   struct in_addr v4;
1821   struct in6_addr v6;
1822   void *addr;
1823   struct DestinationEntry *de;
1824   GNUNET_HashCode key;
1825   
1826   /*  parse request */
1827   msg = (const struct RedirectToServiceRequestMessage *) message;
1828
1829   /* allocate response IP */
1830   addr = NULL;
1831   result_af = (int) htonl (msg->result_af);
1832   switch (result_af)
1833   {
1834   case AF_INET:
1835     if (GNUNET_OK !=
1836         allocate_v4_address (&v4))
1837       result_af = AF_UNSPEC;
1838     else
1839       addr = &v4;
1840     break;
1841   case AF_INET6:
1842     if (GNUNET_OK !=
1843         allocate_v6_address (&v6))
1844       result_af = AF_UNSPEC;
1845     else
1846       addr = &v6;
1847     break;
1848   case AF_UNSPEC:
1849     if (GNUNET_OK ==
1850         allocate_v4_address (&v4))
1851     {
1852       addr = &v4;
1853       result_af = AF_INET;
1854     }
1855     else if (GNUNET_OK ==
1856         allocate_v6_address (&v6))
1857     {
1858       addr = &v6;
1859       result_af = AF_INET6;
1860     }
1861     break;
1862   default:
1863     GNUNET_break (0);
1864     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1865     return;      
1866   }
1867   if ( (result_af == AF_UNSPEC) ||
1868        (GNUNET_NO == ntohl (msg->nac)) )
1869   {
1870     /* send reply "instantly" */
1871     send_client_reply (client,
1872                        msg->request_id,
1873                        result_af,
1874                        addr);
1875   }
1876   if (result_af == AF_UNSPEC)
1877   {
1878     /* failure, we're done */
1879     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1880                 _("Failed to allocate IP address for new destination\n"));
1881     GNUNET_SERVER_receive_done (client, GNUNET_OK);
1882     return;
1883   }
1884
1885   {
1886     char sbuf[INET6_ADDRSTRLEN];
1887     
1888     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1889                 "Allocated address %s for redirection to service %s on peer %s\n",
1890                 inet_ntop (result_af, addr, sbuf, sizeof (sbuf)),
1891                 GNUNET_h2s (&msg->service_descriptor),
1892                 GNUNET_i2s (&msg->target));
1893   }
1894   
1895   /* setup destination record */
1896   de = GNUNET_malloc (sizeof (struct DestinationEntry));
1897   de->is_service = GNUNET_YES;
1898   de->details.service_destination.service_descriptor = msg->service_descriptor;
1899   de->details.service_destination.target = msg->target;
1900   get_destination_key_from_ip (result_af,
1901                                addr,
1902                                &key);
1903   de->key = key;
1904   GNUNET_assert (GNUNET_OK ==
1905                  GNUNET_CONTAINER_multihashmap_put (destination_map,
1906                                                     &key,
1907                                                     de,
1908                                                     GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE));
1909   de->heap_node = GNUNET_CONTAINER_heap_insert (destination_heap,
1910                                                 de,
1911                                                 GNUNET_TIME_absolute_ntoh (msg->expiration_time).abs_value);
1912   /* FIXME: expire OLD destinations if we have too many! */
1913   (void) create_tunnel_to_destination (de,
1914                                        (GNUNET_NO == ntohl (msg->nac)) ? NULL : client,
1915                                        msg->request_id);
1916   /* we're done */
1917   GNUNET_SERVER_receive_done (client, GNUNET_OK);
1918 }
1919
1920
1921
1922 /**
1923  * Function called for inbound tunnels.  As we don't offer
1924  * any mesh services, this function should never be called.
1925  *
1926  * @param cls closure
1927  * @param tunnel new handle to the tunnel
1928  * @param initiator peer that started the tunnel
1929  * @param atsi performance information for the tunnel
1930  * @return initial tunnel context for the tunnel
1931  *         (can be NULL -- that's not an error)
1932  */ 
1933 static void *
1934 inbound_tunnel_cb (void *cls, struct GNUNET_MESH_Tunnel *tunnel,
1935                    const struct GNUNET_PeerIdentity *initiator,
1936                    const struct GNUNET_ATS_Information *atsi)
1937 {
1938   /* How can and why should anyone open an inbound tunnel to vpn? */
1939   GNUNET_break (0);
1940   return NULL;
1941 }
1942
1943
1944 /**
1945  * Free resources associated with a tunnel state.
1946  *
1947  * @param ts state to free
1948  */
1949 static void
1950 free_tunnel_state (struct TunnelState *ts)
1951 {
1952   GNUNET_HashCode key;
1953   struct TunnelMessageQueueEntry *tnq;
1954
1955   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1956               "Cleaning up tunnel state\n");
1957   GNUNET_STATISTICS_update (stats,
1958                             gettext_noop ("# Active tunnels"),
1959                             -1, GNUNET_NO);
1960   while (NULL != (tnq = ts->head))
1961   {
1962     GNUNET_CONTAINER_DLL_remove (ts->head,
1963                                  ts->tail,
1964                                  tnq);
1965     GNUNET_free (tnq);
1966   }
1967   if (NULL != ts->client)
1968   {
1969     GNUNET_SERVER_client_drop (ts->client);
1970     ts->client = NULL;
1971   }
1972   if (NULL != ts->th)
1973   {
1974     GNUNET_MESH_notify_transmit_ready_cancel (ts->th);
1975     ts->th = NULL;
1976   }
1977   GNUNET_assert (NULL == ts->destination.heap_node);
1978   if (NULL != ts->tunnel)
1979   {
1980     GNUNET_MESH_tunnel_destroy (ts->tunnel);
1981     ts->tunnel = NULL;
1982   }
1983   if (NULL != ts->heap_node)
1984   {
1985     GNUNET_CONTAINER_heap_remove_node (ts->heap_node);
1986     ts->heap_node = NULL;
1987     get_tunnel_key_from_ips (ts->af,
1988                              ts->protocol,
1989                              &ts->source_ip,
1990                              ts->source_port,
1991                              &ts->destination_ip,
1992                              ts->destination_port,
1993                              &key);
1994     GNUNET_assert (GNUNET_YES ==
1995                    GNUNET_CONTAINER_multihashmap_remove (tunnel_map,
1996                                                          &key,
1997                                                          ts));
1998   }
1999   if (NULL != ts->destination_container)
2000   {
2001     GNUNET_assert (ts == ts->destination_container->ts);
2002     ts->destination_container->ts = NULL;
2003     ts->destination_container = NULL;
2004   }
2005   GNUNET_free (ts);
2006 }
2007
2008
2009 /**
2010  * Free resources occupied by a destination entry.
2011  *
2012  * @param de entry to free
2013  */
2014 static void
2015 free_destination_entry (struct DestinationEntry *de)
2016 {
2017   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2018               "Cleaning up destination entry\n");
2019   GNUNET_STATISTICS_update (stats,
2020                             gettext_noop ("# Active destinations"),
2021                             -1, GNUNET_NO);
2022   if (NULL != de->ts)
2023   {
2024     free_tunnel_state (de->ts);
2025     GNUNET_assert (NULL == de->ts);
2026   }
2027   if (NULL != de->heap_node)
2028   {
2029     GNUNET_CONTAINER_heap_remove_node (de->heap_node);
2030     de->heap_node = NULL;  
2031     GNUNET_assert (GNUNET_YES ==
2032                    GNUNET_CONTAINER_multihashmap_remove (destination_map,
2033                                                          &de->key,
2034                                                          de));
2035   }
2036   GNUNET_free (de);
2037 }
2038
2039
2040 /**
2041  * Function called whenever an inbound tunnel is destroyed.  Should clean up
2042  * any associated state.
2043  *
2044  * @param cls closure (set from GNUNET_MESH_connect)
2045  * @param tunnel connection to the other end (henceforth invalid)
2046  * @param tunnel_ctx place where local state associated
2047  *                   with the tunnel is stored (our 'struct TunnelState')
2048  */ 
2049 static void
2050 tunnel_cleaner (void *cls, const struct GNUNET_MESH_Tunnel *tunnel, void *tunnel_ctx)
2051 {
2052   struct TunnelState *ts = tunnel_ctx;
2053
2054   if (NULL == ts)
2055   {
2056     GNUNET_break (0);
2057     return;     
2058   }
2059   GNUNET_assert (ts->tunnel == tunnel);
2060   ts->tunnel = NULL;
2061   free_tunnel_state (ts);
2062 }
2063
2064
2065 /**
2066  * Free memory occupied by an entry in the destination map.
2067  *
2068  * @param cls unused
2069  * @param key unused
2070  * @param value a 'struct DestinationEntry *'
2071  * @return GNUNET_OK (continue to iterate)
2072  */
2073 static int
2074 cleanup_destination (void *cls,
2075                      const GNUNET_HashCode *key,
2076                      void *value)
2077 {
2078   struct DestinationEntry *de = value;
2079
2080   free_destination_entry (de);
2081   return GNUNET_OK;
2082 }
2083
2084
2085 /**
2086  * Free memory occupied by an entry in the tunnel map.
2087  *
2088  * @param cls unused
2089  * @param key unused
2090  * @param value a 'struct TunnelState *'
2091  * @return GNUNET_OK (continue to iterate)
2092  */
2093 static int
2094 cleanup_tunnel (void *cls,
2095                 const GNUNET_HashCode *key,
2096                 void *value)
2097 {
2098   struct TunnelState *ts = value;
2099
2100   free_tunnel_state (ts);
2101   return GNUNET_OK;
2102 }
2103
2104
2105 /**
2106  * Function scheduled as very last function, cleans up after us
2107  *
2108  * @param cls unused
2109  * @param tc unused
2110  */
2111 static void
2112 cleanup (void *cls GNUNET_UNUSED,
2113          const struct GNUNET_SCHEDULER_TaskContext *tc)
2114 {
2115   unsigned int i;
2116
2117   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2118               "VPN is shutting down\n");
2119   if (NULL != destination_map)
2120   {  
2121     GNUNET_CONTAINER_multihashmap_iterate (destination_map,
2122                                            &cleanup_destination,
2123                                            NULL);
2124     GNUNET_CONTAINER_multihashmap_destroy (destination_map);
2125     destination_map = NULL;
2126   }
2127   if (NULL != destination_heap)
2128   {
2129     GNUNET_CONTAINER_heap_destroy (destination_heap);
2130     destination_heap = NULL;
2131   }
2132   if (NULL != tunnel_map)
2133   {  
2134     GNUNET_CONTAINER_multihashmap_iterate (tunnel_map,
2135                                            &cleanup_tunnel,
2136                                            NULL);
2137     GNUNET_CONTAINER_multihashmap_destroy (tunnel_map);
2138     tunnel_map = NULL;
2139   }
2140   if (NULL != tunnel_heap)
2141   {
2142     GNUNET_CONTAINER_heap_destroy (tunnel_heap);
2143     tunnel_heap = NULL;
2144   }
2145   if (NULL != mesh_handle)
2146   {
2147     GNUNET_MESH_disconnect (mesh_handle);
2148     mesh_handle = NULL;
2149   }
2150   if (NULL != helper_handle)
2151     {
2152     GNUNET_HELPER_stop (helper_handle);
2153     helper_handle = NULL;
2154   }
2155   if (NULL != nc)
2156   {
2157     GNUNET_SERVER_notification_context_destroy (nc);
2158     nc = NULL;
2159   }
2160   if (stats != NULL)
2161   {
2162     GNUNET_STATISTICS_destroy (stats, GNUNET_YES);
2163     stats = NULL;
2164   }
2165   for (i=0;i<5;i++)
2166     GNUNET_free_non_null (vpn_argv[i]);
2167 }
2168
2169
2170 /**
2171  * A client disconnected, clean up all references to it.
2172  *
2173  * @param cls the client that disconnected
2174  * @param key unused
2175  * @param value a 'struct TunnelState *'
2176  * @return GNUNET_OK (continue to iterate)
2177  */
2178 static int
2179 cleanup_tunnel_client (void *cls,
2180                        const GNUNET_HashCode *key,
2181                        void *value)
2182 {
2183   struct GNUNET_SERVER_Client *client = cls;
2184   struct TunnelState *ts = value;
2185
2186   if (client == ts->client)
2187   {
2188     GNUNET_SERVER_client_drop (ts->client);
2189     ts->client = NULL;
2190   }
2191   return GNUNET_OK;
2192 }
2193
2194
2195 /**
2196  * A client disconnected, clean up all references to it.
2197  *
2198  * @param cls the client that disconnected
2199  * @param key unused
2200  * @param value a 'struct DestinationEntry *'
2201  * @return GNUNET_OK (continue to iterate)
2202  */
2203 static int
2204 cleanup_destination_client (void *cls,
2205                             const GNUNET_HashCode *key,
2206                             void *value)
2207 {
2208   struct GNUNET_SERVER_Client *client = cls;
2209   struct DestinationEntry *de = value;
2210   struct TunnelState *ts;
2211
2212   if (NULL == (ts = de->ts))
2213     return GNUNET_OK;
2214   if (client == ts->client)
2215   {
2216     GNUNET_SERVER_client_drop (ts->client);
2217     ts->client = NULL;
2218   }
2219   return GNUNET_OK;
2220 }
2221
2222   
2223 /**
2224  * A client has disconnected from us.  If we are currently building
2225  * a tunnel for it, cancel the operation.
2226  *
2227  * @param cls unused
2228  * @param client handle to the client that disconnected
2229  */
2230 static void
2231 client_disconnect (void *cls, struct GNUNET_SERVER_Client *client)
2232 {
2233   if (NULL != tunnel_map)
2234     GNUNET_CONTAINER_multihashmap_iterate (tunnel_map,
2235                                            &cleanup_tunnel_client,
2236                                            client);
2237   if (NULL != destination_map)
2238     GNUNET_CONTAINER_multihashmap_iterate (destination_map,
2239                                            &cleanup_destination_client,
2240                                            client);
2241 }
2242
2243
2244 /**
2245  * Main function that will be run by the scheduler.
2246  *
2247  * @param cls closure
2248  * @param server the initialized server
2249  * @param cfg_ configuration
2250  */
2251 static void
2252 run (void *cls,
2253      struct GNUNET_SERVER_Handle *server,
2254      const struct GNUNET_CONFIGURATION_Handle *cfg_)
2255 {
2256   static const struct GNUNET_SERVER_MessageHandler service_handlers[] = {
2257     /* callback, cls, type, size */
2258     {&service_redirect_to_ip, NULL, GNUNET_MESSAGE_TYPE_VPN_CLIENT_REDIRECT_TO_IP, 0},
2259     {&service_redirect_to_service, NULL, 
2260      GNUNET_MESSAGE_TYPE_VPN_CLIENT_REDIRECT_TO_SERVICE, 
2261      sizeof (struct RedirectToServiceRequestMessage) },
2262     {NULL, NULL, 0, 0}
2263   };
2264   static const struct GNUNET_MESH_MessageHandler mesh_handlers[] = {
2265     {receive_udp_back, GNUNET_MESSAGE_TYPE_VPN_SERVICE_UDP_BACK, 0},
2266     {receive_tcp_back, GNUNET_MESSAGE_TYPE_VPN_SERVICE_TCP_BACK, 0},
2267     {receive_udp_back, GNUNET_MESSAGE_TYPE_VPN_REMOTE_UDP_BACK, 0},
2268     {receive_tcp_back, GNUNET_MESSAGE_TYPE_VPN_REMOTE_TCP_BACK, 0},
2269     {NULL, 0, 0}
2270   };
2271   static const GNUNET_MESH_ApplicationType types[] = {
2272     GNUNET_APPLICATION_TYPE_END
2273   };
2274   char *ifname;
2275   char *ipv6addr;
2276   char *ipv6prefix_s;
2277   char *ipv4addr;
2278   char *ipv4mask;
2279   struct in_addr v4;
2280   struct in6_addr v6;
2281
2282   cfg = cfg_;
2283   stats = GNUNET_STATISTICS_create ("vpn", cfg);
2284   if (GNUNET_OK !=
2285       GNUNET_CONFIGURATION_get_value_number (cfg, "vpn", "MAX_MAPPING",
2286                                              &max_destination_mappings))
2287     max_destination_mappings = 200;
2288   if (GNUNET_OK !=
2289       GNUNET_CONFIGURATION_get_value_number (cfg, "vpn", "MAX_TUNNELS",
2290                                              &max_tunnel_mappings))
2291     max_tunnel_mappings = 200;
2292
2293   destination_map = GNUNET_CONTAINER_multihashmap_create (max_destination_mappings * 2);
2294   destination_heap = GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN);
2295   tunnel_map = GNUNET_CONTAINER_multihashmap_create (max_tunnel_mappings * 2);
2296   tunnel_heap = GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN);
2297
2298
2299   vpn_argv[0] = GNUNET_strdup ("vpn-gnunet");
2300   if (GNUNET_SYSERR ==
2301       GNUNET_CONFIGURATION_get_value_string (cfg, "vpn", "IFNAME", &ifname))
2302   {
2303     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2304                 "No entry 'IFNAME' in configuration!\n");
2305     GNUNET_SCHEDULER_shutdown ();
2306     return;
2307   }
2308   vpn_argv[1] = ifname;
2309   if ( (GNUNET_SYSERR ==
2310         GNUNET_CONFIGURATION_get_value_string (cfg, "vpn", "IPV6ADDR",
2311                                                &ipv6addr) ||
2312         (1 != inet_pton (AF_INET6, ipv6addr, &v6))) )
2313   {
2314     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2315                 "No valid entry 'IPV6ADDR' in configuration!\n");
2316     GNUNET_SCHEDULER_shutdown ();
2317     return;
2318   }
2319   vpn_argv[2] = ipv6addr;
2320   if (GNUNET_SYSERR ==
2321       GNUNET_CONFIGURATION_get_value_string (cfg, "vpn", "IPV6PREFIX",
2322                                              &ipv6prefix_s))
2323   {
2324     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2325                 "No entry 'IPV6PREFIX' in configuration!\n");
2326     GNUNET_SCHEDULER_shutdown ();
2327     return;
2328   }
2329   vpn_argv[3] = ipv6prefix_s;
2330   if ( (GNUNET_OK !=
2331         GNUNET_CONFIGURATION_get_value_number (cfg, "vpn",
2332                                                "IPV6PREFIX",
2333                                                &ipv6prefix)) ||
2334        (ipv6prefix >= 127) )
2335   {
2336     GNUNET_SCHEDULER_shutdown ();
2337     return;
2338   }
2339
2340   if ( (GNUNET_SYSERR ==
2341         GNUNET_CONFIGURATION_get_value_string (cfg, "vpn", "IPV4ADDR",
2342                                                &ipv4addr) ||
2343         (1 != inet_pton (AF_INET, ipv4addr, &v4))) )
2344   {
2345     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2346                 "No valid entry for 'IPV4ADDR' in configuration!\n");
2347     GNUNET_SCHEDULER_shutdown ();
2348     return;
2349   }
2350   vpn_argv[4] = ipv4addr;
2351   if ( (GNUNET_SYSERR ==
2352         GNUNET_CONFIGURATION_get_value_string (cfg, "vpn", "IPV4MASK",
2353                                                &ipv4mask) ||
2354         (1 != inet_pton (AF_INET, ipv4mask, &v4))) )
2355   {
2356     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2357                 "No valid entry 'IPV4MASK' in configuration!\n");
2358     GNUNET_SCHEDULER_shutdown ();
2359     return;
2360   }
2361   vpn_argv[5] = ipv4mask;
2362   vpn_argv[6] = NULL;
2363
2364   mesh_handle =
2365     GNUNET_MESH_connect (cfg_, 42 /* queue length */, NULL, 
2366                          &inbound_tunnel_cb, 
2367                          &tunnel_cleaner, 
2368                          mesh_handlers,
2369                          types);
2370   helper_handle = GNUNET_HELPER_start ("gnunet-helper-vpn", vpn_argv,
2371                                        &message_token, NULL);
2372   nc = GNUNET_SERVER_notification_context_create (server, 1);
2373   GNUNET_SERVER_add_handlers (server, service_handlers);
2374   GNUNET_SERVER_disconnect_notify (server, &client_disconnect, NULL);
2375   GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &cleanup, cls);
2376 }
2377
2378
2379 /**
2380  * The main function of the VPN service.
2381  *
2382  * @param argc number of arguments from the command line
2383  * @param argv command line arguments
2384  * @return 0 ok, 1 on error
2385  */
2386 int
2387 main (int argc, char *const *argv)
2388 {
2389   return (GNUNET_OK ==
2390           GNUNET_SERVICE_run (argc, argv, "vpn", 
2391                               GNUNET_SERVICE_OPTION_NONE,
2392                               &run, NULL)) ? 0 : 1;
2393 }
2394
2395 /* end of gnunet-service-vpn.c */