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 channels ready as alternative exits /
31 * detect & recover from channel-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 channels.
59 * Information we track for each IP address to determine which channel
60 * to send the traffic over to the destination.
62 struct DestinationEntry;
65 * List of channels we keep for each destination port for a given
68 struct DestinationChannel
74 struct DestinationChannel *next;
79 struct DestinationChannel *prev;
82 * Destination entry list this `struct DestinationChannel` belongs with.
84 struct DestinationEntry *destination;
87 * Pre-allocated channel for this destination, or NULL for none.
89 struct ChannelState *ts;
92 * Destination port this channel state is used for.
94 uint16_t destination_port;
100 * Information we track for each IP address to determine which channel
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 channels associated with this destination.
115 struct DestinationChannel *dt_head;
118 * Tail of DLL of channels associated with this destination.
120 struct DestinationChannel *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 channel to an Internet-exit,
129 * #GNUNET_YES if this channel is to a service.
134 * Details about the connection (depending on is_service).
142 * The description of the service (only used for service channels).
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 channels).
167 * Address if af is AF_INET.
172 * Address if af is AF_INET6.
185 * A messages we have in queue for a particular channel.
187 struct ChannelMessageQueueEntry
190 * This is a doubly-linked list.
192 struct ChannelMessageQueueEntry *next;
195 * This is a doubly-linked list.
197 struct ChannelMessageQueueEntry *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 channels.
218 * Information about the channel to use, NULL if no channel
219 * is available right now.
221 struct GNUNET_MESH_Channel *channel;
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 channel_heap, NULL as long as this
235 * channel state is not fully bound.
237 struct GNUNET_CONTAINER_HeapNode *heap_node;
240 * Head of list of messages scheduled for transmission.
242 struct ChannelMessageQueueEntry *tmq_head;
245 * Tail of list of messages scheduled for transmission.
247 struct ChannelMessageQueueEntry *tmq_tail;
250 * Destination entry that has a pointer to this channel state;
251 * NULL if this channel state is in the channel map.
253 struct DestinationChannel *destination_container;
256 * Destination to which this channel 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 channel 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 channel 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 channel 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 channel handle).
356 static struct GNUNET_CONTAINER_MultiHashMap *channel_map;
359 * Min-Heap sorted by activity time to expire old mappings; values are
360 * of type 'struct ChannelState'.
362 static struct GNUNET_CONTAINER_Heap *channel_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 channels, old ones
399 static unsigned long long max_channel_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 * channel_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_channel_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 channel state.
538 * @param ts state to free
541 free_channel_state (struct ChannelState *ts)
543 struct GNUNET_HashCode key;
544 struct ChannelMessageQueueEntry *tnq;
545 struct GNUNET_MESH_Channel *channel;
547 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
548 "Cleaning up channel state\n");
549 GNUNET_STATISTICS_update (stats,
550 gettext_noop ("# Active channels"),
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 != (channel = ts->channel))
570 GNUNET_MESH_channel_destroy (channel);
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_channel_key_from_ips (ts->af,
586 ts->destination_port,
588 GNUNET_assert (GNUNET_YES ==
589 GNUNET_CONTAINER_multihashmap_remove (channel_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 ChannelState` 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 ChannelState *ts = cls;
615 struct ChannelMessageQueueEntry *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 channel\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->channel,
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 channel and trigger the
650 * transmission process.
652 * @param tnq message to queue
653 * @param ts channel to queue the message for
656 send_to_channel (struct ChannelMessageQueueEntry *tnq,
657 struct ChannelState *ts)
659 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
660 "Queueing %u bytes for transmission via mesh channel\n",
662 GNUNET_assert (NULL != ts->channel);
663 GNUNET_CONTAINER_DLL_insert_tail (ts->tmq_head,
667 if (ts->tmq_length > MAX_MESSAGE_QUEUE_SIZE)
669 struct ChannelMessageQueueEntry *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->channel,
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 ChannelState'
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 ChannelState *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->channel = GNUNET_MESH_channel_create (mesh_handle,
734 GNUNET_MESH_OPTION_DEFAULT);
739 * Initialize the given destination entry's mesh channel.
741 * @param dt destination channel for which we need to setup a channel
742 * @param client_af address family of the address returned to the client
743 * @return channel state of the channel that was created
745 static struct ChannelState *
746 create_channel_to_destination (struct DestinationChannel *dt,
749 struct ChannelState *ts;
750 unsigned int apptype;
752 GNUNET_STATISTICS_update (stats,
753 gettext_noop ("# Mesh channels created"),
755 GNUNET_assert (NULL == dt->ts);
759 apptype = GNUNET_APPLICATION_TYPE_IPV4_GATEWAY;
762 apptype = GNUNET_APPLICATION_TYPE_IPV6_GATEWAY;
768 ts = GNUNET_new (struct ChannelState);
770 ts->destination = *dt->destination;
771 ts->destination.heap_node = NULL; /* copy is NOT in destination heap */
773 ts->destination_container = dt; /* we are referenced from dt */
774 if (dt->destination->is_service)
776 ts->channel = GNUNET_MESH_channel_create (mesh_handle,
778 &dt->destination->details.service_destination.target,
780 GNUNET_MESH_OPTION_DEFAULT);
781 if (NULL == ts->channel)
783 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
784 _("Failed to setup mesh channel!\n"));
788 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
789 "Creating channel to peer %s offering service %s\n",
790 GNUNET_i2s (&dt->destination->details.service_destination.target),
791 GNUNET_h2s (&dt->destination->details.service_destination.service_descriptor));
797 switch (dt->destination->details.exit_destination.af)
801 char address[GNUNET_TUN_IPV4_REGEXLEN];
803 GNUNET_TUN_ipv4toregexsearch (&dt->destination->details.exit_destination.ip.v4,
804 dt->destination_port,
806 GNUNET_asprintf (&policy, "%s%s",
807 GNUNET_APPLICATION_TYPE_EXIT_REGEX_PREFIX,
813 char address[GNUNET_TUN_IPV6_REGEXLEN];
815 GNUNET_TUN_ipv6toregexsearch (&dt->destination->details.exit_destination.ip.v6,
816 dt->destination_port,
818 GNUNET_asprintf (&policy, "%s%s",
819 GNUNET_APPLICATION_TYPE_EXIT_REGEX_PREFIX,
828 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
829 "Requesting connect by string: %s\n",
831 ts->search = GNUNET_REGEX_search (cfg,
833 &handle_regex_result,
835 GNUNET_free (policy);
842 * We have too many active channels. Clean up the oldest channel.
844 * @param except channel that must NOT be cleaned up, even if it is the oldest
847 expire_channel (struct ChannelState *except)
849 struct ChannelState *ts;
851 ts = GNUNET_CONTAINER_heap_peek (channel_heap);
852 GNUNET_assert (NULL != ts);
854 return; /* can't do this */
855 free_channel_state (ts);
860 * Route a packet via mesh to the given destination.
862 * @param destination description of the destination
863 * @param af address family on this end (AF_INET or AF_INET6)
864 * @param protocol IPPROTO_TCP or IPPROTO_UDP or IPPROTO_ICMP or IPPROTO_ICMPV6
865 * @param source_ip source IP used by the sender (struct in_addr or struct in6_addr)
866 * @param destination_ip destination IP used by the sender (struct in_addr or struct in6_addr)
867 * @param payload payload of the packet after the IP header
868 * @param payload_length number of bytes in @a payload
871 route_packet (struct DestinationEntry *destination,
874 const void *source_ip,
875 const void *destination_ip,
877 size_t payload_length)
879 struct GNUNET_HashCode key;
880 struct ChannelState *ts;
881 struct ChannelMessageQueueEntry *tnq;
885 const struct GNUNET_TUN_UdpHeader *udp;
886 const struct GNUNET_TUN_TcpHeader *tcp;
887 const struct GNUNET_TUN_IcmpHeader *icmp;
888 struct DestinationChannel *dt;
889 uint16_t source_port;
890 uint16_t destination_port;
896 if (payload_length < sizeof (struct GNUNET_TUN_UdpHeader))
902 tcp = NULL; /* make compiler happy */
903 icmp = NULL; /* make compiler happy */
905 if (udp->len < sizeof (struct GNUNET_TUN_UdpHeader))
910 source_port = ntohs (udp->source_port);
911 destination_port = ntohs (udp->destination_port);
912 get_channel_key_from_ips (af,
923 if (payload_length < sizeof (struct GNUNET_TUN_TcpHeader))
929 udp = NULL; /* make compiler happy */
930 icmp = NULL; /* make compiler happy */
932 if (tcp->off * 4 < sizeof (struct GNUNET_TUN_TcpHeader))
937 source_port = ntohs (tcp->source_port);
938 destination_port = ntohs (tcp->destination_port);
939 get_channel_key_from_ips (af,
951 if ( (AF_INET == af) ^ (protocol == IPPROTO_ICMP) )
956 if (payload_length < sizeof (struct GNUNET_TUN_IcmpHeader))
962 tcp = NULL; /* make compiler happy */
963 udp = NULL; /* make compiler happy */
966 destination_port = 0;
967 get_channel_key_from_ips (af,
977 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
978 _("Protocol %u not supported, dropping\n"),
979 (unsigned int) protocol);
983 if (! destination->is_service)
985 switch (destination->details.exit_destination.af)
988 alen = sizeof (struct in_addr);
991 alen = sizeof (struct in6_addr);
998 char sbuf[INET6_ADDRSTRLEN];
999 char dbuf[INET6_ADDRSTRLEN];
1000 char xbuf[INET6_ADDRSTRLEN];
1002 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1003 "Routing %s packet from %s:%u -> %s:%u to destination %s:%u\n",
1004 (protocol == IPPROTO_TCP) ? "TCP" : "UDP",
1005 inet_ntop (af, source_ip, sbuf, sizeof (sbuf)),
1007 inet_ntop (af, destination_ip, dbuf, sizeof (dbuf)),
1009 inet_ntop (destination->details.exit_destination.af,
1010 &destination->details.exit_destination.ip,
1011 xbuf, sizeof (xbuf)),
1014 for (dt = destination->dt_head; NULL != dt; dt = dt->next)
1015 if (dt->destination_port == destination_port)
1021 char sbuf[INET6_ADDRSTRLEN];
1022 char dbuf[INET6_ADDRSTRLEN];
1024 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1025 "Routing %s packet from %s:%u -> %s:%u to service %s at peer %s\n",
1026 (protocol == IPPROTO_TCP) ? "TCP" : "UDP",
1027 inet_ntop (af, source_ip, sbuf, sizeof (sbuf)),
1029 inet_ntop (af, destination_ip, dbuf, sizeof (dbuf)),
1031 GNUNET_h2s (&destination->details.service_destination.service_descriptor),
1032 GNUNET_i2s (&destination->details.service_destination.target));
1034 dt = destination->dt_head;
1038 dt = GNUNET_new (struct DestinationChannel);
1039 dt->destination = destination;
1040 GNUNET_CONTAINER_DLL_insert (destination->dt_head,
1041 destination->dt_tail,
1043 dt->destination_port = destination_port;
1046 /* see if we have an existing channel for this destination */
1047 ts = GNUNET_CONTAINER_multihashmap_get (channel_map,
1051 /* need to either use the existing channel from the destination (if still
1052 available) or create a fresh one */
1053 is_new = GNUNET_YES;
1055 ts = create_channel_to_destination (dt, af);
1061 ts->destination_container = NULL; /* no longer 'contained' */
1062 /* now bind existing "unbound" channel to our IP/port tuple */
1063 ts->protocol = protocol;
1067 ts->source_ip.v4 = * (const struct in_addr *) source_ip;
1068 ts->destination_ip.v4 = * (const struct in_addr *) destination_ip;
1072 ts->source_ip.v6 = * (const struct in6_addr *) source_ip;
1073 ts->destination_ip.v6 = * (const struct in6_addr *) destination_ip;
1075 ts->source_port = source_port;
1076 ts->destination_port = destination_port;
1077 ts->heap_node = GNUNET_CONTAINER_heap_insert (channel_heap,
1079 GNUNET_TIME_absolute_get ().abs_value_us);
1080 GNUNET_assert (GNUNET_YES ==
1081 GNUNET_CONTAINER_multihashmap_put (channel_map,
1084 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
1085 GNUNET_STATISTICS_update (stats,
1086 gettext_noop ("# Active channels"),
1088 while (GNUNET_CONTAINER_multihashmap_size (channel_map) > max_channel_mappings)
1089 expire_channel (ts);
1094 GNUNET_CONTAINER_heap_update_cost (channel_heap,
1096 GNUNET_TIME_absolute_get ().abs_value_us);
1098 GNUNET_assert (NULL != ts->channel);
1100 /* send via channel */
1104 if (destination->is_service)
1106 struct GNUNET_EXIT_UdpServiceMessage *usm;
1108 mlen = sizeof (struct GNUNET_EXIT_UdpServiceMessage) +
1109 payload_length - sizeof (struct GNUNET_TUN_UdpHeader);
1110 if (mlen >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1115 tnq = GNUNET_malloc (sizeof (struct ChannelMessageQueueEntry) + mlen);
1118 usm = (struct GNUNET_EXIT_UdpServiceMessage *) &tnq[1];
1119 usm->header.size = htons ((uint16_t) mlen);
1120 usm->header.type = htons (GNUNET_MESSAGE_TYPE_VPN_UDP_TO_SERVICE);
1121 /* if the source port is below 32000, we assume it has a special
1122 meaning; if not, we pick a random port (this is a heuristic) */
1123 usm->source_port = (ntohs (udp->source_port) < 32000) ? udp->source_port : 0;
1124 usm->destination_port = udp->destination_port;
1125 usm->service_descriptor = destination->details.service_destination.service_descriptor;
1128 payload_length - sizeof (struct GNUNET_TUN_UdpHeader));
1132 struct GNUNET_EXIT_UdpInternetMessage *uim;
1133 struct in_addr *ip4dst;
1134 struct in6_addr *ip6dst;
1137 mlen = sizeof (struct GNUNET_EXIT_UdpInternetMessage) +
1138 alen + payload_length - sizeof (struct GNUNET_TUN_UdpHeader);
1139 if (mlen >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1144 tnq = GNUNET_malloc (sizeof (struct ChannelMessageQueueEntry) + mlen);
1147 uim = (struct GNUNET_EXIT_UdpInternetMessage *) &tnq[1];
1148 uim->header.size = htons ((uint16_t) mlen);
1149 uim->header.type = htons (GNUNET_MESSAGE_TYPE_VPN_UDP_TO_INTERNET);
1150 uim->af = htonl (destination->details.exit_destination.af);
1151 uim->source_port = (ntohs (udp->source_port) < 32000) ? udp->source_port : 0;
1152 uim->destination_port = udp->destination_port;
1153 switch (destination->details.exit_destination.af)
1156 ip4dst = (struct in_addr *) &uim[1];
1157 *ip4dst = destination->details.exit_destination.ip.v4;
1158 payload = &ip4dst[1];
1161 ip6dst = (struct in6_addr *) &uim[1];
1162 *ip6dst = destination->details.exit_destination.ip.v6;
1163 payload = &ip6dst[1];
1170 payload_length - sizeof (struct GNUNET_TUN_UdpHeader));
1176 if (destination->is_service)
1178 struct GNUNET_EXIT_TcpServiceStartMessage *tsm;
1180 mlen = sizeof (struct GNUNET_EXIT_TcpServiceStartMessage) +
1181 payload_length - sizeof (struct GNUNET_TUN_TcpHeader);
1182 if (mlen >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1187 tnq = GNUNET_malloc (sizeof (struct ChannelMessageQueueEntry) + mlen);
1190 tsm = (struct GNUNET_EXIT_TcpServiceStartMessage *) &tnq[1];
1191 tsm->header.size = htons ((uint16_t) mlen);
1192 tsm->header.type = htons (GNUNET_MESSAGE_TYPE_VPN_TCP_TO_SERVICE_START);
1193 tsm->reserved = htonl (0);
1194 tsm->service_descriptor = destination->details.service_destination.service_descriptor;
1195 tsm->tcp_header = *tcp;
1198 payload_length - sizeof (struct GNUNET_TUN_TcpHeader));
1202 struct GNUNET_EXIT_TcpInternetStartMessage *tim;
1203 struct in_addr *ip4dst;
1204 struct in6_addr *ip6dst;
1207 mlen = sizeof (struct GNUNET_EXIT_TcpInternetStartMessage) +
1208 alen + payload_length - sizeof (struct GNUNET_TUN_TcpHeader);
1209 if (mlen >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1214 tnq = GNUNET_malloc (sizeof (struct ChannelMessageQueueEntry) + mlen);
1217 tim = (struct GNUNET_EXIT_TcpInternetStartMessage *) &tnq[1];
1218 tim->header.size = htons ((uint16_t) mlen);
1219 tim->header.type = htons (GNUNET_MESSAGE_TYPE_VPN_TCP_TO_INTERNET_START);
1220 tim->af = htonl (destination->details.exit_destination.af);
1221 tim->tcp_header = *tcp;
1222 switch (destination->details.exit_destination.af)
1225 ip4dst = (struct in_addr *) &tim[1];
1226 *ip4dst = destination->details.exit_destination.ip.v4;
1227 payload = &ip4dst[1];
1230 ip6dst = (struct in6_addr *) &tim[1];
1231 *ip6dst = destination->details.exit_destination.ip.v6;
1232 payload = &ip6dst[1];
1239 payload_length - sizeof (struct GNUNET_TUN_TcpHeader));
1244 struct GNUNET_EXIT_TcpDataMessage *tdm;
1246 mlen = sizeof (struct GNUNET_EXIT_TcpDataMessage) +
1247 payload_length - sizeof (struct GNUNET_TUN_TcpHeader);
1248 if (mlen >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1253 tnq = GNUNET_malloc (sizeof (struct ChannelMessageQueueEntry) + mlen);
1256 tdm = (struct GNUNET_EXIT_TcpDataMessage *) &tnq[1];
1257 tdm->header.size = htons ((uint16_t) mlen);
1258 tdm->header.type = htons (GNUNET_MESSAGE_TYPE_VPN_TCP_DATA_TO_EXIT);
1259 tdm->reserved = htonl (0);
1260 tdm->tcp_header = *tcp;
1263 payload_length - sizeof (struct GNUNET_TUN_TcpHeader));
1267 case IPPROTO_ICMPV6:
1268 if (destination->is_service)
1270 struct GNUNET_EXIT_IcmpServiceMessage *ism;
1272 mlen = sizeof (struct GNUNET_EXIT_IcmpServiceMessage) +
1273 payload_length - sizeof (struct GNUNET_TUN_IcmpHeader);
1274 if (mlen >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1279 tnq = GNUNET_malloc (sizeof (struct ChannelMessageQueueEntry) + mlen);
1281 ism = (struct GNUNET_EXIT_IcmpServiceMessage *) &tnq[1];
1282 ism->header.type = htons (GNUNET_MESSAGE_TYPE_VPN_ICMP_TO_SERVICE);
1283 ism->af = htonl (af); /* need to tell destination ICMP protocol family! */
1284 ism->service_descriptor = destination->details.service_destination.service_descriptor;
1285 ism->icmp_header = *icmp;
1286 /* ICMP protocol translation will be done by the receiver (as we don't know
1287 the target AF); however, we still need to possibly discard the payload
1288 depending on the ICMP type */
1294 case GNUNET_TUN_ICMPTYPE_ECHO_REPLY:
1295 case GNUNET_TUN_ICMPTYPE_ECHO_REQUEST:
1297 case GNUNET_TUN_ICMPTYPE_DESTINATION_UNREACHABLE:
1298 case GNUNET_TUN_ICMPTYPE_SOURCE_QUENCH:
1299 case GNUNET_TUN_ICMPTYPE_TIME_EXCEEDED:
1300 /* throw away ICMP payload, won't be useful for the other side anyway */
1301 payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
1304 GNUNET_STATISTICS_update (stats,
1305 gettext_noop ("# ICMPv4 packets dropped (not allowed)"),
1309 /* end of AF_INET */
1314 case GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE:
1315 case GNUNET_TUN_ICMPTYPE6_PACKET_TOO_BIG:
1316 case GNUNET_TUN_ICMPTYPE6_TIME_EXCEEDED:
1317 case GNUNET_TUN_ICMPTYPE6_PARAMETER_PROBLEM:
1318 /* throw away ICMP payload, won't be useful for the other side anyway */
1319 payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
1321 case GNUNET_TUN_ICMPTYPE6_ECHO_REQUEST:
1322 case GNUNET_TUN_ICMPTYPE6_ECHO_REPLY:
1325 GNUNET_STATISTICS_update (stats,
1326 gettext_noop ("# ICMPv6 packets dropped (not allowed)"),
1330 /* end of AF_INET6 */
1337 /* update length calculations, as payload_length may have changed */
1338 mlen = sizeof (struct GNUNET_EXIT_IcmpServiceMessage) +
1339 alen + payload_length - sizeof (struct GNUNET_TUN_IcmpHeader);
1341 ism->header.size = htons ((uint16_t) mlen);
1342 /* finally, copy payload (if there is any left...) */
1345 payload_length - sizeof (struct GNUNET_TUN_IcmpHeader));
1349 struct GNUNET_EXIT_IcmpInternetMessage *iim;
1350 struct in_addr *ip4dst;
1351 struct in6_addr *ip6dst;
1354 mlen = sizeof (struct GNUNET_EXIT_IcmpInternetMessage) +
1355 alen + payload_length - sizeof (struct GNUNET_TUN_IcmpHeader);
1356 if (mlen >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1361 tnq = GNUNET_malloc (sizeof (struct ChannelMessageQueueEntry) + mlen);
1363 iim = (struct GNUNET_EXIT_IcmpInternetMessage *) &tnq[1];
1364 iim->header.type = htons (GNUNET_MESSAGE_TYPE_VPN_ICMP_TO_INTERNET);
1365 iim->icmp_header = *icmp;
1366 /* Perform ICMP protocol-translation (depending on destination AF and source AF)
1367 and throw away ICMP payload depending on ICMP message type */
1373 case GNUNET_TUN_ICMPTYPE_ECHO_REPLY:
1374 if (destination->details.exit_destination.af == AF_INET6)
1375 iim->icmp_header.type = GNUNET_TUN_ICMPTYPE6_ECHO_REPLY;
1377 case GNUNET_TUN_ICMPTYPE_ECHO_REQUEST:
1378 if (destination->details.exit_destination.af == AF_INET6)
1379 iim->icmp_header.type = GNUNET_TUN_ICMPTYPE6_ECHO_REQUEST;
1381 case GNUNET_TUN_ICMPTYPE_DESTINATION_UNREACHABLE:
1382 if (destination->details.exit_destination.af == AF_INET6)
1383 iim->icmp_header.type = GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE;
1384 /* throw away IP-payload, exit will have to make it up anyway */
1385 payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
1387 case GNUNET_TUN_ICMPTYPE_TIME_EXCEEDED:
1388 if (destination->details.exit_destination.af == AF_INET6)
1389 iim->icmp_header.type = GNUNET_TUN_ICMPTYPE6_TIME_EXCEEDED;
1390 /* throw away IP-payload, exit will have to make it up anyway */
1391 payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
1393 case GNUNET_TUN_ICMPTYPE_SOURCE_QUENCH:
1394 if (destination->details.exit_destination.af == AF_INET6)
1396 GNUNET_STATISTICS_update (stats,
1397 gettext_noop ("# ICMPv4 packets dropped (impossible PT to v6)"),
1402 /* throw away IP-payload, exit will have to make it up anyway */
1403 payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
1406 GNUNET_STATISTICS_update (stats,
1407 gettext_noop ("# ICMPv4 packets dropped (type not allowed)"),
1412 /* end of AF_INET */
1417 case GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE:
1418 if (destination->details.exit_destination.af == AF_INET6)
1419 iim->icmp_header.type = GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE;
1420 /* throw away IP-payload, exit will have to make it up anyway */
1421 payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
1423 case GNUNET_TUN_ICMPTYPE6_TIME_EXCEEDED:
1424 if (destination->details.exit_destination.af == AF_INET)
1425 iim->icmp_header.type = GNUNET_TUN_ICMPTYPE_TIME_EXCEEDED;
1426 /* throw away IP-payload, exit will have to make it up anyway */
1427 payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
1429 case GNUNET_TUN_ICMPTYPE6_PACKET_TOO_BIG:
1430 if (destination->details.exit_destination.af == AF_INET)
1432 GNUNET_STATISTICS_update (stats,
1433 gettext_noop ("# ICMPv6 packets dropped (impossible PT to v4)"),
1438 /* throw away IP-payload, exit will have to make it up anyway */
1439 payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
1441 case GNUNET_TUN_ICMPTYPE6_PARAMETER_PROBLEM:
1442 if (destination->details.exit_destination.af == AF_INET)
1444 GNUNET_STATISTICS_update (stats,
1445 gettext_noop ("# ICMPv6 packets dropped (impossible PT to v4)"),
1450 /* throw away IP-payload, exit will have to make it up anyway */
1451 payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
1453 case GNUNET_TUN_ICMPTYPE6_ECHO_REQUEST:
1454 if (destination->details.exit_destination.af == AF_INET)
1455 iim->icmp_header.type = GNUNET_TUN_ICMPTYPE_ECHO_REQUEST;
1457 case GNUNET_TUN_ICMPTYPE6_ECHO_REPLY:
1458 if (destination->details.exit_destination.af == AF_INET)
1459 iim->icmp_header.type = GNUNET_TUN_ICMPTYPE_ECHO_REPLY;
1462 GNUNET_STATISTICS_update (stats,
1463 gettext_noop ("# ICMPv6 packets dropped (type not allowed)"),
1468 /* end of AF_INET6 */
1473 /* update length calculations, as payload_length may have changed */
1474 mlen = sizeof (struct GNUNET_EXIT_IcmpInternetMessage) +
1475 alen + payload_length - sizeof (struct GNUNET_TUN_IcmpHeader);
1477 iim->header.size = htons ((uint16_t) mlen);
1479 /* need to tell destination ICMP protocol family! */
1480 iim->af = htonl (destination->details.exit_destination.af);
1481 switch (destination->details.exit_destination.af)
1484 ip4dst = (struct in_addr *) &iim[1];
1485 *ip4dst = destination->details.exit_destination.ip.v4;
1486 payload = &ip4dst[1];
1489 ip6dst = (struct in6_addr *) &iim[1];
1490 *ip6dst = destination->details.exit_destination.ip.v6;
1491 payload = &ip6dst[1];
1498 payload_length - sizeof (struct GNUNET_TUN_IcmpHeader));
1502 /* not supported above, how can we get here !? */
1506 send_to_channel (tnq, ts);
1511 * Receive packets from the helper-process (someone send to the local
1512 * virtual channel interface). Find the destination mapping, and if it
1513 * exists, identify the correct MESH channel (or possibly create it)
1514 * and forward the packet.
1516 * @param cls closure, NULL
1517 * @param client NULL
1518 * @param message message we got from the client (VPN channel interface)
1521 message_token (void *cls,
1523 const struct GNUNET_MessageHeader *message)
1525 const struct GNUNET_TUN_Layer2PacketHeader *tun;
1527 struct GNUNET_HashCode key;
1528 struct DestinationEntry *de;
1530 GNUNET_STATISTICS_update (stats,
1531 gettext_noop ("# Packets received from TUN interface"),
1533 mlen = ntohs (message->size);
1534 if ( (ntohs (message->type) != GNUNET_MESSAGE_TYPE_VPN_HELPER) ||
1535 (mlen < sizeof (struct GNUNET_MessageHeader) + sizeof (struct GNUNET_TUN_Layer2PacketHeader)) )
1540 tun = (const struct GNUNET_TUN_Layer2PacketHeader *) &message[1];
1541 mlen -= (sizeof (struct GNUNET_MessageHeader) + sizeof (struct GNUNET_TUN_Layer2PacketHeader));
1542 switch (ntohs (tun->proto))
1546 const struct GNUNET_TUN_IPv6Header *pkt6;
1548 if (mlen < sizeof (struct GNUNET_TUN_IPv6Header))
1554 pkt6 = (const struct GNUNET_TUN_IPv6Header *) &tun[1];
1555 get_destination_key_from_ip (AF_INET6,
1556 &pkt6->destination_address,
1558 de = GNUNET_CONTAINER_multihashmap_get (destination_map, &key);
1561 char buf[INET6_ADDRSTRLEN];
1563 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1564 _("Packet received for unmapped destination `%s' (dropping it)\n"),
1565 inet_ntop (AF_INET6,
1566 &pkt6->destination_address,
1574 &pkt6->source_address,
1575 &pkt6->destination_address,
1577 mlen - sizeof (struct GNUNET_TUN_IPv6Header));
1582 struct GNUNET_TUN_IPv4Header *pkt4;
1584 if (mlen < sizeof (struct GNUNET_TUN_IPv4Header))
1590 pkt4 = (struct GNUNET_TUN_IPv4Header *) &tun[1];
1591 get_destination_key_from_ip (AF_INET,
1592 &pkt4->destination_address,
1594 de = GNUNET_CONTAINER_multihashmap_get (destination_map, &key);
1597 char buf[INET_ADDRSTRLEN];
1599 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1600 _("Packet received for unmapped destination `%s' (dropping it)\n"),
1602 &pkt4->destination_address,
1607 if (pkt4->header_length * 4 != sizeof (struct GNUNET_TUN_IPv4Header))
1609 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1610 _("Received IPv4 packet with options (dropping it)\n"));
1616 &pkt4->source_address,
1617 &pkt4->destination_address,
1619 mlen - sizeof (struct GNUNET_TUN_IPv4Header));
1623 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1624 _("Received packet of unknown protocol %d from TUN (dropping it)\n"),
1625 (unsigned int) ntohs (tun->proto));
1633 * Synthesize a plausible ICMP payload for an ICMP error
1634 * response on the given channel.
1636 * @param ts channel information
1637 * @param ipp IPv4 header to fill in (ICMP payload)
1638 * @param udp "UDP" header to fill in (ICMP payload); might actually
1639 * also be the first 8 bytes of the TCP header
1642 make_up_icmpv4_payload (struct ChannelState *ts,
1643 struct GNUNET_TUN_IPv4Header *ipp,
1644 struct GNUNET_TUN_UdpHeader *udp)
1646 GNUNET_TUN_initialize_ipv4_header (ipp,
1648 sizeof (struct GNUNET_TUN_TcpHeader),
1650 &ts->destination_ip.v4);
1651 udp->source_port = htons (ts->source_port);
1652 udp->destination_port = htons (ts->destination_port);
1653 udp->len = htons (0);
1654 udp->crc = htons (0);
1659 * Synthesize a plausible ICMP payload for an ICMP error
1660 * response on the given channel.
1662 * @param ts channel information
1663 * @param ipp IPv6 header to fill in (ICMP payload)
1664 * @param udp "UDP" header to fill in (ICMP payload); might actually
1665 * also be the first 8 bytes of the TCP header
1668 make_up_icmpv6_payload (struct ChannelState *ts,
1669 struct GNUNET_TUN_IPv6Header *ipp,
1670 struct GNUNET_TUN_UdpHeader *udp)
1672 GNUNET_TUN_initialize_ipv6_header (ipp,
1674 sizeof (struct GNUNET_TUN_TcpHeader),
1676 &ts->destination_ip.v6);
1677 udp->source_port = htons (ts->source_port);
1678 udp->destination_port = htons (ts->destination_port);
1679 udp->len = htons (0);
1680 udp->crc = htons (0);
1685 * We got an ICMP packet back from the MESH channel. Pass it on to the
1686 * local virtual interface via the helper.
1688 * @param cls closure, NULL
1689 * @param channel connection to the other end
1690 * @param channel_ctx pointer to our 'struct ChannelState *'
1691 * @param message the actual message
1692 * @return #GNUNET_OK to keep the connection open,
1693 * #GNUNET_SYSERR to close it (signal serious error)
1696 receive_icmp_back (void *cls,
1697 struct GNUNET_MESH_Channel *channel,
1699 const struct GNUNET_MessageHeader *message)
1701 struct ChannelState *ts = *channel_ctx;
1702 const struct GNUNET_EXIT_IcmpToVPNMessage *i2v;
1705 GNUNET_STATISTICS_update (stats,
1706 gettext_noop ("# ICMP packets received from mesh"),
1708 mlen = ntohs (message->size);
1709 if (mlen < sizeof (struct GNUNET_EXIT_IcmpToVPNMessage))
1711 GNUNET_break_op (0);
1712 return GNUNET_SYSERR;
1714 if (NULL == ts->heap_node)
1716 GNUNET_break_op (0);
1717 return GNUNET_SYSERR;
1719 if (AF_UNSPEC == ts->af)
1721 GNUNET_break_op (0);
1722 return GNUNET_SYSERR;
1724 i2v = (const struct GNUNET_EXIT_IcmpToVPNMessage *) message;
1725 mlen -= sizeof (struct GNUNET_EXIT_IcmpToVPNMessage);
1727 char sbuf[INET6_ADDRSTRLEN];
1728 char dbuf[INET6_ADDRSTRLEN];
1730 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1731 "Received ICMP packet from mesh, sending %u bytes from %s -> %s via TUN\n",
1732 (unsigned int) mlen,
1733 inet_ntop (ts->af, &ts->destination_ip, sbuf, sizeof (sbuf)),
1734 inet_ntop (ts->af, &ts->source_ip, dbuf, sizeof (dbuf)));
1740 size_t size = sizeof (struct GNUNET_TUN_IPv4Header)
1741 + sizeof (struct GNUNET_TUN_IcmpHeader)
1742 + sizeof (struct GNUNET_MessageHeader) +
1743 sizeof (struct GNUNET_TUN_Layer2PacketHeader) +
1746 /* reserve some extra space in case we have an ICMP type here where
1747 we will need to make up the payload ourselves */
1748 char buf[size + sizeof (struct GNUNET_TUN_IPv4Header) + 8] GNUNET_ALIGN;
1749 struct GNUNET_MessageHeader *msg = (struct GNUNET_MessageHeader *) buf;
1750 struct GNUNET_TUN_Layer2PacketHeader *tun = (struct GNUNET_TUN_Layer2PacketHeader*) &msg[1];
1751 struct GNUNET_TUN_IPv4Header *ipv4 = (struct GNUNET_TUN_IPv4Header *) &tun[1];
1752 struct GNUNET_TUN_IcmpHeader *icmp = (struct GNUNET_TUN_IcmpHeader *) &ipv4[1];
1753 msg->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
1754 tun->flags = htons (0);
1755 tun->proto = htons (ETH_P_IPV4);
1756 GNUNET_TUN_initialize_ipv4_header (ipv4,
1758 sizeof (struct GNUNET_TUN_IcmpHeader) + mlen,
1759 &ts->destination_ip.v4,
1761 *icmp = i2v->icmp_header;
1765 /* For some ICMP types, we need to adjust (make up) the payload here.
1766 Also, depending on the AF used on the other side, we have to
1767 do ICMP PT (translate ICMP types) */
1768 switch (ntohl (i2v->af))
1773 case GNUNET_TUN_ICMPTYPE_ECHO_REPLY:
1774 case GNUNET_TUN_ICMPTYPE_ECHO_REQUEST:
1776 case GNUNET_TUN_ICMPTYPE_DESTINATION_UNREACHABLE:
1777 case GNUNET_TUN_ICMPTYPE_SOURCE_QUENCH:
1778 case GNUNET_TUN_ICMPTYPE_TIME_EXCEEDED:
1780 struct GNUNET_TUN_IPv4Header *ipp = (struct GNUNET_TUN_IPv4Header *) &icmp[1];
1781 struct GNUNET_TUN_UdpHeader *udp = (struct GNUNET_TUN_UdpHeader *) &ipp[1];
1785 /* sender did not strip ICMP payload? */
1786 GNUNET_break_op (0);
1787 return GNUNET_SYSERR;
1789 size += sizeof (struct GNUNET_TUN_IPv4Header) + 8;
1790 GNUNET_assert (8 == sizeof (struct GNUNET_TUN_UdpHeader));
1791 make_up_icmpv4_payload (ts, ipp, udp);
1795 GNUNET_break_op (0);
1796 GNUNET_STATISTICS_update (stats,
1797 gettext_noop ("# ICMPv4 packets dropped (type not allowed)"),
1799 return GNUNET_SYSERR;
1804 /* ICMP PT 6-to-4 and possibly making up payloads */
1807 case GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE:
1808 icmp->type = GNUNET_TUN_ICMPTYPE_DESTINATION_UNREACHABLE;
1810 struct GNUNET_TUN_IPv4Header *ipp = (struct GNUNET_TUN_IPv4Header *) &icmp[1];
1811 struct GNUNET_TUN_UdpHeader *udp = (struct GNUNET_TUN_UdpHeader *) &ipp[1];
1815 /* sender did not strip ICMP payload? */
1816 GNUNET_break_op (0);
1817 return GNUNET_SYSERR;
1819 size += sizeof (struct GNUNET_TUN_IPv4Header) + 8;
1820 GNUNET_assert (8 == sizeof (struct GNUNET_TUN_UdpHeader));
1821 make_up_icmpv4_payload (ts, ipp, udp);
1824 case GNUNET_TUN_ICMPTYPE6_TIME_EXCEEDED:
1825 icmp->type = GNUNET_TUN_ICMPTYPE_TIME_EXCEEDED;
1827 struct GNUNET_TUN_IPv4Header *ipp = (struct GNUNET_TUN_IPv4Header *) &icmp[1];
1828 struct GNUNET_TUN_UdpHeader *udp = (struct GNUNET_TUN_UdpHeader *) &ipp[1];
1832 /* sender did not strip ICMP payload? */
1833 GNUNET_break_op (0);
1834 return GNUNET_SYSERR;
1836 size += sizeof (struct GNUNET_TUN_IPv4Header) + 8;
1837 GNUNET_assert (8 == sizeof (struct GNUNET_TUN_UdpHeader));
1838 make_up_icmpv4_payload (ts, ipp, udp);
1841 case GNUNET_TUN_ICMPTYPE6_PACKET_TOO_BIG:
1842 case GNUNET_TUN_ICMPTYPE6_PARAMETER_PROBLEM:
1843 GNUNET_STATISTICS_update (stats,
1844 gettext_noop ("# ICMPv6 packets dropped (impossible PT to v4)"),
1847 case GNUNET_TUN_ICMPTYPE6_ECHO_REQUEST:
1848 icmp->type = GNUNET_TUN_ICMPTYPE_ECHO_REQUEST;
1850 case GNUNET_TUN_ICMPTYPE6_ECHO_REPLY:
1851 icmp->type = GNUNET_TUN_ICMPTYPE_ECHO_REPLY;
1854 GNUNET_break_op (0);
1855 GNUNET_STATISTICS_update (stats,
1856 gettext_noop ("# ICMPv6 packets dropped (type not allowed)"),
1858 return GNUNET_SYSERR;
1863 GNUNET_break_op (0);
1864 return GNUNET_SYSERR;
1866 msg->size = htons (size);
1867 GNUNET_TUN_calculate_icmp_checksum (icmp,
1870 (void) GNUNET_HELPER_send (helper_handle,
1879 size_t size = sizeof (struct GNUNET_TUN_IPv6Header)
1880 + sizeof (struct GNUNET_TUN_IcmpHeader)
1881 + sizeof (struct GNUNET_MessageHeader) +
1882 sizeof (struct GNUNET_TUN_Layer2PacketHeader) +
1885 char buf[size + sizeof (struct GNUNET_TUN_IPv6Header) + 8] GNUNET_ALIGN;
1886 struct GNUNET_MessageHeader *msg = (struct GNUNET_MessageHeader *) buf;
1887 struct GNUNET_TUN_Layer2PacketHeader *tun = (struct GNUNET_TUN_Layer2PacketHeader*) &msg[1];
1888 struct GNUNET_TUN_IPv6Header *ipv6 = (struct GNUNET_TUN_IPv6Header *) &tun[1];
1889 struct GNUNET_TUN_IcmpHeader *icmp = (struct GNUNET_TUN_IcmpHeader *) &ipv6[1];
1890 msg->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
1891 tun->flags = htons (0);
1892 tun->proto = htons (ETH_P_IPV6);
1893 GNUNET_TUN_initialize_ipv6_header (ipv6,
1895 sizeof (struct GNUNET_TUN_IcmpHeader) + mlen,
1896 &ts->destination_ip.v6,
1898 *icmp = i2v->icmp_header;
1903 /* For some ICMP types, we need to adjust (make up) the payload here.
1904 Also, depending on the AF used on the other side, we have to
1905 do ICMP PT (translate ICMP types) */
1906 switch (ntohl (i2v->af))
1909 /* ICMP PT 4-to-6 and possibly making up payloads */
1912 case GNUNET_TUN_ICMPTYPE_ECHO_REPLY:
1913 icmp->type = GNUNET_TUN_ICMPTYPE6_ECHO_REPLY;
1915 case GNUNET_TUN_ICMPTYPE_ECHO_REQUEST:
1916 icmp->type = GNUNET_TUN_ICMPTYPE6_ECHO_REQUEST;
1918 case GNUNET_TUN_ICMPTYPE_DESTINATION_UNREACHABLE:
1919 icmp->type = GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE;
1921 struct GNUNET_TUN_IPv6Header *ipp = (struct GNUNET_TUN_IPv6Header *) &icmp[1];
1922 struct GNUNET_TUN_UdpHeader *udp = (struct GNUNET_TUN_UdpHeader *) &ipp[1];
1926 /* sender did not strip ICMP payload? */
1927 GNUNET_break_op (0);
1928 return GNUNET_SYSERR;
1930 size += sizeof (struct GNUNET_TUN_IPv6Header) + 8;
1931 GNUNET_assert (8 == sizeof (struct GNUNET_TUN_UdpHeader));
1932 make_up_icmpv6_payload (ts, ipp, udp);
1935 case GNUNET_TUN_ICMPTYPE_TIME_EXCEEDED:
1936 icmp->type = GNUNET_TUN_ICMPTYPE6_TIME_EXCEEDED;
1938 struct GNUNET_TUN_IPv6Header *ipp = (struct GNUNET_TUN_IPv6Header *) &icmp[1];
1939 struct GNUNET_TUN_UdpHeader *udp = (struct GNUNET_TUN_UdpHeader *) &ipp[1];
1943 /* sender did not strip ICMP payload? */
1944 GNUNET_break_op (0);
1945 return GNUNET_SYSERR;
1947 size += sizeof (struct GNUNET_TUN_IPv6Header) + 8;
1948 GNUNET_assert (8 == sizeof (struct GNUNET_TUN_UdpHeader));
1949 make_up_icmpv6_payload (ts, ipp, udp);
1952 case GNUNET_TUN_ICMPTYPE_SOURCE_QUENCH:
1953 GNUNET_STATISTICS_update (stats,
1954 gettext_noop ("# ICMPv4 packets dropped (impossible PT to v6)"),
1958 GNUNET_break_op (0);
1959 GNUNET_STATISTICS_update (stats,
1960 gettext_noop ("# ICMPv4 packets dropped (type not allowed)"),
1962 return GNUNET_SYSERR;
1969 case GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE:
1970 case GNUNET_TUN_ICMPTYPE6_TIME_EXCEEDED:
1971 case GNUNET_TUN_ICMPTYPE6_PACKET_TOO_BIG:
1972 case GNUNET_TUN_ICMPTYPE6_PARAMETER_PROBLEM:
1974 struct GNUNET_TUN_IPv6Header *ipp = (struct GNUNET_TUN_IPv6Header *) &icmp[1];
1975 struct GNUNET_TUN_UdpHeader *udp = (struct GNUNET_TUN_UdpHeader *) &ipp[1];
1979 /* sender did not strip ICMP payload? */
1980 GNUNET_break_op (0);
1981 return GNUNET_SYSERR;
1983 size += sizeof (struct GNUNET_TUN_IPv6Header) + 8;
1984 GNUNET_assert (8 == sizeof (struct GNUNET_TUN_UdpHeader));
1985 make_up_icmpv6_payload (ts, ipp, udp);
1988 case GNUNET_TUN_ICMPTYPE6_ECHO_REQUEST:
1991 GNUNET_break_op (0);
1992 GNUNET_STATISTICS_update (stats,
1993 gettext_noop ("# ICMPv6 packets dropped (type not allowed)"),
1995 return GNUNET_SYSERR;
2000 GNUNET_break_op (0);
2001 return GNUNET_SYSERR;
2003 msg->size = htons (size);
2004 GNUNET_TUN_calculate_icmp_checksum (icmp,
2006 (void) GNUNET_HELPER_send (helper_handle,
2016 GNUNET_CONTAINER_heap_update_cost (channel_heap,
2018 GNUNET_TIME_absolute_get ().abs_value_us);
2024 * We got a UDP packet back from the MESH channel. Pass it on to the
2025 * local virtual interface via the helper.
2027 * @param cls closure, NULL
2028 * @param channel connection to the other end
2029 * @param channel_ctx pointer to our 'struct ChannelState *'
2030 * @param message the actual message
2031 * @return #GNUNET_OK to keep the connection open,
2032 * #GNUNET_SYSERR to close it (signal serious error)
2035 receive_udp_back (void *cls,
2036 struct GNUNET_MESH_Channel *channel,
2038 const struct GNUNET_MessageHeader *message)
2040 struct ChannelState *ts = *channel_ctx;
2041 const struct GNUNET_EXIT_UdpReplyMessage *reply;
2044 GNUNET_STATISTICS_update (stats,
2045 gettext_noop ("# UDP packets received from mesh"),
2047 mlen = ntohs (message->size);
2048 if (mlen < sizeof (struct GNUNET_EXIT_UdpReplyMessage))
2050 GNUNET_break_op (0);
2051 return GNUNET_SYSERR;
2053 if (NULL == ts->heap_node)
2055 GNUNET_break_op (0);
2056 return GNUNET_SYSERR;
2058 if (AF_UNSPEC == ts->af)
2060 GNUNET_break_op (0);
2061 return GNUNET_SYSERR;
2063 reply = (const struct GNUNET_EXIT_UdpReplyMessage *) message;
2064 mlen -= sizeof (struct GNUNET_EXIT_UdpReplyMessage);
2066 char sbuf[INET6_ADDRSTRLEN];
2067 char dbuf[INET6_ADDRSTRLEN];
2069 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2070 "Received UDP reply from mesh, sending %u bytes from %s:%u -> %s:%u via TUN\n",
2071 (unsigned int) mlen,
2072 inet_ntop (ts->af, &ts->destination_ip, sbuf, sizeof (sbuf)),
2073 ts->destination_port,
2074 inet_ntop (ts->af, &ts->source_ip, dbuf, sizeof (dbuf)),
2081 size_t size = sizeof (struct GNUNET_TUN_IPv4Header)
2082 + sizeof (struct GNUNET_TUN_UdpHeader)
2083 + sizeof (struct GNUNET_MessageHeader) +
2084 sizeof (struct GNUNET_TUN_Layer2PacketHeader) +
2087 char buf[size] GNUNET_ALIGN;
2088 struct GNUNET_MessageHeader *msg = (struct GNUNET_MessageHeader *) buf;
2089 struct GNUNET_TUN_Layer2PacketHeader *tun = (struct GNUNET_TUN_Layer2PacketHeader*) &msg[1];
2090 struct GNUNET_TUN_IPv4Header *ipv4 = (struct GNUNET_TUN_IPv4Header *) &tun[1];
2091 struct GNUNET_TUN_UdpHeader *udp = (struct GNUNET_TUN_UdpHeader *) &ipv4[1];
2092 msg->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
2093 msg->size = htons (size);
2094 tun->flags = htons (0);
2095 tun->proto = htons (ETH_P_IPV4);
2096 GNUNET_TUN_initialize_ipv4_header (ipv4,
2098 sizeof (struct GNUNET_TUN_UdpHeader) + mlen,
2099 &ts->destination_ip.v4,
2101 if (0 == ntohs (reply->source_port))
2102 udp->source_port = htons (ts->destination_port);
2104 udp->source_port = reply->source_port;
2105 if (0 == ntohs (reply->destination_port))
2106 udp->destination_port = htons (ts->source_port);
2108 udp->destination_port = reply->destination_port;
2109 udp->len = htons (mlen + sizeof (struct GNUNET_TUN_UdpHeader));
2110 GNUNET_TUN_calculate_udp4_checksum (ipv4,
2117 (void) GNUNET_HELPER_send (helper_handle,
2126 size_t size = sizeof (struct GNUNET_TUN_IPv6Header)
2127 + sizeof (struct GNUNET_TUN_UdpHeader)
2128 + sizeof (struct GNUNET_MessageHeader) +
2129 sizeof (struct GNUNET_TUN_Layer2PacketHeader) +
2132 char buf[size] GNUNET_ALIGN;
2133 struct GNUNET_MessageHeader *msg = (struct GNUNET_MessageHeader *) buf;
2134 struct GNUNET_TUN_Layer2PacketHeader *tun = (struct GNUNET_TUN_Layer2PacketHeader*) &msg[1];
2135 struct GNUNET_TUN_IPv6Header *ipv6 = (struct GNUNET_TUN_IPv6Header *) &tun[1];
2136 struct GNUNET_TUN_UdpHeader *udp = (struct GNUNET_TUN_UdpHeader *) &ipv6[1];
2137 msg->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
2138 msg->size = htons (size);
2139 tun->flags = htons (0);
2140 tun->proto = htons (ETH_P_IPV6);
2141 GNUNET_TUN_initialize_ipv6_header (ipv6,
2143 sizeof (struct GNUNET_TUN_UdpHeader) + mlen,
2144 &ts->destination_ip.v6,
2146 if (0 == ntohs (reply->source_port))
2147 udp->source_port = htons (ts->destination_port);
2149 udp->source_port = reply->source_port;
2150 if (0 == ntohs (reply->destination_port))
2151 udp->destination_port = htons (ts->source_port);
2153 udp->destination_port = reply->destination_port;
2154 udp->len = htons (mlen + sizeof (struct GNUNET_TUN_UdpHeader));
2155 GNUNET_TUN_calculate_udp6_checksum (ipv6,
2161 (void) GNUNET_HELPER_send (helper_handle,
2171 GNUNET_CONTAINER_heap_update_cost (channel_heap,
2173 GNUNET_TIME_absolute_get ().abs_value_us);
2179 * We got a TCP packet back from the MESH channel. Pass it on to the
2180 * local virtual interface via the helper.
2182 * @param cls closure, NULL
2183 * @param channel connection to the other end
2184 * @param channel_ctx pointer to our `struct ChannelState *`
2185 * @param message the actual message
2186 * @return #GNUNET_OK to keep the connection open,
2187 * #GNUNET_SYSERR to close it (signal serious error)
2190 receive_tcp_back (void *cls,
2191 struct GNUNET_MESH_Channel *channel,
2193 const struct GNUNET_MessageHeader *message)
2195 struct ChannelState *ts = *channel_ctx;
2196 const struct GNUNET_EXIT_TcpDataMessage *data;
2199 GNUNET_STATISTICS_update (stats,
2200 gettext_noop ("# TCP packets received from mesh"),
2202 mlen = ntohs (message->size);
2203 if (mlen < sizeof (struct GNUNET_EXIT_TcpDataMessage))
2205 GNUNET_break_op (0);
2206 return GNUNET_SYSERR;
2208 if (NULL == ts->heap_node)
2210 GNUNET_break_op (0);
2211 return GNUNET_SYSERR;
2213 data = (const struct GNUNET_EXIT_TcpDataMessage *) message;
2214 mlen -= sizeof (struct GNUNET_EXIT_TcpDataMessage);
2216 char sbuf[INET6_ADDRSTRLEN];
2217 char dbuf[INET6_ADDRSTRLEN];
2219 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2220 "Received TCP reply from mesh, sending %u bytes from %s:%u -> %s:%u via TUN\n",
2221 (unsigned int) mlen,
2222 inet_ntop (ts->af, &ts->destination_ip, sbuf, sizeof (sbuf)),
2223 ts->destination_port,
2224 inet_ntop (ts->af, &ts->source_ip, dbuf, sizeof (dbuf)),
2227 if (data->tcp_header.off * 4 < sizeof (struct GNUNET_TUN_TcpHeader))
2229 GNUNET_break_op (0);
2230 return GNUNET_SYSERR;
2236 size_t size = sizeof (struct GNUNET_TUN_IPv4Header)
2237 + sizeof (struct GNUNET_TUN_TcpHeader)
2238 + sizeof (struct GNUNET_MessageHeader) +
2239 sizeof (struct GNUNET_TUN_Layer2PacketHeader) +
2242 char buf[size] GNUNET_ALIGN;
2243 struct GNUNET_MessageHeader *msg = (struct GNUNET_MessageHeader *) buf;
2244 struct GNUNET_TUN_Layer2PacketHeader *tun = (struct GNUNET_TUN_Layer2PacketHeader*) &msg[1];
2245 struct GNUNET_TUN_IPv4Header *ipv4 = (struct GNUNET_TUN_IPv4Header *) &tun[1];
2246 struct GNUNET_TUN_TcpHeader *tcp = (struct GNUNET_TUN_TcpHeader *) &ipv4[1];
2247 msg->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
2248 msg->size = htons (size);
2249 tun->flags = htons (0);
2250 tun->proto = htons (ETH_P_IPV4);
2251 GNUNET_TUN_initialize_ipv4_header (ipv4,
2253 sizeof (struct GNUNET_TUN_TcpHeader) + mlen,
2254 &ts->destination_ip.v4,
2256 *tcp = data->tcp_header;
2257 tcp->source_port = htons (ts->destination_port);
2258 tcp->destination_port = htons (ts->source_port);
2259 GNUNET_TUN_calculate_tcp4_checksum (ipv4,
2266 (void) GNUNET_HELPER_send (helper_handle,
2275 size_t size = sizeof (struct GNUNET_TUN_IPv6Header)
2276 + sizeof (struct GNUNET_TUN_TcpHeader)
2277 + sizeof (struct GNUNET_MessageHeader) +
2278 sizeof (struct GNUNET_TUN_Layer2PacketHeader) +
2281 char buf[size] GNUNET_ALIGN;
2282 struct GNUNET_MessageHeader *msg = (struct GNUNET_MessageHeader *) buf;
2283 struct GNUNET_TUN_Layer2PacketHeader *tun = (struct GNUNET_TUN_Layer2PacketHeader*) &msg[1];
2284 struct GNUNET_TUN_IPv6Header *ipv6 = (struct GNUNET_TUN_IPv6Header *) &tun[1];
2285 struct GNUNET_TUN_TcpHeader *tcp = (struct GNUNET_TUN_TcpHeader *) &ipv6[1];
2286 msg->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
2287 msg->size = htons (size);
2288 tun->flags = htons (0);
2289 tun->proto = htons (ETH_P_IPV6);
2290 GNUNET_TUN_initialize_ipv6_header (ipv6,
2292 sizeof (struct GNUNET_TUN_TcpHeader) + mlen,
2293 &ts->destination_ip.v6,
2295 *tcp = data->tcp_header;
2296 tcp->source_port = htons (ts->destination_port);
2297 tcp->destination_port = htons (ts->source_port);
2298 GNUNET_TUN_calculate_tcp6_checksum (ipv6,
2305 (void) GNUNET_HELPER_send (helper_handle,
2313 GNUNET_CONTAINER_heap_update_cost (channel_heap,
2315 GNUNET_TIME_absolute_get ().abs_value_us);
2321 * Allocate an IPv4 address from the range of the channel
2322 * for a new redirection.
2324 * @param v4 where to store the address
2325 * @return #GNUNET_OK on success,
2326 * #GNUNET_SYSERR on error
2329 allocate_v4_address (struct in_addr *v4)
2331 const char *ipv4addr = vpn_argv[4];
2332 const char *ipv4mask = vpn_argv[5];
2333 struct in_addr addr;
2334 struct in_addr mask;
2336 struct GNUNET_HashCode key;
2339 GNUNET_assert (1 == inet_pton (AF_INET, ipv4addr, &addr));
2340 GNUNET_assert (1 == inet_pton (AF_INET, ipv4mask, &mask));
2341 /* Given 192.168.0.1/255.255.0.0, we want a mask
2342 of '192.168.255.255', thus: */
2343 mask.s_addr = addr.s_addr | ~mask.s_addr;
2350 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
2351 _("Failed to find unallocated IPv4 address in VPN's range\n"));
2352 return GNUNET_SYSERR;
2354 /* Pick random IPv4 address within the subnet, except 'addr' or 'mask' itself */
2355 rnd.s_addr = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
2357 v4->s_addr = (addr.s_addr | rnd.s_addr) & mask.s_addr;
2358 get_destination_key_from_ip (AF_INET,
2362 while ( (GNUNET_YES ==
2363 GNUNET_CONTAINER_multihashmap_contains (destination_map,
2365 (v4->s_addr == addr.s_addr) ||
2366 (v4->s_addr == mask.s_addr) );
2372 * Allocate an IPv6 address from the range of the channel
2373 * for a new redirection.
2375 * @param v6 where to store the address
2376 * @return #GNUNET_OK on success,
2377 * #GNUNET_SYSERR on error
2380 allocate_v6_address (struct in6_addr *v6)
2382 const char *ipv6addr = vpn_argv[2];
2383 struct in6_addr addr;
2384 struct in6_addr mask;
2385 struct in6_addr rnd;
2387 struct GNUNET_HashCode key;
2390 GNUNET_assert (1 == inet_pton (AF_INET6, ipv6addr, &addr));
2391 GNUNET_assert (ipv6prefix < 128);
2392 /* Given ABCD::/96, we want a mask of 'ABCD::FFFF:FFFF,
2395 for (i=127;i>=ipv6prefix;i--)
2396 mask.s6_addr[i / 8] |= (1 << (i % 8));
2398 /* Pick random IPv6 address within the subnet, except 'addr' or 'mask' itself */
2405 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
2406 _("Failed to find unallocated IPv6 address in VPN's range\n"));
2407 return GNUNET_SYSERR;
2412 rnd.s6_addr[i] = (unsigned char) GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
2415 = (addr.s6_addr[i] | rnd.s6_addr[i]) & mask.s6_addr[i];
2417 get_destination_key_from_ip (AF_INET6,
2421 while ( (GNUNET_YES ==
2422 GNUNET_CONTAINER_multihashmap_contains (destination_map,
2426 sizeof (struct in6_addr))) ||
2429 sizeof (struct in6_addr))) );
2435 * Free resources occupied by a destination entry.
2437 * @param de entry to free
2440 free_destination_entry (struct DestinationEntry *de)
2442 struct DestinationChannel *dt;
2444 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2445 "Cleaning up destination entry\n");
2446 GNUNET_STATISTICS_update (stats,
2447 gettext_noop ("# Active destinations"),
2449 while (NULL != (dt = de->dt_head))
2451 GNUNET_CONTAINER_DLL_remove (de->dt_head,
2456 free_channel_state (dt->ts);
2457 GNUNET_assert (NULL == dt->ts);
2461 if (NULL != de->heap_node)
2463 GNUNET_CONTAINER_heap_remove_node (de->heap_node);
2464 de->heap_node = NULL;
2465 GNUNET_assert (GNUNET_YES ==
2466 GNUNET_CONTAINER_multihashmap_remove (destination_map,
2475 * We have too many active destinations. Clean up the oldest destination.
2477 * @param except destination that must NOT be cleaned up, even if it is the oldest
2480 expire_destination (struct DestinationEntry *except)
2482 struct DestinationEntry *de;
2484 de = GNUNET_CONTAINER_heap_peek (destination_heap);
2485 GNUNET_assert (NULL != de);
2487 return; /* can't do this */
2488 free_destination_entry (de);
2493 * Allocate an IP address for the response.
2495 * @param result_af desired address family; set to the actual
2496 * address family; can initially be AF_UNSPEC if there
2497 * is no preference; will be set to AF_UNSPEC if the
2499 * @param addr set to either v4 or v6 depending on which
2500 * storage location was used; set to NULL if allocation failed
2501 * @param v4 storage space for an IPv4 address
2502 * @param v6 storage space for an IPv6 address
2503 * @return #GNUNET_OK normally, #GNUNET_SYSERR if `* result_af` was
2504 * an unsupported address family (not AF_INET, AF_INET6 or AF_UNSPEC)
2507 allocate_response_ip (int *result_af,
2510 struct in6_addr *v6)
2517 allocate_v4_address (v4))
2518 *result_af = AF_UNSPEC;
2524 allocate_v6_address (v6))
2525 *result_af = AF_UNSPEC;
2531 allocate_v4_address (v4))
2534 *result_af = AF_INET;
2536 else if (GNUNET_OK ==
2537 allocate_v6_address (v6))
2540 *result_af = AF_INET6;
2545 return GNUNET_SYSERR;
2552 * A client asks us to setup a redirection via some exit node to a
2553 * particular IP. Setup the redirection and give the client the
2557 * @param client requesting client
2558 * @param message redirection request (a `struct RedirectToIpRequestMessage`)
2561 service_redirect_to_ip (void *cls,
2562 struct GNUNET_SERVER_Client *client,
2563 const struct GNUNET_MessageHeader *message)
2567 const struct RedirectToIpRequestMessage *msg;
2573 struct DestinationEntry *de;
2574 struct GNUNET_HashCode key;
2576 /* validate and parse request */
2577 mlen = ntohs (message->size);
2578 if (mlen < sizeof (struct RedirectToIpRequestMessage))
2581 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2584 alen = mlen - sizeof (struct RedirectToIpRequestMessage);
2585 msg = (const struct RedirectToIpRequestMessage *) message;
2586 addr_af = (int) htonl (msg->addr_af);
2590 if (alen != sizeof (struct in_addr))
2593 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2598 if (alen != sizeof (struct in6_addr))
2601 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2607 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2611 /* allocate response IP */
2612 result_af = (int) htonl (msg->result_af);
2613 if (GNUNET_OK != allocate_response_ip (&result_af,
2617 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2620 /* send reply with our IP address */
2621 send_client_reply (client,
2625 if (result_af == AF_UNSPEC)
2627 /* failure, we're done */
2628 GNUNET_SERVER_receive_done (client, GNUNET_OK);
2633 char sbuf[INET6_ADDRSTRLEN];
2634 char dbuf[INET6_ADDRSTRLEN];
2636 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2637 "Allocated address %s for redirection via exit to %s\n",
2638 inet_ntop (result_af, addr, sbuf, sizeof (sbuf)),
2640 &msg[1], dbuf, sizeof (dbuf)));
2643 /* setup destination record */
2644 de = GNUNET_new (struct DestinationEntry);
2645 de->is_service = GNUNET_NO;
2646 de->details.exit_destination.af = addr_af;
2647 memcpy (&de->details.exit_destination.ip,
2650 get_destination_key_from_ip (result_af,
2654 GNUNET_assert (GNUNET_OK ==
2655 GNUNET_CONTAINER_multihashmap_put (destination_map,
2658 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE));
2659 de->heap_node = GNUNET_CONTAINER_heap_insert (destination_heap,
2661 GNUNET_TIME_absolute_ntoh (msg->expiration_time).abs_value_us);
2662 GNUNET_STATISTICS_update (stats,
2663 gettext_noop ("# Active destinations"),
2665 while (GNUNET_CONTAINER_multihashmap_size (destination_map) > max_destination_mappings)
2666 expire_destination (de);
2667 GNUNET_SERVER_receive_done (client, GNUNET_OK);
2672 * A client asks us to setup a redirection to a particular peer
2673 * offering a service. Setup the redirection and give the client the
2677 * @param client requesting client
2678 * @param message redirection request (a `struct RedirectToPeerRequestMessage`)
2681 service_redirect_to_service (void *cls,
2682 struct GNUNET_SERVER_Client *client,
2683 const struct GNUNET_MessageHeader *message)
2685 const struct RedirectToServiceRequestMessage *msg;
2690 struct DestinationEntry *de;
2691 struct GNUNET_HashCode key;
2692 struct ChannelState *ts;
2693 struct DestinationChannel *dt;
2696 msg = (const struct RedirectToServiceRequestMessage *) message;
2698 /* allocate response IP */
2699 result_af = (int) htonl (msg->result_af);
2700 if (GNUNET_OK != allocate_response_ip (&result_af,
2704 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2707 send_client_reply (client,
2711 if (result_af == AF_UNSPEC)
2713 /* failure, we're done */
2714 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2715 _("Failed to allocate IP address for new destination\n"));
2716 GNUNET_SERVER_receive_done (client, GNUNET_OK);
2721 char sbuf[INET6_ADDRSTRLEN];
2723 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2724 "Allocated address %s for redirection to service %s on peer %s\n",
2725 inet_ntop (result_af, addr, sbuf, sizeof (sbuf)),
2726 GNUNET_h2s (&msg->service_descriptor),
2727 GNUNET_i2s (&msg->target));
2730 /* setup destination record */
2731 de = GNUNET_new (struct DestinationEntry);
2732 de->is_service = GNUNET_YES;
2733 de->details.service_destination.service_descriptor = msg->service_descriptor;
2734 de->details.service_destination.target = msg->target;
2735 get_destination_key_from_ip (result_af,
2739 GNUNET_assert (GNUNET_OK ==
2740 GNUNET_CONTAINER_multihashmap_put (destination_map,
2743 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE));
2744 de->heap_node = GNUNET_CONTAINER_heap_insert (destination_heap,
2746 GNUNET_TIME_absolute_ntoh (msg->expiration_time).abs_value_us);
2747 while (GNUNET_CONTAINER_multihashmap_size (destination_map) > max_destination_mappings)
2748 expire_destination (de);
2750 dt = GNUNET_new (struct DestinationChannel);
2751 dt->destination = de;
2752 GNUNET_CONTAINER_DLL_insert (de->dt_head,
2755 ts = create_channel_to_destination (dt,
2760 ts->destination_ip.v4 = v4;
2763 ts->destination_ip.v6 = v6;
2769 GNUNET_SERVER_receive_done (client, GNUNET_OK);
2774 * Function called whenever a channel is destroyed. Should clean up
2775 * any associated state.
2777 * @param cls closure (set from #GNUNET_MESH_connect)
2778 * @param channel connection to the other end (henceforth invalid)
2779 * @param channel_ctx place where local state associated
2780 * with the channel is stored (our `struct ChannelState`)
2783 channel_cleaner (void *cls,
2784 const struct GNUNET_MESH_Channel *channel,
2787 struct ChannelState *ts = channel_ctx;
2789 ts->channel = NULL; /* we must not call GNUNET_MESH_channel_destroy() anymore */
2790 free_channel_state (ts);
2795 * Free memory occupied by an entry in the destination map.
2799 * @param value a `struct DestinationEntry *`
2800 * @return #GNUNET_OK (continue to iterate)
2803 cleanup_destination (void *cls,
2804 const struct GNUNET_HashCode *key,
2807 struct DestinationEntry *de = value;
2809 free_destination_entry (de);
2815 * Free memory occupied by an entry in the channel map.
2819 * @param value a `struct ChannelState *`
2820 * @return #GNUNET_OK (continue to iterate)
2823 cleanup_channel (void *cls,
2824 const struct GNUNET_HashCode *key,
2827 struct ChannelState *ts = value;
2829 free_channel_state (ts);
2835 * Function scheduled as very last function, cleans up after us
2842 const struct GNUNET_SCHEDULER_TaskContext *tc)
2846 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2847 "VPN is shutting down\n");
2848 if (NULL != destination_map)
2850 GNUNET_CONTAINER_multihashmap_iterate (destination_map,
2851 &cleanup_destination,
2853 GNUNET_CONTAINER_multihashmap_destroy (destination_map);
2854 destination_map = NULL;
2856 if (NULL != destination_heap)
2858 GNUNET_CONTAINER_heap_destroy (destination_heap);
2859 destination_heap = NULL;
2861 if (NULL != channel_map)
2863 GNUNET_CONTAINER_multihashmap_iterate (channel_map,
2866 GNUNET_CONTAINER_multihashmap_destroy (channel_map);
2869 if (NULL != channel_heap)
2871 GNUNET_CONTAINER_heap_destroy (channel_heap);
2872 channel_heap = NULL;
2874 if (NULL != mesh_handle)
2876 GNUNET_MESH_disconnect (mesh_handle);
2879 if (NULL != helper_handle)
2881 GNUNET_HELPER_stop (helper_handle, GNUNET_NO);
2882 helper_handle = NULL;
2886 GNUNET_SERVER_notification_context_destroy (nc);
2891 GNUNET_STATISTICS_destroy (stats, GNUNET_NO);
2895 GNUNET_free_non_null (vpn_argv[i]);
2900 * Main function that will be run by the scheduler.
2902 * @param cls closure
2903 * @param server the initialized server
2904 * @param cfg_ configuration
2908 struct GNUNET_SERVER_Handle *server,
2909 const struct GNUNET_CONFIGURATION_Handle *cfg_)
2911 static const struct GNUNET_SERVER_MessageHandler service_handlers[] = {
2912 /* callback, cls, type, size */
2913 { &service_redirect_to_ip, NULL, GNUNET_MESSAGE_TYPE_VPN_CLIENT_REDIRECT_TO_IP, 0},
2914 { &service_redirect_to_service, NULL,
2915 GNUNET_MESSAGE_TYPE_VPN_CLIENT_REDIRECT_TO_SERVICE,
2916 sizeof (struct RedirectToServiceRequestMessage) },
2919 static const struct GNUNET_MESH_MessageHandler mesh_handlers[] = {
2920 { &receive_udp_back, GNUNET_MESSAGE_TYPE_VPN_UDP_REPLY, 0},
2921 { &receive_tcp_back, GNUNET_MESSAGE_TYPE_VPN_TCP_DATA_TO_VPN, 0},
2922 { &receive_icmp_back, GNUNET_MESSAGE_TYPE_VPN_ICMP_TO_VPN, 0},
2934 binary = GNUNET_OS_get_libexec_binary_path ("gnunet-helper-vpn");
2937 GNUNET_OS_check_helper_binary (binary, GNUNET_YES, "-d gnunet-vpn - - 169.1.3.3.7 255.255.255.0")) //ipv4 only please!
2940 "`%s' is not SUID, refusing to run.\n",
2941 "gnunet-helper-vpn");
2942 GNUNET_free (binary);
2946 GNUNET_free (binary);
2948 stats = GNUNET_STATISTICS_create ("vpn", cfg);
2950 GNUNET_CONFIGURATION_get_value_number (cfg, "VPN", "MAX_MAPPING",
2951 &max_destination_mappings))
2952 max_destination_mappings = 200;
2954 GNUNET_CONFIGURATION_get_value_number (cfg, "VPN", "MAX_TUNNELS",
2955 &max_channel_mappings))
2956 max_channel_mappings = 200;
2958 destination_map = GNUNET_CONTAINER_multihashmap_create (max_destination_mappings * 2, GNUNET_NO);
2959 destination_heap = GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN);
2960 channel_map = GNUNET_CONTAINER_multihashmap_create (max_channel_mappings * 2, GNUNET_NO);
2961 channel_heap = GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN);
2964 vpn_argv[0] = GNUNET_strdup ("vpn-gnunet");
2965 if (GNUNET_SYSERR ==
2966 GNUNET_CONFIGURATION_get_value_string (cfg, "VPN", "IFNAME", &ifname))
2968 GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, "VPN", "IFNAME");
2969 GNUNET_SCHEDULER_shutdown ();
2972 vpn_argv[1] = ifname;
2974 if (GNUNET_OK == GNUNET_NETWORK_test_pf (PF_INET6))
2976 if ( (GNUNET_SYSERR ==
2977 GNUNET_CONFIGURATION_get_value_string (cfg, "VPN", "IPV6ADDR",
2979 (1 != inet_pton (AF_INET6, ipv6addr, &v6))) )
2981 GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, "VPN", "IPV6ADDR",
2982 _("Must specify valid IPv6 address"));
2983 GNUNET_SCHEDULER_shutdown ();
2984 GNUNET_free_non_null (ipv6addr);
2987 vpn_argv[2] = ipv6addr;
2988 ipv6prefix_s = NULL;
2989 if (GNUNET_SYSERR ==
2990 GNUNET_CONFIGURATION_get_value_string (cfg, "VPN", "IPV6PREFIX",
2993 GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, "VPN", "IPV6PREFIX");
2994 GNUNET_SCHEDULER_shutdown ();
2995 GNUNET_free_non_null (ipv6prefix_s);
2998 vpn_argv[3] = ipv6prefix_s;
3000 GNUNET_CONFIGURATION_get_value_number (cfg, "VPN",
3003 (ipv6prefix >= 127) )
3005 GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, "VPN", "IPV4MASK",
3006 _("Must specify valid IPv6 mask"));
3007 GNUNET_SCHEDULER_shutdown ();
3013 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
3014 _("IPv6 support disabled as this system does not support IPv6\n"));
3015 vpn_argv[2] = GNUNET_strdup ("-");
3016 vpn_argv[3] = GNUNET_strdup ("-");
3018 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 ();
3029 GNUNET_free_non_null (ipv4addr);
3032 vpn_argv[4] = ipv4addr;
3034 if ( (GNUNET_SYSERR ==
3035 GNUNET_CONFIGURATION_get_value_string (cfg, "vpn", "IPV4MASK",
3037 (1 != inet_pton (AF_INET, ipv4mask, &v4))) )
3039 GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, "VPN", "IPV4MASK",
3040 _("Must specify valid IPv4 mask"));
3041 GNUNET_SCHEDULER_shutdown ();
3042 GNUNET_free_non_null (ipv4mask);
3045 vpn_argv[5] = ipv4mask;
3049 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
3050 _("IPv4 support disabled as this system does not support IPv4\n"));
3051 vpn_argv[4] = GNUNET_strdup ("-");
3052 vpn_argv[5] = GNUNET_strdup ("-");
3057 GNUNET_MESH_connect (cfg_, NULL,
3062 helper_handle = GNUNET_HELPER_start (GNUNET_NO,
3063 "gnunet-helper-vpn", vpn_argv,
3064 &message_token, NULL, NULL);
3065 nc = GNUNET_SERVER_notification_context_create (server, 1);
3066 GNUNET_SERVER_add_handlers (server, service_handlers);
3067 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &cleanup, cls);
3072 * The main function of the VPN service.
3074 * @param argc number of arguments from the command line
3075 * @param argv command line arguments
3076 * @return 0 ok, 1 on error
3079 main (int argc, char *const *argv)
3081 return (GNUNET_OK ==
3082 GNUNET_SERVICE_run (argc, argv, "vpn",
3083 GNUNET_SERVICE_OPTION_NONE,
3084 &run, NULL)) ? global_ret : 1;
3087 /* end of gnunet-service-vpn.c */