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 * - fully implement shutdown code
31 * - create secondary mesh tunnels if needed / check overall tunnel creation/management code!
33 * - better message queue management (bounded state, drop oldest/RED?)
34 * - improve support for deciding which tunnels to keep and which ones to destroy
35 * - add back ICMP support (especially needed for IPv6)
36 * - consider moving IP-header building / checksumming code into shared library
37 * with dns/exit/vpn (libgnunettun_tcpip?)
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,
1242 size_t size = sizeof (struct ip6_header)
1243 + sizeof (struct tcp_packet)
1244 + sizeof (struct GNUNET_MessageHeader) +
1245 sizeof (struct tun_header) +
1249 struct GNUNET_MessageHeader *msg = (struct GNUNET_MessageHeader *) buf;
1250 struct tun_header *tun = (struct tun_header*) &msg[1];
1251 struct ip6_header *ipv6 = (struct ip6_header *) &tun[1];
1252 struct tcp_packet *tcp = (struct tcp_packet *) &ipv6[1];
1253 msg->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
1254 msg->size = htons (size);
1255 tun->flags = htons (0);
1256 tun->proto = htons (ETH_P_IPV6);
1257 ipv6->traffic_class_h = 0;
1259 ipv6->traffic_class_l = 0;
1260 ipv6->flow_label = 0;
1261 ipv6->payload_length = htons (sizeof (struct tcp_packet) + sizeof (struct ip6_header) + mlen);
1262 ipv6->next_header = IPPROTO_TCP;
1263 ipv6->hop_limit = 255;
1264 ipv6->source_address = ts->destination_ip.v6;
1265 ipv6->destination_address = ts->source_ip.v6;
1266 tcp->spt = htons (ts->destination_port);
1267 tcp->dpt = htons (ts->source_port);
1273 sum = GNUNET_CRYPTO_crc16_step (sum, &ipv6->source_address, 2 * sizeof (struct in6_addr));
1274 tmp = htonl (sizeof (struct tcp_packet) + mlen);
1275 sum = GNUNET_CRYPTO_crc16_step (sum, &tmp, sizeof (uint32_t));
1276 tmp = htonl (IPPROTO_TCP);
1277 sum = GNUNET_CRYPTO_crc16_step (sum, &tmp, sizeof (uint32_t));
1278 sum = GNUNET_CRYPTO_crc16_step (sum, tcp,
1279 sizeof (struct tcp_packet) + mlen);
1280 tcp->crc = GNUNET_CRYPTO_crc16_finish (sum);
1282 (void) GNUNET_HELPER_send (helper_handle,
1292 // FIXME: refresh entry to avoid expiration...
1293 struct map_entry *me = GNUNET_CONTAINER_multihashmap_get (hashmap, key);
1295 GNUNET_CONTAINER_heap_update_cost (heap, me->heap_node,
1296 GNUNET_TIME_absolute_get ().abs_value);
1304 * Allocate an IPv4 address from the range of the tunnel
1305 * for a new redirection.
1307 * @param v4 where to store the address
1308 * @return GNUNET_OK on success,
1309 * GNUNET_SYSERR on error
1312 allocate_v4_address (struct in_addr *v4)
1314 const char *ipv4addr = vpn_argv[4];
1315 const char *ipv4mask = vpn_argv[5];
1316 struct in_addr addr;
1317 struct in_addr mask;
1319 GNUNET_HashCode key;
1322 GNUNET_assert (1 == inet_pton (AF_INET, ipv4addr, &addr));
1323 GNUNET_assert (1 == inet_pton (AF_INET, ipv4mask, &mask));
1324 /* Given 192.168.0.1/255.255.0.0, we want a mask
1325 of '192.168.255.255', thus: */
1326 mask.s_addr = addr.s_addr | ~mask.s_addr;
1333 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1334 _("Failed to find unallocated IPv4 address in VPN's range\n"));
1335 return GNUNET_SYSERR;
1337 /* Pick random IPv4 address within the subnet, except 'addr' or 'mask' itself */
1338 rnd.s_addr = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
1340 v4->s_addr = (addr.s_addr | rnd.s_addr) & mask.s_addr;
1341 get_destination_key_from_ip (AF_INET,
1345 while ( (GNUNET_YES ==
1346 GNUNET_CONTAINER_multihashmap_contains (destination_map,
1348 (v4->s_addr == addr.s_addr) ||
1349 (v4->s_addr == mask.s_addr) );
1355 * Allocate an IPv6 address from the range of the tunnel
1356 * for a new redirection.
1358 * @param v6 where to store the address
1359 * @return GNUNET_OK on success,
1360 * GNUNET_SYSERR on error
1363 allocate_v6_address (struct in6_addr *v6)
1365 const char *ipv6addr = vpn_argv[2];
1366 struct in6_addr addr;
1367 struct in6_addr mask;
1368 struct in6_addr rnd;
1370 GNUNET_HashCode key;
1373 GNUNET_assert (1 == inet_pton (AF_INET6, ipv6addr, &addr));
1374 GNUNET_assert (ipv6prefix < 128);
1375 /* Given ABCD::/96, we want a mask of 'ABCD::FFFF:FFFF,
1378 for (i=127;i>=128-ipv6prefix;i--)
1379 mask.s6_addr[i / 8] |= (1 << (i % 8));
1381 /* Pick random IPv6 address within the subnet, except 'addr' or 'mask' itself */
1388 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1389 _("Failed to find unallocated IPv6 address in VPN's range\n"));
1390 return GNUNET_SYSERR;
1395 rnd.s6_addr[i] = (unsigned char) GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
1398 = (addr.s6_addr[i] | rnd.s6_addr[i]) & mask.s6_addr[i];
1400 get_destination_key_from_ip (AF_INET6,
1404 while ( (GNUNET_YES ==
1405 GNUNET_CONTAINER_multihashmap_contains (destination_map,
1409 sizeof (struct in6_addr))) ||
1412 sizeof (struct in6_addr))) );
1418 * A client asks us to setup a redirection via some exit
1419 * node to a particular IP. Setup the redirection and
1420 * give the client the allocated IP.
1423 * @param client requesting client
1424 * @param message redirection request (a 'struct RedirectToIpRequestMessage')
1427 service_redirect_to_ip (void *cls GNUNET_UNUSED, struct GNUNET_SERVER_Client *client,
1428 const struct GNUNET_MessageHeader *message)
1432 const struct RedirectToIpRequestMessage *msg;
1438 struct DestinationEntry *de;
1439 GNUNET_HashCode key;
1440 struct TunnelState *ts;
1441 GNUNET_MESH_ApplicationType app_type;
1443 /* validate and parse request */
1444 mlen = ntohs (message->size);
1445 if (mlen < sizeof (struct RedirectToIpRequestMessage))
1448 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1451 alen = mlen - sizeof (struct RedirectToIpRequestMessage);
1452 msg = (const struct RedirectToIpRequestMessage *) message;
1453 addr_af = (int) htonl (msg->addr_af);
1457 if (alen != sizeof (struct in_addr))
1460 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1463 app_type = GNUNET_APPLICATION_TYPE_IPV4_GATEWAY;
1466 if (alen != sizeof (struct in6_addr))
1469 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1472 app_type = GNUNET_APPLICATION_TYPE_IPV6_GATEWAY;
1476 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1480 /* allocate response IP */
1482 result_af = (int) htonl (msg->result_af);
1487 allocate_v4_address (&v4))
1488 result_af = AF_UNSPEC;
1494 allocate_v6_address (&v6))
1495 result_af = AF_UNSPEC;
1501 allocate_v4_address (&v4))
1504 result_af = AF_INET;
1506 else if (GNUNET_OK ==
1507 allocate_v6_address (&v6))
1510 result_af = AF_INET6;
1515 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1518 if ( (result_af == AF_UNSPEC) ||
1519 (GNUNET_NO == ntohl (msg->nac)) )
1521 /* send reply "instantly" */
1522 send_client_reply (client,
1527 if (result_af == AF_UNSPEC)
1529 /* failure, we're done */
1530 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1534 /* setup destination record */
1535 de = GNUNET_malloc (sizeof (struct DestinationEntry));
1536 de->is_service = GNUNET_NO;
1537 de->details.exit_destination.af = addr_af;
1538 memcpy (&de->details.exit_destination.ip,
1541 get_destination_key_from_ip (result_af,
1544 GNUNET_assert (GNUNET_OK ==
1545 GNUNET_CONTAINER_multihashmap_put (destination_map,
1548 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE));
1549 de->heap_node = GNUNET_CONTAINER_heap_insert (destination_heap,
1551 GNUNET_TIME_absolute_ntoh (msg->expiration_time).abs_value);
1552 /* setup tunnel to destination */
1553 ts = GNUNET_malloc (sizeof (struct TunnelState));
1554 if (GNUNET_NO != ntohl (msg->nac))
1556 ts->request_id = msg->request_id;
1557 ts->client = client;
1558 GNUNET_SERVER_client_keep (client);
1560 ts->destination = *de;
1561 ts->destination.heap_node = NULL;
1562 ts->is_service = GNUNET_NO;
1564 if (result_af == AF_INET)
1565 ts->destination_ip.v4 = v4;
1567 ts->destination_ip.v6 = v6;
1568 de->tunnel = GNUNET_MESH_tunnel_create (mesh_handle,
1570 &tunnel_peer_connect_handler,
1571 &tunnel_peer_disconnect_handler,
1573 GNUNET_MESH_peer_request_connect_by_type (de->tunnel,
1576 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1581 * A client asks us to setup a redirection to a particular peer
1582 * offering a service. Setup the redirection and give the client the
1586 * @param client requesting client
1587 * @param message redirection request (a 'struct RedirectToPeerRequestMessage')
1590 service_redirect_to_service (void *cls GNUNET_UNUSED, struct GNUNET_SERVER_Client *client,
1591 const struct GNUNET_MessageHeader *message)
1593 const struct RedirectToServiceRequestMessage *msg;
1598 struct DestinationEntry *de;
1599 GNUNET_HashCode key;
1600 struct TunnelState *ts;
1603 msg = (const struct RedirectToServiceRequestMessage *) message;
1605 /* allocate response IP */
1607 result_af = (int) htonl (msg->result_af);
1612 allocate_v4_address (&v4))
1613 result_af = AF_UNSPEC;
1619 allocate_v6_address (&v6))
1620 result_af = AF_UNSPEC;
1626 allocate_v4_address (&v4))
1629 result_af = AF_INET;
1631 else if (GNUNET_OK ==
1632 allocate_v6_address (&v6))
1635 result_af = AF_INET6;
1640 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1643 if ( (result_af == AF_UNSPEC) ||
1644 (GNUNET_NO == ntohl (msg->nac)) )
1646 /* send reply "instantly" */
1647 send_client_reply (client,
1652 if (result_af == AF_UNSPEC)
1654 /* failure, we're done */
1655 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1659 /* setup destination record */
1660 de = GNUNET_malloc (sizeof (struct DestinationEntry));
1661 de->is_service = GNUNET_YES;
1662 de->details.service_destination.service_descriptor = msg->service_descriptor;
1663 de->details.service_destination.target = msg->target;
1664 get_destination_key_from_ip (result_af,
1667 GNUNET_assert (GNUNET_OK ==
1668 GNUNET_CONTAINER_multihashmap_put (destination_map,
1671 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE));
1672 de->heap_node = GNUNET_CONTAINER_heap_insert (destination_heap,
1674 GNUNET_TIME_absolute_ntoh (msg->expiration_time).abs_value);
1676 /* setup tunnel to destination */
1677 ts = GNUNET_malloc (sizeof (struct TunnelState));
1678 if (GNUNET_NO != ntohl (msg->nac))
1680 ts->request_id = msg->request_id;
1681 ts->client = client;
1682 GNUNET_SERVER_client_keep (client);
1684 ts->destination = *de;
1685 ts->destination.heap_node = NULL;
1686 ts->is_service = GNUNET_YES;
1688 if (result_af == AF_INET)
1689 ts->destination_ip.v4 = v4;
1691 ts->destination_ip.v6 = v6;
1692 de->tunnel = GNUNET_MESH_tunnel_create (mesh_handle,
1694 &tunnel_peer_connect_handler,
1695 &tunnel_peer_disconnect_handler,
1697 GNUNET_MESH_peer_request_connect_add (de->tunnel,
1700 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1706 * Function called for inbound tunnels. As we don't offer
1707 * any mesh services, this function should never be called.
1709 * @param cls closure
1710 * @param tunnel new handle to the tunnel
1711 * @param initiator peer that started the tunnel
1712 * @param atsi performance information for the tunnel
1713 * @return initial tunnel context for the tunnel
1714 * (can be NULL -- that's not an error)
1717 inbound_tunnel_cb (void *cls, struct GNUNET_MESH_Tunnel *tunnel,
1718 const struct GNUNET_PeerIdentity *initiator,
1719 const struct GNUNET_ATS_Information *atsi)
1721 /* Why should anyone open an inbound tunnel to vpn? */
1728 * Function called whenever an inbound tunnel is destroyed. Should clean up
1729 * any associated state.
1731 * @param cls closure (set from GNUNET_MESH_connect)
1732 * @param tunnel connection to the other end (henceforth invalid)
1733 * @param tunnel_ctx place where local state associated
1734 * with the tunnel is stored
1737 tunnel_cleaner (void *cls, const struct GNUNET_MESH_Tunnel *tunnel, void *tunnel_ctx)
1739 /* FIXME: is this function called for outbound tunnels that go down?
1740 Should we clean up something here? */
1746 * Function scheduled as very last function, cleans up after us
1749 cleanup (void *cls GNUNET_UNUSED,
1750 const struct GNUNET_SCHEDULER_TaskContext *tskctx)
1754 // FIXME: clean up heaps and maps!
1755 if (NULL != mesh_handle)
1757 GNUNET_MESH_disconnect (mesh_handle);
1760 if (NULL != helper_handle)
1762 GNUNET_HELPER_stop (helper_handle);
1763 helper_handle = NULL;
1767 GNUNET_SERVER_notification_context_destroy (nc);
1771 GNUNET_free_non_null (vpn_argv[i]);
1776 * A client has disconnected from us. If we are currently building
1777 * a tunnel for it, cancel the operation.
1780 * @param client handle to the client that disconnected
1783 client_disconnect (void *cls, struct GNUNET_SERVER_Client *client)
1785 // FIXME: find all TunnelState's and check if they point
1786 // to the client and if so, clean the reference up!
1791 * Main function that will be run by the scheduler.
1793 * @param cls closure
1794 * @param server the initialized server
1795 * @param cfg_ configuration
1799 struct GNUNET_SERVER_Handle *server,
1800 const struct GNUNET_CONFIGURATION_Handle *cfg_)
1802 static const struct GNUNET_SERVER_MessageHandler service_handlers[] = {
1803 /* callback, cls, type, size */
1804 {&service_redirect_to_ip, NULL, GNUNET_MESSAGE_TYPE_VPN_CLIENT_REDIRECT_TO_IP, 0},
1805 {&service_redirect_to_service, NULL,
1806 GNUNET_MESSAGE_TYPE_VPN_CLIENT_REDIRECT_TO_SERVICE,
1807 sizeof (struct RedirectToServiceRequestMessage) },
1810 static const struct GNUNET_MESH_MessageHandler mesh_handlers[] = {
1811 {receive_udp_back, GNUNET_MESSAGE_TYPE_VPN_SERVICE_UDP_BACK, 0},
1812 {receive_tcp_back, GNUNET_MESSAGE_TYPE_VPN_SERVICE_TCP_BACK, 0},
1813 {receive_udp_back, GNUNET_MESSAGE_TYPE_VPN_REMOTE_UDP_BACK, 0},
1814 {receive_tcp_back, GNUNET_MESSAGE_TYPE_VPN_REMOTE_TCP_BACK, 0},
1817 static const GNUNET_MESH_ApplicationType types[] = {
1818 GNUNET_APPLICATION_TYPE_END
1830 GNUNET_CONFIGURATION_get_value_number (cfg, "vpn", "MAX_MAPPING",
1831 &max_destination_mappings))
1832 max_destination_mappings = 200;
1834 GNUNET_CONFIGURATION_get_value_number (cfg, "vpn", "MAX_TUNNELS",
1835 &max_tunnel_mappings))
1836 max_tunnel_mappings = 200;
1838 destination_map = GNUNET_CONTAINER_multihashmap_create (max_destination_mappings * 2);
1839 destination_heap = GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN);
1840 tunnel_map = GNUNET_CONTAINER_multihashmap_create (max_tunnel_mappings * 2);
1841 tunnel_heap = GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN);
1844 vpn_argv[0] = GNUNET_strdup ("vpn-gnunet");
1845 if (GNUNET_SYSERR ==
1846 GNUNET_CONFIGURATION_get_value_string (cfg, "vpn", "IFNAME", &ifname))
1848 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1849 "No entry 'IFNAME' in configuration!\n");
1850 GNUNET_SCHEDULER_shutdown ();
1853 vpn_argv[1] = ifname;
1854 if ( (GNUNET_SYSERR ==
1855 GNUNET_CONFIGURATION_get_value_string (cfg, "vpn", "IPV6ADDR",
1857 (1 != inet_pton (AF_INET6, ipv6addr, &v6))) )
1859 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1860 "No valid entry 'IPV6ADDR' in configuration!\n");
1861 GNUNET_SCHEDULER_shutdown ();
1864 vpn_argv[2] = ipv6addr;
1865 if (GNUNET_SYSERR ==
1866 GNUNET_CONFIGURATION_get_value_string (cfg, "vpn", "IPV6PREFIX",
1869 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1870 "No entry 'IPV6PREFIX' in configuration!\n");
1871 GNUNET_SCHEDULER_shutdown ();
1874 vpn_argv[3] = ipv6prefix_s;
1876 GNUNET_CONFIGURATION_get_value_number (cfg, "vpn",
1879 (ipv6prefix >= 127) )
1881 GNUNET_SCHEDULER_shutdown ();
1885 if ( (GNUNET_SYSERR ==
1886 GNUNET_CONFIGURATION_get_value_string (cfg, "vpn", "IPV4ADDR",
1888 (1 != inet_pton (AF_INET, ipv4addr, &v4))) )
1890 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1891 "No valid entry for 'IPV4ADDR' in configuration!\n");
1892 GNUNET_SCHEDULER_shutdown ();
1895 vpn_argv[4] = ipv4addr;
1896 if ( (GNUNET_SYSERR ==
1897 GNUNET_CONFIGURATION_get_value_string (cfg, "vpn", "IPV4MASK",
1899 (1 != inet_pton (AF_INET, ipv4mask, &v4))) )
1901 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1902 "No valid entry 'IPV4MASK' in configuration!\n");
1903 GNUNET_SCHEDULER_shutdown ();
1906 vpn_argv[5] = ipv4mask;
1910 GNUNET_MESH_connect (cfg_, 42 /* queue length */, NULL,
1915 helper_handle = GNUNET_HELPER_start ("gnunet-helper-vpn", vpn_argv,
1916 &message_token, NULL);
1917 nc = GNUNET_SERVER_notification_context_create (server, 1);
1918 GNUNET_SERVER_add_handlers (server, service_handlers);
1919 GNUNET_SERVER_disconnect_notify (server, &client_disconnect, NULL);
1920 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &cleanup, cls);
1925 * The main function of the VPN service.
1927 * @param argc number of arguments from the command line
1928 * @param argv command line arguments
1929 * @return 0 ok, 1 on error
1932 main (int argc, char *const *argv)
1934 return (GNUNET_OK ==
1935 GNUNET_SERVICE_run (argc, argv, "vpn",
1936 GNUNET_SERVICE_OPTION_NONE,
1937 &run, NULL)) ? 0 : 1;
1940 /* end of gnunet-service-vpn.c */