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