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 * Destination entry that has a pointer to this tunnel state;
208 * NULL if this tunnel state is in the tunnel map.
210 struct DestinationEntry *destination_container;
213 * Destination to which this tunnel leads. Note that
214 * this struct is NOT in the destination_map (but a
215 * local copy) and that the 'heap_node' should always
218 struct DestinationEntry destination;
221 * Task scheduled to destroy the tunnel (or NO_TASK).
223 GNUNET_SCHEDULER_TaskIdentifier destroy_task;
226 * Addess family used for this tunnel on the local TUN interface.
231 * Length of the doubly linked 'tmq_head/tmq_tail' list.
233 unsigned int tmq_length;
236 * IPPROTO_TCP or IPPROTO_UDP once bound.
241 * IP address of the source on our end, initially uninitialized.
246 * Address if af is AF_INET.
251 * Address if af is AF_INET6.
258 * Destination IP address used by the source on our end (this is the IP
259 * that we pick freely within the VPN's tunnel IP range).
264 * Address if af is AF_INET.
269 * Address if af is AF_INET6.
276 * Source port used by the sender on our end; 0 for uninitialized.
278 uint16_t source_port;
281 * Destination port used by the sender on our end; 0 for uninitialized.
283 uint16_t destination_port;
289 * Return value from 'main'.
291 static int global_ret;
294 * Configuration we use.
296 static const struct GNUNET_CONFIGURATION_Handle *cfg;
299 * Handle to the mesh service.
301 static struct GNUNET_MESH_Handle *mesh_handle;
304 * Map from IP address to destination information (possibly with a
305 * MESH tunnel handle for fast setup).
307 static struct GNUNET_CONTAINER_MultiHashMap *destination_map;
310 * Min-Heap sorted by activity time to expire old mappings.
312 static struct GNUNET_CONTAINER_Heap *destination_heap;
315 * Map from source and destination address (IP+port) to connection
316 * information (mostly with the respective MESH tunnel handle).
318 static struct GNUNET_CONTAINER_MultiHashMap *tunnel_map;
321 * Min-Heap sorted by activity time to expire old mappings; values are
322 * of type 'struct TunnelState'.
324 static struct GNUNET_CONTAINER_Heap *tunnel_heap;
329 static struct GNUNET_STATISTICS_Handle *stats;
332 * The handle to the VPN helper process "gnunet-helper-vpn".
334 static struct GNUNET_HELPER_Handle *helper_handle;
337 * Arguments to the vpn helper.
339 static char *vpn_argv[7];
342 * Length of the prefix of the VPN's IPv6 network.
344 static unsigned long long ipv6prefix;
347 * Notification context for sending replies to clients.
349 static struct GNUNET_SERVER_NotificationContext *nc;
352 * If there are more than this number of address-mappings, old ones
355 static unsigned long long max_destination_mappings;
358 * If there are more than this number of open tunnels, old ones
361 static unsigned long long max_tunnel_mappings;
365 * Compute the key under which we would store an entry in the
366 * destination_map for the given IP address.
368 * @param af address family (AF_INET or AF_INET6)
369 * @param address IP address, struct in_addr or struct in6_addr
370 * @param key where to store the key
373 get_destination_key_from_ip (int af,
375 struct GNUNET_HashCode *key)
380 GNUNET_CRYPTO_hash (address,
381 sizeof (struct in_addr),
385 GNUNET_CRYPTO_hash (address,
386 sizeof (struct in6_addr),
397 * Compute the key under which we would store an entry in the
398 * tunnel_map for the given socket address pair.
400 * @param af address family (AF_INET or AF_INET6)
401 * @param protocol IPPROTO_TCP or IPPROTO_UDP
402 * @param source_ip sender's source IP, struct in_addr or struct in6_addr
403 * @param source_port sender's source port
404 * @param destination_ip sender's destination IP, struct in_addr or struct in6_addr
405 * @param destination_port sender's destination port
406 * @param key where to store the key
409 get_tunnel_key_from_ips (int af,
411 const void *source_ip,
412 uint16_t source_port,
413 const void *destination_ip,
414 uint16_t destination_port,
415 struct GNUNET_HashCode *key)
419 memset (key, 0, sizeof (struct GNUNET_HashCode));
420 /* the GNUnet hashmap only uses the first sizeof(unsigned int) of the hash,
421 so we put the ports in there (and hope for few collisions) */
423 memcpy (off, &source_port, sizeof (uint16_t));
424 off += sizeof (uint16_t);
425 memcpy (off, &destination_port, sizeof (uint16_t));
426 off += sizeof (uint16_t);
430 memcpy (off, source_ip, sizeof (struct in_addr));
431 off += sizeof (struct in_addr);
432 memcpy (off, destination_ip, sizeof (struct in_addr));
433 off += sizeof (struct in_addr);
436 memcpy (off, source_ip, sizeof (struct in6_addr));
437 off += sizeof (struct in6_addr);
438 memcpy (off, destination_ip, sizeof (struct in6_addr));
439 off += sizeof (struct in6_addr);
445 memcpy (off, &protocol, sizeof (uint8_t));
446 /* off += sizeof (uint8_t); */
451 * Notify the client about the result of its request.
453 * @param client client to notify
454 * @param request_id original request ID to include in response
455 * @param result_af resulting address family
456 * @param addr resulting IP address
459 send_client_reply (struct GNUNET_SERVER_Client *client,
464 char buf[sizeof (struct RedirectToIpResponseMessage) + sizeof (struct in6_addr)] GNUNET_ALIGN;
465 struct RedirectToIpResponseMessage *res;
471 rlen = sizeof (struct in_addr);
474 rlen = sizeof (struct in6_addr);
483 res = (struct RedirectToIpResponseMessage *) buf;
484 res->header.size = htons (sizeof (struct RedirectToIpResponseMessage) + rlen);
485 res->header.type = htons (GNUNET_MESSAGE_TYPE_VPN_CLIENT_USE_IP);
486 res->result_af = htonl (result_af);
487 res->request_id = request_id;
488 memcpy (&res[1], addr, rlen);
489 GNUNET_SERVER_notification_context_add (nc, client);
490 GNUNET_SERVER_notification_context_unicast (nc,
498 * Free resources associated with a tunnel state.
500 * @param ts state to free
503 free_tunnel_state (struct TunnelState *ts)
505 struct GNUNET_HashCode key;
506 struct TunnelMessageQueueEntry *tnq;
507 struct GNUNET_MESH_Tunnel *tunnel;
509 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
510 "Cleaning up tunnel state\n");
511 GNUNET_STATISTICS_update (stats,
512 gettext_noop ("# Active tunnels"),
514 while (NULL != (tnq = ts->tmq_head))
516 GNUNET_CONTAINER_DLL_remove (ts->tmq_head,
522 GNUNET_assert (0 == ts->tmq_length);
525 GNUNET_MESH_notify_transmit_ready_cancel (ts->th);
528 GNUNET_assert (NULL == ts->destination.heap_node);
529 if (NULL != (tunnel = ts->tunnel))
532 GNUNET_MESH_tunnel_destroy (tunnel);
534 if (NULL != ts->search)
536 GNUNET_REGEX_search_cancel (ts->search);
539 if (GNUNET_SCHEDULER_NO_TASK != ts->destroy_task)
541 GNUNET_SCHEDULER_cancel (ts->destroy_task);
542 ts->destroy_task = GNUNET_SCHEDULER_NO_TASK;
544 if (NULL != ts->heap_node)
546 GNUNET_CONTAINER_heap_remove_node (ts->heap_node);
547 ts->heap_node = NULL;
548 get_tunnel_key_from_ips (ts->af,
553 ts->destination_port,
555 GNUNET_assert (GNUNET_YES ==
556 GNUNET_CONTAINER_multihashmap_remove (tunnel_map,
560 if (NULL != ts->destination_container)
562 GNUNET_assert (ts == ts->destination_container->ts);
563 ts->destination_container->ts = NULL;
564 ts->destination_container = NULL;
571 * Destroy the mesh tunnel.
573 * @param cls the `struct TunnelState` with the tunnel to destroy
574 * @param tc scheduler context
577 destroy_tunnel_task (void *cls,
578 const struct GNUNET_SCHEDULER_TaskContext *tc)
580 struct TunnelState *ts = cls;
581 struct GNUNET_MESH_Tunnel *tunnel;
583 ts->destroy_task = GNUNET_SCHEDULER_NO_TASK;
584 GNUNET_assert (NULL != ts->tunnel);
587 GNUNET_MESH_tunnel_destroy (tunnel);
588 free_tunnel_state (ts);
593 * Method called whenever a peer has disconnected from the tunnel.
595 * FIXME merge with inbound_cleaner
598 * @param peer peer identity the tunnel stopped working with
601 tunnel_peer_disconnect_handler (void *cls,
603 GNUNET_PeerIdentity *peer)
605 struct TunnelState *ts = cls;
607 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
608 "Peer %s disconnected from tunnel.\n",
610 GNUNET_STATISTICS_update (stats,
611 gettext_noop ("# peers connected to mesh tunnels"),
615 GNUNET_MESH_notify_transmit_ready_cancel (ts->th);
618 if (ts->destination.is_service)
619 return; /* hope for reconnect eventually */
620 /* as we are most likely going to change the exit node now,
621 we should just destroy the tunnel entirely... */
622 if (GNUNET_SCHEDULER_NO_TASK == ts->destroy_task)
623 ts->destroy_task = GNUNET_SCHEDULER_add_now (&destroy_tunnel_task, ts);
628 * Send a message from the message queue via mesh.
630 * @param cls the `struct TunnelState` with the message queue
631 * @param size number of bytes available in @a buf
632 * @param buf where to copy the message
633 * @return number of bytes copied to @a buf
636 send_to_peer_notify_callback (void *cls, size_t size, void *buf)
638 struct TunnelState *ts = cls;
639 struct TunnelMessageQueueEntry *tnq;
646 GNUNET_assert (NULL != tnq);
647 GNUNET_assert (size >= tnq->len);
648 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
649 "Sending %u bytes via mesh tunnel\n",
651 GNUNET_CONTAINER_DLL_remove (ts->tmq_head,
655 memcpy (buf, tnq->msg, tnq->len);
658 if (NULL != (tnq = ts->tmq_head))
659 ts->th = GNUNET_MESH_notify_transmit_ready (ts->tunnel,
660 GNUNET_NO /* cork */,
661 GNUNET_TIME_UNIT_FOREVER_REL,
663 &send_to_peer_notify_callback,
665 GNUNET_STATISTICS_update (stats,
666 gettext_noop ("# Bytes given to mesh for transmission"),
673 * Add the given message to the given tunnel and trigger the
674 * transmission process.
676 * @param tnq message to queue
677 * @param ts tunnel to queue the message for
680 send_to_tunnel (struct TunnelMessageQueueEntry *tnq,
681 struct TunnelState *ts)
683 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
684 "Queueing %u bytes for transmission via mesh tunnel\n",
686 GNUNET_assert (NULL != ts->tunnel);
687 GNUNET_CONTAINER_DLL_insert_tail (ts->tmq_head,
691 if (ts->tmq_length > MAX_MESSAGE_QUEUE_SIZE)
693 struct TunnelMessageQueueEntry *dq;
696 GNUNET_assert (dq != tnq);
697 GNUNET_CONTAINER_DLL_remove (ts->tmq_head,
701 GNUNET_MESH_notify_transmit_ready_cancel (ts->th);
703 GNUNET_STATISTICS_update (stats,
704 gettext_noop ("# Bytes dropped in mesh queue (overflow)"),
710 ts->th = GNUNET_MESH_notify_transmit_ready (ts->tunnel,
711 GNUNET_NO /* cork */,
712 GNUNET_TIME_UNIT_FOREVER_REL,
714 &send_to_peer_notify_callback,
720 * Regex has found a potential exit peer for us; consider using it.
722 * @param cls the 'struct TunnelState'
723 * @param id Peer providing a regex that matches the string.
724 * @param get_path Path of the get request.
725 * @param get_path_length Lenght of get_path.
726 * @param put_path Path of the put request.
727 * @param put_path_length Length of the put_path.
730 handle_regex_result (void *cls,
731 const struct GNUNET_PeerIdentity *id,
732 const struct GNUNET_PeerIdentity *get_path,
733 unsigned int get_path_length,
734 const struct GNUNET_PeerIdentity *put_path,
735 unsigned int put_path_length)
737 struct TunnelState *ts = cls;
739 GNUNET_REGEX_search_cancel (ts->search);
741 ts->tunnel = GNUNET_MESH_tunnel_create (mesh_handle,
751 * Initialize the given destination entry's mesh tunnel.
753 * @param de destination entry for which we need to setup a tunnel
754 * @param client_af address family of the address returned to the client
755 * @param request_id request ID to send in client notification (unused if client is NULL)
756 * @return tunnel state of the tunnel that was created
758 static struct TunnelState *
759 create_tunnel_to_destination (struct DestinationEntry *de,
763 struct TunnelState *ts;
765 GNUNET_STATISTICS_update (stats,
766 gettext_noop ("# Mesh tunnels created"),
768 GNUNET_assert (NULL == de->ts);
769 ts = GNUNET_new (struct TunnelState);
771 ts->destination = *de;
772 ts->destination.heap_node = NULL; /* copy is NOT in destination heap */
774 ts->destination_container = de; /* we are referenced from de */
777 ts->tunnel = GNUNET_MESH_tunnel_create (mesh_handle,
779 &de->details.service_destination.target,
783 if (NULL == ts->tunnel)
785 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
786 _("Failed to setup mesh tunnel!\n"));
790 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
791 "Creating tunnel to peer %s offering service %s\n",
792 GNUNET_i2s (&de->details.service_destination.target),
793 GNUNET_h2s (&de->details.service_destination.service_descriptor));
799 switch (de->details.exit_destination.af)
803 char address[GNUNET_TUN_IPV4_REGEXLEN];
805 GNUNET_TUN_ipv4toregexsearch (&de->details.exit_destination.ip.v4,
806 "255.255.255.255", address);
807 GNUNET_asprintf (&policy, "%s%s%s",
808 GNUNET_APPLICATION_TYPE_EXIT_REGEX_PREFIX,
815 char address[GNUNET_TUN_IPV6_REGEXLEN];
817 GNUNET_TUN_ipv6toregexsearch (&de->details.exit_destination.ip.v6,
819 GNUNET_asprintf (&policy, "%s%s%s",
820 GNUNET_APPLICATION_TYPE_EXIT_REGEX_PREFIX,
830 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
831 "Requesting connect by string: %s\n",
833 ts->search = GNUNET_REGEX_search (cfg,
835 &handle_regex_result,
837 GNUNET_free (policy);
844 * We have too many active tunnels. Clean up the oldest tunnel.
846 * @param except tunnel that must NOT be cleaned up, even if it is the oldest
849 expire_tunnel (struct TunnelState *except)
851 struct TunnelState *ts;
853 ts = GNUNET_CONTAINER_heap_peek (tunnel_heap);
854 GNUNET_assert (NULL != ts);
856 return; /* can't do this */
857 free_tunnel_state (ts);
862 * Route a packet via mesh to the given destination.
864 * @param destination description of the destination
865 * @param af address family on this end (AF_INET or AF_INET6)
866 * @param protocol IPPROTO_TCP or IPPROTO_UDP or IPPROTO_ICMP or IPPROTO_ICMPV6
867 * @param source_ip source IP used by the sender (struct in_addr or struct in6_addr)
868 * @param destination_ip destination IP used by the sender (struct in_addr or struct in6_addr)
869 * @param payload payload of the packet after the IP header
870 * @param payload_length number of bytes in payload
873 route_packet (struct DestinationEntry *destination,
876 const void *source_ip,
877 const void *destination_ip,
879 size_t payload_length)
881 struct GNUNET_HashCode key;
882 struct TunnelState *ts;
883 struct TunnelMessageQueueEntry *tnq;
887 const struct GNUNET_TUN_UdpHeader *udp;
888 const struct GNUNET_TUN_TcpHeader *tcp;
889 const struct GNUNET_TUN_IcmpHeader *icmp;
890 uint16_t source_port;
891 uint16_t destination_port;
897 if (payload_length < sizeof (struct GNUNET_TUN_UdpHeader))
903 tcp = NULL; /* make compiler happy */
904 icmp = NULL; /* make compiler happy */
906 if (udp->len < sizeof (struct GNUNET_TUN_UdpHeader))
911 source_port = ntohs (udp->source_port);
912 destination_port = ntohs (udp->destination_port);
913 get_tunnel_key_from_ips (af,
924 if (payload_length < sizeof (struct GNUNET_TUN_TcpHeader))
930 udp = NULL; /* make compiler happy */
931 icmp = NULL; /* make compiler happy */
933 if (tcp->off * 4 < sizeof (struct GNUNET_TUN_TcpHeader))
938 source_port = ntohs (tcp->source_port);
939 destination_port = ntohs (tcp->destination_port);
940 get_tunnel_key_from_ips (af,
952 if ( (AF_INET == af) ^ (protocol == IPPROTO_ICMP) )
957 if (payload_length < sizeof (struct GNUNET_TUN_IcmpHeader))
963 tcp = NULL; /* make compiler happy */
964 udp = NULL; /* make compiler happy */
967 destination_port = 0;
968 get_tunnel_key_from_ips (af,
978 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
979 _("Protocol %u not supported, dropping\n"),
980 (unsigned int) protocol);
984 if (! destination->is_service)
986 switch (destination->details.exit_destination.af)
989 alen = sizeof (struct in_addr);
992 alen = sizeof (struct in6_addr);
999 char sbuf[INET6_ADDRSTRLEN];
1000 char dbuf[INET6_ADDRSTRLEN];
1001 char xbuf[INET6_ADDRSTRLEN];
1003 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1004 "Routing %s packet from %s:%u -> %s:%u to destination %s:%u\n",
1005 (protocol == IPPROTO_TCP) ? "TCP" : "UDP",
1006 inet_ntop (af, source_ip, sbuf, sizeof (sbuf)),
1008 inet_ntop (af, destination_ip, dbuf, sizeof (dbuf)),
1010 inet_ntop (destination->details.exit_destination.af,
1011 &destination->details.exit_destination.ip,
1012 xbuf, sizeof (xbuf)),
1019 char sbuf[INET6_ADDRSTRLEN];
1020 char dbuf[INET6_ADDRSTRLEN];
1022 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1023 "Routing %s packet from %s:%u -> %s:%u to service %s at peer %s\n",
1024 (protocol == IPPROTO_TCP) ? "TCP" : "UDP",
1025 inet_ntop (af, source_ip, sbuf, sizeof (sbuf)),
1027 inet_ntop (af, destination_ip, dbuf, sizeof (dbuf)),
1029 GNUNET_h2s (&destination->details.service_destination.service_descriptor),
1030 GNUNET_i2s (&destination->details.service_destination.target));
1035 /* see if we have an existing tunnel for this destination */
1036 ts = GNUNET_CONTAINER_multihashmap_get (tunnel_map,
1040 /* need to either use the existing tunnel from the destination (if still
1041 available) or create a fresh one */
1042 is_new = GNUNET_YES;
1043 if (NULL == destination->ts)
1044 ts = create_tunnel_to_destination (destination, af, 0);
1046 ts = destination->ts;
1049 destination->ts = NULL;
1050 ts->destination_container = NULL; /* no longer 'contained' */
1051 /* now bind existing "unbound" tunnel to our IP/port tuple */
1052 ts->protocol = protocol;
1056 ts->source_ip.v4 = * (const struct in_addr *) source_ip;
1057 ts->destination_ip.v4 = * (const struct in_addr *) destination_ip;
1061 ts->source_ip.v6 = * (const struct in6_addr *) source_ip;
1062 ts->destination_ip.v6 = * (const struct in6_addr *) destination_ip;
1064 ts->source_port = source_port;
1065 ts->destination_port = destination_port;
1066 ts->heap_node = GNUNET_CONTAINER_heap_insert (tunnel_heap,
1068 GNUNET_TIME_absolute_get ().abs_value_us);
1069 GNUNET_assert (GNUNET_YES ==
1070 GNUNET_CONTAINER_multihashmap_put (tunnel_map,
1073 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
1074 GNUNET_STATISTICS_update (stats,
1075 gettext_noop ("# Active tunnels"),
1077 while (GNUNET_CONTAINER_multihashmap_size (tunnel_map) > max_tunnel_mappings)
1083 GNUNET_CONTAINER_heap_update_cost (tunnel_heap,
1085 GNUNET_TIME_absolute_get ().abs_value_us);
1087 GNUNET_assert (NULL != ts->tunnel);
1089 /* send via tunnel */
1093 if (destination->is_service)
1095 struct GNUNET_EXIT_UdpServiceMessage *usm;
1097 mlen = sizeof (struct GNUNET_EXIT_UdpServiceMessage) +
1098 payload_length - sizeof (struct GNUNET_TUN_UdpHeader);
1099 if (mlen >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1104 tnq = GNUNET_malloc (sizeof (struct TunnelMessageQueueEntry) + mlen);
1107 usm = (struct GNUNET_EXIT_UdpServiceMessage *) &tnq[1];
1108 usm->header.size = htons ((uint16_t) mlen);
1109 usm->header.type = htons (GNUNET_MESSAGE_TYPE_VPN_UDP_TO_SERVICE);
1110 /* if the source port is below 32000, we assume it has a special
1111 meaning; if not, we pick a random port (this is a heuristic) */
1112 usm->source_port = (ntohs (udp->source_port) < 32000) ? udp->source_port : 0;
1113 usm->destination_port = udp->destination_port;
1114 usm->service_descriptor = destination->details.service_destination.service_descriptor;
1117 payload_length - sizeof (struct GNUNET_TUN_UdpHeader));
1121 struct GNUNET_EXIT_UdpInternetMessage *uim;
1122 struct in_addr *ip4dst;
1123 struct in6_addr *ip6dst;
1126 mlen = sizeof (struct GNUNET_EXIT_UdpInternetMessage) +
1127 alen + payload_length - sizeof (struct GNUNET_TUN_UdpHeader);
1128 if (mlen >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1133 tnq = GNUNET_malloc (sizeof (struct TunnelMessageQueueEntry) +
1137 uim = (struct GNUNET_EXIT_UdpInternetMessage *) &tnq[1];
1138 uim->header.size = htons ((uint16_t) mlen);
1139 uim->header.type = htons (GNUNET_MESSAGE_TYPE_VPN_UDP_TO_INTERNET);
1140 uim->af = htonl (destination->details.exit_destination.af);
1141 uim->source_port = (ntohs (udp->source_port) < 32000) ? udp->source_port : 0;
1142 uim->destination_port = udp->destination_port;
1143 switch (destination->details.exit_destination.af)
1146 ip4dst = (struct in_addr *) &uim[1];
1147 *ip4dst = destination->details.exit_destination.ip.v4;
1148 payload = &ip4dst[1];
1151 ip6dst = (struct in6_addr *) &uim[1];
1152 *ip6dst = destination->details.exit_destination.ip.v6;
1153 payload = &ip6dst[1];
1160 payload_length - sizeof (struct GNUNET_TUN_UdpHeader));
1166 if (destination->is_service)
1168 struct GNUNET_EXIT_TcpServiceStartMessage *tsm;
1170 mlen = sizeof (struct GNUNET_EXIT_TcpServiceStartMessage) +
1171 payload_length - sizeof (struct GNUNET_TUN_TcpHeader);
1172 if (mlen >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1177 tnq = GNUNET_malloc (sizeof (struct TunnelMessageQueueEntry) + mlen);
1180 tsm = (struct GNUNET_EXIT_TcpServiceStartMessage *) &tnq[1];
1181 tsm->header.size = htons ((uint16_t) mlen);
1182 tsm->header.type = htons (GNUNET_MESSAGE_TYPE_VPN_TCP_TO_SERVICE_START);
1183 tsm->reserved = htonl (0);
1184 tsm->service_descriptor = destination->details.service_destination.service_descriptor;
1185 tsm->tcp_header = *tcp;
1188 payload_length - sizeof (struct GNUNET_TUN_TcpHeader));
1192 struct GNUNET_EXIT_TcpInternetStartMessage *tim;
1193 struct in_addr *ip4dst;
1194 struct in6_addr *ip6dst;
1197 mlen = sizeof (struct GNUNET_EXIT_TcpInternetStartMessage) +
1198 alen + payload_length - sizeof (struct GNUNET_TUN_TcpHeader);
1199 if (mlen >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1204 tnq = GNUNET_malloc (sizeof (struct TunnelMessageQueueEntry) + mlen);
1207 tim = (struct GNUNET_EXIT_TcpInternetStartMessage *) &tnq[1];
1208 tim->header.size = htons ((uint16_t) mlen);
1209 tim->header.type = htons (GNUNET_MESSAGE_TYPE_VPN_TCP_TO_INTERNET_START);
1210 tim->af = htonl (destination->details.exit_destination.af);
1211 tim->tcp_header = *tcp;
1212 switch (destination->details.exit_destination.af)
1215 ip4dst = (struct in_addr *) &tim[1];
1216 *ip4dst = destination->details.exit_destination.ip.v4;
1217 payload = &ip4dst[1];
1220 ip6dst = (struct in6_addr *) &tim[1];
1221 *ip6dst = destination->details.exit_destination.ip.v6;
1222 payload = &ip6dst[1];
1229 payload_length - sizeof (struct GNUNET_TUN_TcpHeader));
1234 struct GNUNET_EXIT_TcpDataMessage *tdm;
1236 mlen = sizeof (struct GNUNET_EXIT_TcpDataMessage) +
1237 payload_length - sizeof (struct GNUNET_TUN_TcpHeader);
1238 if (mlen >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1243 tnq = GNUNET_malloc (sizeof (struct TunnelMessageQueueEntry) + mlen);
1246 tdm = (struct GNUNET_EXIT_TcpDataMessage *) &tnq[1];
1247 tdm->header.size = htons ((uint16_t) mlen);
1248 tdm->header.type = htons (GNUNET_MESSAGE_TYPE_VPN_TCP_DATA_TO_EXIT);
1249 tdm->reserved = htonl (0);
1250 tdm->tcp_header = *tcp;
1253 payload_length - sizeof (struct GNUNET_TUN_TcpHeader));
1257 case IPPROTO_ICMPV6:
1258 if (destination->is_service)
1260 struct GNUNET_EXIT_IcmpServiceMessage *ism;
1262 mlen = sizeof (struct GNUNET_EXIT_IcmpServiceMessage) +
1263 payload_length - sizeof (struct GNUNET_TUN_IcmpHeader);
1264 if (mlen >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1269 tnq = GNUNET_malloc (sizeof (struct TunnelMessageQueueEntry) + mlen);
1271 ism = (struct GNUNET_EXIT_IcmpServiceMessage *) &tnq[1];
1272 ism->header.type = htons (GNUNET_MESSAGE_TYPE_VPN_ICMP_TO_SERVICE);
1273 ism->af = htonl (af); /* need to tell destination ICMP protocol family! */
1274 ism->service_descriptor = destination->details.service_destination.service_descriptor;
1275 ism->icmp_header = *icmp;
1276 /* ICMP protocol translation will be done by the receiver (as we don't know
1277 the target AF); however, we still need to possibly discard the payload
1278 depending on the ICMP type */
1284 case GNUNET_TUN_ICMPTYPE_ECHO_REPLY:
1285 case GNUNET_TUN_ICMPTYPE_ECHO_REQUEST:
1287 case GNUNET_TUN_ICMPTYPE_DESTINATION_UNREACHABLE:
1288 case GNUNET_TUN_ICMPTYPE_SOURCE_QUENCH:
1289 case GNUNET_TUN_ICMPTYPE_TIME_EXCEEDED:
1290 /* throw away ICMP payload, won't be useful for the other side anyway */
1291 payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
1294 GNUNET_STATISTICS_update (stats,
1295 gettext_noop ("# ICMPv4 packets dropped (not allowed)"),
1299 /* end of AF_INET */
1304 case GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE:
1305 case GNUNET_TUN_ICMPTYPE6_PACKET_TOO_BIG:
1306 case GNUNET_TUN_ICMPTYPE6_TIME_EXCEEDED:
1307 case GNUNET_TUN_ICMPTYPE6_PARAMETER_PROBLEM:
1308 /* throw away ICMP payload, won't be useful for the other side anyway */
1309 payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
1311 case GNUNET_TUN_ICMPTYPE6_ECHO_REQUEST:
1312 case GNUNET_TUN_ICMPTYPE6_ECHO_REPLY:
1315 GNUNET_STATISTICS_update (stats,
1316 gettext_noop ("# ICMPv6 packets dropped (not allowed)"),
1320 /* end of AF_INET6 */
1327 /* update length calculations, as payload_length may have changed */
1328 mlen = sizeof (struct GNUNET_EXIT_IcmpServiceMessage) +
1329 alen + payload_length - sizeof (struct GNUNET_TUN_IcmpHeader);
1331 ism->header.size = htons ((uint16_t) mlen);
1332 /* finally, copy payload (if there is any left...) */
1335 payload_length - sizeof (struct GNUNET_TUN_IcmpHeader));
1339 struct GNUNET_EXIT_IcmpInternetMessage *iim;
1340 struct in_addr *ip4dst;
1341 struct in6_addr *ip6dst;
1344 mlen = sizeof (struct GNUNET_EXIT_IcmpInternetMessage) +
1345 alen + payload_length - sizeof (struct GNUNET_TUN_IcmpHeader);
1346 if (mlen >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1351 tnq = GNUNET_malloc (sizeof (struct TunnelMessageQueueEntry) +
1354 iim = (struct GNUNET_EXIT_IcmpInternetMessage *) &tnq[1];
1355 iim->header.type = htons (GNUNET_MESSAGE_TYPE_VPN_ICMP_TO_INTERNET);
1356 iim->icmp_header = *icmp;
1357 /* Perform ICMP protocol-translation (depending on destination AF and source AF)
1358 and throw away ICMP payload depending on ICMP message type */
1364 case GNUNET_TUN_ICMPTYPE_ECHO_REPLY:
1365 if (destination->details.exit_destination.af == AF_INET6)
1366 iim->icmp_header.type = GNUNET_TUN_ICMPTYPE6_ECHO_REPLY;
1368 case GNUNET_TUN_ICMPTYPE_ECHO_REQUEST:
1369 if (destination->details.exit_destination.af == AF_INET6)
1370 iim->icmp_header.type = GNUNET_TUN_ICMPTYPE6_ECHO_REQUEST;
1372 case GNUNET_TUN_ICMPTYPE_DESTINATION_UNREACHABLE:
1373 if (destination->details.exit_destination.af == AF_INET6)
1374 iim->icmp_header.type = GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE;
1375 /* throw away IP-payload, exit will have to make it up anyway */
1376 payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
1378 case GNUNET_TUN_ICMPTYPE_TIME_EXCEEDED:
1379 if (destination->details.exit_destination.af == AF_INET6)
1380 iim->icmp_header.type = GNUNET_TUN_ICMPTYPE6_TIME_EXCEEDED;
1381 /* throw away IP-payload, exit will have to make it up anyway */
1382 payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
1384 case GNUNET_TUN_ICMPTYPE_SOURCE_QUENCH:
1385 if (destination->details.exit_destination.af == AF_INET6)
1387 GNUNET_STATISTICS_update (stats,
1388 gettext_noop ("# ICMPv4 packets dropped (impossible PT to v6)"),
1393 /* throw away IP-payload, exit will have to make it up anyway */
1394 payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
1397 GNUNET_STATISTICS_update (stats,
1398 gettext_noop ("# ICMPv4 packets dropped (type not allowed)"),
1403 /* end of AF_INET */
1408 case GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE:
1409 if (destination->details.exit_destination.af == AF_INET6)
1410 iim->icmp_header.type = GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE;
1411 /* throw away IP-payload, exit will have to make it up anyway */
1412 payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
1414 case GNUNET_TUN_ICMPTYPE6_TIME_EXCEEDED:
1415 if (destination->details.exit_destination.af == AF_INET)
1416 iim->icmp_header.type = GNUNET_TUN_ICMPTYPE_TIME_EXCEEDED;
1417 /* throw away IP-payload, exit will have to make it up anyway */
1418 payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
1420 case GNUNET_TUN_ICMPTYPE6_PACKET_TOO_BIG:
1421 if (destination->details.exit_destination.af == AF_INET)
1423 GNUNET_STATISTICS_update (stats,
1424 gettext_noop ("# ICMPv6 packets dropped (impossible PT to v4)"),
1429 /* throw away IP-payload, exit will have to make it up anyway */
1430 payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
1432 case GNUNET_TUN_ICMPTYPE6_PARAMETER_PROBLEM:
1433 if (destination->details.exit_destination.af == AF_INET)
1435 GNUNET_STATISTICS_update (stats,
1436 gettext_noop ("# ICMPv6 packets dropped (impossible PT to v4)"),
1441 /* throw away IP-payload, exit will have to make it up anyway */
1442 payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
1444 case GNUNET_TUN_ICMPTYPE6_ECHO_REQUEST:
1445 if (destination->details.exit_destination.af == AF_INET)
1446 iim->icmp_header.type = GNUNET_TUN_ICMPTYPE_ECHO_REQUEST;
1448 case GNUNET_TUN_ICMPTYPE6_ECHO_REPLY:
1449 if (destination->details.exit_destination.af == AF_INET)
1450 iim->icmp_header.type = GNUNET_TUN_ICMPTYPE_ECHO_REPLY;
1453 GNUNET_STATISTICS_update (stats,
1454 gettext_noop ("# ICMPv6 packets dropped (type not allowed)"),
1459 /* end of AF_INET6 */
1464 /* update length calculations, as payload_length may have changed */
1465 mlen = sizeof (struct GNUNET_EXIT_IcmpInternetMessage) +
1466 alen + payload_length - sizeof (struct GNUNET_TUN_IcmpHeader);
1468 iim->header.size = htons ((uint16_t) mlen);
1470 /* need to tell destination ICMP protocol family! */
1471 iim->af = htonl (destination->details.exit_destination.af);
1472 switch (destination->details.exit_destination.af)
1475 ip4dst = (struct in_addr *) &iim[1];
1476 *ip4dst = destination->details.exit_destination.ip.v4;
1477 payload = &ip4dst[1];
1480 ip6dst = (struct in6_addr *) &iim[1];
1481 *ip6dst = destination->details.exit_destination.ip.v6;
1482 payload = &ip6dst[1];
1489 payload_length - sizeof (struct GNUNET_TUN_IcmpHeader));
1493 /* not supported above, how can we get here !? */
1497 send_to_tunnel (tnq, ts);
1502 * Receive packets from the helper-process (someone send to the local
1503 * virtual tunnel interface). Find the destination mapping, and if it
1504 * exists, identify the correct MESH tunnel (or possibly create it)
1505 * and forward the packet.
1507 * @param cls closure, NULL
1508 * @param client NULL
1509 * @param message message we got from the client (VPN tunnel interface)
1512 message_token (void *cls GNUNET_UNUSED, void *client GNUNET_UNUSED,
1513 const struct GNUNET_MessageHeader *message)
1515 const struct GNUNET_TUN_Layer2PacketHeader *tun;
1517 struct GNUNET_HashCode key;
1518 struct DestinationEntry *de;
1520 GNUNET_STATISTICS_update (stats,
1521 gettext_noop ("# Packets received from TUN interface"),
1523 mlen = ntohs (message->size);
1524 if ( (ntohs (message->type) != GNUNET_MESSAGE_TYPE_VPN_HELPER) ||
1525 (mlen < sizeof (struct GNUNET_MessageHeader) + sizeof (struct GNUNET_TUN_Layer2PacketHeader)) )
1530 tun = (const struct GNUNET_TUN_Layer2PacketHeader *) &message[1];
1531 mlen -= (sizeof (struct GNUNET_MessageHeader) + sizeof (struct GNUNET_TUN_Layer2PacketHeader));
1532 switch (ntohs (tun->proto))
1536 const struct GNUNET_TUN_IPv6Header *pkt6;
1538 if (mlen < sizeof (struct GNUNET_TUN_IPv6Header))
1544 pkt6 = (const struct GNUNET_TUN_IPv6Header *) &tun[1];
1545 get_destination_key_from_ip (AF_INET6,
1546 &pkt6->destination_address,
1548 de = GNUNET_CONTAINER_multihashmap_get (destination_map, &key);
1551 char buf[INET6_ADDRSTRLEN];
1553 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1554 _("Packet received for unmapped destination `%s' (dropping it)\n"),
1555 inet_ntop (AF_INET6,
1556 &pkt6->destination_address,
1564 &pkt6->source_address,
1565 &pkt6->destination_address,
1567 mlen - sizeof (struct GNUNET_TUN_IPv6Header));
1572 struct GNUNET_TUN_IPv4Header *pkt4;
1574 if (mlen < sizeof (struct GNUNET_TUN_IPv4Header))
1580 pkt4 = (struct GNUNET_TUN_IPv4Header *) &tun[1];
1581 get_destination_key_from_ip (AF_INET,
1582 &pkt4->destination_address,
1584 de = GNUNET_CONTAINER_multihashmap_get (destination_map, &key);
1587 char buf[INET_ADDRSTRLEN];
1589 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1590 _("Packet received for unmapped destination `%s' (dropping it)\n"),
1592 &pkt4->destination_address,
1597 if (pkt4->header_length * 4 != sizeof (struct GNUNET_TUN_IPv4Header))
1599 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1600 _("Received IPv4 packet with options (dropping it)\n"));
1606 &pkt4->source_address,
1607 &pkt4->destination_address,
1609 mlen - sizeof (struct GNUNET_TUN_IPv4Header));
1613 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1614 _("Received packet of unknown protocol %d from TUN (dropping it)\n"),
1615 (unsigned int) ntohs (tun->proto));
1623 * Synthesize a plausible ICMP payload for an ICMP error
1624 * response on the given tunnel.
1626 * @param ts tunnel information
1627 * @param ipp IPv4 header to fill in (ICMP payload)
1628 * @param udp "UDP" header to fill in (ICMP payload); might actually
1629 * also be the first 8 bytes of the TCP header
1632 make_up_icmpv4_payload (struct TunnelState *ts,
1633 struct GNUNET_TUN_IPv4Header *ipp,
1634 struct GNUNET_TUN_UdpHeader *udp)
1636 GNUNET_TUN_initialize_ipv4_header (ipp,
1638 sizeof (struct GNUNET_TUN_TcpHeader),
1640 &ts->destination_ip.v4);
1641 udp->source_port = htons (ts->source_port);
1642 udp->destination_port = htons (ts->destination_port);
1643 udp->len = htons (0);
1644 udp->crc = htons (0);
1649 * Synthesize a plausible ICMP payload for an ICMP error
1650 * response on the given tunnel.
1652 * @param ts tunnel information
1653 * @param ipp IPv6 header to fill in (ICMP payload)
1654 * @param udp "UDP" header to fill in (ICMP payload); might actually
1655 * also be the first 8 bytes of the TCP header
1658 make_up_icmpv6_payload (struct TunnelState *ts,
1659 struct GNUNET_TUN_IPv6Header *ipp,
1660 struct GNUNET_TUN_UdpHeader *udp)
1662 GNUNET_TUN_initialize_ipv6_header (ipp,
1664 sizeof (struct GNUNET_TUN_TcpHeader),
1666 &ts->destination_ip.v6);
1667 udp->source_port = htons (ts->source_port);
1668 udp->destination_port = htons (ts->destination_port);
1669 udp->len = htons (0);
1670 udp->crc = htons (0);
1675 * We got an ICMP packet back from the MESH tunnel. Pass it on to the
1676 * local virtual interface via the helper.
1678 * @param cls closure, NULL
1679 * @param tunnel connection to the other end
1680 * @param tunnel_ctx pointer to our 'struct TunnelState *'
1681 * @param message the actual message
1682 * @return #GNUNET_OK to keep the connection open,
1683 * #GNUNET_SYSERR to close it (signal serious error)
1686 receive_icmp_back (void *cls GNUNET_UNUSED, struct GNUNET_MESH_Tunnel *tunnel,
1688 const struct GNUNET_MessageHeader *message)
1690 struct TunnelState *ts = *tunnel_ctx;
1691 const struct GNUNET_EXIT_IcmpToVPNMessage *i2v;
1694 GNUNET_STATISTICS_update (stats,
1695 gettext_noop ("# ICMP packets received from mesh"),
1697 mlen = ntohs (message->size);
1698 if (mlen < sizeof (struct GNUNET_EXIT_IcmpToVPNMessage))
1700 GNUNET_break_op (0);
1701 return GNUNET_SYSERR;
1703 if (NULL == ts->heap_node)
1705 GNUNET_break_op (0);
1706 return GNUNET_SYSERR;
1708 if (AF_UNSPEC == ts->af)
1710 GNUNET_break_op (0);
1711 return GNUNET_SYSERR;
1713 i2v = (const struct GNUNET_EXIT_IcmpToVPNMessage *) message;
1714 mlen -= sizeof (struct GNUNET_EXIT_IcmpToVPNMessage);
1716 char sbuf[INET6_ADDRSTRLEN];
1717 char dbuf[INET6_ADDRSTRLEN];
1719 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1720 "Received ICMP packet from mesh, sending %u bytes from %s -> %s via TUN\n",
1721 (unsigned int) mlen,
1722 inet_ntop (ts->af, &ts->destination_ip, sbuf, sizeof (sbuf)),
1723 inet_ntop (ts->af, &ts->source_ip, dbuf, sizeof (dbuf)));
1729 size_t size = sizeof (struct GNUNET_TUN_IPv4Header)
1730 + sizeof (struct GNUNET_TUN_IcmpHeader)
1731 + sizeof (struct GNUNET_MessageHeader) +
1732 sizeof (struct GNUNET_TUN_Layer2PacketHeader) +
1735 /* reserve some extra space in case we have an ICMP type here where
1736 we will need to make up the payload ourselves */
1737 char buf[size + sizeof (struct GNUNET_TUN_IPv4Header) + 8] GNUNET_ALIGN;
1738 struct GNUNET_MessageHeader *msg = (struct GNUNET_MessageHeader *) buf;
1739 struct GNUNET_TUN_Layer2PacketHeader *tun = (struct GNUNET_TUN_Layer2PacketHeader*) &msg[1];
1740 struct GNUNET_TUN_IPv4Header *ipv4 = (struct GNUNET_TUN_IPv4Header *) &tun[1];
1741 struct GNUNET_TUN_IcmpHeader *icmp = (struct GNUNET_TUN_IcmpHeader *) &ipv4[1];
1742 msg->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
1743 tun->flags = htons (0);
1744 tun->proto = htons (ETH_P_IPV4);
1745 GNUNET_TUN_initialize_ipv4_header (ipv4,
1747 sizeof (struct GNUNET_TUN_IcmpHeader) + mlen,
1748 &ts->destination_ip.v4,
1750 *icmp = i2v->icmp_header;
1754 /* For some ICMP types, we need to adjust (make up) the payload here.
1755 Also, depending on the AF used on the other side, we have to
1756 do ICMP PT (translate ICMP types) */
1757 switch (ntohl (i2v->af))
1762 case GNUNET_TUN_ICMPTYPE_ECHO_REPLY:
1763 case GNUNET_TUN_ICMPTYPE_ECHO_REQUEST:
1765 case GNUNET_TUN_ICMPTYPE_DESTINATION_UNREACHABLE:
1766 case GNUNET_TUN_ICMPTYPE_SOURCE_QUENCH:
1767 case GNUNET_TUN_ICMPTYPE_TIME_EXCEEDED:
1769 struct GNUNET_TUN_IPv4Header *ipp = (struct GNUNET_TUN_IPv4Header *) &icmp[1];
1770 struct GNUNET_TUN_UdpHeader *udp = (struct GNUNET_TUN_UdpHeader *) &ipp[1];
1774 /* sender did not strip ICMP payload? */
1775 GNUNET_break_op (0);
1776 return GNUNET_SYSERR;
1778 size += sizeof (struct GNUNET_TUN_IPv4Header) + 8;
1779 GNUNET_assert (8 == sizeof (struct GNUNET_TUN_UdpHeader));
1780 make_up_icmpv4_payload (ts, ipp, udp);
1784 GNUNET_break_op (0);
1785 GNUNET_STATISTICS_update (stats,
1786 gettext_noop ("# ICMPv4 packets dropped (type not allowed)"),
1788 return GNUNET_SYSERR;
1793 /* ICMP PT 6-to-4 and possibly making up payloads */
1796 case GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE:
1797 icmp->type = GNUNET_TUN_ICMPTYPE_DESTINATION_UNREACHABLE;
1799 struct GNUNET_TUN_IPv4Header *ipp = (struct GNUNET_TUN_IPv4Header *) &icmp[1];
1800 struct GNUNET_TUN_UdpHeader *udp = (struct GNUNET_TUN_UdpHeader *) &ipp[1];
1804 /* sender did not strip ICMP payload? */
1805 GNUNET_break_op (0);
1806 return GNUNET_SYSERR;
1808 size += sizeof (struct GNUNET_TUN_IPv4Header) + 8;
1809 GNUNET_assert (8 == sizeof (struct GNUNET_TUN_UdpHeader));
1810 make_up_icmpv4_payload (ts, ipp, udp);
1813 case GNUNET_TUN_ICMPTYPE6_TIME_EXCEEDED:
1814 icmp->type = GNUNET_TUN_ICMPTYPE_TIME_EXCEEDED;
1816 struct GNUNET_TUN_IPv4Header *ipp = (struct GNUNET_TUN_IPv4Header *) &icmp[1];
1817 struct GNUNET_TUN_UdpHeader *udp = (struct GNUNET_TUN_UdpHeader *) &ipp[1];
1821 /* sender did not strip ICMP payload? */
1822 GNUNET_break_op (0);
1823 return GNUNET_SYSERR;
1825 size += sizeof (struct GNUNET_TUN_IPv4Header) + 8;
1826 GNUNET_assert (8 == sizeof (struct GNUNET_TUN_UdpHeader));
1827 make_up_icmpv4_payload (ts, ipp, udp);
1830 case GNUNET_TUN_ICMPTYPE6_PACKET_TOO_BIG:
1831 case GNUNET_TUN_ICMPTYPE6_PARAMETER_PROBLEM:
1832 GNUNET_STATISTICS_update (stats,
1833 gettext_noop ("# ICMPv6 packets dropped (impossible PT to v4)"),
1836 case GNUNET_TUN_ICMPTYPE6_ECHO_REQUEST:
1837 icmp->type = GNUNET_TUN_ICMPTYPE_ECHO_REQUEST;
1839 case GNUNET_TUN_ICMPTYPE6_ECHO_REPLY:
1840 icmp->type = GNUNET_TUN_ICMPTYPE_ECHO_REPLY;
1843 GNUNET_break_op (0);
1844 GNUNET_STATISTICS_update (stats,
1845 gettext_noop ("# ICMPv6 packets dropped (type not allowed)"),
1847 return GNUNET_SYSERR;
1852 GNUNET_break_op (0);
1853 return GNUNET_SYSERR;
1855 msg->size = htons (size);
1856 GNUNET_TUN_calculate_icmp_checksum (icmp,
1859 (void) GNUNET_HELPER_send (helper_handle,
1868 size_t size = sizeof (struct GNUNET_TUN_IPv6Header)
1869 + sizeof (struct GNUNET_TUN_IcmpHeader)
1870 + sizeof (struct GNUNET_MessageHeader) +
1871 sizeof (struct GNUNET_TUN_Layer2PacketHeader) +
1874 char buf[size + sizeof (struct GNUNET_TUN_IPv6Header) + 8] GNUNET_ALIGN;
1875 struct GNUNET_MessageHeader *msg = (struct GNUNET_MessageHeader *) buf;
1876 struct GNUNET_TUN_Layer2PacketHeader *tun = (struct GNUNET_TUN_Layer2PacketHeader*) &msg[1];
1877 struct GNUNET_TUN_IPv6Header *ipv6 = (struct GNUNET_TUN_IPv6Header *) &tun[1];
1878 struct GNUNET_TUN_IcmpHeader *icmp = (struct GNUNET_TUN_IcmpHeader *) &ipv6[1];
1879 msg->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
1880 tun->flags = htons (0);
1881 tun->proto = htons (ETH_P_IPV6);
1882 GNUNET_TUN_initialize_ipv6_header (ipv6,
1884 sizeof (struct GNUNET_TUN_IcmpHeader) + mlen,
1885 &ts->destination_ip.v6,
1887 *icmp = i2v->icmp_header;
1892 /* For some ICMP types, we need to adjust (make up) the payload here.
1893 Also, depending on the AF used on the other side, we have to
1894 do ICMP PT (translate ICMP types) */
1895 switch (ntohl (i2v->af))
1898 /* ICMP PT 4-to-6 and possibly making up payloads */
1901 case GNUNET_TUN_ICMPTYPE_ECHO_REPLY:
1902 icmp->type = GNUNET_TUN_ICMPTYPE6_ECHO_REPLY;
1904 case GNUNET_TUN_ICMPTYPE_ECHO_REQUEST:
1905 icmp->type = GNUNET_TUN_ICMPTYPE6_ECHO_REQUEST;
1907 case GNUNET_TUN_ICMPTYPE_DESTINATION_UNREACHABLE:
1908 icmp->type = GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE;
1910 struct GNUNET_TUN_IPv6Header *ipp = (struct GNUNET_TUN_IPv6Header *) &icmp[1];
1911 struct GNUNET_TUN_UdpHeader *udp = (struct GNUNET_TUN_UdpHeader *) &ipp[1];
1915 /* sender did not strip ICMP payload? */
1916 GNUNET_break_op (0);
1917 return GNUNET_SYSERR;
1919 size += sizeof (struct GNUNET_TUN_IPv6Header) + 8;
1920 GNUNET_assert (8 == sizeof (struct GNUNET_TUN_UdpHeader));
1921 make_up_icmpv6_payload (ts, ipp, udp);
1924 case GNUNET_TUN_ICMPTYPE_TIME_EXCEEDED:
1925 icmp->type = GNUNET_TUN_ICMPTYPE6_TIME_EXCEEDED;
1927 struct GNUNET_TUN_IPv6Header *ipp = (struct GNUNET_TUN_IPv6Header *) &icmp[1];
1928 struct GNUNET_TUN_UdpHeader *udp = (struct GNUNET_TUN_UdpHeader *) &ipp[1];
1932 /* sender did not strip ICMP payload? */
1933 GNUNET_break_op (0);
1934 return GNUNET_SYSERR;
1936 size += sizeof (struct GNUNET_TUN_IPv6Header) + 8;
1937 GNUNET_assert (8 == sizeof (struct GNUNET_TUN_UdpHeader));
1938 make_up_icmpv6_payload (ts, ipp, udp);
1941 case GNUNET_TUN_ICMPTYPE_SOURCE_QUENCH:
1942 GNUNET_STATISTICS_update (stats,
1943 gettext_noop ("# ICMPv4 packets dropped (impossible PT to v6)"),
1947 GNUNET_break_op (0);
1948 GNUNET_STATISTICS_update (stats,
1949 gettext_noop ("# ICMPv4 packets dropped (type not allowed)"),
1951 return GNUNET_SYSERR;
1958 case GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE:
1959 case GNUNET_TUN_ICMPTYPE6_TIME_EXCEEDED:
1960 case GNUNET_TUN_ICMPTYPE6_PACKET_TOO_BIG:
1961 case GNUNET_TUN_ICMPTYPE6_PARAMETER_PROBLEM:
1963 struct GNUNET_TUN_IPv6Header *ipp = (struct GNUNET_TUN_IPv6Header *) &icmp[1];
1964 struct GNUNET_TUN_UdpHeader *udp = (struct GNUNET_TUN_UdpHeader *) &ipp[1];
1968 /* sender did not strip ICMP payload? */
1969 GNUNET_break_op (0);
1970 return GNUNET_SYSERR;
1972 size += sizeof (struct GNUNET_TUN_IPv6Header) + 8;
1973 GNUNET_assert (8 == sizeof (struct GNUNET_TUN_UdpHeader));
1974 make_up_icmpv6_payload (ts, ipp, udp);
1977 case GNUNET_TUN_ICMPTYPE6_ECHO_REQUEST:
1980 GNUNET_break_op (0);
1981 GNUNET_STATISTICS_update (stats,
1982 gettext_noop ("# ICMPv6 packets dropped (type not allowed)"),
1984 return GNUNET_SYSERR;
1989 GNUNET_break_op (0);
1990 return GNUNET_SYSERR;
1992 msg->size = htons (size);
1993 GNUNET_TUN_calculate_icmp_checksum (icmp,
1995 (void) GNUNET_HELPER_send (helper_handle,
2005 GNUNET_CONTAINER_heap_update_cost (tunnel_heap,
2007 GNUNET_TIME_absolute_get ().abs_value_us);
2013 * We got a UDP packet back from the MESH tunnel. Pass it on to the
2014 * local virtual interface via the helper.
2016 * @param cls closure, NULL
2017 * @param tunnel connection to the other end
2018 * @param tunnel_ctx pointer to our 'struct TunnelState *'
2019 * @param message the actual message
2020 * @return #GNUNET_OK to keep the connection open,
2021 * #GNUNET_SYSERR to close it (signal serious error)
2024 receive_udp_back (void *cls GNUNET_UNUSED, struct GNUNET_MESH_Tunnel *tunnel,
2026 const struct GNUNET_MessageHeader *message)
2028 struct TunnelState *ts = *tunnel_ctx;
2029 const struct GNUNET_EXIT_UdpReplyMessage *reply;
2032 GNUNET_STATISTICS_update (stats,
2033 gettext_noop ("# UDP packets received from mesh"),
2035 mlen = ntohs (message->size);
2036 if (mlen < sizeof (struct GNUNET_EXIT_UdpReplyMessage))
2038 GNUNET_break_op (0);
2039 return GNUNET_SYSERR;
2041 if (NULL == ts->heap_node)
2043 GNUNET_break_op (0);
2044 return GNUNET_SYSERR;
2046 if (AF_UNSPEC == ts->af)
2048 GNUNET_break_op (0);
2049 return GNUNET_SYSERR;
2051 reply = (const struct GNUNET_EXIT_UdpReplyMessage *) message;
2052 mlen -= sizeof (struct GNUNET_EXIT_UdpReplyMessage);
2054 char sbuf[INET6_ADDRSTRLEN];
2055 char dbuf[INET6_ADDRSTRLEN];
2057 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2058 "Received UDP reply from mesh, sending %u bytes from %s:%u -> %s:%u via TUN\n",
2059 (unsigned int) mlen,
2060 inet_ntop (ts->af, &ts->destination_ip, sbuf, sizeof (sbuf)),
2061 ts->destination_port,
2062 inet_ntop (ts->af, &ts->source_ip, dbuf, sizeof (dbuf)),
2069 size_t size = sizeof (struct GNUNET_TUN_IPv4Header)
2070 + sizeof (struct GNUNET_TUN_UdpHeader)
2071 + sizeof (struct GNUNET_MessageHeader) +
2072 sizeof (struct GNUNET_TUN_Layer2PacketHeader) +
2075 char buf[size] GNUNET_ALIGN;
2076 struct GNUNET_MessageHeader *msg = (struct GNUNET_MessageHeader *) buf;
2077 struct GNUNET_TUN_Layer2PacketHeader *tun = (struct GNUNET_TUN_Layer2PacketHeader*) &msg[1];
2078 struct GNUNET_TUN_IPv4Header *ipv4 = (struct GNUNET_TUN_IPv4Header *) &tun[1];
2079 struct GNUNET_TUN_UdpHeader *udp = (struct GNUNET_TUN_UdpHeader *) &ipv4[1];
2080 msg->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
2081 msg->size = htons (size);
2082 tun->flags = htons (0);
2083 tun->proto = htons (ETH_P_IPV4);
2084 GNUNET_TUN_initialize_ipv4_header (ipv4,
2086 sizeof (struct GNUNET_TUN_UdpHeader) + mlen,
2087 &ts->destination_ip.v4,
2089 if (0 == ntohs (reply->source_port))
2090 udp->source_port = htons (ts->destination_port);
2092 udp->source_port = reply->source_port;
2093 if (0 == ntohs (reply->destination_port))
2094 udp->destination_port = htons (ts->source_port);
2096 udp->destination_port = reply->destination_port;
2097 udp->len = htons (mlen + sizeof (struct GNUNET_TUN_UdpHeader));
2098 GNUNET_TUN_calculate_udp4_checksum (ipv4,
2105 (void) GNUNET_HELPER_send (helper_handle,
2114 size_t size = sizeof (struct GNUNET_TUN_IPv6Header)
2115 + sizeof (struct GNUNET_TUN_UdpHeader)
2116 + sizeof (struct GNUNET_MessageHeader) +
2117 sizeof (struct GNUNET_TUN_Layer2PacketHeader) +
2120 char buf[size] GNUNET_ALIGN;
2121 struct GNUNET_MessageHeader *msg = (struct GNUNET_MessageHeader *) buf;
2122 struct GNUNET_TUN_Layer2PacketHeader *tun = (struct GNUNET_TUN_Layer2PacketHeader*) &msg[1];
2123 struct GNUNET_TUN_IPv6Header *ipv6 = (struct GNUNET_TUN_IPv6Header *) &tun[1];
2124 struct GNUNET_TUN_UdpHeader *udp = (struct GNUNET_TUN_UdpHeader *) &ipv6[1];
2125 msg->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
2126 msg->size = htons (size);
2127 tun->flags = htons (0);
2128 tun->proto = htons (ETH_P_IPV6);
2129 GNUNET_TUN_initialize_ipv6_header (ipv6,
2131 sizeof (struct GNUNET_TUN_UdpHeader) + mlen,
2132 &ts->destination_ip.v6,
2134 if (0 == ntohs (reply->source_port))
2135 udp->source_port = htons (ts->destination_port);
2137 udp->source_port = reply->source_port;
2138 if (0 == ntohs (reply->destination_port))
2139 udp->destination_port = htons (ts->source_port);
2141 udp->destination_port = reply->destination_port;
2142 udp->len = htons (mlen + sizeof (struct GNUNET_TUN_UdpHeader));
2143 GNUNET_TUN_calculate_udp6_checksum (ipv6,
2149 (void) GNUNET_HELPER_send (helper_handle,
2159 GNUNET_CONTAINER_heap_update_cost (tunnel_heap,
2161 GNUNET_TIME_absolute_get ().abs_value_us);
2167 * We got a TCP packet back from the MESH tunnel. Pass it on to the
2168 * local virtual interface via the helper.
2170 * @param cls closure, NULL
2171 * @param tunnel connection to the other end
2172 * @param tunnel_ctx pointer to our `struct TunnelState *`
2173 * @param message the actual message
2174 * @return #GNUNET_OK to keep the connection open,
2175 * #GNUNET_SYSERR to close it (signal serious error)
2178 receive_tcp_back (void *cls GNUNET_UNUSED, struct GNUNET_MESH_Tunnel *tunnel,
2180 const struct GNUNET_MessageHeader *message)
2182 struct TunnelState *ts = *tunnel_ctx;
2183 const struct GNUNET_EXIT_TcpDataMessage *data;
2186 GNUNET_STATISTICS_update (stats,
2187 gettext_noop ("# TCP packets received from mesh"),
2189 mlen = ntohs (message->size);
2190 if (mlen < sizeof (struct GNUNET_EXIT_TcpDataMessage))
2192 GNUNET_break_op (0);
2193 return GNUNET_SYSERR;
2195 if (NULL == ts->heap_node)
2197 GNUNET_break_op (0);
2198 return GNUNET_SYSERR;
2200 data = (const struct GNUNET_EXIT_TcpDataMessage *) message;
2201 mlen -= sizeof (struct GNUNET_EXIT_TcpDataMessage);
2203 char sbuf[INET6_ADDRSTRLEN];
2204 char dbuf[INET6_ADDRSTRLEN];
2206 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2207 "Received TCP reply from mesh, sending %u bytes from %s:%u -> %s:%u via TUN\n",
2208 (unsigned int) mlen,
2209 inet_ntop (ts->af, &ts->destination_ip, sbuf, sizeof (sbuf)),
2210 ts->destination_port,
2211 inet_ntop (ts->af, &ts->source_ip, dbuf, sizeof (dbuf)),
2214 if (data->tcp_header.off * 4 < sizeof (struct GNUNET_TUN_TcpHeader))
2216 GNUNET_break_op (0);
2217 return GNUNET_SYSERR;
2223 size_t size = sizeof (struct GNUNET_TUN_IPv4Header)
2224 + sizeof (struct GNUNET_TUN_TcpHeader)
2225 + sizeof (struct GNUNET_MessageHeader) +
2226 sizeof (struct GNUNET_TUN_Layer2PacketHeader) +
2229 char buf[size] GNUNET_ALIGN;
2230 struct GNUNET_MessageHeader *msg = (struct GNUNET_MessageHeader *) buf;
2231 struct GNUNET_TUN_Layer2PacketHeader *tun = (struct GNUNET_TUN_Layer2PacketHeader*) &msg[1];
2232 struct GNUNET_TUN_IPv4Header *ipv4 = (struct GNUNET_TUN_IPv4Header *) &tun[1];
2233 struct GNUNET_TUN_TcpHeader *tcp = (struct GNUNET_TUN_TcpHeader *) &ipv4[1];
2234 msg->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
2235 msg->size = htons (size);
2236 tun->flags = htons (0);
2237 tun->proto = htons (ETH_P_IPV4);
2238 GNUNET_TUN_initialize_ipv4_header (ipv4,
2240 sizeof (struct GNUNET_TUN_TcpHeader) + mlen,
2241 &ts->destination_ip.v4,
2243 *tcp = data->tcp_header;
2244 tcp->source_port = htons (ts->destination_port);
2245 tcp->destination_port = htons (ts->source_port);
2246 GNUNET_TUN_calculate_tcp4_checksum (ipv4,
2253 (void) GNUNET_HELPER_send (helper_handle,
2262 size_t size = sizeof (struct GNUNET_TUN_IPv6Header)
2263 + sizeof (struct GNUNET_TUN_TcpHeader)
2264 + sizeof (struct GNUNET_MessageHeader) +
2265 sizeof (struct GNUNET_TUN_Layer2PacketHeader) +
2268 char buf[size] GNUNET_ALIGN;
2269 struct GNUNET_MessageHeader *msg = (struct GNUNET_MessageHeader *) buf;
2270 struct GNUNET_TUN_Layer2PacketHeader *tun = (struct GNUNET_TUN_Layer2PacketHeader*) &msg[1];
2271 struct GNUNET_TUN_IPv6Header *ipv6 = (struct GNUNET_TUN_IPv6Header *) &tun[1];
2272 struct GNUNET_TUN_TcpHeader *tcp = (struct GNUNET_TUN_TcpHeader *) &ipv6[1];
2273 msg->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
2274 msg->size = htons (size);
2275 tun->flags = htons (0);
2276 tun->proto = htons (ETH_P_IPV6);
2277 GNUNET_TUN_initialize_ipv6_header (ipv6,
2279 sizeof (struct GNUNET_TUN_TcpHeader) + mlen,
2280 &ts->destination_ip.v6,
2282 *tcp = data->tcp_header;
2283 tcp->source_port = htons (ts->destination_port);
2284 tcp->destination_port = htons (ts->source_port);
2285 GNUNET_TUN_calculate_tcp6_checksum (ipv6,
2292 (void) GNUNET_HELPER_send (helper_handle,
2300 GNUNET_CONTAINER_heap_update_cost (tunnel_heap,
2302 GNUNET_TIME_absolute_get ().abs_value_us);
2308 * Allocate an IPv4 address from the range of the tunnel
2309 * for a new redirection.
2311 * @param v4 where to store the address
2312 * @return #GNUNET_OK on success,
2313 * #GNUNET_SYSERR on error
2316 allocate_v4_address (struct in_addr *v4)
2318 const char *ipv4addr = vpn_argv[4];
2319 const char *ipv4mask = vpn_argv[5];
2320 struct in_addr addr;
2321 struct in_addr mask;
2323 struct GNUNET_HashCode key;
2326 GNUNET_assert (1 == inet_pton (AF_INET, ipv4addr, &addr));
2327 GNUNET_assert (1 == inet_pton (AF_INET, ipv4mask, &mask));
2328 /* Given 192.168.0.1/255.255.0.0, we want a mask
2329 of '192.168.255.255', thus: */
2330 mask.s_addr = addr.s_addr | ~mask.s_addr;
2337 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
2338 _("Failed to find unallocated IPv4 address in VPN's range\n"));
2339 return GNUNET_SYSERR;
2341 /* Pick random IPv4 address within the subnet, except 'addr' or 'mask' itself */
2342 rnd.s_addr = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
2344 v4->s_addr = (addr.s_addr | rnd.s_addr) & mask.s_addr;
2345 get_destination_key_from_ip (AF_INET,
2349 while ( (GNUNET_YES ==
2350 GNUNET_CONTAINER_multihashmap_contains (destination_map,
2352 (v4->s_addr == addr.s_addr) ||
2353 (v4->s_addr == mask.s_addr) );
2359 * Allocate an IPv6 address from the range of the tunnel
2360 * for a new redirection.
2362 * @param v6 where to store the address
2363 * @return #GNUNET_OK on success,
2364 * #GNUNET_SYSERR on error
2367 allocate_v6_address (struct in6_addr *v6)
2369 const char *ipv6addr = vpn_argv[2];
2370 struct in6_addr addr;
2371 struct in6_addr mask;
2372 struct in6_addr rnd;
2374 struct GNUNET_HashCode key;
2377 GNUNET_assert (1 == inet_pton (AF_INET6, ipv6addr, &addr));
2378 GNUNET_assert (ipv6prefix < 128);
2379 /* Given ABCD::/96, we want a mask of 'ABCD::FFFF:FFFF,
2382 for (i=127;i>=ipv6prefix;i--)
2383 mask.s6_addr[i / 8] |= (1 << (i % 8));
2385 /* Pick random IPv6 address within the subnet, except 'addr' or 'mask' itself */
2392 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
2393 _("Failed to find unallocated IPv6 address in VPN's range\n"));
2394 return GNUNET_SYSERR;
2399 rnd.s6_addr[i] = (unsigned char) GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
2402 = (addr.s6_addr[i] | rnd.s6_addr[i]) & mask.s6_addr[i];
2404 get_destination_key_from_ip (AF_INET6,
2408 while ( (GNUNET_YES ==
2409 GNUNET_CONTAINER_multihashmap_contains (destination_map,
2413 sizeof (struct in6_addr))) ||
2416 sizeof (struct in6_addr))) );
2422 * Free resources occupied by a destination entry.
2424 * @param de entry to free
2427 free_destination_entry (struct DestinationEntry *de)
2429 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2430 "Cleaning up destination entry\n");
2431 GNUNET_STATISTICS_update (stats,
2432 gettext_noop ("# Active destinations"),
2436 free_tunnel_state (de->ts);
2437 GNUNET_assert (NULL == de->ts);
2439 if (NULL != de->heap_node)
2441 GNUNET_CONTAINER_heap_remove_node (de->heap_node);
2442 de->heap_node = NULL;
2443 GNUNET_assert (GNUNET_YES ==
2444 GNUNET_CONTAINER_multihashmap_remove (destination_map,
2453 * We have too many active destinations. Clean up the oldest destination.
2455 * @param except destination that must NOT be cleaned up, even if it is the oldest
2458 expire_destination (struct DestinationEntry *except)
2460 struct DestinationEntry *de;
2462 de = GNUNET_CONTAINER_heap_peek (destination_heap);
2463 GNUNET_assert (NULL != de);
2465 return; /* can't do this */
2466 free_destination_entry (de);
2471 * Allocate an IP address for the response.
2473 * @param result_af desired address family; set to the actual
2474 * address family; can initially be AF_UNSPEC if there
2475 * is no preference; will be set to AF_UNSPEC if the
2477 * @param addr set to either v4 or v6 depending on which
2478 * storage location was used; set to NULL if allocation failed
2479 * @param v4 storage space for an IPv4 address
2480 * @param v6 storage space for an IPv6 address
2481 * @return #GNUNET_OK normally, #GNUNET_SYSERR if `* result_af` was
2482 * an unsupported address family (not AF_INET, AF_INET6 or AF_UNSPEC)
2485 allocate_response_ip (int *result_af,
2488 struct in6_addr *v6)
2495 allocate_v4_address (v4))
2496 *result_af = AF_UNSPEC;
2502 allocate_v6_address (v6))
2503 *result_af = AF_UNSPEC;
2509 allocate_v4_address (v4))
2512 *result_af = AF_INET;
2514 else if (GNUNET_OK ==
2515 allocate_v6_address (v6))
2518 *result_af = AF_INET6;
2523 return GNUNET_SYSERR;
2530 * A client asks us to setup a redirection via some exit node to a
2531 * particular IP. Setup the redirection and give the client the
2535 * @param client requesting client
2536 * @param message redirection request (a `struct RedirectToIpRequestMessage`)
2539 service_redirect_to_ip (void *cls,
2540 struct GNUNET_SERVER_Client *client,
2541 const struct GNUNET_MessageHeader *message)
2545 const struct RedirectToIpRequestMessage *msg;
2551 struct DestinationEntry *de;
2552 struct GNUNET_HashCode key;
2553 struct TunnelState *ts;
2555 /* validate and parse request */
2556 mlen = ntohs (message->size);
2557 if (mlen < sizeof (struct RedirectToIpRequestMessage))
2560 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2563 alen = mlen - sizeof (struct RedirectToIpRequestMessage);
2564 msg = (const struct RedirectToIpRequestMessage *) message;
2565 addr_af = (int) htonl (msg->addr_af);
2569 if (alen != sizeof (struct in_addr))
2572 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2577 if (alen != sizeof (struct in6_addr))
2580 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2586 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2590 /* allocate response IP */
2591 result_af = (int) htonl (msg->result_af);
2592 if (GNUNET_OK != allocate_response_ip (&result_af,
2596 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2599 /* send reply with our IP address */
2600 send_client_reply (client,
2604 if (result_af == AF_UNSPEC)
2606 /* failure, we're done */
2607 GNUNET_SERVER_receive_done (client, GNUNET_OK);
2612 char sbuf[INET6_ADDRSTRLEN];
2613 char dbuf[INET6_ADDRSTRLEN];
2615 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2616 "Allocated address %s for redirection via exit to %s\n",
2617 inet_ntop (result_af, addr, sbuf, sizeof (sbuf)),
2619 &msg[1], dbuf, sizeof (dbuf)));
2622 /* setup destination record */
2623 de = GNUNET_new (struct DestinationEntry);
2624 de->is_service = GNUNET_NO;
2625 de->details.exit_destination.af = addr_af;
2626 memcpy (&de->details.exit_destination.ip,
2629 get_destination_key_from_ip (result_af,
2633 GNUNET_assert (GNUNET_OK ==
2634 GNUNET_CONTAINER_multihashmap_put (destination_map,
2637 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE));
2638 de->heap_node = GNUNET_CONTAINER_heap_insert (destination_heap,
2640 GNUNET_TIME_absolute_ntoh (msg->expiration_time).abs_value_us);
2641 GNUNET_STATISTICS_update (stats,
2642 gettext_noop ("# Active destinations"),
2644 while (GNUNET_CONTAINER_multihashmap_size (destination_map) > max_destination_mappings)
2645 expire_destination (de);
2647 /* setup tunnel to destination */
2648 ts = create_tunnel_to_destination (de,
2654 ts->destination_ip.v4 = v4;
2657 ts->destination_ip.v6 = v6;
2663 GNUNET_SERVER_receive_done (client, GNUNET_OK);
2668 * A client asks us to setup a redirection to a particular peer
2669 * offering a service. Setup the redirection and give the client the
2673 * @param client requesting client
2674 * @param message redirection request (a `struct RedirectToPeerRequestMessage`)
2677 service_redirect_to_service (void *cls GNUNET_UNUSED, struct GNUNET_SERVER_Client *client,
2678 const struct GNUNET_MessageHeader *message)
2680 const struct RedirectToServiceRequestMessage *msg;
2685 struct DestinationEntry *de;
2686 struct GNUNET_HashCode key;
2687 struct TunnelState *ts;
2690 msg = (const struct RedirectToServiceRequestMessage *) message;
2692 /* allocate response IP */
2693 result_af = (int) htonl (msg->result_af);
2694 if (GNUNET_OK != allocate_response_ip (&result_af,
2698 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2701 send_client_reply (client,
2705 if (result_af == AF_UNSPEC)
2707 /* failure, we're done */
2708 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2709 _("Failed to allocate IP address for new destination\n"));
2710 GNUNET_SERVER_receive_done (client, GNUNET_OK);
2715 char sbuf[INET6_ADDRSTRLEN];
2717 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2718 "Allocated address %s for redirection to service %s on peer %s\n",
2719 inet_ntop (result_af, addr, sbuf, sizeof (sbuf)),
2720 GNUNET_h2s (&msg->service_descriptor),
2721 GNUNET_i2s (&msg->target));
2724 /* setup destination record */
2725 de = GNUNET_new (struct DestinationEntry);
2726 de->is_service = GNUNET_YES;
2727 de->details.service_destination.service_descriptor = msg->service_descriptor;
2728 de->details.service_destination.target = msg->target;
2729 get_destination_key_from_ip (result_af,
2733 GNUNET_assert (GNUNET_OK ==
2734 GNUNET_CONTAINER_multihashmap_put (destination_map,
2737 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE));
2738 de->heap_node = GNUNET_CONTAINER_heap_insert (destination_heap,
2740 GNUNET_TIME_absolute_ntoh (msg->expiration_time).abs_value_us);
2741 while (GNUNET_CONTAINER_multihashmap_size (destination_map) > max_destination_mappings)
2742 expire_destination (de);
2743 ts = create_tunnel_to_destination (de,
2749 ts->destination_ip.v4 = v4;
2752 ts->destination_ip.v6 = v6;
2758 GNUNET_SERVER_receive_done (client, GNUNET_OK);
2763 * Function called whenever a tunnel is destroyed. Should clean up
2764 * any associated state.
2766 * @param cls closure (set from #GNUNET_MESH_connect)
2767 * @param tunnel connection to the other end (henceforth invalid)
2768 * @param tunnel_ctx place where local state associated
2769 * with the tunnel is stored (our `struct TunnelState`)
2772 tunnel_cleaner (void *cls,
2773 const struct GNUNET_MESH_Tunnel *tunnel,
2776 struct TunnelState *ts = tunnel_ctx;
2778 ts->tunnel = NULL; /* we must not call GNUNET_MESH_tunnel_destroy() anymore */
2779 free_tunnel_state (ts);
2784 * Free memory occupied by an entry in the destination map.
2788 * @param value a `struct DestinationEntry *`
2789 * @return #GNUNET_OK (continue to iterate)
2792 cleanup_destination (void *cls,
2793 const struct GNUNET_HashCode *key,
2796 struct DestinationEntry *de = value;
2798 free_destination_entry (de);
2804 * Free memory occupied by an entry in the tunnel map.
2808 * @param value a `struct TunnelState *`
2809 * @return #GNUNET_OK (continue to iterate)
2812 cleanup_tunnel (void *cls,
2813 const struct GNUNET_HashCode *key,
2816 struct TunnelState *ts = value;
2818 free_tunnel_state (ts);
2824 * Function scheduled as very last function, cleans up after us
2831 const struct GNUNET_SCHEDULER_TaskContext *tc)
2835 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2836 "VPN is shutting down\n");
2837 if (NULL != destination_map)
2839 GNUNET_CONTAINER_multihashmap_iterate (destination_map,
2840 &cleanup_destination,
2842 GNUNET_CONTAINER_multihashmap_destroy (destination_map);
2843 destination_map = NULL;
2845 if (NULL != destination_heap)
2847 GNUNET_CONTAINER_heap_destroy (destination_heap);
2848 destination_heap = NULL;
2850 if (NULL != tunnel_map)
2852 GNUNET_CONTAINER_multihashmap_iterate (tunnel_map,
2855 GNUNET_CONTAINER_multihashmap_destroy (tunnel_map);
2858 if (NULL != tunnel_heap)
2860 GNUNET_CONTAINER_heap_destroy (tunnel_heap);
2863 if (NULL != mesh_handle)
2865 GNUNET_MESH_disconnect (mesh_handle);
2868 if (NULL != helper_handle)
2870 GNUNET_HELPER_stop (helper_handle, GNUNET_NO);
2871 helper_handle = NULL;
2875 GNUNET_SERVER_notification_context_destroy (nc);
2880 GNUNET_STATISTICS_destroy (stats, GNUNET_NO);
2884 GNUNET_free_non_null (vpn_argv[i]);
2889 * Main function that will be run by the scheduler.
2891 * @param cls closure
2892 * @param server the initialized server
2893 * @param cfg_ configuration
2897 struct GNUNET_SERVER_Handle *server,
2898 const struct GNUNET_CONFIGURATION_Handle *cfg_)
2900 static const struct GNUNET_SERVER_MessageHandler service_handlers[] = {
2901 /* callback, cls, type, size */
2902 { &service_redirect_to_ip, NULL, GNUNET_MESSAGE_TYPE_VPN_CLIENT_REDIRECT_TO_IP, 0},
2903 { &service_redirect_to_service, NULL,
2904 GNUNET_MESSAGE_TYPE_VPN_CLIENT_REDIRECT_TO_SERVICE,
2905 sizeof (struct RedirectToServiceRequestMessage) },
2908 static const struct GNUNET_MESH_MessageHandler mesh_handlers[] = {
2909 { &receive_udp_back, GNUNET_MESSAGE_TYPE_VPN_UDP_REPLY, 0},
2910 { &receive_tcp_back, GNUNET_MESSAGE_TYPE_VPN_TCP_DATA_TO_VPN, 0},
2911 { &receive_icmp_back, GNUNET_MESSAGE_TYPE_VPN_ICMP_TO_VPN, 0},
2923 binary = GNUNET_OS_get_libexec_binary_path ("gnunet-helper-vpn");
2926 GNUNET_OS_check_helper_binary (binary, GNUNET_YES, "-d gnunet-vpn - - 169.1.3.3.7 255.255.255.0")) //ipv4 only please!
2929 "`%s' is not SUID, refusing to run.\n",
2930 "gnunet-helper-vpn");
2931 GNUNET_free (binary);
2935 GNUNET_free (binary);
2937 stats = GNUNET_STATISTICS_create ("vpn", cfg);
2939 GNUNET_CONFIGURATION_get_value_number (cfg, "VPN", "MAX_MAPPING",
2940 &max_destination_mappings))
2941 max_destination_mappings = 200;
2943 GNUNET_CONFIGURATION_get_value_number (cfg, "VPN", "MAX_TUNNELS",
2944 &max_tunnel_mappings))
2945 max_tunnel_mappings = 200;
2947 destination_map = GNUNET_CONTAINER_multihashmap_create (max_destination_mappings * 2, GNUNET_NO);
2948 destination_heap = GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN);
2949 tunnel_map = GNUNET_CONTAINER_multihashmap_create (max_tunnel_mappings * 2, GNUNET_NO);
2950 tunnel_heap = GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN);
2953 vpn_argv[0] = GNUNET_strdup ("vpn-gnunet");
2954 if (GNUNET_SYSERR ==
2955 GNUNET_CONFIGURATION_get_value_string (cfg, "VPN", "IFNAME", &ifname))
2957 GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, "VPN", "IFNAME");
2958 GNUNET_SCHEDULER_shutdown ();
2961 vpn_argv[1] = ifname;
2962 if (GNUNET_OK == GNUNET_NETWORK_test_pf (PF_INET6))
2964 if ( (GNUNET_SYSERR ==
2965 GNUNET_CONFIGURATION_get_value_string (cfg, "VPN", "IPV6ADDR",
2967 (1 != inet_pton (AF_INET6, ipv6addr, &v6))) )
2969 GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, "VPN", "IPV6ADDR",
2970 _("Must specify valid IPv6 address"));
2971 GNUNET_SCHEDULER_shutdown ();
2974 vpn_argv[2] = ipv6addr;
2975 if (GNUNET_SYSERR ==
2976 GNUNET_CONFIGURATION_get_value_string (cfg, "VPN", "IPV6PREFIX",
2979 GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, "VPN", "IPV6PREFIX");
2980 GNUNET_SCHEDULER_shutdown ();
2983 vpn_argv[3] = ipv6prefix_s;
2985 GNUNET_CONFIGURATION_get_value_number (cfg, "VPN",
2988 (ipv6prefix >= 127) )
2990 GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, "VPN", "IPV4MASK",
2991 _("Must specify valid IPv6 mask"));
2992 GNUNET_SCHEDULER_shutdown ();
2998 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
2999 _("IPv6 support disabled as this system does not support IPv6\n"));
3000 vpn_argv[2] = GNUNET_strdup ("-");
3001 vpn_argv[3] = GNUNET_strdup ("-");
3003 if (GNUNET_OK == GNUNET_NETWORK_test_pf (PF_INET))
3005 if ( (GNUNET_SYSERR ==
3006 GNUNET_CONFIGURATION_get_value_string (cfg, "vpn", "IPV4ADDR",
3008 (1 != inet_pton (AF_INET, ipv4addr, &v4))) )
3010 GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, "VPN", "IPV4ADDR",
3011 _("Must specify valid IPv4 address"));
3012 GNUNET_SCHEDULER_shutdown ();
3015 vpn_argv[4] = ipv4addr;
3016 if ( (GNUNET_SYSERR ==
3017 GNUNET_CONFIGURATION_get_value_string (cfg, "vpn", "IPV4MASK",
3019 (1 != inet_pton (AF_INET, ipv4mask, &v4))) )
3021 GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, "VPN", "IPV4MASK",
3022 _("Must specify valid IPv4 mask"));
3023 GNUNET_SCHEDULER_shutdown ();
3026 vpn_argv[5] = ipv4mask;
3030 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
3031 _("IPv4 support disabled as this system does not support IPv4\n"));
3032 vpn_argv[4] = GNUNET_strdup ("-");
3033 vpn_argv[5] = GNUNET_strdup ("-");
3038 GNUNET_MESH_connect (cfg_, NULL,
3043 helper_handle = GNUNET_HELPER_start (GNUNET_NO,
3044 "gnunet-helper-vpn", vpn_argv,
3045 &message_token, NULL, NULL);
3046 nc = GNUNET_SERVER_notification_context_create (server, 1);
3047 GNUNET_SERVER_add_handlers (server, service_handlers);
3048 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &cleanup, cls);
3053 * The main function of the VPN service.
3055 * @param argc number of arguments from the command line
3056 * @param argv command line arguments
3057 * @return 0 ok, 1 on error
3060 main (int argc, char *const *argv)
3062 return (GNUNET_OK ==
3063 GNUNET_SERVICE_run (argc, argv, "vpn",
3064 GNUNET_SERVICE_OPTION_NONE,
3065 &run, NULL)) ? global_ret : 1;
3068 /* end of gnunet-service-vpn.c */