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 * detect & 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.
59 * Information we track for each IP address to determine which tunnel
60 * to send the traffic over to the destination.
62 struct DestinationEntry;
65 * List of tunnels we keep for each destination port for a given
68 struct DestinationTunnel
74 struct DestinationTunnel *next;
79 struct DestinationTunnel *prev;
82 * Destination entry list this `struct DestinationTunnel` belongs with.
84 struct DestinationEntry *destination;
87 * Pre-allocated tunnel for this destination, or NULL for none.
89 struct TunnelState *ts;
92 * Destination port this tunnel state is used for.
94 uint16_t destination_port;
100 * Information we track for each IP address to determine which tunnel
101 * to send the traffic over to the destination.
103 struct DestinationEntry
107 * Key under which this entry is in the 'destination_map' (only valid
108 * if 'heap_node != NULL').
110 struct GNUNET_HashCode key;
113 * Head of DLL of tunnels associated with this destination.
115 struct DestinationTunnel *dt_head;
118 * Tail of DLL of tunnels associated with this destination.
120 struct DestinationTunnel *dt_tail;
123 * Entry for this entry in the destination_heap.
125 struct GNUNET_CONTAINER_HeapNode *heap_node;
128 * #GNUNET_NO if this is a tunnel to an Internet-exit,
129 * #GNUNET_YES if this tunnel is to a service.
134 * Details about the connection (depending on is_service).
142 * The description of the service (only used for service tunnels).
144 struct GNUNET_HashCode service_descriptor;
147 * Peer offering the service.
149 struct GNUNET_PeerIdentity target;
151 } service_destination;
157 * Address family used (AF_INET or AF_INET6).
162 * IP address of the ultimate destination (only used for exit tunnels).
167 * Address if af is AF_INET.
172 * Address if af is AF_INET6.
185 * A messages we have in queue for a particular tunnel.
187 struct TunnelMessageQueueEntry
190 * This is a doubly-linked list.
192 struct TunnelMessageQueueEntry *next;
195 * This is a doubly-linked list.
197 struct TunnelMessageQueueEntry *prev;
200 * Number of bytes in 'msg'.
205 * Message to transmit, allocated at the end of this struct.
212 * State we keep for each of our tunnels.
218 * Information about the tunnel to use, NULL if no tunnel
219 * is available right now.
221 struct GNUNET_MESH_Tunnel *tunnel;
224 * Active query with REGEX to locate exit.
226 struct GNUNET_REGEX_Search *search;
229 * Active transmission handle, NULL for none.
231 struct GNUNET_MESH_TransmitHandle *th;
234 * Entry for this entry in the tunnel_heap, NULL as long as this
235 * tunnel state is not fully bound.
237 struct GNUNET_CONTAINER_HeapNode *heap_node;
240 * Head of list of messages scheduled for transmission.
242 struct TunnelMessageQueueEntry *tmq_head;
245 * Tail of list of messages scheduled for transmission.
247 struct TunnelMessageQueueEntry *tmq_tail;
250 * Destination entry that has a pointer to this tunnel state;
251 * NULL if this tunnel state is in the tunnel map.
253 struct DestinationTunnel *destination_container;
256 * Destination to which this tunnel leads. Note that
257 * this struct is NOT in the destination_map (but a
258 * local copy) and that the 'heap_node' should always
261 struct DestinationEntry destination;
264 * Addess family used for this tunnel on the local TUN interface.
269 * Length of the doubly linked 'tmq_head/tmq_tail' list.
271 unsigned int tmq_length;
274 * IPPROTO_TCP or IPPROTO_UDP once bound.
279 * IP address of the source on our end, initially uninitialized.
284 * Address if af is AF_INET.
289 * Address if af is AF_INET6.
296 * Destination IP address used by the source on our end (this is the IP
297 * that we pick freely within the VPN's tunnel IP range).
302 * Address if af is AF_INET.
307 * Address if af is AF_INET6.
314 * Source port used by the sender on our end; 0 for uninitialized.
316 uint16_t source_port;
319 * Destination port used by the sender on our end; 0 for uninitialized.
321 uint16_t destination_port;
327 * Return value from 'main'.
329 static int global_ret;
332 * Configuration we use.
334 static const struct GNUNET_CONFIGURATION_Handle *cfg;
337 * Handle to the mesh service.
339 static struct GNUNET_MESH_Handle *mesh_handle;
342 * Map from IP address to destination information (possibly with a
343 * MESH tunnel handle for fast setup).
345 static struct GNUNET_CONTAINER_MultiHashMap *destination_map;
348 * Min-Heap sorted by activity time to expire old mappings.
350 static struct GNUNET_CONTAINER_Heap *destination_heap;
353 * Map from source and destination address (IP+port) to connection
354 * information (mostly with the respective MESH tunnel handle).
356 static struct GNUNET_CONTAINER_MultiHashMap *tunnel_map;
359 * Min-Heap sorted by activity time to expire old mappings; values are
360 * of type 'struct TunnelState'.
362 static struct GNUNET_CONTAINER_Heap *tunnel_heap;
367 static struct GNUNET_STATISTICS_Handle *stats;
370 * The handle to the VPN helper process "gnunet-helper-vpn".
372 static struct GNUNET_HELPER_Handle *helper_handle;
375 * Arguments to the vpn helper.
377 static char *vpn_argv[7];
380 * Length of the prefix of the VPN's IPv6 network.
382 static unsigned long long ipv6prefix;
385 * Notification context for sending replies to clients.
387 static struct GNUNET_SERVER_NotificationContext *nc;
390 * If there are more than this number of address-mappings, old ones
393 static unsigned long long max_destination_mappings;
396 * If there are more than this number of open tunnels, old ones
399 static unsigned long long max_tunnel_mappings;
403 * Compute the key under which we would store an entry in the
404 * destination_map for the given IP address.
406 * @param af address family (AF_INET or AF_INET6)
407 * @param address IP address, struct in_addr or struct in6_addr
408 * @param key where to store the key
411 get_destination_key_from_ip (int af,
413 struct GNUNET_HashCode *key)
418 GNUNET_CRYPTO_hash (address,
419 sizeof (struct in_addr),
423 GNUNET_CRYPTO_hash (address,
424 sizeof (struct in6_addr),
435 * Compute the key under which we would store an entry in the
436 * tunnel_map for the given socket address pair.
438 * @param af address family (AF_INET or AF_INET6)
439 * @param protocol IPPROTO_TCP or IPPROTO_UDP
440 * @param source_ip sender's source IP, struct in_addr or struct in6_addr
441 * @param source_port sender's source port
442 * @param destination_ip sender's destination IP, struct in_addr or struct in6_addr
443 * @param destination_port sender's destination port
444 * @param key where to store the key
447 get_tunnel_key_from_ips (int af,
449 const void *source_ip,
450 uint16_t source_port,
451 const void *destination_ip,
452 uint16_t destination_port,
453 struct GNUNET_HashCode *key)
457 memset (key, 0, sizeof (struct GNUNET_HashCode));
458 /* the GNUnet hashmap only uses the first sizeof(unsigned int) of the hash,
459 so we put the ports in there (and hope for few collisions) */
461 memcpy (off, &source_port, sizeof (uint16_t));
462 off += sizeof (uint16_t);
463 memcpy (off, &destination_port, sizeof (uint16_t));
464 off += sizeof (uint16_t);
468 memcpy (off, source_ip, sizeof (struct in_addr));
469 off += sizeof (struct in_addr);
470 memcpy (off, destination_ip, sizeof (struct in_addr));
471 off += sizeof (struct in_addr);
474 memcpy (off, source_ip, sizeof (struct in6_addr));
475 off += sizeof (struct in6_addr);
476 memcpy (off, destination_ip, sizeof (struct in6_addr));
477 off += sizeof (struct in6_addr);
483 memcpy (off, &protocol, sizeof (uint8_t));
484 /* off += sizeof (uint8_t); */
489 * Notify the client about the result of its request.
491 * @param client client to notify
492 * @param request_id original request ID to include in response
493 * @param result_af resulting address family
494 * @param addr resulting IP address
497 send_client_reply (struct GNUNET_SERVER_Client *client,
502 char buf[sizeof (struct RedirectToIpResponseMessage) + sizeof (struct in6_addr)] GNUNET_ALIGN;
503 struct RedirectToIpResponseMessage *res;
509 rlen = sizeof (struct in_addr);
512 rlen = sizeof (struct in6_addr);
521 res = (struct RedirectToIpResponseMessage *) buf;
522 res->header.size = htons (sizeof (struct RedirectToIpResponseMessage) + rlen);
523 res->header.type = htons (GNUNET_MESSAGE_TYPE_VPN_CLIENT_USE_IP);
524 res->result_af = htonl (result_af);
525 res->request_id = request_id;
526 memcpy (&res[1], addr, rlen);
527 GNUNET_SERVER_notification_context_add (nc, client);
528 GNUNET_SERVER_notification_context_unicast (nc,
536 * Free resources associated with a tunnel state.
538 * @param ts state to free
541 free_tunnel_state (struct TunnelState *ts)
543 struct GNUNET_HashCode key;
544 struct TunnelMessageQueueEntry *tnq;
545 struct GNUNET_MESH_Tunnel *tunnel;
547 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
548 "Cleaning up tunnel state\n");
549 GNUNET_STATISTICS_update (stats,
550 gettext_noop ("# Active tunnels"),
552 while (NULL != (tnq = ts->tmq_head))
554 GNUNET_CONTAINER_DLL_remove (ts->tmq_head,
560 GNUNET_assert (0 == ts->tmq_length);
563 GNUNET_MESH_notify_transmit_ready_cancel (ts->th);
566 GNUNET_assert (NULL == ts->destination.heap_node);
567 if (NULL != (tunnel = ts->tunnel))
570 GNUNET_MESH_tunnel_destroy (tunnel);
572 if (NULL != ts->search)
574 GNUNET_REGEX_search_cancel (ts->search);
577 if (NULL != ts->heap_node)
579 GNUNET_CONTAINER_heap_remove_node (ts->heap_node);
580 ts->heap_node = NULL;
581 get_tunnel_key_from_ips (ts->af,
586 ts->destination_port,
588 GNUNET_assert (GNUNET_YES ==
589 GNUNET_CONTAINER_multihashmap_remove (tunnel_map,
593 if (NULL != ts->destination_container)
595 GNUNET_assert (ts == ts->destination_container->ts);
596 ts->destination_container->ts = NULL;
597 ts->destination_container = NULL;
604 * Send a message from the message queue via mesh.
606 * @param cls the `struct TunnelState` with the message queue
607 * @param size number of bytes available in @a buf
608 * @param buf where to copy the message
609 * @return number of bytes copied to @a buf
612 send_to_peer_notify_callback (void *cls, size_t size, void *buf)
614 struct TunnelState *ts = cls;
615 struct TunnelMessageQueueEntry *tnq;
622 GNUNET_assert (NULL != tnq);
623 GNUNET_assert (size >= tnq->len);
624 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
625 "Sending %u bytes via mesh tunnel\n",
627 GNUNET_CONTAINER_DLL_remove (ts->tmq_head,
631 memcpy (buf, tnq->msg, tnq->len);
634 if (NULL != (tnq = ts->tmq_head))
635 ts->th = GNUNET_MESH_notify_transmit_ready (ts->tunnel,
636 GNUNET_NO /* cork */,
637 GNUNET_TIME_UNIT_FOREVER_REL,
639 &send_to_peer_notify_callback,
641 GNUNET_STATISTICS_update (stats,
642 gettext_noop ("# Bytes given to mesh for transmission"),
649 * Add the given message to the given tunnel and trigger the
650 * transmission process.
652 * @param tnq message to queue
653 * @param ts tunnel to queue the message for
656 send_to_tunnel (struct TunnelMessageQueueEntry *tnq,
657 struct TunnelState *ts)
659 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
660 "Queueing %u bytes for transmission via mesh tunnel\n",
662 GNUNET_assert (NULL != ts->tunnel);
663 GNUNET_CONTAINER_DLL_insert_tail (ts->tmq_head,
667 if (ts->tmq_length > MAX_MESSAGE_QUEUE_SIZE)
669 struct TunnelMessageQueueEntry *dq;
672 GNUNET_assert (dq != tnq);
673 GNUNET_CONTAINER_DLL_remove (ts->tmq_head,
677 GNUNET_MESH_notify_transmit_ready_cancel (ts->th);
679 GNUNET_STATISTICS_update (stats,
680 gettext_noop ("# Bytes dropped in mesh queue (overflow)"),
686 ts->th = GNUNET_MESH_notify_transmit_ready (ts->tunnel,
687 GNUNET_NO /* cork */,
688 GNUNET_TIME_UNIT_FOREVER_REL,
690 &send_to_peer_notify_callback,
696 * Regex has found a potential exit peer for us; consider using it.
698 * @param cls the 'struct TunnelState'
699 * @param id Peer providing a regex that matches the string.
700 * @param get_path Path of the get request.
701 * @param get_path_length Lenght of @a get_path.
702 * @param put_path Path of the put request.
703 * @param put_path_length Length of the @a put_path.
706 handle_regex_result (void *cls,
707 const struct GNUNET_PeerIdentity *id,
708 const struct GNUNET_PeerIdentity *get_path,
709 unsigned int get_path_length,
710 const struct GNUNET_PeerIdentity *put_path,
711 unsigned int put_path_length)
713 struct TunnelState *ts = cls;
714 unsigned int apptype;
716 GNUNET_REGEX_search_cancel (ts->search);
721 apptype = GNUNET_APPLICATION_TYPE_IPV4_GATEWAY;
724 apptype = GNUNET_APPLICATION_TYPE_IPV6_GATEWAY;
730 ts->tunnel = GNUNET_MESH_tunnel_create (mesh_handle,
740 * Initialize the given destination entry's mesh tunnel.
742 * @param dt destination tunnel for which we need to setup a tunnel
743 * @param client_af address family of the address returned to the client
744 * @return tunnel state of the tunnel that was created
746 static struct TunnelState *
747 create_tunnel_to_destination (struct DestinationTunnel *dt,
750 struct TunnelState *ts;
751 unsigned int apptype;
753 GNUNET_STATISTICS_update (stats,
754 gettext_noop ("# Mesh tunnels created"),
756 GNUNET_assert (NULL == dt->ts);
760 apptype = GNUNET_APPLICATION_TYPE_IPV4_GATEWAY;
763 apptype = GNUNET_APPLICATION_TYPE_IPV6_GATEWAY;
769 ts = GNUNET_new (struct TunnelState);
771 ts->destination = *dt->destination;
772 ts->destination.heap_node = NULL; /* copy is NOT in destination heap */
774 ts->destination_container = dt; /* we are referenced from dt */
775 if (dt->destination->is_service)
777 ts->tunnel = GNUNET_MESH_tunnel_create (mesh_handle,
779 &dt->destination->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 (&dt->destination->details.service_destination.target),
793 GNUNET_h2s (&dt->destination->details.service_destination.service_descriptor));
799 switch (dt->destination->details.exit_destination.af)
803 char address[GNUNET_TUN_IPV4_REGEXLEN];
805 GNUNET_TUN_ipv4toregexsearch (&dt->destination->details.exit_destination.ip.v4,
808 GNUNET_asprintf (&policy, "%s%s%s:%u",
809 GNUNET_APPLICATION_TYPE_EXIT_REGEX_PREFIX,
812 (unsigned int) dt->destination_port);
817 char address[GNUNET_TUN_IPV6_REGEXLEN];
819 GNUNET_TUN_ipv6toregexsearch (&dt->destination->details.exit_destination.ip.v6,
821 GNUNET_asprintf (&policy, "%s%s%s:%u",
822 GNUNET_APPLICATION_TYPE_EXIT_REGEX_PREFIX,
825 (unsigned int) dt->destination_port);
833 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
834 "Requesting connect by string: %s\n",
836 ts->search = GNUNET_REGEX_search (cfg,
838 &handle_regex_result,
840 GNUNET_free (policy);
847 * We have too many active tunnels. Clean up the oldest tunnel.
849 * @param except tunnel that must NOT be cleaned up, even if it is the oldest
852 expire_tunnel (struct TunnelState *except)
854 struct TunnelState *ts;
856 ts = GNUNET_CONTAINER_heap_peek (tunnel_heap);
857 GNUNET_assert (NULL != ts);
859 return; /* can't do this */
860 free_tunnel_state (ts);
865 * Route a packet via mesh to the given destination.
867 * @param destination description of the destination
868 * @param af address family on this end (AF_INET or AF_INET6)
869 * @param protocol IPPROTO_TCP or IPPROTO_UDP or IPPROTO_ICMP or IPPROTO_ICMPV6
870 * @param source_ip source IP used by the sender (struct in_addr or struct in6_addr)
871 * @param destination_ip destination IP used by the sender (struct in_addr or struct in6_addr)
872 * @param payload payload of the packet after the IP header
873 * @param payload_length number of bytes in @a payload
876 route_packet (struct DestinationEntry *destination,
879 const void *source_ip,
880 const void *destination_ip,
882 size_t payload_length)
884 struct GNUNET_HashCode key;
885 struct TunnelState *ts;
886 struct TunnelMessageQueueEntry *tnq;
890 const struct GNUNET_TUN_UdpHeader *udp;
891 const struct GNUNET_TUN_TcpHeader *tcp;
892 const struct GNUNET_TUN_IcmpHeader *icmp;
893 struct DestinationTunnel *dt;
894 uint16_t source_port;
895 uint16_t destination_port;
901 if (payload_length < sizeof (struct GNUNET_TUN_UdpHeader))
907 tcp = NULL; /* make compiler happy */
908 icmp = NULL; /* make compiler happy */
910 if (udp->len < sizeof (struct GNUNET_TUN_UdpHeader))
915 source_port = ntohs (udp->source_port);
916 destination_port = ntohs (udp->destination_port);
917 get_tunnel_key_from_ips (af,
928 if (payload_length < sizeof (struct GNUNET_TUN_TcpHeader))
934 udp = NULL; /* make compiler happy */
935 icmp = NULL; /* make compiler happy */
937 if (tcp->off * 4 < sizeof (struct GNUNET_TUN_TcpHeader))
942 source_port = ntohs (tcp->source_port);
943 destination_port = ntohs (tcp->destination_port);
944 get_tunnel_key_from_ips (af,
956 if ( (AF_INET == af) ^ (protocol == IPPROTO_ICMP) )
961 if (payload_length < sizeof (struct GNUNET_TUN_IcmpHeader))
967 tcp = NULL; /* make compiler happy */
968 udp = NULL; /* make compiler happy */
971 destination_port = 0;
972 get_tunnel_key_from_ips (af,
982 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
983 _("Protocol %u not supported, dropping\n"),
984 (unsigned int) protocol);
988 if (! destination->is_service)
990 switch (destination->details.exit_destination.af)
993 alen = sizeof (struct in_addr);
996 alen = sizeof (struct in6_addr);
1003 char sbuf[INET6_ADDRSTRLEN];
1004 char dbuf[INET6_ADDRSTRLEN];
1005 char xbuf[INET6_ADDRSTRLEN];
1007 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1008 "Routing %s packet from %s:%u -> %s:%u to destination %s:%u\n",
1009 (protocol == IPPROTO_TCP) ? "TCP" : "UDP",
1010 inet_ntop (af, source_ip, sbuf, sizeof (sbuf)),
1012 inet_ntop (af, destination_ip, dbuf, sizeof (dbuf)),
1014 inet_ntop (destination->details.exit_destination.af,
1015 &destination->details.exit_destination.ip,
1016 xbuf, sizeof (xbuf)),
1019 for (dt = destination->dt_head; NULL != dt; dt = dt->next)
1020 if (dt->destination_port == destination_port)
1026 char sbuf[INET6_ADDRSTRLEN];
1027 char dbuf[INET6_ADDRSTRLEN];
1029 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1030 "Routing %s packet from %s:%u -> %s:%u to service %s at peer %s\n",
1031 (protocol == IPPROTO_TCP) ? "TCP" : "UDP",
1032 inet_ntop (af, source_ip, sbuf, sizeof (sbuf)),
1034 inet_ntop (af, destination_ip, dbuf, sizeof (dbuf)),
1036 GNUNET_h2s (&destination->details.service_destination.service_descriptor),
1037 GNUNET_i2s (&destination->details.service_destination.target));
1039 dt = destination->dt_head;
1043 dt = GNUNET_new (struct DestinationTunnel);
1044 dt->destination = destination;
1045 GNUNET_CONTAINER_DLL_insert (destination->dt_head,
1046 destination->dt_tail,
1048 dt->destination_port = destination_port;
1051 /* see if we have an existing tunnel for this destination */
1052 ts = GNUNET_CONTAINER_multihashmap_get (tunnel_map,
1056 /* need to either use the existing tunnel from the destination (if still
1057 available) or create a fresh one */
1058 is_new = GNUNET_YES;
1060 ts = create_tunnel_to_destination (dt, af);
1066 ts->destination_container = NULL; /* no longer 'contained' */
1067 /* now bind existing "unbound" tunnel to our IP/port tuple */
1068 ts->protocol = protocol;
1072 ts->source_ip.v4 = * (const struct in_addr *) source_ip;
1073 ts->destination_ip.v4 = * (const struct in_addr *) destination_ip;
1077 ts->source_ip.v6 = * (const struct in6_addr *) source_ip;
1078 ts->destination_ip.v6 = * (const struct in6_addr *) destination_ip;
1080 ts->source_port = source_port;
1081 ts->destination_port = destination_port;
1082 ts->heap_node = GNUNET_CONTAINER_heap_insert (tunnel_heap,
1084 GNUNET_TIME_absolute_get ().abs_value_us);
1085 GNUNET_assert (GNUNET_YES ==
1086 GNUNET_CONTAINER_multihashmap_put (tunnel_map,
1089 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
1090 GNUNET_STATISTICS_update (stats,
1091 gettext_noop ("# Active tunnels"),
1093 while (GNUNET_CONTAINER_multihashmap_size (tunnel_map) > max_tunnel_mappings)
1099 GNUNET_CONTAINER_heap_update_cost (tunnel_heap,
1101 GNUNET_TIME_absolute_get ().abs_value_us);
1103 GNUNET_assert (NULL != ts->tunnel);
1105 /* send via tunnel */
1109 if (destination->is_service)
1111 struct GNUNET_EXIT_UdpServiceMessage *usm;
1113 mlen = sizeof (struct GNUNET_EXIT_UdpServiceMessage) +
1114 payload_length - sizeof (struct GNUNET_TUN_UdpHeader);
1115 if (mlen >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1120 tnq = GNUNET_malloc (sizeof (struct TunnelMessageQueueEntry) + mlen);
1123 usm = (struct GNUNET_EXIT_UdpServiceMessage *) &tnq[1];
1124 usm->header.size = htons ((uint16_t) mlen);
1125 usm->header.type = htons (GNUNET_MESSAGE_TYPE_VPN_UDP_TO_SERVICE);
1126 /* if the source port is below 32000, we assume it has a special
1127 meaning; if not, we pick a random port (this is a heuristic) */
1128 usm->source_port = (ntohs (udp->source_port) < 32000) ? udp->source_port : 0;
1129 usm->destination_port = udp->destination_port;
1130 usm->service_descriptor = destination->details.service_destination.service_descriptor;
1133 payload_length - sizeof (struct GNUNET_TUN_UdpHeader));
1137 struct GNUNET_EXIT_UdpInternetMessage *uim;
1138 struct in_addr *ip4dst;
1139 struct in6_addr *ip6dst;
1142 mlen = sizeof (struct GNUNET_EXIT_UdpInternetMessage) +
1143 alen + payload_length - sizeof (struct GNUNET_TUN_UdpHeader);
1144 if (mlen >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1149 tnq = GNUNET_malloc (sizeof (struct TunnelMessageQueueEntry) + mlen);
1152 uim = (struct GNUNET_EXIT_UdpInternetMessage *) &tnq[1];
1153 uim->header.size = htons ((uint16_t) mlen);
1154 uim->header.type = htons (GNUNET_MESSAGE_TYPE_VPN_UDP_TO_INTERNET);
1155 uim->af = htonl (destination->details.exit_destination.af);
1156 uim->source_port = (ntohs (udp->source_port) < 32000) ? udp->source_port : 0;
1157 uim->destination_port = udp->destination_port;
1158 switch (destination->details.exit_destination.af)
1161 ip4dst = (struct in_addr *) &uim[1];
1162 *ip4dst = destination->details.exit_destination.ip.v4;
1163 payload = &ip4dst[1];
1166 ip6dst = (struct in6_addr *) &uim[1];
1167 *ip6dst = destination->details.exit_destination.ip.v6;
1168 payload = &ip6dst[1];
1175 payload_length - sizeof (struct GNUNET_TUN_UdpHeader));
1181 if (destination->is_service)
1183 struct GNUNET_EXIT_TcpServiceStartMessage *tsm;
1185 mlen = sizeof (struct GNUNET_EXIT_TcpServiceStartMessage) +
1186 payload_length - sizeof (struct GNUNET_TUN_TcpHeader);
1187 if (mlen >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1192 tnq = GNUNET_malloc (sizeof (struct TunnelMessageQueueEntry) + mlen);
1195 tsm = (struct GNUNET_EXIT_TcpServiceStartMessage *) &tnq[1];
1196 tsm->header.size = htons ((uint16_t) mlen);
1197 tsm->header.type = htons (GNUNET_MESSAGE_TYPE_VPN_TCP_TO_SERVICE_START);
1198 tsm->reserved = htonl (0);
1199 tsm->service_descriptor = destination->details.service_destination.service_descriptor;
1200 tsm->tcp_header = *tcp;
1203 payload_length - sizeof (struct GNUNET_TUN_TcpHeader));
1207 struct GNUNET_EXIT_TcpInternetStartMessage *tim;
1208 struct in_addr *ip4dst;
1209 struct in6_addr *ip6dst;
1212 mlen = sizeof (struct GNUNET_EXIT_TcpInternetStartMessage) +
1213 alen + payload_length - sizeof (struct GNUNET_TUN_TcpHeader);
1214 if (mlen >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1219 tnq = GNUNET_malloc (sizeof (struct TunnelMessageQueueEntry) + mlen);
1222 tim = (struct GNUNET_EXIT_TcpInternetStartMessage *) &tnq[1];
1223 tim->header.size = htons ((uint16_t) mlen);
1224 tim->header.type = htons (GNUNET_MESSAGE_TYPE_VPN_TCP_TO_INTERNET_START);
1225 tim->af = htonl (destination->details.exit_destination.af);
1226 tim->tcp_header = *tcp;
1227 switch (destination->details.exit_destination.af)
1230 ip4dst = (struct in_addr *) &tim[1];
1231 *ip4dst = destination->details.exit_destination.ip.v4;
1232 payload = &ip4dst[1];
1235 ip6dst = (struct in6_addr *) &tim[1];
1236 *ip6dst = destination->details.exit_destination.ip.v6;
1237 payload = &ip6dst[1];
1244 payload_length - sizeof (struct GNUNET_TUN_TcpHeader));
1249 struct GNUNET_EXIT_TcpDataMessage *tdm;
1251 mlen = sizeof (struct GNUNET_EXIT_TcpDataMessage) +
1252 payload_length - sizeof (struct GNUNET_TUN_TcpHeader);
1253 if (mlen >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1258 tnq = GNUNET_malloc (sizeof (struct TunnelMessageQueueEntry) + mlen);
1261 tdm = (struct GNUNET_EXIT_TcpDataMessage *) &tnq[1];
1262 tdm->header.size = htons ((uint16_t) mlen);
1263 tdm->header.type = htons (GNUNET_MESSAGE_TYPE_VPN_TCP_DATA_TO_EXIT);
1264 tdm->reserved = htonl (0);
1265 tdm->tcp_header = *tcp;
1268 payload_length - sizeof (struct GNUNET_TUN_TcpHeader));
1272 case IPPROTO_ICMPV6:
1273 if (destination->is_service)
1275 struct GNUNET_EXIT_IcmpServiceMessage *ism;
1277 mlen = sizeof (struct GNUNET_EXIT_IcmpServiceMessage) +
1278 payload_length - sizeof (struct GNUNET_TUN_IcmpHeader);
1279 if (mlen >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1284 tnq = GNUNET_malloc (sizeof (struct TunnelMessageQueueEntry) + mlen);
1286 ism = (struct GNUNET_EXIT_IcmpServiceMessage *) &tnq[1];
1287 ism->header.type = htons (GNUNET_MESSAGE_TYPE_VPN_ICMP_TO_SERVICE);
1288 ism->af = htonl (af); /* need to tell destination ICMP protocol family! */
1289 ism->service_descriptor = destination->details.service_destination.service_descriptor;
1290 ism->icmp_header = *icmp;
1291 /* ICMP protocol translation will be done by the receiver (as we don't know
1292 the target AF); however, we still need to possibly discard the payload
1293 depending on the ICMP type */
1299 case GNUNET_TUN_ICMPTYPE_ECHO_REPLY:
1300 case GNUNET_TUN_ICMPTYPE_ECHO_REQUEST:
1302 case GNUNET_TUN_ICMPTYPE_DESTINATION_UNREACHABLE:
1303 case GNUNET_TUN_ICMPTYPE_SOURCE_QUENCH:
1304 case GNUNET_TUN_ICMPTYPE_TIME_EXCEEDED:
1305 /* throw away ICMP payload, won't be useful for the other side anyway */
1306 payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
1309 GNUNET_STATISTICS_update (stats,
1310 gettext_noop ("# ICMPv4 packets dropped (not allowed)"),
1314 /* end of AF_INET */
1319 case GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE:
1320 case GNUNET_TUN_ICMPTYPE6_PACKET_TOO_BIG:
1321 case GNUNET_TUN_ICMPTYPE6_TIME_EXCEEDED:
1322 case GNUNET_TUN_ICMPTYPE6_PARAMETER_PROBLEM:
1323 /* throw away ICMP payload, won't be useful for the other side anyway */
1324 payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
1326 case GNUNET_TUN_ICMPTYPE6_ECHO_REQUEST:
1327 case GNUNET_TUN_ICMPTYPE6_ECHO_REPLY:
1330 GNUNET_STATISTICS_update (stats,
1331 gettext_noop ("# ICMPv6 packets dropped (not allowed)"),
1335 /* end of AF_INET6 */
1342 /* update length calculations, as payload_length may have changed */
1343 mlen = sizeof (struct GNUNET_EXIT_IcmpServiceMessage) +
1344 alen + payload_length - sizeof (struct GNUNET_TUN_IcmpHeader);
1346 ism->header.size = htons ((uint16_t) mlen);
1347 /* finally, copy payload (if there is any left...) */
1350 payload_length - sizeof (struct GNUNET_TUN_IcmpHeader));
1354 struct GNUNET_EXIT_IcmpInternetMessage *iim;
1355 struct in_addr *ip4dst;
1356 struct in6_addr *ip6dst;
1359 mlen = sizeof (struct GNUNET_EXIT_IcmpInternetMessage) +
1360 alen + payload_length - sizeof (struct GNUNET_TUN_IcmpHeader);
1361 if (mlen >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1366 tnq = GNUNET_malloc (sizeof (struct TunnelMessageQueueEntry) + mlen);
1368 iim = (struct GNUNET_EXIT_IcmpInternetMessage *) &tnq[1];
1369 iim->header.type = htons (GNUNET_MESSAGE_TYPE_VPN_ICMP_TO_INTERNET);
1370 iim->icmp_header = *icmp;
1371 /* Perform ICMP protocol-translation (depending on destination AF and source AF)
1372 and throw away ICMP payload depending on ICMP message type */
1378 case GNUNET_TUN_ICMPTYPE_ECHO_REPLY:
1379 if (destination->details.exit_destination.af == AF_INET6)
1380 iim->icmp_header.type = GNUNET_TUN_ICMPTYPE6_ECHO_REPLY;
1382 case GNUNET_TUN_ICMPTYPE_ECHO_REQUEST:
1383 if (destination->details.exit_destination.af == AF_INET6)
1384 iim->icmp_header.type = GNUNET_TUN_ICMPTYPE6_ECHO_REQUEST;
1386 case GNUNET_TUN_ICMPTYPE_DESTINATION_UNREACHABLE:
1387 if (destination->details.exit_destination.af == AF_INET6)
1388 iim->icmp_header.type = GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE;
1389 /* throw away IP-payload, exit will have to make it up anyway */
1390 payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
1392 case GNUNET_TUN_ICMPTYPE_TIME_EXCEEDED:
1393 if (destination->details.exit_destination.af == AF_INET6)
1394 iim->icmp_header.type = GNUNET_TUN_ICMPTYPE6_TIME_EXCEEDED;
1395 /* throw away IP-payload, exit will have to make it up anyway */
1396 payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
1398 case GNUNET_TUN_ICMPTYPE_SOURCE_QUENCH:
1399 if (destination->details.exit_destination.af == AF_INET6)
1401 GNUNET_STATISTICS_update (stats,
1402 gettext_noop ("# ICMPv4 packets dropped (impossible PT to v6)"),
1407 /* throw away IP-payload, exit will have to make it up anyway */
1408 payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
1411 GNUNET_STATISTICS_update (stats,
1412 gettext_noop ("# ICMPv4 packets dropped (type not allowed)"),
1417 /* end of AF_INET */
1422 case GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE:
1423 if (destination->details.exit_destination.af == AF_INET6)
1424 iim->icmp_header.type = GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE;
1425 /* throw away IP-payload, exit will have to make it up anyway */
1426 payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
1428 case GNUNET_TUN_ICMPTYPE6_TIME_EXCEEDED:
1429 if (destination->details.exit_destination.af == AF_INET)
1430 iim->icmp_header.type = GNUNET_TUN_ICMPTYPE_TIME_EXCEEDED;
1431 /* throw away IP-payload, exit will have to make it up anyway */
1432 payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
1434 case GNUNET_TUN_ICMPTYPE6_PACKET_TOO_BIG:
1435 if (destination->details.exit_destination.af == AF_INET)
1437 GNUNET_STATISTICS_update (stats,
1438 gettext_noop ("# ICMPv6 packets dropped (impossible PT to v4)"),
1443 /* throw away IP-payload, exit will have to make it up anyway */
1444 payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
1446 case GNUNET_TUN_ICMPTYPE6_PARAMETER_PROBLEM:
1447 if (destination->details.exit_destination.af == AF_INET)
1449 GNUNET_STATISTICS_update (stats,
1450 gettext_noop ("# ICMPv6 packets dropped (impossible PT to v4)"),
1455 /* throw away IP-payload, exit will have to make it up anyway */
1456 payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
1458 case GNUNET_TUN_ICMPTYPE6_ECHO_REQUEST:
1459 if (destination->details.exit_destination.af == AF_INET)
1460 iim->icmp_header.type = GNUNET_TUN_ICMPTYPE_ECHO_REQUEST;
1462 case GNUNET_TUN_ICMPTYPE6_ECHO_REPLY:
1463 if (destination->details.exit_destination.af == AF_INET)
1464 iim->icmp_header.type = GNUNET_TUN_ICMPTYPE_ECHO_REPLY;
1467 GNUNET_STATISTICS_update (stats,
1468 gettext_noop ("# ICMPv6 packets dropped (type not allowed)"),
1473 /* end of AF_INET6 */
1478 /* update length calculations, as payload_length may have changed */
1479 mlen = sizeof (struct GNUNET_EXIT_IcmpInternetMessage) +
1480 alen + payload_length - sizeof (struct GNUNET_TUN_IcmpHeader);
1482 iim->header.size = htons ((uint16_t) mlen);
1484 /* need to tell destination ICMP protocol family! */
1485 iim->af = htonl (destination->details.exit_destination.af);
1486 switch (destination->details.exit_destination.af)
1489 ip4dst = (struct in_addr *) &iim[1];
1490 *ip4dst = destination->details.exit_destination.ip.v4;
1491 payload = &ip4dst[1];
1494 ip6dst = (struct in6_addr *) &iim[1];
1495 *ip6dst = destination->details.exit_destination.ip.v6;
1496 payload = &ip6dst[1];
1503 payload_length - sizeof (struct GNUNET_TUN_IcmpHeader));
1507 /* not supported above, how can we get here !? */
1511 send_to_tunnel (tnq, ts);
1516 * Receive packets from the helper-process (someone send to the local
1517 * virtual tunnel interface). Find the destination mapping, and if it
1518 * exists, identify the correct MESH tunnel (or possibly create it)
1519 * and forward the packet.
1521 * @param cls closure, NULL
1522 * @param client NULL
1523 * @param message message we got from the client (VPN tunnel interface)
1526 message_token (void *cls,
1528 const struct GNUNET_MessageHeader *message)
1530 const struct GNUNET_TUN_Layer2PacketHeader *tun;
1532 struct GNUNET_HashCode key;
1533 struct DestinationEntry *de;
1535 GNUNET_STATISTICS_update (stats,
1536 gettext_noop ("# Packets received from TUN interface"),
1538 mlen = ntohs (message->size);
1539 if ( (ntohs (message->type) != GNUNET_MESSAGE_TYPE_VPN_HELPER) ||
1540 (mlen < sizeof (struct GNUNET_MessageHeader) + sizeof (struct GNUNET_TUN_Layer2PacketHeader)) )
1545 tun = (const struct GNUNET_TUN_Layer2PacketHeader *) &message[1];
1546 mlen -= (sizeof (struct GNUNET_MessageHeader) + sizeof (struct GNUNET_TUN_Layer2PacketHeader));
1547 switch (ntohs (tun->proto))
1551 const struct GNUNET_TUN_IPv6Header *pkt6;
1553 if (mlen < sizeof (struct GNUNET_TUN_IPv6Header))
1559 pkt6 = (const struct GNUNET_TUN_IPv6Header *) &tun[1];
1560 get_destination_key_from_ip (AF_INET6,
1561 &pkt6->destination_address,
1563 de = GNUNET_CONTAINER_multihashmap_get (destination_map, &key);
1566 char buf[INET6_ADDRSTRLEN];
1568 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1569 _("Packet received for unmapped destination `%s' (dropping it)\n"),
1570 inet_ntop (AF_INET6,
1571 &pkt6->destination_address,
1579 &pkt6->source_address,
1580 &pkt6->destination_address,
1582 mlen - sizeof (struct GNUNET_TUN_IPv6Header));
1587 struct GNUNET_TUN_IPv4Header *pkt4;
1589 if (mlen < sizeof (struct GNUNET_TUN_IPv4Header))
1595 pkt4 = (struct GNUNET_TUN_IPv4Header *) &tun[1];
1596 get_destination_key_from_ip (AF_INET,
1597 &pkt4->destination_address,
1599 de = GNUNET_CONTAINER_multihashmap_get (destination_map, &key);
1602 char buf[INET_ADDRSTRLEN];
1604 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1605 _("Packet received for unmapped destination `%s' (dropping it)\n"),
1607 &pkt4->destination_address,
1612 if (pkt4->header_length * 4 != sizeof (struct GNUNET_TUN_IPv4Header))
1614 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1615 _("Received IPv4 packet with options (dropping it)\n"));
1621 &pkt4->source_address,
1622 &pkt4->destination_address,
1624 mlen - sizeof (struct GNUNET_TUN_IPv4Header));
1628 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1629 _("Received packet of unknown protocol %d from TUN (dropping it)\n"),
1630 (unsigned int) ntohs (tun->proto));
1638 * Synthesize a plausible ICMP payload for an ICMP error
1639 * response on the given tunnel.
1641 * @param ts tunnel information
1642 * @param ipp IPv4 header to fill in (ICMP payload)
1643 * @param udp "UDP" header to fill in (ICMP payload); might actually
1644 * also be the first 8 bytes of the TCP header
1647 make_up_icmpv4_payload (struct TunnelState *ts,
1648 struct GNUNET_TUN_IPv4Header *ipp,
1649 struct GNUNET_TUN_UdpHeader *udp)
1651 GNUNET_TUN_initialize_ipv4_header (ipp,
1653 sizeof (struct GNUNET_TUN_TcpHeader),
1655 &ts->destination_ip.v4);
1656 udp->source_port = htons (ts->source_port);
1657 udp->destination_port = htons (ts->destination_port);
1658 udp->len = htons (0);
1659 udp->crc = htons (0);
1664 * Synthesize a plausible ICMP payload for an ICMP error
1665 * response on the given tunnel.
1667 * @param ts tunnel information
1668 * @param ipp IPv6 header to fill in (ICMP payload)
1669 * @param udp "UDP" header to fill in (ICMP payload); might actually
1670 * also be the first 8 bytes of the TCP header
1673 make_up_icmpv6_payload (struct TunnelState *ts,
1674 struct GNUNET_TUN_IPv6Header *ipp,
1675 struct GNUNET_TUN_UdpHeader *udp)
1677 GNUNET_TUN_initialize_ipv6_header (ipp,
1679 sizeof (struct GNUNET_TUN_TcpHeader),
1681 &ts->destination_ip.v6);
1682 udp->source_port = htons (ts->source_port);
1683 udp->destination_port = htons (ts->destination_port);
1684 udp->len = htons (0);
1685 udp->crc = htons (0);
1690 * We got an ICMP packet back from the MESH tunnel. Pass it on to the
1691 * local virtual interface via the helper.
1693 * @param cls closure, NULL
1694 * @param tunnel connection to the other end
1695 * @param tunnel_ctx pointer to our 'struct TunnelState *'
1696 * @param message the actual message
1697 * @return #GNUNET_OK to keep the connection open,
1698 * #GNUNET_SYSERR to close it (signal serious error)
1701 receive_icmp_back (void *cls,
1702 struct GNUNET_MESH_Tunnel *tunnel,
1704 const struct GNUNET_MessageHeader *message)
1706 struct TunnelState *ts = *tunnel_ctx;
1707 const struct GNUNET_EXIT_IcmpToVPNMessage *i2v;
1710 GNUNET_STATISTICS_update (stats,
1711 gettext_noop ("# ICMP packets received from mesh"),
1713 mlen = ntohs (message->size);
1714 if (mlen < sizeof (struct GNUNET_EXIT_IcmpToVPNMessage))
1716 GNUNET_break_op (0);
1717 return GNUNET_SYSERR;
1719 if (NULL == ts->heap_node)
1721 GNUNET_break_op (0);
1722 return GNUNET_SYSERR;
1724 if (AF_UNSPEC == ts->af)
1726 GNUNET_break_op (0);
1727 return GNUNET_SYSERR;
1729 i2v = (const struct GNUNET_EXIT_IcmpToVPNMessage *) message;
1730 mlen -= sizeof (struct GNUNET_EXIT_IcmpToVPNMessage);
1732 char sbuf[INET6_ADDRSTRLEN];
1733 char dbuf[INET6_ADDRSTRLEN];
1735 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1736 "Received ICMP packet from mesh, sending %u bytes from %s -> %s via TUN\n",
1737 (unsigned int) mlen,
1738 inet_ntop (ts->af, &ts->destination_ip, sbuf, sizeof (sbuf)),
1739 inet_ntop (ts->af, &ts->source_ip, dbuf, sizeof (dbuf)));
1745 size_t size = sizeof (struct GNUNET_TUN_IPv4Header)
1746 + sizeof (struct GNUNET_TUN_IcmpHeader)
1747 + sizeof (struct GNUNET_MessageHeader) +
1748 sizeof (struct GNUNET_TUN_Layer2PacketHeader) +
1751 /* reserve some extra space in case we have an ICMP type here where
1752 we will need to make up the payload ourselves */
1753 char buf[size + sizeof (struct GNUNET_TUN_IPv4Header) + 8] GNUNET_ALIGN;
1754 struct GNUNET_MessageHeader *msg = (struct GNUNET_MessageHeader *) buf;
1755 struct GNUNET_TUN_Layer2PacketHeader *tun = (struct GNUNET_TUN_Layer2PacketHeader*) &msg[1];
1756 struct GNUNET_TUN_IPv4Header *ipv4 = (struct GNUNET_TUN_IPv4Header *) &tun[1];
1757 struct GNUNET_TUN_IcmpHeader *icmp = (struct GNUNET_TUN_IcmpHeader *) &ipv4[1];
1758 msg->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
1759 tun->flags = htons (0);
1760 tun->proto = htons (ETH_P_IPV4);
1761 GNUNET_TUN_initialize_ipv4_header (ipv4,
1763 sizeof (struct GNUNET_TUN_IcmpHeader) + mlen,
1764 &ts->destination_ip.v4,
1766 *icmp = i2v->icmp_header;
1770 /* For some ICMP types, we need to adjust (make up) the payload here.
1771 Also, depending on the AF used on the other side, we have to
1772 do ICMP PT (translate ICMP types) */
1773 switch (ntohl (i2v->af))
1778 case GNUNET_TUN_ICMPTYPE_ECHO_REPLY:
1779 case GNUNET_TUN_ICMPTYPE_ECHO_REQUEST:
1781 case GNUNET_TUN_ICMPTYPE_DESTINATION_UNREACHABLE:
1782 case GNUNET_TUN_ICMPTYPE_SOURCE_QUENCH:
1783 case GNUNET_TUN_ICMPTYPE_TIME_EXCEEDED:
1785 struct GNUNET_TUN_IPv4Header *ipp = (struct GNUNET_TUN_IPv4Header *) &icmp[1];
1786 struct GNUNET_TUN_UdpHeader *udp = (struct GNUNET_TUN_UdpHeader *) &ipp[1];
1790 /* sender did not strip ICMP payload? */
1791 GNUNET_break_op (0);
1792 return GNUNET_SYSERR;
1794 size += sizeof (struct GNUNET_TUN_IPv4Header) + 8;
1795 GNUNET_assert (8 == sizeof (struct GNUNET_TUN_UdpHeader));
1796 make_up_icmpv4_payload (ts, ipp, udp);
1800 GNUNET_break_op (0);
1801 GNUNET_STATISTICS_update (stats,
1802 gettext_noop ("# ICMPv4 packets dropped (type not allowed)"),
1804 return GNUNET_SYSERR;
1809 /* ICMP PT 6-to-4 and possibly making up payloads */
1812 case GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE:
1813 icmp->type = GNUNET_TUN_ICMPTYPE_DESTINATION_UNREACHABLE;
1815 struct GNUNET_TUN_IPv4Header *ipp = (struct GNUNET_TUN_IPv4Header *) &icmp[1];
1816 struct GNUNET_TUN_UdpHeader *udp = (struct GNUNET_TUN_UdpHeader *) &ipp[1];
1820 /* sender did not strip ICMP payload? */
1821 GNUNET_break_op (0);
1822 return GNUNET_SYSERR;
1824 size += sizeof (struct GNUNET_TUN_IPv4Header) + 8;
1825 GNUNET_assert (8 == sizeof (struct GNUNET_TUN_UdpHeader));
1826 make_up_icmpv4_payload (ts, ipp, udp);
1829 case GNUNET_TUN_ICMPTYPE6_TIME_EXCEEDED:
1830 icmp->type = GNUNET_TUN_ICMPTYPE_TIME_EXCEEDED;
1832 struct GNUNET_TUN_IPv4Header *ipp = (struct GNUNET_TUN_IPv4Header *) &icmp[1];
1833 struct GNUNET_TUN_UdpHeader *udp = (struct GNUNET_TUN_UdpHeader *) &ipp[1];
1837 /* sender did not strip ICMP payload? */
1838 GNUNET_break_op (0);
1839 return GNUNET_SYSERR;
1841 size += sizeof (struct GNUNET_TUN_IPv4Header) + 8;
1842 GNUNET_assert (8 == sizeof (struct GNUNET_TUN_UdpHeader));
1843 make_up_icmpv4_payload (ts, ipp, udp);
1846 case GNUNET_TUN_ICMPTYPE6_PACKET_TOO_BIG:
1847 case GNUNET_TUN_ICMPTYPE6_PARAMETER_PROBLEM:
1848 GNUNET_STATISTICS_update (stats,
1849 gettext_noop ("# ICMPv6 packets dropped (impossible PT to v4)"),
1852 case GNUNET_TUN_ICMPTYPE6_ECHO_REQUEST:
1853 icmp->type = GNUNET_TUN_ICMPTYPE_ECHO_REQUEST;
1855 case GNUNET_TUN_ICMPTYPE6_ECHO_REPLY:
1856 icmp->type = GNUNET_TUN_ICMPTYPE_ECHO_REPLY;
1859 GNUNET_break_op (0);
1860 GNUNET_STATISTICS_update (stats,
1861 gettext_noop ("# ICMPv6 packets dropped (type not allowed)"),
1863 return GNUNET_SYSERR;
1868 GNUNET_break_op (0);
1869 return GNUNET_SYSERR;
1871 msg->size = htons (size);
1872 GNUNET_TUN_calculate_icmp_checksum (icmp,
1875 (void) GNUNET_HELPER_send (helper_handle,
1884 size_t size = sizeof (struct GNUNET_TUN_IPv6Header)
1885 + sizeof (struct GNUNET_TUN_IcmpHeader)
1886 + sizeof (struct GNUNET_MessageHeader) +
1887 sizeof (struct GNUNET_TUN_Layer2PacketHeader) +
1890 char buf[size + sizeof (struct GNUNET_TUN_IPv6Header) + 8] GNUNET_ALIGN;
1891 struct GNUNET_MessageHeader *msg = (struct GNUNET_MessageHeader *) buf;
1892 struct GNUNET_TUN_Layer2PacketHeader *tun = (struct GNUNET_TUN_Layer2PacketHeader*) &msg[1];
1893 struct GNUNET_TUN_IPv6Header *ipv6 = (struct GNUNET_TUN_IPv6Header *) &tun[1];
1894 struct GNUNET_TUN_IcmpHeader *icmp = (struct GNUNET_TUN_IcmpHeader *) &ipv6[1];
1895 msg->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
1896 tun->flags = htons (0);
1897 tun->proto = htons (ETH_P_IPV6);
1898 GNUNET_TUN_initialize_ipv6_header (ipv6,
1900 sizeof (struct GNUNET_TUN_IcmpHeader) + mlen,
1901 &ts->destination_ip.v6,
1903 *icmp = i2v->icmp_header;
1908 /* For some ICMP types, we need to adjust (make up) the payload here.
1909 Also, depending on the AF used on the other side, we have to
1910 do ICMP PT (translate ICMP types) */
1911 switch (ntohl (i2v->af))
1914 /* ICMP PT 4-to-6 and possibly making up payloads */
1917 case GNUNET_TUN_ICMPTYPE_ECHO_REPLY:
1918 icmp->type = GNUNET_TUN_ICMPTYPE6_ECHO_REPLY;
1920 case GNUNET_TUN_ICMPTYPE_ECHO_REQUEST:
1921 icmp->type = GNUNET_TUN_ICMPTYPE6_ECHO_REQUEST;
1923 case GNUNET_TUN_ICMPTYPE_DESTINATION_UNREACHABLE:
1924 icmp->type = GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE;
1926 struct GNUNET_TUN_IPv6Header *ipp = (struct GNUNET_TUN_IPv6Header *) &icmp[1];
1927 struct GNUNET_TUN_UdpHeader *udp = (struct GNUNET_TUN_UdpHeader *) &ipp[1];
1931 /* sender did not strip ICMP payload? */
1932 GNUNET_break_op (0);
1933 return GNUNET_SYSERR;
1935 size += sizeof (struct GNUNET_TUN_IPv6Header) + 8;
1936 GNUNET_assert (8 == sizeof (struct GNUNET_TUN_UdpHeader));
1937 make_up_icmpv6_payload (ts, ipp, udp);
1940 case GNUNET_TUN_ICMPTYPE_TIME_EXCEEDED:
1941 icmp->type = GNUNET_TUN_ICMPTYPE6_TIME_EXCEEDED;
1943 struct GNUNET_TUN_IPv6Header *ipp = (struct GNUNET_TUN_IPv6Header *) &icmp[1];
1944 struct GNUNET_TUN_UdpHeader *udp = (struct GNUNET_TUN_UdpHeader *) &ipp[1];
1948 /* sender did not strip ICMP payload? */
1949 GNUNET_break_op (0);
1950 return GNUNET_SYSERR;
1952 size += sizeof (struct GNUNET_TUN_IPv6Header) + 8;
1953 GNUNET_assert (8 == sizeof (struct GNUNET_TUN_UdpHeader));
1954 make_up_icmpv6_payload (ts, ipp, udp);
1957 case GNUNET_TUN_ICMPTYPE_SOURCE_QUENCH:
1958 GNUNET_STATISTICS_update (stats,
1959 gettext_noop ("# ICMPv4 packets dropped (impossible PT to v6)"),
1963 GNUNET_break_op (0);
1964 GNUNET_STATISTICS_update (stats,
1965 gettext_noop ("# ICMPv4 packets dropped (type not allowed)"),
1967 return GNUNET_SYSERR;
1974 case GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE:
1975 case GNUNET_TUN_ICMPTYPE6_TIME_EXCEEDED:
1976 case GNUNET_TUN_ICMPTYPE6_PACKET_TOO_BIG:
1977 case GNUNET_TUN_ICMPTYPE6_PARAMETER_PROBLEM:
1979 struct GNUNET_TUN_IPv6Header *ipp = (struct GNUNET_TUN_IPv6Header *) &icmp[1];
1980 struct GNUNET_TUN_UdpHeader *udp = (struct GNUNET_TUN_UdpHeader *) &ipp[1];
1984 /* sender did not strip ICMP payload? */
1985 GNUNET_break_op (0);
1986 return GNUNET_SYSERR;
1988 size += sizeof (struct GNUNET_TUN_IPv6Header) + 8;
1989 GNUNET_assert (8 == sizeof (struct GNUNET_TUN_UdpHeader));
1990 make_up_icmpv6_payload (ts, ipp, udp);
1993 case GNUNET_TUN_ICMPTYPE6_ECHO_REQUEST:
1996 GNUNET_break_op (0);
1997 GNUNET_STATISTICS_update (stats,
1998 gettext_noop ("# ICMPv6 packets dropped (type not allowed)"),
2000 return GNUNET_SYSERR;
2005 GNUNET_break_op (0);
2006 return GNUNET_SYSERR;
2008 msg->size = htons (size);
2009 GNUNET_TUN_calculate_icmp_checksum (icmp,
2011 (void) GNUNET_HELPER_send (helper_handle,
2021 GNUNET_CONTAINER_heap_update_cost (tunnel_heap,
2023 GNUNET_TIME_absolute_get ().abs_value_us);
2029 * We got a UDP packet back from the MESH tunnel. Pass it on to the
2030 * local virtual interface via the helper.
2032 * @param cls closure, NULL
2033 * @param tunnel connection to the other end
2034 * @param tunnel_ctx pointer to our 'struct TunnelState *'
2035 * @param message the actual message
2036 * @return #GNUNET_OK to keep the connection open,
2037 * #GNUNET_SYSERR to close it (signal serious error)
2040 receive_udp_back (void *cls,
2041 struct GNUNET_MESH_Tunnel *tunnel,
2043 const struct GNUNET_MessageHeader *message)
2045 struct TunnelState *ts = *tunnel_ctx;
2046 const struct GNUNET_EXIT_UdpReplyMessage *reply;
2049 GNUNET_STATISTICS_update (stats,
2050 gettext_noop ("# UDP packets received from mesh"),
2052 mlen = ntohs (message->size);
2053 if (mlen < sizeof (struct GNUNET_EXIT_UdpReplyMessage))
2055 GNUNET_break_op (0);
2056 return GNUNET_SYSERR;
2058 if (NULL == ts->heap_node)
2060 GNUNET_break_op (0);
2061 return GNUNET_SYSERR;
2063 if (AF_UNSPEC == ts->af)
2065 GNUNET_break_op (0);
2066 return GNUNET_SYSERR;
2068 reply = (const struct GNUNET_EXIT_UdpReplyMessage *) message;
2069 mlen -= sizeof (struct GNUNET_EXIT_UdpReplyMessage);
2071 char sbuf[INET6_ADDRSTRLEN];
2072 char dbuf[INET6_ADDRSTRLEN];
2074 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2075 "Received UDP reply from mesh, sending %u bytes from %s:%u -> %s:%u via TUN\n",
2076 (unsigned int) mlen,
2077 inet_ntop (ts->af, &ts->destination_ip, sbuf, sizeof (sbuf)),
2078 ts->destination_port,
2079 inet_ntop (ts->af, &ts->source_ip, dbuf, sizeof (dbuf)),
2086 size_t size = sizeof (struct GNUNET_TUN_IPv4Header)
2087 + sizeof (struct GNUNET_TUN_UdpHeader)
2088 + sizeof (struct GNUNET_MessageHeader) +
2089 sizeof (struct GNUNET_TUN_Layer2PacketHeader) +
2092 char buf[size] GNUNET_ALIGN;
2093 struct GNUNET_MessageHeader *msg = (struct GNUNET_MessageHeader *) buf;
2094 struct GNUNET_TUN_Layer2PacketHeader *tun = (struct GNUNET_TUN_Layer2PacketHeader*) &msg[1];
2095 struct GNUNET_TUN_IPv4Header *ipv4 = (struct GNUNET_TUN_IPv4Header *) &tun[1];
2096 struct GNUNET_TUN_UdpHeader *udp = (struct GNUNET_TUN_UdpHeader *) &ipv4[1];
2097 msg->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
2098 msg->size = htons (size);
2099 tun->flags = htons (0);
2100 tun->proto = htons (ETH_P_IPV4);
2101 GNUNET_TUN_initialize_ipv4_header (ipv4,
2103 sizeof (struct GNUNET_TUN_UdpHeader) + mlen,
2104 &ts->destination_ip.v4,
2106 if (0 == ntohs (reply->source_port))
2107 udp->source_port = htons (ts->destination_port);
2109 udp->source_port = reply->source_port;
2110 if (0 == ntohs (reply->destination_port))
2111 udp->destination_port = htons (ts->source_port);
2113 udp->destination_port = reply->destination_port;
2114 udp->len = htons (mlen + sizeof (struct GNUNET_TUN_UdpHeader));
2115 GNUNET_TUN_calculate_udp4_checksum (ipv4,
2122 (void) GNUNET_HELPER_send (helper_handle,
2131 size_t size = sizeof (struct GNUNET_TUN_IPv6Header)
2132 + sizeof (struct GNUNET_TUN_UdpHeader)
2133 + sizeof (struct GNUNET_MessageHeader) +
2134 sizeof (struct GNUNET_TUN_Layer2PacketHeader) +
2137 char buf[size] GNUNET_ALIGN;
2138 struct GNUNET_MessageHeader *msg = (struct GNUNET_MessageHeader *) buf;
2139 struct GNUNET_TUN_Layer2PacketHeader *tun = (struct GNUNET_TUN_Layer2PacketHeader*) &msg[1];
2140 struct GNUNET_TUN_IPv6Header *ipv6 = (struct GNUNET_TUN_IPv6Header *) &tun[1];
2141 struct GNUNET_TUN_UdpHeader *udp = (struct GNUNET_TUN_UdpHeader *) &ipv6[1];
2142 msg->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
2143 msg->size = htons (size);
2144 tun->flags = htons (0);
2145 tun->proto = htons (ETH_P_IPV6);
2146 GNUNET_TUN_initialize_ipv6_header (ipv6,
2148 sizeof (struct GNUNET_TUN_UdpHeader) + mlen,
2149 &ts->destination_ip.v6,
2151 if (0 == ntohs (reply->source_port))
2152 udp->source_port = htons (ts->destination_port);
2154 udp->source_port = reply->source_port;
2155 if (0 == ntohs (reply->destination_port))
2156 udp->destination_port = htons (ts->source_port);
2158 udp->destination_port = reply->destination_port;
2159 udp->len = htons (mlen + sizeof (struct GNUNET_TUN_UdpHeader));
2160 GNUNET_TUN_calculate_udp6_checksum (ipv6,
2166 (void) GNUNET_HELPER_send (helper_handle,
2176 GNUNET_CONTAINER_heap_update_cost (tunnel_heap,
2178 GNUNET_TIME_absolute_get ().abs_value_us);
2184 * We got a TCP packet back from the MESH tunnel. Pass it on to the
2185 * local virtual interface via the helper.
2187 * @param cls closure, NULL
2188 * @param tunnel connection to the other end
2189 * @param tunnel_ctx pointer to our `struct TunnelState *`
2190 * @param message the actual message
2191 * @return #GNUNET_OK to keep the connection open,
2192 * #GNUNET_SYSERR to close it (signal serious error)
2195 receive_tcp_back (void *cls,
2196 struct GNUNET_MESH_Tunnel *tunnel,
2198 const struct GNUNET_MessageHeader *message)
2200 struct TunnelState *ts = *tunnel_ctx;
2201 const struct GNUNET_EXIT_TcpDataMessage *data;
2204 GNUNET_STATISTICS_update (stats,
2205 gettext_noop ("# TCP packets received from mesh"),
2207 mlen = ntohs (message->size);
2208 if (mlen < sizeof (struct GNUNET_EXIT_TcpDataMessage))
2210 GNUNET_break_op (0);
2211 return GNUNET_SYSERR;
2213 if (NULL == ts->heap_node)
2215 GNUNET_break_op (0);
2216 return GNUNET_SYSERR;
2218 data = (const struct GNUNET_EXIT_TcpDataMessage *) message;
2219 mlen -= sizeof (struct GNUNET_EXIT_TcpDataMessage);
2221 char sbuf[INET6_ADDRSTRLEN];
2222 char dbuf[INET6_ADDRSTRLEN];
2224 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2225 "Received TCP reply from mesh, sending %u bytes from %s:%u -> %s:%u via TUN\n",
2226 (unsigned int) mlen,
2227 inet_ntop (ts->af, &ts->destination_ip, sbuf, sizeof (sbuf)),
2228 ts->destination_port,
2229 inet_ntop (ts->af, &ts->source_ip, dbuf, sizeof (dbuf)),
2232 if (data->tcp_header.off * 4 < sizeof (struct GNUNET_TUN_TcpHeader))
2234 GNUNET_break_op (0);
2235 return GNUNET_SYSERR;
2241 size_t size = sizeof (struct GNUNET_TUN_IPv4Header)
2242 + sizeof (struct GNUNET_TUN_TcpHeader)
2243 + sizeof (struct GNUNET_MessageHeader) +
2244 sizeof (struct GNUNET_TUN_Layer2PacketHeader) +
2247 char buf[size] GNUNET_ALIGN;
2248 struct GNUNET_MessageHeader *msg = (struct GNUNET_MessageHeader *) buf;
2249 struct GNUNET_TUN_Layer2PacketHeader *tun = (struct GNUNET_TUN_Layer2PacketHeader*) &msg[1];
2250 struct GNUNET_TUN_IPv4Header *ipv4 = (struct GNUNET_TUN_IPv4Header *) &tun[1];
2251 struct GNUNET_TUN_TcpHeader *tcp = (struct GNUNET_TUN_TcpHeader *) &ipv4[1];
2252 msg->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
2253 msg->size = htons (size);
2254 tun->flags = htons (0);
2255 tun->proto = htons (ETH_P_IPV4);
2256 GNUNET_TUN_initialize_ipv4_header (ipv4,
2258 sizeof (struct GNUNET_TUN_TcpHeader) + mlen,
2259 &ts->destination_ip.v4,
2261 *tcp = data->tcp_header;
2262 tcp->source_port = htons (ts->destination_port);
2263 tcp->destination_port = htons (ts->source_port);
2264 GNUNET_TUN_calculate_tcp4_checksum (ipv4,
2271 (void) GNUNET_HELPER_send (helper_handle,
2280 size_t size = sizeof (struct GNUNET_TUN_IPv6Header)
2281 + sizeof (struct GNUNET_TUN_TcpHeader)
2282 + sizeof (struct GNUNET_MessageHeader) +
2283 sizeof (struct GNUNET_TUN_Layer2PacketHeader) +
2286 char buf[size] GNUNET_ALIGN;
2287 struct GNUNET_MessageHeader *msg = (struct GNUNET_MessageHeader *) buf;
2288 struct GNUNET_TUN_Layer2PacketHeader *tun = (struct GNUNET_TUN_Layer2PacketHeader*) &msg[1];
2289 struct GNUNET_TUN_IPv6Header *ipv6 = (struct GNUNET_TUN_IPv6Header *) &tun[1];
2290 struct GNUNET_TUN_TcpHeader *tcp = (struct GNUNET_TUN_TcpHeader *) &ipv6[1];
2291 msg->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
2292 msg->size = htons (size);
2293 tun->flags = htons (0);
2294 tun->proto = htons (ETH_P_IPV6);
2295 GNUNET_TUN_initialize_ipv6_header (ipv6,
2297 sizeof (struct GNUNET_TUN_TcpHeader) + mlen,
2298 &ts->destination_ip.v6,
2300 *tcp = data->tcp_header;
2301 tcp->source_port = htons (ts->destination_port);
2302 tcp->destination_port = htons (ts->source_port);
2303 GNUNET_TUN_calculate_tcp6_checksum (ipv6,
2310 (void) GNUNET_HELPER_send (helper_handle,
2318 GNUNET_CONTAINER_heap_update_cost (tunnel_heap,
2320 GNUNET_TIME_absolute_get ().abs_value_us);
2326 * Allocate an IPv4 address from the range of the tunnel
2327 * for a new redirection.
2329 * @param v4 where to store the address
2330 * @return #GNUNET_OK on success,
2331 * #GNUNET_SYSERR on error
2334 allocate_v4_address (struct in_addr *v4)
2336 const char *ipv4addr = vpn_argv[4];
2337 const char *ipv4mask = vpn_argv[5];
2338 struct in_addr addr;
2339 struct in_addr mask;
2341 struct GNUNET_HashCode key;
2344 GNUNET_assert (1 == inet_pton (AF_INET, ipv4addr, &addr));
2345 GNUNET_assert (1 == inet_pton (AF_INET, ipv4mask, &mask));
2346 /* Given 192.168.0.1/255.255.0.0, we want a mask
2347 of '192.168.255.255', thus: */
2348 mask.s_addr = addr.s_addr | ~mask.s_addr;
2355 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
2356 _("Failed to find unallocated IPv4 address in VPN's range\n"));
2357 return GNUNET_SYSERR;
2359 /* Pick random IPv4 address within the subnet, except 'addr' or 'mask' itself */
2360 rnd.s_addr = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
2362 v4->s_addr = (addr.s_addr | rnd.s_addr) & mask.s_addr;
2363 get_destination_key_from_ip (AF_INET,
2367 while ( (GNUNET_YES ==
2368 GNUNET_CONTAINER_multihashmap_contains (destination_map,
2370 (v4->s_addr == addr.s_addr) ||
2371 (v4->s_addr == mask.s_addr) );
2377 * Allocate an IPv6 address from the range of the tunnel
2378 * for a new redirection.
2380 * @param v6 where to store the address
2381 * @return #GNUNET_OK on success,
2382 * #GNUNET_SYSERR on error
2385 allocate_v6_address (struct in6_addr *v6)
2387 const char *ipv6addr = vpn_argv[2];
2388 struct in6_addr addr;
2389 struct in6_addr mask;
2390 struct in6_addr rnd;
2392 struct GNUNET_HashCode key;
2395 GNUNET_assert (1 == inet_pton (AF_INET6, ipv6addr, &addr));
2396 GNUNET_assert (ipv6prefix < 128);
2397 /* Given ABCD::/96, we want a mask of 'ABCD::FFFF:FFFF,
2400 for (i=127;i>=ipv6prefix;i--)
2401 mask.s6_addr[i / 8] |= (1 << (i % 8));
2403 /* Pick random IPv6 address within the subnet, except 'addr' or 'mask' itself */
2410 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
2411 _("Failed to find unallocated IPv6 address in VPN's range\n"));
2412 return GNUNET_SYSERR;
2417 rnd.s6_addr[i] = (unsigned char) GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
2420 = (addr.s6_addr[i] | rnd.s6_addr[i]) & mask.s6_addr[i];
2422 get_destination_key_from_ip (AF_INET6,
2426 while ( (GNUNET_YES ==
2427 GNUNET_CONTAINER_multihashmap_contains (destination_map,
2431 sizeof (struct in6_addr))) ||
2434 sizeof (struct in6_addr))) );
2440 * Free resources occupied by a destination entry.
2442 * @param de entry to free
2445 free_destination_entry (struct DestinationEntry *de)
2447 struct DestinationTunnel *dt;
2449 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2450 "Cleaning up destination entry\n");
2451 GNUNET_STATISTICS_update (stats,
2452 gettext_noop ("# Active destinations"),
2454 while (NULL != (dt = de->dt_head))
2458 free_tunnel_state (dt->ts);
2459 GNUNET_assert (NULL == dt->ts);
2461 GNUNET_CONTAINER_DLL_remove (de->dt_head,
2466 if (NULL != de->heap_node)
2468 GNUNET_CONTAINER_heap_remove_node (de->heap_node);
2469 de->heap_node = NULL;
2470 GNUNET_assert (GNUNET_YES ==
2471 GNUNET_CONTAINER_multihashmap_remove (destination_map,
2480 * We have too many active destinations. Clean up the oldest destination.
2482 * @param except destination that must NOT be cleaned up, even if it is the oldest
2485 expire_destination (struct DestinationEntry *except)
2487 struct DestinationEntry *de;
2489 de = GNUNET_CONTAINER_heap_peek (destination_heap);
2490 GNUNET_assert (NULL != de);
2492 return; /* can't do this */
2493 free_destination_entry (de);
2498 * Allocate an IP address for the response.
2500 * @param result_af desired address family; set to the actual
2501 * address family; can initially be AF_UNSPEC if there
2502 * is no preference; will be set to AF_UNSPEC if the
2504 * @param addr set to either v4 or v6 depending on which
2505 * storage location was used; set to NULL if allocation failed
2506 * @param v4 storage space for an IPv4 address
2507 * @param v6 storage space for an IPv6 address
2508 * @return #GNUNET_OK normally, #GNUNET_SYSERR if `* result_af` was
2509 * an unsupported address family (not AF_INET, AF_INET6 or AF_UNSPEC)
2512 allocate_response_ip (int *result_af,
2515 struct in6_addr *v6)
2522 allocate_v4_address (v4))
2523 *result_af = AF_UNSPEC;
2529 allocate_v6_address (v6))
2530 *result_af = AF_UNSPEC;
2536 allocate_v4_address (v4))
2539 *result_af = AF_INET;
2541 else if (GNUNET_OK ==
2542 allocate_v6_address (v6))
2545 *result_af = AF_INET6;
2550 return GNUNET_SYSERR;
2557 * A client asks us to setup a redirection via some exit node to a
2558 * particular IP. Setup the redirection and give the client the
2562 * @param client requesting client
2563 * @param message redirection request (a `struct RedirectToIpRequestMessage`)
2566 service_redirect_to_ip (void *cls,
2567 struct GNUNET_SERVER_Client *client,
2568 const struct GNUNET_MessageHeader *message)
2572 const struct RedirectToIpRequestMessage *msg;
2578 struct DestinationEntry *de;
2579 struct GNUNET_HashCode key;
2581 /* validate and parse request */
2582 mlen = ntohs (message->size);
2583 if (mlen < sizeof (struct RedirectToIpRequestMessage))
2586 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2589 alen = mlen - sizeof (struct RedirectToIpRequestMessage);
2590 msg = (const struct RedirectToIpRequestMessage *) message;
2591 addr_af = (int) htonl (msg->addr_af);
2595 if (alen != sizeof (struct in_addr))
2598 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2603 if (alen != sizeof (struct in6_addr))
2606 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2612 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2616 /* allocate response IP */
2617 result_af = (int) htonl (msg->result_af);
2618 if (GNUNET_OK != allocate_response_ip (&result_af,
2622 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2625 /* send reply with our IP address */
2626 send_client_reply (client,
2630 if (result_af == AF_UNSPEC)
2632 /* failure, we're done */
2633 GNUNET_SERVER_receive_done (client, GNUNET_OK);
2638 char sbuf[INET6_ADDRSTRLEN];
2639 char dbuf[INET6_ADDRSTRLEN];
2641 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2642 "Allocated address %s for redirection via exit to %s\n",
2643 inet_ntop (result_af, addr, sbuf, sizeof (sbuf)),
2645 &msg[1], dbuf, sizeof (dbuf)));
2648 /* setup destination record */
2649 de = GNUNET_new (struct DestinationEntry);
2650 de->is_service = GNUNET_NO;
2651 de->details.exit_destination.af = addr_af;
2652 memcpy (&de->details.exit_destination.ip,
2655 get_destination_key_from_ip (result_af,
2659 GNUNET_assert (GNUNET_OK ==
2660 GNUNET_CONTAINER_multihashmap_put (destination_map,
2663 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE));
2664 de->heap_node = GNUNET_CONTAINER_heap_insert (destination_heap,
2666 GNUNET_TIME_absolute_ntoh (msg->expiration_time).abs_value_us);
2667 GNUNET_STATISTICS_update (stats,
2668 gettext_noop ("# Active destinations"),
2670 while (GNUNET_CONTAINER_multihashmap_size (destination_map) > max_destination_mappings)
2671 expire_destination (de);
2672 GNUNET_SERVER_receive_done (client, GNUNET_OK);
2677 * A client asks us to setup a redirection to a particular peer
2678 * offering a service. Setup the redirection and give the client the
2682 * @param client requesting client
2683 * @param message redirection request (a `struct RedirectToPeerRequestMessage`)
2686 service_redirect_to_service (void *cls,
2687 struct GNUNET_SERVER_Client *client,
2688 const struct GNUNET_MessageHeader *message)
2690 const struct RedirectToServiceRequestMessage *msg;
2695 struct DestinationEntry *de;
2696 struct GNUNET_HashCode key;
2697 struct TunnelState *ts;
2698 struct DestinationTunnel *dt;
2701 msg = (const struct RedirectToServiceRequestMessage *) message;
2703 /* allocate response IP */
2704 result_af = (int) htonl (msg->result_af);
2705 if (GNUNET_OK != allocate_response_ip (&result_af,
2709 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2712 send_client_reply (client,
2716 if (result_af == AF_UNSPEC)
2718 /* failure, we're done */
2719 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2720 _("Failed to allocate IP address for new destination\n"));
2721 GNUNET_SERVER_receive_done (client, GNUNET_OK);
2726 char sbuf[INET6_ADDRSTRLEN];
2728 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2729 "Allocated address %s for redirection to service %s on peer %s\n",
2730 inet_ntop (result_af, addr, sbuf, sizeof (sbuf)),
2731 GNUNET_h2s (&msg->service_descriptor),
2732 GNUNET_i2s (&msg->target));
2735 /* setup destination record */
2736 de = GNUNET_new (struct DestinationEntry);
2737 de->is_service = GNUNET_YES;
2738 de->details.service_destination.service_descriptor = msg->service_descriptor;
2739 de->details.service_destination.target = msg->target;
2740 get_destination_key_from_ip (result_af,
2744 GNUNET_assert (GNUNET_OK ==
2745 GNUNET_CONTAINER_multihashmap_put (destination_map,
2748 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE));
2749 de->heap_node = GNUNET_CONTAINER_heap_insert (destination_heap,
2751 GNUNET_TIME_absolute_ntoh (msg->expiration_time).abs_value_us);
2752 while (GNUNET_CONTAINER_multihashmap_size (destination_map) > max_destination_mappings)
2753 expire_destination (de);
2755 dt = GNUNET_new (struct DestinationTunnel);
2756 dt->destination = de;
2757 GNUNET_CONTAINER_DLL_insert (de->dt_head,
2760 ts = create_tunnel_to_destination (dt,
2765 ts->destination_ip.v4 = v4;
2768 ts->destination_ip.v6 = v6;
2774 GNUNET_SERVER_receive_done (client, GNUNET_OK);
2779 * Function called whenever a tunnel is destroyed. Should clean up
2780 * any associated state.
2782 * @param cls closure (set from #GNUNET_MESH_connect)
2783 * @param tunnel connection to the other end (henceforth invalid)
2784 * @param tunnel_ctx place where local state associated
2785 * with the tunnel is stored (our `struct TunnelState`)
2788 tunnel_cleaner (void *cls,
2789 const struct GNUNET_MESH_Tunnel *tunnel,
2792 struct TunnelState *ts = tunnel_ctx;
2794 ts->tunnel = NULL; /* we must not call GNUNET_MESH_tunnel_destroy() anymore */
2795 free_tunnel_state (ts);
2800 * Free memory occupied by an entry in the destination map.
2804 * @param value a `struct DestinationEntry *`
2805 * @return #GNUNET_OK (continue to iterate)
2808 cleanup_destination (void *cls,
2809 const struct GNUNET_HashCode *key,
2812 struct DestinationEntry *de = value;
2814 free_destination_entry (de);
2820 * Free memory occupied by an entry in the tunnel map.
2824 * @param value a `struct TunnelState *`
2825 * @return #GNUNET_OK (continue to iterate)
2828 cleanup_tunnel (void *cls,
2829 const struct GNUNET_HashCode *key,
2832 struct TunnelState *ts = value;
2834 free_tunnel_state (ts);
2840 * Function scheduled as very last function, cleans up after us
2847 const struct GNUNET_SCHEDULER_TaskContext *tc)
2851 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2852 "VPN is shutting down\n");
2853 if (NULL != destination_map)
2855 GNUNET_CONTAINER_multihashmap_iterate (destination_map,
2856 &cleanup_destination,
2858 GNUNET_CONTAINER_multihashmap_destroy (destination_map);
2859 destination_map = NULL;
2861 if (NULL != destination_heap)
2863 GNUNET_CONTAINER_heap_destroy (destination_heap);
2864 destination_heap = NULL;
2866 if (NULL != tunnel_map)
2868 GNUNET_CONTAINER_multihashmap_iterate (tunnel_map,
2871 GNUNET_CONTAINER_multihashmap_destroy (tunnel_map);
2874 if (NULL != tunnel_heap)
2876 GNUNET_CONTAINER_heap_destroy (tunnel_heap);
2879 if (NULL != mesh_handle)
2881 GNUNET_MESH_disconnect (mesh_handle);
2884 if (NULL != helper_handle)
2886 GNUNET_HELPER_stop (helper_handle, GNUNET_NO);
2887 helper_handle = NULL;
2891 GNUNET_SERVER_notification_context_destroy (nc);
2896 GNUNET_STATISTICS_destroy (stats, GNUNET_NO);
2900 GNUNET_free_non_null (vpn_argv[i]);
2905 * Main function that will be run by the scheduler.
2907 * @param cls closure
2908 * @param server the initialized server
2909 * @param cfg_ configuration
2913 struct GNUNET_SERVER_Handle *server,
2914 const struct GNUNET_CONFIGURATION_Handle *cfg_)
2916 static const struct GNUNET_SERVER_MessageHandler service_handlers[] = {
2917 /* callback, cls, type, size */
2918 { &service_redirect_to_ip, NULL, GNUNET_MESSAGE_TYPE_VPN_CLIENT_REDIRECT_TO_IP, 0},
2919 { &service_redirect_to_service, NULL,
2920 GNUNET_MESSAGE_TYPE_VPN_CLIENT_REDIRECT_TO_SERVICE,
2921 sizeof (struct RedirectToServiceRequestMessage) },
2924 static const struct GNUNET_MESH_MessageHandler mesh_handlers[] = {
2925 { &receive_udp_back, GNUNET_MESSAGE_TYPE_VPN_UDP_REPLY, 0},
2926 { &receive_tcp_back, GNUNET_MESSAGE_TYPE_VPN_TCP_DATA_TO_VPN, 0},
2927 { &receive_icmp_back, GNUNET_MESSAGE_TYPE_VPN_ICMP_TO_VPN, 0},
2939 binary = GNUNET_OS_get_libexec_binary_path ("gnunet-helper-vpn");
2942 GNUNET_OS_check_helper_binary (binary, GNUNET_YES, "-d gnunet-vpn - - 169.1.3.3.7 255.255.255.0")) //ipv4 only please!
2945 "`%s' is not SUID, refusing to run.\n",
2946 "gnunet-helper-vpn");
2947 GNUNET_free (binary);
2951 GNUNET_free (binary);
2953 stats = GNUNET_STATISTICS_create ("vpn", cfg);
2955 GNUNET_CONFIGURATION_get_value_number (cfg, "VPN", "MAX_MAPPING",
2956 &max_destination_mappings))
2957 max_destination_mappings = 200;
2959 GNUNET_CONFIGURATION_get_value_number (cfg, "VPN", "MAX_TUNNELS",
2960 &max_tunnel_mappings))
2961 max_tunnel_mappings = 200;
2963 destination_map = GNUNET_CONTAINER_multihashmap_create (max_destination_mappings * 2, GNUNET_NO);
2964 destination_heap = GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN);
2965 tunnel_map = GNUNET_CONTAINER_multihashmap_create (max_tunnel_mappings * 2, GNUNET_NO);
2966 tunnel_heap = GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN);
2969 vpn_argv[0] = GNUNET_strdup ("vpn-gnunet");
2970 if (GNUNET_SYSERR ==
2971 GNUNET_CONFIGURATION_get_value_string (cfg, "VPN", "IFNAME", &ifname))
2973 GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, "VPN", "IFNAME");
2974 GNUNET_SCHEDULER_shutdown ();
2977 vpn_argv[1] = ifname;
2978 if (GNUNET_OK == GNUNET_NETWORK_test_pf (PF_INET6))
2980 if ( (GNUNET_SYSERR ==
2981 GNUNET_CONFIGURATION_get_value_string (cfg, "VPN", "IPV6ADDR",
2983 (1 != inet_pton (AF_INET6, ipv6addr, &v6))) )
2985 GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, "VPN", "IPV6ADDR",
2986 _("Must specify valid IPv6 address"));
2987 GNUNET_SCHEDULER_shutdown ();
2990 vpn_argv[2] = ipv6addr;
2991 if (GNUNET_SYSERR ==
2992 GNUNET_CONFIGURATION_get_value_string (cfg, "VPN", "IPV6PREFIX",
2995 GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, "VPN", "IPV6PREFIX");
2996 GNUNET_SCHEDULER_shutdown ();
2999 vpn_argv[3] = ipv6prefix_s;
3001 GNUNET_CONFIGURATION_get_value_number (cfg, "VPN",
3004 (ipv6prefix >= 127) )
3006 GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, "VPN", "IPV4MASK",
3007 _("Must specify valid IPv6 mask"));
3008 GNUNET_SCHEDULER_shutdown ();
3014 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
3015 _("IPv6 support disabled as this system does not support IPv6\n"));
3016 vpn_argv[2] = GNUNET_strdup ("-");
3017 vpn_argv[3] = GNUNET_strdup ("-");
3019 if (GNUNET_OK == GNUNET_NETWORK_test_pf (PF_INET))
3021 if ( (GNUNET_SYSERR ==
3022 GNUNET_CONFIGURATION_get_value_string (cfg, "vpn", "IPV4ADDR",
3024 (1 != inet_pton (AF_INET, ipv4addr, &v4))) )
3026 GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, "VPN", "IPV4ADDR",
3027 _("Must specify valid IPv4 address"));
3028 GNUNET_SCHEDULER_shutdown ();
3031 vpn_argv[4] = ipv4addr;
3032 if ( (GNUNET_SYSERR ==
3033 GNUNET_CONFIGURATION_get_value_string (cfg, "vpn", "IPV4MASK",
3035 (1 != inet_pton (AF_INET, ipv4mask, &v4))) )
3037 GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, "VPN", "IPV4MASK",
3038 _("Must specify valid IPv4 mask"));
3039 GNUNET_SCHEDULER_shutdown ();
3042 vpn_argv[5] = ipv4mask;
3046 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
3047 _("IPv4 support disabled as this system does not support IPv4\n"));
3048 vpn_argv[4] = GNUNET_strdup ("-");
3049 vpn_argv[5] = GNUNET_strdup ("-");
3054 GNUNET_MESH_connect (cfg_, NULL,
3059 helper_handle = GNUNET_HELPER_start (GNUNET_NO,
3060 "gnunet-helper-vpn", vpn_argv,
3061 &message_token, NULL, NULL);
3062 nc = GNUNET_SERVER_notification_context_create (server, 1);
3063 GNUNET_SERVER_add_handlers (server, service_handlers);
3064 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &cleanup, cls);
3069 * The main function of the VPN service.
3071 * @param argc number of arguments from the command line
3072 * @param argv command line arguments
3073 * @return 0 ok, 1 on error
3076 main (int argc, char *const *argv)
3078 return (GNUNET_OK ==
3079 GNUNET_SERVICE_run (argc, argv, "vpn",
3080 GNUNET_SERVICE_OPTION_NONE,
3081 &run, NULL)) ? global_ret : 1;
3084 /* end of gnunet-service-vpn.c */