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