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
54 * State we keep for each of our tunnels.
60 * Information we track for each IP address to determine which tunnel
61 * to send the traffic over to the destination.
63 struct DestinationEntry
67 * Key under which this entry is in the 'destination_map' (only valid
68 * if 'heap_node != NULL').
70 struct GNUNET_HashCode key;
73 * Pre-allocated tunnel for this destination, or NULL for none.
75 struct TunnelState *ts;
78 * Entry for this entry in the destination_heap.
80 struct GNUNET_CONTAINER_HeapNode *heap_node;
83 * GNUNET_NO if this is a tunnel to an Internet-exit,
84 * GNUNET_YES if this tunnel is to a service.
89 * Details about the connection (depending on is_service).
97 * The description of the service (only used for service tunnels).
99 struct GNUNET_HashCode service_descriptor;
102 * Peer offering the service.
104 struct GNUNET_PeerIdentity target;
106 } service_destination;
112 * Address family used (AF_INET or AF_INET6).
117 * IP address of the ultimate destination (only used for exit tunnels).
122 * Address if af is AF_INET.
127 * Address if af is AF_INET6.
140 * A messages we have in queue for a particular tunnel.
142 struct TunnelMessageQueueEntry
145 * This is a doubly-linked list.
147 struct TunnelMessageQueueEntry *next;
150 * This is a doubly-linked list.
152 struct TunnelMessageQueueEntry *prev;
155 * Number of bytes in 'msg'.
160 * Message to transmit, allocated at the end of this struct.
167 * State we keep for each of our tunnels.
173 * Information about the tunnel to use, NULL if no tunnel
174 * is available right now.
176 struct GNUNET_MESH_Tunnel *tunnel;
179 * Active query with REGEX to locate exit.
181 struct GNUNET_REGEX_Search *search;
184 * Active transmission handle, NULL for none.
186 struct GNUNET_MESH_TransmitHandle *th;
189 * Entry for this entry in the tunnel_heap, NULL as long as this
190 * tunnel state is not fully bound.
192 struct GNUNET_CONTAINER_HeapNode *heap_node;
195 * Head of list of messages scheduled for transmission.
197 struct TunnelMessageQueueEntry *tmq_head;
200 * Tail of list of messages scheduled for transmission.
202 struct TunnelMessageQueueEntry *tmq_tail;
205 * Client that needs to be notified about the tunnel being
206 * up as soon as a peer is connected; NULL for none.
208 struct GNUNET_SERVER_Client *client;
211 * Destination entry that has a pointer to this tunnel state;
212 * NULL if this tunnel state is in the tunnel map.
214 struct DestinationEntry *destination_container;
217 * ID of the client request that caused us to setup this entry.
222 * Destination to which this tunnel leads. Note that
223 * this struct is NOT in the destination_map (but a
224 * local copy) and that the 'heap_node' should always
227 struct DestinationEntry destination;
230 * Task scheduled to destroy the tunnel (or NO_TASK).
232 GNUNET_SCHEDULER_TaskIdentifier destroy_task;
235 * Addess family used for this tunnel on the local TUN interface.
240 * Length of the doubly linked 'tmq_head/tmq_tail' list.
242 unsigned int tmq_length;
245 * IPPROTO_TCP or IPPROTO_UDP once bound.
250 * IP address of the source on our end, initially uninitialized.
255 * Address if af is AF_INET.
260 * Address if af is AF_INET6.
267 * Destination IP address used by the source on our end (this is the IP
268 * that we pick freely within the VPN's tunnel IP range).
273 * Address if af is AF_INET.
278 * Address if af is AF_INET6.
285 * Source port used by the sender on our end; 0 for uninitialized.
287 uint16_t source_port;
290 * Destination port used by the sender on our end; 0 for uninitialized.
292 uint16_t destination_port;
298 * Return value from 'main'.
300 static int global_ret;
303 * Configuration we use.
305 static const struct GNUNET_CONFIGURATION_Handle *cfg;
308 * Handle to the mesh service.
310 static struct GNUNET_MESH_Handle *mesh_handle;
313 * Map from IP address to destination information (possibly with a
314 * MESH tunnel handle for fast setup).
316 static struct GNUNET_CONTAINER_MultiHashMap *destination_map;
319 * Min-Heap sorted by activity time to expire old mappings.
321 static struct GNUNET_CONTAINER_Heap *destination_heap;
324 * Map from source and destination address (IP+port) to connection
325 * information (mostly with the respective MESH tunnel handle).
327 static struct GNUNET_CONTAINER_MultiHashMap *tunnel_map;
330 * Min-Heap sorted by activity time to expire old mappings; values are
331 * of type 'struct TunnelState'.
333 static struct GNUNET_CONTAINER_Heap *tunnel_heap;
338 static struct GNUNET_STATISTICS_Handle *stats;
341 * The handle to the VPN helper process "gnunet-helper-vpn".
343 static struct GNUNET_HELPER_Handle *helper_handle;
346 * Arguments to the vpn helper.
348 static char *vpn_argv[7];
351 * Length of the prefix of the VPN's IPv6 network.
353 static unsigned long long ipv6prefix;
356 * Notification context for sending replies to clients.
358 static struct GNUNET_SERVER_NotificationContext *nc;
361 * If there are more than this number of address-mappings, old ones
364 static unsigned long long max_destination_mappings;
367 * If there are more than this number of open tunnels, old ones
370 static unsigned long long max_tunnel_mappings;
374 * Compute the key under which we would store an entry in the
375 * destination_map for the given IP address.
377 * @param af address family (AF_INET or AF_INET6)
378 * @param address IP address, struct in_addr or struct in6_addr
379 * @param key where to store the key
382 get_destination_key_from_ip (int af,
384 struct GNUNET_HashCode *key)
389 GNUNET_CRYPTO_hash (address,
390 sizeof (struct in_addr),
394 GNUNET_CRYPTO_hash (address,
395 sizeof (struct in6_addr),
406 * Compute the key under which we would store an entry in the
407 * tunnel_map for the given socket address pair.
409 * @param af address family (AF_INET or AF_INET6)
410 * @param protocol IPPROTO_TCP or IPPROTO_UDP
411 * @param source_ip sender's source IP, struct in_addr or struct in6_addr
412 * @param source_port sender's source port
413 * @param destination_ip sender's destination IP, struct in_addr or struct in6_addr
414 * @param destination_port sender's destination port
415 * @param key where to store the key
418 get_tunnel_key_from_ips (int af,
420 const void *source_ip,
421 uint16_t source_port,
422 const void *destination_ip,
423 uint16_t destination_port,
424 struct GNUNET_HashCode *key)
428 memset (key, 0, sizeof (struct GNUNET_HashCode));
429 /* the GNUnet hashmap only uses the first sizeof(unsigned int) of the hash,
430 so we put the ports in there (and hope for few collisions) */
432 memcpy (off, &source_port, sizeof (uint16_t));
433 off += sizeof (uint16_t);
434 memcpy (off, &destination_port, sizeof (uint16_t));
435 off += sizeof (uint16_t);
439 memcpy (off, source_ip, sizeof (struct in_addr));
440 off += sizeof (struct in_addr);
441 memcpy (off, destination_ip, sizeof (struct in_addr));
442 off += sizeof (struct in_addr);
445 memcpy (off, source_ip, sizeof (struct in6_addr));
446 off += sizeof (struct in6_addr);
447 memcpy (off, destination_ip, sizeof (struct in6_addr));
448 off += sizeof (struct in6_addr);
454 memcpy (off, &protocol, sizeof (uint8_t));
455 off += sizeof (uint8_t);
460 * Notify the client about the result of its request.
462 * @param client client to notify
463 * @param request_id original request ID to include in response
464 * @param result_af resulting address family
465 * @param addr resulting IP address
468 send_client_reply (struct GNUNET_SERVER_Client *client,
473 char buf[sizeof (struct RedirectToIpResponseMessage) + sizeof (struct in6_addr)] GNUNET_ALIGN;
474 struct RedirectToIpResponseMessage *res;
480 rlen = sizeof (struct in_addr);
483 rlen = sizeof (struct in6_addr);
492 res = (struct RedirectToIpResponseMessage *) buf;
493 res->header.size = htons (sizeof (struct RedirectToIpResponseMessage) + rlen);
494 res->header.type = htons (GNUNET_MESSAGE_TYPE_VPN_CLIENT_USE_IP);
495 res->result_af = htonl (result_af);
496 res->request_id = request_id;
497 memcpy (&res[1], addr, rlen);
498 GNUNET_SERVER_notification_context_add (nc, client);
499 GNUNET_SERVER_notification_context_unicast (nc,
507 * Free resources associated with a tunnel state.
509 * @param ts state to free
512 free_tunnel_state (struct TunnelState *ts)
514 struct GNUNET_HashCode key;
515 struct TunnelMessageQueueEntry *tnq;
516 struct GNUNET_MESH_Tunnel *tunnel;
518 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
519 "Cleaning up tunnel state\n");
520 GNUNET_STATISTICS_update (stats,
521 gettext_noop ("# Active tunnels"),
523 while (NULL != (tnq = ts->tmq_head))
525 GNUNET_CONTAINER_DLL_remove (ts->tmq_head,
531 GNUNET_assert (0 == ts->tmq_length);
534 GNUNET_MESH_notify_transmit_ready_cancel (ts->th);
537 GNUNET_assert (NULL == ts->destination.heap_node);
538 if (NULL != (tunnel = ts->tunnel))
541 GNUNET_MESH_tunnel_destroy (tunnel);
543 if (NULL != ts->search)
545 GNUNET_REGEX_search_cancel (ts->search);
548 if (GNUNET_SCHEDULER_NO_TASK != ts->destroy_task)
550 GNUNET_SCHEDULER_cancel (ts->destroy_task);
551 ts->destroy_task = GNUNET_SCHEDULER_NO_TASK;
553 if (NULL != ts->heap_node)
555 GNUNET_CONTAINER_heap_remove_node (ts->heap_node);
556 ts->heap_node = NULL;
557 get_tunnel_key_from_ips (ts->af,
562 ts->destination_port,
564 GNUNET_assert (GNUNET_YES ==
565 GNUNET_CONTAINER_multihashmap_remove (tunnel_map,
569 if (NULL != ts->destination_container)
571 GNUNET_assert (ts == ts->destination_container->ts);
572 ts->destination_container->ts = NULL;
573 ts->destination_container = NULL;
580 * Destroy the mesh tunnel.
582 * @param cls the 'struct TunnelState' with the tunnel to destroy
583 * @param tc scheduler context
586 destroy_tunnel_task (void *cls,
587 const struct GNUNET_SCHEDULER_TaskContext *tc)
589 struct TunnelState *ts = cls;
590 struct GNUNET_MESH_Tunnel *tunnel;
592 ts->destroy_task = GNUNET_SCHEDULER_NO_TASK;
593 GNUNET_assert (NULL != ts->tunnel);
596 GNUNET_MESH_tunnel_destroy (tunnel);
597 free_tunnel_state (ts);
602 * Method called whenever a peer has disconnected from the tunnel.
605 * @param peer peer identity the tunnel stopped working with
608 tunnel_peer_disconnect_handler (void *cls,
610 GNUNET_PeerIdentity * peer)
612 struct TunnelState *ts = cls;
614 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
615 "Peer %s disconnected from tunnel.\n",
617 GNUNET_STATISTICS_update (stats,
618 gettext_noop ("# peers connected to mesh tunnels"),
622 GNUNET_MESH_notify_transmit_ready_cancel (ts->th);
625 if (ts->destination.is_service)
626 return; /* hope for reconnect eventually */
627 /* as we are most likely going to change the exit node now,
628 we should just destroy the tunnel entirely... */
629 if (GNUNET_SCHEDULER_NO_TASK == ts->destroy_task)
630 ts->destroy_task = GNUNET_SCHEDULER_add_now (&destroy_tunnel_task, ts);
635 * Method called whenever a peer has connected to the tunnel. Notifies
636 * the waiting client that the tunnel is now up.
639 * @param peer peer identity the tunnel was created to, NULL on timeout
640 * @param atsi performance data for the connection
643 tunnel_peer_connect_handler (void *cls,
644 const struct GNUNET_PeerIdentity
647 GNUNET_ATS_Information * atsi)
649 struct TunnelState *ts = cls;
651 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
652 "Peer %s connected to tunnel.\n",
654 GNUNET_STATISTICS_update (stats,
655 gettext_noop ("# peers connected to mesh tunnels"),
657 if (NULL == ts->client)
658 return; /* nothing to do */
659 send_client_reply (ts->client,
662 &ts->destination_ip);
668 * Send a message from the message queue via mesh.
670 * @param cls the 'struct TunnelState' with the message queue
671 * @param size number of bytes available in buf
672 * @param buf where to copy the message
673 * @return number of bytes copied to buf
676 send_to_peer_notify_callback (void *cls, size_t size, void *buf)
678 struct TunnelState *ts = cls;
679 struct TunnelMessageQueueEntry *tnq;
686 GNUNET_assert (NULL != tnq);
687 GNUNET_assert (size >= tnq->len);
688 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
689 "Sending %u bytes via mesh tunnel\n",
691 GNUNET_CONTAINER_DLL_remove (ts->tmq_head,
695 memcpy (buf, tnq->msg, tnq->len);
698 if (NULL != (tnq = ts->tmq_head))
699 ts->th = GNUNET_MESH_notify_transmit_ready (ts->tunnel,
700 GNUNET_NO /* cork */,
701 GNUNET_TIME_UNIT_FOREVER_REL,
704 &send_to_peer_notify_callback,
706 GNUNET_STATISTICS_update (stats,
707 gettext_noop ("# Bytes given to mesh for transmission"),
714 * Add the given message to the given tunnel and trigger the
715 * transmission process.
717 * @param tnq message to queue
718 * @param ts tunnel to queue the message for
721 send_to_tunnel (struct TunnelMessageQueueEntry *tnq,
722 struct TunnelState *ts)
724 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
725 "Queueing %u bytes for transmission via mesh tunnel\n",
727 GNUNET_assert (NULL != ts->tunnel);
728 GNUNET_CONTAINER_DLL_insert_tail (ts->tmq_head,
732 if (ts->tmq_length > MAX_MESSAGE_QUEUE_SIZE)
734 struct TunnelMessageQueueEntry *dq;
737 GNUNET_assert (dq != tnq);
738 GNUNET_CONTAINER_DLL_remove (ts->tmq_head,
742 GNUNET_MESH_notify_transmit_ready_cancel (ts->th);
744 GNUNET_STATISTICS_update (stats,
745 gettext_noop ("# Bytes dropped in mesh queue (overflow)"),
751 ts->th = GNUNET_MESH_notify_transmit_ready (ts->tunnel,
752 GNUNET_NO /* cork */,
753 GNUNET_TIME_UNIT_FOREVER_REL,
756 &send_to_peer_notify_callback,
762 * Regex has found a potential exit peer for us; consider using it.
764 * @param cls the 'struct TunnelState'
765 * @param id Peer providing a regex that matches the string.
766 * @param get_path Path of the get request.
767 * @param get_path_length Lenght of get_path.
768 * @param put_path Path of the put request.
769 * @param put_path_length Length of the put_path.
772 handle_regex_result (void *cls,
773 const struct GNUNET_PeerIdentity *id,
774 const struct GNUNET_PeerIdentity *get_path,
775 unsigned int get_path_length,
776 const struct GNUNET_PeerIdentity *put_path,
777 unsigned int put_path_length)
779 struct TunnelState *ts = cls;
781 GNUNET_REGEX_search_cancel (ts->search);
783 ts->tunnel = GNUNET_MESH_tunnel_create (mesh_handle,
785 &tunnel_peer_connect_handler,
786 &tunnel_peer_disconnect_handler,
788 GNUNET_MESH_peer_request_connect_add (ts->tunnel,
794 * Initialize the given destination entry's mesh tunnel.
796 * @param de destination entry for which we need to setup a tunnel
797 * @param client client to notify on successful tunnel setup, or NULL for none
798 * @param client_af address family of the address returned to the client
799 * @param request_id request ID to send in client notification (unused if client is NULL)
800 * @return tunnel state of the tunnel that was created
802 static struct TunnelState *
803 create_tunnel_to_destination (struct DestinationEntry *de,
804 struct GNUNET_SERVER_Client *client,
808 struct TunnelState *ts;
810 GNUNET_STATISTICS_update (stats,
811 gettext_noop ("# Mesh tunnels created"),
813 GNUNET_assert (NULL == de->ts);
814 ts = GNUNET_malloc (sizeof (struct TunnelState));
818 ts->request_id = request_id;
821 ts->destination = *de;
822 ts->destination.heap_node = NULL; /* copy is NOT in destination heap */
824 ts->destination_container = de; /* we are referenced from de */
827 ts->tunnel = GNUNET_MESH_tunnel_create (mesh_handle,
829 &tunnel_peer_connect_handler,
830 &tunnel_peer_disconnect_handler,
832 if (NULL == ts->tunnel)
834 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
835 _("Failed to setup mesh tunnel!\n"));
839 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
840 "Creating tunnel to peer %s offering service %s\n",
841 GNUNET_i2s (&de->details.service_destination.target),
842 GNUNET_h2s (&de->details.service_destination.service_descriptor));
843 GNUNET_MESH_peer_request_connect_add (ts->tunnel,
844 &de->details.service_destination.target);
850 switch (de->details.exit_destination.af)
854 char address[GNUNET_TUN_IPV4_REGEXLEN];
856 GNUNET_TUN_ipv4toregex (&de->details.exit_destination.ip.v4,
857 "255.255.255.255", address);
858 GNUNET_asprintf (&policy, "%s%s%s",
859 GNUNET_APPLICATION_TYPE_EXIT_REGEX_PREFIX,
866 char address[GNUNET_TUN_IPV6_REGEXLEN];
868 GNUNET_TUN_ipv6toregex (&de->details.exit_destination.ip.v6,
870 GNUNET_asprintf (&policy, "%s%s%s",
871 GNUNET_APPLICATION_TYPE_EXIT_REGEX_PREFIX,
881 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
882 "Requesting connect by string: %s\n",
884 ts->search = GNUNET_REGEX_search (cfg,
886 &handle_regex_result,
888 GNUNET_free (policy);
895 * We have too many active tunnels. Clean up the oldest tunnel.
897 * @param except tunnel that must NOT be cleaned up, even if it is the oldest
900 expire_tunnel (struct TunnelState *except)
902 struct TunnelState *ts;
904 ts = GNUNET_CONTAINER_heap_peek (tunnel_heap);
905 GNUNET_assert (NULL != ts);
907 return; /* can't do this */
908 free_tunnel_state (ts);
913 * Route a packet via mesh to the given destination.
915 * @param destination description of the destination
916 * @param af address family on this end (AF_INET or AF_INET6)
917 * @param protocol IPPROTO_TCP or IPPROTO_UDP or IPPROTO_ICMP or IPPROTO_ICMPV6
918 * @param source_ip source IP used by the sender (struct in_addr or struct in6_addr)
919 * @param destination_ip destination IP used by the sender (struct in_addr or struct in6_addr)
920 * @param payload payload of the packet after the IP header
921 * @param payload_length number of bytes in payload
924 route_packet (struct DestinationEntry *destination,
927 const void *source_ip,
928 const void *destination_ip,
930 size_t payload_length)
932 struct GNUNET_HashCode key;
933 struct TunnelState *ts;
934 struct TunnelMessageQueueEntry *tnq;
938 const struct GNUNET_TUN_UdpHeader *udp;
939 const struct GNUNET_TUN_TcpHeader *tcp;
940 const struct GNUNET_TUN_IcmpHeader *icmp;
941 uint16_t source_port;
942 uint16_t destination_port;
948 if (payload_length < sizeof (struct GNUNET_TUN_UdpHeader))
954 tcp = NULL; /* make compiler happy */
955 icmp = NULL; /* make compiler happy */
957 if (udp->len < sizeof (struct GNUNET_TUN_UdpHeader))
962 source_port = ntohs (udp->source_port);
963 destination_port = ntohs (udp->destination_port);
964 get_tunnel_key_from_ips (af,
975 if (payload_length < sizeof (struct GNUNET_TUN_TcpHeader))
981 udp = NULL; /* make compiler happy */
982 icmp = NULL; /* make compiler happy */
984 if (tcp->off * 4 < sizeof (struct GNUNET_TUN_TcpHeader))
989 source_port = ntohs (tcp->source_port);
990 destination_port = ntohs (tcp->destination_port);
991 get_tunnel_key_from_ips (af,
1001 case IPPROTO_ICMPV6:
1003 if ( (AF_INET == af) ^ (protocol == IPPROTO_ICMP) )
1008 if (payload_length < sizeof (struct GNUNET_TUN_IcmpHeader))
1014 tcp = NULL; /* make compiler happy */
1015 udp = NULL; /* make compiler happy */
1018 destination_port = 0;
1019 get_tunnel_key_from_ips (af,
1029 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1030 _("Protocol %u not supported, dropping\n"),
1031 (unsigned int) protocol);
1034 if (! destination->is_service)
1036 switch (destination->details.exit_destination.af)
1039 alen = sizeof (struct in_addr);
1042 alen = sizeof (struct in6_addr);
1050 char sbuf[INET6_ADDRSTRLEN];
1051 char dbuf[INET6_ADDRSTRLEN];
1052 char xbuf[INET6_ADDRSTRLEN];
1054 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1055 "Routing %s packet from %s:%u -> %s:%u to destination %s:%u\n",
1056 (protocol == IPPROTO_TCP) ? "TCP" : "UDP",
1057 inet_ntop (af, source_ip, sbuf, sizeof (sbuf)),
1059 inet_ntop (af, destination_ip, dbuf, sizeof (dbuf)),
1061 inet_ntop (destination->details.exit_destination.af,
1062 &destination->details.exit_destination.ip,
1063 xbuf, sizeof (xbuf)),
1069 /* make compiler happy */
1072 char sbuf[INET6_ADDRSTRLEN];
1073 char dbuf[INET6_ADDRSTRLEN];
1075 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1076 "Routing %s packet from %s:%u -> %s:%u to service %s at peer %s\n",
1077 (protocol == IPPROTO_TCP) ? "TCP" : "UDP",
1078 inet_ntop (af, source_ip, sbuf, sizeof (sbuf)),
1080 inet_ntop (af, destination_ip, dbuf, sizeof (dbuf)),
1082 GNUNET_h2s (&destination->details.service_destination.service_descriptor),
1083 GNUNET_i2s (&destination->details.service_destination.target));
1088 /* see if we have an existing tunnel for this destination */
1089 ts = GNUNET_CONTAINER_multihashmap_get (tunnel_map,
1093 /* need to either use the existing tunnel from the destination (if still
1094 available) or create a fresh one */
1095 is_new = GNUNET_YES;
1096 if (NULL == destination->ts)
1097 ts = create_tunnel_to_destination (destination, NULL, af, 0);
1099 ts = destination->ts;
1102 destination->ts = NULL;
1103 ts->destination_container = NULL; /* no longer 'contained' */
1104 /* now bind existing "unbound" tunnel to our IP/port tuple */
1105 ts->protocol = protocol;
1109 ts->source_ip.v4 = * (const struct in_addr *) source_ip;
1110 ts->destination_ip.v4 = * (const struct in_addr *) destination_ip;
1114 ts->source_ip.v6 = * (const struct in6_addr *) source_ip;
1115 ts->destination_ip.v6 = * (const struct in6_addr *) destination_ip;
1117 ts->source_port = source_port;
1118 ts->destination_port = destination_port;
1119 ts->heap_node = GNUNET_CONTAINER_heap_insert (tunnel_heap,
1121 GNUNET_TIME_absolute_get ().abs_value);
1122 GNUNET_assert (GNUNET_YES ==
1123 GNUNET_CONTAINER_multihashmap_put (tunnel_map,
1126 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
1127 GNUNET_STATISTICS_update (stats,
1128 gettext_noop ("# Active tunnels"),
1130 while (GNUNET_CONTAINER_multihashmap_size (tunnel_map) > max_tunnel_mappings)
1136 GNUNET_CONTAINER_heap_update_cost (tunnel_heap,
1138 GNUNET_TIME_absolute_get ().abs_value);
1140 GNUNET_assert (NULL != ts->tunnel);
1142 /* send via tunnel */
1146 if (destination->is_service)
1148 struct GNUNET_EXIT_UdpServiceMessage *usm;
1150 mlen = sizeof (struct GNUNET_EXIT_UdpServiceMessage) +
1151 payload_length - sizeof (struct GNUNET_TUN_UdpHeader);
1152 if (mlen >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1157 tnq = GNUNET_malloc (sizeof (struct TunnelMessageQueueEntry) + mlen);
1160 usm = (struct GNUNET_EXIT_UdpServiceMessage *) &tnq[1];
1161 usm->header.size = htons ((uint16_t) mlen);
1162 usm->header.type = htons (GNUNET_MESSAGE_TYPE_VPN_UDP_TO_SERVICE);
1163 /* if the source port is below 32000, we assume it has a special
1164 meaning; if not, we pick a random port (this is a heuristic) */
1165 usm->source_port = (ntohs (udp->source_port) < 32000) ? udp->source_port : 0;
1166 usm->destination_port = udp->destination_port;
1167 usm->service_descriptor = destination->details.service_destination.service_descriptor;
1170 payload_length - sizeof (struct GNUNET_TUN_UdpHeader));
1174 struct GNUNET_EXIT_UdpInternetMessage *uim;
1175 struct in_addr *ip4dst;
1176 struct in6_addr *ip6dst;
1179 mlen = sizeof (struct GNUNET_EXIT_UdpInternetMessage) +
1180 alen + payload_length - sizeof (struct GNUNET_TUN_UdpHeader);
1181 if (mlen >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1186 tnq = GNUNET_malloc (sizeof (struct TunnelMessageQueueEntry) +
1190 uim = (struct GNUNET_EXIT_UdpInternetMessage *) &tnq[1];
1191 uim->header.size = htons ((uint16_t) mlen);
1192 uim->header.type = htons (GNUNET_MESSAGE_TYPE_VPN_UDP_TO_INTERNET);
1193 uim->af = htonl (destination->details.exit_destination.af);
1194 uim->source_port = (ntohs (udp->source_port) < 32000) ? udp->source_port : 0;
1195 uim->destination_port = udp->destination_port;
1196 switch (destination->details.exit_destination.af)
1199 ip4dst = (struct in_addr *) &uim[1];
1200 *ip4dst = destination->details.exit_destination.ip.v4;
1201 payload = &ip4dst[1];
1204 ip6dst = (struct in6_addr *) &uim[1];
1205 *ip6dst = destination->details.exit_destination.ip.v6;
1206 payload = &ip6dst[1];
1213 payload_length - sizeof (struct GNUNET_TUN_UdpHeader));
1219 if (destination->is_service)
1221 struct GNUNET_EXIT_TcpServiceStartMessage *tsm;
1223 mlen = sizeof (struct GNUNET_EXIT_TcpServiceStartMessage) +
1224 payload_length - sizeof (struct GNUNET_TUN_TcpHeader);
1225 if (mlen >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1230 tnq = GNUNET_malloc (sizeof (struct TunnelMessageQueueEntry) + mlen);
1233 tsm = (struct GNUNET_EXIT_TcpServiceStartMessage *) &tnq[1];
1234 tsm->header.size = htons ((uint16_t) mlen);
1235 tsm->header.type = htons (GNUNET_MESSAGE_TYPE_VPN_TCP_TO_SERVICE_START);
1236 tsm->reserved = htonl (0);
1237 tsm->service_descriptor = destination->details.service_destination.service_descriptor;
1238 tsm->tcp_header = *tcp;
1241 payload_length - sizeof (struct GNUNET_TUN_TcpHeader));
1245 struct GNUNET_EXIT_TcpInternetStartMessage *tim;
1246 struct in_addr *ip4dst;
1247 struct in6_addr *ip6dst;
1250 mlen = sizeof (struct GNUNET_EXIT_TcpInternetStartMessage) +
1251 alen + payload_length - sizeof (struct GNUNET_TUN_TcpHeader);
1252 if (mlen >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1257 tnq = GNUNET_malloc (sizeof (struct TunnelMessageQueueEntry) + mlen);
1260 tim = (struct GNUNET_EXIT_TcpInternetStartMessage *) &tnq[1];
1261 tim->header.size = htons ((uint16_t) mlen);
1262 tim->header.type = htons (GNUNET_MESSAGE_TYPE_VPN_TCP_TO_INTERNET_START);
1263 tim->af = htonl (destination->details.exit_destination.af);
1264 tim->tcp_header = *tcp;
1265 switch (destination->details.exit_destination.af)
1268 ip4dst = (struct in_addr *) &tim[1];
1269 *ip4dst = destination->details.exit_destination.ip.v4;
1270 payload = &ip4dst[1];
1273 ip6dst = (struct in6_addr *) &tim[1];
1274 *ip6dst = destination->details.exit_destination.ip.v6;
1275 payload = &ip6dst[1];
1282 payload_length - sizeof (struct GNUNET_TUN_TcpHeader));
1287 struct GNUNET_EXIT_TcpDataMessage *tdm;
1289 mlen = sizeof (struct GNUNET_EXIT_TcpDataMessage) +
1290 payload_length - sizeof (struct GNUNET_TUN_TcpHeader);
1291 if (mlen >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1296 tnq = GNUNET_malloc (sizeof (struct TunnelMessageQueueEntry) + mlen);
1299 tdm = (struct GNUNET_EXIT_TcpDataMessage *) &tnq[1];
1300 tdm->header.size = htons ((uint16_t) mlen);
1301 tdm->header.type = htons (GNUNET_MESSAGE_TYPE_VPN_TCP_DATA_TO_EXIT);
1302 tdm->reserved = htonl (0);
1303 tdm->tcp_header = *tcp;
1306 payload_length - sizeof (struct GNUNET_TUN_TcpHeader));
1310 case IPPROTO_ICMPV6:
1311 if (destination->is_service)
1313 struct GNUNET_EXIT_IcmpServiceMessage *ism;
1315 mlen = sizeof (struct GNUNET_EXIT_IcmpServiceMessage) +
1316 payload_length - sizeof (struct GNUNET_TUN_IcmpHeader);
1317 if (mlen >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1322 tnq = GNUNET_malloc (sizeof (struct TunnelMessageQueueEntry) + mlen);
1324 ism = (struct GNUNET_EXIT_IcmpServiceMessage *) &tnq[1];
1325 ism->header.type = htons (GNUNET_MESSAGE_TYPE_VPN_ICMP_TO_SERVICE);
1326 ism->af = htonl (af); /* need to tell destination ICMP protocol family! */
1327 ism->service_descriptor = destination->details.service_destination.service_descriptor;
1328 ism->icmp_header = *icmp;
1329 /* ICMP protocol translation will be done by the receiver (as we don't know
1330 the target AF); however, we still need to possibly discard the payload
1331 depending on the ICMP type */
1337 case GNUNET_TUN_ICMPTYPE_ECHO_REPLY:
1338 case GNUNET_TUN_ICMPTYPE_ECHO_REQUEST:
1340 case GNUNET_TUN_ICMPTYPE_DESTINATION_UNREACHABLE:
1341 case GNUNET_TUN_ICMPTYPE_SOURCE_QUENCH:
1342 case GNUNET_TUN_ICMPTYPE_TIME_EXCEEDED:
1343 /* throw away ICMP payload, won't be useful for the other side anyway */
1344 payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
1347 GNUNET_STATISTICS_update (stats,
1348 gettext_noop ("# ICMPv4 packets dropped (not allowed)"),
1352 /* end of AF_INET */
1357 case GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE:
1358 case GNUNET_TUN_ICMPTYPE6_PACKET_TOO_BIG:
1359 case GNUNET_TUN_ICMPTYPE6_TIME_EXCEEDED:
1360 case GNUNET_TUN_ICMPTYPE6_PARAMETER_PROBLEM:
1361 /* throw away ICMP payload, won't be useful for the other side anyway */
1362 payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
1364 case GNUNET_TUN_ICMPTYPE6_ECHO_REQUEST:
1365 case GNUNET_TUN_ICMPTYPE6_ECHO_REPLY:
1368 GNUNET_STATISTICS_update (stats,
1369 gettext_noop ("# ICMPv6 packets dropped (not allowed)"),
1373 /* end of AF_INET6 */
1380 /* update length calculations, as payload_length may have changed */
1381 mlen = sizeof (struct GNUNET_EXIT_IcmpServiceMessage) +
1382 alen + payload_length - sizeof (struct GNUNET_TUN_IcmpHeader);
1384 ism->header.size = htons ((uint16_t) mlen);
1385 /* finally, copy payload (if there is any left...) */
1388 payload_length - sizeof (struct GNUNET_TUN_IcmpHeader));
1392 struct GNUNET_EXIT_IcmpInternetMessage *iim;
1393 struct in_addr *ip4dst;
1394 struct in6_addr *ip6dst;
1397 mlen = sizeof (struct GNUNET_EXIT_IcmpInternetMessage) +
1398 alen + payload_length - sizeof (struct GNUNET_TUN_IcmpHeader);
1399 if (mlen >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1404 tnq = GNUNET_malloc (sizeof (struct TunnelMessageQueueEntry) +
1407 iim = (struct GNUNET_EXIT_IcmpInternetMessage *) &tnq[1];
1408 iim->header.type = htons (GNUNET_MESSAGE_TYPE_VPN_ICMP_TO_INTERNET);
1409 iim->icmp_header = *icmp;
1410 /* Perform ICMP protocol-translation (depending on destination AF and source AF)
1411 and throw away ICMP payload depending on ICMP message type */
1417 case GNUNET_TUN_ICMPTYPE_ECHO_REPLY:
1418 if (destination->details.exit_destination.af == AF_INET6)
1419 iim->icmp_header.type = GNUNET_TUN_ICMPTYPE6_ECHO_REPLY;
1421 case GNUNET_TUN_ICMPTYPE_ECHO_REQUEST:
1422 if (destination->details.exit_destination.af == AF_INET6)
1423 iim->icmp_header.type = GNUNET_TUN_ICMPTYPE6_ECHO_REQUEST;
1425 case GNUNET_TUN_ICMPTYPE_DESTINATION_UNREACHABLE:
1426 if (destination->details.exit_destination.af == AF_INET6)
1427 iim->icmp_header.type = GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE;
1428 /* throw away IP-payload, exit will have to make it up anyway */
1429 payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
1431 case GNUNET_TUN_ICMPTYPE_TIME_EXCEEDED:
1432 if (destination->details.exit_destination.af == AF_INET6)
1433 iim->icmp_header.type = GNUNET_TUN_ICMPTYPE6_TIME_EXCEEDED;
1434 /* throw away IP-payload, exit will have to make it up anyway */
1435 payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
1437 case GNUNET_TUN_ICMPTYPE_SOURCE_QUENCH:
1438 if (destination->details.exit_destination.af == AF_INET6)
1440 GNUNET_STATISTICS_update (stats,
1441 gettext_noop ("# ICMPv4 packets dropped (impossible PT to v6)"),
1446 /* throw away IP-payload, exit will have to make it up anyway */
1447 payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
1450 GNUNET_STATISTICS_update (stats,
1451 gettext_noop ("# ICMPv4 packets dropped (type not allowed)"),
1456 /* end of AF_INET */
1461 case GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE:
1462 if (destination->details.exit_destination.af == AF_INET6)
1463 iim->icmp_header.type = GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE;
1464 /* throw away IP-payload, exit will have to make it up anyway */
1465 payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
1467 case GNUNET_TUN_ICMPTYPE6_TIME_EXCEEDED:
1468 if (destination->details.exit_destination.af == AF_INET)
1469 iim->icmp_header.type = GNUNET_TUN_ICMPTYPE_TIME_EXCEEDED;
1470 /* throw away IP-payload, exit will have to make it up anyway */
1471 payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
1473 case GNUNET_TUN_ICMPTYPE6_PACKET_TOO_BIG:
1474 if (destination->details.exit_destination.af == AF_INET)
1476 GNUNET_STATISTICS_update (stats,
1477 gettext_noop ("# ICMPv6 packets dropped (impossible PT to v4)"),
1482 /* throw away IP-payload, exit will have to make it up anyway */
1483 payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
1485 case GNUNET_TUN_ICMPTYPE6_PARAMETER_PROBLEM:
1486 if (destination->details.exit_destination.af == AF_INET)
1488 GNUNET_STATISTICS_update (stats,
1489 gettext_noop ("# ICMPv6 packets dropped (impossible PT to v4)"),
1494 /* throw away IP-payload, exit will have to make it up anyway */
1495 payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
1497 case GNUNET_TUN_ICMPTYPE6_ECHO_REQUEST:
1498 if (destination->details.exit_destination.af == AF_INET)
1499 iim->icmp_header.type = GNUNET_TUN_ICMPTYPE_ECHO_REQUEST;
1501 case GNUNET_TUN_ICMPTYPE6_ECHO_REPLY:
1502 if (destination->details.exit_destination.af == AF_INET)
1503 iim->icmp_header.type = GNUNET_TUN_ICMPTYPE_ECHO_REPLY;
1506 GNUNET_STATISTICS_update (stats,
1507 gettext_noop ("# ICMPv6 packets dropped (type not allowed)"),
1512 /* end of AF_INET6 */
1517 /* update length calculations, as payload_length may have changed */
1518 mlen = sizeof (struct GNUNET_EXIT_IcmpInternetMessage) +
1519 alen + payload_length - sizeof (struct GNUNET_TUN_IcmpHeader);
1521 iim->header.size = htons ((uint16_t) mlen);
1523 /* need to tell destination ICMP protocol family! */
1524 iim->af = htonl (destination->details.exit_destination.af);
1525 switch (destination->details.exit_destination.af)
1528 ip4dst = (struct in_addr *) &iim[1];
1529 *ip4dst = destination->details.exit_destination.ip.v4;
1530 payload = &ip4dst[1];
1533 ip6dst = (struct in6_addr *) &iim[1];
1534 *ip6dst = destination->details.exit_destination.ip.v6;
1535 payload = &ip6dst[1];
1542 payload_length - sizeof (struct GNUNET_TUN_IcmpHeader));
1546 /* not supported above, how can we get here !? */
1550 send_to_tunnel (tnq, ts);
1555 * Receive packets from the helper-process (someone send to the local
1556 * virtual tunnel interface). Find the destination mapping, and if it
1557 * exists, identify the correct MESH tunnel (or possibly create it)
1558 * and forward the packet.
1560 * @param cls closure, NULL
1561 * @param client NULL
1562 * @param message message we got from the client (VPN tunnel interface)
1565 message_token (void *cls GNUNET_UNUSED, void *client GNUNET_UNUSED,
1566 const struct GNUNET_MessageHeader *message)
1568 const struct GNUNET_TUN_Layer2PacketHeader *tun;
1570 struct GNUNET_HashCode key;
1571 struct DestinationEntry *de;
1573 GNUNET_STATISTICS_update (stats,
1574 gettext_noop ("# Packets received from TUN interface"),
1576 mlen = ntohs (message->size);
1577 if ( (ntohs (message->type) != GNUNET_MESSAGE_TYPE_VPN_HELPER) ||
1578 (mlen < sizeof (struct GNUNET_MessageHeader) + sizeof (struct GNUNET_TUN_Layer2PacketHeader)) )
1583 tun = (const struct GNUNET_TUN_Layer2PacketHeader *) &message[1];
1584 mlen -= (sizeof (struct GNUNET_MessageHeader) + sizeof (struct GNUNET_TUN_Layer2PacketHeader));
1585 switch (ntohs (tun->proto))
1589 const struct GNUNET_TUN_IPv6Header *pkt6;
1591 if (mlen < sizeof (struct GNUNET_TUN_IPv6Header))
1597 pkt6 = (const struct GNUNET_TUN_IPv6Header *) &tun[1];
1598 get_destination_key_from_ip (AF_INET6,
1599 &pkt6->destination_address,
1601 de = GNUNET_CONTAINER_multihashmap_get (destination_map, &key);
1602 /* FIXME: do we need to guard against hash collision?
1603 (if so, we need to also store the local destination IP in the
1604 destination entry and then compare here; however, the risk
1605 of collision seems minimal AND the impact is unlikely to be
1606 super-problematic as well... */
1609 char buf[INET6_ADDRSTRLEN];
1611 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1612 _("Packet received for unmapped destination `%s' (dropping it)\n"),
1613 inet_ntop (AF_INET6,
1614 &pkt6->destination_address,
1622 &pkt6->source_address,
1623 &pkt6->destination_address,
1625 mlen - sizeof (struct GNUNET_TUN_IPv6Header));
1630 struct GNUNET_TUN_IPv4Header *pkt4;
1632 if (mlen < sizeof (struct GNUNET_TUN_IPv4Header))
1638 pkt4 = (struct GNUNET_TUN_IPv4Header *) &tun[1];
1639 get_destination_key_from_ip (AF_INET,
1640 &pkt4->destination_address,
1642 de = GNUNET_CONTAINER_multihashmap_get (destination_map, &key);
1643 /* FIXME: do we need to guard against hash collision?
1644 (if so, we need to also store the local destination IP in the
1645 destination entry and then compare here; however, the risk
1646 of collision seems minimal AND the impact is unlikely to be
1647 super-problematic as well... */
1650 char buf[INET_ADDRSTRLEN];
1652 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1653 _("Packet received for unmapped destination `%s' (dropping it)\n"),
1655 &pkt4->destination_address,
1660 if (pkt4->header_length * 4 != sizeof (struct GNUNET_TUN_IPv4Header))
1662 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1663 _("Received IPv4 packet with options (dropping it)\n"));
1669 &pkt4->source_address,
1670 &pkt4->destination_address,
1672 mlen - sizeof (struct GNUNET_TUN_IPv4Header));
1676 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1677 _("Received packet of unknown protocol %d from TUN (dropping it)\n"),
1678 (unsigned int) ntohs (tun->proto));
1686 * Synthesize a plausible ICMP payload for an ICMP error
1687 * response on the given tunnel.
1689 * @param ts tunnel information
1690 * @param ipp IPv4 header to fill in (ICMP payload)
1691 * @param udp "UDP" header to fill in (ICMP payload); might actually
1692 * also be the first 8 bytes of the TCP header
1695 make_up_icmpv4_payload (struct TunnelState *ts,
1696 struct GNUNET_TUN_IPv4Header *ipp,
1697 struct GNUNET_TUN_UdpHeader *udp)
1699 GNUNET_TUN_initialize_ipv4_header (ipp,
1701 sizeof (struct GNUNET_TUN_TcpHeader),
1703 &ts->destination_ip.v4);
1704 udp->source_port = htons (ts->source_port);
1705 udp->destination_port = htons (ts->destination_port);
1706 udp->len = htons (0);
1707 udp->crc = htons (0);
1712 * Synthesize a plausible ICMP payload for an ICMP error
1713 * response on the given tunnel.
1715 * @param ts tunnel information
1716 * @param ipp IPv6 header to fill in (ICMP payload)
1717 * @param udp "UDP" header to fill in (ICMP payload); might actually
1718 * also be the first 8 bytes of the TCP header
1721 make_up_icmpv6_payload (struct TunnelState *ts,
1722 struct GNUNET_TUN_IPv6Header *ipp,
1723 struct GNUNET_TUN_UdpHeader *udp)
1725 GNUNET_TUN_initialize_ipv6_header (ipp,
1727 sizeof (struct GNUNET_TUN_TcpHeader),
1729 &ts->destination_ip.v6);
1730 udp->source_port = htons (ts->source_port);
1731 udp->destination_port = htons (ts->destination_port);
1732 udp->len = htons (0);
1733 udp->crc = htons (0);
1738 * We got an ICMP packet back from the MESH tunnel. Pass it on to the
1739 * local virtual interface via the helper.
1741 * @param cls closure, NULL
1742 * @param tunnel connection to the other end
1743 * @param tunnel_ctx pointer to our 'struct TunnelState *'
1744 * @param sender who sent the message
1745 * @param message the actual message
1746 * @param atsi performance data for the connection
1747 * @return GNUNET_OK to keep the connection open,
1748 * GNUNET_SYSERR to close it (signal serious error)
1751 receive_icmp_back (void *cls GNUNET_UNUSED, struct GNUNET_MESH_Tunnel *tunnel,
1752 void **tunnel_ctx, const struct GNUNET_PeerIdentity *sender,
1753 const struct GNUNET_MessageHeader *message,
1754 const struct GNUNET_ATS_Information *atsi GNUNET_UNUSED)
1756 struct TunnelState *ts = *tunnel_ctx;
1757 const struct GNUNET_EXIT_IcmpToVPNMessage *i2v;
1760 GNUNET_STATISTICS_update (stats,
1761 gettext_noop ("# ICMP packets received from mesh"),
1763 mlen = ntohs (message->size);
1764 if (mlen < sizeof (struct GNUNET_EXIT_IcmpToVPNMessage))
1766 GNUNET_break_op (0);
1767 return GNUNET_SYSERR;
1769 if (NULL == ts->heap_node)
1771 GNUNET_break_op (0);
1772 return GNUNET_SYSERR;
1774 if (AF_UNSPEC == ts->af)
1776 GNUNET_break_op (0);
1777 return GNUNET_SYSERR;
1779 i2v = (const struct GNUNET_EXIT_IcmpToVPNMessage *) message;
1780 mlen -= sizeof (struct GNUNET_EXIT_IcmpToVPNMessage);
1782 char sbuf[INET6_ADDRSTRLEN];
1783 char dbuf[INET6_ADDRSTRLEN];
1785 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1786 "Received ICMP packet from mesh, sending %u bytes from %s -> %s via TUN\n",
1787 (unsigned int) mlen,
1788 inet_ntop (ts->af, &ts->destination_ip, sbuf, sizeof (sbuf)),
1789 inet_ntop (ts->af, &ts->source_ip, dbuf, sizeof (dbuf)));
1795 size_t size = sizeof (struct GNUNET_TUN_IPv4Header)
1796 + sizeof (struct GNUNET_TUN_IcmpHeader)
1797 + sizeof (struct GNUNET_MessageHeader) +
1798 sizeof (struct GNUNET_TUN_Layer2PacketHeader) +
1801 /* reserve some extra space in case we have an ICMP type here where
1802 we will need to make up the payload ourselves */
1803 char buf[size + sizeof (struct GNUNET_TUN_IPv4Header) + 8] GNUNET_ALIGN;
1804 struct GNUNET_MessageHeader *msg = (struct GNUNET_MessageHeader *) buf;
1805 struct GNUNET_TUN_Layer2PacketHeader *tun = (struct GNUNET_TUN_Layer2PacketHeader*) &msg[1];
1806 struct GNUNET_TUN_IPv4Header *ipv4 = (struct GNUNET_TUN_IPv4Header *) &tun[1];
1807 struct GNUNET_TUN_IcmpHeader *icmp = (struct GNUNET_TUN_IcmpHeader *) &ipv4[1];
1808 msg->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
1809 tun->flags = htons (0);
1810 tun->proto = htons (ETH_P_IPV4);
1811 GNUNET_TUN_initialize_ipv4_header (ipv4,
1813 sizeof (struct GNUNET_TUN_IcmpHeader) + mlen,
1814 &ts->destination_ip.v4,
1816 *icmp = i2v->icmp_header;
1820 /* For some ICMP types, we need to adjust (make up) the payload here.
1821 Also, depending on the AF used on the other side, we have to
1822 do ICMP PT (translate ICMP types) */
1823 switch (ntohl (i2v->af))
1828 case GNUNET_TUN_ICMPTYPE_ECHO_REPLY:
1829 case GNUNET_TUN_ICMPTYPE_ECHO_REQUEST:
1831 case GNUNET_TUN_ICMPTYPE_DESTINATION_UNREACHABLE:
1832 case GNUNET_TUN_ICMPTYPE_SOURCE_QUENCH:
1833 case GNUNET_TUN_ICMPTYPE_TIME_EXCEEDED:
1835 struct GNUNET_TUN_IPv4Header *ipp = (struct GNUNET_TUN_IPv4Header *) &icmp[1];
1836 struct GNUNET_TUN_UdpHeader *udp = (struct GNUNET_TUN_UdpHeader *) &ipp[1];
1840 /* sender did not strip ICMP payload? */
1841 GNUNET_break_op (0);
1842 return GNUNET_SYSERR;
1844 size += sizeof (struct GNUNET_TUN_IPv4Header) + 8;
1845 GNUNET_assert (8 == sizeof (struct GNUNET_TUN_UdpHeader));
1846 make_up_icmpv4_payload (ts, ipp, udp);
1850 GNUNET_break_op (0);
1851 GNUNET_STATISTICS_update (stats,
1852 gettext_noop ("# ICMPv4 packets dropped (type not allowed)"),
1854 return GNUNET_SYSERR;
1859 /* ICMP PT 6-to-4 and possibly making up payloads */
1862 case GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE:
1863 icmp->type = GNUNET_TUN_ICMPTYPE_DESTINATION_UNREACHABLE;
1865 struct GNUNET_TUN_IPv4Header *ipp = (struct GNUNET_TUN_IPv4Header *) &icmp[1];
1866 struct GNUNET_TUN_UdpHeader *udp = (struct GNUNET_TUN_UdpHeader *) &ipp[1];
1870 /* sender did not strip ICMP payload? */
1871 GNUNET_break_op (0);
1872 return GNUNET_SYSERR;
1874 size += sizeof (struct GNUNET_TUN_IPv4Header) + 8;
1875 GNUNET_assert (8 == sizeof (struct GNUNET_TUN_UdpHeader));
1876 make_up_icmpv4_payload (ts, ipp, udp);
1879 case GNUNET_TUN_ICMPTYPE6_TIME_EXCEEDED:
1880 icmp->type = GNUNET_TUN_ICMPTYPE_TIME_EXCEEDED;
1882 struct GNUNET_TUN_IPv4Header *ipp = (struct GNUNET_TUN_IPv4Header *) &icmp[1];
1883 struct GNUNET_TUN_UdpHeader *udp = (struct GNUNET_TUN_UdpHeader *) &ipp[1];
1887 /* sender did not strip ICMP payload? */
1888 GNUNET_break_op (0);
1889 return GNUNET_SYSERR;
1891 size += sizeof (struct GNUNET_TUN_IPv4Header) + 8;
1892 GNUNET_assert (8 == sizeof (struct GNUNET_TUN_UdpHeader));
1893 make_up_icmpv4_payload (ts, ipp, udp);
1896 case GNUNET_TUN_ICMPTYPE6_PACKET_TOO_BIG:
1897 case GNUNET_TUN_ICMPTYPE6_PARAMETER_PROBLEM:
1898 GNUNET_STATISTICS_update (stats,
1899 gettext_noop ("# ICMPv6 packets dropped (impossible PT to v4)"),
1902 case GNUNET_TUN_ICMPTYPE6_ECHO_REQUEST:
1903 icmp->type = GNUNET_TUN_ICMPTYPE_ECHO_REQUEST;
1905 case GNUNET_TUN_ICMPTYPE6_ECHO_REPLY:
1906 icmp->type = GNUNET_TUN_ICMPTYPE_ECHO_REPLY;
1909 GNUNET_break_op (0);
1910 GNUNET_STATISTICS_update (stats,
1911 gettext_noop ("# ICMPv6 packets dropped (type not allowed)"),
1913 return GNUNET_SYSERR;
1918 GNUNET_break_op (0);
1919 return GNUNET_SYSERR;
1921 msg->size = htons (size);
1922 GNUNET_TUN_calculate_icmp_checksum (icmp,
1925 (void) GNUNET_HELPER_send (helper_handle,
1934 size_t size = sizeof (struct GNUNET_TUN_IPv6Header)
1935 + sizeof (struct GNUNET_TUN_IcmpHeader)
1936 + sizeof (struct GNUNET_MessageHeader) +
1937 sizeof (struct GNUNET_TUN_Layer2PacketHeader) +
1940 char buf[size + sizeof (struct GNUNET_TUN_IPv6Header) + 8] GNUNET_ALIGN;
1941 struct GNUNET_MessageHeader *msg = (struct GNUNET_MessageHeader *) buf;
1942 struct GNUNET_TUN_Layer2PacketHeader *tun = (struct GNUNET_TUN_Layer2PacketHeader*) &msg[1];
1943 struct GNUNET_TUN_IPv6Header *ipv6 = (struct GNUNET_TUN_IPv6Header *) &tun[1];
1944 struct GNUNET_TUN_IcmpHeader *icmp = (struct GNUNET_TUN_IcmpHeader *) &ipv6[1];
1945 msg->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
1946 tun->flags = htons (0);
1947 tun->proto = htons (ETH_P_IPV6);
1948 GNUNET_TUN_initialize_ipv6_header (ipv6,
1950 sizeof (struct GNUNET_TUN_IcmpHeader) + mlen,
1951 &ts->destination_ip.v6,
1953 *icmp = i2v->icmp_header;
1958 /* For some ICMP types, we need to adjust (make up) the payload here.
1959 Also, depending on the AF used on the other side, we have to
1960 do ICMP PT (translate ICMP types) */
1961 switch (ntohl (i2v->af))
1964 /* ICMP PT 4-to-6 and possibly making up payloads */
1967 case GNUNET_TUN_ICMPTYPE_ECHO_REPLY:
1968 icmp->type = GNUNET_TUN_ICMPTYPE6_ECHO_REPLY;
1970 case GNUNET_TUN_ICMPTYPE_ECHO_REQUEST:
1971 icmp->type = GNUNET_TUN_ICMPTYPE6_ECHO_REQUEST;
1973 case GNUNET_TUN_ICMPTYPE_DESTINATION_UNREACHABLE:
1974 icmp->type = GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE;
1976 struct GNUNET_TUN_IPv6Header *ipp = (struct GNUNET_TUN_IPv6Header *) &icmp[1];
1977 struct GNUNET_TUN_UdpHeader *udp = (struct GNUNET_TUN_UdpHeader *) &ipp[1];
1981 /* sender did not strip ICMP payload? */
1982 GNUNET_break_op (0);
1983 return GNUNET_SYSERR;
1985 size += sizeof (struct GNUNET_TUN_IPv6Header) + 8;
1986 GNUNET_assert (8 == sizeof (struct GNUNET_TUN_UdpHeader));
1987 make_up_icmpv6_payload (ts, ipp, udp);
1990 case GNUNET_TUN_ICMPTYPE_TIME_EXCEEDED:
1991 icmp->type = GNUNET_TUN_ICMPTYPE6_TIME_EXCEEDED;
1993 struct GNUNET_TUN_IPv6Header *ipp = (struct GNUNET_TUN_IPv6Header *) &icmp[1];
1994 struct GNUNET_TUN_UdpHeader *udp = (struct GNUNET_TUN_UdpHeader *) &ipp[1];
1998 /* sender did not strip ICMP payload? */
1999 GNUNET_break_op (0);
2000 return GNUNET_SYSERR;
2002 size += sizeof (struct GNUNET_TUN_IPv6Header) + 8;
2003 GNUNET_assert (8 == sizeof (struct GNUNET_TUN_UdpHeader));
2004 make_up_icmpv6_payload (ts, ipp, udp);
2007 case GNUNET_TUN_ICMPTYPE_SOURCE_QUENCH:
2008 GNUNET_STATISTICS_update (stats,
2009 gettext_noop ("# ICMPv4 packets dropped (impossible PT to v6)"),
2013 GNUNET_break_op (0);
2014 GNUNET_STATISTICS_update (stats,
2015 gettext_noop ("# ICMPv4 packets dropped (type not allowed)"),
2017 return GNUNET_SYSERR;
2024 case GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE:
2025 case GNUNET_TUN_ICMPTYPE6_TIME_EXCEEDED:
2026 case GNUNET_TUN_ICMPTYPE6_PACKET_TOO_BIG:
2027 case GNUNET_TUN_ICMPTYPE6_PARAMETER_PROBLEM:
2029 struct GNUNET_TUN_IPv6Header *ipp = (struct GNUNET_TUN_IPv6Header *) &icmp[1];
2030 struct GNUNET_TUN_UdpHeader *udp = (struct GNUNET_TUN_UdpHeader *) &ipp[1];
2034 /* sender did not strip ICMP payload? */
2035 GNUNET_break_op (0);
2036 return GNUNET_SYSERR;
2038 size += sizeof (struct GNUNET_TUN_IPv6Header) + 8;
2039 GNUNET_assert (8 == sizeof (struct GNUNET_TUN_UdpHeader));
2040 make_up_icmpv6_payload (ts, ipp, udp);
2043 case GNUNET_TUN_ICMPTYPE6_ECHO_REQUEST:
2046 GNUNET_break_op (0);
2047 GNUNET_STATISTICS_update (stats,
2048 gettext_noop ("# ICMPv6 packets dropped (type not allowed)"),
2050 return GNUNET_SYSERR;
2055 GNUNET_break_op (0);
2056 return GNUNET_SYSERR;
2058 msg->size = htons (size);
2059 GNUNET_TUN_calculate_icmp_checksum (icmp,
2061 (void) GNUNET_HELPER_send (helper_handle,
2071 GNUNET_CONTAINER_heap_update_cost (tunnel_heap,
2073 GNUNET_TIME_absolute_get ().abs_value);
2079 * We got a UDP packet back from the MESH tunnel. Pass it on to the
2080 * local virtual interface via the helper.
2082 * @param cls closure, NULL
2083 * @param tunnel connection to the other end
2084 * @param tunnel_ctx pointer to our 'struct TunnelState *'
2085 * @param sender who sent the message
2086 * @param message the actual message
2087 * @param atsi performance data for the connection
2088 * @return GNUNET_OK to keep the connection open,
2089 * GNUNET_SYSERR to close it (signal serious error)
2092 receive_udp_back (void *cls GNUNET_UNUSED, struct GNUNET_MESH_Tunnel *tunnel,
2093 void **tunnel_ctx, const struct GNUNET_PeerIdentity *sender,
2094 const struct GNUNET_MessageHeader *message,
2095 const struct GNUNET_ATS_Information *atsi GNUNET_UNUSED)
2097 struct TunnelState *ts = *tunnel_ctx;
2098 const struct GNUNET_EXIT_UdpReplyMessage *reply;
2101 GNUNET_STATISTICS_update (stats,
2102 gettext_noop ("# UDP packets received from mesh"),
2104 mlen = ntohs (message->size);
2105 if (mlen < sizeof (struct GNUNET_EXIT_UdpReplyMessage))
2107 GNUNET_break_op (0);
2108 return GNUNET_SYSERR;
2110 if (NULL == ts->heap_node)
2112 GNUNET_break_op (0);
2113 return GNUNET_SYSERR;
2115 if (AF_UNSPEC == ts->af)
2117 GNUNET_break_op (0);
2118 return GNUNET_SYSERR;
2120 reply = (const struct GNUNET_EXIT_UdpReplyMessage *) message;
2121 mlen -= sizeof (struct GNUNET_EXIT_UdpReplyMessage);
2123 char sbuf[INET6_ADDRSTRLEN];
2124 char dbuf[INET6_ADDRSTRLEN];
2126 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2127 "Received UDP reply from mesh, sending %u bytes from %s:%u -> %s:%u via TUN\n",
2128 (unsigned int) mlen,
2129 inet_ntop (ts->af, &ts->destination_ip, sbuf, sizeof (sbuf)),
2130 ts->destination_port,
2131 inet_ntop (ts->af, &ts->source_ip, dbuf, sizeof (dbuf)),
2138 size_t size = sizeof (struct GNUNET_TUN_IPv4Header)
2139 + sizeof (struct GNUNET_TUN_UdpHeader)
2140 + sizeof (struct GNUNET_MessageHeader) +
2141 sizeof (struct GNUNET_TUN_Layer2PacketHeader) +
2144 char buf[size] GNUNET_ALIGN;
2145 struct GNUNET_MessageHeader *msg = (struct GNUNET_MessageHeader *) buf;
2146 struct GNUNET_TUN_Layer2PacketHeader *tun = (struct GNUNET_TUN_Layer2PacketHeader*) &msg[1];
2147 struct GNUNET_TUN_IPv4Header *ipv4 = (struct GNUNET_TUN_IPv4Header *) &tun[1];
2148 struct GNUNET_TUN_UdpHeader *udp = (struct GNUNET_TUN_UdpHeader *) &ipv4[1];
2149 msg->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
2150 msg->size = htons (size);
2151 tun->flags = htons (0);
2152 tun->proto = htons (ETH_P_IPV4);
2153 GNUNET_TUN_initialize_ipv4_header (ipv4,
2155 sizeof (struct GNUNET_TUN_UdpHeader) + mlen,
2156 &ts->destination_ip.v4,
2158 if (0 == ntohs (reply->source_port))
2159 udp->source_port = htons (ts->destination_port);
2161 udp->source_port = reply->source_port;
2162 if (0 == ntohs (reply->destination_port))
2163 udp->destination_port = htons (ts->source_port);
2165 udp->destination_port = reply->destination_port;
2166 udp->len = htons (mlen + sizeof (struct GNUNET_TUN_UdpHeader));
2167 GNUNET_TUN_calculate_udp4_checksum (ipv4,
2174 (void) GNUNET_HELPER_send (helper_handle,
2183 size_t size = sizeof (struct GNUNET_TUN_IPv6Header)
2184 + sizeof (struct GNUNET_TUN_UdpHeader)
2185 + sizeof (struct GNUNET_MessageHeader) +
2186 sizeof (struct GNUNET_TUN_Layer2PacketHeader) +
2189 char buf[size] GNUNET_ALIGN;
2190 struct GNUNET_MessageHeader *msg = (struct GNUNET_MessageHeader *) buf;
2191 struct GNUNET_TUN_Layer2PacketHeader *tun = (struct GNUNET_TUN_Layer2PacketHeader*) &msg[1];
2192 struct GNUNET_TUN_IPv6Header *ipv6 = (struct GNUNET_TUN_IPv6Header *) &tun[1];
2193 struct GNUNET_TUN_UdpHeader *udp = (struct GNUNET_TUN_UdpHeader *) &ipv6[1];
2194 msg->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
2195 msg->size = htons (size);
2196 tun->flags = htons (0);
2197 tun->proto = htons (ETH_P_IPV6);
2198 GNUNET_TUN_initialize_ipv6_header (ipv6,
2200 sizeof (struct GNUNET_TUN_UdpHeader) + mlen,
2201 &ts->destination_ip.v6,
2203 if (0 == ntohs (reply->source_port))
2204 udp->source_port = htons (ts->destination_port);
2206 udp->source_port = reply->source_port;
2207 if (0 == ntohs (reply->destination_port))
2208 udp->destination_port = htons (ts->source_port);
2210 udp->destination_port = reply->destination_port;
2211 udp->len = htons (mlen + sizeof (struct GNUNET_TUN_UdpHeader));
2212 GNUNET_TUN_calculate_udp6_checksum (ipv6,
2218 (void) GNUNET_HELPER_send (helper_handle,
2228 GNUNET_CONTAINER_heap_update_cost (tunnel_heap,
2230 GNUNET_TIME_absolute_get ().abs_value);
2236 * We got a TCP packet back from the MESH tunnel. Pass it on to the
2237 * local virtual interface via the helper.
2239 * @param cls closure, NULL
2240 * @param tunnel connection to the other end
2241 * @param tunnel_ctx pointer to our 'struct TunnelState *'
2242 * @param sender who sent the message
2243 * @param message the actual message
2244 * @param atsi performance data for the connection
2245 * @return GNUNET_OK to keep the connection open,
2246 * GNUNET_SYSERR to close it (signal serious error)
2249 receive_tcp_back (void *cls GNUNET_UNUSED, struct GNUNET_MESH_Tunnel *tunnel,
2251 const struct GNUNET_PeerIdentity *sender GNUNET_UNUSED,
2252 const struct GNUNET_MessageHeader *message,
2253 const struct GNUNET_ATS_Information *atsi GNUNET_UNUSED)
2255 struct TunnelState *ts = *tunnel_ctx;
2256 const struct GNUNET_EXIT_TcpDataMessage *data;
2259 GNUNET_STATISTICS_update (stats,
2260 gettext_noop ("# TCP packets received from mesh"),
2262 mlen = ntohs (message->size);
2263 if (mlen < sizeof (struct GNUNET_EXIT_TcpDataMessage))
2265 GNUNET_break_op (0);
2266 return GNUNET_SYSERR;
2268 if (NULL == ts->heap_node)
2270 GNUNET_break_op (0);
2271 return GNUNET_SYSERR;
2273 data = (const struct GNUNET_EXIT_TcpDataMessage *) message;
2274 mlen -= sizeof (struct GNUNET_EXIT_TcpDataMessage);
2276 char sbuf[INET6_ADDRSTRLEN];
2277 char dbuf[INET6_ADDRSTRLEN];
2279 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2280 "Received TCP reply from mesh, sending %u bytes from %s:%u -> %s:%u via TUN\n",
2281 (unsigned int) mlen,
2282 inet_ntop (ts->af, &ts->destination_ip, sbuf, sizeof (sbuf)),
2283 ts->destination_port,
2284 inet_ntop (ts->af, &ts->source_ip, dbuf, sizeof (dbuf)),
2287 if (data->tcp_header.off * 4 < sizeof (struct GNUNET_TUN_TcpHeader))
2289 GNUNET_break_op (0);
2290 return GNUNET_SYSERR;
2296 size_t size = sizeof (struct GNUNET_TUN_IPv4Header)
2297 + sizeof (struct GNUNET_TUN_TcpHeader)
2298 + sizeof (struct GNUNET_MessageHeader) +
2299 sizeof (struct GNUNET_TUN_Layer2PacketHeader) +
2302 char buf[size] GNUNET_ALIGN;
2303 struct GNUNET_MessageHeader *msg = (struct GNUNET_MessageHeader *) buf;
2304 struct GNUNET_TUN_Layer2PacketHeader *tun = (struct GNUNET_TUN_Layer2PacketHeader*) &msg[1];
2305 struct GNUNET_TUN_IPv4Header *ipv4 = (struct GNUNET_TUN_IPv4Header *) &tun[1];
2306 struct GNUNET_TUN_TcpHeader *tcp = (struct GNUNET_TUN_TcpHeader *) &ipv4[1];
2307 msg->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
2308 msg->size = htons (size);
2309 tun->flags = htons (0);
2310 tun->proto = htons (ETH_P_IPV4);
2311 GNUNET_TUN_initialize_ipv4_header (ipv4,
2313 sizeof (struct GNUNET_TUN_TcpHeader) + mlen,
2314 &ts->destination_ip.v4,
2316 *tcp = data->tcp_header;
2317 tcp->source_port = htons (ts->destination_port);
2318 tcp->destination_port = htons (ts->source_port);
2319 GNUNET_TUN_calculate_tcp4_checksum (ipv4,
2326 (void) GNUNET_HELPER_send (helper_handle,
2335 size_t size = sizeof (struct GNUNET_TUN_IPv6Header)
2336 + sizeof (struct GNUNET_TUN_TcpHeader)
2337 + sizeof (struct GNUNET_MessageHeader) +
2338 sizeof (struct GNUNET_TUN_Layer2PacketHeader) +
2341 char buf[size] GNUNET_ALIGN;
2342 struct GNUNET_MessageHeader *msg = (struct GNUNET_MessageHeader *) buf;
2343 struct GNUNET_TUN_Layer2PacketHeader *tun = (struct GNUNET_TUN_Layer2PacketHeader*) &msg[1];
2344 struct GNUNET_TUN_IPv6Header *ipv6 = (struct GNUNET_TUN_IPv6Header *) &tun[1];
2345 struct GNUNET_TUN_TcpHeader *tcp = (struct GNUNET_TUN_TcpHeader *) &ipv6[1];
2346 msg->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
2347 msg->size = htons (size);
2348 tun->flags = htons (0);
2349 tun->proto = htons (ETH_P_IPV6);
2350 GNUNET_TUN_initialize_ipv6_header (ipv6,
2352 sizeof (struct GNUNET_TUN_TcpHeader) + mlen,
2353 &ts->destination_ip.v6,
2355 *tcp = data->tcp_header;
2356 tcp->source_port = htons (ts->destination_port);
2357 tcp->destination_port = htons (ts->source_port);
2358 GNUNET_TUN_calculate_tcp6_checksum (ipv6,
2365 (void) GNUNET_HELPER_send (helper_handle,
2373 GNUNET_CONTAINER_heap_update_cost (tunnel_heap,
2375 GNUNET_TIME_absolute_get ().abs_value);
2381 * Allocate an IPv4 address from the range of the tunnel
2382 * for a new redirection.
2384 * @param v4 where to store the address
2385 * @return GNUNET_OK on success,
2386 * GNUNET_SYSERR on error
2389 allocate_v4_address (struct in_addr *v4)
2391 const char *ipv4addr = vpn_argv[4];
2392 const char *ipv4mask = vpn_argv[5];
2393 struct in_addr addr;
2394 struct in_addr mask;
2396 struct GNUNET_HashCode key;
2399 GNUNET_assert (1 == inet_pton (AF_INET, ipv4addr, &addr));
2400 GNUNET_assert (1 == inet_pton (AF_INET, ipv4mask, &mask));
2401 /* Given 192.168.0.1/255.255.0.0, we want a mask
2402 of '192.168.255.255', thus: */
2403 mask.s_addr = addr.s_addr | ~mask.s_addr;
2410 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
2411 _("Failed to find unallocated IPv4 address in VPN's range\n"));
2412 return GNUNET_SYSERR;
2414 /* Pick random IPv4 address within the subnet, except 'addr' or 'mask' itself */
2415 rnd.s_addr = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
2417 v4->s_addr = (addr.s_addr | rnd.s_addr) & mask.s_addr;
2418 get_destination_key_from_ip (AF_INET,
2422 while ( (GNUNET_YES ==
2423 GNUNET_CONTAINER_multihashmap_contains (destination_map,
2425 (v4->s_addr == addr.s_addr) ||
2426 (v4->s_addr == mask.s_addr) );
2432 * Allocate an IPv6 address from the range of the tunnel
2433 * for a new redirection.
2435 * @param v6 where to store the address
2436 * @return GNUNET_OK on success,
2437 * GNUNET_SYSERR on error
2440 allocate_v6_address (struct in6_addr *v6)
2442 const char *ipv6addr = vpn_argv[2];
2443 struct in6_addr addr;
2444 struct in6_addr mask;
2445 struct in6_addr rnd;
2447 struct GNUNET_HashCode key;
2450 GNUNET_assert (1 == inet_pton (AF_INET6, ipv6addr, &addr));
2451 GNUNET_assert (ipv6prefix < 128);
2452 /* Given ABCD::/96, we want a mask of 'ABCD::FFFF:FFFF,
2455 for (i=127;i>=ipv6prefix;i--)
2456 mask.s6_addr[i / 8] |= (1 << (i % 8));
2458 /* Pick random IPv6 address within the subnet, except 'addr' or 'mask' itself */
2465 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
2466 _("Failed to find unallocated IPv6 address in VPN's range\n"));
2467 return GNUNET_SYSERR;
2472 rnd.s6_addr[i] = (unsigned char) GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
2475 = (addr.s6_addr[i] | rnd.s6_addr[i]) & mask.s6_addr[i];
2477 get_destination_key_from_ip (AF_INET6,
2481 while ( (GNUNET_YES ==
2482 GNUNET_CONTAINER_multihashmap_contains (destination_map,
2486 sizeof (struct in6_addr))) ||
2489 sizeof (struct in6_addr))) );
2495 * Free resources occupied by a destination entry.
2497 * @param de entry to free
2500 free_destination_entry (struct DestinationEntry *de)
2502 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2503 "Cleaning up destination entry\n");
2504 GNUNET_STATISTICS_update (stats,
2505 gettext_noop ("# Active destinations"),
2509 free_tunnel_state (de->ts);
2510 GNUNET_assert (NULL == de->ts);
2512 if (NULL != de->heap_node)
2514 GNUNET_CONTAINER_heap_remove_node (de->heap_node);
2515 de->heap_node = NULL;
2516 GNUNET_assert (GNUNET_YES ==
2517 GNUNET_CONTAINER_multihashmap_remove (destination_map,
2526 * We have too many active destinations. Clean up the oldest destination.
2528 * @param except destination that must NOT be cleaned up, even if it is the oldest
2531 expire_destination (struct DestinationEntry *except)
2533 struct DestinationEntry *de;
2535 de = GNUNET_CONTAINER_heap_peek (destination_heap);
2536 GNUNET_assert (NULL != de);
2538 return; /* can't do this */
2539 free_destination_entry (de);
2544 * Allocate an IP address for the response.
2546 * @param result_af desired address family; set to the actual
2547 * address family; can initially be AF_UNSPEC if there
2548 * is no preference; will be set to AF_UNSPEC if the
2550 * @param addr set to either v4 or v6 depending on which
2551 * storage location was used; set to NULL if allocation failed
2552 * @param v4 storage space for an IPv4 address
2553 * @param v6 storage space for an IPv6 address
2554 * @return GNUNET_OK normally, GNUNET_SYSERR if '*result_af' was
2555 * an unsupported address family (not AF_INET, AF_INET6 or AF_UNSPEC)
2558 allocate_response_ip (int *result_af,
2561 struct in6_addr *v6)
2568 allocate_v4_address (v4))
2569 *result_af = AF_UNSPEC;
2575 allocate_v6_address (v6))
2576 *result_af = AF_UNSPEC;
2582 allocate_v4_address (v4))
2585 *result_af = AF_INET;
2587 else if (GNUNET_OK ==
2588 allocate_v6_address (v6))
2591 *result_af = AF_INET6;
2596 return GNUNET_SYSERR;
2603 * A client asks us to setup a redirection via some exit
2604 * node to a particular IP. Setup the redirection and
2605 * give the client the allocated IP.
2608 * @param client requesting client
2609 * @param message redirection request (a 'struct RedirectToIpRequestMessage')
2612 service_redirect_to_ip (void *cls GNUNET_UNUSED, struct GNUNET_SERVER_Client *client,
2613 const struct GNUNET_MessageHeader *message)
2617 const struct RedirectToIpRequestMessage *msg;
2623 struct DestinationEntry *de;
2624 struct GNUNET_HashCode key;
2625 struct TunnelState *ts;
2627 /* validate and parse request */
2628 mlen = ntohs (message->size);
2629 if (mlen < sizeof (struct RedirectToIpRequestMessage))
2632 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2635 alen = mlen - sizeof (struct RedirectToIpRequestMessage);
2636 msg = (const struct RedirectToIpRequestMessage *) message;
2637 addr_af = (int) htonl (msg->addr_af);
2641 if (alen != sizeof (struct in_addr))
2644 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2649 if (alen != sizeof (struct in6_addr))
2652 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2658 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2662 /* allocate response IP */
2663 result_af = (int) htonl (msg->result_af);
2664 if (GNUNET_OK != allocate_response_ip (&result_af,
2668 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2671 if ( (result_af == AF_UNSPEC) ||
2672 (GNUNET_NO == ntohl (msg->nac)) )
2674 /* send reply "instantly" */
2675 send_client_reply (client,
2680 if (result_af == AF_UNSPEC)
2682 /* failure, we're done */
2683 GNUNET_SERVER_receive_done (client, GNUNET_OK);
2688 char sbuf[INET6_ADDRSTRLEN];
2689 char dbuf[INET6_ADDRSTRLEN];
2691 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2692 "Allocated address %s for redirection via exit to %s\n",
2693 inet_ntop (result_af, addr, sbuf, sizeof (sbuf)),
2695 &msg[1], dbuf, sizeof (dbuf)));
2698 /* setup destination record */
2699 de = GNUNET_malloc (sizeof (struct DestinationEntry));
2700 de->is_service = GNUNET_NO;
2701 de->details.exit_destination.af = addr_af;
2702 memcpy (&de->details.exit_destination.ip,
2705 get_destination_key_from_ip (result_af,
2709 GNUNET_assert (GNUNET_OK ==
2710 GNUNET_CONTAINER_multihashmap_put (destination_map,
2713 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE));
2714 de->heap_node = GNUNET_CONTAINER_heap_insert (destination_heap,
2716 GNUNET_TIME_absolute_ntoh (msg->expiration_time).abs_value);
2717 GNUNET_STATISTICS_update (stats,
2718 gettext_noop ("# Active destinations"),
2720 while (GNUNET_CONTAINER_multihashmap_size (destination_map) > max_destination_mappings)
2721 expire_destination (de);
2723 /* setup tunnel to destination */
2724 ts = create_tunnel_to_destination (de,
2725 (GNUNET_NO == ntohl (msg->nac)) ? NULL : client,
2731 ts->destination_ip.v4 = v4;
2734 ts->destination_ip.v6 = v6;
2740 GNUNET_SERVER_receive_done (client, GNUNET_OK);
2745 * A client asks us to setup a redirection to a particular peer
2746 * offering a service. Setup the redirection and give the client the
2750 * @param client requesting client
2751 * @param message redirection request (a 'struct RedirectToPeerRequestMessage')
2754 service_redirect_to_service (void *cls GNUNET_UNUSED, struct GNUNET_SERVER_Client *client,
2755 const struct GNUNET_MessageHeader *message)
2757 const struct RedirectToServiceRequestMessage *msg;
2762 struct DestinationEntry *de;
2763 struct GNUNET_HashCode key;
2764 struct TunnelState *ts;
2767 msg = (const struct RedirectToServiceRequestMessage *) message;
2769 /* allocate response IP */
2770 result_af = (int) htonl (msg->result_af);
2771 if (GNUNET_OK != allocate_response_ip (&result_af,
2775 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2778 if ( (result_af == AF_UNSPEC) ||
2779 (GNUNET_NO == ntohl (msg->nac)) )
2781 /* send reply "instantly" */
2782 send_client_reply (client,
2787 if (result_af == AF_UNSPEC)
2789 /* failure, we're done */
2790 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2791 _("Failed to allocate IP address for new destination\n"));
2792 GNUNET_SERVER_receive_done (client, GNUNET_OK);
2797 char sbuf[INET6_ADDRSTRLEN];
2799 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2800 "Allocated address %s for redirection to service %s on peer %s\n",
2801 inet_ntop (result_af, addr, sbuf, sizeof (sbuf)),
2802 GNUNET_h2s (&msg->service_descriptor),
2803 GNUNET_i2s (&msg->target));
2806 /* setup destination record */
2807 de = GNUNET_malloc (sizeof (struct DestinationEntry));
2808 de->is_service = GNUNET_YES;
2809 de->details.service_destination.service_descriptor = msg->service_descriptor;
2810 de->details.service_destination.target = msg->target;
2811 get_destination_key_from_ip (result_af,
2815 GNUNET_assert (GNUNET_OK ==
2816 GNUNET_CONTAINER_multihashmap_put (destination_map,
2819 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE));
2820 de->heap_node = GNUNET_CONTAINER_heap_insert (destination_heap,
2822 GNUNET_TIME_absolute_ntoh (msg->expiration_time).abs_value);
2823 while (GNUNET_CONTAINER_multihashmap_size (destination_map) > max_destination_mappings)
2824 expire_destination (de);
2825 ts = create_tunnel_to_destination (de,
2826 (GNUNET_NO == ntohl (msg->nac)) ? NULL : client,
2832 ts->destination_ip.v4 = v4;
2835 ts->destination_ip.v6 = v6;
2841 GNUNET_SERVER_receive_done (client, GNUNET_OK);
2847 * Function called for inbound tunnels. As we don't offer
2848 * any mesh services, this function should never be called.
2850 * @param cls closure
2851 * @param tunnel new handle to the tunnel
2852 * @param initiator peer that started the tunnel
2853 * @param atsi performance information for the tunnel
2854 * @return initial tunnel context for the tunnel
2855 * (can be NULL -- that's not an error)
2858 inbound_tunnel_cb (void *cls, struct GNUNET_MESH_Tunnel *tunnel,
2859 const struct GNUNET_PeerIdentity *initiator,
2860 const struct GNUNET_ATS_Information *atsi)
2862 /* How can and why should anyone open an inbound tunnel to vpn? */
2869 * Function called whenever an inbound tunnel is destroyed. Should clean up
2870 * any associated state.
2872 * @param cls closure (set from GNUNET_MESH_connect)
2873 * @param tunnel connection to the other end (henceforth invalid)
2874 * @param tunnel_ctx place where local state associated
2875 * with the tunnel is stored (our 'struct TunnelState')
2878 tunnel_cleaner (void *cls, const struct GNUNET_MESH_Tunnel *tunnel, void *tunnel_ctx)
2880 /* we don't have inbound tunnels, so this function should never be called */
2886 * Free memory occupied by an entry in the destination map.
2890 * @param value a 'struct DestinationEntry *'
2891 * @return GNUNET_OK (continue to iterate)
2894 cleanup_destination (void *cls,
2895 const struct GNUNET_HashCode *key,
2898 struct DestinationEntry *de = value;
2900 free_destination_entry (de);
2906 * Free memory occupied by an entry in the tunnel map.
2910 * @param value a 'struct TunnelState *'
2911 * @return GNUNET_OK (continue to iterate)
2914 cleanup_tunnel (void *cls,
2915 const struct GNUNET_HashCode *key,
2918 struct TunnelState *ts = value;
2920 free_tunnel_state (ts);
2926 * Function scheduled as very last function, cleans up after us
2932 cleanup (void *cls GNUNET_UNUSED,
2933 const struct GNUNET_SCHEDULER_TaskContext *tc)
2937 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2938 "VPN is shutting down\n");
2939 if (NULL != destination_map)
2941 GNUNET_CONTAINER_multihashmap_iterate (destination_map,
2942 &cleanup_destination,
2944 GNUNET_CONTAINER_multihashmap_destroy (destination_map);
2945 destination_map = NULL;
2947 if (NULL != destination_heap)
2949 GNUNET_CONTAINER_heap_destroy (destination_heap);
2950 destination_heap = NULL;
2952 if (NULL != tunnel_map)
2954 GNUNET_CONTAINER_multihashmap_iterate (tunnel_map,
2957 GNUNET_CONTAINER_multihashmap_destroy (tunnel_map);
2960 if (NULL != tunnel_heap)
2962 GNUNET_CONTAINER_heap_destroy (tunnel_heap);
2965 if (NULL != mesh_handle)
2967 GNUNET_MESH_disconnect (mesh_handle);
2970 if (NULL != helper_handle)
2972 GNUNET_HELPER_stop (helper_handle, GNUNET_NO);
2973 helper_handle = NULL;
2977 GNUNET_SERVER_notification_context_destroy (nc);
2982 GNUNET_STATISTICS_destroy (stats, GNUNET_NO);
2986 GNUNET_free_non_null (vpn_argv[i]);
2991 * A client disconnected, clean up all references to it.
2993 * @param cls the client that disconnected
2995 * @param value a 'struct TunnelState *'
2996 * @return GNUNET_OK (continue to iterate)
2999 cleanup_tunnel_client (void *cls,
3000 const struct GNUNET_HashCode *key,
3003 struct GNUNET_SERVER_Client *client = cls;
3004 struct TunnelState *ts = value;
3006 if (client == ts->client)
3013 * A client disconnected, clean up all references to it.
3015 * @param cls the client that disconnected
3017 * @param value a 'struct DestinationEntry *'
3018 * @return GNUNET_OK (continue to iterate)
3021 cleanup_destination_client (void *cls,
3022 const struct GNUNET_HashCode *key,
3025 struct GNUNET_SERVER_Client *client = cls;
3026 struct DestinationEntry *de = value;
3027 struct TunnelState *ts;
3029 if (NULL == (ts = de->ts))
3031 if (client == ts->client)
3038 * A client has disconnected from us. If we are currently building
3039 * a tunnel for it, cancel the operation.
3042 * @param client handle to the client that disconnected
3045 client_disconnect (void *cls, struct GNUNET_SERVER_Client *client)
3047 if (NULL != tunnel_map)
3048 GNUNET_CONTAINER_multihashmap_iterate (tunnel_map,
3049 &cleanup_tunnel_client,
3051 if (NULL != destination_map)
3052 GNUNET_CONTAINER_multihashmap_iterate (destination_map,
3053 &cleanup_destination_client,
3059 * Main function that will be run by the scheduler.
3061 * @param cls closure
3062 * @param server the initialized server
3063 * @param cfg_ configuration
3067 struct GNUNET_SERVER_Handle *server,
3068 const struct GNUNET_CONFIGURATION_Handle *cfg_)
3070 static const struct GNUNET_SERVER_MessageHandler service_handlers[] = {
3071 /* callback, cls, type, size */
3072 { &service_redirect_to_ip, NULL, GNUNET_MESSAGE_TYPE_VPN_CLIENT_REDIRECT_TO_IP, 0},
3073 { &service_redirect_to_service, NULL,
3074 GNUNET_MESSAGE_TYPE_VPN_CLIENT_REDIRECT_TO_SERVICE,
3075 sizeof (struct RedirectToServiceRequestMessage) },
3078 static const struct GNUNET_MESH_MessageHandler mesh_handlers[] = {
3079 { &receive_udp_back, GNUNET_MESSAGE_TYPE_VPN_UDP_REPLY, 0},
3080 { &receive_tcp_back, GNUNET_MESSAGE_TYPE_VPN_TCP_DATA_TO_VPN, 0},
3081 { &receive_icmp_back, GNUNET_MESSAGE_TYPE_VPN_ICMP_TO_VPN, 0},
3084 static const GNUNET_MESH_ApplicationType types[] = {
3085 GNUNET_APPLICATION_TYPE_END
3096 binary = GNUNET_OS_get_libexec_binary_path ("gnunet-helper-vpn");
3099 GNUNET_OS_check_helper_binary (binary, GNUNET_YES, "-d gnunet-vpn - - 169.1.3.3.7 255.255.255.0")) //ipv4 only please!
3102 "`%s' is not SUID, refusing to run.\n",
3103 "gnunet-helper-vpn");
3104 GNUNET_free (binary);
3108 GNUNET_free (binary);
3110 stats = GNUNET_STATISTICS_create ("vpn", cfg);
3112 GNUNET_CONFIGURATION_get_value_number (cfg, "vpn", "MAX_MAPPING",
3113 &max_destination_mappings))
3114 max_destination_mappings = 200;
3116 GNUNET_CONFIGURATION_get_value_number (cfg, "vpn", "MAX_TUNNELS",
3117 &max_tunnel_mappings))
3118 max_tunnel_mappings = 200;
3120 destination_map = GNUNET_CONTAINER_multihashmap_create (max_destination_mappings * 2, GNUNET_NO);
3121 destination_heap = GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN);
3122 tunnel_map = GNUNET_CONTAINER_multihashmap_create (max_tunnel_mappings * 2, GNUNET_NO);
3123 tunnel_heap = GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN);
3126 vpn_argv[0] = GNUNET_strdup ("vpn-gnunet");
3127 if (GNUNET_SYSERR ==
3128 GNUNET_CONFIGURATION_get_value_string (cfg, "vpn", "IFNAME", &ifname))
3130 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
3131 "No entry 'IFNAME' in configuration!\n");
3132 GNUNET_SCHEDULER_shutdown ();
3135 vpn_argv[1] = ifname;
3136 if (GNUNET_OK == GNUNET_NETWORK_test_pf (PF_INET6))
3138 if ( (GNUNET_SYSERR ==
3139 GNUNET_CONFIGURATION_get_value_string (cfg, "vpn", "IPV6ADDR",
3141 (1 != inet_pton (AF_INET6, ipv6addr, &v6))) )
3143 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
3144 "No valid entry 'IPV6ADDR' in configuration!\n");
3145 GNUNET_SCHEDULER_shutdown ();
3148 vpn_argv[2] = ipv6addr;
3149 if (GNUNET_SYSERR ==
3150 GNUNET_CONFIGURATION_get_value_string (cfg, "vpn", "IPV6PREFIX",
3153 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
3154 "No entry 'IPV6PREFIX' in configuration!\n");
3155 GNUNET_SCHEDULER_shutdown ();
3158 vpn_argv[3] = ipv6prefix_s;
3160 GNUNET_CONFIGURATION_get_value_number (cfg, "vpn",
3163 (ipv6prefix >= 127) )
3165 GNUNET_SCHEDULER_shutdown ();
3171 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
3172 _("IPv6 support disabled as this system does not support IPv6\n"));
3173 vpn_argv[2] = GNUNET_strdup ("-");
3174 vpn_argv[3] = GNUNET_strdup ("-");
3176 if (GNUNET_OK == GNUNET_NETWORK_test_pf (PF_INET))
3178 if ( (GNUNET_SYSERR ==
3179 GNUNET_CONFIGURATION_get_value_string (cfg, "vpn", "IPV4ADDR",
3181 (1 != inet_pton (AF_INET, ipv4addr, &v4))) )
3183 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
3184 "No valid entry for 'IPV4ADDR' in configuration!\n");
3185 GNUNET_SCHEDULER_shutdown ();
3188 vpn_argv[4] = ipv4addr;
3189 if ( (GNUNET_SYSERR ==
3190 GNUNET_CONFIGURATION_get_value_string (cfg, "vpn", "IPV4MASK",
3192 (1 != inet_pton (AF_INET, ipv4mask, &v4))) )
3194 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
3195 "No valid entry 'IPV4MASK' in configuration!\n");
3196 GNUNET_SCHEDULER_shutdown ();
3199 vpn_argv[5] = ipv4mask;
3203 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
3204 _("IPv4 support disabled as this system does not support IPv4\n"));
3205 vpn_argv[4] = GNUNET_strdup ("-");
3206 vpn_argv[5] = GNUNET_strdup ("-");
3211 GNUNET_MESH_connect (cfg_, NULL,
3216 helper_handle = GNUNET_HELPER_start (GNUNET_NO,
3217 "gnunet-helper-vpn", vpn_argv,
3218 &message_token, NULL, NULL);
3219 nc = GNUNET_SERVER_notification_context_create (server, 1);
3220 GNUNET_SERVER_add_handlers (server, service_handlers);
3221 GNUNET_SERVER_disconnect_notify (server, &client_disconnect, NULL);
3222 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &cleanup, cls);
3227 * The main function of the VPN service.
3229 * @param argc number of arguments from the command line
3230 * @param argv command line arguments
3231 * @return 0 ok, 1 on error
3234 main (int argc, char *const *argv)
3236 return (GNUNET_OK ==
3237 GNUNET_SERVICE_run (argc, argv, "vpn",
3238 GNUNET_SERVICE_OPTION_NONE,
3239 &run, NULL)) ? global_ret : 1;
3242 /* end of gnunet-service-vpn.c */