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