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 * Addess family used for this tunnel on the local TUN interface.
226 * Length of the doubly linked 'tmq_head/tmq_tail' list.
228 unsigned int tmq_length;
231 * IPPROTO_TCP or IPPROTO_UDP once bound.
236 * IP address of the source on our end, initially uninitialized.
241 * Address if af is AF_INET.
246 * Address if af is AF_INET6.
253 * Destination IP address used by the source on our end (this is the IP
254 * that we pick freely within the VPN's tunnel IP range).
259 * Address if af is AF_INET.
264 * Address if af is AF_INET6.
271 * Source port used by the sender on our end; 0 for uninitialized.
273 uint16_t source_port;
276 * Destination port used by the sender on our end; 0 for uninitialized.
278 uint16_t destination_port;
284 * Return value from 'main'.
286 static int global_ret;
289 * Configuration we use.
291 static const struct GNUNET_CONFIGURATION_Handle *cfg;
294 * Handle to the mesh service.
296 static struct GNUNET_MESH_Handle *mesh_handle;
299 * Map from IP address to destination information (possibly with a
300 * MESH tunnel handle for fast setup).
302 static struct GNUNET_CONTAINER_MultiHashMap *destination_map;
305 * Min-Heap sorted by activity time to expire old mappings.
307 static struct GNUNET_CONTAINER_Heap *destination_heap;
310 * Map from source and destination address (IP+port) to connection
311 * information (mostly with the respective MESH tunnel handle).
313 static struct GNUNET_CONTAINER_MultiHashMap *tunnel_map;
316 * Min-Heap sorted by activity time to expire old mappings; values are
317 * of type 'struct TunnelState'.
319 static struct GNUNET_CONTAINER_Heap *tunnel_heap;
324 static struct GNUNET_STATISTICS_Handle *stats;
327 * The handle to the VPN helper process "gnunet-helper-vpn".
329 static struct GNUNET_HELPER_Handle *helper_handle;
332 * Arguments to the vpn helper.
334 static char *vpn_argv[7];
337 * Length of the prefix of the VPN's IPv6 network.
339 static unsigned long long ipv6prefix;
342 * Notification context for sending replies to clients.
344 static struct GNUNET_SERVER_NotificationContext *nc;
347 * If there are more than this number of address-mappings, old ones
350 static unsigned long long max_destination_mappings;
353 * If there are more than this number of open tunnels, old ones
356 static unsigned long long max_tunnel_mappings;
360 * Compute the key under which we would store an entry in the
361 * destination_map for the given IP address.
363 * @param af address family (AF_INET or AF_INET6)
364 * @param address IP address, struct in_addr or struct in6_addr
365 * @param key where to store the key
368 get_destination_key_from_ip (int af,
370 struct GNUNET_HashCode *key)
375 GNUNET_CRYPTO_hash (address,
376 sizeof (struct in_addr),
380 GNUNET_CRYPTO_hash (address,
381 sizeof (struct in6_addr),
392 * Compute the key under which we would store an entry in the
393 * tunnel_map for the given socket address pair.
395 * @param af address family (AF_INET or AF_INET6)
396 * @param protocol IPPROTO_TCP or IPPROTO_UDP
397 * @param source_ip sender's source IP, struct in_addr or struct in6_addr
398 * @param source_port sender's source port
399 * @param destination_ip sender's destination IP, struct in_addr or struct in6_addr
400 * @param destination_port sender's destination port
401 * @param key where to store the key
404 get_tunnel_key_from_ips (int af,
406 const void *source_ip,
407 uint16_t source_port,
408 const void *destination_ip,
409 uint16_t destination_port,
410 struct GNUNET_HashCode *key)
414 memset (key, 0, sizeof (struct GNUNET_HashCode));
415 /* the GNUnet hashmap only uses the first sizeof(unsigned int) of the hash,
416 so we put the ports in there (and hope for few collisions) */
418 memcpy (off, &source_port, sizeof (uint16_t));
419 off += sizeof (uint16_t);
420 memcpy (off, &destination_port, sizeof (uint16_t));
421 off += sizeof (uint16_t);
425 memcpy (off, source_ip, sizeof (struct in_addr));
426 off += sizeof (struct in_addr);
427 memcpy (off, destination_ip, sizeof (struct in_addr));
428 off += sizeof (struct in_addr);
431 memcpy (off, source_ip, sizeof (struct in6_addr));
432 off += sizeof (struct in6_addr);
433 memcpy (off, destination_ip, sizeof (struct in6_addr));
434 off += sizeof (struct in6_addr);
440 memcpy (off, &protocol, sizeof (uint8_t));
441 /* off += sizeof (uint8_t); */
446 * Notify the client about the result of its request.
448 * @param client client to notify
449 * @param request_id original request ID to include in response
450 * @param result_af resulting address family
451 * @param addr resulting IP address
454 send_client_reply (struct GNUNET_SERVER_Client *client,
459 char buf[sizeof (struct RedirectToIpResponseMessage) + sizeof (struct in6_addr)] GNUNET_ALIGN;
460 struct RedirectToIpResponseMessage *res;
466 rlen = sizeof (struct in_addr);
469 rlen = sizeof (struct in6_addr);
478 res = (struct RedirectToIpResponseMessage *) buf;
479 res->header.size = htons (sizeof (struct RedirectToIpResponseMessage) + rlen);
480 res->header.type = htons (GNUNET_MESSAGE_TYPE_VPN_CLIENT_USE_IP);
481 res->result_af = htonl (result_af);
482 res->request_id = request_id;
483 memcpy (&res[1], addr, rlen);
484 GNUNET_SERVER_notification_context_add (nc, client);
485 GNUNET_SERVER_notification_context_unicast (nc,
493 * Free resources associated with a tunnel state.
495 * @param ts state to free
498 free_tunnel_state (struct TunnelState *ts)
500 struct GNUNET_HashCode key;
501 struct TunnelMessageQueueEntry *tnq;
502 struct GNUNET_MESH_Tunnel *tunnel;
504 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
505 "Cleaning up tunnel state\n");
506 GNUNET_STATISTICS_update (stats,
507 gettext_noop ("# Active tunnels"),
509 while (NULL != (tnq = ts->tmq_head))
511 GNUNET_CONTAINER_DLL_remove (ts->tmq_head,
517 GNUNET_assert (0 == ts->tmq_length);
520 GNUNET_MESH_notify_transmit_ready_cancel (ts->th);
523 GNUNET_assert (NULL == ts->destination.heap_node);
524 if (NULL != (tunnel = ts->tunnel))
527 GNUNET_MESH_tunnel_destroy (tunnel);
529 if (NULL != ts->search)
531 GNUNET_REGEX_search_cancel (ts->search);
534 if (NULL != ts->heap_node)
536 GNUNET_CONTAINER_heap_remove_node (ts->heap_node);
537 ts->heap_node = NULL;
538 get_tunnel_key_from_ips (ts->af,
543 ts->destination_port,
545 GNUNET_assert (GNUNET_YES ==
546 GNUNET_CONTAINER_multihashmap_remove (tunnel_map,
550 if (NULL != ts->destination_container)
552 GNUNET_assert (ts == ts->destination_container->ts);
553 ts->destination_container->ts = NULL;
554 ts->destination_container = NULL;
561 * Send a message from the message queue via mesh.
563 * @param cls the `struct TunnelState` with the message queue
564 * @param size number of bytes available in @a buf
565 * @param buf where to copy the message
566 * @return number of bytes copied to @a buf
569 send_to_peer_notify_callback (void *cls, size_t size, void *buf)
571 struct TunnelState *ts = cls;
572 struct TunnelMessageQueueEntry *tnq;
579 GNUNET_assert (NULL != tnq);
580 GNUNET_assert (size >= tnq->len);
581 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
582 "Sending %u bytes via mesh tunnel\n",
584 GNUNET_CONTAINER_DLL_remove (ts->tmq_head,
588 memcpy (buf, tnq->msg, tnq->len);
591 if (NULL != (tnq = ts->tmq_head))
592 ts->th = GNUNET_MESH_notify_transmit_ready (ts->tunnel,
593 GNUNET_NO /* cork */,
594 GNUNET_TIME_UNIT_FOREVER_REL,
596 &send_to_peer_notify_callback,
598 GNUNET_STATISTICS_update (stats,
599 gettext_noop ("# Bytes given to mesh for transmission"),
606 * Add the given message to the given tunnel and trigger the
607 * transmission process.
609 * @param tnq message to queue
610 * @param ts tunnel to queue the message for
613 send_to_tunnel (struct TunnelMessageQueueEntry *tnq,
614 struct TunnelState *ts)
616 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
617 "Queueing %u bytes for transmission via mesh tunnel\n",
619 GNUNET_assert (NULL != ts->tunnel);
620 GNUNET_CONTAINER_DLL_insert_tail (ts->tmq_head,
624 if (ts->tmq_length > MAX_MESSAGE_QUEUE_SIZE)
626 struct TunnelMessageQueueEntry *dq;
629 GNUNET_assert (dq != tnq);
630 GNUNET_CONTAINER_DLL_remove (ts->tmq_head,
634 GNUNET_MESH_notify_transmit_ready_cancel (ts->th);
636 GNUNET_STATISTICS_update (stats,
637 gettext_noop ("# Bytes dropped in mesh queue (overflow)"),
643 ts->th = GNUNET_MESH_notify_transmit_ready (ts->tunnel,
644 GNUNET_NO /* cork */,
645 GNUNET_TIME_UNIT_FOREVER_REL,
647 &send_to_peer_notify_callback,
653 * Regex has found a potential exit peer for us; consider using it.
655 * @param cls the 'struct TunnelState'
656 * @param id Peer providing a regex that matches the string.
657 * @param get_path Path of the get request.
658 * @param get_path_length Lenght of get_path.
659 * @param put_path Path of the put request.
660 * @param put_path_length Length of the put_path.
663 handle_regex_result (void *cls,
664 const struct GNUNET_PeerIdentity *id,
665 const struct GNUNET_PeerIdentity *get_path,
666 unsigned int get_path_length,
667 const struct GNUNET_PeerIdentity *put_path,
668 unsigned int put_path_length)
670 struct TunnelState *ts = cls;
672 GNUNET_REGEX_search_cancel (ts->search);
674 ts->tunnel = GNUNET_MESH_tunnel_create (mesh_handle,
684 * Initialize the given destination entry's mesh tunnel.
686 * @param de destination entry for which we need to setup a tunnel
687 * @param client_af address family of the address returned to the client
688 * @return tunnel state of the tunnel that was created
690 static struct TunnelState *
691 create_tunnel_to_destination (struct DestinationEntry *de,
694 struct TunnelState *ts;
696 GNUNET_STATISTICS_update (stats,
697 gettext_noop ("# Mesh tunnels created"),
699 GNUNET_assert (NULL == de->ts);
700 ts = GNUNET_new (struct TunnelState);
702 ts->destination = *de;
703 ts->destination.heap_node = NULL; /* copy is NOT in destination heap */
705 ts->destination_container = de; /* we are referenced from de */
708 ts->tunnel = GNUNET_MESH_tunnel_create (mesh_handle,
710 &de->details.service_destination.target,
714 if (NULL == ts->tunnel)
716 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
717 _("Failed to setup mesh tunnel!\n"));
721 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
722 "Creating tunnel to peer %s offering service %s\n",
723 GNUNET_i2s (&de->details.service_destination.target),
724 GNUNET_h2s (&de->details.service_destination.service_descriptor));
730 switch (de->details.exit_destination.af)
734 char address[GNUNET_TUN_IPV4_REGEXLEN];
736 GNUNET_TUN_ipv4toregexsearch (&de->details.exit_destination.ip.v4,
737 "255.255.255.255", address);
738 GNUNET_asprintf (&policy, "%s%s%s",
739 GNUNET_APPLICATION_TYPE_EXIT_REGEX_PREFIX,
746 char address[GNUNET_TUN_IPV6_REGEXLEN];
748 GNUNET_TUN_ipv6toregexsearch (&de->details.exit_destination.ip.v6,
750 GNUNET_asprintf (&policy, "%s%s%s",
751 GNUNET_APPLICATION_TYPE_EXIT_REGEX_PREFIX,
761 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
762 "Requesting connect by string: %s\n",
764 ts->search = GNUNET_REGEX_search (cfg,
766 &handle_regex_result,
768 GNUNET_free (policy);
775 * We have too many active tunnels. Clean up the oldest tunnel.
777 * @param except tunnel that must NOT be cleaned up, even if it is the oldest
780 expire_tunnel (struct TunnelState *except)
782 struct TunnelState *ts;
784 ts = GNUNET_CONTAINER_heap_peek (tunnel_heap);
785 GNUNET_assert (NULL != ts);
787 return; /* can't do this */
788 free_tunnel_state (ts);
793 * Route a packet via mesh to the given destination.
795 * @param destination description of the destination
796 * @param af address family on this end (AF_INET or AF_INET6)
797 * @param protocol IPPROTO_TCP or IPPROTO_UDP or IPPROTO_ICMP or IPPROTO_ICMPV6
798 * @param source_ip source IP used by the sender (struct in_addr or struct in6_addr)
799 * @param destination_ip destination IP used by the sender (struct in_addr or struct in6_addr)
800 * @param payload payload of the packet after the IP header
801 * @param payload_length number of bytes in payload
804 route_packet (struct DestinationEntry *destination,
807 const void *source_ip,
808 const void *destination_ip,
810 size_t payload_length)
812 struct GNUNET_HashCode key;
813 struct TunnelState *ts;
814 struct TunnelMessageQueueEntry *tnq;
818 const struct GNUNET_TUN_UdpHeader *udp;
819 const struct GNUNET_TUN_TcpHeader *tcp;
820 const struct GNUNET_TUN_IcmpHeader *icmp;
821 uint16_t source_port;
822 uint16_t destination_port;
828 if (payload_length < sizeof (struct GNUNET_TUN_UdpHeader))
834 tcp = NULL; /* make compiler happy */
835 icmp = NULL; /* make compiler happy */
837 if (udp->len < sizeof (struct GNUNET_TUN_UdpHeader))
842 source_port = ntohs (udp->source_port);
843 destination_port = ntohs (udp->destination_port);
844 get_tunnel_key_from_ips (af,
855 if (payload_length < sizeof (struct GNUNET_TUN_TcpHeader))
861 udp = NULL; /* make compiler happy */
862 icmp = NULL; /* make compiler happy */
864 if (tcp->off * 4 < sizeof (struct GNUNET_TUN_TcpHeader))
869 source_port = ntohs (tcp->source_port);
870 destination_port = ntohs (tcp->destination_port);
871 get_tunnel_key_from_ips (af,
883 if ( (AF_INET == af) ^ (protocol == IPPROTO_ICMP) )
888 if (payload_length < sizeof (struct GNUNET_TUN_IcmpHeader))
894 tcp = NULL; /* make compiler happy */
895 udp = NULL; /* make compiler happy */
898 destination_port = 0;
899 get_tunnel_key_from_ips (af,
909 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
910 _("Protocol %u not supported, dropping\n"),
911 (unsigned int) protocol);
915 if (! destination->is_service)
917 switch (destination->details.exit_destination.af)
920 alen = sizeof (struct in_addr);
923 alen = sizeof (struct in6_addr);
930 char sbuf[INET6_ADDRSTRLEN];
931 char dbuf[INET6_ADDRSTRLEN];
932 char xbuf[INET6_ADDRSTRLEN];
934 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
935 "Routing %s packet from %s:%u -> %s:%u to destination %s:%u\n",
936 (protocol == IPPROTO_TCP) ? "TCP" : "UDP",
937 inet_ntop (af, source_ip, sbuf, sizeof (sbuf)),
939 inet_ntop (af, destination_ip, dbuf, sizeof (dbuf)),
941 inet_ntop (destination->details.exit_destination.af,
942 &destination->details.exit_destination.ip,
943 xbuf, sizeof (xbuf)),
950 char sbuf[INET6_ADDRSTRLEN];
951 char dbuf[INET6_ADDRSTRLEN];
953 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
954 "Routing %s packet from %s:%u -> %s:%u to service %s at peer %s\n",
955 (protocol == IPPROTO_TCP) ? "TCP" : "UDP",
956 inet_ntop (af, source_ip, sbuf, sizeof (sbuf)),
958 inet_ntop (af, destination_ip, dbuf, sizeof (dbuf)),
960 GNUNET_h2s (&destination->details.service_destination.service_descriptor),
961 GNUNET_i2s (&destination->details.service_destination.target));
966 /* see if we have an existing tunnel for this destination */
967 ts = GNUNET_CONTAINER_multihashmap_get (tunnel_map,
971 /* need to either use the existing tunnel from the destination (if still
972 available) or create a fresh one */
974 if (NULL == destination->ts)
975 ts = create_tunnel_to_destination (destination, af);
977 ts = destination->ts;
980 destination->ts = NULL;
981 ts->destination_container = NULL; /* no longer 'contained' */
982 /* now bind existing "unbound" tunnel to our IP/port tuple */
983 ts->protocol = protocol;
987 ts->source_ip.v4 = * (const struct in_addr *) source_ip;
988 ts->destination_ip.v4 = * (const struct in_addr *) destination_ip;
992 ts->source_ip.v6 = * (const struct in6_addr *) source_ip;
993 ts->destination_ip.v6 = * (const struct in6_addr *) destination_ip;
995 ts->source_port = source_port;
996 ts->destination_port = destination_port;
997 ts->heap_node = GNUNET_CONTAINER_heap_insert (tunnel_heap,
999 GNUNET_TIME_absolute_get ().abs_value_us);
1000 GNUNET_assert (GNUNET_YES ==
1001 GNUNET_CONTAINER_multihashmap_put (tunnel_map,
1004 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
1005 GNUNET_STATISTICS_update (stats,
1006 gettext_noop ("# Active tunnels"),
1008 while (GNUNET_CONTAINER_multihashmap_size (tunnel_map) > max_tunnel_mappings)
1014 GNUNET_CONTAINER_heap_update_cost (tunnel_heap,
1016 GNUNET_TIME_absolute_get ().abs_value_us);
1018 GNUNET_assert (NULL != ts->tunnel);
1020 /* send via tunnel */
1024 if (destination->is_service)
1026 struct GNUNET_EXIT_UdpServiceMessage *usm;
1028 mlen = sizeof (struct GNUNET_EXIT_UdpServiceMessage) +
1029 payload_length - sizeof (struct GNUNET_TUN_UdpHeader);
1030 if (mlen >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1035 tnq = GNUNET_malloc (sizeof (struct TunnelMessageQueueEntry) + mlen);
1038 usm = (struct GNUNET_EXIT_UdpServiceMessage *) &tnq[1];
1039 usm->header.size = htons ((uint16_t) mlen);
1040 usm->header.type = htons (GNUNET_MESSAGE_TYPE_VPN_UDP_TO_SERVICE);
1041 /* if the source port is below 32000, we assume it has a special
1042 meaning; if not, we pick a random port (this is a heuristic) */
1043 usm->source_port = (ntohs (udp->source_port) < 32000) ? udp->source_port : 0;
1044 usm->destination_port = udp->destination_port;
1045 usm->service_descriptor = destination->details.service_destination.service_descriptor;
1048 payload_length - sizeof (struct GNUNET_TUN_UdpHeader));
1052 struct GNUNET_EXIT_UdpInternetMessage *uim;
1053 struct in_addr *ip4dst;
1054 struct in6_addr *ip6dst;
1057 mlen = sizeof (struct GNUNET_EXIT_UdpInternetMessage) +
1058 alen + payload_length - sizeof (struct GNUNET_TUN_UdpHeader);
1059 if (mlen >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1064 tnq = GNUNET_malloc (sizeof (struct TunnelMessageQueueEntry) +
1068 uim = (struct GNUNET_EXIT_UdpInternetMessage *) &tnq[1];
1069 uim->header.size = htons ((uint16_t) mlen);
1070 uim->header.type = htons (GNUNET_MESSAGE_TYPE_VPN_UDP_TO_INTERNET);
1071 uim->af = htonl (destination->details.exit_destination.af);
1072 uim->source_port = (ntohs (udp->source_port) < 32000) ? udp->source_port : 0;
1073 uim->destination_port = udp->destination_port;
1074 switch (destination->details.exit_destination.af)
1077 ip4dst = (struct in_addr *) &uim[1];
1078 *ip4dst = destination->details.exit_destination.ip.v4;
1079 payload = &ip4dst[1];
1082 ip6dst = (struct in6_addr *) &uim[1];
1083 *ip6dst = destination->details.exit_destination.ip.v6;
1084 payload = &ip6dst[1];
1091 payload_length - sizeof (struct GNUNET_TUN_UdpHeader));
1097 if (destination->is_service)
1099 struct GNUNET_EXIT_TcpServiceStartMessage *tsm;
1101 mlen = sizeof (struct GNUNET_EXIT_TcpServiceStartMessage) +
1102 payload_length - sizeof (struct GNUNET_TUN_TcpHeader);
1103 if (mlen >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1108 tnq = GNUNET_malloc (sizeof (struct TunnelMessageQueueEntry) + mlen);
1111 tsm = (struct GNUNET_EXIT_TcpServiceStartMessage *) &tnq[1];
1112 tsm->header.size = htons ((uint16_t) mlen);
1113 tsm->header.type = htons (GNUNET_MESSAGE_TYPE_VPN_TCP_TO_SERVICE_START);
1114 tsm->reserved = htonl (0);
1115 tsm->service_descriptor = destination->details.service_destination.service_descriptor;
1116 tsm->tcp_header = *tcp;
1119 payload_length - sizeof (struct GNUNET_TUN_TcpHeader));
1123 struct GNUNET_EXIT_TcpInternetStartMessage *tim;
1124 struct in_addr *ip4dst;
1125 struct in6_addr *ip6dst;
1128 mlen = sizeof (struct GNUNET_EXIT_TcpInternetStartMessage) +
1129 alen + payload_length - sizeof (struct GNUNET_TUN_TcpHeader);
1130 if (mlen >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1135 tnq = GNUNET_malloc (sizeof (struct TunnelMessageQueueEntry) + mlen);
1138 tim = (struct GNUNET_EXIT_TcpInternetStartMessage *) &tnq[1];
1139 tim->header.size = htons ((uint16_t) mlen);
1140 tim->header.type = htons (GNUNET_MESSAGE_TYPE_VPN_TCP_TO_INTERNET_START);
1141 tim->af = htonl (destination->details.exit_destination.af);
1142 tim->tcp_header = *tcp;
1143 switch (destination->details.exit_destination.af)
1146 ip4dst = (struct in_addr *) &tim[1];
1147 *ip4dst = destination->details.exit_destination.ip.v4;
1148 payload = &ip4dst[1];
1151 ip6dst = (struct in6_addr *) &tim[1];
1152 *ip6dst = destination->details.exit_destination.ip.v6;
1153 payload = &ip6dst[1];
1160 payload_length - sizeof (struct GNUNET_TUN_TcpHeader));
1165 struct GNUNET_EXIT_TcpDataMessage *tdm;
1167 mlen = sizeof (struct GNUNET_EXIT_TcpDataMessage) +
1168 payload_length - sizeof (struct GNUNET_TUN_TcpHeader);
1169 if (mlen >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1174 tnq = GNUNET_malloc (sizeof (struct TunnelMessageQueueEntry) + mlen);
1177 tdm = (struct GNUNET_EXIT_TcpDataMessage *) &tnq[1];
1178 tdm->header.size = htons ((uint16_t) mlen);
1179 tdm->header.type = htons (GNUNET_MESSAGE_TYPE_VPN_TCP_DATA_TO_EXIT);
1180 tdm->reserved = htonl (0);
1181 tdm->tcp_header = *tcp;
1184 payload_length - sizeof (struct GNUNET_TUN_TcpHeader));
1188 case IPPROTO_ICMPV6:
1189 if (destination->is_service)
1191 struct GNUNET_EXIT_IcmpServiceMessage *ism;
1193 mlen = sizeof (struct GNUNET_EXIT_IcmpServiceMessage) +
1194 payload_length - sizeof (struct GNUNET_TUN_IcmpHeader);
1195 if (mlen >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1200 tnq = GNUNET_malloc (sizeof (struct TunnelMessageQueueEntry) + mlen);
1202 ism = (struct GNUNET_EXIT_IcmpServiceMessage *) &tnq[1];
1203 ism->header.type = htons (GNUNET_MESSAGE_TYPE_VPN_ICMP_TO_SERVICE);
1204 ism->af = htonl (af); /* need to tell destination ICMP protocol family! */
1205 ism->service_descriptor = destination->details.service_destination.service_descriptor;
1206 ism->icmp_header = *icmp;
1207 /* ICMP protocol translation will be done by the receiver (as we don't know
1208 the target AF); however, we still need to possibly discard the payload
1209 depending on the ICMP type */
1215 case GNUNET_TUN_ICMPTYPE_ECHO_REPLY:
1216 case GNUNET_TUN_ICMPTYPE_ECHO_REQUEST:
1218 case GNUNET_TUN_ICMPTYPE_DESTINATION_UNREACHABLE:
1219 case GNUNET_TUN_ICMPTYPE_SOURCE_QUENCH:
1220 case GNUNET_TUN_ICMPTYPE_TIME_EXCEEDED:
1221 /* throw away ICMP payload, won't be useful for the other side anyway */
1222 payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
1225 GNUNET_STATISTICS_update (stats,
1226 gettext_noop ("# ICMPv4 packets dropped (not allowed)"),
1230 /* end of AF_INET */
1235 case GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE:
1236 case GNUNET_TUN_ICMPTYPE6_PACKET_TOO_BIG:
1237 case GNUNET_TUN_ICMPTYPE6_TIME_EXCEEDED:
1238 case GNUNET_TUN_ICMPTYPE6_PARAMETER_PROBLEM:
1239 /* throw away ICMP payload, won't be useful for the other side anyway */
1240 payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
1242 case GNUNET_TUN_ICMPTYPE6_ECHO_REQUEST:
1243 case GNUNET_TUN_ICMPTYPE6_ECHO_REPLY:
1246 GNUNET_STATISTICS_update (stats,
1247 gettext_noop ("# ICMPv6 packets dropped (not allowed)"),
1251 /* end of AF_INET6 */
1258 /* update length calculations, as payload_length may have changed */
1259 mlen = sizeof (struct GNUNET_EXIT_IcmpServiceMessage) +
1260 alen + payload_length - sizeof (struct GNUNET_TUN_IcmpHeader);
1262 ism->header.size = htons ((uint16_t) mlen);
1263 /* finally, copy payload (if there is any left...) */
1266 payload_length - sizeof (struct GNUNET_TUN_IcmpHeader));
1270 struct GNUNET_EXIT_IcmpInternetMessage *iim;
1271 struct in_addr *ip4dst;
1272 struct in6_addr *ip6dst;
1275 mlen = sizeof (struct GNUNET_EXIT_IcmpInternetMessage) +
1276 alen + payload_length - sizeof (struct GNUNET_TUN_IcmpHeader);
1277 if (mlen >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1282 tnq = GNUNET_malloc (sizeof (struct TunnelMessageQueueEntry) +
1285 iim = (struct GNUNET_EXIT_IcmpInternetMessage *) &tnq[1];
1286 iim->header.type = htons (GNUNET_MESSAGE_TYPE_VPN_ICMP_TO_INTERNET);
1287 iim->icmp_header = *icmp;
1288 /* Perform ICMP protocol-translation (depending on destination AF and source AF)
1289 and throw away ICMP payload depending on ICMP message type */
1295 case GNUNET_TUN_ICMPTYPE_ECHO_REPLY:
1296 if (destination->details.exit_destination.af == AF_INET6)
1297 iim->icmp_header.type = GNUNET_TUN_ICMPTYPE6_ECHO_REPLY;
1299 case GNUNET_TUN_ICMPTYPE_ECHO_REQUEST:
1300 if (destination->details.exit_destination.af == AF_INET6)
1301 iim->icmp_header.type = GNUNET_TUN_ICMPTYPE6_ECHO_REQUEST;
1303 case GNUNET_TUN_ICMPTYPE_DESTINATION_UNREACHABLE:
1304 if (destination->details.exit_destination.af == AF_INET6)
1305 iim->icmp_header.type = GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE;
1306 /* throw away IP-payload, exit will have to make it up anyway */
1307 payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
1309 case GNUNET_TUN_ICMPTYPE_TIME_EXCEEDED:
1310 if (destination->details.exit_destination.af == AF_INET6)
1311 iim->icmp_header.type = GNUNET_TUN_ICMPTYPE6_TIME_EXCEEDED;
1312 /* throw away IP-payload, exit will have to make it up anyway */
1313 payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
1315 case GNUNET_TUN_ICMPTYPE_SOURCE_QUENCH:
1316 if (destination->details.exit_destination.af == AF_INET6)
1318 GNUNET_STATISTICS_update (stats,
1319 gettext_noop ("# ICMPv4 packets dropped (impossible PT to v6)"),
1324 /* throw away IP-payload, exit will have to make it up anyway */
1325 payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
1328 GNUNET_STATISTICS_update (stats,
1329 gettext_noop ("# ICMPv4 packets dropped (type not allowed)"),
1334 /* end of AF_INET */
1339 case GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE:
1340 if (destination->details.exit_destination.af == AF_INET6)
1341 iim->icmp_header.type = GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE;
1342 /* throw away IP-payload, exit will have to make it up anyway */
1343 payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
1345 case GNUNET_TUN_ICMPTYPE6_TIME_EXCEEDED:
1346 if (destination->details.exit_destination.af == AF_INET)
1347 iim->icmp_header.type = GNUNET_TUN_ICMPTYPE_TIME_EXCEEDED;
1348 /* throw away IP-payload, exit will have to make it up anyway */
1349 payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
1351 case GNUNET_TUN_ICMPTYPE6_PACKET_TOO_BIG:
1352 if (destination->details.exit_destination.af == AF_INET)
1354 GNUNET_STATISTICS_update (stats,
1355 gettext_noop ("# ICMPv6 packets dropped (impossible PT to v4)"),
1360 /* throw away IP-payload, exit will have to make it up anyway */
1361 payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
1363 case GNUNET_TUN_ICMPTYPE6_PARAMETER_PROBLEM:
1364 if (destination->details.exit_destination.af == AF_INET)
1366 GNUNET_STATISTICS_update (stats,
1367 gettext_noop ("# ICMPv6 packets dropped (impossible PT to v4)"),
1372 /* throw away IP-payload, exit will have to make it up anyway */
1373 payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
1375 case GNUNET_TUN_ICMPTYPE6_ECHO_REQUEST:
1376 if (destination->details.exit_destination.af == AF_INET)
1377 iim->icmp_header.type = GNUNET_TUN_ICMPTYPE_ECHO_REQUEST;
1379 case GNUNET_TUN_ICMPTYPE6_ECHO_REPLY:
1380 if (destination->details.exit_destination.af == AF_INET)
1381 iim->icmp_header.type = GNUNET_TUN_ICMPTYPE_ECHO_REPLY;
1384 GNUNET_STATISTICS_update (stats,
1385 gettext_noop ("# ICMPv6 packets dropped (type not allowed)"),
1390 /* end of AF_INET6 */
1395 /* update length calculations, as payload_length may have changed */
1396 mlen = sizeof (struct GNUNET_EXIT_IcmpInternetMessage) +
1397 alen + payload_length - sizeof (struct GNUNET_TUN_IcmpHeader);
1399 iim->header.size = htons ((uint16_t) mlen);
1401 /* need to tell destination ICMP protocol family! */
1402 iim->af = htonl (destination->details.exit_destination.af);
1403 switch (destination->details.exit_destination.af)
1406 ip4dst = (struct in_addr *) &iim[1];
1407 *ip4dst = destination->details.exit_destination.ip.v4;
1408 payload = &ip4dst[1];
1411 ip6dst = (struct in6_addr *) &iim[1];
1412 *ip6dst = destination->details.exit_destination.ip.v6;
1413 payload = &ip6dst[1];
1420 payload_length - sizeof (struct GNUNET_TUN_IcmpHeader));
1424 /* not supported above, how can we get here !? */
1428 send_to_tunnel (tnq, ts);
1433 * Receive packets from the helper-process (someone send to the local
1434 * virtual tunnel interface). Find the destination mapping, and if it
1435 * exists, identify the correct MESH tunnel (or possibly create it)
1436 * and forward the packet.
1438 * @param cls closure, NULL
1439 * @param client NULL
1440 * @param message message we got from the client (VPN tunnel interface)
1443 message_token (void *cls GNUNET_UNUSED, void *client GNUNET_UNUSED,
1444 const struct GNUNET_MessageHeader *message)
1446 const struct GNUNET_TUN_Layer2PacketHeader *tun;
1448 struct GNUNET_HashCode key;
1449 struct DestinationEntry *de;
1451 GNUNET_STATISTICS_update (stats,
1452 gettext_noop ("# Packets received from TUN interface"),
1454 mlen = ntohs (message->size);
1455 if ( (ntohs (message->type) != GNUNET_MESSAGE_TYPE_VPN_HELPER) ||
1456 (mlen < sizeof (struct GNUNET_MessageHeader) + sizeof (struct GNUNET_TUN_Layer2PacketHeader)) )
1461 tun = (const struct GNUNET_TUN_Layer2PacketHeader *) &message[1];
1462 mlen -= (sizeof (struct GNUNET_MessageHeader) + sizeof (struct GNUNET_TUN_Layer2PacketHeader));
1463 switch (ntohs (tun->proto))
1467 const struct GNUNET_TUN_IPv6Header *pkt6;
1469 if (mlen < sizeof (struct GNUNET_TUN_IPv6Header))
1475 pkt6 = (const struct GNUNET_TUN_IPv6Header *) &tun[1];
1476 get_destination_key_from_ip (AF_INET6,
1477 &pkt6->destination_address,
1479 de = GNUNET_CONTAINER_multihashmap_get (destination_map, &key);
1482 char buf[INET6_ADDRSTRLEN];
1484 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1485 _("Packet received for unmapped destination `%s' (dropping it)\n"),
1486 inet_ntop (AF_INET6,
1487 &pkt6->destination_address,
1495 &pkt6->source_address,
1496 &pkt6->destination_address,
1498 mlen - sizeof (struct GNUNET_TUN_IPv6Header));
1503 struct GNUNET_TUN_IPv4Header *pkt4;
1505 if (mlen < sizeof (struct GNUNET_TUN_IPv4Header))
1511 pkt4 = (struct GNUNET_TUN_IPv4Header *) &tun[1];
1512 get_destination_key_from_ip (AF_INET,
1513 &pkt4->destination_address,
1515 de = GNUNET_CONTAINER_multihashmap_get (destination_map, &key);
1518 char buf[INET_ADDRSTRLEN];
1520 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1521 _("Packet received for unmapped destination `%s' (dropping it)\n"),
1523 &pkt4->destination_address,
1528 if (pkt4->header_length * 4 != sizeof (struct GNUNET_TUN_IPv4Header))
1530 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1531 _("Received IPv4 packet with options (dropping it)\n"));
1537 &pkt4->source_address,
1538 &pkt4->destination_address,
1540 mlen - sizeof (struct GNUNET_TUN_IPv4Header));
1544 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1545 _("Received packet of unknown protocol %d from TUN (dropping it)\n"),
1546 (unsigned int) ntohs (tun->proto));
1554 * Synthesize a plausible ICMP payload for an ICMP error
1555 * response on the given tunnel.
1557 * @param ts tunnel information
1558 * @param ipp IPv4 header to fill in (ICMP payload)
1559 * @param udp "UDP" header to fill in (ICMP payload); might actually
1560 * also be the first 8 bytes of the TCP header
1563 make_up_icmpv4_payload (struct TunnelState *ts,
1564 struct GNUNET_TUN_IPv4Header *ipp,
1565 struct GNUNET_TUN_UdpHeader *udp)
1567 GNUNET_TUN_initialize_ipv4_header (ipp,
1569 sizeof (struct GNUNET_TUN_TcpHeader),
1571 &ts->destination_ip.v4);
1572 udp->source_port = htons (ts->source_port);
1573 udp->destination_port = htons (ts->destination_port);
1574 udp->len = htons (0);
1575 udp->crc = htons (0);
1580 * Synthesize a plausible ICMP payload for an ICMP error
1581 * response on the given tunnel.
1583 * @param ts tunnel information
1584 * @param ipp IPv6 header to fill in (ICMP payload)
1585 * @param udp "UDP" header to fill in (ICMP payload); might actually
1586 * also be the first 8 bytes of the TCP header
1589 make_up_icmpv6_payload (struct TunnelState *ts,
1590 struct GNUNET_TUN_IPv6Header *ipp,
1591 struct GNUNET_TUN_UdpHeader *udp)
1593 GNUNET_TUN_initialize_ipv6_header (ipp,
1595 sizeof (struct GNUNET_TUN_TcpHeader),
1597 &ts->destination_ip.v6);
1598 udp->source_port = htons (ts->source_port);
1599 udp->destination_port = htons (ts->destination_port);
1600 udp->len = htons (0);
1601 udp->crc = htons (0);
1606 * We got an ICMP packet back from the MESH tunnel. Pass it on to the
1607 * local virtual interface via the helper.
1609 * @param cls closure, NULL
1610 * @param tunnel connection to the other end
1611 * @param tunnel_ctx pointer to our 'struct TunnelState *'
1612 * @param message the actual message
1613 * @return #GNUNET_OK to keep the connection open,
1614 * #GNUNET_SYSERR to close it (signal serious error)
1617 receive_icmp_back (void *cls GNUNET_UNUSED, struct GNUNET_MESH_Tunnel *tunnel,
1619 const struct GNUNET_MessageHeader *message)
1621 struct TunnelState *ts = *tunnel_ctx;
1622 const struct GNUNET_EXIT_IcmpToVPNMessage *i2v;
1625 GNUNET_STATISTICS_update (stats,
1626 gettext_noop ("# ICMP packets received from mesh"),
1628 mlen = ntohs (message->size);
1629 if (mlen < sizeof (struct GNUNET_EXIT_IcmpToVPNMessage))
1631 GNUNET_break_op (0);
1632 return GNUNET_SYSERR;
1634 if (NULL == ts->heap_node)
1636 GNUNET_break_op (0);
1637 return GNUNET_SYSERR;
1639 if (AF_UNSPEC == ts->af)
1641 GNUNET_break_op (0);
1642 return GNUNET_SYSERR;
1644 i2v = (const struct GNUNET_EXIT_IcmpToVPNMessage *) message;
1645 mlen -= sizeof (struct GNUNET_EXIT_IcmpToVPNMessage);
1647 char sbuf[INET6_ADDRSTRLEN];
1648 char dbuf[INET6_ADDRSTRLEN];
1650 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1651 "Received ICMP packet from mesh, sending %u bytes from %s -> %s via TUN\n",
1652 (unsigned int) mlen,
1653 inet_ntop (ts->af, &ts->destination_ip, sbuf, sizeof (sbuf)),
1654 inet_ntop (ts->af, &ts->source_ip, dbuf, sizeof (dbuf)));
1660 size_t size = sizeof (struct GNUNET_TUN_IPv4Header)
1661 + sizeof (struct GNUNET_TUN_IcmpHeader)
1662 + sizeof (struct GNUNET_MessageHeader) +
1663 sizeof (struct GNUNET_TUN_Layer2PacketHeader) +
1666 /* reserve some extra space in case we have an ICMP type here where
1667 we will need to make up the payload ourselves */
1668 char buf[size + sizeof (struct GNUNET_TUN_IPv4Header) + 8] GNUNET_ALIGN;
1669 struct GNUNET_MessageHeader *msg = (struct GNUNET_MessageHeader *) buf;
1670 struct GNUNET_TUN_Layer2PacketHeader *tun = (struct GNUNET_TUN_Layer2PacketHeader*) &msg[1];
1671 struct GNUNET_TUN_IPv4Header *ipv4 = (struct GNUNET_TUN_IPv4Header *) &tun[1];
1672 struct GNUNET_TUN_IcmpHeader *icmp = (struct GNUNET_TUN_IcmpHeader *) &ipv4[1];
1673 msg->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
1674 tun->flags = htons (0);
1675 tun->proto = htons (ETH_P_IPV4);
1676 GNUNET_TUN_initialize_ipv4_header (ipv4,
1678 sizeof (struct GNUNET_TUN_IcmpHeader) + mlen,
1679 &ts->destination_ip.v4,
1681 *icmp = i2v->icmp_header;
1685 /* For some ICMP types, we need to adjust (make up) the payload here.
1686 Also, depending on the AF used on the other side, we have to
1687 do ICMP PT (translate ICMP types) */
1688 switch (ntohl (i2v->af))
1693 case GNUNET_TUN_ICMPTYPE_ECHO_REPLY:
1694 case GNUNET_TUN_ICMPTYPE_ECHO_REQUEST:
1696 case GNUNET_TUN_ICMPTYPE_DESTINATION_UNREACHABLE:
1697 case GNUNET_TUN_ICMPTYPE_SOURCE_QUENCH:
1698 case GNUNET_TUN_ICMPTYPE_TIME_EXCEEDED:
1700 struct GNUNET_TUN_IPv4Header *ipp = (struct GNUNET_TUN_IPv4Header *) &icmp[1];
1701 struct GNUNET_TUN_UdpHeader *udp = (struct GNUNET_TUN_UdpHeader *) &ipp[1];
1705 /* sender did not strip ICMP payload? */
1706 GNUNET_break_op (0);
1707 return GNUNET_SYSERR;
1709 size += sizeof (struct GNUNET_TUN_IPv4Header) + 8;
1710 GNUNET_assert (8 == sizeof (struct GNUNET_TUN_UdpHeader));
1711 make_up_icmpv4_payload (ts, ipp, udp);
1715 GNUNET_break_op (0);
1716 GNUNET_STATISTICS_update (stats,
1717 gettext_noop ("# ICMPv4 packets dropped (type not allowed)"),
1719 return GNUNET_SYSERR;
1724 /* ICMP PT 6-to-4 and possibly making up payloads */
1727 case GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE:
1728 icmp->type = GNUNET_TUN_ICMPTYPE_DESTINATION_UNREACHABLE;
1730 struct GNUNET_TUN_IPv4Header *ipp = (struct GNUNET_TUN_IPv4Header *) &icmp[1];
1731 struct GNUNET_TUN_UdpHeader *udp = (struct GNUNET_TUN_UdpHeader *) &ipp[1];
1735 /* sender did not strip ICMP payload? */
1736 GNUNET_break_op (0);
1737 return GNUNET_SYSERR;
1739 size += sizeof (struct GNUNET_TUN_IPv4Header) + 8;
1740 GNUNET_assert (8 == sizeof (struct GNUNET_TUN_UdpHeader));
1741 make_up_icmpv4_payload (ts, ipp, udp);
1744 case GNUNET_TUN_ICMPTYPE6_TIME_EXCEEDED:
1745 icmp->type = GNUNET_TUN_ICMPTYPE_TIME_EXCEEDED;
1747 struct GNUNET_TUN_IPv4Header *ipp = (struct GNUNET_TUN_IPv4Header *) &icmp[1];
1748 struct GNUNET_TUN_UdpHeader *udp = (struct GNUNET_TUN_UdpHeader *) &ipp[1];
1752 /* sender did not strip ICMP payload? */
1753 GNUNET_break_op (0);
1754 return GNUNET_SYSERR;
1756 size += sizeof (struct GNUNET_TUN_IPv4Header) + 8;
1757 GNUNET_assert (8 == sizeof (struct GNUNET_TUN_UdpHeader));
1758 make_up_icmpv4_payload (ts, ipp, udp);
1761 case GNUNET_TUN_ICMPTYPE6_PACKET_TOO_BIG:
1762 case GNUNET_TUN_ICMPTYPE6_PARAMETER_PROBLEM:
1763 GNUNET_STATISTICS_update (stats,
1764 gettext_noop ("# ICMPv6 packets dropped (impossible PT to v4)"),
1767 case GNUNET_TUN_ICMPTYPE6_ECHO_REQUEST:
1768 icmp->type = GNUNET_TUN_ICMPTYPE_ECHO_REQUEST;
1770 case GNUNET_TUN_ICMPTYPE6_ECHO_REPLY:
1771 icmp->type = GNUNET_TUN_ICMPTYPE_ECHO_REPLY;
1774 GNUNET_break_op (0);
1775 GNUNET_STATISTICS_update (stats,
1776 gettext_noop ("# ICMPv6 packets dropped (type not allowed)"),
1778 return GNUNET_SYSERR;
1783 GNUNET_break_op (0);
1784 return GNUNET_SYSERR;
1786 msg->size = htons (size);
1787 GNUNET_TUN_calculate_icmp_checksum (icmp,
1790 (void) GNUNET_HELPER_send (helper_handle,
1799 size_t size = sizeof (struct GNUNET_TUN_IPv6Header)
1800 + sizeof (struct GNUNET_TUN_IcmpHeader)
1801 + sizeof (struct GNUNET_MessageHeader) +
1802 sizeof (struct GNUNET_TUN_Layer2PacketHeader) +
1805 char buf[size + sizeof (struct GNUNET_TUN_IPv6Header) + 8] GNUNET_ALIGN;
1806 struct GNUNET_MessageHeader *msg = (struct GNUNET_MessageHeader *) buf;
1807 struct GNUNET_TUN_Layer2PacketHeader *tun = (struct GNUNET_TUN_Layer2PacketHeader*) &msg[1];
1808 struct GNUNET_TUN_IPv6Header *ipv6 = (struct GNUNET_TUN_IPv6Header *) &tun[1];
1809 struct GNUNET_TUN_IcmpHeader *icmp = (struct GNUNET_TUN_IcmpHeader *) &ipv6[1];
1810 msg->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
1811 tun->flags = htons (0);
1812 tun->proto = htons (ETH_P_IPV6);
1813 GNUNET_TUN_initialize_ipv6_header (ipv6,
1815 sizeof (struct GNUNET_TUN_IcmpHeader) + mlen,
1816 &ts->destination_ip.v6,
1818 *icmp = i2v->icmp_header;
1823 /* For some ICMP types, we need to adjust (make up) the payload here.
1824 Also, depending on the AF used on the other side, we have to
1825 do ICMP PT (translate ICMP types) */
1826 switch (ntohl (i2v->af))
1829 /* ICMP PT 4-to-6 and possibly making up payloads */
1832 case GNUNET_TUN_ICMPTYPE_ECHO_REPLY:
1833 icmp->type = GNUNET_TUN_ICMPTYPE6_ECHO_REPLY;
1835 case GNUNET_TUN_ICMPTYPE_ECHO_REQUEST:
1836 icmp->type = GNUNET_TUN_ICMPTYPE6_ECHO_REQUEST;
1838 case GNUNET_TUN_ICMPTYPE_DESTINATION_UNREACHABLE:
1839 icmp->type = GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE;
1841 struct GNUNET_TUN_IPv6Header *ipp = (struct GNUNET_TUN_IPv6Header *) &icmp[1];
1842 struct GNUNET_TUN_UdpHeader *udp = (struct GNUNET_TUN_UdpHeader *) &ipp[1];
1846 /* sender did not strip ICMP payload? */
1847 GNUNET_break_op (0);
1848 return GNUNET_SYSERR;
1850 size += sizeof (struct GNUNET_TUN_IPv6Header) + 8;
1851 GNUNET_assert (8 == sizeof (struct GNUNET_TUN_UdpHeader));
1852 make_up_icmpv6_payload (ts, ipp, udp);
1855 case GNUNET_TUN_ICMPTYPE_TIME_EXCEEDED:
1856 icmp->type = GNUNET_TUN_ICMPTYPE6_TIME_EXCEEDED;
1858 struct GNUNET_TUN_IPv6Header *ipp = (struct GNUNET_TUN_IPv6Header *) &icmp[1];
1859 struct GNUNET_TUN_UdpHeader *udp = (struct GNUNET_TUN_UdpHeader *) &ipp[1];
1863 /* sender did not strip ICMP payload? */
1864 GNUNET_break_op (0);
1865 return GNUNET_SYSERR;
1867 size += sizeof (struct GNUNET_TUN_IPv6Header) + 8;
1868 GNUNET_assert (8 == sizeof (struct GNUNET_TUN_UdpHeader));
1869 make_up_icmpv6_payload (ts, ipp, udp);
1872 case GNUNET_TUN_ICMPTYPE_SOURCE_QUENCH:
1873 GNUNET_STATISTICS_update (stats,
1874 gettext_noop ("# ICMPv4 packets dropped (impossible PT to v6)"),
1878 GNUNET_break_op (0);
1879 GNUNET_STATISTICS_update (stats,
1880 gettext_noop ("# ICMPv4 packets dropped (type not allowed)"),
1882 return GNUNET_SYSERR;
1889 case GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE:
1890 case GNUNET_TUN_ICMPTYPE6_TIME_EXCEEDED:
1891 case GNUNET_TUN_ICMPTYPE6_PACKET_TOO_BIG:
1892 case GNUNET_TUN_ICMPTYPE6_PARAMETER_PROBLEM:
1894 struct GNUNET_TUN_IPv6Header *ipp = (struct GNUNET_TUN_IPv6Header *) &icmp[1];
1895 struct GNUNET_TUN_UdpHeader *udp = (struct GNUNET_TUN_UdpHeader *) &ipp[1];
1899 /* sender did not strip ICMP payload? */
1900 GNUNET_break_op (0);
1901 return GNUNET_SYSERR;
1903 size += sizeof (struct GNUNET_TUN_IPv6Header) + 8;
1904 GNUNET_assert (8 == sizeof (struct GNUNET_TUN_UdpHeader));
1905 make_up_icmpv6_payload (ts, ipp, udp);
1908 case GNUNET_TUN_ICMPTYPE6_ECHO_REQUEST:
1911 GNUNET_break_op (0);
1912 GNUNET_STATISTICS_update (stats,
1913 gettext_noop ("# ICMPv6 packets dropped (type not allowed)"),
1915 return GNUNET_SYSERR;
1920 GNUNET_break_op (0);
1921 return GNUNET_SYSERR;
1923 msg->size = htons (size);
1924 GNUNET_TUN_calculate_icmp_checksum (icmp,
1926 (void) GNUNET_HELPER_send (helper_handle,
1936 GNUNET_CONTAINER_heap_update_cost (tunnel_heap,
1938 GNUNET_TIME_absolute_get ().abs_value_us);
1944 * We got a UDP packet back from the MESH tunnel. Pass it on to the
1945 * local virtual interface via the helper.
1947 * @param cls closure, NULL
1948 * @param tunnel connection to the other end
1949 * @param tunnel_ctx pointer to our 'struct TunnelState *'
1950 * @param message the actual message
1951 * @return #GNUNET_OK to keep the connection open,
1952 * #GNUNET_SYSERR to close it (signal serious error)
1955 receive_udp_back (void *cls GNUNET_UNUSED, struct GNUNET_MESH_Tunnel *tunnel,
1957 const struct GNUNET_MessageHeader *message)
1959 struct TunnelState *ts = *tunnel_ctx;
1960 const struct GNUNET_EXIT_UdpReplyMessage *reply;
1963 GNUNET_STATISTICS_update (stats,
1964 gettext_noop ("# UDP packets received from mesh"),
1966 mlen = ntohs (message->size);
1967 if (mlen < sizeof (struct GNUNET_EXIT_UdpReplyMessage))
1969 GNUNET_break_op (0);
1970 return GNUNET_SYSERR;
1972 if (NULL == ts->heap_node)
1974 GNUNET_break_op (0);
1975 return GNUNET_SYSERR;
1977 if (AF_UNSPEC == ts->af)
1979 GNUNET_break_op (0);
1980 return GNUNET_SYSERR;
1982 reply = (const struct GNUNET_EXIT_UdpReplyMessage *) message;
1983 mlen -= sizeof (struct GNUNET_EXIT_UdpReplyMessage);
1985 char sbuf[INET6_ADDRSTRLEN];
1986 char dbuf[INET6_ADDRSTRLEN];
1988 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1989 "Received UDP reply from mesh, sending %u bytes from %s:%u -> %s:%u via TUN\n",
1990 (unsigned int) mlen,
1991 inet_ntop (ts->af, &ts->destination_ip, sbuf, sizeof (sbuf)),
1992 ts->destination_port,
1993 inet_ntop (ts->af, &ts->source_ip, dbuf, sizeof (dbuf)),
2000 size_t size = sizeof (struct GNUNET_TUN_IPv4Header)
2001 + sizeof (struct GNUNET_TUN_UdpHeader)
2002 + sizeof (struct GNUNET_MessageHeader) +
2003 sizeof (struct GNUNET_TUN_Layer2PacketHeader) +
2006 char buf[size] GNUNET_ALIGN;
2007 struct GNUNET_MessageHeader *msg = (struct GNUNET_MessageHeader *) buf;
2008 struct GNUNET_TUN_Layer2PacketHeader *tun = (struct GNUNET_TUN_Layer2PacketHeader*) &msg[1];
2009 struct GNUNET_TUN_IPv4Header *ipv4 = (struct GNUNET_TUN_IPv4Header *) &tun[1];
2010 struct GNUNET_TUN_UdpHeader *udp = (struct GNUNET_TUN_UdpHeader *) &ipv4[1];
2011 msg->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
2012 msg->size = htons (size);
2013 tun->flags = htons (0);
2014 tun->proto = htons (ETH_P_IPV4);
2015 GNUNET_TUN_initialize_ipv4_header (ipv4,
2017 sizeof (struct GNUNET_TUN_UdpHeader) + mlen,
2018 &ts->destination_ip.v4,
2020 if (0 == ntohs (reply->source_port))
2021 udp->source_port = htons (ts->destination_port);
2023 udp->source_port = reply->source_port;
2024 if (0 == ntohs (reply->destination_port))
2025 udp->destination_port = htons (ts->source_port);
2027 udp->destination_port = reply->destination_port;
2028 udp->len = htons (mlen + sizeof (struct GNUNET_TUN_UdpHeader));
2029 GNUNET_TUN_calculate_udp4_checksum (ipv4,
2036 (void) GNUNET_HELPER_send (helper_handle,
2045 size_t size = sizeof (struct GNUNET_TUN_IPv6Header)
2046 + sizeof (struct GNUNET_TUN_UdpHeader)
2047 + sizeof (struct GNUNET_MessageHeader) +
2048 sizeof (struct GNUNET_TUN_Layer2PacketHeader) +
2051 char buf[size] GNUNET_ALIGN;
2052 struct GNUNET_MessageHeader *msg = (struct GNUNET_MessageHeader *) buf;
2053 struct GNUNET_TUN_Layer2PacketHeader *tun = (struct GNUNET_TUN_Layer2PacketHeader*) &msg[1];
2054 struct GNUNET_TUN_IPv6Header *ipv6 = (struct GNUNET_TUN_IPv6Header *) &tun[1];
2055 struct GNUNET_TUN_UdpHeader *udp = (struct GNUNET_TUN_UdpHeader *) &ipv6[1];
2056 msg->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
2057 msg->size = htons (size);
2058 tun->flags = htons (0);
2059 tun->proto = htons (ETH_P_IPV6);
2060 GNUNET_TUN_initialize_ipv6_header (ipv6,
2062 sizeof (struct GNUNET_TUN_UdpHeader) + mlen,
2063 &ts->destination_ip.v6,
2065 if (0 == ntohs (reply->source_port))
2066 udp->source_port = htons (ts->destination_port);
2068 udp->source_port = reply->source_port;
2069 if (0 == ntohs (reply->destination_port))
2070 udp->destination_port = htons (ts->source_port);
2072 udp->destination_port = reply->destination_port;
2073 udp->len = htons (mlen + sizeof (struct GNUNET_TUN_UdpHeader));
2074 GNUNET_TUN_calculate_udp6_checksum (ipv6,
2080 (void) GNUNET_HELPER_send (helper_handle,
2090 GNUNET_CONTAINER_heap_update_cost (tunnel_heap,
2092 GNUNET_TIME_absolute_get ().abs_value_us);
2098 * We got a TCP packet back from the MESH tunnel. Pass it on to the
2099 * local virtual interface via the helper.
2101 * @param cls closure, NULL
2102 * @param tunnel connection to the other end
2103 * @param tunnel_ctx pointer to our `struct TunnelState *`
2104 * @param message the actual message
2105 * @return #GNUNET_OK to keep the connection open,
2106 * #GNUNET_SYSERR to close it (signal serious error)
2109 receive_tcp_back (void *cls GNUNET_UNUSED, struct GNUNET_MESH_Tunnel *tunnel,
2111 const struct GNUNET_MessageHeader *message)
2113 struct TunnelState *ts = *tunnel_ctx;
2114 const struct GNUNET_EXIT_TcpDataMessage *data;
2117 GNUNET_STATISTICS_update (stats,
2118 gettext_noop ("# TCP packets received from mesh"),
2120 mlen = ntohs (message->size);
2121 if (mlen < sizeof (struct GNUNET_EXIT_TcpDataMessage))
2123 GNUNET_break_op (0);
2124 return GNUNET_SYSERR;
2126 if (NULL == ts->heap_node)
2128 GNUNET_break_op (0);
2129 return GNUNET_SYSERR;
2131 data = (const struct GNUNET_EXIT_TcpDataMessage *) message;
2132 mlen -= sizeof (struct GNUNET_EXIT_TcpDataMessage);
2134 char sbuf[INET6_ADDRSTRLEN];
2135 char dbuf[INET6_ADDRSTRLEN];
2137 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2138 "Received TCP reply from mesh, sending %u bytes from %s:%u -> %s:%u via TUN\n",
2139 (unsigned int) mlen,
2140 inet_ntop (ts->af, &ts->destination_ip, sbuf, sizeof (sbuf)),
2141 ts->destination_port,
2142 inet_ntop (ts->af, &ts->source_ip, dbuf, sizeof (dbuf)),
2145 if (data->tcp_header.off * 4 < sizeof (struct GNUNET_TUN_TcpHeader))
2147 GNUNET_break_op (0);
2148 return GNUNET_SYSERR;
2154 size_t size = sizeof (struct GNUNET_TUN_IPv4Header)
2155 + sizeof (struct GNUNET_TUN_TcpHeader)
2156 + sizeof (struct GNUNET_MessageHeader) +
2157 sizeof (struct GNUNET_TUN_Layer2PacketHeader) +
2160 char buf[size] GNUNET_ALIGN;
2161 struct GNUNET_MessageHeader *msg = (struct GNUNET_MessageHeader *) buf;
2162 struct GNUNET_TUN_Layer2PacketHeader *tun = (struct GNUNET_TUN_Layer2PacketHeader*) &msg[1];
2163 struct GNUNET_TUN_IPv4Header *ipv4 = (struct GNUNET_TUN_IPv4Header *) &tun[1];
2164 struct GNUNET_TUN_TcpHeader *tcp = (struct GNUNET_TUN_TcpHeader *) &ipv4[1];
2165 msg->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
2166 msg->size = htons (size);
2167 tun->flags = htons (0);
2168 tun->proto = htons (ETH_P_IPV4);
2169 GNUNET_TUN_initialize_ipv4_header (ipv4,
2171 sizeof (struct GNUNET_TUN_TcpHeader) + mlen,
2172 &ts->destination_ip.v4,
2174 *tcp = data->tcp_header;
2175 tcp->source_port = htons (ts->destination_port);
2176 tcp->destination_port = htons (ts->source_port);
2177 GNUNET_TUN_calculate_tcp4_checksum (ipv4,
2184 (void) GNUNET_HELPER_send (helper_handle,
2193 size_t size = sizeof (struct GNUNET_TUN_IPv6Header)
2194 + sizeof (struct GNUNET_TUN_TcpHeader)
2195 + sizeof (struct GNUNET_MessageHeader) +
2196 sizeof (struct GNUNET_TUN_Layer2PacketHeader) +
2199 char buf[size] GNUNET_ALIGN;
2200 struct GNUNET_MessageHeader *msg = (struct GNUNET_MessageHeader *) buf;
2201 struct GNUNET_TUN_Layer2PacketHeader *tun = (struct GNUNET_TUN_Layer2PacketHeader*) &msg[1];
2202 struct GNUNET_TUN_IPv6Header *ipv6 = (struct GNUNET_TUN_IPv6Header *) &tun[1];
2203 struct GNUNET_TUN_TcpHeader *tcp = (struct GNUNET_TUN_TcpHeader *) &ipv6[1];
2204 msg->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
2205 msg->size = htons (size);
2206 tun->flags = htons (0);
2207 tun->proto = htons (ETH_P_IPV6);
2208 GNUNET_TUN_initialize_ipv6_header (ipv6,
2210 sizeof (struct GNUNET_TUN_TcpHeader) + mlen,
2211 &ts->destination_ip.v6,
2213 *tcp = data->tcp_header;
2214 tcp->source_port = htons (ts->destination_port);
2215 tcp->destination_port = htons (ts->source_port);
2216 GNUNET_TUN_calculate_tcp6_checksum (ipv6,
2223 (void) GNUNET_HELPER_send (helper_handle,
2231 GNUNET_CONTAINER_heap_update_cost (tunnel_heap,
2233 GNUNET_TIME_absolute_get ().abs_value_us);
2239 * Allocate an IPv4 address from the range of the tunnel
2240 * for a new redirection.
2242 * @param v4 where to store the address
2243 * @return #GNUNET_OK on success,
2244 * #GNUNET_SYSERR on error
2247 allocate_v4_address (struct in_addr *v4)
2249 const char *ipv4addr = vpn_argv[4];
2250 const char *ipv4mask = vpn_argv[5];
2251 struct in_addr addr;
2252 struct in_addr mask;
2254 struct GNUNET_HashCode key;
2257 GNUNET_assert (1 == inet_pton (AF_INET, ipv4addr, &addr));
2258 GNUNET_assert (1 == inet_pton (AF_INET, ipv4mask, &mask));
2259 /* Given 192.168.0.1/255.255.0.0, we want a mask
2260 of '192.168.255.255', thus: */
2261 mask.s_addr = addr.s_addr | ~mask.s_addr;
2268 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
2269 _("Failed to find unallocated IPv4 address in VPN's range\n"));
2270 return GNUNET_SYSERR;
2272 /* Pick random IPv4 address within the subnet, except 'addr' or 'mask' itself */
2273 rnd.s_addr = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
2275 v4->s_addr = (addr.s_addr | rnd.s_addr) & mask.s_addr;
2276 get_destination_key_from_ip (AF_INET,
2280 while ( (GNUNET_YES ==
2281 GNUNET_CONTAINER_multihashmap_contains (destination_map,
2283 (v4->s_addr == addr.s_addr) ||
2284 (v4->s_addr == mask.s_addr) );
2290 * Allocate an IPv6 address from the range of the tunnel
2291 * for a new redirection.
2293 * @param v6 where to store the address
2294 * @return #GNUNET_OK on success,
2295 * #GNUNET_SYSERR on error
2298 allocate_v6_address (struct in6_addr *v6)
2300 const char *ipv6addr = vpn_argv[2];
2301 struct in6_addr addr;
2302 struct in6_addr mask;
2303 struct in6_addr rnd;
2305 struct GNUNET_HashCode key;
2308 GNUNET_assert (1 == inet_pton (AF_INET6, ipv6addr, &addr));
2309 GNUNET_assert (ipv6prefix < 128);
2310 /* Given ABCD::/96, we want a mask of 'ABCD::FFFF:FFFF,
2313 for (i=127;i>=ipv6prefix;i--)
2314 mask.s6_addr[i / 8] |= (1 << (i % 8));
2316 /* Pick random IPv6 address within the subnet, except 'addr' or 'mask' itself */
2323 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
2324 _("Failed to find unallocated IPv6 address in VPN's range\n"));
2325 return GNUNET_SYSERR;
2330 rnd.s6_addr[i] = (unsigned char) GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
2333 = (addr.s6_addr[i] | rnd.s6_addr[i]) & mask.s6_addr[i];
2335 get_destination_key_from_ip (AF_INET6,
2339 while ( (GNUNET_YES ==
2340 GNUNET_CONTAINER_multihashmap_contains (destination_map,
2344 sizeof (struct in6_addr))) ||
2347 sizeof (struct in6_addr))) );
2353 * Free resources occupied by a destination entry.
2355 * @param de entry to free
2358 free_destination_entry (struct DestinationEntry *de)
2360 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2361 "Cleaning up destination entry\n");
2362 GNUNET_STATISTICS_update (stats,
2363 gettext_noop ("# Active destinations"),
2367 free_tunnel_state (de->ts);
2368 GNUNET_assert (NULL == de->ts);
2370 if (NULL != de->heap_node)
2372 GNUNET_CONTAINER_heap_remove_node (de->heap_node);
2373 de->heap_node = NULL;
2374 GNUNET_assert (GNUNET_YES ==
2375 GNUNET_CONTAINER_multihashmap_remove (destination_map,
2384 * We have too many active destinations. Clean up the oldest destination.
2386 * @param except destination that must NOT be cleaned up, even if it is the oldest
2389 expire_destination (struct DestinationEntry *except)
2391 struct DestinationEntry *de;
2393 de = GNUNET_CONTAINER_heap_peek (destination_heap);
2394 GNUNET_assert (NULL != de);
2396 return; /* can't do this */
2397 free_destination_entry (de);
2402 * Allocate an IP address for the response.
2404 * @param result_af desired address family; set to the actual
2405 * address family; can initially be AF_UNSPEC if there
2406 * is no preference; will be set to AF_UNSPEC if the
2408 * @param addr set to either v4 or v6 depending on which
2409 * storage location was used; set to NULL if allocation failed
2410 * @param v4 storage space for an IPv4 address
2411 * @param v6 storage space for an IPv6 address
2412 * @return #GNUNET_OK normally, #GNUNET_SYSERR if `* result_af` was
2413 * an unsupported address family (not AF_INET, AF_INET6 or AF_UNSPEC)
2416 allocate_response_ip (int *result_af,
2419 struct in6_addr *v6)
2426 allocate_v4_address (v4))
2427 *result_af = AF_UNSPEC;
2433 allocate_v6_address (v6))
2434 *result_af = AF_UNSPEC;
2440 allocate_v4_address (v4))
2443 *result_af = AF_INET;
2445 else if (GNUNET_OK ==
2446 allocate_v6_address (v6))
2449 *result_af = AF_INET6;
2454 return GNUNET_SYSERR;
2461 * A client asks us to setup a redirection via some exit node to a
2462 * particular IP. Setup the redirection and give the client the
2466 * @param client requesting client
2467 * @param message redirection request (a `struct RedirectToIpRequestMessage`)
2470 service_redirect_to_ip (void *cls,
2471 struct GNUNET_SERVER_Client *client,
2472 const struct GNUNET_MessageHeader *message)
2476 const struct RedirectToIpRequestMessage *msg;
2482 struct DestinationEntry *de;
2483 struct GNUNET_HashCode key;
2484 struct TunnelState *ts;
2486 /* validate and parse request */
2487 mlen = ntohs (message->size);
2488 if (mlen < sizeof (struct RedirectToIpRequestMessage))
2491 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2494 alen = mlen - sizeof (struct RedirectToIpRequestMessage);
2495 msg = (const struct RedirectToIpRequestMessage *) message;
2496 addr_af = (int) htonl (msg->addr_af);
2500 if (alen != sizeof (struct in_addr))
2503 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2508 if (alen != sizeof (struct in6_addr))
2511 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2517 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2521 /* allocate response IP */
2522 result_af = (int) htonl (msg->result_af);
2523 if (GNUNET_OK != allocate_response_ip (&result_af,
2527 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2530 /* send reply with our IP address */
2531 send_client_reply (client,
2535 if (result_af == AF_UNSPEC)
2537 /* failure, we're done */
2538 GNUNET_SERVER_receive_done (client, GNUNET_OK);
2543 char sbuf[INET6_ADDRSTRLEN];
2544 char dbuf[INET6_ADDRSTRLEN];
2546 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2547 "Allocated address %s for redirection via exit to %s\n",
2548 inet_ntop (result_af, addr, sbuf, sizeof (sbuf)),
2550 &msg[1], dbuf, sizeof (dbuf)));
2553 /* setup destination record */
2554 de = GNUNET_new (struct DestinationEntry);
2555 de->is_service = GNUNET_NO;
2556 de->details.exit_destination.af = addr_af;
2557 memcpy (&de->details.exit_destination.ip,
2560 get_destination_key_from_ip (result_af,
2564 GNUNET_assert (GNUNET_OK ==
2565 GNUNET_CONTAINER_multihashmap_put (destination_map,
2568 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE));
2569 de->heap_node = GNUNET_CONTAINER_heap_insert (destination_heap,
2571 GNUNET_TIME_absolute_ntoh (msg->expiration_time).abs_value_us);
2572 GNUNET_STATISTICS_update (stats,
2573 gettext_noop ("# Active destinations"),
2575 while (GNUNET_CONTAINER_multihashmap_size (destination_map) > max_destination_mappings)
2576 expire_destination (de);
2578 /* setup tunnel to destination */
2579 ts = create_tunnel_to_destination (de,
2584 ts->destination_ip.v4 = v4;
2587 ts->destination_ip.v6 = v6;
2593 GNUNET_SERVER_receive_done (client, GNUNET_OK);
2598 * A client asks us to setup a redirection to a particular peer
2599 * offering a service. Setup the redirection and give the client the
2603 * @param client requesting client
2604 * @param message redirection request (a `struct RedirectToPeerRequestMessage`)
2607 service_redirect_to_service (void *cls GNUNET_UNUSED, struct GNUNET_SERVER_Client *client,
2608 const struct GNUNET_MessageHeader *message)
2610 const struct RedirectToServiceRequestMessage *msg;
2615 struct DestinationEntry *de;
2616 struct GNUNET_HashCode key;
2617 struct TunnelState *ts;
2620 msg = (const struct RedirectToServiceRequestMessage *) message;
2622 /* allocate response IP */
2623 result_af = (int) htonl (msg->result_af);
2624 if (GNUNET_OK != allocate_response_ip (&result_af,
2628 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2631 send_client_reply (client,
2635 if (result_af == AF_UNSPEC)
2637 /* failure, we're done */
2638 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2639 _("Failed to allocate IP address for new destination\n"));
2640 GNUNET_SERVER_receive_done (client, GNUNET_OK);
2645 char sbuf[INET6_ADDRSTRLEN];
2647 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2648 "Allocated address %s for redirection to service %s on peer %s\n",
2649 inet_ntop (result_af, addr, sbuf, sizeof (sbuf)),
2650 GNUNET_h2s (&msg->service_descriptor),
2651 GNUNET_i2s (&msg->target));
2654 /* setup destination record */
2655 de = GNUNET_new (struct DestinationEntry);
2656 de->is_service = GNUNET_YES;
2657 de->details.service_destination.service_descriptor = msg->service_descriptor;
2658 de->details.service_destination.target = msg->target;
2659 get_destination_key_from_ip (result_af,
2663 GNUNET_assert (GNUNET_OK ==
2664 GNUNET_CONTAINER_multihashmap_put (destination_map,
2667 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE));
2668 de->heap_node = GNUNET_CONTAINER_heap_insert (destination_heap,
2670 GNUNET_TIME_absolute_ntoh (msg->expiration_time).abs_value_us);
2671 while (GNUNET_CONTAINER_multihashmap_size (destination_map) > max_destination_mappings)
2672 expire_destination (de);
2673 ts = create_tunnel_to_destination (de,
2678 ts->destination_ip.v4 = v4;
2681 ts->destination_ip.v6 = v6;
2687 GNUNET_SERVER_receive_done (client, GNUNET_OK);
2692 * Function called whenever a tunnel is destroyed. Should clean up
2693 * any associated state.
2695 * @param cls closure (set from #GNUNET_MESH_connect)
2696 * @param tunnel connection to the other end (henceforth invalid)
2697 * @param tunnel_ctx place where local state associated
2698 * with the tunnel is stored (our `struct TunnelState`)
2701 tunnel_cleaner (void *cls,
2702 const struct GNUNET_MESH_Tunnel *tunnel,
2705 struct TunnelState *ts = tunnel_ctx;
2707 ts->tunnel = NULL; /* we must not call GNUNET_MESH_tunnel_destroy() anymore */
2708 free_tunnel_state (ts);
2713 * Free memory occupied by an entry in the destination map.
2717 * @param value a `struct DestinationEntry *`
2718 * @return #GNUNET_OK (continue to iterate)
2721 cleanup_destination (void *cls,
2722 const struct GNUNET_HashCode *key,
2725 struct DestinationEntry *de = value;
2727 free_destination_entry (de);
2733 * Free memory occupied by an entry in the tunnel map.
2737 * @param value a `struct TunnelState *`
2738 * @return #GNUNET_OK (continue to iterate)
2741 cleanup_tunnel (void *cls,
2742 const struct GNUNET_HashCode *key,
2745 struct TunnelState *ts = value;
2747 free_tunnel_state (ts);
2753 * Function scheduled as very last function, cleans up after us
2760 const struct GNUNET_SCHEDULER_TaskContext *tc)
2764 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2765 "VPN is shutting down\n");
2766 if (NULL != destination_map)
2768 GNUNET_CONTAINER_multihashmap_iterate (destination_map,
2769 &cleanup_destination,
2771 GNUNET_CONTAINER_multihashmap_destroy (destination_map);
2772 destination_map = NULL;
2774 if (NULL != destination_heap)
2776 GNUNET_CONTAINER_heap_destroy (destination_heap);
2777 destination_heap = NULL;
2779 if (NULL != tunnel_map)
2781 GNUNET_CONTAINER_multihashmap_iterate (tunnel_map,
2784 GNUNET_CONTAINER_multihashmap_destroy (tunnel_map);
2787 if (NULL != tunnel_heap)
2789 GNUNET_CONTAINER_heap_destroy (tunnel_heap);
2792 if (NULL != mesh_handle)
2794 GNUNET_MESH_disconnect (mesh_handle);
2797 if (NULL != helper_handle)
2799 GNUNET_HELPER_stop (helper_handle, GNUNET_NO);
2800 helper_handle = NULL;
2804 GNUNET_SERVER_notification_context_destroy (nc);
2809 GNUNET_STATISTICS_destroy (stats, GNUNET_NO);
2813 GNUNET_free_non_null (vpn_argv[i]);
2818 * Main function that will be run by the scheduler.
2820 * @param cls closure
2821 * @param server the initialized server
2822 * @param cfg_ configuration
2826 struct GNUNET_SERVER_Handle *server,
2827 const struct GNUNET_CONFIGURATION_Handle *cfg_)
2829 static const struct GNUNET_SERVER_MessageHandler service_handlers[] = {
2830 /* callback, cls, type, size */
2831 { &service_redirect_to_ip, NULL, GNUNET_MESSAGE_TYPE_VPN_CLIENT_REDIRECT_TO_IP, 0},
2832 { &service_redirect_to_service, NULL,
2833 GNUNET_MESSAGE_TYPE_VPN_CLIENT_REDIRECT_TO_SERVICE,
2834 sizeof (struct RedirectToServiceRequestMessage) },
2837 static const struct GNUNET_MESH_MessageHandler mesh_handlers[] = {
2838 { &receive_udp_back, GNUNET_MESSAGE_TYPE_VPN_UDP_REPLY, 0},
2839 { &receive_tcp_back, GNUNET_MESSAGE_TYPE_VPN_TCP_DATA_TO_VPN, 0},
2840 { &receive_icmp_back, GNUNET_MESSAGE_TYPE_VPN_ICMP_TO_VPN, 0},
2852 binary = GNUNET_OS_get_libexec_binary_path ("gnunet-helper-vpn");
2855 GNUNET_OS_check_helper_binary (binary, GNUNET_YES, "-d gnunet-vpn - - 169.1.3.3.7 255.255.255.0")) //ipv4 only please!
2858 "`%s' is not SUID, refusing to run.\n",
2859 "gnunet-helper-vpn");
2860 GNUNET_free (binary);
2864 GNUNET_free (binary);
2866 stats = GNUNET_STATISTICS_create ("vpn", cfg);
2868 GNUNET_CONFIGURATION_get_value_number (cfg, "VPN", "MAX_MAPPING",
2869 &max_destination_mappings))
2870 max_destination_mappings = 200;
2872 GNUNET_CONFIGURATION_get_value_number (cfg, "VPN", "MAX_TUNNELS",
2873 &max_tunnel_mappings))
2874 max_tunnel_mappings = 200;
2876 destination_map = GNUNET_CONTAINER_multihashmap_create (max_destination_mappings * 2, GNUNET_NO);
2877 destination_heap = GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN);
2878 tunnel_map = GNUNET_CONTAINER_multihashmap_create (max_tunnel_mappings * 2, GNUNET_NO);
2879 tunnel_heap = GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN);
2882 vpn_argv[0] = GNUNET_strdup ("vpn-gnunet");
2883 if (GNUNET_SYSERR ==
2884 GNUNET_CONFIGURATION_get_value_string (cfg, "VPN", "IFNAME", &ifname))
2886 GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, "VPN", "IFNAME");
2887 GNUNET_SCHEDULER_shutdown ();
2890 vpn_argv[1] = ifname;
2891 if (GNUNET_OK == GNUNET_NETWORK_test_pf (PF_INET6))
2893 if ( (GNUNET_SYSERR ==
2894 GNUNET_CONFIGURATION_get_value_string (cfg, "VPN", "IPV6ADDR",
2896 (1 != inet_pton (AF_INET6, ipv6addr, &v6))) )
2898 GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, "VPN", "IPV6ADDR",
2899 _("Must specify valid IPv6 address"));
2900 GNUNET_SCHEDULER_shutdown ();
2903 vpn_argv[2] = ipv6addr;
2904 if (GNUNET_SYSERR ==
2905 GNUNET_CONFIGURATION_get_value_string (cfg, "VPN", "IPV6PREFIX",
2908 GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, "VPN", "IPV6PREFIX");
2909 GNUNET_SCHEDULER_shutdown ();
2912 vpn_argv[3] = ipv6prefix_s;
2914 GNUNET_CONFIGURATION_get_value_number (cfg, "VPN",
2917 (ipv6prefix >= 127) )
2919 GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, "VPN", "IPV4MASK",
2920 _("Must specify valid IPv6 mask"));
2921 GNUNET_SCHEDULER_shutdown ();
2927 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
2928 _("IPv6 support disabled as this system does not support IPv6\n"));
2929 vpn_argv[2] = GNUNET_strdup ("-");
2930 vpn_argv[3] = GNUNET_strdup ("-");
2932 if (GNUNET_OK == GNUNET_NETWORK_test_pf (PF_INET))
2934 if ( (GNUNET_SYSERR ==
2935 GNUNET_CONFIGURATION_get_value_string (cfg, "vpn", "IPV4ADDR",
2937 (1 != inet_pton (AF_INET, ipv4addr, &v4))) )
2939 GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, "VPN", "IPV4ADDR",
2940 _("Must specify valid IPv4 address"));
2941 GNUNET_SCHEDULER_shutdown ();
2944 vpn_argv[4] = ipv4addr;
2945 if ( (GNUNET_SYSERR ==
2946 GNUNET_CONFIGURATION_get_value_string (cfg, "vpn", "IPV4MASK",
2948 (1 != inet_pton (AF_INET, ipv4mask, &v4))) )
2950 GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, "VPN", "IPV4MASK",
2951 _("Must specify valid IPv4 mask"));
2952 GNUNET_SCHEDULER_shutdown ();
2955 vpn_argv[5] = ipv4mask;
2959 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
2960 _("IPv4 support disabled as this system does not support IPv4\n"));
2961 vpn_argv[4] = GNUNET_strdup ("-");
2962 vpn_argv[5] = GNUNET_strdup ("-");
2967 GNUNET_MESH_connect (cfg_, NULL,
2972 helper_handle = GNUNET_HELPER_start (GNUNET_NO,
2973 "gnunet-helper-vpn", vpn_argv,
2974 &message_token, NULL, NULL);
2975 nc = GNUNET_SERVER_notification_context_create (server, 1);
2976 GNUNET_SERVER_add_handlers (server, service_handlers);
2977 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &cleanup, cls);
2982 * The main function of the VPN service.
2984 * @param argc number of arguments from the command line
2985 * @param argv command line arguments
2986 * @return 0 ok, 1 on error
2989 main (int argc, char *const *argv)
2991 return (GNUNET_OK ==
2992 GNUNET_SERVICE_run (argc, argv, "vpn",
2993 GNUNET_SERVICE_OPTION_NONE,
2994 &run, NULL)) ? global_ret : 1;
2997 /* end of gnunet-service-vpn.c */