-implement local address allocation
[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  * - define mesh message formats between VPN and EXIT!
31  * - build mesh messages
32  * - parse mesh replies 
33  * - build IP messages from mesh replies
34  * - create secondary mesh tunnels if needed
35  * - fully implement shutdown code
36  * - better message queue management (bounded state, drop oldest/RED?)
37  * - imrpove support for deciding which tunnels to keep and which ones to destroy
38  * - add back ICMP support (especially needed for IPv6)
39  */
40 #include "platform.h"
41 #include "gnunet_util_lib.h"
42 #include "gnunet_common.h"
43 #include "gnunet_protocols.h"
44 #include "gnunet_applications.h"
45 #include "gnunet_mesh_service.h"
46 #include "gnunet_constants.h"
47 #include "tcpip_tun.h"
48 #include "vpn.h"
49
50
51 /**
52  * Information we track for each IP address to determine which tunnel
53  * to send the traffic over to the destination.
54  */
55 struct DestinationEntry
56 {
57   /**
58    * Information about the tunnel to use, NULL if no tunnel
59    * is available right now.
60    */
61   struct GNUNET_MESH_Tunnel *tunnel;
62
63   /**
64    * Entry for this entry in the destination_heap.
65    */
66   struct GNUNET_CONTAINER_HeapNode *heap_node;
67
68   /**
69    * GNUNET_NO if this is a tunnel to an Internet-exit,
70    * GNUNET_YES if this tunnel is to a service.
71    */
72   int is_service;
73
74   /**
75    * Details about the connection (depending on is_service).
76    */
77   union
78   {
79
80     struct
81     {
82       /**
83        * The description of the service (only used for service tunnels).
84        */
85       GNUNET_HashCode service_descriptor;
86
87       /**
88        * Peer offering the service.
89        */
90       struct GNUNET_PeerIdentity target;
91
92     } service_destination;
93
94     struct 
95     {
96   
97       /**
98        * Address family used (AF_INET or AF_INET6).
99        */
100       int af;
101       
102       /**
103        * IP address of the ultimate destination (only used for exit tunnels).
104        */
105       union
106       {
107         /**
108          * Address if af is AF_INET.
109          */
110         struct in_addr v4;
111         
112         /**
113          * Address if af is AF_INET6.
114          */
115         struct in6_addr v6;
116       } ip;
117
118     } exit_destination;
119
120   } details;
121     
122 };
123
124
125 /**
126  * A messages we have in queue for a particular tunnel.
127  */
128 struct TunnelMessageQueueEntry
129 {
130   /**
131    * This is a doubly-linked list.
132    */
133   struct TunnelMessageQueueEntry *next;
134
135   /**
136    * This is a doubly-linked list.
137    */
138   struct TunnelMessageQueueEntry *prev;
139   
140   /**
141    * Number of bytes in 'msg'.
142    */
143   size_t len;
144
145   /**
146    * Message to transmit, allocated at the end of this struct.
147    */
148   const void *msg;
149 };
150
151
152 /**
153  * State we keep for each of our tunnels.
154  */
155 struct TunnelState
156 {
157   /**
158    * Active transmission handle, NULL for none.
159    */
160   struct GNUNET_MESH_TransmitHandle *th;
161
162   /**
163    * Entry for this entry in the tunnel_heap, NULL as long as this
164    * tunnel state is not fully bound.
165    */
166   struct GNUNET_CONTAINER_HeapNode *heap_node;
167
168   /**
169    * Head of list of messages scheduled for transmission.
170    */
171   struct TunnelMessageQueueEntry *head;
172
173   /**
174    * Tail of list of messages scheduled for transmission.
175    */
176   struct TunnelMessageQueueEntry *tail;
177
178   /**
179    * Client that needs to be notified about the tunnel being
180    * up as soon as a peer is connected; NULL for none.
181    */
182   struct GNUNET_SERVER_Client *client;
183
184   /**
185    * ID of the client request that caused us to setup this entry.
186    */ 
187   uint64_t request_id;
188
189   /**
190    * Destination to which this tunnel leads.  Note that
191    * this struct is NOT in the destination_map (but a
192    * local copy) and that the 'heap_node' should always
193    * be NULL.
194    */
195   struct DestinationEntry destination;
196
197   /**
198    * GNUNET_NO if this is a tunnel to an Internet-exit,
199    * GNUNET_YES if this tunnel is to a service.
200    */
201   int is_service;
202
203   /**
204    * Addess family used for this tunnel on the local TUN interface.
205    */
206   int af;
207
208   /**
209    * IP address of the source on our end, initially uninitialized.
210    */
211   union
212   {
213     /**
214      * Address if af is AF_INET.
215      */
216     struct in_addr v4;
217     
218     /**
219      * Address if af is AF_INET6.
220      */
221     struct in6_addr v6;
222
223   } source_ip;
224
225   /**
226    * Destination IP address used by the source on our end (this is the IP
227    * that we pick freely within the VPN's tunnel IP range).
228    */
229   union
230   {
231     /**
232      * Address if af is AF_INET.
233      */
234     struct in_addr v4;
235     
236     /**
237      * Address if af is AF_INET6.
238      */
239     struct in6_addr v6;
240
241   } destination_ip;
242
243   /**
244    * Source port used by the sender on our end; 0 for uninitialized.
245    */
246   uint16_t source_port;
247
248   /**
249    * Destination port used by the sender on our end; 0 for uninitialized.
250    */
251   uint16_t destination_port;
252
253 };
254
255
256 /**
257  * Configuration we use.
258  */
259 static const struct GNUNET_CONFIGURATION_Handle *cfg;
260
261 /**
262  * Handle to the mesh service.
263  */
264 static struct GNUNET_MESH_Handle *mesh_handle;
265
266 /**
267  * Map from IP address to destination information (possibly with a
268  * MESH tunnel handle for fast setup).
269  */
270 static struct GNUNET_CONTAINER_MultiHashMap *destination_map;
271
272 /**
273  * Min-Heap sorted by activity time to expire old mappings.
274  */
275 static struct GNUNET_CONTAINER_Heap *destination_heap;
276
277 /**
278  * Map from source and destination address (IP+port) to connection
279  * information (mostly with the respective MESH tunnel handle).
280  */
281 static struct GNUNET_CONTAINER_MultiHashMap *tunnel_map;
282
283 /**
284  * Min-Heap sorted by activity time to expire old mappings.
285  */
286 static struct GNUNET_CONTAINER_Heap *tunnel_heap;
287
288 /**
289  * The handle to the VPN helper process "gnunet-helper-vpn".
290  */
291 static struct GNUNET_HELPER_Handle *helper_handle;
292
293 /**
294  * Arguments to the vpn helper.
295  */
296 static char *vpn_argv[7];
297
298 /**
299  * Length of the prefix of the VPN's IPv6 network.
300  */
301 static unsigned long long ipv6prefix;
302
303 /**
304  * Notification context for sending replies to clients.
305  */
306 static struct GNUNET_SERVER_NotificationContext *nc;
307
308 /**
309  * If there are more than this number of address-mappings, old ones
310  * will be removed
311  */
312 static unsigned long long max_destination_mappings;
313
314 /**
315  * If there are more than this number of open tunnels, old ones
316  * will be removed
317  */
318 static unsigned long long max_tunnel_mappings;
319
320
321 /**
322  * Compute the key under which we would store an entry in the
323  * destination_map for the given IP address.
324  *
325  * @param af address family (AF_INET or AF_INET6)
326  * @param address IP address, struct in_addr or struct in6_addr
327  * @param key where to store the key
328  */
329 static void
330 get_destination_key_from_ip (int af,
331                              const void *address,
332                              GNUNET_HashCode *key)
333 {
334   switch (af)
335   {
336   case AF_INET:
337     GNUNET_CRYPTO_hash (address,
338                         sizeof (struct in_addr),
339                         key);
340     break;
341   case AF_INET6:
342     GNUNET_CRYPTO_hash (address,
343                         sizeof (struct in6_addr),
344                         key);
345     break;
346   default:
347     GNUNET_assert (0);
348     break;
349   }
350 }
351
352
353 /**
354  * Compute the key under which we would store an entry in the
355  * tunnel_map for the given socket address pair.
356  *
357  * @param af address family (AF_INET or AF_INET6)
358  * @param protocol IPPROTO_TCP or IPPROTO_UDP
359  * @param source_ip sender's source IP, struct in_addr or struct in6_addr
360  * @param source_port sender's source port
361  * @param destination_ip sender's destination IP, struct in_addr or struct in6_addr
362  * @param destination_port sender's destination port
363  * @param key where to store the key
364  */
365 static void
366 get_tunnel_key_from_ips (int af,
367                          uint8_t protocol,
368                          const void *source_ip,
369                          uint16_t source_port,
370                          const void *destination_ip,
371                          uint16_t destination_port,
372                          GNUNET_HashCode *key)
373 {
374   char *off;
375
376   memset (key, 0, sizeof (GNUNET_HashCode));
377   /* the GNUnet hashmap only uses the first sizeof(unsigned int) of the hash,
378      so we put the ports in there (and hope for few collisions) */
379   off = (char*) key;
380   memcpy (off, &source_port, sizeof (uint16_t));
381   off += sizeof (uint16_t);
382   memcpy (off, &destination_port, sizeof (uint16_t));
383   off += sizeof (uint16_t);
384   switch (af)
385   {
386   case AF_INET:
387     memcpy (off, source_ip, sizeof (struct in_addr));
388     off += sizeof (struct in_addr);
389     memcpy (off, destination_ip, sizeof (struct in_addr));
390     off += sizeof (struct in_addr);
391     break;
392   case AF_INET6:
393     memcpy (off, source_ip, sizeof (struct in6_addr));
394     off += sizeof (struct in6_addr);
395     memcpy (off, destination_ip, sizeof (struct in6_addr));
396     off += sizeof (struct in6_addr);
397     break;
398   default:
399     GNUNET_assert (0);
400     break;
401   }
402   memcpy (off, &protocol, sizeof (uint8_t));
403   off += sizeof (uint8_t);  
404 }
405
406
407 /**
408  * Send a message from the message queue via mesh.
409  *
410  * @param cls the 'struct TunnelState' with the message queue
411  * @param size number of bytes available in buf
412  * @param buf where to copy the message
413  * @return number of bytes copied to buf
414  */
415 static size_t
416 send_to_peer_notify_callback (void *cls, size_t size, void *buf)
417 {
418   struct TunnelState *ts = cls;
419   struct TunnelMessageQueueEntry *tnq;
420   size_t ret;
421
422   ts->th = NULL;
423   if (NULL == buf)
424     return 0;
425   tnq = ts->head;
426   GNUNET_assert (NULL != tnq);
427   GNUNET_assert (size >= tnq->len);
428   GNUNET_CONTAINER_DLL_remove (ts->head,
429                                ts->tail,
430                                tnq);
431   memcpy (buf, tnq->msg, tnq->len);
432   ret = tnq->len;
433   GNUNET_free (tnq);
434   if (NULL != (tnq = ts->head))
435     ts->th = GNUNET_MESH_notify_transmit_ready (ts->destination.tunnel, 
436                                                 GNUNET_NO /* cork */, 
437                                                 42 /* priority */,
438                                                 GNUNET_TIME_UNIT_FOREVER_REL,
439                                                 NULL, 
440                                                 tnq->len,
441                                                 &send_to_peer_notify_callback,
442                                                 ts);
443   return ret;
444 }
445
446
447 /**
448  * Add the given message to the given tunnel and
449  * trigger the transmission process.
450  *
451  * @param tnq message to queue
452  * @param ts tunnel to queue the message for
453  */
454 static void
455 send_to_tunnel (struct TunnelMessageQueueEntry *tnq,
456                    struct TunnelState *ts)
457 {
458   GNUNET_CONTAINER_DLL_insert_tail (ts->head,
459                                     ts->tail,
460                                     tnq);
461   if (NULL == ts->th)
462     ts->th = GNUNET_MESH_notify_transmit_ready (ts->destination.tunnel, 
463                                                 GNUNET_NO /* cork */,
464                                                 42 /* priority */,
465                                                 GNUNET_TIME_UNIT_FOREVER_REL,
466                                                 NULL, 
467                                                 tnq->len,
468                                                 &send_to_peer_notify_callback,
469                                                 ts);
470 }
471
472
473 /**
474  * Route a packet via mesh to the given destination.  
475  *
476  * @param destination description of the destination
477  * @param af address family on this end (AF_INET or AF_INET6)
478  * @param protocol IPPROTO_TCP or IPPROTO_UDP
479  * @param source_ip source IP used by the sender (struct in_addr or struct in6_addr)
480  * @param destination_ip destination IP used by the sender (struct in_addr or struct in6_addr)
481  * @param payload payload of the packet after the IP header
482  * @param payload_length number of bytes in payload
483  */
484 static void
485 route_packet (struct DestinationEntry *destination,
486               int af,
487               uint8_t protocol,
488               const void *source_ip,
489               const void *destination_ip,
490               const void *payload,
491               size_t payload_length)
492 {
493   GNUNET_HashCode key;
494   struct TunnelState *ts;
495   struct TunnelMessageQueueEntry *tnq;
496                    
497   switch (protocol)
498   {
499   case IPPROTO_UDP:
500     {
501       const struct udp_packet *udp;
502
503       if (payload_length < sizeof (struct udp_packet))
504       {
505         /* blame kernel? */
506         GNUNET_break (0);
507         return;
508       }
509       udp = payload;
510       get_tunnel_key_from_ips (af,
511                                IPPROTO_UDP,
512                                source_ip,
513                                ntohs (udp->spt),
514                                destination_ip,
515                                ntohs (udp->dpt),
516                                &key);
517     }
518     break;
519   case IPPROTO_TCP:
520     {
521       const struct tcp_packet *tcp;
522
523       if (payload_length < sizeof (struct tcp_packet))
524       {
525         /* blame kernel? */
526         GNUNET_break (0);
527         return;
528       }
529       tcp = payload;
530       get_tunnel_key_from_ips (af,
531                                IPPROTO_TCP,
532                                source_ip,
533                                ntohs (tcp->spt),
534                                destination_ip,
535                                ntohs (tcp->dpt),
536                                &key);
537     }
538     break;
539   default:
540     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
541                 _("Protocol %u not supported, dropping\n"),
542                 (unsigned int) protocol);
543     return;
544   }
545
546   /* find tunnel */
547   ts = GNUNET_CONTAINER_multihashmap_get (tunnel_map,
548                                           &key);
549   if (NULL == ts)
550   {
551     /* create new tunnel */
552     // FIXME: create tunnel!
553 #if 0
554             *cls =
555                 GNUNET_MESH_tunnel_create (mesh_handle,
556                                            initialize_tunnel_state (16, NULL),
557                                            &send_pkt_to_peer, NULL, cls);
558
559             GNUNET_MESH_peer_request_connect_add (*cls,
560                                                   (struct GNUNET_PeerIdentity *)
561                                                   &me->desc);
562             me->tunnel = *cls;
563 #endif
564   }
565   
566   /* send via tunnel */
567   switch (protocol)
568   {
569   case IPPROTO_UDP:
570     if (destination->is_service)
571     {
572       tnq = GNUNET_malloc (sizeof (struct TunnelMessageQueueEntry) + 42);
573       // FIXME: build message!
574     }
575     else
576     {
577       tnq = GNUNET_malloc (sizeof (struct TunnelMessageQueueEntry) + 42);
578       // FIXME: build message!
579     }
580     break;
581   case IPPROTO_TCP:
582     if (destination->is_service)
583     {
584       tnq = GNUNET_malloc (sizeof (struct TunnelMessageQueueEntry) + 42);
585       // FIXME: build message!
586     }
587     else
588     {
589       tnq = GNUNET_malloc (sizeof (struct TunnelMessageQueueEntry) + 42);
590       // FIXME: build message!
591     }
592     break;
593   default:
594     /* not supported above, how can we get here !? */
595     GNUNET_assert (0);
596     break;
597   }
598   send_to_tunnel (tnq, ts);
599 }
600
601
602
603 /**
604  * Receive packets from the helper-process (someone send to the local
605  * virtual tunnel interface).  Find the destination mapping, and if it
606  * exists, identify the correct MESH tunnel (or possibly create it)
607  * and forward the packet.
608  *
609  * @param cls closure, NULL
610  * @param client NULL
611  * @param message message we got from the client (VPN tunnel interface)
612  */
613 static void
614 message_token (void *cls GNUNET_UNUSED, void *client GNUNET_UNUSED,
615                const struct GNUNET_MessageHeader *message)
616 {
617   const struct tun_header *tun;
618   size_t mlen;
619   GNUNET_HashCode key;
620   struct DestinationEntry *de;
621
622   mlen = ntohs (message->size);
623   if ( (ntohs (message->type) != GNUNET_MESSAGE_TYPE_VPN_HELPER) ||
624        (mlen < sizeof (struct GNUNET_MessageHeader) + sizeof (struct tun_header)) )
625   {
626     GNUNET_break (0);
627     return;
628   }
629   tun = (const struct tun_header *) &message[1];
630   mlen -= (sizeof (struct GNUNET_MessageHeader) + sizeof (struct tun_header));
631   switch (ntohs (tun->proto))
632   {
633   case ETH_P_IPV6:
634     {
635       const struct ip6_header *pkt6;
636       
637       if (mlen < sizeof (struct ip6_header))
638       {
639         /* blame kernel */
640         GNUNET_break (0);
641         return;
642       }
643       pkt6 = (const struct ip6_header *) &tun[1];
644       get_destination_key_from_ip (AF_INET6,
645                                    &pkt6->destination_address,
646                                    &key);
647       de = GNUNET_CONTAINER_multihashmap_get (destination_map, &key);
648       /* FIXME: do we need to guard against hash collision? */
649       if (NULL == de)
650       {
651         char buf[INET6_ADDRSTRLEN];
652         
653         GNUNET_log (GNUNET_ERROR_TYPE_INFO,
654                     _("Packet received for unmapped destination `%s' (dropping it)\n"),
655                     inet_ntop (AF_INET6,
656                                &pkt6->destination_address,
657                                buf,
658                                sizeof (buf)));
659         return;
660       }
661       route_packet (de,
662                     AF_INET6,
663                     pkt6->next_header,
664                     &pkt6->source_address,                  
665                     &pkt6->destination_address,             
666                     &pkt6[1],
667                     mlen - sizeof (struct ip6_header));
668     }
669     break;
670   case ETH_P_IPV4:
671     {
672       struct ip4_header *pkt4;
673
674       if (mlen < sizeof (struct ip4_header))
675       {
676         /* blame kernel */
677         GNUNET_break (0);
678         return;
679       }
680       pkt4 = (struct ip4_header *) &tun[1];
681       get_destination_key_from_ip (AF_INET,
682                                    &pkt4->destination_address,
683                                    &key);
684       de = GNUNET_CONTAINER_multihashmap_get (destination_map, &key);
685       /* FIXME: do we need to guard against hash collision? */
686       if (NULL == de)
687       {
688         char buf[INET_ADDRSTRLEN];
689         
690         GNUNET_log (GNUNET_ERROR_TYPE_INFO,
691                     _("Packet received for unmapped destination `%s' (dropping it)\n"),
692                     inet_ntop (AF_INET,
693                                &pkt4->destination_address,
694                                buf,
695                                sizeof (buf)));
696         return;
697       }
698       if (pkt4->header_length * 4 != sizeof (struct ip4_header))
699       {
700         GNUNET_log (GNUNET_ERROR_TYPE_INFO,
701                     _("Received IPv4 packet with options (dropping it)\n"));                
702         return;
703       }
704       route_packet (de,
705                     AF_INET,
706                     pkt4->protocol,
707                     &pkt4->source_address,                  
708                     &pkt4->destination_address,             
709                     &pkt4[1],
710                     mlen - sizeof (struct ip4_header));
711     }
712     break;
713   default:
714     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
715                 _("Received packet of unknown protocol %d from TUN (dropping it)\n"),
716                 (unsigned int) ntohs (tun->proto));
717     break;
718   }
719 }
720
721
722 /**
723  * We got a UDP packet back from the MESH tunnel.  Pass it on to the
724  * local virtual interface via the helper.
725  *
726  * @param cls closure, NULL
727  * @param tunnel connection to the other end
728  * @param tunnel_ctx pointer to our 'struct TunnelState *'
729  * @param sender who sent the message
730  * @param message the actual message
731  * @param atsi performance data for the connection
732  * @return GNUNET_OK to keep the connection open,
733  *         GNUNET_SYSERR to close it (signal serious error)
734  */ 
735 static int
736 receive_udp_back (void *cls GNUNET_UNUSED, struct GNUNET_MESH_Tunnel *tunnel,
737                   void **tunnel_ctx, const struct GNUNET_PeerIdentity *sender,
738                   const struct GNUNET_MessageHeader *message,
739                   const struct GNUNET_ATS_Information *atsi GNUNET_UNUSED)
740 {
741   // FIXME: parse message, build IP packet, give to TUN!
742 #if 0
743   GNUNET_HashCode *desc = (GNUNET_HashCode *) (message + 1);
744   struct remote_addr *s = (struct remote_addr *) desc;
745   struct udp_pkt *pkt = (struct udp_pkt *) (desc + 1);
746   const struct GNUNET_PeerIdentity *other = sender;
747   struct TunnelState *ts = *tunnel_ctx;
748
749   if (16 == ts->addrlen)
750   {
751     size_t size =
752         sizeof (struct ip6_udp) + ntohs (pkt->len) - 1 -
753         sizeof (struct udp_pkt);
754
755     struct ip6_udp *pkt6 = alloca (size);
756
757     GNUNET_assert (pkt6 != NULL);
758
759     if (ntohs (message->type) == GNUNET_MESSAGE_TYPE_VPN_SERVICE_UDP_BACK)
760       new_ip6addr (&pkt6->ip6_hdr.sadr, &other->hashPubKey, desc);
761     else
762       new_ip6addr_remote (&pkt6->ip6_hdr.sadr, s->addr, s->addrlen);
763
764     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
765                 "Relaying calc:%d gnu:%d udp:%d bytes!\n", size,
766                 ntohs (message->size), ntohs (pkt->len));
767
768     pkt6->shdr.type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
769     pkt6->shdr.size = htons (size);
770
771     pkt6->tun.flags = 0;
772     pkt6->tun.type = htons (0x86dd);
773
774     pkt6->ip6_hdr.version = 6;
775     pkt6->ip6_hdr.tclass_h = 0;
776     pkt6->ip6_hdr.tclass_l = 0;
777     pkt6->ip6_hdr.flowlbl = 0;
778     pkt6->ip6_hdr.paylgth = pkt->len;
779     pkt6->ip6_hdr.nxthdr = IPPROTO_UDP;
780     pkt6->ip6_hdr.hoplmt = 0xff;
781
782     {
783       char *ipv6addr;
784
785       GNUNET_assert (GNUNET_OK ==
786                      GNUNET_CONFIGURATION_get_value_string (cfg, "vpn",
787                                                             "IPV6ADDR",
788                                                             &ipv6addr));
789       inet_pton (AF_INET6, ipv6addr, &pkt6->ip6_hdr.dadr);
790       GNUNET_free (ipv6addr);
791     }
792     memcpy (&pkt6->udp_hdr, pkt, ntohs (pkt->len));
793
794     GNUNET_HashCode *key = address6_mapping_exists (&pkt6->ip6_hdr.sadr);
795
796     GNUNET_assert (key != NULL);
797
798     struct map_entry *me = GNUNET_CONTAINER_multihashmap_get (hashmap, key);
799
800     GNUNET_CONTAINER_heap_update_cost (heap, me->heap_node,
801                                        GNUNET_TIME_absolute_get ().abs_value);
802
803     GNUNET_free (key);
804
805     GNUNET_assert (me != NULL);
806
807     pkt6->udp_hdr.crc = 0;
808     uint32_t sum = 0;
809
810     sum =
811         GNUNET_CRYPTO_crc16_step (sum, (uint16_t *) & pkt6->ip6_hdr.sadr, 16);
812     sum =
813         GNUNET_CRYPTO_crc16_step (sum, (uint16_t *) & pkt6->ip6_hdr.dadr, 16);
814     uint32_t tmp = (pkt6->udp_hdr.len & 0xffff);
815
816     sum = GNUNET_CRYPTO_crc16_step (sum, (uint16_t *) & tmp, 4);
817     tmp = htons (((pkt6->ip6_hdr.nxthdr & 0x00ff)));
818     sum = GNUNET_CRYPTO_crc16_step (sum, (uint16_t *) & tmp, 4);
819
820     sum =
821         GNUNET_CRYPTO_crc16_step (sum, (uint16_t *) & pkt6->udp_hdr,
822                                    ntohs (pkt->len));
823     pkt6->udp_hdr.crc = GNUNET_CRYPTO_crc16_finish (sum);
824     
825     (void) GNUNET_HELPER_send (helper_handle,
826                                &pkt6->shdr,
827                                GNUNET_YES,
828                                NULL, NULL);
829   }
830   else
831   {
832     size_t size =
833         sizeof (struct ip_udp) + ntohs (pkt->len) - 1 - sizeof (struct udp_pkt);
834
835     struct ip_udp *pkt4 = alloca (size);
836
837     GNUNET_assert (pkt4 != NULL);
838
839     GNUNET_assert (ntohs (message->type) ==
840                    GNUNET_MESSAGE_TYPE_VPN_REMOTE_UDP_BACK);
841     uint32_t sadr;
842
843     new_ip4addr_remote ((unsigned char *) &sadr, s->addr, s->addrlen);
844     pkt4->ip_hdr.sadr.s_addr = sadr;
845
846     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
847                 "Relaying calc:%d gnu:%d udp:%d bytes!\n", size,
848                 ntohs (message->size), ntohs (pkt->len));
849
850     pkt4->shdr.type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
851     pkt4->shdr.size = htons (size);
852
853     pkt4->tun.flags = 0;
854     pkt4->tun.type = htons (0x0800);
855
856     pkt4->ip_hdr.version = 4;
857     pkt4->ip_hdr.hdr_lngth = 5;
858     pkt4->ip_hdr.diff_serv = 0;
859     pkt4->ip_hdr.tot_lngth = htons (20 + ntohs (pkt->len));
860     pkt4->ip_hdr.ident = 0;
861     pkt4->ip_hdr.flags = 0;
862     pkt4->ip_hdr.frag_off = 0;
863     pkt4->ip_hdr.ttl = 255;
864     pkt4->ip_hdr.proto = IPPROTO_UDP;
865     pkt4->ip_hdr.chks = 0;      /* Will be calculated later */
866
867     {
868       char *ipv4addr;
869       uint32_t dadr;
870
871       GNUNET_assert (GNUNET_OK ==
872                      GNUNET_CONFIGURATION_get_value_string (cfg, "vpn",
873                                                             "IPV4ADDR",
874                                                             &ipv4addr));
875       inet_pton (AF_INET, ipv4addr, &dadr);
876       GNUNET_free (ipv4addr);
877       pkt4->ip_hdr.dadr.s_addr = dadr;
878     }
879     memcpy (&pkt4->udp_hdr, pkt, ntohs (pkt->len));
880
881     GNUNET_HashCode *key = address4_mapping_exists (pkt4->ip_hdr.sadr.s_addr);
882
883     GNUNET_assert (key != NULL);
884
885     struct map_entry *me = GNUNET_CONTAINER_multihashmap_get (hashmap, key);
886
887     GNUNET_CONTAINER_heap_update_cost (heap, me->heap_node,
888                                        GNUNET_TIME_absolute_get ().abs_value);
889
890     GNUNET_free (key);
891
892     GNUNET_assert (me != NULL);
893
894     pkt4->udp_hdr.crc = 0;      /* Optional for IPv4 */
895
896     pkt4->ip_hdr.chks =
897         GNUNET_CRYPTO_crc16_n ((uint16_t *) & pkt4->ip_hdr, 5 * 4);
898
899     (void) GNUNET_HELPER_send (helper_handle,
900                                &pkt4->shdr,
901                                GNUNET_YES,
902                                NULL, NULL);
903   }
904 #endif
905   return GNUNET_OK;
906 }
907
908
909 /**
910  * We got a TCP packet back from the MESH tunnel.  Pass it on to the
911  * local virtual interface via the helper.
912  *
913  * @param cls closure, NULL
914  * @param tunnel connection to the other end
915  * @param tunnel_ctx pointer to our 'struct TunnelState *'
916  * @param sender who sent the message
917  * @param message the actual message
918  * @param atsi performance data for the connection
919  * @return GNUNET_OK to keep the connection open,
920  *         GNUNET_SYSERR to close it (signal serious error)
921  */ 
922 static int
923 receive_tcp_back (void *cls GNUNET_UNUSED, struct GNUNET_MESH_Tunnel *tunnel,
924                   void **tunnel_ctx,
925                   const struct GNUNET_PeerIdentity *sender GNUNET_UNUSED,
926                   const struct GNUNET_MessageHeader *message,
927                   const struct GNUNET_ATS_Information *atsi GNUNET_UNUSED)
928 {
929   // FIXME: parse message, build IP packet, give to TUN!
930 #if 0
931   GNUNET_HashCode *desc = (GNUNET_HashCode *) (message + 1);
932   struct remote_addr *s = (struct remote_addr *) desc;
933   struct tcp_pkt *pkt = (struct tcp_pkt *) (desc + 1);
934   const struct GNUNET_PeerIdentity *other = sender;
935   struct TunnelState *ts = *tunnel_ctx;
936
937   size_t pktlen =
938       ntohs (message->size) - sizeof (struct GNUNET_MessageHeader) -
939       sizeof (GNUNET_HashCode);
940
941   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
942               "Received TCP-Packet back, addrlen = %d\n", s->addrlen);
943
944   if (ntohs (message->type) == GNUNET_MESSAGE_TYPE_VPN_SERVICE_TCP_BACK ||
945       ts->addrlen == 16)
946   {
947     size_t size = pktlen + sizeof (struct ip6_tcp) - 1;
948
949     struct ip6_tcp *pkt6 = alloca (size);
950
951     memset (pkt6, 0, size);
952
953     GNUNET_assert (pkt6 != NULL);
954
955     if (ntohs (message->type) == GNUNET_MESSAGE_TYPE_VPN_SERVICE_TCP_BACK)
956       new_ip6addr (&pkt6->ip6_hdr.sadr, &other->hashPubKey, desc);
957     else
958       new_ip6addr_remote (&pkt6->ip6_hdr.sadr, s->addr, s->addrlen);
959
960     pkt6->shdr.type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
961     pkt6->shdr.size = htons (size);
962
963     pkt6->tun.flags = 0;
964     pkt6->tun.type = htons (0x86dd);
965
966     pkt6->ip6_hdr.version = 6;
967     pkt6->ip6_hdr.tclass_h = 0;
968     pkt6->ip6_hdr.tclass_l = 0;
969     pkt6->ip6_hdr.flowlbl = 0;
970     pkt6->ip6_hdr.paylgth = htons (pktlen);
971     pkt6->ip6_hdr.nxthdr = IPPROTO_TCP;
972     pkt6->ip6_hdr.hoplmt = 0xff;
973
974     {
975       char *ipv6addr;
976
977       GNUNET_assert (GNUNET_OK ==
978                      GNUNET_CONFIGURATION_get_value_string (cfg, "vpn",
979                                                             "IPV6ADDR",
980                                                             &ipv6addr));
981       inet_pton (AF_INET6, ipv6addr, &pkt6->ip6_hdr.dadr);
982       GNUNET_free (ipv6addr);
983     }
984     memcpy (&pkt6->tcp_hdr, pkt, pktlen);
985
986     GNUNET_HashCode *key = address6_mapping_exists (&pkt6->ip6_hdr.sadr);
987
988     GNUNET_assert (key != NULL);
989
990     struct map_entry *me = GNUNET_CONTAINER_multihashmap_get (hashmap, key);
991
992     GNUNET_CONTAINER_heap_update_cost (heap, me->heap_node,
993                                        GNUNET_TIME_absolute_get ().abs_value);
994
995     GNUNET_free (key);
996
997     GNUNET_assert (me != NULL);
998
999     pkt6->tcp_hdr.crc = 0;
1000     uint32_t sum = 0;
1001     uint32_t tmp;
1002
1003     sum =
1004         GNUNET_CRYPTO_crc16_step (sum, (uint16_t *) & pkt6->ip6_hdr.sadr, 16);
1005     sum =
1006         GNUNET_CRYPTO_crc16_step (sum, (uint16_t *) & pkt6->ip6_hdr.dadr, 16);
1007     tmp = htonl (pktlen);
1008     sum = GNUNET_CRYPTO_crc16_step (sum, (uint16_t *) & tmp, 4);
1009     tmp = htonl (((pkt6->ip6_hdr.nxthdr & 0x000000ff)));
1010     sum = GNUNET_CRYPTO_crc16_step (sum, (uint16_t *) & tmp, 4);
1011
1012     sum =
1013         GNUNET_CRYPTO_crc16_step (sum, (uint16_t *) & pkt6->tcp_hdr,
1014                                    ntohs (pkt6->ip6_hdr.paylgth));
1015     pkt6->tcp_hdr.crc = GNUNET_CRYPTO_crc16_finish (sum);
1016
1017     (void) GNUNET_HELPER_send (helper_handle,
1018                                &pkt6->shdr,
1019                                GNUNET_YES,
1020                                NULL, NULL);
1021   }
1022   else
1023   {
1024     size_t size = pktlen + sizeof (struct ip_tcp) - 1;
1025
1026     struct ip_tcp *pkt4 = alloca (size);
1027
1028     GNUNET_assert (pkt4 != NULL);
1029     memset (pkt4, 0, size);
1030
1031     GNUNET_assert (ntohs (message->type) ==
1032                    GNUNET_MESSAGE_TYPE_VPN_REMOTE_TCP_BACK);
1033     uint32_t sadr;
1034
1035     new_ip4addr_remote ((unsigned char *) &sadr, s->addr, s->addrlen);
1036     pkt4->ip_hdr.sadr.s_addr = sadr;
1037
1038     pkt4->shdr.type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
1039     pkt4->shdr.size = htons (size);
1040
1041     pkt4->tun.flags = 0;
1042     pkt4->tun.type = htons (0x0800);
1043
1044     pkt4->ip_hdr.version = 4;
1045     pkt4->ip_hdr.hdr_lngth = 5;
1046     pkt4->ip_hdr.diff_serv = 0;
1047     pkt4->ip_hdr.tot_lngth = htons (20 + pktlen);
1048     pkt4->ip_hdr.ident = 0;
1049     pkt4->ip_hdr.flags = 0;
1050     pkt4->ip_hdr.frag_off = 0;
1051     pkt4->ip_hdr.ttl = 255;
1052     pkt4->ip_hdr.proto = IPPROTO_TCP;
1053     pkt4->ip_hdr.chks = 0;      /* Will be calculated later */
1054
1055     {
1056       char *ipv4addr;
1057       uint32_t dadr;
1058
1059       GNUNET_assert (GNUNET_OK ==
1060                      GNUNET_CONFIGURATION_get_value_string (cfg, "vpn",
1061                                                             "IPV4ADDR",
1062                                                             &ipv4addr));
1063       inet_pton (AF_INET, ipv4addr, &dadr);
1064       GNUNET_free (ipv4addr);
1065       pkt4->ip_hdr.dadr.s_addr = dadr;
1066     }
1067
1068     memcpy (&pkt4->tcp_hdr, pkt, pktlen);
1069
1070     GNUNET_HashCode *key = address4_mapping_exists (pkt4->ip_hdr.sadr.s_addr);
1071
1072     GNUNET_assert (key != NULL);
1073
1074     struct map_entry *me = GNUNET_CONTAINER_multihashmap_get (hashmap, key);
1075
1076     GNUNET_CONTAINER_heap_update_cost (heap, me->heap_node,
1077                                        GNUNET_TIME_absolute_get ().abs_value);
1078
1079     GNUNET_free (key);
1080
1081     GNUNET_assert (me != NULL);
1082     pkt4->tcp_hdr.crc = 0;
1083     uint32_t sum = 0;
1084     uint32_t tmp;
1085
1086     sum = GNUNET_CRYPTO_crc16_step (sum, (uint16_t *) &pkt4->ip_hdr.sadr, 4);
1087     sum = GNUNET_CRYPTO_crc16_step (sum, (uint16_t *) &pkt4->ip_hdr.dadr, 4);
1088
1089     tmp = (0x06 << 16) | (0xffff & pktlen);     // 0x06 for TCP?
1090
1091     tmp = htonl (tmp);
1092
1093     sum = GNUNET_CRYPTO_crc16_step (sum, (uint16_t *) & tmp, 4);
1094
1095     sum = GNUNET_CRYPTO_crc16_step (sum, (uint16_t *) & pkt4->tcp_hdr, pktlen);
1096     pkt4->tcp_hdr.crc = GNUNET_CRYPTO_crc16_finish (sum);
1097
1098     pkt4->ip_hdr.chks =
1099         GNUNET_CRYPTO_crc16_n ((uint16_t *) & pkt4->ip_hdr, 5 * 4);
1100
1101     (void) GNUNET_HELPER_send (helper_handle,
1102                                &pkt4->shdr,
1103                                GNUNET_YES,
1104                                NULL, NULL);
1105
1106   }
1107 #endif
1108   return GNUNET_OK;
1109 }
1110
1111
1112 /**
1113  * Allocate an IPv4 address from the range of the tunnel
1114  * for a new redirection.
1115  *
1116  * @param v4 where to store the address
1117  * @return GNUNET_OK on success,
1118  *         GNUNET_SYSERR on error
1119  */
1120 static int
1121 allocate_v4_address (struct in_addr *v4)
1122 {
1123   const char *ipv4addr = vpn_argv[4];
1124   const char *ipv4mask = vpn_argv[5];
1125   struct in_addr addr;
1126   struct in_addr mask;
1127   struct in_addr rnd;
1128   GNUNET_HashCode key;
1129   unsigned int tries;
1130
1131   GNUNET_assert (1 == inet_pton (AF_INET, ipv4addr, &addr));
1132   GNUNET_assert (1 == inet_pton (AF_INET, ipv4mask, &mask));           
1133   /* Given 192.168.0.1/255.255.0.0, we want a mask 
1134      of '192.168.255.255', thus:  */
1135   mask.s_addr = addr.s_addr | ~mask.s_addr;  
1136   tries = 0;
1137   do
1138     {
1139       tries++;
1140       if (tries > 16)
1141       {
1142         GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1143                     _("Failed to find unallocated IPv4 address in VPN's range\n"));
1144         return GNUNET_SYSERR;
1145       }
1146       /* Pick random IPv4 address within the subnet, except 'addr' or 'mask' itself */
1147       rnd.s_addr = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, 
1148                                              UINT32_MAX);       
1149       v4->s_addr = (addr.s_addr | rnd.s_addr) & mask.s_addr;          
1150       get_destination_key_from_ip (AF_INET,
1151                                    v4,
1152                                    &key);
1153     }
1154   while ( (GNUNET_YES ==
1155            GNUNET_CONTAINER_multihashmap_contains (destination_map,
1156                                                    &key)) ||
1157           (v4->s_addr == addr.s_addr) ||
1158           (v4->s_addr == mask.s_addr) );
1159   return GNUNET_OK;
1160 }
1161
1162
1163 /**
1164  * Allocate an IPv6 address from the range of the tunnel
1165  * for a new redirection.
1166  *
1167  * @param v6 where to store the address
1168  * @return GNUNET_OK on success,
1169  *         GNUNET_SYSERR on error
1170  */
1171 static int
1172 allocate_v6_address (struct in6_addr *v6)
1173 {
1174   const char *ipv6addr = vpn_argv[2];
1175   struct in6_addr addr;
1176   struct in6_addr mask;
1177   struct in6_addr rnd;
1178   int i;
1179   GNUNET_HashCode key;
1180   unsigned int tries;
1181
1182   GNUNET_assert (1 == inet_pton (AF_INET6, ipv6addr, &addr));
1183   GNUNET_assert (ipv6prefix < 128);
1184   /* Given ABCD::/96, we want a mask of 'ABCD::FFFF:FFFF,
1185      thus: */
1186   mask = addr;
1187   for (i=127;i>=128-ipv6prefix;i--)
1188     mask.s6_addr[i / 8] |= (1 << (i % 8));
1189   
1190   /* Pick random IPv6 address within the subnet, except 'addr' or 'mask' itself */
1191   tries = 0;
1192   do
1193     {
1194       tries++;
1195       if (tries > 16)
1196         {
1197           GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1198                       _("Failed to find unallocated IPv6 address in VPN's range\n"));
1199           return GNUNET_SYSERR;
1200
1201         }
1202       for (i=0;i<16;i++)
1203         {
1204           rnd.s6_addr[i] = (unsigned char) GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, 
1205                                                                      256);
1206           v6->s6_addr[i]
1207             = (addr.s6_addr[i] | rnd.s6_addr[i]) & mask.s6_addr[i];
1208         }
1209       get_destination_key_from_ip (AF_INET6,
1210                                    v6,
1211                                    &key);
1212     }
1213   while ( (GNUNET_YES ==
1214            GNUNET_CONTAINER_multihashmap_contains (destination_map,
1215                                                    &key)) ||
1216           (0 == memcmp (v6,
1217                         &addr,
1218                         sizeof (struct in6_addr))) ||
1219           (0 == memcmp (v6,
1220                         &mask,
1221                         sizeof (struct in6_addr))) );
1222   return GNUNET_OK;
1223 }
1224
1225
1226 /**
1227  * Notify the client about the result of its request.
1228  *
1229  * @param client client to notify
1230  * @param request_id original request ID to include in response
1231  * @param result_af resulting address family
1232  * @param addr resulting IP address
1233  */
1234 static void
1235 send_client_reply (struct GNUNET_SERVER_Client *client,
1236                    uint64_t request_id,
1237                    int result_af,
1238                    const void *addr)
1239 {
1240   char buf[sizeof (struct RedirectToIpResponseMessage) + sizeof (struct in6_addr)];
1241   struct RedirectToIpResponseMessage *res;
1242   size_t rlen;
1243
1244   switch (result_af)
1245   {
1246   case AF_INET:
1247     rlen = sizeof (struct in_addr);    
1248     break;
1249   case AF_INET6:
1250     rlen = sizeof (struct in6_addr);
1251     break;
1252   case AF_UNSPEC:
1253     rlen = 0;
1254     break;
1255   default:
1256     GNUNET_assert (0);
1257     return;
1258   }
1259   res = (struct RedirectToIpResponseMessage *) buf;
1260   res->header.size = htons (sizeof (struct RedirectToIpResponseMessage) + rlen);
1261   res->header.type = htons (GNUNET_MESSAGE_TYPE_VPN_CLIENT_USE_IP);
1262   res->result_af = htonl (result_af);
1263   res->request_id = request_id;
1264   memcpy (&res[1], addr, rlen);
1265   GNUNET_SERVER_notification_context_add (nc, client);
1266   GNUNET_SERVER_notification_context_unicast (nc,
1267                                               client,
1268                                               &res->header,
1269                                               GNUNET_NO);
1270 }
1271
1272
1273 /**
1274  * Method called whenever a peer has disconnected from the tunnel.
1275  *
1276  * @param cls closure
1277  * @param peer peer identity the tunnel stopped working with
1278  */
1279 static void
1280 tunnel_peer_disconnect_handler (void *cls,
1281                                 const struct
1282                                 GNUNET_PeerIdentity * peer)
1283 {
1284   /* FIXME: should we do anything here? 
1285    - stop transmitting to the tunnel (start queueing?)
1286    - possibly destroy the tunnel entirely (unless service tunnel?) 
1287   */
1288 }
1289
1290
1291 /**
1292  * Method called whenever a peer has connected to the tunnel.  Notifies
1293  * the waiting client that the tunnel is now up.
1294  *
1295  * @param cls closure
1296  * @param peer peer identity the tunnel was created to, NULL on timeout
1297  * @param atsi performance data for the connection
1298  */
1299 static void
1300 tunnel_peer_connect_handler (void *cls,
1301                              const struct GNUNET_PeerIdentity
1302                              * peer,
1303                              const struct
1304                              GNUNET_ATS_Information * atsi)
1305 {
1306   struct TunnelState *ts = cls;
1307
1308   if (NULL == ts->client)
1309     return; /* nothing to do */
1310   send_client_reply (ts->client,
1311                      ts->request_id,
1312                      ts->af,
1313                      &ts->destination_ip);
1314   GNUNET_SERVER_client_drop (ts->client);
1315   ts->client = NULL;
1316 }
1317
1318
1319 /**
1320  * A client asks us to setup a redirection via some exit
1321  * node to a particular IP.  Setup the redirection and
1322  * give the client the allocated IP.
1323  *
1324  * @param cls unused
1325  * @param client requesting client
1326  * @param message redirection request (a 'struct RedirectToIpRequestMessage')
1327  */
1328 static void
1329 service_redirect_to_ip (void *cls GNUNET_UNUSED, struct GNUNET_SERVER_Client *client,
1330                         const struct GNUNET_MessageHeader *message)
1331 {
1332   size_t mlen;
1333   size_t alen;
1334   const struct RedirectToIpRequestMessage *msg;
1335   int addr_af;
1336   int result_af;
1337   struct in_addr v4;
1338   struct in6_addr v6;
1339   void *addr;
1340   struct DestinationEntry *de;
1341   GNUNET_HashCode key;
1342   struct TunnelState *ts;
1343   GNUNET_MESH_ApplicationType app_type;
1344   
1345   /* validate and parse request */
1346   mlen = ntohs (message->size);
1347   if (mlen < sizeof (struct RedirectToIpRequestMessage))
1348   {
1349     GNUNET_break (0);
1350     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1351     return;
1352   }
1353   alen = mlen - sizeof (struct RedirectToIpRequestMessage);
1354   msg = (const struct RedirectToIpRequestMessage *) message;
1355   addr_af = (int) htonl (msg->addr_af);
1356   switch (addr_af)
1357   {
1358   case AF_INET:
1359     if (alen != sizeof (struct in_addr))
1360     {
1361       GNUNET_break (0);
1362       GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1363       return;      
1364     }
1365     app_type = GNUNET_APPLICATION_TYPE_IPV4_GATEWAY; 
1366     break;
1367   case AF_INET6:
1368     if (alen != sizeof (struct in6_addr))
1369     {
1370       GNUNET_break (0);
1371       GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1372       return;      
1373     }
1374     app_type = GNUNET_APPLICATION_TYPE_IPV6_GATEWAY; 
1375     break;
1376   default:
1377     GNUNET_break (0);
1378     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1379     return;      
1380   }
1381
1382   /* allocate response IP */
1383   addr = NULL;
1384   result_af = (int) htonl (msg->result_af);
1385   switch (result_af)
1386   {
1387   case AF_INET:
1388     if (GNUNET_OK !=
1389         allocate_v4_address (&v4))
1390       result_af = AF_UNSPEC;
1391     else
1392       addr = &v4;
1393     break;
1394   case AF_INET6:
1395     if (GNUNET_OK !=
1396         allocate_v6_address (&v6))
1397       result_af = AF_UNSPEC;
1398     else
1399       addr = &v6;
1400     break;
1401   case AF_UNSPEC:
1402     if (GNUNET_OK ==
1403         allocate_v4_address (&v4))
1404     {
1405       addr = &v4;
1406       result_af = AF_INET;
1407     }
1408     else if (GNUNET_OK ==
1409         allocate_v6_address (&v6))
1410     {
1411       addr = &v6;
1412       result_af = AF_INET6;
1413     }
1414     break;
1415   default:
1416     GNUNET_break (0);
1417     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1418     return;      
1419   }
1420   if ( (result_af == AF_UNSPEC) ||
1421        (GNUNET_NO == ntohl (msg->nac)) )
1422   {
1423     /* send reply "instantly" */
1424     send_client_reply (client,
1425                        msg->request_id,
1426                        result_af,
1427                        addr);
1428   }
1429   if (result_af == AF_UNSPEC)
1430   {
1431     /* failure, we're done */
1432     GNUNET_SERVER_receive_done (client, GNUNET_OK);
1433     return;
1434   }
1435   
1436   /* setup destination record */
1437   de = GNUNET_malloc (sizeof (struct DestinationEntry));
1438   de->is_service = GNUNET_NO;
1439   de->details.exit_destination.af = addr_af;
1440   memcpy (&de->details.exit_destination.ip,
1441           &msg[1],
1442           alen);
1443   get_destination_key_from_ip (result_af,
1444                                addr,
1445                                &key);
1446   GNUNET_assert (GNUNET_OK ==
1447                  GNUNET_CONTAINER_multihashmap_put (destination_map,
1448                                                     &key,
1449                                                     de,
1450                                                     GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE));
1451   de->heap_node = GNUNET_CONTAINER_heap_insert (destination_heap,
1452                                                 de,
1453                                                 GNUNET_TIME_absolute_ntoh (msg->expiration_time).abs_value);
1454   /* setup tunnel to destination */
1455   ts = GNUNET_malloc (sizeof (struct TunnelState));
1456   if (GNUNET_NO != ntohl (msg->nac))
1457   {
1458     ts->request_id = msg->request_id;
1459     ts->client = client;
1460     GNUNET_SERVER_client_keep (client);
1461   }
1462   ts->destination = *de;
1463   ts->destination.heap_node = NULL;
1464   ts->is_service = GNUNET_NO;
1465   ts->af = result_af;
1466   if (result_af == AF_INET) 
1467     ts->destination_ip.v4 = v4;
1468   else
1469     ts->destination_ip.v6 = v6;
1470   de->tunnel = GNUNET_MESH_tunnel_create (mesh_handle,
1471                                           ts,
1472                                           &tunnel_peer_connect_handler,
1473                                           &tunnel_peer_disconnect_handler,
1474                                           ts);
1475   GNUNET_MESH_peer_request_connect_by_type (de->tunnel,
1476                                             app_type);  
1477   /* we're done */
1478   GNUNET_SERVER_receive_done (client, GNUNET_OK);
1479 }
1480
1481
1482 /**
1483  * A client asks us to setup a redirection to a particular peer
1484  * offering a service.  Setup the redirection and give the client the
1485  * allocated IP.
1486  *
1487  * @param cls unused
1488  * @param client requesting client
1489  * @param message redirection request (a 'struct RedirectToPeerRequestMessage')
1490  */
1491 static void
1492 service_redirect_to_service (void *cls GNUNET_UNUSED, struct GNUNET_SERVER_Client *client,
1493                              const struct GNUNET_MessageHeader *message)
1494 {
1495   const struct RedirectToServiceRequestMessage *msg;
1496   int result_af;
1497   struct in_addr v4;
1498   struct in6_addr v6;
1499   void *addr;
1500   struct DestinationEntry *de;
1501   GNUNET_HashCode key;
1502   struct TunnelState *ts;
1503   
1504   /*  parse request */
1505   msg = (const struct RedirectToServiceRequestMessage *) message;
1506
1507   /* allocate response IP */
1508   addr = NULL;
1509   result_af = (int) htonl (msg->result_af);
1510   switch (result_af)
1511   {
1512   case AF_INET:
1513     if (GNUNET_OK !=
1514         allocate_v4_address (&v4))
1515       result_af = AF_UNSPEC;
1516     else
1517       addr = &v4;
1518     break;
1519   case AF_INET6:
1520     if (GNUNET_OK !=
1521         allocate_v6_address (&v6))
1522       result_af = AF_UNSPEC;
1523     else
1524       addr = &v6;
1525     break;
1526   case AF_UNSPEC:
1527     if (GNUNET_OK ==
1528         allocate_v4_address (&v4))
1529     {
1530       addr = &v4;
1531       result_af = AF_INET;
1532     }
1533     else if (GNUNET_OK ==
1534         allocate_v6_address (&v6))
1535     {
1536       addr = &v6;
1537       result_af = AF_INET6;
1538     }
1539     break;
1540   default:
1541     GNUNET_break (0);
1542     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1543     return;      
1544   }
1545   if ( (result_af == AF_UNSPEC) ||
1546        (GNUNET_NO == ntohl (msg->nac)) )
1547   {
1548     /* send reply "instantly" */
1549     send_client_reply (client,
1550                        msg->request_id,
1551                        result_af,
1552                        addr);
1553   }
1554   if (result_af == AF_UNSPEC)
1555   {
1556     /* failure, we're done */
1557     GNUNET_SERVER_receive_done (client, GNUNET_OK);
1558     return;
1559   }
1560   
1561   /* setup destination record */
1562   de = GNUNET_malloc (sizeof (struct DestinationEntry));
1563   de->is_service = GNUNET_YES;
1564   de->details.service_destination.service_descriptor = msg->service_descriptor;
1565   de->details.service_destination.target = msg->target;
1566   get_destination_key_from_ip (result_af,
1567                                addr,
1568                                &key);
1569   GNUNET_assert (GNUNET_OK ==
1570                  GNUNET_CONTAINER_multihashmap_put (destination_map,
1571                                                     &key,
1572                                                     de,
1573                                                     GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE));
1574   de->heap_node = GNUNET_CONTAINER_heap_insert (destination_heap,
1575                                                 de,
1576                                                 GNUNET_TIME_absolute_ntoh (msg->expiration_time).abs_value);
1577
1578   /* setup tunnel to destination */
1579   ts = GNUNET_malloc (sizeof (struct TunnelState));
1580   if (GNUNET_NO != ntohl (msg->nac))
1581   {
1582     ts->request_id = msg->request_id;
1583     ts->client = client;
1584     GNUNET_SERVER_client_keep (client);
1585   }
1586   ts->destination = *de;
1587   ts->destination.heap_node = NULL;
1588   ts->is_service = GNUNET_YES;
1589   ts->af = result_af;
1590   if (result_af == AF_INET) 
1591     ts->destination_ip.v4 = v4;
1592   else
1593     ts->destination_ip.v6 = v6;
1594   de->tunnel = GNUNET_MESH_tunnel_create (mesh_handle,
1595                                           ts,
1596                                           &tunnel_peer_connect_handler,
1597                                           &tunnel_peer_disconnect_handler,
1598                                           ts);
1599   GNUNET_MESH_peer_request_connect_add (de->tunnel,
1600                                         &msg->target);  
1601   /* we're done */
1602   GNUNET_SERVER_receive_done (client, GNUNET_OK);
1603 }
1604
1605
1606
1607 /**
1608  * Function called for inbound tunnels.  As we don't offer
1609  * any mesh services, this function should never be called.
1610  *
1611  * @param cls closure
1612  * @param tunnel new handle to the tunnel
1613  * @param initiator peer that started the tunnel
1614  * @param atsi performance information for the tunnel
1615  * @return initial tunnel context for the tunnel
1616  *         (can be NULL -- that's not an error)
1617  */ 
1618 static void *
1619 inbound_tunnel_cb (void *cls, struct GNUNET_MESH_Tunnel *tunnel,
1620                    const struct GNUNET_PeerIdentity *initiator,
1621                    const struct GNUNET_ATS_Information *atsi)
1622 {
1623   /* Why should anyone open an inbound tunnel to vpn? */
1624   GNUNET_break (0);
1625   return NULL;
1626 }
1627
1628
1629 /**
1630  * Function called whenever an inbound tunnel is destroyed.  Should clean up
1631  * any associated state.
1632  *
1633  * @param cls closure (set from GNUNET_MESH_connect)
1634  * @param tunnel connection to the other end (henceforth invalid)
1635  * @param tunnel_ctx place where local state associated
1636  *                   with the tunnel is stored
1637  */ 
1638 static void
1639 tunnel_cleaner (void *cls, const struct GNUNET_MESH_Tunnel *tunnel, void *tunnel_ctx)
1640 {
1641   /* FIXME: is this function called for outbound tunnels that go down?
1642      Should we clean up something here? */
1643   GNUNET_break (0);
1644 }
1645
1646
1647 /**
1648  * Function scheduled as very last function, cleans up after us
1649  */
1650 static void
1651 cleanup (void *cls GNUNET_UNUSED,
1652          const struct GNUNET_SCHEDULER_TaskContext *tskctx)
1653 {
1654   unsigned int i;
1655
1656   // FIXME: clean up heaps and maps!
1657   if (NULL != mesh_handle)
1658   {
1659     GNUNET_MESH_disconnect (mesh_handle);
1660     mesh_handle = NULL;
1661   }
1662   if (NULL != helper_handle)
1663     {
1664     GNUNET_HELPER_stop (helper_handle);
1665     helper_handle = NULL;
1666   }
1667   if (NULL != nc)
1668   {
1669     GNUNET_SERVER_notification_context_destroy (nc);
1670     nc = NULL;
1671   }
1672   for (i=0;i<5;i++)
1673     GNUNET_free_non_null (vpn_argv[i]);
1674 }
1675
1676
1677 /**
1678  * A client has disconnected from us.  If we are currently building
1679  * a tunnel for it, cancel the operation.
1680  *
1681  * @param cls unused
1682  * @param client handle to the client that disconnected
1683  */
1684 static void
1685 client_disconnect (void *cls, struct GNUNET_SERVER_Client *client)
1686 {
1687   // FIXME: find all TunnelState's and check if they point
1688   // to the client and if so, clean the reference up!
1689 }
1690
1691
1692 /**
1693  * Main function that will be run by the scheduler.
1694  *
1695  * @param cls closure
1696  * @param server the initialized server
1697  * @param cfg_ configuration
1698  */
1699 static void
1700 run (void *cls,
1701      struct GNUNET_SERVER_Handle *server,
1702      const struct GNUNET_CONFIGURATION_Handle *cfg_)
1703 {
1704   static const struct GNUNET_SERVER_MessageHandler service_handlers[] = {
1705     /* callback, cls, type, size */
1706     {&service_redirect_to_ip, NULL, GNUNET_MESSAGE_TYPE_VPN_CLIENT_REDIRECT_TO_IP, 0},
1707     {&service_redirect_to_service, NULL, 
1708      GNUNET_MESSAGE_TYPE_VPN_CLIENT_REDIRECT_TO_SERVICE, 
1709      sizeof (struct RedirectToServiceRequestMessage) },
1710     {NULL, NULL, 0, 0}
1711   };
1712   static const struct GNUNET_MESH_MessageHandler mesh_handlers[] = {
1713     {receive_udp_back, GNUNET_MESSAGE_TYPE_VPN_SERVICE_UDP_BACK, 0},
1714     {receive_tcp_back, GNUNET_MESSAGE_TYPE_VPN_SERVICE_TCP_BACK, 0},
1715     {receive_udp_back, GNUNET_MESSAGE_TYPE_VPN_REMOTE_UDP_BACK, 0},
1716     {receive_tcp_back, GNUNET_MESSAGE_TYPE_VPN_REMOTE_TCP_BACK, 0},
1717     {NULL, 0, 0}
1718   };
1719   static const GNUNET_MESH_ApplicationType types[] = {
1720     GNUNET_APPLICATION_TYPE_END
1721   };
1722   char *ifname;
1723   char *ipv6addr;
1724   char *ipv6prefix_s;
1725   char *ipv4addr;
1726   char *ipv4mask;
1727   struct in_addr v4;
1728   struct in6_addr v6;
1729
1730   cfg = cfg_;
1731   if (GNUNET_OK !=
1732       GNUNET_CONFIGURATION_get_value_number (cfg, "vpn", "MAX_MAPPING",
1733                                              &max_destination_mappings))
1734     max_destination_mappings = 200;
1735   if (GNUNET_OK !=
1736       GNUNET_CONFIGURATION_get_value_number (cfg, "vpn", "MAX_TUNNELS",
1737                                              &max_tunnel_mappings))
1738     max_tunnel_mappings = 200;
1739
1740   destination_map = GNUNET_CONTAINER_multihashmap_create (max_destination_mappings * 2);
1741   destination_heap = GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN);
1742   tunnel_map = GNUNET_CONTAINER_multihashmap_create (max_tunnel_mappings * 2);
1743   tunnel_heap = GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN);
1744
1745
1746   vpn_argv[0] = GNUNET_strdup ("vpn-gnunet");
1747   if (GNUNET_SYSERR ==
1748       GNUNET_CONFIGURATION_get_value_string (cfg, "vpn", "IFNAME", &ifname))
1749   {
1750     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1751                 "No entry 'IFNAME' in configuration!\n");
1752     GNUNET_SCHEDULER_shutdown ();
1753     return;
1754   }
1755   vpn_argv[1] = ifname;
1756   if ( (GNUNET_SYSERR ==
1757         GNUNET_CONFIGURATION_get_value_string (cfg, "vpn", "IPV6ADDR",
1758                                                &ipv6addr) ||
1759         (1 != inet_pton (AF_INET6, ipv6addr, &v6))) )
1760   {
1761     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1762                 "No valid entry 'IPV6ADDR' in configuration!\n");
1763     GNUNET_SCHEDULER_shutdown ();
1764     return;
1765   }
1766   vpn_argv[2] = ipv6addr;
1767   if (GNUNET_SYSERR ==
1768       GNUNET_CONFIGURATION_get_value_string (cfg, "vpn", "IPV6PREFIX",
1769                                              &ipv6prefix_s))
1770   {
1771     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1772                 "No entry 'IPV6PREFIX' in configuration!\n");
1773     GNUNET_SCHEDULER_shutdown ();
1774     return;
1775   }
1776   vpn_argv[3] = ipv6prefix_s;
1777   if ( (GNUNET_OK !=
1778         GNUNET_CONFIGURATION_get_value_number (cfg, "vpn",
1779                                                "IPV6PREFIX",
1780                                                &ipv6prefix)) ||
1781        (ipv6prefix >= 127) )
1782   {
1783     GNUNET_SCHEDULER_shutdown ();
1784     return;
1785   }
1786
1787   if ( (GNUNET_SYSERR ==
1788         GNUNET_CONFIGURATION_get_value_string (cfg, "vpn", "IPV4ADDR",
1789                                                &ipv4addr) ||
1790         (1 != inet_pton (AF_INET, ipv4addr, &v4))) )
1791   {
1792     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1793                 "No valid entry for 'IPV4ADDR' in configuration!\n");
1794     GNUNET_SCHEDULER_shutdown ();
1795     return;
1796   }
1797   vpn_argv[4] = ipv4addr;
1798   if ( (GNUNET_SYSERR ==
1799         GNUNET_CONFIGURATION_get_value_string (cfg, "vpn", "IPV4MASK",
1800                                                &ipv4mask) ||
1801         (1 != inet_pton (AF_INET, ipv4mask, &v4))) )
1802   {
1803     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1804                 "No valid entry 'IPV4MASK' in configuration!\n");
1805     GNUNET_SCHEDULER_shutdown ();
1806     return;
1807   }
1808   vpn_argv[5] = ipv4mask;
1809   vpn_argv[6] = NULL;
1810
1811   mesh_handle =
1812     GNUNET_MESH_connect (cfg_, 42 /* queue length */, NULL, 
1813                          &inbound_tunnel_cb, 
1814                          &tunnel_cleaner, 
1815                          mesh_handlers,
1816                          types);
1817   helper_handle = GNUNET_HELPER_start ("gnunet-helper-vpn", vpn_argv,
1818                                        &message_token, NULL);
1819   nc = GNUNET_SERVER_notification_context_create (server, 1);
1820   GNUNET_SERVER_add_handlers (server, service_handlers);
1821   GNUNET_SERVER_disconnect_notify (server, &client_disconnect, NULL);
1822   GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &cleanup, cls);
1823 }
1824
1825
1826 /**
1827  * The main function of the VPN service.
1828  *
1829  * @param argc number of arguments from the command line
1830  * @param argv command line arguments
1831  * @return 0 ok, 1 on error
1832  */
1833 int
1834 main (int argc, char *const *argv)
1835 {
1836   return (GNUNET_OK ==
1837           GNUNET_SERVICE_run (argc, argv, "vpn", 
1838                               GNUNET_SERVICE_OPTION_NONE,
1839                               &run, NULL)) ? 0 : 1;
1840 }
1841
1842 /* end of gnunet-service-vpn.c */