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 * - keep multiple peers/mesh tunnels ready as alternative exits /
31 * recover from tunnel-to-exit failure gracefully
34 #include "gnunet_util_lib.h"
35 #include "gnunet_common.h"
36 #include "gnunet_protocols.h"
37 #include "gnunet_applications.h"
38 #include "gnunet_mesh_service.h"
39 #include "gnunet_statistics_service.h"
40 #include "gnunet_constants.h"
41 #include "gnunet_tun_lib.h"
42 #include "gnunet_regex_service.h"
48 * Maximum number of messages we allow in the queue for mesh.
50 #define MAX_MESSAGE_QUEUE_SIZE 4
56 * State we keep for each of our tunnels.
62 * Information we track for each IP address to determine which tunnel
63 * to send the traffic over to the destination.
65 struct DestinationEntry
69 * Key under which this entry is in the 'destination_map' (only valid
70 * if 'heap_node != NULL').
72 struct GNUNET_HashCode key;
75 * Pre-allocated tunnel for this destination, or NULL for none.
77 struct TunnelState *ts;
80 * Entry for this entry in the destination_heap.
82 struct GNUNET_CONTAINER_HeapNode *heap_node;
85 * #GNUNET_NO if this is a tunnel to an Internet-exit,
86 * #GNUNET_YES if this tunnel is to a service.
91 * Details about the connection (depending on is_service).
99 * The description of the service (only used for service tunnels).
101 struct GNUNET_HashCode service_descriptor;
104 * Peer offering the service.
106 struct GNUNET_PeerIdentity target;
108 } service_destination;
114 * Address family used (AF_INET or AF_INET6).
119 * IP address of the ultimate destination (only used for exit tunnels).
124 * Address if af is AF_INET.
129 * Address if af is AF_INET6.
142 * A messages we have in queue for a particular tunnel.
144 struct TunnelMessageQueueEntry
147 * This is a doubly-linked list.
149 struct TunnelMessageQueueEntry *next;
152 * This is a doubly-linked list.
154 struct TunnelMessageQueueEntry *prev;
157 * Number of bytes in 'msg'.
162 * Message to transmit, allocated at the end of this struct.
169 * State we keep for each of our tunnels.
175 * Information about the tunnel to use, NULL if no tunnel
176 * is available right now.
178 struct GNUNET_MESH_Tunnel *tunnel;
181 * Active query with REGEX to locate exit.
183 struct GNUNET_REGEX_Search *search;
186 * Active transmission handle, NULL for none.
188 struct GNUNET_MESH_TransmitHandle *th;
191 * Entry for this entry in the tunnel_heap, NULL as long as this
192 * tunnel state is not fully bound.
194 struct GNUNET_CONTAINER_HeapNode *heap_node;
197 * Head of list of messages scheduled for transmission.
199 struct TunnelMessageQueueEntry *tmq_head;
202 * Tail of list of messages scheduled for transmission.
204 struct TunnelMessageQueueEntry *tmq_tail;
207 * Client that needs to be notified about the tunnel being
208 * up as soon as a peer is connected; NULL for none.
210 struct GNUNET_SERVER_Client *client;
213 * Destination entry that has a pointer to this tunnel state;
214 * NULL if this tunnel state is in the tunnel map.
216 struct DestinationEntry *destination_container;
219 * ID of the client request that caused us to setup this entry.
224 * Destination to which this tunnel leads. Note that
225 * this struct is NOT in the destination_map (but a
226 * local copy) and that the 'heap_node' should always
229 struct DestinationEntry destination;
232 * Task scheduled to destroy the tunnel (or NO_TASK).
234 GNUNET_SCHEDULER_TaskIdentifier destroy_task;
237 * Addess family used for this tunnel on the local TUN interface.
242 * Length of the doubly linked 'tmq_head/tmq_tail' list.
244 unsigned int tmq_length;
247 * IPPROTO_TCP or IPPROTO_UDP once bound.
252 * IP address of the source on our end, initially uninitialized.
257 * Address if af is AF_INET.
262 * Address if af is AF_INET6.
269 * Destination IP address used by the source on our end (this is the IP
270 * that we pick freely within the VPN's tunnel IP range).
275 * Address if af is AF_INET.
280 * Address if af is AF_INET6.
287 * Source port used by the sender on our end; 0 for uninitialized.
289 uint16_t source_port;
292 * Destination port used by the sender on our end; 0 for uninitialized.
294 uint16_t destination_port;
300 * Return value from 'main'.
302 static int global_ret;
305 * Configuration we use.
307 static const struct GNUNET_CONFIGURATION_Handle *cfg;
310 * Handle to the mesh service.
312 static struct GNUNET_MESH_Handle *mesh_handle;
315 * Map from IP address to destination information (possibly with a
316 * MESH tunnel handle for fast setup).
318 static struct GNUNET_CONTAINER_MultiHashMap *destination_map;
321 * Min-Heap sorted by activity time to expire old mappings.
323 static struct GNUNET_CONTAINER_Heap *destination_heap;
326 * Map from source and destination address (IP+port) to connection
327 * information (mostly with the respective MESH tunnel handle).
329 static struct GNUNET_CONTAINER_MultiHashMap *tunnel_map;
332 * Min-Heap sorted by activity time to expire old mappings; values are
333 * of type 'struct TunnelState'.
335 static struct GNUNET_CONTAINER_Heap *tunnel_heap;
340 static struct GNUNET_STATISTICS_Handle *stats;
343 * The handle to the VPN helper process "gnunet-helper-vpn".
345 static struct GNUNET_HELPER_Handle *helper_handle;
348 * Arguments to the vpn helper.
350 static char *vpn_argv[7];
353 * Length of the prefix of the VPN's IPv6 network.
355 static unsigned long long ipv6prefix;
358 * Notification context for sending replies to clients.
360 static struct GNUNET_SERVER_NotificationContext *nc;
363 * If there are more than this number of address-mappings, old ones
366 static unsigned long long max_destination_mappings;
369 * If there are more than this number of open tunnels, old ones
372 static unsigned long long max_tunnel_mappings;
376 * Compute the key under which we would store an entry in the
377 * destination_map for the given IP address.
379 * @param af address family (AF_INET or AF_INET6)
380 * @param address IP address, struct in_addr or struct in6_addr
381 * @param key where to store the key
384 get_destination_key_from_ip (int af,
386 struct GNUNET_HashCode *key)
391 GNUNET_CRYPTO_hash (address,
392 sizeof (struct in_addr),
396 GNUNET_CRYPTO_hash (address,
397 sizeof (struct in6_addr),
408 * Compute the key under which we would store an entry in the
409 * tunnel_map for the given socket address pair.
411 * @param af address family (AF_INET or AF_INET6)
412 * @param protocol IPPROTO_TCP or IPPROTO_UDP
413 * @param source_ip sender's source IP, struct in_addr or struct in6_addr
414 * @param source_port sender's source port
415 * @param destination_ip sender's destination IP, struct in_addr or struct in6_addr
416 * @param destination_port sender's destination port
417 * @param key where to store the key
420 get_tunnel_key_from_ips (int af,
422 const void *source_ip,
423 uint16_t source_port,
424 const void *destination_ip,
425 uint16_t destination_port,
426 struct GNUNET_HashCode *key)
430 memset (key, 0, sizeof (struct GNUNET_HashCode));
431 /* the GNUnet hashmap only uses the first sizeof(unsigned int) of the hash,
432 so we put the ports in there (and hope for few collisions) */
434 memcpy (off, &source_port, sizeof (uint16_t));
435 off += sizeof (uint16_t);
436 memcpy (off, &destination_port, sizeof (uint16_t));
437 off += sizeof (uint16_t);
441 memcpy (off, source_ip, sizeof (struct in_addr));
442 off += sizeof (struct in_addr);
443 memcpy (off, destination_ip, sizeof (struct in_addr));
444 off += sizeof (struct in_addr);
447 memcpy (off, source_ip, sizeof (struct in6_addr));
448 off += sizeof (struct in6_addr);
449 memcpy (off, destination_ip, sizeof (struct in6_addr));
450 off += sizeof (struct in6_addr);
456 memcpy (off, &protocol, sizeof (uint8_t));
457 /* off += sizeof (uint8_t); */
462 * Notify the client about the result of its request.
464 * @param client client to notify
465 * @param request_id original request ID to include in response
466 * @param result_af resulting address family
467 * @param addr resulting IP address
470 send_client_reply (struct GNUNET_SERVER_Client *client,
475 char buf[sizeof (struct RedirectToIpResponseMessage) + sizeof (struct in6_addr)] GNUNET_ALIGN;
476 struct RedirectToIpResponseMessage *res;
482 rlen = sizeof (struct in_addr);
485 rlen = sizeof (struct in6_addr);
494 res = (struct RedirectToIpResponseMessage *) buf;
495 res->header.size = htons (sizeof (struct RedirectToIpResponseMessage) + rlen);
496 res->header.type = htons (GNUNET_MESSAGE_TYPE_VPN_CLIENT_USE_IP);
497 res->result_af = htonl (result_af);
498 res->request_id = request_id;
499 memcpy (&res[1], addr, rlen);
500 GNUNET_SERVER_notification_context_add (nc, client);
501 GNUNET_SERVER_notification_context_unicast (nc,
509 * Free resources associated with a tunnel state.
511 * @param ts state to free
514 free_tunnel_state (struct TunnelState *ts)
516 struct GNUNET_HashCode key;
517 struct TunnelMessageQueueEntry *tnq;
518 struct GNUNET_MESH_Tunnel *tunnel;
520 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
521 "Cleaning up tunnel state\n");
522 GNUNET_STATISTICS_update (stats,
523 gettext_noop ("# Active tunnels"),
525 while (NULL != (tnq = ts->tmq_head))
527 GNUNET_CONTAINER_DLL_remove (ts->tmq_head,
533 GNUNET_assert (0 == ts->tmq_length);
536 GNUNET_MESH_notify_transmit_ready_cancel (ts->th);
539 GNUNET_assert (NULL == ts->destination.heap_node);
540 if (NULL != (tunnel = ts->tunnel))
543 GNUNET_MESH_tunnel_destroy (tunnel);
545 if (NULL != ts->search)
547 GNUNET_REGEX_search_cancel (ts->search);
550 if (GNUNET_SCHEDULER_NO_TASK != ts->destroy_task)
552 GNUNET_SCHEDULER_cancel (ts->destroy_task);
553 ts->destroy_task = GNUNET_SCHEDULER_NO_TASK;
555 if (NULL != ts->heap_node)
557 GNUNET_CONTAINER_heap_remove_node (ts->heap_node);
558 ts->heap_node = NULL;
559 get_tunnel_key_from_ips (ts->af,
564 ts->destination_port,
566 GNUNET_assert (GNUNET_YES ==
567 GNUNET_CONTAINER_multihashmap_remove (tunnel_map,
571 if (NULL != ts->destination_container)
573 GNUNET_assert (ts == ts->destination_container->ts);
574 ts->destination_container->ts = NULL;
575 ts->destination_container = NULL;
582 * Destroy the mesh tunnel.
584 * @param cls the `struct TunnelState` with the tunnel to destroy
585 * @param tc scheduler context
588 destroy_tunnel_task (void *cls,
589 const struct GNUNET_SCHEDULER_TaskContext *tc)
591 struct TunnelState *ts = cls;
592 struct GNUNET_MESH_Tunnel *tunnel;
594 ts->destroy_task = GNUNET_SCHEDULER_NO_TASK;
595 GNUNET_assert (NULL != ts->tunnel);
598 GNUNET_MESH_tunnel_destroy (tunnel);
599 free_tunnel_state (ts);
604 * Method called whenever a peer has disconnected from the tunnel.
606 * FIXME merge with inbound_cleaner
609 * @param peer peer identity the tunnel stopped working with
612 tunnel_peer_disconnect_handler (void *cls,
614 GNUNET_PeerIdentity *peer)
616 struct TunnelState *ts = cls;
618 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
619 "Peer %s disconnected from tunnel.\n",
621 GNUNET_STATISTICS_update (stats,
622 gettext_noop ("# peers connected to mesh tunnels"),
626 GNUNET_MESH_notify_transmit_ready_cancel (ts->th);
629 if (ts->destination.is_service)
630 return; /* hope for reconnect eventually */
631 /* as we are most likely going to change the exit node now,
632 we should just destroy the tunnel entirely... */
633 if (GNUNET_SCHEDULER_NO_TASK == ts->destroy_task)
634 ts->destroy_task = GNUNET_SCHEDULER_add_now (&destroy_tunnel_task, ts);
639 * Method called whenever a peer has connected to the tunnel. Notifies
640 * the waiting client that the tunnel is now up.
642 * FIXME merge with tunnel_create
645 * @param peer peer identity the tunnel was created to, NULL on timeout
646 * @param atsi performance data for the connection
649 tunnel_peer_connect_handler (void *cls,
650 const struct GNUNET_PeerIdentity *peer,
652 GNUNET_ATS_Information * atsi)
654 struct TunnelState *ts = cls;
656 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
657 "Peer %s connected to tunnel.\n",
659 GNUNET_STATISTICS_update (stats,
660 gettext_noop ("# peers connected to mesh tunnels"),
662 if (NULL == ts->client)
663 return; /* nothing to do */
664 send_client_reply (ts->client,
667 &ts->destination_ip);
673 * Send a message from the message queue via mesh.
675 * @param cls the `struct TunnelState` with the message queue
676 * @param size number of bytes available in @a buf
677 * @param buf where to copy the message
678 * @return number of bytes copied to @a buf
681 send_to_peer_notify_callback (void *cls, size_t size, void *buf)
683 struct TunnelState *ts = cls;
684 struct TunnelMessageQueueEntry *tnq;
691 GNUNET_assert (NULL != tnq);
692 GNUNET_assert (size >= tnq->len);
693 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
694 "Sending %u bytes via mesh tunnel\n",
696 GNUNET_CONTAINER_DLL_remove (ts->tmq_head,
700 memcpy (buf, tnq->msg, tnq->len);
703 if (NULL != (tnq = ts->tmq_head))
704 ts->th = GNUNET_MESH_notify_transmit_ready (ts->tunnel,
705 GNUNET_NO /* cork */,
706 GNUNET_TIME_UNIT_FOREVER_REL,
708 &send_to_peer_notify_callback,
710 GNUNET_STATISTICS_update (stats,
711 gettext_noop ("# Bytes given to mesh for transmission"),
718 * Add the given message to the given tunnel and trigger the
719 * transmission process.
721 * @param tnq message to queue
722 * @param ts tunnel to queue the message for
725 send_to_tunnel (struct TunnelMessageQueueEntry *tnq,
726 struct TunnelState *ts)
728 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
729 "Queueing %u bytes for transmission via mesh tunnel\n",
731 GNUNET_assert (NULL != ts->tunnel);
732 GNUNET_CONTAINER_DLL_insert_tail (ts->tmq_head,
736 if (ts->tmq_length > MAX_MESSAGE_QUEUE_SIZE)
738 struct TunnelMessageQueueEntry *dq;
741 GNUNET_assert (dq != tnq);
742 GNUNET_CONTAINER_DLL_remove (ts->tmq_head,
746 GNUNET_MESH_notify_transmit_ready_cancel (ts->th);
748 GNUNET_STATISTICS_update (stats,
749 gettext_noop ("# Bytes dropped in mesh queue (overflow)"),
755 ts->th = GNUNET_MESH_notify_transmit_ready (ts->tunnel,
756 GNUNET_NO /* cork */,
757 GNUNET_TIME_UNIT_FOREVER_REL,
759 &send_to_peer_notify_callback,
765 * Regex has found a potential exit peer for us; consider using it.
767 * @param cls the 'struct TunnelState'
768 * @param id Peer providing a regex that matches the string.
769 * @param get_path Path of the get request.
770 * @param get_path_length Lenght of get_path.
771 * @param put_path Path of the put request.
772 * @param put_path_length Length of the put_path.
775 handle_regex_result (void *cls,
776 const struct GNUNET_PeerIdentity *id,
777 const struct GNUNET_PeerIdentity *get_path,
778 unsigned int get_path_length,
779 const struct GNUNET_PeerIdentity *put_path,
780 unsigned int put_path_length)
782 struct TunnelState *ts = cls;
784 GNUNET_REGEX_search_cancel (ts->search);
786 ts->tunnel = GNUNET_MESH_tunnel_create (mesh_handle,
796 * Initialize the given destination entry's mesh tunnel.
798 * @param de destination entry for which we need to setup a tunnel
799 * @param client client to notify on successful tunnel setup, or NULL for none
800 * @param client_af address family of the address returned to the client
801 * @param request_id request ID to send in client notification (unused if client is NULL)
802 * @return tunnel state of the tunnel that was created
804 static struct TunnelState *
805 create_tunnel_to_destination (struct DestinationEntry *de,
806 struct GNUNET_SERVER_Client *client,
810 struct TunnelState *ts;
812 GNUNET_STATISTICS_update (stats,
813 gettext_noop ("# Mesh tunnels created"),
815 GNUNET_assert (NULL == de->ts);
816 ts = GNUNET_new (struct TunnelState);
820 ts->request_id = request_id;
823 ts->destination = *de;
824 ts->destination.heap_node = NULL; /* copy is NOT in destination heap */
826 ts->destination_container = de; /* we are referenced from de */
829 ts->tunnel = GNUNET_MESH_tunnel_create (mesh_handle,
831 &de->details.service_destination.target,
835 if (NULL == ts->tunnel)
837 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
838 _("Failed to setup mesh tunnel!\n"));
842 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
843 "Creating tunnel to peer %s offering service %s\n",
844 GNUNET_i2s (&de->details.service_destination.target),
845 GNUNET_h2s (&de->details.service_destination.service_descriptor));
851 switch (de->details.exit_destination.af)
855 char address[GNUNET_TUN_IPV4_REGEXLEN];
857 GNUNET_TUN_ipv4toregexsearch (&de->details.exit_destination.ip.v4,
858 "255.255.255.255", address);
859 GNUNET_asprintf (&policy, "%s%s%s",
860 GNUNET_APPLICATION_TYPE_EXIT_REGEX_PREFIX,
867 char address[GNUNET_TUN_IPV6_REGEXLEN];
869 GNUNET_TUN_ipv6toregexsearch (&de->details.exit_destination.ip.v6,
871 GNUNET_asprintf (&policy, "%s%s%s",
872 GNUNET_APPLICATION_TYPE_EXIT_REGEX_PREFIX,
882 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
883 "Requesting connect by string: %s\n",
885 ts->search = GNUNET_REGEX_search (cfg,
887 &handle_regex_result,
889 GNUNET_free (policy);
896 * We have too many active tunnels. Clean up the oldest tunnel.
898 * @param except tunnel that must NOT be cleaned up, even if it is the oldest
901 expire_tunnel (struct TunnelState *except)
903 struct TunnelState *ts;
905 ts = GNUNET_CONTAINER_heap_peek (tunnel_heap);
906 GNUNET_assert (NULL != ts);
908 return; /* can't do this */
909 free_tunnel_state (ts);
914 * Route a packet via mesh to the given destination.
916 * @param destination description of the destination
917 * @param af address family on this end (AF_INET or AF_INET6)
918 * @param protocol IPPROTO_TCP or IPPROTO_UDP or IPPROTO_ICMP or IPPROTO_ICMPV6
919 * @param source_ip source IP used by the sender (struct in_addr or struct in6_addr)
920 * @param destination_ip destination IP used by the sender (struct in_addr or struct in6_addr)
921 * @param payload payload of the packet after the IP header
922 * @param payload_length number of bytes in payload
925 route_packet (struct DestinationEntry *destination,
928 const void *source_ip,
929 const void *destination_ip,
931 size_t payload_length)
933 struct GNUNET_HashCode key;
934 struct TunnelState *ts;
935 struct TunnelMessageQueueEntry *tnq;
939 const struct GNUNET_TUN_UdpHeader *udp;
940 const struct GNUNET_TUN_TcpHeader *tcp;
941 const struct GNUNET_TUN_IcmpHeader *icmp;
942 uint16_t source_port;
943 uint16_t destination_port;
949 if (payload_length < sizeof (struct GNUNET_TUN_UdpHeader))
955 tcp = NULL; /* make compiler happy */
956 icmp = NULL; /* make compiler happy */
958 if (udp->len < sizeof (struct GNUNET_TUN_UdpHeader))
963 source_port = ntohs (udp->source_port);
964 destination_port = ntohs (udp->destination_port);
965 get_tunnel_key_from_ips (af,
976 if (payload_length < sizeof (struct GNUNET_TUN_TcpHeader))
982 udp = NULL; /* make compiler happy */
983 icmp = NULL; /* make compiler happy */
985 if (tcp->off * 4 < sizeof (struct GNUNET_TUN_TcpHeader))
990 source_port = ntohs (tcp->source_port);
991 destination_port = ntohs (tcp->destination_port);
992 get_tunnel_key_from_ips (af,
1002 case IPPROTO_ICMPV6:
1004 if ( (AF_INET == af) ^ (protocol == IPPROTO_ICMP) )
1009 if (payload_length < sizeof (struct GNUNET_TUN_IcmpHeader))
1015 tcp = NULL; /* make compiler happy */
1016 udp = NULL; /* make compiler happy */
1019 destination_port = 0;
1020 get_tunnel_key_from_ips (af,
1030 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1031 _("Protocol %u not supported, dropping\n"),
1032 (unsigned int) protocol);
1036 if (! destination->is_service)
1038 switch (destination->details.exit_destination.af)
1041 alen = sizeof (struct in_addr);
1044 alen = sizeof (struct in6_addr);
1051 char sbuf[INET6_ADDRSTRLEN];
1052 char dbuf[INET6_ADDRSTRLEN];
1053 char xbuf[INET6_ADDRSTRLEN];
1055 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1056 "Routing %s packet from %s:%u -> %s:%u to destination %s:%u\n",
1057 (protocol == IPPROTO_TCP) ? "TCP" : "UDP",
1058 inet_ntop (af, source_ip, sbuf, sizeof (sbuf)),
1060 inet_ntop (af, destination_ip, dbuf, sizeof (dbuf)),
1062 inet_ntop (destination->details.exit_destination.af,
1063 &destination->details.exit_destination.ip,
1064 xbuf, sizeof (xbuf)),
1071 char sbuf[INET6_ADDRSTRLEN];
1072 char dbuf[INET6_ADDRSTRLEN];
1074 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1075 "Routing %s packet from %s:%u -> %s:%u to service %s at peer %s\n",
1076 (protocol == IPPROTO_TCP) ? "TCP" : "UDP",
1077 inet_ntop (af, source_ip, sbuf, sizeof (sbuf)),
1079 inet_ntop (af, destination_ip, dbuf, sizeof (dbuf)),
1081 GNUNET_h2s (&destination->details.service_destination.service_descriptor),
1082 GNUNET_i2s (&destination->details.service_destination.target));
1087 /* see if we have an existing tunnel for this destination */
1088 ts = GNUNET_CONTAINER_multihashmap_get (tunnel_map,
1092 /* need to either use the existing tunnel from the destination (if still
1093 available) or create a fresh one */
1094 is_new = GNUNET_YES;
1095 if (NULL == destination->ts)
1096 ts = create_tunnel_to_destination (destination, NULL, af, 0);
1098 ts = destination->ts;
1101 destination->ts = NULL;
1102 ts->destination_container = NULL; /* no longer 'contained' */
1103 /* now bind existing "unbound" tunnel to our IP/port tuple */
1104 ts->protocol = protocol;
1108 ts->source_ip.v4 = * (const struct in_addr *) source_ip;
1109 ts->destination_ip.v4 = * (const struct in_addr *) destination_ip;
1113 ts->source_ip.v6 = * (const struct in6_addr *) source_ip;
1114 ts->destination_ip.v6 = * (const struct in6_addr *) destination_ip;
1116 ts->source_port = source_port;
1117 ts->destination_port = destination_port;
1118 ts->heap_node = GNUNET_CONTAINER_heap_insert (tunnel_heap,
1120 GNUNET_TIME_absolute_get ().abs_value_us);
1121 GNUNET_assert (GNUNET_YES ==
1122 GNUNET_CONTAINER_multihashmap_put (tunnel_map,
1125 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
1126 GNUNET_STATISTICS_update (stats,
1127 gettext_noop ("# Active tunnels"),
1129 while (GNUNET_CONTAINER_multihashmap_size (tunnel_map) > max_tunnel_mappings)
1135 GNUNET_CONTAINER_heap_update_cost (tunnel_heap,
1137 GNUNET_TIME_absolute_get ().abs_value_us);
1139 GNUNET_assert (NULL != ts->tunnel);
1141 /* send via tunnel */
1145 if (destination->is_service)
1147 struct GNUNET_EXIT_UdpServiceMessage *usm;
1149 mlen = sizeof (struct GNUNET_EXIT_UdpServiceMessage) +
1150 payload_length - sizeof (struct GNUNET_TUN_UdpHeader);
1151 if (mlen >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1156 tnq = GNUNET_malloc (sizeof (struct TunnelMessageQueueEntry) + mlen);
1159 usm = (struct GNUNET_EXIT_UdpServiceMessage *) &tnq[1];
1160 usm->header.size = htons ((uint16_t) mlen);
1161 usm->header.type = htons (GNUNET_MESSAGE_TYPE_VPN_UDP_TO_SERVICE);
1162 /* if the source port is below 32000, we assume it has a special
1163 meaning; if not, we pick a random port (this is a heuristic) */
1164 usm->source_port = (ntohs (udp->source_port) < 32000) ? udp->source_port : 0;
1165 usm->destination_port = udp->destination_port;
1166 usm->service_descriptor = destination->details.service_destination.service_descriptor;
1169 payload_length - sizeof (struct GNUNET_TUN_UdpHeader));
1173 struct GNUNET_EXIT_UdpInternetMessage *uim;
1174 struct in_addr *ip4dst;
1175 struct in6_addr *ip6dst;
1178 mlen = sizeof (struct GNUNET_EXIT_UdpInternetMessage) +
1179 alen + payload_length - sizeof (struct GNUNET_TUN_UdpHeader);
1180 if (mlen >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1185 tnq = GNUNET_malloc (sizeof (struct TunnelMessageQueueEntry) +
1189 uim = (struct GNUNET_EXIT_UdpInternetMessage *) &tnq[1];
1190 uim->header.size = htons ((uint16_t) mlen);
1191 uim->header.type = htons (GNUNET_MESSAGE_TYPE_VPN_UDP_TO_INTERNET);
1192 uim->af = htonl (destination->details.exit_destination.af);
1193 uim->source_port = (ntohs (udp->source_port) < 32000) ? udp->source_port : 0;
1194 uim->destination_port = udp->destination_port;
1195 switch (destination->details.exit_destination.af)
1198 ip4dst = (struct in_addr *) &uim[1];
1199 *ip4dst = destination->details.exit_destination.ip.v4;
1200 payload = &ip4dst[1];
1203 ip6dst = (struct in6_addr *) &uim[1];
1204 *ip6dst = destination->details.exit_destination.ip.v6;
1205 payload = &ip6dst[1];
1212 payload_length - sizeof (struct GNUNET_TUN_UdpHeader));
1218 if (destination->is_service)
1220 struct GNUNET_EXIT_TcpServiceStartMessage *tsm;
1222 mlen = sizeof (struct GNUNET_EXIT_TcpServiceStartMessage) +
1223 payload_length - sizeof (struct GNUNET_TUN_TcpHeader);
1224 if (mlen >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1229 tnq = GNUNET_malloc (sizeof (struct TunnelMessageQueueEntry) + mlen);
1232 tsm = (struct GNUNET_EXIT_TcpServiceStartMessage *) &tnq[1];
1233 tsm->header.size = htons ((uint16_t) mlen);
1234 tsm->header.type = htons (GNUNET_MESSAGE_TYPE_VPN_TCP_TO_SERVICE_START);
1235 tsm->reserved = htonl (0);
1236 tsm->service_descriptor = destination->details.service_destination.service_descriptor;
1237 tsm->tcp_header = *tcp;
1240 payload_length - sizeof (struct GNUNET_TUN_TcpHeader));
1244 struct GNUNET_EXIT_TcpInternetStartMessage *tim;
1245 struct in_addr *ip4dst;
1246 struct in6_addr *ip6dst;
1249 mlen = sizeof (struct GNUNET_EXIT_TcpInternetStartMessage) +
1250 alen + payload_length - sizeof (struct GNUNET_TUN_TcpHeader);
1251 if (mlen >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1256 tnq = GNUNET_malloc (sizeof (struct TunnelMessageQueueEntry) + mlen);
1259 tim = (struct GNUNET_EXIT_TcpInternetStartMessage *) &tnq[1];
1260 tim->header.size = htons ((uint16_t) mlen);
1261 tim->header.type = htons (GNUNET_MESSAGE_TYPE_VPN_TCP_TO_INTERNET_START);
1262 tim->af = htonl (destination->details.exit_destination.af);
1263 tim->tcp_header = *tcp;
1264 switch (destination->details.exit_destination.af)
1267 ip4dst = (struct in_addr *) &tim[1];
1268 *ip4dst = destination->details.exit_destination.ip.v4;
1269 payload = &ip4dst[1];
1272 ip6dst = (struct in6_addr *) &tim[1];
1273 *ip6dst = destination->details.exit_destination.ip.v6;
1274 payload = &ip6dst[1];
1281 payload_length - sizeof (struct GNUNET_TUN_TcpHeader));
1286 struct GNUNET_EXIT_TcpDataMessage *tdm;
1288 mlen = sizeof (struct GNUNET_EXIT_TcpDataMessage) +
1289 payload_length - sizeof (struct GNUNET_TUN_TcpHeader);
1290 if (mlen >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1295 tnq = GNUNET_malloc (sizeof (struct TunnelMessageQueueEntry) + mlen);
1298 tdm = (struct GNUNET_EXIT_TcpDataMessage *) &tnq[1];
1299 tdm->header.size = htons ((uint16_t) mlen);
1300 tdm->header.type = htons (GNUNET_MESSAGE_TYPE_VPN_TCP_DATA_TO_EXIT);
1301 tdm->reserved = htonl (0);
1302 tdm->tcp_header = *tcp;
1305 payload_length - sizeof (struct GNUNET_TUN_TcpHeader));
1309 case IPPROTO_ICMPV6:
1310 if (destination->is_service)
1312 struct GNUNET_EXIT_IcmpServiceMessage *ism;
1314 mlen = sizeof (struct GNUNET_EXIT_IcmpServiceMessage) +
1315 payload_length - sizeof (struct GNUNET_TUN_IcmpHeader);
1316 if (mlen >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1321 tnq = GNUNET_malloc (sizeof (struct TunnelMessageQueueEntry) + mlen);
1323 ism = (struct GNUNET_EXIT_IcmpServiceMessage *) &tnq[1];
1324 ism->header.type = htons (GNUNET_MESSAGE_TYPE_VPN_ICMP_TO_SERVICE);
1325 ism->af = htonl (af); /* need to tell destination ICMP protocol family! */
1326 ism->service_descriptor = destination->details.service_destination.service_descriptor;
1327 ism->icmp_header = *icmp;
1328 /* ICMP protocol translation will be done by the receiver (as we don't know
1329 the target AF); however, we still need to possibly discard the payload
1330 depending on the ICMP type */
1336 case GNUNET_TUN_ICMPTYPE_ECHO_REPLY:
1337 case GNUNET_TUN_ICMPTYPE_ECHO_REQUEST:
1339 case GNUNET_TUN_ICMPTYPE_DESTINATION_UNREACHABLE:
1340 case GNUNET_TUN_ICMPTYPE_SOURCE_QUENCH:
1341 case GNUNET_TUN_ICMPTYPE_TIME_EXCEEDED:
1342 /* throw away ICMP payload, won't be useful for the other side anyway */
1343 payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
1346 GNUNET_STATISTICS_update (stats,
1347 gettext_noop ("# ICMPv4 packets dropped (not allowed)"),
1351 /* end of AF_INET */
1356 case GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE:
1357 case GNUNET_TUN_ICMPTYPE6_PACKET_TOO_BIG:
1358 case GNUNET_TUN_ICMPTYPE6_TIME_EXCEEDED:
1359 case GNUNET_TUN_ICMPTYPE6_PARAMETER_PROBLEM:
1360 /* throw away ICMP payload, won't be useful for the other side anyway */
1361 payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
1363 case GNUNET_TUN_ICMPTYPE6_ECHO_REQUEST:
1364 case GNUNET_TUN_ICMPTYPE6_ECHO_REPLY:
1367 GNUNET_STATISTICS_update (stats,
1368 gettext_noop ("# ICMPv6 packets dropped (not allowed)"),
1372 /* end of AF_INET6 */
1379 /* update length calculations, as payload_length may have changed */
1380 mlen = sizeof (struct GNUNET_EXIT_IcmpServiceMessage) +
1381 alen + payload_length - sizeof (struct GNUNET_TUN_IcmpHeader);
1383 ism->header.size = htons ((uint16_t) mlen);
1384 /* finally, copy payload (if there is any left...) */
1387 payload_length - sizeof (struct GNUNET_TUN_IcmpHeader));
1391 struct GNUNET_EXIT_IcmpInternetMessage *iim;
1392 struct in_addr *ip4dst;
1393 struct in6_addr *ip6dst;
1396 mlen = sizeof (struct GNUNET_EXIT_IcmpInternetMessage) +
1397 alen + payload_length - sizeof (struct GNUNET_TUN_IcmpHeader);
1398 if (mlen >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1403 tnq = GNUNET_malloc (sizeof (struct TunnelMessageQueueEntry) +
1406 iim = (struct GNUNET_EXIT_IcmpInternetMessage *) &tnq[1];
1407 iim->header.type = htons (GNUNET_MESSAGE_TYPE_VPN_ICMP_TO_INTERNET);
1408 iim->icmp_header = *icmp;
1409 /* Perform ICMP protocol-translation (depending on destination AF and source AF)
1410 and throw away ICMP payload depending on ICMP message type */
1416 case GNUNET_TUN_ICMPTYPE_ECHO_REPLY:
1417 if (destination->details.exit_destination.af == AF_INET6)
1418 iim->icmp_header.type = GNUNET_TUN_ICMPTYPE6_ECHO_REPLY;
1420 case GNUNET_TUN_ICMPTYPE_ECHO_REQUEST:
1421 if (destination->details.exit_destination.af == AF_INET6)
1422 iim->icmp_header.type = GNUNET_TUN_ICMPTYPE6_ECHO_REQUEST;
1424 case GNUNET_TUN_ICMPTYPE_DESTINATION_UNREACHABLE:
1425 if (destination->details.exit_destination.af == AF_INET6)
1426 iim->icmp_header.type = GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE;
1427 /* throw away IP-payload, exit will have to make it up anyway */
1428 payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
1430 case GNUNET_TUN_ICMPTYPE_TIME_EXCEEDED:
1431 if (destination->details.exit_destination.af == AF_INET6)
1432 iim->icmp_header.type = GNUNET_TUN_ICMPTYPE6_TIME_EXCEEDED;
1433 /* throw away IP-payload, exit will have to make it up anyway */
1434 payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
1436 case GNUNET_TUN_ICMPTYPE_SOURCE_QUENCH:
1437 if (destination->details.exit_destination.af == AF_INET6)
1439 GNUNET_STATISTICS_update (stats,
1440 gettext_noop ("# ICMPv4 packets dropped (impossible PT to v6)"),
1445 /* throw away IP-payload, exit will have to make it up anyway */
1446 payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
1449 GNUNET_STATISTICS_update (stats,
1450 gettext_noop ("# ICMPv4 packets dropped (type not allowed)"),
1455 /* end of AF_INET */
1460 case GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE:
1461 if (destination->details.exit_destination.af == AF_INET6)
1462 iim->icmp_header.type = GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE;
1463 /* throw away IP-payload, exit will have to make it up anyway */
1464 payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
1466 case GNUNET_TUN_ICMPTYPE6_TIME_EXCEEDED:
1467 if (destination->details.exit_destination.af == AF_INET)
1468 iim->icmp_header.type = GNUNET_TUN_ICMPTYPE_TIME_EXCEEDED;
1469 /* throw away IP-payload, exit will have to make it up anyway */
1470 payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
1472 case GNUNET_TUN_ICMPTYPE6_PACKET_TOO_BIG:
1473 if (destination->details.exit_destination.af == AF_INET)
1475 GNUNET_STATISTICS_update (stats,
1476 gettext_noop ("# ICMPv6 packets dropped (impossible PT to v4)"),
1481 /* throw away IP-payload, exit will have to make it up anyway */
1482 payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
1484 case GNUNET_TUN_ICMPTYPE6_PARAMETER_PROBLEM:
1485 if (destination->details.exit_destination.af == AF_INET)
1487 GNUNET_STATISTICS_update (stats,
1488 gettext_noop ("# ICMPv6 packets dropped (impossible PT to v4)"),
1493 /* throw away IP-payload, exit will have to make it up anyway */
1494 payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
1496 case GNUNET_TUN_ICMPTYPE6_ECHO_REQUEST:
1497 if (destination->details.exit_destination.af == AF_INET)
1498 iim->icmp_header.type = GNUNET_TUN_ICMPTYPE_ECHO_REQUEST;
1500 case GNUNET_TUN_ICMPTYPE6_ECHO_REPLY:
1501 if (destination->details.exit_destination.af == AF_INET)
1502 iim->icmp_header.type = GNUNET_TUN_ICMPTYPE_ECHO_REPLY;
1505 GNUNET_STATISTICS_update (stats,
1506 gettext_noop ("# ICMPv6 packets dropped (type not allowed)"),
1511 /* end of AF_INET6 */
1516 /* update length calculations, as payload_length may have changed */
1517 mlen = sizeof (struct GNUNET_EXIT_IcmpInternetMessage) +
1518 alen + payload_length - sizeof (struct GNUNET_TUN_IcmpHeader);
1520 iim->header.size = htons ((uint16_t) mlen);
1522 /* need to tell destination ICMP protocol family! */
1523 iim->af = htonl (destination->details.exit_destination.af);
1524 switch (destination->details.exit_destination.af)
1527 ip4dst = (struct in_addr *) &iim[1];
1528 *ip4dst = destination->details.exit_destination.ip.v4;
1529 payload = &ip4dst[1];
1532 ip6dst = (struct in6_addr *) &iim[1];
1533 *ip6dst = destination->details.exit_destination.ip.v6;
1534 payload = &ip6dst[1];
1541 payload_length - sizeof (struct GNUNET_TUN_IcmpHeader));
1545 /* not supported above, how can we get here !? */
1549 send_to_tunnel (tnq, ts);
1554 * Receive packets from the helper-process (someone send to the local
1555 * virtual tunnel interface). Find the destination mapping, and if it
1556 * exists, identify the correct MESH tunnel (or possibly create it)
1557 * and forward the packet.
1559 * @param cls closure, NULL
1560 * @param client NULL
1561 * @param message message we got from the client (VPN tunnel interface)
1564 message_token (void *cls GNUNET_UNUSED, void *client GNUNET_UNUSED,
1565 const struct GNUNET_MessageHeader *message)
1567 const struct GNUNET_TUN_Layer2PacketHeader *tun;
1569 struct GNUNET_HashCode key;
1570 struct DestinationEntry *de;
1572 GNUNET_STATISTICS_update (stats,
1573 gettext_noop ("# Packets received from TUN interface"),
1575 mlen = ntohs (message->size);
1576 if ( (ntohs (message->type) != GNUNET_MESSAGE_TYPE_VPN_HELPER) ||
1577 (mlen < sizeof (struct GNUNET_MessageHeader) + sizeof (struct GNUNET_TUN_Layer2PacketHeader)) )
1582 tun = (const struct GNUNET_TUN_Layer2PacketHeader *) &message[1];
1583 mlen -= (sizeof (struct GNUNET_MessageHeader) + sizeof (struct GNUNET_TUN_Layer2PacketHeader));
1584 switch (ntohs (tun->proto))
1588 const struct GNUNET_TUN_IPv6Header *pkt6;
1590 if (mlen < sizeof (struct GNUNET_TUN_IPv6Header))
1596 pkt6 = (const struct GNUNET_TUN_IPv6Header *) &tun[1];
1597 get_destination_key_from_ip (AF_INET6,
1598 &pkt6->destination_address,
1600 de = GNUNET_CONTAINER_multihashmap_get (destination_map, &key);
1603 char buf[INET6_ADDRSTRLEN];
1605 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1606 _("Packet received for unmapped destination `%s' (dropping it)\n"),
1607 inet_ntop (AF_INET6,
1608 &pkt6->destination_address,
1616 &pkt6->source_address,
1617 &pkt6->destination_address,
1619 mlen - sizeof (struct GNUNET_TUN_IPv6Header));
1624 struct GNUNET_TUN_IPv4Header *pkt4;
1626 if (mlen < sizeof (struct GNUNET_TUN_IPv4Header))
1632 pkt4 = (struct GNUNET_TUN_IPv4Header *) &tun[1];
1633 get_destination_key_from_ip (AF_INET,
1634 &pkt4->destination_address,
1636 de = GNUNET_CONTAINER_multihashmap_get (destination_map, &key);
1639 char buf[INET_ADDRSTRLEN];
1641 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1642 _("Packet received for unmapped destination `%s' (dropping it)\n"),
1644 &pkt4->destination_address,
1649 if (pkt4->header_length * 4 != sizeof (struct GNUNET_TUN_IPv4Header))
1651 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1652 _("Received IPv4 packet with options (dropping it)\n"));
1658 &pkt4->source_address,
1659 &pkt4->destination_address,
1661 mlen - sizeof (struct GNUNET_TUN_IPv4Header));
1665 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1666 _("Received packet of unknown protocol %d from TUN (dropping it)\n"),
1667 (unsigned int) ntohs (tun->proto));
1675 * Synthesize a plausible ICMP payload for an ICMP error
1676 * response on the given tunnel.
1678 * @param ts tunnel information
1679 * @param ipp IPv4 header to fill in (ICMP payload)
1680 * @param udp "UDP" header to fill in (ICMP payload); might actually
1681 * also be the first 8 bytes of the TCP header
1684 make_up_icmpv4_payload (struct TunnelState *ts,
1685 struct GNUNET_TUN_IPv4Header *ipp,
1686 struct GNUNET_TUN_UdpHeader *udp)
1688 GNUNET_TUN_initialize_ipv4_header (ipp,
1690 sizeof (struct GNUNET_TUN_TcpHeader),
1692 &ts->destination_ip.v4);
1693 udp->source_port = htons (ts->source_port);
1694 udp->destination_port = htons (ts->destination_port);
1695 udp->len = htons (0);
1696 udp->crc = htons (0);
1701 * Synthesize a plausible ICMP payload for an ICMP error
1702 * response on the given tunnel.
1704 * @param ts tunnel information
1705 * @param ipp IPv6 header to fill in (ICMP payload)
1706 * @param udp "UDP" header to fill in (ICMP payload); might actually
1707 * also be the first 8 bytes of the TCP header
1710 make_up_icmpv6_payload (struct TunnelState *ts,
1711 struct GNUNET_TUN_IPv6Header *ipp,
1712 struct GNUNET_TUN_UdpHeader *udp)
1714 GNUNET_TUN_initialize_ipv6_header (ipp,
1716 sizeof (struct GNUNET_TUN_TcpHeader),
1718 &ts->destination_ip.v6);
1719 udp->source_port = htons (ts->source_port);
1720 udp->destination_port = htons (ts->destination_port);
1721 udp->len = htons (0);
1722 udp->crc = htons (0);
1727 * We got an ICMP packet back from the MESH tunnel. Pass it on to the
1728 * local virtual interface via the helper.
1730 * @param cls closure, NULL
1731 * @param tunnel connection to the other end
1732 * @param tunnel_ctx pointer to our 'struct TunnelState *'
1733 * @param message the actual message
1734 * @return #GNUNET_OK to keep the connection open,
1735 * #GNUNET_SYSERR to close it (signal serious error)
1738 receive_icmp_back (void *cls GNUNET_UNUSED, struct GNUNET_MESH_Tunnel *tunnel,
1740 const struct GNUNET_MessageHeader *message)
1742 struct TunnelState *ts = *tunnel_ctx;
1743 const struct GNUNET_EXIT_IcmpToVPNMessage *i2v;
1746 GNUNET_STATISTICS_update (stats,
1747 gettext_noop ("# ICMP packets received from mesh"),
1749 mlen = ntohs (message->size);
1750 if (mlen < sizeof (struct GNUNET_EXIT_IcmpToVPNMessage))
1752 GNUNET_break_op (0);
1753 return GNUNET_SYSERR;
1755 if (NULL == ts->heap_node)
1757 GNUNET_break_op (0);
1758 return GNUNET_SYSERR;
1760 if (AF_UNSPEC == ts->af)
1762 GNUNET_break_op (0);
1763 return GNUNET_SYSERR;
1765 i2v = (const struct GNUNET_EXIT_IcmpToVPNMessage *) message;
1766 mlen -= sizeof (struct GNUNET_EXIT_IcmpToVPNMessage);
1768 char sbuf[INET6_ADDRSTRLEN];
1769 char dbuf[INET6_ADDRSTRLEN];
1771 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1772 "Received ICMP packet from mesh, sending %u bytes from %s -> %s via TUN\n",
1773 (unsigned int) mlen,
1774 inet_ntop (ts->af, &ts->destination_ip, sbuf, sizeof (sbuf)),
1775 inet_ntop (ts->af, &ts->source_ip, dbuf, sizeof (dbuf)));
1781 size_t size = sizeof (struct GNUNET_TUN_IPv4Header)
1782 + sizeof (struct GNUNET_TUN_IcmpHeader)
1783 + sizeof (struct GNUNET_MessageHeader) +
1784 sizeof (struct GNUNET_TUN_Layer2PacketHeader) +
1787 /* reserve some extra space in case we have an ICMP type here where
1788 we will need to make up the payload ourselves */
1789 char buf[size + sizeof (struct GNUNET_TUN_IPv4Header) + 8] GNUNET_ALIGN;
1790 struct GNUNET_MessageHeader *msg = (struct GNUNET_MessageHeader *) buf;
1791 struct GNUNET_TUN_Layer2PacketHeader *tun = (struct GNUNET_TUN_Layer2PacketHeader*) &msg[1];
1792 struct GNUNET_TUN_IPv4Header *ipv4 = (struct GNUNET_TUN_IPv4Header *) &tun[1];
1793 struct GNUNET_TUN_IcmpHeader *icmp = (struct GNUNET_TUN_IcmpHeader *) &ipv4[1];
1794 msg->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
1795 tun->flags = htons (0);
1796 tun->proto = htons (ETH_P_IPV4);
1797 GNUNET_TUN_initialize_ipv4_header (ipv4,
1799 sizeof (struct GNUNET_TUN_IcmpHeader) + mlen,
1800 &ts->destination_ip.v4,
1802 *icmp = i2v->icmp_header;
1806 /* For some ICMP types, we need to adjust (make up) the payload here.
1807 Also, depending on the AF used on the other side, we have to
1808 do ICMP PT (translate ICMP types) */
1809 switch (ntohl (i2v->af))
1814 case GNUNET_TUN_ICMPTYPE_ECHO_REPLY:
1815 case GNUNET_TUN_ICMPTYPE_ECHO_REQUEST:
1817 case GNUNET_TUN_ICMPTYPE_DESTINATION_UNREACHABLE:
1818 case GNUNET_TUN_ICMPTYPE_SOURCE_QUENCH:
1819 case GNUNET_TUN_ICMPTYPE_TIME_EXCEEDED:
1821 struct GNUNET_TUN_IPv4Header *ipp = (struct GNUNET_TUN_IPv4Header *) &icmp[1];
1822 struct GNUNET_TUN_UdpHeader *udp = (struct GNUNET_TUN_UdpHeader *) &ipp[1];
1826 /* sender did not strip ICMP payload? */
1827 GNUNET_break_op (0);
1828 return GNUNET_SYSERR;
1830 size += sizeof (struct GNUNET_TUN_IPv4Header) + 8;
1831 GNUNET_assert (8 == sizeof (struct GNUNET_TUN_UdpHeader));
1832 make_up_icmpv4_payload (ts, ipp, udp);
1836 GNUNET_break_op (0);
1837 GNUNET_STATISTICS_update (stats,
1838 gettext_noop ("# ICMPv4 packets dropped (type not allowed)"),
1840 return GNUNET_SYSERR;
1845 /* ICMP PT 6-to-4 and possibly making up payloads */
1848 case GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE:
1849 icmp->type = GNUNET_TUN_ICMPTYPE_DESTINATION_UNREACHABLE;
1851 struct GNUNET_TUN_IPv4Header *ipp = (struct GNUNET_TUN_IPv4Header *) &icmp[1];
1852 struct GNUNET_TUN_UdpHeader *udp = (struct GNUNET_TUN_UdpHeader *) &ipp[1];
1856 /* sender did not strip ICMP payload? */
1857 GNUNET_break_op (0);
1858 return GNUNET_SYSERR;
1860 size += sizeof (struct GNUNET_TUN_IPv4Header) + 8;
1861 GNUNET_assert (8 == sizeof (struct GNUNET_TUN_UdpHeader));
1862 make_up_icmpv4_payload (ts, ipp, udp);
1865 case GNUNET_TUN_ICMPTYPE6_TIME_EXCEEDED:
1866 icmp->type = GNUNET_TUN_ICMPTYPE_TIME_EXCEEDED;
1868 struct GNUNET_TUN_IPv4Header *ipp = (struct GNUNET_TUN_IPv4Header *) &icmp[1];
1869 struct GNUNET_TUN_UdpHeader *udp = (struct GNUNET_TUN_UdpHeader *) &ipp[1];
1873 /* sender did not strip ICMP payload? */
1874 GNUNET_break_op (0);
1875 return GNUNET_SYSERR;
1877 size += sizeof (struct GNUNET_TUN_IPv4Header) + 8;
1878 GNUNET_assert (8 == sizeof (struct GNUNET_TUN_UdpHeader));
1879 make_up_icmpv4_payload (ts, ipp, udp);
1882 case GNUNET_TUN_ICMPTYPE6_PACKET_TOO_BIG:
1883 case GNUNET_TUN_ICMPTYPE6_PARAMETER_PROBLEM:
1884 GNUNET_STATISTICS_update (stats,
1885 gettext_noop ("# ICMPv6 packets dropped (impossible PT to v4)"),
1888 case GNUNET_TUN_ICMPTYPE6_ECHO_REQUEST:
1889 icmp->type = GNUNET_TUN_ICMPTYPE_ECHO_REQUEST;
1891 case GNUNET_TUN_ICMPTYPE6_ECHO_REPLY:
1892 icmp->type = GNUNET_TUN_ICMPTYPE_ECHO_REPLY;
1895 GNUNET_break_op (0);
1896 GNUNET_STATISTICS_update (stats,
1897 gettext_noop ("# ICMPv6 packets dropped (type not allowed)"),
1899 return GNUNET_SYSERR;
1904 GNUNET_break_op (0);
1905 return GNUNET_SYSERR;
1907 msg->size = htons (size);
1908 GNUNET_TUN_calculate_icmp_checksum (icmp,
1911 (void) GNUNET_HELPER_send (helper_handle,
1920 size_t size = sizeof (struct GNUNET_TUN_IPv6Header)
1921 + sizeof (struct GNUNET_TUN_IcmpHeader)
1922 + sizeof (struct GNUNET_MessageHeader) +
1923 sizeof (struct GNUNET_TUN_Layer2PacketHeader) +
1926 char buf[size + sizeof (struct GNUNET_TUN_IPv6Header) + 8] GNUNET_ALIGN;
1927 struct GNUNET_MessageHeader *msg = (struct GNUNET_MessageHeader *) buf;
1928 struct GNUNET_TUN_Layer2PacketHeader *tun = (struct GNUNET_TUN_Layer2PacketHeader*) &msg[1];
1929 struct GNUNET_TUN_IPv6Header *ipv6 = (struct GNUNET_TUN_IPv6Header *) &tun[1];
1930 struct GNUNET_TUN_IcmpHeader *icmp = (struct GNUNET_TUN_IcmpHeader *) &ipv6[1];
1931 msg->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
1932 tun->flags = htons (0);
1933 tun->proto = htons (ETH_P_IPV6);
1934 GNUNET_TUN_initialize_ipv6_header (ipv6,
1936 sizeof (struct GNUNET_TUN_IcmpHeader) + mlen,
1937 &ts->destination_ip.v6,
1939 *icmp = i2v->icmp_header;
1944 /* For some ICMP types, we need to adjust (make up) the payload here.
1945 Also, depending on the AF used on the other side, we have to
1946 do ICMP PT (translate ICMP types) */
1947 switch (ntohl (i2v->af))
1950 /* ICMP PT 4-to-6 and possibly making up payloads */
1953 case GNUNET_TUN_ICMPTYPE_ECHO_REPLY:
1954 icmp->type = GNUNET_TUN_ICMPTYPE6_ECHO_REPLY;
1956 case GNUNET_TUN_ICMPTYPE_ECHO_REQUEST:
1957 icmp->type = GNUNET_TUN_ICMPTYPE6_ECHO_REQUEST;
1959 case GNUNET_TUN_ICMPTYPE_DESTINATION_UNREACHABLE:
1960 icmp->type = GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE;
1962 struct GNUNET_TUN_IPv6Header *ipp = (struct GNUNET_TUN_IPv6Header *) &icmp[1];
1963 struct GNUNET_TUN_UdpHeader *udp = (struct GNUNET_TUN_UdpHeader *) &ipp[1];
1967 /* sender did not strip ICMP payload? */
1968 GNUNET_break_op (0);
1969 return GNUNET_SYSERR;
1971 size += sizeof (struct GNUNET_TUN_IPv6Header) + 8;
1972 GNUNET_assert (8 == sizeof (struct GNUNET_TUN_UdpHeader));
1973 make_up_icmpv6_payload (ts, ipp, udp);
1976 case GNUNET_TUN_ICMPTYPE_TIME_EXCEEDED:
1977 icmp->type = GNUNET_TUN_ICMPTYPE6_TIME_EXCEEDED;
1979 struct GNUNET_TUN_IPv6Header *ipp = (struct GNUNET_TUN_IPv6Header *) &icmp[1];
1980 struct GNUNET_TUN_UdpHeader *udp = (struct GNUNET_TUN_UdpHeader *) &ipp[1];
1984 /* sender did not strip ICMP payload? */
1985 GNUNET_break_op (0);
1986 return GNUNET_SYSERR;
1988 size += sizeof (struct GNUNET_TUN_IPv6Header) + 8;
1989 GNUNET_assert (8 == sizeof (struct GNUNET_TUN_UdpHeader));
1990 make_up_icmpv6_payload (ts, ipp, udp);
1993 case GNUNET_TUN_ICMPTYPE_SOURCE_QUENCH:
1994 GNUNET_STATISTICS_update (stats,
1995 gettext_noop ("# ICMPv4 packets dropped (impossible PT to v6)"),
1999 GNUNET_break_op (0);
2000 GNUNET_STATISTICS_update (stats,
2001 gettext_noop ("# ICMPv4 packets dropped (type not allowed)"),
2003 return GNUNET_SYSERR;
2010 case GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE:
2011 case GNUNET_TUN_ICMPTYPE6_TIME_EXCEEDED:
2012 case GNUNET_TUN_ICMPTYPE6_PACKET_TOO_BIG:
2013 case GNUNET_TUN_ICMPTYPE6_PARAMETER_PROBLEM:
2015 struct GNUNET_TUN_IPv6Header *ipp = (struct GNUNET_TUN_IPv6Header *) &icmp[1];
2016 struct GNUNET_TUN_UdpHeader *udp = (struct GNUNET_TUN_UdpHeader *) &ipp[1];
2020 /* sender did not strip ICMP payload? */
2021 GNUNET_break_op (0);
2022 return GNUNET_SYSERR;
2024 size += sizeof (struct GNUNET_TUN_IPv6Header) + 8;
2025 GNUNET_assert (8 == sizeof (struct GNUNET_TUN_UdpHeader));
2026 make_up_icmpv6_payload (ts, ipp, udp);
2029 case GNUNET_TUN_ICMPTYPE6_ECHO_REQUEST:
2032 GNUNET_break_op (0);
2033 GNUNET_STATISTICS_update (stats,
2034 gettext_noop ("# ICMPv6 packets dropped (type not allowed)"),
2036 return GNUNET_SYSERR;
2041 GNUNET_break_op (0);
2042 return GNUNET_SYSERR;
2044 msg->size = htons (size);
2045 GNUNET_TUN_calculate_icmp_checksum (icmp,
2047 (void) GNUNET_HELPER_send (helper_handle,
2057 GNUNET_CONTAINER_heap_update_cost (tunnel_heap,
2059 GNUNET_TIME_absolute_get ().abs_value_us);
2065 * We got a UDP packet back from the MESH tunnel. Pass it on to the
2066 * local virtual interface via the helper.
2068 * @param cls closure, NULL
2069 * @param tunnel connection to the other end
2070 * @param tunnel_ctx pointer to our 'struct TunnelState *'
2071 * @param message the actual message
2072 * @return #GNUNET_OK to keep the connection open,
2073 * #GNUNET_SYSERR to close it (signal serious error)
2076 receive_udp_back (void *cls GNUNET_UNUSED, struct GNUNET_MESH_Tunnel *tunnel,
2078 const struct GNUNET_MessageHeader *message)
2080 struct TunnelState *ts = *tunnel_ctx;
2081 const struct GNUNET_EXIT_UdpReplyMessage *reply;
2084 GNUNET_STATISTICS_update (stats,
2085 gettext_noop ("# UDP packets received from mesh"),
2087 mlen = ntohs (message->size);
2088 if (mlen < sizeof (struct GNUNET_EXIT_UdpReplyMessage))
2090 GNUNET_break_op (0);
2091 return GNUNET_SYSERR;
2093 if (NULL == ts->heap_node)
2095 GNUNET_break_op (0);
2096 return GNUNET_SYSERR;
2098 if (AF_UNSPEC == ts->af)
2100 GNUNET_break_op (0);
2101 return GNUNET_SYSERR;
2103 reply = (const struct GNUNET_EXIT_UdpReplyMessage *) message;
2104 mlen -= sizeof (struct GNUNET_EXIT_UdpReplyMessage);
2106 char sbuf[INET6_ADDRSTRLEN];
2107 char dbuf[INET6_ADDRSTRLEN];
2109 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2110 "Received UDP reply from mesh, sending %u bytes from %s:%u -> %s:%u via TUN\n",
2111 (unsigned int) mlen,
2112 inet_ntop (ts->af, &ts->destination_ip, sbuf, sizeof (sbuf)),
2113 ts->destination_port,
2114 inet_ntop (ts->af, &ts->source_ip, dbuf, sizeof (dbuf)),
2121 size_t size = sizeof (struct GNUNET_TUN_IPv4Header)
2122 + sizeof (struct GNUNET_TUN_UdpHeader)
2123 + sizeof (struct GNUNET_MessageHeader) +
2124 sizeof (struct GNUNET_TUN_Layer2PacketHeader) +
2127 char buf[size] GNUNET_ALIGN;
2128 struct GNUNET_MessageHeader *msg = (struct GNUNET_MessageHeader *) buf;
2129 struct GNUNET_TUN_Layer2PacketHeader *tun = (struct GNUNET_TUN_Layer2PacketHeader*) &msg[1];
2130 struct GNUNET_TUN_IPv4Header *ipv4 = (struct GNUNET_TUN_IPv4Header *) &tun[1];
2131 struct GNUNET_TUN_UdpHeader *udp = (struct GNUNET_TUN_UdpHeader *) &ipv4[1];
2132 msg->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
2133 msg->size = htons (size);
2134 tun->flags = htons (0);
2135 tun->proto = htons (ETH_P_IPV4);
2136 GNUNET_TUN_initialize_ipv4_header (ipv4,
2138 sizeof (struct GNUNET_TUN_UdpHeader) + mlen,
2139 &ts->destination_ip.v4,
2141 if (0 == ntohs (reply->source_port))
2142 udp->source_port = htons (ts->destination_port);
2144 udp->source_port = reply->source_port;
2145 if (0 == ntohs (reply->destination_port))
2146 udp->destination_port = htons (ts->source_port);
2148 udp->destination_port = reply->destination_port;
2149 udp->len = htons (mlen + sizeof (struct GNUNET_TUN_UdpHeader));
2150 GNUNET_TUN_calculate_udp4_checksum (ipv4,
2157 (void) GNUNET_HELPER_send (helper_handle,
2166 size_t size = sizeof (struct GNUNET_TUN_IPv6Header)
2167 + sizeof (struct GNUNET_TUN_UdpHeader)
2168 + sizeof (struct GNUNET_MessageHeader) +
2169 sizeof (struct GNUNET_TUN_Layer2PacketHeader) +
2172 char buf[size] GNUNET_ALIGN;
2173 struct GNUNET_MessageHeader *msg = (struct GNUNET_MessageHeader *) buf;
2174 struct GNUNET_TUN_Layer2PacketHeader *tun = (struct GNUNET_TUN_Layer2PacketHeader*) &msg[1];
2175 struct GNUNET_TUN_IPv6Header *ipv6 = (struct GNUNET_TUN_IPv6Header *) &tun[1];
2176 struct GNUNET_TUN_UdpHeader *udp = (struct GNUNET_TUN_UdpHeader *) &ipv6[1];
2177 msg->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
2178 msg->size = htons (size);
2179 tun->flags = htons (0);
2180 tun->proto = htons (ETH_P_IPV6);
2181 GNUNET_TUN_initialize_ipv6_header (ipv6,
2183 sizeof (struct GNUNET_TUN_UdpHeader) + mlen,
2184 &ts->destination_ip.v6,
2186 if (0 == ntohs (reply->source_port))
2187 udp->source_port = htons (ts->destination_port);
2189 udp->source_port = reply->source_port;
2190 if (0 == ntohs (reply->destination_port))
2191 udp->destination_port = htons (ts->source_port);
2193 udp->destination_port = reply->destination_port;
2194 udp->len = htons (mlen + sizeof (struct GNUNET_TUN_UdpHeader));
2195 GNUNET_TUN_calculate_udp6_checksum (ipv6,
2201 (void) GNUNET_HELPER_send (helper_handle,
2211 GNUNET_CONTAINER_heap_update_cost (tunnel_heap,
2213 GNUNET_TIME_absolute_get ().abs_value_us);
2219 * We got a TCP packet back from the MESH tunnel. Pass it on to the
2220 * local virtual interface via the helper.
2222 * @param cls closure, NULL
2223 * @param tunnel connection to the other end
2224 * @param tunnel_ctx pointer to our `struct TunnelState *`
2225 * @param message the actual message
2226 * @return #GNUNET_OK to keep the connection open,
2227 * #GNUNET_SYSERR to close it (signal serious error)
2230 receive_tcp_back (void *cls GNUNET_UNUSED, struct GNUNET_MESH_Tunnel *tunnel,
2232 const struct GNUNET_MessageHeader *message)
2234 struct TunnelState *ts = *tunnel_ctx;
2235 const struct GNUNET_EXIT_TcpDataMessage *data;
2238 GNUNET_STATISTICS_update (stats,
2239 gettext_noop ("# TCP packets received from mesh"),
2241 mlen = ntohs (message->size);
2242 if (mlen < sizeof (struct GNUNET_EXIT_TcpDataMessage))
2244 GNUNET_break_op (0);
2245 return GNUNET_SYSERR;
2247 if (NULL == ts->heap_node)
2249 GNUNET_break_op (0);
2250 return GNUNET_SYSERR;
2252 data = (const struct GNUNET_EXIT_TcpDataMessage *) message;
2253 mlen -= sizeof (struct GNUNET_EXIT_TcpDataMessage);
2255 char sbuf[INET6_ADDRSTRLEN];
2256 char dbuf[INET6_ADDRSTRLEN];
2258 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2259 "Received TCP reply from mesh, sending %u bytes from %s:%u -> %s:%u via TUN\n",
2260 (unsigned int) mlen,
2261 inet_ntop (ts->af, &ts->destination_ip, sbuf, sizeof (sbuf)),
2262 ts->destination_port,
2263 inet_ntop (ts->af, &ts->source_ip, dbuf, sizeof (dbuf)),
2266 if (data->tcp_header.off * 4 < sizeof (struct GNUNET_TUN_TcpHeader))
2268 GNUNET_break_op (0);
2269 return GNUNET_SYSERR;
2275 size_t size = sizeof (struct GNUNET_TUN_IPv4Header)
2276 + sizeof (struct GNUNET_TUN_TcpHeader)
2277 + sizeof (struct GNUNET_MessageHeader) +
2278 sizeof (struct GNUNET_TUN_Layer2PacketHeader) +
2281 char buf[size] GNUNET_ALIGN;
2282 struct GNUNET_MessageHeader *msg = (struct GNUNET_MessageHeader *) buf;
2283 struct GNUNET_TUN_Layer2PacketHeader *tun = (struct GNUNET_TUN_Layer2PacketHeader*) &msg[1];
2284 struct GNUNET_TUN_IPv4Header *ipv4 = (struct GNUNET_TUN_IPv4Header *) &tun[1];
2285 struct GNUNET_TUN_TcpHeader *tcp = (struct GNUNET_TUN_TcpHeader *) &ipv4[1];
2286 msg->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
2287 msg->size = htons (size);
2288 tun->flags = htons (0);
2289 tun->proto = htons (ETH_P_IPV4);
2290 GNUNET_TUN_initialize_ipv4_header (ipv4,
2292 sizeof (struct GNUNET_TUN_TcpHeader) + mlen,
2293 &ts->destination_ip.v4,
2295 *tcp = data->tcp_header;
2296 tcp->source_port = htons (ts->destination_port);
2297 tcp->destination_port = htons (ts->source_port);
2298 GNUNET_TUN_calculate_tcp4_checksum (ipv4,
2305 (void) GNUNET_HELPER_send (helper_handle,
2314 size_t size = sizeof (struct GNUNET_TUN_IPv6Header)
2315 + sizeof (struct GNUNET_TUN_TcpHeader)
2316 + sizeof (struct GNUNET_MessageHeader) +
2317 sizeof (struct GNUNET_TUN_Layer2PacketHeader) +
2320 char buf[size] GNUNET_ALIGN;
2321 struct GNUNET_MessageHeader *msg = (struct GNUNET_MessageHeader *) buf;
2322 struct GNUNET_TUN_Layer2PacketHeader *tun = (struct GNUNET_TUN_Layer2PacketHeader*) &msg[1];
2323 struct GNUNET_TUN_IPv6Header *ipv6 = (struct GNUNET_TUN_IPv6Header *) &tun[1];
2324 struct GNUNET_TUN_TcpHeader *tcp = (struct GNUNET_TUN_TcpHeader *) &ipv6[1];
2325 msg->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
2326 msg->size = htons (size);
2327 tun->flags = htons (0);
2328 tun->proto = htons (ETH_P_IPV6);
2329 GNUNET_TUN_initialize_ipv6_header (ipv6,
2331 sizeof (struct GNUNET_TUN_TcpHeader) + mlen,
2332 &ts->destination_ip.v6,
2334 *tcp = data->tcp_header;
2335 tcp->source_port = htons (ts->destination_port);
2336 tcp->destination_port = htons (ts->source_port);
2337 GNUNET_TUN_calculate_tcp6_checksum (ipv6,
2344 (void) GNUNET_HELPER_send (helper_handle,
2352 GNUNET_CONTAINER_heap_update_cost (tunnel_heap,
2354 GNUNET_TIME_absolute_get ().abs_value_us);
2360 * Allocate an IPv4 address from the range of the tunnel
2361 * for a new redirection.
2363 * @param v4 where to store the address
2364 * @return #GNUNET_OK on success,
2365 * #GNUNET_SYSERR on error
2368 allocate_v4_address (struct in_addr *v4)
2370 const char *ipv4addr = vpn_argv[4];
2371 const char *ipv4mask = vpn_argv[5];
2372 struct in_addr addr;
2373 struct in_addr mask;
2375 struct GNUNET_HashCode key;
2378 GNUNET_assert (1 == inet_pton (AF_INET, ipv4addr, &addr));
2379 GNUNET_assert (1 == inet_pton (AF_INET, ipv4mask, &mask));
2380 /* Given 192.168.0.1/255.255.0.0, we want a mask
2381 of '192.168.255.255', thus: */
2382 mask.s_addr = addr.s_addr | ~mask.s_addr;
2389 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
2390 _("Failed to find unallocated IPv4 address in VPN's range\n"));
2391 return GNUNET_SYSERR;
2393 /* Pick random IPv4 address within the subnet, except 'addr' or 'mask' itself */
2394 rnd.s_addr = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
2396 v4->s_addr = (addr.s_addr | rnd.s_addr) & mask.s_addr;
2397 get_destination_key_from_ip (AF_INET,
2401 while ( (GNUNET_YES ==
2402 GNUNET_CONTAINER_multihashmap_contains (destination_map,
2404 (v4->s_addr == addr.s_addr) ||
2405 (v4->s_addr == mask.s_addr) );
2411 * Allocate an IPv6 address from the range of the tunnel
2412 * for a new redirection.
2414 * @param v6 where to store the address
2415 * @return #GNUNET_OK on success,
2416 * #GNUNET_SYSERR on error
2419 allocate_v6_address (struct in6_addr *v6)
2421 const char *ipv6addr = vpn_argv[2];
2422 struct in6_addr addr;
2423 struct in6_addr mask;
2424 struct in6_addr rnd;
2426 struct GNUNET_HashCode key;
2429 GNUNET_assert (1 == inet_pton (AF_INET6, ipv6addr, &addr));
2430 GNUNET_assert (ipv6prefix < 128);
2431 /* Given ABCD::/96, we want a mask of 'ABCD::FFFF:FFFF,
2434 for (i=127;i>=ipv6prefix;i--)
2435 mask.s6_addr[i / 8] |= (1 << (i % 8));
2437 /* Pick random IPv6 address within the subnet, except 'addr' or 'mask' itself */
2444 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
2445 _("Failed to find unallocated IPv6 address in VPN's range\n"));
2446 return GNUNET_SYSERR;
2451 rnd.s6_addr[i] = (unsigned char) GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
2454 = (addr.s6_addr[i] | rnd.s6_addr[i]) & mask.s6_addr[i];
2456 get_destination_key_from_ip (AF_INET6,
2460 while ( (GNUNET_YES ==
2461 GNUNET_CONTAINER_multihashmap_contains (destination_map,
2465 sizeof (struct in6_addr))) ||
2468 sizeof (struct in6_addr))) );
2474 * Free resources occupied by a destination entry.
2476 * @param de entry to free
2479 free_destination_entry (struct DestinationEntry *de)
2481 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2482 "Cleaning up destination entry\n");
2483 GNUNET_STATISTICS_update (stats,
2484 gettext_noop ("# Active destinations"),
2488 free_tunnel_state (de->ts);
2489 GNUNET_assert (NULL == de->ts);
2491 if (NULL != de->heap_node)
2493 GNUNET_CONTAINER_heap_remove_node (de->heap_node);
2494 de->heap_node = NULL;
2495 GNUNET_assert (GNUNET_YES ==
2496 GNUNET_CONTAINER_multihashmap_remove (destination_map,
2505 * We have too many active destinations. Clean up the oldest destination.
2507 * @param except destination that must NOT be cleaned up, even if it is the oldest
2510 expire_destination (struct DestinationEntry *except)
2512 struct DestinationEntry *de;
2514 de = GNUNET_CONTAINER_heap_peek (destination_heap);
2515 GNUNET_assert (NULL != de);
2517 return; /* can't do this */
2518 free_destination_entry (de);
2523 * Allocate an IP address for the response.
2525 * @param result_af desired address family; set to the actual
2526 * address family; can initially be AF_UNSPEC if there
2527 * is no preference; will be set to AF_UNSPEC if the
2529 * @param addr set to either v4 or v6 depending on which
2530 * storage location was used; set to NULL if allocation failed
2531 * @param v4 storage space for an IPv4 address
2532 * @param v6 storage space for an IPv6 address
2533 * @return #GNUNET_OK normally, #GNUNET_SYSERR if `* result_af` was
2534 * an unsupported address family (not AF_INET, AF_INET6 or AF_UNSPEC)
2537 allocate_response_ip (int *result_af,
2540 struct in6_addr *v6)
2547 allocate_v4_address (v4))
2548 *result_af = AF_UNSPEC;
2554 allocate_v6_address (v6))
2555 *result_af = AF_UNSPEC;
2561 allocate_v4_address (v4))
2564 *result_af = AF_INET;
2566 else if (GNUNET_OK ==
2567 allocate_v6_address (v6))
2570 *result_af = AF_INET6;
2575 return GNUNET_SYSERR;
2582 * A client asks us to setup a redirection via some exit
2583 * node to a particular IP. Setup the redirection and
2584 * give the client the allocated IP.
2587 * @param client requesting client
2588 * @param message redirection request (a `struct RedirectToIpRequestMessage`)
2591 service_redirect_to_ip (void *cls GNUNET_UNUSED, struct GNUNET_SERVER_Client *client,
2592 const struct GNUNET_MessageHeader *message)
2596 const struct RedirectToIpRequestMessage *msg;
2602 struct DestinationEntry *de;
2603 struct GNUNET_HashCode key;
2604 struct TunnelState *ts;
2606 /* validate and parse request */
2607 mlen = ntohs (message->size);
2608 if (mlen < sizeof (struct RedirectToIpRequestMessage))
2611 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2614 alen = mlen - sizeof (struct RedirectToIpRequestMessage);
2615 msg = (const struct RedirectToIpRequestMessage *) message;
2616 addr_af = (int) htonl (msg->addr_af);
2620 if (alen != sizeof (struct in_addr))
2623 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2628 if (alen != sizeof (struct in6_addr))
2631 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2637 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2641 /* allocate response IP */
2642 result_af = (int) htonl (msg->result_af);
2643 if (GNUNET_OK != allocate_response_ip (&result_af,
2647 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2650 if ( (result_af == AF_UNSPEC) ||
2651 (GNUNET_NO == ntohl (msg->nac)) )
2653 /* send reply "instantly" */
2654 send_client_reply (client,
2659 if (result_af == AF_UNSPEC)
2661 /* failure, we're done */
2662 GNUNET_SERVER_receive_done (client, GNUNET_OK);
2667 char sbuf[INET6_ADDRSTRLEN];
2668 char dbuf[INET6_ADDRSTRLEN];
2670 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2671 "Allocated address %s for redirection via exit to %s\n",
2672 inet_ntop (result_af, addr, sbuf, sizeof (sbuf)),
2674 &msg[1], dbuf, sizeof (dbuf)));
2677 /* setup destination record */
2678 de = GNUNET_new (struct DestinationEntry);
2679 de->is_service = GNUNET_NO;
2680 de->details.exit_destination.af = addr_af;
2681 memcpy (&de->details.exit_destination.ip,
2684 get_destination_key_from_ip (result_af,
2688 GNUNET_assert (GNUNET_OK ==
2689 GNUNET_CONTAINER_multihashmap_put (destination_map,
2692 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE));
2693 de->heap_node = GNUNET_CONTAINER_heap_insert (destination_heap,
2695 GNUNET_TIME_absolute_ntoh (msg->expiration_time).abs_value_us);
2696 GNUNET_STATISTICS_update (stats,
2697 gettext_noop ("# Active destinations"),
2699 while (GNUNET_CONTAINER_multihashmap_size (destination_map) > max_destination_mappings)
2700 expire_destination (de);
2702 /* setup tunnel to destination */
2703 ts = create_tunnel_to_destination (de,
2704 (GNUNET_NO == ntohl (msg->nac)) ? NULL : client,
2710 ts->destination_ip.v4 = v4;
2713 ts->destination_ip.v6 = v6;
2719 GNUNET_SERVER_receive_done (client, GNUNET_OK);
2724 * A client asks us to setup a redirection to a particular peer
2725 * offering a service. Setup the redirection and give the client the
2729 * @param client requesting client
2730 * @param message redirection request (a `struct RedirectToPeerRequestMessage`)
2733 service_redirect_to_service (void *cls GNUNET_UNUSED, struct GNUNET_SERVER_Client *client,
2734 const struct GNUNET_MessageHeader *message)
2736 const struct RedirectToServiceRequestMessage *msg;
2741 struct DestinationEntry *de;
2742 struct GNUNET_HashCode key;
2743 struct TunnelState *ts;
2746 msg = (const struct RedirectToServiceRequestMessage *) message;
2748 /* allocate response IP */
2749 result_af = (int) htonl (msg->result_af);
2750 if (GNUNET_OK != allocate_response_ip (&result_af,
2754 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2757 if ( (result_af == AF_UNSPEC) ||
2758 (GNUNET_NO == ntohl (msg->nac)) )
2760 /* send reply "instantly" */
2761 send_client_reply (client,
2766 if (result_af == AF_UNSPEC)
2768 /* failure, we're done */
2769 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2770 _("Failed to allocate IP address for new destination\n"));
2771 GNUNET_SERVER_receive_done (client, GNUNET_OK);
2776 char sbuf[INET6_ADDRSTRLEN];
2778 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2779 "Allocated address %s for redirection to service %s on peer %s\n",
2780 inet_ntop (result_af, addr, sbuf, sizeof (sbuf)),
2781 GNUNET_h2s (&msg->service_descriptor),
2782 GNUNET_i2s (&msg->target));
2785 /* setup destination record */
2786 de = GNUNET_new (struct DestinationEntry);
2787 de->is_service = GNUNET_YES;
2788 de->details.service_destination.service_descriptor = msg->service_descriptor;
2789 de->details.service_destination.target = msg->target;
2790 get_destination_key_from_ip (result_af,
2794 GNUNET_assert (GNUNET_OK ==
2795 GNUNET_CONTAINER_multihashmap_put (destination_map,
2798 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE));
2799 de->heap_node = GNUNET_CONTAINER_heap_insert (destination_heap,
2801 GNUNET_TIME_absolute_ntoh (msg->expiration_time).abs_value_us);
2802 while (GNUNET_CONTAINER_multihashmap_size (destination_map) > max_destination_mappings)
2803 expire_destination (de);
2804 ts = create_tunnel_to_destination (de,
2805 (GNUNET_NO == ntohl (msg->nac)) ? NULL : client,
2811 ts->destination_ip.v4 = v4;
2814 ts->destination_ip.v6 = v6;
2820 GNUNET_SERVER_receive_done (client, GNUNET_OK);
2825 * Function called whenever a tunnel is destroyed. Should clean up
2826 * any associated state.
2828 * @param cls closure (set from #GNUNET_MESH_connect)
2829 * @param tunnel connection to the other end (henceforth invalid)
2830 * @param tunnel_ctx place where local state associated
2831 * with the tunnel is stored (our `struct TunnelState`)
2834 tunnel_cleaner (void *cls,
2835 const struct GNUNET_MESH_Tunnel *tunnel,
2838 struct TunnelState *ts = tunnel_ctx;
2840 ts->tunnel = NULL; /* we must not call GNUNET_MESH_tunnel_destroy() anymore */
2841 free_tunnel_state (ts);
2846 * Free memory occupied by an entry in the destination map.
2850 * @param value a `struct DestinationEntry *`
2851 * @return #GNUNET_OK (continue to iterate)
2854 cleanup_destination (void *cls,
2855 const struct GNUNET_HashCode *key,
2858 struct DestinationEntry *de = value;
2860 free_destination_entry (de);
2866 * Free memory occupied by an entry in the tunnel map.
2870 * @param value a `struct TunnelState *`
2871 * @return #GNUNET_OK (continue to iterate)
2874 cleanup_tunnel (void *cls,
2875 const struct GNUNET_HashCode *key,
2878 struct TunnelState *ts = value;
2880 free_tunnel_state (ts);
2886 * Function scheduled as very last function, cleans up after us
2893 const struct GNUNET_SCHEDULER_TaskContext *tc)
2897 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2898 "VPN is shutting down\n");
2899 if (NULL != destination_map)
2901 GNUNET_CONTAINER_multihashmap_iterate (destination_map,
2902 &cleanup_destination,
2904 GNUNET_CONTAINER_multihashmap_destroy (destination_map);
2905 destination_map = NULL;
2907 if (NULL != destination_heap)
2909 GNUNET_CONTAINER_heap_destroy (destination_heap);
2910 destination_heap = NULL;
2912 if (NULL != tunnel_map)
2914 GNUNET_CONTAINER_multihashmap_iterate (tunnel_map,
2917 GNUNET_CONTAINER_multihashmap_destroy (tunnel_map);
2920 if (NULL != tunnel_heap)
2922 GNUNET_CONTAINER_heap_destroy (tunnel_heap);
2925 if (NULL != mesh_handle)
2927 GNUNET_MESH_disconnect (mesh_handle);
2930 if (NULL != helper_handle)
2932 GNUNET_HELPER_stop (helper_handle, GNUNET_NO);
2933 helper_handle = NULL;
2937 GNUNET_SERVER_notification_context_destroy (nc);
2942 GNUNET_STATISTICS_destroy (stats, GNUNET_NO);
2946 GNUNET_free_non_null (vpn_argv[i]);
2951 * A client disconnected, clean up all references to it.
2953 * @param cls the client that disconnected
2955 * @param value a `struct TunnelState *`
2956 * @return #GNUNET_OK (continue to iterate)
2959 cleanup_tunnel_client (void *cls,
2960 const struct GNUNET_HashCode *key,
2963 struct GNUNET_SERVER_Client *client = cls;
2964 struct TunnelState *ts = value;
2966 if (client == ts->client)
2973 * A client disconnected, clean up all references to it.
2975 * @param cls the client that disconnected
2977 * @param value a `struct DestinationEntry *`
2978 * @return #GNUNET_OK (continue to iterate)
2981 cleanup_destination_client (void *cls,
2982 const struct GNUNET_HashCode *key,
2985 struct GNUNET_SERVER_Client *client = cls;
2986 struct DestinationEntry *de = value;
2987 struct TunnelState *ts;
2989 if (NULL == (ts = de->ts))
2991 if (client == ts->client)
2998 * A client has disconnected from us. If we are currently building
2999 * a tunnel for it, cancel the operation.
3002 * @param client handle to the client that disconnected
3005 client_disconnect (void *cls,
3006 struct GNUNET_SERVER_Client *client)
3008 if (NULL != tunnel_map)
3009 GNUNET_CONTAINER_multihashmap_iterate (tunnel_map,
3010 &cleanup_tunnel_client,
3012 if (NULL != destination_map)
3013 GNUNET_CONTAINER_multihashmap_iterate (destination_map,
3014 &cleanup_destination_client,
3020 * Main function that will be run by the scheduler.
3022 * @param cls closure
3023 * @param server the initialized server
3024 * @param cfg_ configuration
3028 struct GNUNET_SERVER_Handle *server,
3029 const struct GNUNET_CONFIGURATION_Handle *cfg_)
3031 static const struct GNUNET_SERVER_MessageHandler service_handlers[] = {
3032 /* callback, cls, type, size */
3033 { &service_redirect_to_ip, NULL, GNUNET_MESSAGE_TYPE_VPN_CLIENT_REDIRECT_TO_IP, 0},
3034 { &service_redirect_to_service, NULL,
3035 GNUNET_MESSAGE_TYPE_VPN_CLIENT_REDIRECT_TO_SERVICE,
3036 sizeof (struct RedirectToServiceRequestMessage) },
3039 static const struct GNUNET_MESH_MessageHandler mesh_handlers[] = {
3040 { &receive_udp_back, GNUNET_MESSAGE_TYPE_VPN_UDP_REPLY, 0},
3041 { &receive_tcp_back, GNUNET_MESSAGE_TYPE_VPN_TCP_DATA_TO_VPN, 0},
3042 { &receive_icmp_back, GNUNET_MESSAGE_TYPE_VPN_ICMP_TO_VPN, 0},
3054 binary = GNUNET_OS_get_libexec_binary_path ("gnunet-helper-vpn");
3057 GNUNET_OS_check_helper_binary (binary, GNUNET_YES, "-d gnunet-vpn - - 169.1.3.3.7 255.255.255.0")) //ipv4 only please!
3060 "`%s' is not SUID, refusing to run.\n",
3061 "gnunet-helper-vpn");
3062 GNUNET_free (binary);
3066 GNUNET_free (binary);
3068 stats = GNUNET_STATISTICS_create ("vpn", cfg);
3070 GNUNET_CONFIGURATION_get_value_number (cfg, "VPN", "MAX_MAPPING",
3071 &max_destination_mappings))
3072 max_destination_mappings = 200;
3074 GNUNET_CONFIGURATION_get_value_number (cfg, "VPN", "MAX_TUNNELS",
3075 &max_tunnel_mappings))
3076 max_tunnel_mappings = 200;
3078 destination_map = GNUNET_CONTAINER_multihashmap_create (max_destination_mappings * 2, GNUNET_NO);
3079 destination_heap = GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN);
3080 tunnel_map = GNUNET_CONTAINER_multihashmap_create (max_tunnel_mappings * 2, GNUNET_NO);
3081 tunnel_heap = GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN);
3084 vpn_argv[0] = GNUNET_strdup ("vpn-gnunet");
3085 if (GNUNET_SYSERR ==
3086 GNUNET_CONFIGURATION_get_value_string (cfg, "VPN", "IFNAME", &ifname))
3088 GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, "VPN", "IFNAME");
3089 GNUNET_SCHEDULER_shutdown ();
3092 vpn_argv[1] = ifname;
3093 if (GNUNET_OK == GNUNET_NETWORK_test_pf (PF_INET6))
3095 if ( (GNUNET_SYSERR ==
3096 GNUNET_CONFIGURATION_get_value_string (cfg, "VPN", "IPV6ADDR",
3098 (1 != inet_pton (AF_INET6, ipv6addr, &v6))) )
3100 GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, "VPN", "IPV6ADDR",
3101 _("Must specify valid IPv6 address"));
3102 GNUNET_SCHEDULER_shutdown ();
3105 vpn_argv[2] = ipv6addr;
3106 if (GNUNET_SYSERR ==
3107 GNUNET_CONFIGURATION_get_value_string (cfg, "VPN", "IPV6PREFIX",
3110 GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, "VPN", "IPV6PREFIX");
3111 GNUNET_SCHEDULER_shutdown ();
3114 vpn_argv[3] = ipv6prefix_s;
3116 GNUNET_CONFIGURATION_get_value_number (cfg, "VPN",
3119 (ipv6prefix >= 127) )
3121 GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, "VPN", "IPV4MASK",
3122 _("Must specify valid IPv6 mask"));
3123 GNUNET_SCHEDULER_shutdown ();
3129 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
3130 _("IPv6 support disabled as this system does not support IPv6\n"));
3131 vpn_argv[2] = GNUNET_strdup ("-");
3132 vpn_argv[3] = GNUNET_strdup ("-");
3134 if (GNUNET_OK == GNUNET_NETWORK_test_pf (PF_INET))
3136 if ( (GNUNET_SYSERR ==
3137 GNUNET_CONFIGURATION_get_value_string (cfg, "vpn", "IPV4ADDR",
3139 (1 != inet_pton (AF_INET, ipv4addr, &v4))) )
3141 GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, "VPN", "IPV4ADDR",
3142 _("Must specify valid IPv4 address"));
3143 GNUNET_SCHEDULER_shutdown ();
3146 vpn_argv[4] = ipv4addr;
3147 if ( (GNUNET_SYSERR ==
3148 GNUNET_CONFIGURATION_get_value_string (cfg, "vpn", "IPV4MASK",
3150 (1 != inet_pton (AF_INET, ipv4mask, &v4))) )
3152 GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, "VPN", "IPV4MASK",
3153 _("Must specify valid IPv4 mask"));
3154 GNUNET_SCHEDULER_shutdown ();
3157 vpn_argv[5] = ipv4mask;
3161 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
3162 _("IPv4 support disabled as this system does not support IPv4\n"));
3163 vpn_argv[4] = GNUNET_strdup ("-");
3164 vpn_argv[5] = GNUNET_strdup ("-");
3169 GNUNET_MESH_connect (cfg_, NULL,
3174 helper_handle = GNUNET_HELPER_start (GNUNET_NO,
3175 "gnunet-helper-vpn", vpn_argv,
3176 &message_token, NULL, NULL);
3177 nc = GNUNET_SERVER_notification_context_create (server, 1);
3178 GNUNET_SERVER_add_handlers (server, service_handlers);
3179 GNUNET_SERVER_disconnect_notify (server, &client_disconnect, NULL);
3180 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &cleanup, cls);
3185 * The main function of the VPN service.
3187 * @param argc number of arguments from the command line
3188 * @param argv command line arguments
3189 * @return 0 ok, 1 on error
3192 main (int argc, char *const *argv)
3194 return (GNUNET_OK ==
3195 GNUNET_SERVICE_run (argc, argv, "vpn",
3196 GNUNET_SERVICE_OPTION_NONE,
3197 &run, NULL)) ? global_ret : 1;
3200 /* end of gnunet-service-vpn.c */