2 This file is part of GNUnet.
3 (C) 2010, 2011, 2012 Christian Grothoff
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.
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.
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.
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
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)
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"
51 * Information we track for each IP address to determine which tunnel
52 * to send the traffic over to the destination.
54 struct DestinationEntry
57 * Information about the tunnel to use, NULL if no tunnel
58 * is available right now.
60 struct GNUNET_MESH_Tunnel *tunnel;
63 * Entry for this entry in the destination_heap.
65 struct GNUNET_CONTAINER_HeapNode *heap_node;
68 * GNUNET_NO if this is a tunnel to an Internet-exit,
69 * GNUNET_YES if this tunnel is to a service.
74 * Details about the connection (depending on is_service).
82 * The description of the service (only used for service tunnels).
84 GNUNET_HashCode service_descriptor;
87 * Peer offering the service.
89 struct GNUNET_PeerIdentity target;
91 } service_destination;
97 * Address family used (AF_INET or AF_INET6).
102 * IP address of the ultimate destination (only used for exit tunnels).
107 * Address if af is AF_INET.
112 * Address if af is AF_INET6.
125 * A messages we have in queue for a particular tunnel.
127 struct TunnelMessageQueueEntry
130 * This is a doubly-linked list.
132 struct TunnelMessageQueueEntry *next;
135 * This is a doubly-linked list.
137 struct TunnelMessageQueueEntry *prev;
140 * Number of bytes in 'msg'.
145 * Message to transmit, allocated at the end of this struct.
152 * State we keep for each of our tunnels.
157 * Active transmission handle, NULL for none.
159 struct GNUNET_MESH_TransmitHandle *th;
162 * Entry for this entry in the tunnel_heap, NULL as long as this
163 * tunnel state is not fully bound.
165 struct GNUNET_CONTAINER_HeapNode *heap_node;
168 * Head of list of messages scheduled for transmission.
170 struct TunnelMessageQueueEntry *head;
173 * Tail of list of messages scheduled for transmission.
175 struct TunnelMessageQueueEntry *tail;
178 * Client that needs to be notified about the tunnel being
179 * up as soon as a peer is connected; NULL for none.
181 struct GNUNET_SERVER_Client *client;
184 * ID of the client request that caused us to setup this entry.
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
194 struct DestinationEntry destination;
197 * GNUNET_NO if this is a tunnel to an Internet-exit,
198 * GNUNET_YES if this tunnel is to a service.
203 * Addess family used for this tunnel on the local TUN interface.
208 * IP address of the source on our end, initially uninitialized.
213 * Address if af is AF_INET.
218 * Address if af is AF_INET6.
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).
231 * Address if af is AF_INET.
236 * Address if af is AF_INET6.
243 * Source port used by the sender on our end; 0 for uninitialized.
245 uint16_t source_port;
248 * Destination port used by the sender on our end; 0 for uninitialized.
250 uint16_t destination_port;
256 * Configuration we use.
258 static const struct GNUNET_CONFIGURATION_Handle *cfg;
261 * Handle to the mesh service.
263 static struct GNUNET_MESH_Handle *mesh_handle;
266 * Map from IP address to destination information (possibly with a
267 * MESH tunnel handle for fast setup).
269 static struct GNUNET_CONTAINER_MultiHashMap *destination_map;
272 * Min-Heap sorted by activity time to expire old mappings.
274 static struct GNUNET_CONTAINER_Heap *destination_heap;
277 * Map from source and destination address (IP+port) to connection
278 * information (mostly with the respective MESH tunnel handle).
280 static struct GNUNET_CONTAINER_MultiHashMap *tunnel_map;
283 * Min-Heap sorted by activity time to expire old mappings.
285 static struct GNUNET_CONTAINER_Heap *tunnel_heap;
288 * The handle to the VPN helper process "gnunet-helper-vpn".
290 static struct GNUNET_HELPER_Handle *helper_handle;
293 * Arguments to the vpn helper.
295 static char *vpn_argv[7];
298 * Length of the prefix of the VPN's IPv6 network.
300 static unsigned long long ipv6prefix;
303 * Notification context for sending replies to clients.
305 static struct GNUNET_SERVER_NotificationContext *nc;
308 * If there are more than this number of address-mappings, old ones
311 static unsigned long long max_destination_mappings;
314 * If there are more than this number of open tunnels, old ones
317 static unsigned long long max_tunnel_mappings;
321 * Compute the key under which we would store an entry in the
322 * destination_map for the given IP address.
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
329 get_destination_key_from_ip (int af,
331 GNUNET_HashCode *key)
336 GNUNET_CRYPTO_hash (address,
337 sizeof (struct in_addr),
341 GNUNET_CRYPTO_hash (address,
342 sizeof (struct in6_addr),
353 * Compute the key under which we would store an entry in the
354 * tunnel_map for the given socket address pair.
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
365 get_tunnel_key_from_ips (int af,
367 const void *source_ip,
368 uint16_t source_port,
369 const void *destination_ip,
370 uint16_t destination_port,
371 GNUNET_HashCode *key)
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) */
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);
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);
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);
401 memcpy (off, &protocol, sizeof (uint8_t));
402 off += sizeof (uint8_t);
407 * Notify the client about the result of its request.
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
415 send_client_reply (struct GNUNET_SERVER_Client *client,
420 char buf[sizeof (struct RedirectToIpResponseMessage) + sizeof (struct in6_addr)];
421 struct RedirectToIpResponseMessage *res;
427 rlen = sizeof (struct in_addr);
430 rlen = sizeof (struct in6_addr);
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,
454 * Method called whenever a peer has disconnected from the tunnel.
457 * @param peer peer identity the tunnel stopped working with
460 tunnel_peer_disconnect_handler (void *cls,
462 GNUNET_PeerIdentity * peer)
464 /* FIXME: should we do anything here?
465 - stop transmitting to the tunnel (start queueing?)
466 - possibly destroy the tunnel entirely (unless service tunnel?)
472 * Method called whenever a peer has connected to the tunnel. Notifies
473 * the waiting client that the tunnel is now up.
476 * @param peer peer identity the tunnel was created to, NULL on timeout
477 * @param atsi performance data for the connection
480 tunnel_peer_connect_handler (void *cls,
481 const struct GNUNET_PeerIdentity
484 GNUNET_ATS_Information * atsi)
486 struct TunnelState *ts = cls;
488 if (NULL == ts->client)
489 return; /* nothing to do */
490 send_client_reply (ts->client,
493 &ts->destination_ip);
494 GNUNET_SERVER_client_drop (ts->client);
500 * Send a message from the message queue via mesh.
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
508 send_to_peer_notify_callback (void *cls, size_t size, void *buf)
510 struct TunnelState *ts = cls;
511 struct TunnelMessageQueueEntry *tnq;
518 GNUNET_assert (NULL != tnq);
519 GNUNET_assert (size >= tnq->len);
520 GNUNET_CONTAINER_DLL_remove (ts->head,
523 memcpy (buf, tnq->msg, tnq->len);
526 if (NULL != (tnq = ts->head))
527 ts->th = GNUNET_MESH_notify_transmit_ready (ts->destination.tunnel,
528 GNUNET_NO /* cork */,
530 GNUNET_TIME_UNIT_FOREVER_REL,
533 &send_to_peer_notify_callback,
540 * Add the given message to the given tunnel and
541 * trigger the transmission process.
543 * @param tnq message to queue
544 * @param ts tunnel to queue the message for
547 send_to_tunnel (struct TunnelMessageQueueEntry *tnq,
548 struct TunnelState *ts)
550 GNUNET_CONTAINER_DLL_insert_tail (ts->head,
554 ts->th = GNUNET_MESH_notify_transmit_ready (ts->destination.tunnel,
555 GNUNET_NO /* cork */,
557 GNUNET_TIME_UNIT_FOREVER_REL,
560 &send_to_peer_notify_callback,
566 * Route a packet via mesh to the given destination.
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
577 route_packet (struct DestinationEntry *destination,
580 const void *source_ip,
581 const void *destination_ip,
583 size_t payload_length)
586 struct TunnelState *ts;
587 struct TunnelMessageQueueEntry *tnq;
590 GNUNET_MESH_ApplicationType app_type;
592 const struct udp_packet *udp;
593 const struct tcp_packet *tcp;
599 if (payload_length < sizeof (struct udp_packet))
606 get_tunnel_key_from_ips (af,
617 if (payload_length < sizeof (struct tcp_packet))
624 get_tunnel_key_from_ips (af,
634 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
635 _("Protocol %u not supported, dropping\n"),
636 (unsigned int) protocol);
640 if (! destination->is_service)
642 switch (destination->details.exit_destination.af)
645 alen = sizeof (struct in_addr);
646 app_type = GNUNET_APPLICATION_TYPE_IPV4_GATEWAY;
649 alen = sizeof (struct in6_addr);
650 app_type = GNUNET_APPLICATION_TYPE_IPV6_GATEWAY;
659 /* make compiler happy */
664 // FIXME: something is horrifically wrong here about
665 // how we lookup 'ts', match it and how we decide about
666 // creating new tunnels!
669 ts = GNUNET_CONTAINER_multihashmap_get (tunnel_map,
673 /* create new tunnel */
675 ts = GNUNET_malloc (sizeof (struct TunnelState));
676 ts->destination.tunnel = GNUNET_MESH_tunnel_create (mesh_handle,
678 &tunnel_peer_connect_handler,
679 &tunnel_peer_disconnect_handler,
681 if (destination->is_service)
682 GNUNET_MESH_peer_request_connect_add (ts->destination.tunnel,
683 &destination->details.service_destination.target);
685 GNUNET_MESH_peer_request_connect_by_type (ts->destination.tunnel,
689 /* send via tunnel */
693 if (destination->is_service)
695 struct GNUNET_EXIT_UdpServiceMessage *usm;
697 mlen = sizeof (struct GNUNET_EXIT_UdpServiceMessage) +
698 payload_length - sizeof (struct udp_packet);
699 if (mlen >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
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;
715 payload_length - sizeof (struct udp_packet));
719 struct GNUNET_EXIT_UdpInternetMessage *uim;
720 struct in_addr *ip4dst;
721 struct in6_addr *ip6dst;
724 mlen = sizeof (struct GNUNET_EXIT_UdpInternetMessage) +
725 alen + payload_length - sizeof (struct udp_packet);
726 if (mlen >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
731 tnq = GNUNET_malloc (sizeof (struct TunnelMessageQueueEntry) +
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)
742 ip4dst = (struct in_addr *) &uim[1];
743 *ip4dst = destination->details.exit_destination.ip.v4;
744 payload = &ip4dst[1];
747 ip6dst = (struct in6_addr *) &uim[1];
748 *ip6dst = destination->details.exit_destination.ip.v6;
749 payload = &ip6dst[1];
756 payload_length - sizeof (struct udp_packet));
762 if (destination->is_service)
764 struct GNUNET_EXIT_TcpServiceStartMessage *tsm;
766 mlen = sizeof (struct GNUNET_EXIT_TcpServiceStartMessage) +
767 payload_length - sizeof (struct tcp_packet);
768 if (mlen >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
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;
782 payload_length - sizeof (struct tcp_packet));
786 struct GNUNET_EXIT_TcpInternetStartMessage *tim;
787 struct in_addr *ip4dst;
788 struct in6_addr *ip6dst;
791 mlen = sizeof (struct GNUNET_EXIT_TcpInternetStartMessage) +
792 alen + payload_length - sizeof (struct tcp_packet);
793 if (mlen >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
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)
807 ip4dst = (struct in_addr *) &tim[1];
808 *ip4dst = destination->details.exit_destination.ip.v4;
809 payload = &ip4dst[1];
812 ip6dst = (struct in6_addr *) &tim[1];
813 *ip6dst = destination->details.exit_destination.ip.v6;
814 payload = &ip6dst[1];
821 payload_length - sizeof (struct tcp_packet));
826 struct GNUNET_EXIT_TcpDataMessage *tdm;
828 mlen = sizeof (struct GNUNET_EXIT_TcpDataMessage) +
829 alen + payload_length - sizeof (struct tcp_packet);
830 if (mlen >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
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;
843 payload_length - sizeof (struct tcp_packet));
847 /* not supported above, how can we get here !? */
851 send_to_tunnel (tnq, ts);
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.
861 * @param cls closure, NULL
863 * @param message message we got from the client (VPN tunnel interface)
866 message_token (void *cls GNUNET_UNUSED, void *client GNUNET_UNUSED,
867 const struct GNUNET_MessageHeader *message)
869 const struct tun_header *tun;
872 struct DestinationEntry *de;
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)) )
881 tun = (const struct tun_header *) &message[1];
882 mlen -= (sizeof (struct GNUNET_MessageHeader) + sizeof (struct tun_header));
883 switch (ntohs (tun->proto))
887 const struct ip6_header *pkt6;
889 if (mlen < sizeof (struct ip6_header))
895 pkt6 = (const struct ip6_header *) &tun[1];
896 get_destination_key_from_ip (AF_INET6,
897 &pkt6->destination_address,
899 de = GNUNET_CONTAINER_multihashmap_get (destination_map, &key);
900 /* FIXME: do we need to guard against hash collision? */
903 char buf[INET6_ADDRSTRLEN];
905 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
906 _("Packet received for unmapped destination `%s' (dropping it)\n"),
908 &pkt6->destination_address,
916 &pkt6->source_address,
917 &pkt6->destination_address,
919 mlen - sizeof (struct ip6_header));
924 struct ip4_header *pkt4;
926 if (mlen < sizeof (struct ip4_header))
932 pkt4 = (struct ip4_header *) &tun[1];
933 get_destination_key_from_ip (AF_INET,
934 &pkt4->destination_address,
936 de = GNUNET_CONTAINER_multihashmap_get (destination_map, &key);
937 /* FIXME: do we need to guard against hash collision? */
940 char buf[INET_ADDRSTRLEN];
942 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
943 _("Packet received for unmapped destination `%s' (dropping it)\n"),
945 &pkt4->destination_address,
950 if (pkt4->header_length * 4 != sizeof (struct ip4_header))
952 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
953 _("Received IPv4 packet with options (dropping it)\n"));
959 &pkt4->source_address,
960 &pkt4->destination_address,
962 mlen - sizeof (struct ip4_header));
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));
975 * We got a UDP packet back from the MESH tunnel. Pass it on to the
976 * local virtual interface via the helper.
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)
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)
993 struct TunnelState *ts = *tunnel_ctx;
994 const struct GNUNET_EXIT_UdpReplyMessage *reply;
997 mlen = ntohs (message->size);
998 if (mlen < sizeof (struct GNUNET_EXIT_UdpReplyMessage))
1000 GNUNET_break_op (0);
1001 return GNUNET_SYSERR;
1003 if (NULL == ts->heap_node)
1005 GNUNET_break_op (0);
1006 return GNUNET_SYSERR;
1008 reply = (const struct GNUNET_EXIT_UdpReplyMessage *) message;
1009 mlen -= sizeof (struct GNUNET_EXIT_UdpReplyMessage);
1014 size_t size = sizeof (struct ip4_header)
1015 + sizeof (struct udp_packet)
1016 + sizeof (struct GNUNET_MessageHeader) +
1017 sizeof (struct tun_header) +
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);
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) +
1035 ipv4->identification = (uint16_t) GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
1038 ipv4->fragmentation_offset = 0;
1040 ipv4->protocol = IPPROTO_UDP;
1042 ipv4->source_address = ts->destination_ip.v4;
1043 ipv4->destination_address = ts->source_ip.v4;
1045 GNUNET_CRYPTO_crc16_n (ipv4, sizeof (struct ip4_header));
1046 if (0 == ntohs (reply->source_port))
1047 udp->spt = htons (ts->destination_port);
1049 udp->spt = reply->source_port;
1050 if (0 == ntohs (reply->destination_port))
1051 udp->dpt = htons (ts->source_port);
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
1059 (void) GNUNET_HELPER_send (helper_handle,
1068 size_t size = sizeof (struct ip6_header)
1069 + sizeof (struct udp_packet)
1070 + sizeof (struct GNUNET_MessageHeader) +
1071 sizeof (struct tun_header) +
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;
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);
1095 udp->spt = reply->source_port;
1096 if (0 == ntohs (reply->destination_port))
1097 udp->dpt = htons (ts->source_port);
1099 udp->dpt = reply->destination_port;
1100 udp->len = htons (mlen + sizeof (struct udp_packet));
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,
1117 udp->crc = GNUNET_CRYPTO_crc16_finish (sum);
1119 (void) GNUNET_HELPER_send (helper_handle,
1130 // FIXME: refresh entry to avoid expiration...
1131 struct map_entry *me = GNUNET_CONTAINER_multihashmap_get (hashmap, key);
1133 GNUNET_CONTAINER_heap_update_cost (heap, me->heap_node,
1134 GNUNET_TIME_absolute_get ().abs_value);
1142 * We got a TCP packet back from the MESH tunnel. Pass it on to the
1143 * local virtual interface via the helper.
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)
1155 receive_tcp_back (void *cls GNUNET_UNUSED, struct GNUNET_MESH_Tunnel *tunnel,
1157 const struct GNUNET_PeerIdentity *sender GNUNET_UNUSED,
1158 const struct GNUNET_MessageHeader *message,
1159 const struct GNUNET_ATS_Information *atsi GNUNET_UNUSED)
1161 struct TunnelState *ts = *tunnel_ctx;
1162 const struct GNUNET_EXIT_TcpDataMessage *data;
1165 mlen = ntohs (message->size);
1166 if (mlen < sizeof (struct GNUNET_EXIT_TcpDataMessage))
1168 GNUNET_break_op (0);
1169 return GNUNET_SYSERR;
1171 if (NULL == ts->heap_node)
1173 GNUNET_break_op (0);
1174 return GNUNET_SYSERR;
1176 data = (const struct GNUNET_EXIT_TcpDataMessage *) message;
1177 mlen -= sizeof (struct GNUNET_EXIT_TcpDataMessage);
1182 size_t size = sizeof (struct ip4_header)
1183 + sizeof (struct tcp_packet)
1184 + sizeof (struct GNUNET_MessageHeader) +
1185 sizeof (struct tun_header) +
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);
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) +
1203 ipv4->identification = (uint16_t) GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
1206 ipv4->fragmentation_offset = 0;
1208 ipv4->protocol = IPPROTO_TCP;
1210 ipv4->source_address = ts->destination_ip.v4;
1211 ipv4->destination_address = ts->source_ip.v4;
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);
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);
1233 (void) GNUNET_HELPER_send (helper_handle,
1245 // FIXME: parse message, build IP packet, give to TUN!
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;
1254 ntohs (message->size) - sizeof (struct GNUNET_MessageHeader) -
1255 sizeof (GNUNET_HashCode);
1257 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1258 "Received TCP-Packet back, addrlen = %d\n", s->addrlen);
1260 if (ntohs (message->type) == GNUNET_MESSAGE_TYPE_VPN_SERVICE_TCP_BACK ||
1263 size_t size = pktlen + sizeof (struct ip6_tcp) - 1;
1265 struct ip6_tcp *pkt6 = alloca (size);
1267 memset (pkt6, 0, size);
1269 GNUNET_assert (pkt6 != NULL);
1271 if (ntohs (message->type) == GNUNET_MESSAGE_TYPE_VPN_SERVICE_TCP_BACK)
1272 new_ip6addr (&pkt6->ip6_hdr.sadr, &other->hashPubKey, desc);
1274 new_ip6addr_remote (&pkt6->ip6_hdr.sadr, s->addr, s->addrlen);
1276 pkt6->shdr.type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
1277 pkt6->shdr.size = htons (size);
1279 pkt6->tun.flags = 0;
1280 pkt6->tun.type = htons (0x86dd);
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;
1293 GNUNET_assert (GNUNET_OK ==
1294 GNUNET_CONFIGURATION_get_value_string (cfg, "vpn",
1297 inet_pton (AF_INET6, ipv6addr, &pkt6->ip6_hdr.dadr);
1298 GNUNET_free (ipv6addr);
1300 memcpy (&pkt6->tcp_hdr, pkt, pktlen);
1302 GNUNET_HashCode *key = address6_mapping_exists (&pkt6->ip6_hdr.sadr);
1304 GNUNET_assert (key != NULL);
1306 struct map_entry *me = GNUNET_CONTAINER_multihashmap_get (hashmap, key);
1308 GNUNET_CONTAINER_heap_update_cost (heap, me->heap_node,
1309 GNUNET_TIME_absolute_get ().abs_value);
1313 GNUNET_assert (me != NULL);
1315 pkt6->tcp_hdr.crc = 0;
1320 sum = GNUNET_CRYPTO_crc16_step (sum, (uint16_t *) & pkt6->ip6_hdr.sadr, 16);
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);
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);
1334 (void) GNUNET_HELPER_send (helper_handle,
1341 size_t size = pktlen + sizeof (struct ip_tcp) - 1;
1343 struct ip_tcp *pkt4 = alloca (size);
1345 GNUNET_assert (pkt4 != NULL);
1346 memset (pkt4, 0, size);
1348 GNUNET_assert (ntohs (message->type) ==
1349 GNUNET_MESSAGE_TYPE_VPN_REMOTE_TCP_BACK);
1352 new_ip4addr_remote ((unsigned char *) &sadr, s->addr, s->addrlen);
1353 pkt4->ip_hdr.sadr.s_addr = sadr;
1355 pkt4->shdr.type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
1356 pkt4->shdr.size = htons (size);
1358 pkt4->tun.flags = 0;
1359 pkt4->tun.type = htons (0x0800);
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 */
1376 GNUNET_assert (GNUNET_OK ==
1377 GNUNET_CONFIGURATION_get_value_string (cfg, "vpn",
1380 inet_pton (AF_INET, ipv4addr, &dadr);
1381 GNUNET_free (ipv4addr);
1382 pkt4->ip_hdr.dadr.s_addr = dadr;
1385 memcpy (&pkt4->tcp_hdr, pkt, pktlen);
1387 GNUNET_HashCode *key = address4_mapping_exists (pkt4->ip_hdr.sadr.s_addr);
1389 GNUNET_assert (key != NULL);
1391 struct map_entry *me = GNUNET_CONTAINER_multihashmap_get (hashmap, key);
1393 GNUNET_CONTAINER_heap_update_cost (heap, me->heap_node,
1394 GNUNET_TIME_absolute_get ().abs_value);
1398 GNUNET_assert (me != NULL);
1399 pkt4->tcp_hdr.crc = 0;
1401 (void) GNUNET_HELPER_send (helper_handle,
1410 // FIXME: refresh entry to avoid expiration...
1411 struct map_entry *me = GNUNET_CONTAINER_multihashmap_get (hashmap, key);
1413 GNUNET_CONTAINER_heap_update_cost (heap, me->heap_node,
1414 GNUNET_TIME_absolute_get ().abs_value);
1422 * Allocate an IPv4 address from the range of the tunnel
1423 * for a new redirection.
1425 * @param v4 where to store the address
1426 * @return GNUNET_OK on success,
1427 * GNUNET_SYSERR on error
1430 allocate_v4_address (struct in_addr *v4)
1432 const char *ipv4addr = vpn_argv[4];
1433 const char *ipv4mask = vpn_argv[5];
1434 struct in_addr addr;
1435 struct in_addr mask;
1437 GNUNET_HashCode key;
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;
1451 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1452 _("Failed to find unallocated IPv4 address in VPN's range\n"));
1453 return GNUNET_SYSERR;
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,
1458 v4->s_addr = (addr.s_addr | rnd.s_addr) & mask.s_addr;
1459 get_destination_key_from_ip (AF_INET,
1463 while ( (GNUNET_YES ==
1464 GNUNET_CONTAINER_multihashmap_contains (destination_map,
1466 (v4->s_addr == addr.s_addr) ||
1467 (v4->s_addr == mask.s_addr) );
1473 * Allocate an IPv6 address from the range of the tunnel
1474 * for a new redirection.
1476 * @param v6 where to store the address
1477 * @return GNUNET_OK on success,
1478 * GNUNET_SYSERR on error
1481 allocate_v6_address (struct in6_addr *v6)
1483 const char *ipv6addr = vpn_argv[2];
1484 struct in6_addr addr;
1485 struct in6_addr mask;
1486 struct in6_addr rnd;
1488 GNUNET_HashCode key;
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,
1496 for (i=127;i>=128-ipv6prefix;i--)
1497 mask.s6_addr[i / 8] |= (1 << (i % 8));
1499 /* Pick random IPv6 address within the subnet, except 'addr' or 'mask' itself */
1506 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1507 _("Failed to find unallocated IPv6 address in VPN's range\n"));
1508 return GNUNET_SYSERR;
1513 rnd.s6_addr[i] = (unsigned char) GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
1516 = (addr.s6_addr[i] | rnd.s6_addr[i]) & mask.s6_addr[i];
1518 get_destination_key_from_ip (AF_INET6,
1522 while ( (GNUNET_YES ==
1523 GNUNET_CONTAINER_multihashmap_contains (destination_map,
1527 sizeof (struct in6_addr))) ||
1530 sizeof (struct in6_addr))) );
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.
1541 * @param client requesting client
1542 * @param message redirection request (a 'struct RedirectToIpRequestMessage')
1545 service_redirect_to_ip (void *cls GNUNET_UNUSED, struct GNUNET_SERVER_Client *client,
1546 const struct GNUNET_MessageHeader *message)
1550 const struct RedirectToIpRequestMessage *msg;
1556 struct DestinationEntry *de;
1557 GNUNET_HashCode key;
1558 struct TunnelState *ts;
1559 GNUNET_MESH_ApplicationType app_type;
1561 /* validate and parse request */
1562 mlen = ntohs (message->size);
1563 if (mlen < sizeof (struct RedirectToIpRequestMessage))
1566 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1569 alen = mlen - sizeof (struct RedirectToIpRequestMessage);
1570 msg = (const struct RedirectToIpRequestMessage *) message;
1571 addr_af = (int) htonl (msg->addr_af);
1575 if (alen != sizeof (struct in_addr))
1578 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1581 app_type = GNUNET_APPLICATION_TYPE_IPV4_GATEWAY;
1584 if (alen != sizeof (struct in6_addr))
1587 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1590 app_type = GNUNET_APPLICATION_TYPE_IPV6_GATEWAY;
1594 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1598 /* allocate response IP */
1600 result_af = (int) htonl (msg->result_af);
1605 allocate_v4_address (&v4))
1606 result_af = AF_UNSPEC;
1612 allocate_v6_address (&v6))
1613 result_af = AF_UNSPEC;
1619 allocate_v4_address (&v4))
1622 result_af = AF_INET;
1624 else if (GNUNET_OK ==
1625 allocate_v6_address (&v6))
1628 result_af = AF_INET6;
1633 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1636 if ( (result_af == AF_UNSPEC) ||
1637 (GNUNET_NO == ntohl (msg->nac)) )
1639 /* send reply "instantly" */
1640 send_client_reply (client,
1645 if (result_af == AF_UNSPEC)
1647 /* failure, we're done */
1648 GNUNET_SERVER_receive_done (client, GNUNET_OK);
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,
1659 get_destination_key_from_ip (result_af,
1662 GNUNET_assert (GNUNET_OK ==
1663 GNUNET_CONTAINER_multihashmap_put (destination_map,
1666 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE));
1667 de->heap_node = GNUNET_CONTAINER_heap_insert (destination_heap,
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))
1674 ts->request_id = msg->request_id;
1675 ts->client = client;
1676 GNUNET_SERVER_client_keep (client);
1678 ts->destination = *de;
1679 ts->destination.heap_node = NULL;
1680 ts->is_service = GNUNET_NO;
1682 if (result_af == AF_INET)
1683 ts->destination_ip.v4 = v4;
1685 ts->destination_ip.v6 = v6;
1686 de->tunnel = GNUNET_MESH_tunnel_create (mesh_handle,
1688 &tunnel_peer_connect_handler,
1689 &tunnel_peer_disconnect_handler,
1691 GNUNET_MESH_peer_request_connect_by_type (de->tunnel,
1694 GNUNET_SERVER_receive_done (client, GNUNET_OK);
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
1704 * @param client requesting client
1705 * @param message redirection request (a 'struct RedirectToPeerRequestMessage')
1708 service_redirect_to_service (void *cls GNUNET_UNUSED, struct GNUNET_SERVER_Client *client,
1709 const struct GNUNET_MessageHeader *message)
1711 const struct RedirectToServiceRequestMessage *msg;
1716 struct DestinationEntry *de;
1717 GNUNET_HashCode key;
1718 struct TunnelState *ts;
1721 msg = (const struct RedirectToServiceRequestMessage *) message;
1723 /* allocate response IP */
1725 result_af = (int) htonl (msg->result_af);
1730 allocate_v4_address (&v4))
1731 result_af = AF_UNSPEC;
1737 allocate_v6_address (&v6))
1738 result_af = AF_UNSPEC;
1744 allocate_v4_address (&v4))
1747 result_af = AF_INET;
1749 else if (GNUNET_OK ==
1750 allocate_v6_address (&v6))
1753 result_af = AF_INET6;
1758 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1761 if ( (result_af == AF_UNSPEC) ||
1762 (GNUNET_NO == ntohl (msg->nac)) )
1764 /* send reply "instantly" */
1765 send_client_reply (client,
1770 if (result_af == AF_UNSPEC)
1772 /* failure, we're done */
1773 GNUNET_SERVER_receive_done (client, GNUNET_OK);
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,
1785 GNUNET_assert (GNUNET_OK ==
1786 GNUNET_CONTAINER_multihashmap_put (destination_map,
1789 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE));
1790 de->heap_node = GNUNET_CONTAINER_heap_insert (destination_heap,
1792 GNUNET_TIME_absolute_ntoh (msg->expiration_time).abs_value);
1794 /* setup tunnel to destination */
1795 ts = GNUNET_malloc (sizeof (struct TunnelState));
1796 if (GNUNET_NO != ntohl (msg->nac))
1798 ts->request_id = msg->request_id;
1799 ts->client = client;
1800 GNUNET_SERVER_client_keep (client);
1802 ts->destination = *de;
1803 ts->destination.heap_node = NULL;
1804 ts->is_service = GNUNET_YES;
1806 if (result_af == AF_INET)
1807 ts->destination_ip.v4 = v4;
1809 ts->destination_ip.v6 = v6;
1810 de->tunnel = GNUNET_MESH_tunnel_create (mesh_handle,
1812 &tunnel_peer_connect_handler,
1813 &tunnel_peer_disconnect_handler,
1815 GNUNET_MESH_peer_request_connect_add (de->tunnel,
1818 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1824 * Function called for inbound tunnels. As we don't offer
1825 * any mesh services, this function should never be called.
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)
1835 inbound_tunnel_cb (void *cls, struct GNUNET_MESH_Tunnel *tunnel,
1836 const struct GNUNET_PeerIdentity *initiator,
1837 const struct GNUNET_ATS_Information *atsi)
1839 /* Why should anyone open an inbound tunnel to vpn? */
1846 * Function called whenever an inbound tunnel is destroyed. Should clean up
1847 * any associated state.
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
1855 tunnel_cleaner (void *cls, const struct GNUNET_MESH_Tunnel *tunnel, void *tunnel_ctx)
1857 /* FIXME: is this function called for outbound tunnels that go down?
1858 Should we clean up something here? */
1864 * Function scheduled as very last function, cleans up after us
1867 cleanup (void *cls GNUNET_UNUSED,
1868 const struct GNUNET_SCHEDULER_TaskContext *tskctx)
1872 // FIXME: clean up heaps and maps!
1873 if (NULL != mesh_handle)
1875 GNUNET_MESH_disconnect (mesh_handle);
1878 if (NULL != helper_handle)
1880 GNUNET_HELPER_stop (helper_handle);
1881 helper_handle = NULL;
1885 GNUNET_SERVER_notification_context_destroy (nc);
1889 GNUNET_free_non_null (vpn_argv[i]);
1894 * A client has disconnected from us. If we are currently building
1895 * a tunnel for it, cancel the operation.
1898 * @param client handle to the client that disconnected
1901 client_disconnect (void *cls, struct GNUNET_SERVER_Client *client)
1903 // FIXME: find all TunnelState's and check if they point
1904 // to the client and if so, clean the reference up!
1909 * Main function that will be run by the scheduler.
1911 * @param cls closure
1912 * @param server the initialized server
1913 * @param cfg_ configuration
1917 struct GNUNET_SERVER_Handle *server,
1918 const struct GNUNET_CONFIGURATION_Handle *cfg_)
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) },
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},
1935 static const GNUNET_MESH_ApplicationType types[] = {
1936 GNUNET_APPLICATION_TYPE_END
1948 GNUNET_CONFIGURATION_get_value_number (cfg, "vpn", "MAX_MAPPING",
1949 &max_destination_mappings))
1950 max_destination_mappings = 200;
1952 GNUNET_CONFIGURATION_get_value_number (cfg, "vpn", "MAX_TUNNELS",
1953 &max_tunnel_mappings))
1954 max_tunnel_mappings = 200;
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);
1962 vpn_argv[0] = GNUNET_strdup ("vpn-gnunet");
1963 if (GNUNET_SYSERR ==
1964 GNUNET_CONFIGURATION_get_value_string (cfg, "vpn", "IFNAME", &ifname))
1966 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1967 "No entry 'IFNAME' in configuration!\n");
1968 GNUNET_SCHEDULER_shutdown ();
1971 vpn_argv[1] = ifname;
1972 if ( (GNUNET_SYSERR ==
1973 GNUNET_CONFIGURATION_get_value_string (cfg, "vpn", "IPV6ADDR",
1975 (1 != inet_pton (AF_INET6, ipv6addr, &v6))) )
1977 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1978 "No valid entry 'IPV6ADDR' in configuration!\n");
1979 GNUNET_SCHEDULER_shutdown ();
1982 vpn_argv[2] = ipv6addr;
1983 if (GNUNET_SYSERR ==
1984 GNUNET_CONFIGURATION_get_value_string (cfg, "vpn", "IPV6PREFIX",
1987 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1988 "No entry 'IPV6PREFIX' in configuration!\n");
1989 GNUNET_SCHEDULER_shutdown ();
1992 vpn_argv[3] = ipv6prefix_s;
1994 GNUNET_CONFIGURATION_get_value_number (cfg, "vpn",
1997 (ipv6prefix >= 127) )
1999 GNUNET_SCHEDULER_shutdown ();
2003 if ( (GNUNET_SYSERR ==
2004 GNUNET_CONFIGURATION_get_value_string (cfg, "vpn", "IPV4ADDR",
2006 (1 != inet_pton (AF_INET, ipv4addr, &v4))) )
2008 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2009 "No valid entry for 'IPV4ADDR' in configuration!\n");
2010 GNUNET_SCHEDULER_shutdown ();
2013 vpn_argv[4] = ipv4addr;
2014 if ( (GNUNET_SYSERR ==
2015 GNUNET_CONFIGURATION_get_value_string (cfg, "vpn", "IPV4MASK",
2017 (1 != inet_pton (AF_INET, ipv4mask, &v4))) )
2019 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2020 "No valid entry 'IPV4MASK' in configuration!\n");
2021 GNUNET_SCHEDULER_shutdown ();
2024 vpn_argv[5] = ipv4mask;
2028 GNUNET_MESH_connect (cfg_, 42 /* queue length */, NULL,
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);
2043 * The main function of the VPN service.
2045 * @param argc number of arguments from the command line
2046 * @param argv command line arguments
2047 * @return 0 ok, 1 on error
2050 main (int argc, char *const *argv)
2052 return (GNUNET_OK ==
2053 GNUNET_SERVICE_run (argc, argv, "vpn",
2054 GNUNET_SERVICE_OPTION_NONE,
2055 &run, NULL)) ? 0 : 1;
2058 /* end of gnunet-service-vpn.c */