2 This file is part of GNUnet.
3 Copyright (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 cadet
26 * @author Philipp Toelke
27 * @author Christian Grothoff
30 * - keep multiple peers/cadet 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_cadet_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 cadet.
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_CADET_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_CADET_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 cadet service.
339 static struct GNUNET_CADET_Handle *cadet_handle;
342 * Map from IP address to destination information (possibly with a
343 * CADET 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 CADET 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_CADET_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_CADET_notify_transmit_ready_cancel (ts->th);
566 GNUNET_assert (NULL == ts->destination.heap_node);
567 if (NULL != (channel = ts->channel))
570 GNUNET_CADET_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 cadet.
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 cadet 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_CADET_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 cadet 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 cadet 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_CADET_notify_transmit_ready_cancel (ts->th);
679 GNUNET_STATISTICS_update (stats,
680 gettext_noop ("# Bytes dropped in cadet queue (overflow)"),
686 ts->th = GNUNET_CADET_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_CADET_channel_create (cadet_handle,
734 GNUNET_CADET_OPTION_DEFAULT);
739 * Initialize the given destination entry's cadet 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 ("# Cadet 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_CADET_channel_create (cadet_handle,
778 &dt->destination->details.service_destination.target,
780 GNUNET_CADET_OPTION_DEFAULT);
781 if (NULL == ts->channel)
783 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
784 _("Failed to setup cadet 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 cadet 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 if (NULL == ts->channel)
1100 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1101 "Packet dropped, channel not yet ready\n");
1102 GNUNET_STATISTICS_update (stats,
1103 gettext_noop ("# Packets dropped (channel not yet online)"),
1109 /* send via channel */
1113 if (destination->is_service)
1115 struct GNUNET_EXIT_UdpServiceMessage *usm;
1117 mlen = sizeof (struct GNUNET_EXIT_UdpServiceMessage) +
1118 payload_length - sizeof (struct GNUNET_TUN_UdpHeader);
1119 if (mlen >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1124 tnq = GNUNET_malloc (sizeof (struct ChannelMessageQueueEntry) + mlen);
1127 usm = (struct GNUNET_EXIT_UdpServiceMessage *) &tnq[1];
1128 usm->header.size = htons ((uint16_t) mlen);
1129 usm->header.type = htons (GNUNET_MESSAGE_TYPE_VPN_UDP_TO_SERVICE);
1130 /* if the source port is below 32000, we assume it has a special
1131 meaning; if not, we pick a random port (this is a heuristic) */
1132 usm->source_port = (ntohs (udp->source_port) < 32000) ? udp->source_port : 0;
1133 usm->destination_port = udp->destination_port;
1134 usm->service_descriptor = destination->details.service_destination.service_descriptor;
1137 payload_length - sizeof (struct GNUNET_TUN_UdpHeader));
1141 struct GNUNET_EXIT_UdpInternetMessage *uim;
1142 struct in_addr *ip4dst;
1143 struct in6_addr *ip6dst;
1146 mlen = sizeof (struct GNUNET_EXIT_UdpInternetMessage) +
1147 alen + payload_length - sizeof (struct GNUNET_TUN_UdpHeader);
1148 if (mlen >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1153 tnq = GNUNET_malloc (sizeof (struct ChannelMessageQueueEntry) + mlen);
1156 uim = (struct GNUNET_EXIT_UdpInternetMessage *) &tnq[1];
1157 uim->header.size = htons ((uint16_t) mlen);
1158 uim->header.type = htons (GNUNET_MESSAGE_TYPE_VPN_UDP_TO_INTERNET);
1159 uim->af = htonl (destination->details.exit_destination.af);
1160 uim->source_port = (ntohs (udp->source_port) < 32000) ? udp->source_port : 0;
1161 uim->destination_port = udp->destination_port;
1162 switch (destination->details.exit_destination.af)
1165 ip4dst = (struct in_addr *) &uim[1];
1166 *ip4dst = destination->details.exit_destination.ip.v4;
1167 payload = &ip4dst[1];
1170 ip6dst = (struct in6_addr *) &uim[1];
1171 *ip6dst = destination->details.exit_destination.ip.v6;
1172 payload = &ip6dst[1];
1179 payload_length - sizeof (struct GNUNET_TUN_UdpHeader));
1185 if (destination->is_service)
1187 struct GNUNET_EXIT_TcpServiceStartMessage *tsm;
1189 mlen = sizeof (struct GNUNET_EXIT_TcpServiceStartMessage) +
1190 payload_length - sizeof (struct GNUNET_TUN_TcpHeader);
1191 if (mlen >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1196 tnq = GNUNET_malloc (sizeof (struct ChannelMessageQueueEntry) + mlen);
1199 tsm = (struct GNUNET_EXIT_TcpServiceStartMessage *) &tnq[1];
1200 tsm->header.size = htons ((uint16_t) mlen);
1201 tsm->header.type = htons (GNUNET_MESSAGE_TYPE_VPN_TCP_TO_SERVICE_START);
1202 tsm->reserved = htonl (0);
1203 tsm->service_descriptor = destination->details.service_destination.service_descriptor;
1204 tsm->tcp_header = *tcp;
1207 payload_length - sizeof (struct GNUNET_TUN_TcpHeader));
1211 struct GNUNET_EXIT_TcpInternetStartMessage *tim;
1212 struct in_addr *ip4dst;
1213 struct in6_addr *ip6dst;
1216 mlen = sizeof (struct GNUNET_EXIT_TcpInternetStartMessage) +
1217 alen + payload_length - sizeof (struct GNUNET_TUN_TcpHeader);
1218 if (mlen >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1223 tnq = GNUNET_malloc (sizeof (struct ChannelMessageQueueEntry) + mlen);
1226 tim = (struct GNUNET_EXIT_TcpInternetStartMessage *) &tnq[1];
1227 tim->header.size = htons ((uint16_t) mlen);
1228 tim->header.type = htons (GNUNET_MESSAGE_TYPE_VPN_TCP_TO_INTERNET_START);
1229 tim->af = htonl (destination->details.exit_destination.af);
1230 tim->tcp_header = *tcp;
1231 switch (destination->details.exit_destination.af)
1234 ip4dst = (struct in_addr *) &tim[1];
1235 *ip4dst = destination->details.exit_destination.ip.v4;
1236 payload = &ip4dst[1];
1239 ip6dst = (struct in6_addr *) &tim[1];
1240 *ip6dst = destination->details.exit_destination.ip.v6;
1241 payload = &ip6dst[1];
1248 payload_length - sizeof (struct GNUNET_TUN_TcpHeader));
1253 struct GNUNET_EXIT_TcpDataMessage *tdm;
1255 mlen = sizeof (struct GNUNET_EXIT_TcpDataMessage) +
1256 payload_length - sizeof (struct GNUNET_TUN_TcpHeader);
1257 if (mlen >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1262 tnq = GNUNET_malloc (sizeof (struct ChannelMessageQueueEntry) + mlen);
1265 tdm = (struct GNUNET_EXIT_TcpDataMessage *) &tnq[1];
1266 tdm->header.size = htons ((uint16_t) mlen);
1267 tdm->header.type = htons (GNUNET_MESSAGE_TYPE_VPN_TCP_DATA_TO_EXIT);
1268 tdm->reserved = htonl (0);
1269 tdm->tcp_header = *tcp;
1272 payload_length - sizeof (struct GNUNET_TUN_TcpHeader));
1276 case IPPROTO_ICMPV6:
1277 if (destination->is_service)
1279 struct GNUNET_EXIT_IcmpServiceMessage *ism;
1281 mlen = sizeof (struct GNUNET_EXIT_IcmpServiceMessage) +
1282 payload_length - sizeof (struct GNUNET_TUN_IcmpHeader);
1283 if (mlen >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1288 tnq = GNUNET_malloc (sizeof (struct ChannelMessageQueueEntry) + mlen);
1290 ism = (struct GNUNET_EXIT_IcmpServiceMessage *) &tnq[1];
1291 ism->header.type = htons (GNUNET_MESSAGE_TYPE_VPN_ICMP_TO_SERVICE);
1292 ism->af = htonl (af); /* need to tell destination ICMP protocol family! */
1293 ism->service_descriptor = destination->details.service_destination.service_descriptor;
1294 ism->icmp_header = *icmp;
1295 /* ICMP protocol translation will be done by the receiver (as we don't know
1296 the target AF); however, we still need to possibly discard the payload
1297 depending on the ICMP type */
1303 case GNUNET_TUN_ICMPTYPE_ECHO_REPLY:
1304 case GNUNET_TUN_ICMPTYPE_ECHO_REQUEST:
1306 case GNUNET_TUN_ICMPTYPE_DESTINATION_UNREACHABLE:
1307 case GNUNET_TUN_ICMPTYPE_SOURCE_QUENCH:
1308 case GNUNET_TUN_ICMPTYPE_TIME_EXCEEDED:
1309 /* throw away ICMP payload, won't be useful for the other side anyway */
1310 payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
1313 GNUNET_STATISTICS_update (stats,
1314 gettext_noop ("# ICMPv4 packets dropped (not allowed)"),
1318 /* end of AF_INET */
1323 case GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE:
1324 case GNUNET_TUN_ICMPTYPE6_PACKET_TOO_BIG:
1325 case GNUNET_TUN_ICMPTYPE6_TIME_EXCEEDED:
1326 case GNUNET_TUN_ICMPTYPE6_PARAMETER_PROBLEM:
1327 /* throw away ICMP payload, won't be useful for the other side anyway */
1328 payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
1330 case GNUNET_TUN_ICMPTYPE6_ECHO_REQUEST:
1331 case GNUNET_TUN_ICMPTYPE6_ECHO_REPLY:
1334 GNUNET_STATISTICS_update (stats,
1335 gettext_noop ("# ICMPv6 packets dropped (not allowed)"),
1339 /* end of AF_INET6 */
1346 /* update length calculations, as payload_length may have changed */
1347 mlen = sizeof (struct GNUNET_EXIT_IcmpServiceMessage) +
1348 alen + payload_length - sizeof (struct GNUNET_TUN_IcmpHeader);
1350 ism->header.size = htons ((uint16_t) mlen);
1351 /* finally, copy payload (if there is any left...) */
1354 payload_length - sizeof (struct GNUNET_TUN_IcmpHeader));
1358 struct GNUNET_EXIT_IcmpInternetMessage *iim;
1359 struct in_addr *ip4dst;
1360 struct in6_addr *ip6dst;
1363 mlen = sizeof (struct GNUNET_EXIT_IcmpInternetMessage) +
1364 alen + payload_length - sizeof (struct GNUNET_TUN_IcmpHeader);
1365 if (mlen >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1370 tnq = GNUNET_malloc (sizeof (struct ChannelMessageQueueEntry) + mlen);
1372 iim = (struct GNUNET_EXIT_IcmpInternetMessage *) &tnq[1];
1373 iim->header.type = htons (GNUNET_MESSAGE_TYPE_VPN_ICMP_TO_INTERNET);
1374 iim->icmp_header = *icmp;
1375 /* Perform ICMP protocol-translation (depending on destination AF and source AF)
1376 and throw away ICMP payload depending on ICMP message type */
1382 case GNUNET_TUN_ICMPTYPE_ECHO_REPLY:
1383 if (destination->details.exit_destination.af == AF_INET6)
1384 iim->icmp_header.type = GNUNET_TUN_ICMPTYPE6_ECHO_REPLY;
1386 case GNUNET_TUN_ICMPTYPE_ECHO_REQUEST:
1387 if (destination->details.exit_destination.af == AF_INET6)
1388 iim->icmp_header.type = GNUNET_TUN_ICMPTYPE6_ECHO_REQUEST;
1390 case GNUNET_TUN_ICMPTYPE_DESTINATION_UNREACHABLE:
1391 if (destination->details.exit_destination.af == AF_INET6)
1392 iim->icmp_header.type = GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE;
1393 /* throw away IP-payload, exit will have to make it up anyway */
1394 payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
1396 case GNUNET_TUN_ICMPTYPE_TIME_EXCEEDED:
1397 if (destination->details.exit_destination.af == AF_INET6)
1398 iim->icmp_header.type = GNUNET_TUN_ICMPTYPE6_TIME_EXCEEDED;
1399 /* throw away IP-payload, exit will have to make it up anyway */
1400 payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
1402 case GNUNET_TUN_ICMPTYPE_SOURCE_QUENCH:
1403 if (destination->details.exit_destination.af == AF_INET6)
1405 GNUNET_STATISTICS_update (stats,
1406 gettext_noop ("# ICMPv4 packets dropped (impossible PT to v6)"),
1411 /* throw away IP-payload, exit will have to make it up anyway */
1412 payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
1415 GNUNET_STATISTICS_update (stats,
1416 gettext_noop ("# ICMPv4 packets dropped (type not allowed)"),
1421 /* end of AF_INET */
1426 case GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE:
1427 if (destination->details.exit_destination.af == AF_INET6)
1428 iim->icmp_header.type = GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE;
1429 /* throw away IP-payload, exit will have to make it up anyway */
1430 payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
1432 case GNUNET_TUN_ICMPTYPE6_TIME_EXCEEDED:
1433 if (destination->details.exit_destination.af == AF_INET)
1434 iim->icmp_header.type = GNUNET_TUN_ICMPTYPE_TIME_EXCEEDED;
1435 /* throw away IP-payload, exit will have to make it up anyway */
1436 payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
1438 case GNUNET_TUN_ICMPTYPE6_PACKET_TOO_BIG:
1439 if (destination->details.exit_destination.af == AF_INET)
1441 GNUNET_STATISTICS_update (stats,
1442 gettext_noop ("# ICMPv6 packets dropped (impossible PT to v4)"),
1447 /* throw away IP-payload, exit will have to make it up anyway */
1448 payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
1450 case GNUNET_TUN_ICMPTYPE6_PARAMETER_PROBLEM:
1451 if (destination->details.exit_destination.af == AF_INET)
1453 GNUNET_STATISTICS_update (stats,
1454 gettext_noop ("# ICMPv6 packets dropped (impossible PT to v4)"),
1459 /* throw away IP-payload, exit will have to make it up anyway */
1460 payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
1462 case GNUNET_TUN_ICMPTYPE6_ECHO_REQUEST:
1463 if (destination->details.exit_destination.af == AF_INET)
1464 iim->icmp_header.type = GNUNET_TUN_ICMPTYPE_ECHO_REQUEST;
1466 case GNUNET_TUN_ICMPTYPE6_ECHO_REPLY:
1467 if (destination->details.exit_destination.af == AF_INET)
1468 iim->icmp_header.type = GNUNET_TUN_ICMPTYPE_ECHO_REPLY;
1471 GNUNET_STATISTICS_update (stats,
1472 gettext_noop ("# ICMPv6 packets dropped (type not allowed)"),
1477 /* end of AF_INET6 */
1482 /* update length calculations, as payload_length may have changed */
1483 mlen = sizeof (struct GNUNET_EXIT_IcmpInternetMessage) +
1484 alen + payload_length - sizeof (struct GNUNET_TUN_IcmpHeader);
1486 iim->header.size = htons ((uint16_t) mlen);
1488 /* need to tell destination ICMP protocol family! */
1489 iim->af = htonl (destination->details.exit_destination.af);
1490 switch (destination->details.exit_destination.af)
1493 ip4dst = (struct in_addr *) &iim[1];
1494 *ip4dst = destination->details.exit_destination.ip.v4;
1495 payload = &ip4dst[1];
1498 ip6dst = (struct in6_addr *) &iim[1];
1499 *ip6dst = destination->details.exit_destination.ip.v6;
1500 payload = &ip6dst[1];
1507 payload_length - sizeof (struct GNUNET_TUN_IcmpHeader));
1511 /* not supported above, how can we get here !? */
1515 send_to_channel (tnq, ts);
1520 * Receive packets from the helper-process (someone send to the local
1521 * virtual channel interface). Find the destination mapping, and if it
1522 * exists, identify the correct CADET channel (or possibly create it)
1523 * and forward the packet.
1525 * @param cls closure, NULL
1526 * @param client NULL
1527 * @param message message we got from the client (VPN channel interface)
1530 message_token (void *cls,
1532 const struct GNUNET_MessageHeader *message)
1534 const struct GNUNET_TUN_Layer2PacketHeader *tun;
1536 struct GNUNET_HashCode key;
1537 struct DestinationEntry *de;
1539 GNUNET_STATISTICS_update (stats,
1540 gettext_noop ("# Packets received from TUN interface"),
1542 mlen = ntohs (message->size);
1543 if ( (ntohs (message->type) != GNUNET_MESSAGE_TYPE_VPN_HELPER) ||
1544 (mlen < sizeof (struct GNUNET_MessageHeader) + sizeof (struct GNUNET_TUN_Layer2PacketHeader)) )
1549 tun = (const struct GNUNET_TUN_Layer2PacketHeader *) &message[1];
1550 mlen -= (sizeof (struct GNUNET_MessageHeader) + sizeof (struct GNUNET_TUN_Layer2PacketHeader));
1551 switch (ntohs (tun->proto))
1555 const struct GNUNET_TUN_IPv6Header *pkt6;
1557 if (mlen < sizeof (struct GNUNET_TUN_IPv6Header))
1563 pkt6 = (const struct GNUNET_TUN_IPv6Header *) &tun[1];
1564 get_destination_key_from_ip (AF_INET6,
1565 &pkt6->destination_address,
1567 de = GNUNET_CONTAINER_multihashmap_get (destination_map, &key);
1570 char buf[INET6_ADDRSTRLEN];
1572 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1573 _("Packet received for unmapped destination `%s' (dropping it)\n"),
1574 inet_ntop (AF_INET6,
1575 &pkt6->destination_address,
1583 &pkt6->source_address,
1584 &pkt6->destination_address,
1586 mlen - sizeof (struct GNUNET_TUN_IPv6Header));
1591 struct GNUNET_TUN_IPv4Header *pkt4;
1593 if (mlen < sizeof (struct GNUNET_TUN_IPv4Header))
1599 pkt4 = (struct GNUNET_TUN_IPv4Header *) &tun[1];
1600 get_destination_key_from_ip (AF_INET,
1601 &pkt4->destination_address,
1603 de = GNUNET_CONTAINER_multihashmap_get (destination_map, &key);
1606 char buf[INET_ADDRSTRLEN];
1608 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1609 _("Packet received for unmapped destination `%s' (dropping it)\n"),
1611 &pkt4->destination_address,
1616 if (pkt4->header_length * 4 != sizeof (struct GNUNET_TUN_IPv4Header))
1618 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1619 _("Received IPv4 packet with options (dropping it)\n"));
1625 &pkt4->source_address,
1626 &pkt4->destination_address,
1628 mlen - sizeof (struct GNUNET_TUN_IPv4Header));
1632 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1633 _("Received packet of unknown protocol %d from TUN (dropping it)\n"),
1634 (unsigned int) ntohs (tun->proto));
1642 * Synthesize a plausible ICMP payload for an ICMP error
1643 * response on the given channel.
1645 * @param ts channel information
1646 * @param ipp IPv4 header to fill in (ICMP payload)
1647 * @param udp "UDP" header to fill in (ICMP payload); might actually
1648 * also be the first 8 bytes of the TCP header
1651 make_up_icmpv4_payload (struct ChannelState *ts,
1652 struct GNUNET_TUN_IPv4Header *ipp,
1653 struct GNUNET_TUN_UdpHeader *udp)
1655 GNUNET_TUN_initialize_ipv4_header (ipp,
1657 sizeof (struct GNUNET_TUN_TcpHeader),
1659 &ts->destination_ip.v4);
1660 udp->source_port = htons (ts->source_port);
1661 udp->destination_port = htons (ts->destination_port);
1662 udp->len = htons (0);
1663 udp->crc = htons (0);
1668 * Synthesize a plausible ICMP payload for an ICMP error
1669 * response on the given channel.
1671 * @param ts channel information
1672 * @param ipp IPv6 header to fill in (ICMP payload)
1673 * @param udp "UDP" header to fill in (ICMP payload); might actually
1674 * also be the first 8 bytes of the TCP header
1677 make_up_icmpv6_payload (struct ChannelState *ts,
1678 struct GNUNET_TUN_IPv6Header *ipp,
1679 struct GNUNET_TUN_UdpHeader *udp)
1681 GNUNET_TUN_initialize_ipv6_header (ipp,
1683 sizeof (struct GNUNET_TUN_TcpHeader),
1685 &ts->destination_ip.v6);
1686 udp->source_port = htons (ts->source_port);
1687 udp->destination_port = htons (ts->destination_port);
1688 udp->len = htons (0);
1689 udp->crc = htons (0);
1694 * We got an ICMP packet back from the CADET channel. Pass it on to the
1695 * local virtual interface via the helper.
1697 * @param cls closure, NULL
1698 * @param channel connection to the other end
1699 * @param channel_ctx pointer to our 'struct ChannelState *'
1700 * @param message the actual message
1701 * @return #GNUNET_OK to keep the connection open,
1702 * #GNUNET_SYSERR to close it (signal serious error)
1705 receive_icmp_back (void *cls,
1706 struct GNUNET_CADET_Channel *channel,
1708 const struct GNUNET_MessageHeader *message)
1710 struct ChannelState *ts = *channel_ctx;
1711 const struct GNUNET_EXIT_IcmpToVPNMessage *i2v;
1714 GNUNET_STATISTICS_update (stats,
1715 gettext_noop ("# ICMP packets received from cadet"),
1717 mlen = ntohs (message->size);
1718 if (mlen < sizeof (struct GNUNET_EXIT_IcmpToVPNMessage))
1720 GNUNET_break_op (0);
1721 return GNUNET_SYSERR;
1723 if (NULL == ts->heap_node)
1725 GNUNET_break_op (0);
1726 return GNUNET_SYSERR;
1728 if (AF_UNSPEC == ts->af)
1730 GNUNET_break_op (0);
1731 return GNUNET_SYSERR;
1733 i2v = (const struct GNUNET_EXIT_IcmpToVPNMessage *) message;
1734 mlen -= sizeof (struct GNUNET_EXIT_IcmpToVPNMessage);
1736 char sbuf[INET6_ADDRSTRLEN];
1737 char dbuf[INET6_ADDRSTRLEN];
1739 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1740 "Received ICMP packet from cadet, sending %u bytes from %s -> %s via TUN\n",
1741 (unsigned int) mlen,
1742 inet_ntop (ts->af, &ts->destination_ip, sbuf, sizeof (sbuf)),
1743 inet_ntop (ts->af, &ts->source_ip, dbuf, sizeof (dbuf)));
1749 size_t size = sizeof (struct GNUNET_TUN_IPv4Header)
1750 + sizeof (struct GNUNET_TUN_IcmpHeader)
1751 + sizeof (struct GNUNET_MessageHeader) +
1752 sizeof (struct GNUNET_TUN_Layer2PacketHeader) +
1755 /* reserve some extra space in case we have an ICMP type here where
1756 we will need to make up the payload ourselves */
1757 char buf[size + sizeof (struct GNUNET_TUN_IPv4Header) + 8] GNUNET_ALIGN;
1758 struct GNUNET_MessageHeader *msg = (struct GNUNET_MessageHeader *) buf;
1759 struct GNUNET_TUN_Layer2PacketHeader *tun = (struct GNUNET_TUN_Layer2PacketHeader*) &msg[1];
1760 struct GNUNET_TUN_IPv4Header *ipv4 = (struct GNUNET_TUN_IPv4Header *) &tun[1];
1761 struct GNUNET_TUN_IcmpHeader *icmp = (struct GNUNET_TUN_IcmpHeader *) &ipv4[1];
1762 msg->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
1763 tun->flags = htons (0);
1764 tun->proto = htons (ETH_P_IPV4);
1765 GNUNET_TUN_initialize_ipv4_header (ipv4,
1767 sizeof (struct GNUNET_TUN_IcmpHeader) + mlen,
1768 &ts->destination_ip.v4,
1770 *icmp = i2v->icmp_header;
1774 /* For some ICMP types, we need to adjust (make up) the payload here.
1775 Also, depending on the AF used on the other side, we have to
1776 do ICMP PT (translate ICMP types) */
1777 switch (ntohl (i2v->af))
1782 case GNUNET_TUN_ICMPTYPE_ECHO_REPLY:
1783 case GNUNET_TUN_ICMPTYPE_ECHO_REQUEST:
1785 case GNUNET_TUN_ICMPTYPE_DESTINATION_UNREACHABLE:
1786 case GNUNET_TUN_ICMPTYPE_SOURCE_QUENCH:
1787 case GNUNET_TUN_ICMPTYPE_TIME_EXCEEDED:
1789 struct GNUNET_TUN_IPv4Header *ipp = (struct GNUNET_TUN_IPv4Header *) &icmp[1];
1790 struct GNUNET_TUN_UdpHeader *udp = (struct GNUNET_TUN_UdpHeader *) &ipp[1];
1794 /* sender did not strip ICMP payload? */
1795 GNUNET_break_op (0);
1796 return GNUNET_SYSERR;
1798 size += sizeof (struct GNUNET_TUN_IPv4Header) + 8;
1799 GNUNET_assert (8 == sizeof (struct GNUNET_TUN_UdpHeader));
1800 make_up_icmpv4_payload (ts, ipp, udp);
1804 GNUNET_break_op (0);
1805 GNUNET_STATISTICS_update (stats,
1806 gettext_noop ("# ICMPv4 packets dropped (type not allowed)"),
1808 return GNUNET_SYSERR;
1813 /* ICMP PT 6-to-4 and possibly making up payloads */
1816 case GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE:
1817 icmp->type = GNUNET_TUN_ICMPTYPE_DESTINATION_UNREACHABLE;
1819 struct GNUNET_TUN_IPv4Header *ipp = (struct GNUNET_TUN_IPv4Header *) &icmp[1];
1820 struct GNUNET_TUN_UdpHeader *udp = (struct GNUNET_TUN_UdpHeader *) &ipp[1];
1824 /* sender did not strip ICMP payload? */
1825 GNUNET_break_op (0);
1826 return GNUNET_SYSERR;
1828 size += sizeof (struct GNUNET_TUN_IPv4Header) + 8;
1829 GNUNET_assert (8 == sizeof (struct GNUNET_TUN_UdpHeader));
1830 make_up_icmpv4_payload (ts, ipp, udp);
1833 case GNUNET_TUN_ICMPTYPE6_TIME_EXCEEDED:
1834 icmp->type = GNUNET_TUN_ICMPTYPE_TIME_EXCEEDED;
1836 struct GNUNET_TUN_IPv4Header *ipp = (struct GNUNET_TUN_IPv4Header *) &icmp[1];
1837 struct GNUNET_TUN_UdpHeader *udp = (struct GNUNET_TUN_UdpHeader *) &ipp[1];
1841 /* sender did not strip ICMP payload? */
1842 GNUNET_break_op (0);
1843 return GNUNET_SYSERR;
1845 size += sizeof (struct GNUNET_TUN_IPv4Header) + 8;
1846 GNUNET_assert (8 == sizeof (struct GNUNET_TUN_UdpHeader));
1847 make_up_icmpv4_payload (ts, ipp, udp);
1850 case GNUNET_TUN_ICMPTYPE6_PACKET_TOO_BIG:
1851 case GNUNET_TUN_ICMPTYPE6_PARAMETER_PROBLEM:
1852 GNUNET_STATISTICS_update (stats,
1853 gettext_noop ("# ICMPv6 packets dropped (impossible PT to v4)"),
1856 case GNUNET_TUN_ICMPTYPE6_ECHO_REQUEST:
1857 icmp->type = GNUNET_TUN_ICMPTYPE_ECHO_REQUEST;
1859 case GNUNET_TUN_ICMPTYPE6_ECHO_REPLY:
1860 icmp->type = GNUNET_TUN_ICMPTYPE_ECHO_REPLY;
1863 GNUNET_break_op (0);
1864 GNUNET_STATISTICS_update (stats,
1865 gettext_noop ("# ICMPv6 packets dropped (type not allowed)"),
1867 return GNUNET_SYSERR;
1872 GNUNET_break_op (0);
1873 return GNUNET_SYSERR;
1875 msg->size = htons (size);
1876 GNUNET_TUN_calculate_icmp_checksum (icmp,
1879 (void) GNUNET_HELPER_send (helper_handle,
1888 size_t size = sizeof (struct GNUNET_TUN_IPv6Header)
1889 + sizeof (struct GNUNET_TUN_IcmpHeader)
1890 + sizeof (struct GNUNET_MessageHeader) +
1891 sizeof (struct GNUNET_TUN_Layer2PacketHeader) +
1894 char buf[size + sizeof (struct GNUNET_TUN_IPv6Header) + 8] GNUNET_ALIGN;
1895 struct GNUNET_MessageHeader *msg = (struct GNUNET_MessageHeader *) buf;
1896 struct GNUNET_TUN_Layer2PacketHeader *tun = (struct GNUNET_TUN_Layer2PacketHeader*) &msg[1];
1897 struct GNUNET_TUN_IPv6Header *ipv6 = (struct GNUNET_TUN_IPv6Header *) &tun[1];
1898 struct GNUNET_TUN_IcmpHeader *icmp = (struct GNUNET_TUN_IcmpHeader *) &ipv6[1];
1899 msg->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
1900 tun->flags = htons (0);
1901 tun->proto = htons (ETH_P_IPV6);
1902 GNUNET_TUN_initialize_ipv6_header (ipv6,
1904 sizeof (struct GNUNET_TUN_IcmpHeader) + mlen,
1905 &ts->destination_ip.v6,
1907 *icmp = i2v->icmp_header;
1912 /* For some ICMP types, we need to adjust (make up) the payload here.
1913 Also, depending on the AF used on the other side, we have to
1914 do ICMP PT (translate ICMP types) */
1915 switch (ntohl (i2v->af))
1918 /* ICMP PT 4-to-6 and possibly making up payloads */
1921 case GNUNET_TUN_ICMPTYPE_ECHO_REPLY:
1922 icmp->type = GNUNET_TUN_ICMPTYPE6_ECHO_REPLY;
1924 case GNUNET_TUN_ICMPTYPE_ECHO_REQUEST:
1925 icmp->type = GNUNET_TUN_ICMPTYPE6_ECHO_REQUEST;
1927 case GNUNET_TUN_ICMPTYPE_DESTINATION_UNREACHABLE:
1928 icmp->type = GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE;
1930 struct GNUNET_TUN_IPv6Header *ipp = (struct GNUNET_TUN_IPv6Header *) &icmp[1];
1931 struct GNUNET_TUN_UdpHeader *udp = (struct GNUNET_TUN_UdpHeader *) &ipp[1];
1935 /* sender did not strip ICMP payload? */
1936 GNUNET_break_op (0);
1937 return GNUNET_SYSERR;
1939 size += sizeof (struct GNUNET_TUN_IPv6Header) + 8;
1940 GNUNET_assert (8 == sizeof (struct GNUNET_TUN_UdpHeader));
1941 make_up_icmpv6_payload (ts, ipp, udp);
1944 case GNUNET_TUN_ICMPTYPE_TIME_EXCEEDED:
1945 icmp->type = GNUNET_TUN_ICMPTYPE6_TIME_EXCEEDED;
1947 struct GNUNET_TUN_IPv6Header *ipp = (struct GNUNET_TUN_IPv6Header *) &icmp[1];
1948 struct GNUNET_TUN_UdpHeader *udp = (struct GNUNET_TUN_UdpHeader *) &ipp[1];
1952 /* sender did not strip ICMP payload? */
1953 GNUNET_break_op (0);
1954 return GNUNET_SYSERR;
1956 size += sizeof (struct GNUNET_TUN_IPv6Header) + 8;
1957 GNUNET_assert (8 == sizeof (struct GNUNET_TUN_UdpHeader));
1958 make_up_icmpv6_payload (ts, ipp, udp);
1961 case GNUNET_TUN_ICMPTYPE_SOURCE_QUENCH:
1962 GNUNET_STATISTICS_update (stats,
1963 gettext_noop ("# ICMPv4 packets dropped (impossible PT to v6)"),
1967 GNUNET_break_op (0);
1968 GNUNET_STATISTICS_update (stats,
1969 gettext_noop ("# ICMPv4 packets dropped (type not allowed)"),
1971 return GNUNET_SYSERR;
1978 case GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE:
1979 case GNUNET_TUN_ICMPTYPE6_TIME_EXCEEDED:
1980 case GNUNET_TUN_ICMPTYPE6_PACKET_TOO_BIG:
1981 case GNUNET_TUN_ICMPTYPE6_PARAMETER_PROBLEM:
1983 struct GNUNET_TUN_IPv6Header *ipp = (struct GNUNET_TUN_IPv6Header *) &icmp[1];
1984 struct GNUNET_TUN_UdpHeader *udp = (struct GNUNET_TUN_UdpHeader *) &ipp[1];
1988 /* sender did not strip ICMP payload? */
1989 GNUNET_break_op (0);
1990 return GNUNET_SYSERR;
1992 size += sizeof (struct GNUNET_TUN_IPv6Header) + 8;
1993 GNUNET_assert (8 == sizeof (struct GNUNET_TUN_UdpHeader));
1994 make_up_icmpv6_payload (ts, ipp, udp);
1997 case GNUNET_TUN_ICMPTYPE6_ECHO_REQUEST:
2000 GNUNET_break_op (0);
2001 GNUNET_STATISTICS_update (stats,
2002 gettext_noop ("# ICMPv6 packets dropped (type not allowed)"),
2004 return GNUNET_SYSERR;
2009 GNUNET_break_op (0);
2010 return GNUNET_SYSERR;
2012 msg->size = htons (size);
2013 GNUNET_TUN_calculate_icmp_checksum (icmp,
2015 (void) GNUNET_HELPER_send (helper_handle,
2025 GNUNET_CONTAINER_heap_update_cost (channel_heap,
2027 GNUNET_TIME_absolute_get ().abs_value_us);
2033 * We got a UDP packet back from the CADET channel. Pass it on to the
2034 * local virtual interface via the helper.
2036 * @param cls closure, NULL
2037 * @param channel connection to the other end
2038 * @param channel_ctx pointer to our 'struct ChannelState *'
2039 * @param message the actual message
2040 * @return #GNUNET_OK to keep the connection open,
2041 * #GNUNET_SYSERR to close it (signal serious error)
2044 receive_udp_back (void *cls,
2045 struct GNUNET_CADET_Channel *channel,
2047 const struct GNUNET_MessageHeader *message)
2049 struct ChannelState *ts = *channel_ctx;
2050 const struct GNUNET_EXIT_UdpReplyMessage *reply;
2053 GNUNET_STATISTICS_update (stats,
2054 gettext_noop ("# UDP packets received from cadet"),
2056 mlen = ntohs (message->size);
2057 if (mlen < sizeof (struct GNUNET_EXIT_UdpReplyMessage))
2059 GNUNET_break_op (0);
2060 return GNUNET_SYSERR;
2062 if (NULL == ts->heap_node)
2064 GNUNET_break_op (0);
2065 return GNUNET_SYSERR;
2067 if (AF_UNSPEC == ts->af)
2069 GNUNET_break_op (0);
2070 return GNUNET_SYSERR;
2072 reply = (const struct GNUNET_EXIT_UdpReplyMessage *) message;
2073 mlen -= sizeof (struct GNUNET_EXIT_UdpReplyMessage);
2075 char sbuf[INET6_ADDRSTRLEN];
2076 char dbuf[INET6_ADDRSTRLEN];
2078 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2079 "Received UDP reply from cadet, sending %u bytes from %s:%u -> %s:%u via TUN\n",
2080 (unsigned int) mlen,
2081 inet_ntop (ts->af, &ts->destination_ip, sbuf, sizeof (sbuf)),
2082 ts->destination_port,
2083 inet_ntop (ts->af, &ts->source_ip, dbuf, sizeof (dbuf)),
2090 size_t size = sizeof (struct GNUNET_TUN_IPv4Header)
2091 + sizeof (struct GNUNET_TUN_UdpHeader)
2092 + sizeof (struct GNUNET_MessageHeader) +
2093 sizeof (struct GNUNET_TUN_Layer2PacketHeader) +
2096 char buf[size] GNUNET_ALIGN;
2097 struct GNUNET_MessageHeader *msg = (struct GNUNET_MessageHeader *) buf;
2098 struct GNUNET_TUN_Layer2PacketHeader *tun = (struct GNUNET_TUN_Layer2PacketHeader*) &msg[1];
2099 struct GNUNET_TUN_IPv4Header *ipv4 = (struct GNUNET_TUN_IPv4Header *) &tun[1];
2100 struct GNUNET_TUN_UdpHeader *udp = (struct GNUNET_TUN_UdpHeader *) &ipv4[1];
2101 msg->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
2102 msg->size = htons (size);
2103 tun->flags = htons (0);
2104 tun->proto = htons (ETH_P_IPV4);
2105 GNUNET_TUN_initialize_ipv4_header (ipv4,
2107 sizeof (struct GNUNET_TUN_UdpHeader) + mlen,
2108 &ts->destination_ip.v4,
2110 if (0 == ntohs (reply->source_port))
2111 udp->source_port = htons (ts->destination_port);
2113 udp->source_port = reply->source_port;
2114 if (0 == ntohs (reply->destination_port))
2115 udp->destination_port = htons (ts->source_port);
2117 udp->destination_port = reply->destination_port;
2118 udp->len = htons (mlen + sizeof (struct GNUNET_TUN_UdpHeader));
2119 GNUNET_TUN_calculate_udp4_checksum (ipv4,
2126 (void) GNUNET_HELPER_send (helper_handle,
2135 size_t size = sizeof (struct GNUNET_TUN_IPv6Header)
2136 + sizeof (struct GNUNET_TUN_UdpHeader)
2137 + sizeof (struct GNUNET_MessageHeader) +
2138 sizeof (struct GNUNET_TUN_Layer2PacketHeader) +
2141 char buf[size] GNUNET_ALIGN;
2142 struct GNUNET_MessageHeader *msg = (struct GNUNET_MessageHeader *) buf;
2143 struct GNUNET_TUN_Layer2PacketHeader *tun = (struct GNUNET_TUN_Layer2PacketHeader*) &msg[1];
2144 struct GNUNET_TUN_IPv6Header *ipv6 = (struct GNUNET_TUN_IPv6Header *) &tun[1];
2145 struct GNUNET_TUN_UdpHeader *udp = (struct GNUNET_TUN_UdpHeader *) &ipv6[1];
2146 msg->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
2147 msg->size = htons (size);
2148 tun->flags = htons (0);
2149 tun->proto = htons (ETH_P_IPV6);
2150 GNUNET_TUN_initialize_ipv6_header (ipv6,
2152 sizeof (struct GNUNET_TUN_UdpHeader) + mlen,
2153 &ts->destination_ip.v6,
2155 if (0 == ntohs (reply->source_port))
2156 udp->source_port = htons (ts->destination_port);
2158 udp->source_port = reply->source_port;
2159 if (0 == ntohs (reply->destination_port))
2160 udp->destination_port = htons (ts->source_port);
2162 udp->destination_port = reply->destination_port;
2163 udp->len = htons (mlen + sizeof (struct GNUNET_TUN_UdpHeader));
2164 GNUNET_TUN_calculate_udp6_checksum (ipv6,
2170 (void) GNUNET_HELPER_send (helper_handle,
2180 GNUNET_CONTAINER_heap_update_cost (channel_heap,
2182 GNUNET_TIME_absolute_get ().abs_value_us);
2188 * We got a TCP packet back from the CADET channel. Pass it on to the
2189 * local virtual interface via the helper.
2191 * @param cls closure, NULL
2192 * @param channel connection to the other end
2193 * @param channel_ctx pointer to our `struct ChannelState *`
2194 * @param message the actual message
2195 * @return #GNUNET_OK to keep the connection open,
2196 * #GNUNET_SYSERR to close it (signal serious error)
2199 receive_tcp_back (void *cls,
2200 struct GNUNET_CADET_Channel *channel,
2202 const struct GNUNET_MessageHeader *message)
2204 struct ChannelState *ts = *channel_ctx;
2205 const struct GNUNET_EXIT_TcpDataMessage *data;
2208 GNUNET_STATISTICS_update (stats,
2209 gettext_noop ("# TCP packets received from cadet"),
2211 mlen = ntohs (message->size);
2212 if (mlen < sizeof (struct GNUNET_EXIT_TcpDataMessage))
2214 GNUNET_break_op (0);
2215 return GNUNET_SYSERR;
2217 if (NULL == ts->heap_node)
2219 GNUNET_break_op (0);
2220 return GNUNET_SYSERR;
2222 data = (const struct GNUNET_EXIT_TcpDataMessage *) message;
2223 mlen -= sizeof (struct GNUNET_EXIT_TcpDataMessage);
2225 char sbuf[INET6_ADDRSTRLEN];
2226 char dbuf[INET6_ADDRSTRLEN];
2228 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2229 "Received TCP reply from cadet, sending %u bytes from %s:%u -> %s:%u via TUN\n",
2230 (unsigned int) mlen,
2231 inet_ntop (ts->af, &ts->destination_ip, sbuf, sizeof (sbuf)),
2232 ts->destination_port,
2233 inet_ntop (ts->af, &ts->source_ip, dbuf, sizeof (dbuf)),
2236 if (data->tcp_header.off * 4 < sizeof (struct GNUNET_TUN_TcpHeader))
2238 GNUNET_break_op (0);
2239 return GNUNET_SYSERR;
2245 size_t size = sizeof (struct GNUNET_TUN_IPv4Header)
2246 + sizeof (struct GNUNET_TUN_TcpHeader)
2247 + sizeof (struct GNUNET_MessageHeader) +
2248 sizeof (struct GNUNET_TUN_Layer2PacketHeader) +
2251 char buf[size] GNUNET_ALIGN;
2252 struct GNUNET_MessageHeader *msg = (struct GNUNET_MessageHeader *) buf;
2253 struct GNUNET_TUN_Layer2PacketHeader *tun = (struct GNUNET_TUN_Layer2PacketHeader*) &msg[1];
2254 struct GNUNET_TUN_IPv4Header *ipv4 = (struct GNUNET_TUN_IPv4Header *) &tun[1];
2255 struct GNUNET_TUN_TcpHeader *tcp = (struct GNUNET_TUN_TcpHeader *) &ipv4[1];
2256 msg->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
2257 msg->size = htons (size);
2258 tun->flags = htons (0);
2259 tun->proto = htons (ETH_P_IPV4);
2260 GNUNET_TUN_initialize_ipv4_header (ipv4,
2262 sizeof (struct GNUNET_TUN_TcpHeader) + mlen,
2263 &ts->destination_ip.v4,
2265 *tcp = data->tcp_header;
2266 tcp->source_port = htons (ts->destination_port);
2267 tcp->destination_port = htons (ts->source_port);
2268 GNUNET_TUN_calculate_tcp4_checksum (ipv4,
2275 (void) GNUNET_HELPER_send (helper_handle,
2284 size_t size = sizeof (struct GNUNET_TUN_IPv6Header)
2285 + sizeof (struct GNUNET_TUN_TcpHeader)
2286 + sizeof (struct GNUNET_MessageHeader) +
2287 sizeof (struct GNUNET_TUN_Layer2PacketHeader) +
2290 char buf[size] GNUNET_ALIGN;
2291 struct GNUNET_MessageHeader *msg = (struct GNUNET_MessageHeader *) buf;
2292 struct GNUNET_TUN_Layer2PacketHeader *tun = (struct GNUNET_TUN_Layer2PacketHeader*) &msg[1];
2293 struct GNUNET_TUN_IPv6Header *ipv6 = (struct GNUNET_TUN_IPv6Header *) &tun[1];
2294 struct GNUNET_TUN_TcpHeader *tcp = (struct GNUNET_TUN_TcpHeader *) &ipv6[1];
2295 msg->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
2296 msg->size = htons (size);
2297 tun->flags = htons (0);
2298 tun->proto = htons (ETH_P_IPV6);
2299 GNUNET_TUN_initialize_ipv6_header (ipv6,
2301 sizeof (struct GNUNET_TUN_TcpHeader) + mlen,
2302 &ts->destination_ip.v6,
2304 *tcp = data->tcp_header;
2305 tcp->source_port = htons (ts->destination_port);
2306 tcp->destination_port = htons (ts->source_port);
2307 GNUNET_TUN_calculate_tcp6_checksum (ipv6,
2314 (void) GNUNET_HELPER_send (helper_handle,
2322 GNUNET_CONTAINER_heap_update_cost (channel_heap,
2324 GNUNET_TIME_absolute_get ().abs_value_us);
2330 * Allocate an IPv4 address from the range of the channel
2331 * for a new redirection.
2333 * @param v4 where to store the address
2334 * @return #GNUNET_OK on success,
2335 * #GNUNET_SYSERR on error
2338 allocate_v4_address (struct in_addr *v4)
2340 const char *ipv4addr = vpn_argv[4];
2341 const char *ipv4mask = vpn_argv[5];
2342 struct in_addr addr;
2343 struct in_addr mask;
2345 struct GNUNET_HashCode key;
2348 GNUNET_assert (1 == inet_pton (AF_INET, ipv4addr, &addr));
2349 GNUNET_assert (1 == inet_pton (AF_INET, ipv4mask, &mask));
2350 /* Given 192.168.0.1/255.255.0.0, we want a mask
2351 of '192.168.255.255', thus: */
2352 mask.s_addr = addr.s_addr | ~mask.s_addr;
2359 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
2360 _("Failed to find unallocated IPv4 address in VPN's range\n"));
2361 return GNUNET_SYSERR;
2363 /* Pick random IPv4 address within the subnet, except 'addr' or 'mask' itself */
2364 rnd.s_addr = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
2366 v4->s_addr = (addr.s_addr | rnd.s_addr) & mask.s_addr;
2367 get_destination_key_from_ip (AF_INET,
2371 while ( (GNUNET_YES ==
2372 GNUNET_CONTAINER_multihashmap_contains (destination_map,
2374 (v4->s_addr == addr.s_addr) ||
2375 (v4->s_addr == mask.s_addr) );
2381 * Allocate an IPv6 address from the range of the channel
2382 * for a new redirection.
2384 * @param v6 where to store the address
2385 * @return #GNUNET_OK on success,
2386 * #GNUNET_SYSERR on error
2389 allocate_v6_address (struct in6_addr *v6)
2391 const char *ipv6addr = vpn_argv[2];
2392 struct in6_addr addr;
2393 struct in6_addr mask;
2394 struct in6_addr rnd;
2396 struct GNUNET_HashCode key;
2399 GNUNET_assert (1 == inet_pton (AF_INET6, ipv6addr, &addr));
2400 GNUNET_assert (ipv6prefix < 128);
2401 /* Given ABCD::/96, we want a mask of 'ABCD::FFFF:FFFF,
2404 for (i=127;i>=ipv6prefix;i--)
2405 mask.s6_addr[i / 8] |= (1 << (i % 8));
2407 /* Pick random IPv6 address within the subnet, except 'addr' or 'mask' itself */
2414 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
2415 _("Failed to find unallocated IPv6 address in VPN's range\n"));
2416 return GNUNET_SYSERR;
2421 rnd.s6_addr[i] = (unsigned char) GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
2424 = (addr.s6_addr[i] | rnd.s6_addr[i]) & mask.s6_addr[i];
2426 get_destination_key_from_ip (AF_INET6,
2430 while ( (GNUNET_YES ==
2431 GNUNET_CONTAINER_multihashmap_contains (destination_map,
2435 sizeof (struct in6_addr))) ||
2438 sizeof (struct in6_addr))) );
2444 * Free resources occupied by a destination entry.
2446 * @param de entry to free
2449 free_destination_entry (struct DestinationEntry *de)
2451 struct DestinationChannel *dt;
2453 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2454 "Cleaning up destination entry\n");
2455 GNUNET_STATISTICS_update (stats,
2456 gettext_noop ("# Active destinations"),
2458 while (NULL != (dt = de->dt_head))
2460 GNUNET_CONTAINER_DLL_remove (de->dt_head,
2465 free_channel_state (dt->ts);
2466 GNUNET_assert (NULL == dt->ts);
2470 if (NULL != de->heap_node)
2472 GNUNET_CONTAINER_heap_remove_node (de->heap_node);
2473 de->heap_node = NULL;
2474 GNUNET_assert (GNUNET_YES ==
2475 GNUNET_CONTAINER_multihashmap_remove (destination_map,
2484 * We have too many active destinations. Clean up the oldest destination.
2486 * @param except destination that must NOT be cleaned up, even if it is the oldest
2489 expire_destination (struct DestinationEntry *except)
2491 struct DestinationEntry *de;
2493 de = GNUNET_CONTAINER_heap_peek (destination_heap);
2494 GNUNET_assert (NULL != de);
2496 return; /* can't do this */
2497 free_destination_entry (de);
2502 * Allocate an IP address for the response.
2504 * @param result_af desired address family; set to the actual
2505 * address family; can initially be AF_UNSPEC if there
2506 * is no preference; will be set to AF_UNSPEC if the
2508 * @param addr set to either v4 or v6 depending on which
2509 * storage location was used; set to NULL if allocation failed
2510 * @param v4 storage space for an IPv4 address
2511 * @param v6 storage space for an IPv6 address
2512 * @return #GNUNET_OK normally, #GNUNET_SYSERR if `* result_af` was
2513 * an unsupported address family (not AF_INET, AF_INET6 or AF_UNSPEC)
2516 allocate_response_ip (int *result_af,
2519 struct in6_addr *v6)
2526 allocate_v4_address (v4))
2527 *result_af = AF_UNSPEC;
2533 allocate_v6_address (v6))
2534 *result_af = AF_UNSPEC;
2540 allocate_v4_address (v4))
2543 *result_af = AF_INET;
2545 else if (GNUNET_OK ==
2546 allocate_v6_address (v6))
2549 *result_af = AF_INET6;
2554 return GNUNET_SYSERR;
2561 * A client asks us to setup a redirection via some exit node to a
2562 * particular IP. Setup the redirection and give the client the
2566 * @param client requesting client
2567 * @param message redirection request (a `struct RedirectToIpRequestMessage`)
2570 service_redirect_to_ip (void *cls,
2571 struct GNUNET_SERVER_Client *client,
2572 const struct GNUNET_MessageHeader *message)
2576 const struct RedirectToIpRequestMessage *msg;
2582 struct DestinationEntry *de;
2583 struct GNUNET_HashCode key;
2585 /* validate and parse request */
2586 mlen = ntohs (message->size);
2587 if (mlen < sizeof (struct RedirectToIpRequestMessage))
2590 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2593 alen = mlen - sizeof (struct RedirectToIpRequestMessage);
2594 msg = (const struct RedirectToIpRequestMessage *) message;
2595 addr_af = (int) htonl (msg->addr_af);
2599 if (alen != sizeof (struct in_addr))
2602 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2607 if (alen != sizeof (struct in6_addr))
2610 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2616 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2620 /* allocate response IP */
2621 result_af = (int) htonl (msg->result_af);
2622 if (GNUNET_OK != allocate_response_ip (&result_af,
2626 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2629 /* send reply with our IP address */
2630 send_client_reply (client,
2634 if (result_af == AF_UNSPEC)
2636 /* failure, we're done */
2637 GNUNET_SERVER_receive_done (client, GNUNET_OK);
2642 char sbuf[INET6_ADDRSTRLEN];
2643 char dbuf[INET6_ADDRSTRLEN];
2645 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2646 "Allocated address %s for redirection via exit to %s\n",
2647 inet_ntop (result_af, addr, sbuf, sizeof (sbuf)),
2649 &msg[1], dbuf, sizeof (dbuf)));
2652 /* setup destination record */
2653 de = GNUNET_new (struct DestinationEntry);
2654 de->is_service = GNUNET_NO;
2655 de->details.exit_destination.af = addr_af;
2656 memcpy (&de->details.exit_destination.ip,
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 GNUNET_STATISTICS_update (stats,
2672 gettext_noop ("# Active destinations"),
2674 while (GNUNET_CONTAINER_multihashmap_size (destination_map) > max_destination_mappings)
2675 expire_destination (de);
2676 GNUNET_SERVER_receive_done (client, GNUNET_OK);
2681 * A client asks us to setup a redirection to a particular peer
2682 * offering a service. Setup the redirection and give the client the
2686 * @param client requesting client
2687 * @param message redirection request (a `struct RedirectToPeerRequestMessage`)
2690 service_redirect_to_service (void *cls,
2691 struct GNUNET_SERVER_Client *client,
2692 const struct GNUNET_MessageHeader *message)
2694 const struct RedirectToServiceRequestMessage *msg;
2699 struct DestinationEntry *de;
2700 struct GNUNET_HashCode key;
2701 struct ChannelState *ts;
2702 struct DestinationChannel *dt;
2705 msg = (const struct RedirectToServiceRequestMessage *) message;
2707 /* allocate response IP */
2708 result_af = (int) htonl (msg->result_af);
2709 if (GNUNET_OK != allocate_response_ip (&result_af,
2713 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2716 send_client_reply (client,
2720 if (result_af == AF_UNSPEC)
2722 /* failure, we're done */
2723 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2724 _("Failed to allocate IP address for new destination\n"));
2725 GNUNET_SERVER_receive_done (client, GNUNET_OK);
2730 char sbuf[INET6_ADDRSTRLEN];
2732 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2733 "Allocated address %s for redirection to service %s on peer %s\n",
2734 inet_ntop (result_af, addr, sbuf, sizeof (sbuf)),
2735 GNUNET_h2s (&msg->service_descriptor),
2736 GNUNET_i2s (&msg->target));
2739 /* setup destination record */
2740 de = GNUNET_new (struct DestinationEntry);
2741 de->is_service = GNUNET_YES;
2742 de->details.service_destination.service_descriptor = msg->service_descriptor;
2743 de->details.service_destination.target = msg->target;
2744 get_destination_key_from_ip (result_af,
2748 GNUNET_assert (GNUNET_OK ==
2749 GNUNET_CONTAINER_multihashmap_put (destination_map,
2752 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE));
2753 de->heap_node = GNUNET_CONTAINER_heap_insert (destination_heap,
2755 GNUNET_TIME_absolute_ntoh (msg->expiration_time).abs_value_us);
2756 while (GNUNET_CONTAINER_multihashmap_size (destination_map) > max_destination_mappings)
2757 expire_destination (de);
2759 dt = GNUNET_new (struct DestinationChannel);
2760 dt->destination = de;
2761 GNUNET_CONTAINER_DLL_insert (de->dt_head,
2764 ts = create_channel_to_destination (dt,
2769 ts->destination_ip.v4 = v4;
2772 ts->destination_ip.v6 = v6;
2778 GNUNET_SERVER_receive_done (client, GNUNET_OK);
2783 * Function called whenever a channel is destroyed. Should clean up
2784 * any associated state.
2786 * @param cls closure (set from #GNUNET_CADET_connect)
2787 * @param channel connection to the other end (henceforth invalid)
2788 * @param channel_ctx place where local state associated
2789 * with the channel is stored (our `struct ChannelState`)
2792 channel_cleaner (void *cls,
2793 const struct GNUNET_CADET_Channel *channel,
2796 struct ChannelState *ts = channel_ctx;
2798 ts->channel = NULL; /* we must not call GNUNET_CADET_channel_destroy() anymore */
2799 free_channel_state (ts);
2804 * Free memory occupied by an entry in the destination map.
2808 * @param value a `struct DestinationEntry *`
2809 * @return #GNUNET_OK (continue to iterate)
2812 cleanup_destination (void *cls,
2813 const struct GNUNET_HashCode *key,
2816 struct DestinationEntry *de = value;
2818 free_destination_entry (de);
2824 * Free memory occupied by an entry in the channel map.
2828 * @param value a `struct ChannelState *`
2829 * @return #GNUNET_OK (continue to iterate)
2832 cleanup_channel (void *cls,
2833 const struct GNUNET_HashCode *key,
2836 struct ChannelState *ts = value;
2838 free_channel_state (ts);
2844 * Function scheduled as very last function, cleans up after us
2851 const struct GNUNET_SCHEDULER_TaskContext *tc)
2855 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2856 "VPN is shutting down\n");
2857 if (NULL != destination_map)
2859 GNUNET_CONTAINER_multihashmap_iterate (destination_map,
2860 &cleanup_destination,
2862 GNUNET_CONTAINER_multihashmap_destroy (destination_map);
2863 destination_map = NULL;
2865 if (NULL != destination_heap)
2867 GNUNET_CONTAINER_heap_destroy (destination_heap);
2868 destination_heap = NULL;
2870 if (NULL != channel_map)
2872 GNUNET_CONTAINER_multihashmap_iterate (channel_map,
2875 GNUNET_CONTAINER_multihashmap_destroy (channel_map);
2878 if (NULL != channel_heap)
2880 GNUNET_CONTAINER_heap_destroy (channel_heap);
2881 channel_heap = NULL;
2883 if (NULL != cadet_handle)
2885 GNUNET_CADET_disconnect (cadet_handle);
2886 cadet_handle = NULL;
2888 if (NULL != helper_handle)
2890 GNUNET_HELPER_stop (helper_handle, GNUNET_NO);
2891 helper_handle = NULL;
2895 GNUNET_SERVER_notification_context_destroy (nc);
2900 GNUNET_STATISTICS_destroy (stats, GNUNET_NO);
2904 GNUNET_free_non_null (vpn_argv[i]);
2909 * Main function that will be run by the scheduler.
2911 * @param cls closure
2912 * @param server the initialized server
2913 * @param cfg_ configuration
2917 struct GNUNET_SERVER_Handle *server,
2918 const struct GNUNET_CONFIGURATION_Handle *cfg_)
2920 static const struct GNUNET_SERVER_MessageHandler service_handlers[] = {
2921 /* callback, cls, type, size */
2922 { &service_redirect_to_ip, NULL, GNUNET_MESSAGE_TYPE_VPN_CLIENT_REDIRECT_TO_IP, 0},
2923 { &service_redirect_to_service, NULL,
2924 GNUNET_MESSAGE_TYPE_VPN_CLIENT_REDIRECT_TO_SERVICE,
2925 sizeof (struct RedirectToServiceRequestMessage) },
2928 static const struct GNUNET_CADET_MessageHandler cadet_handlers[] = {
2929 { &receive_udp_back, GNUNET_MESSAGE_TYPE_VPN_UDP_REPLY, 0},
2930 { &receive_tcp_back, GNUNET_MESSAGE_TYPE_VPN_TCP_DATA_TO_VPN, 0},
2931 { &receive_icmp_back, GNUNET_MESSAGE_TYPE_VPN_ICMP_TO_VPN, 0},
2943 binary = GNUNET_OS_get_libexec_binary_path ("gnunet-helper-vpn");
2946 GNUNET_OS_check_helper_binary (binary,
2948 "-d gnunet-vpn - - 169.1.3.3.7 255.255.255.0")) //ipv4 only please!
2950 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2951 "`%s' is not SUID, refusing to run.\n",
2952 "gnunet-helper-vpn");
2953 GNUNET_free (binary);
2955 /* we won't "really" exit here, as the 'service' is still running;
2956 however, as no handlers are registered, the service won't do
2960 GNUNET_free (binary);
2962 stats = GNUNET_STATISTICS_create ("vpn", cfg);
2964 GNUNET_CONFIGURATION_get_value_number (cfg, "VPN", "MAX_MAPPING",
2965 &max_destination_mappings))
2966 max_destination_mappings = 200;
2968 GNUNET_CONFIGURATION_get_value_number (cfg, "VPN", "MAX_TUNNELS",
2969 &max_channel_mappings))
2970 max_channel_mappings = 200;
2972 destination_map = GNUNET_CONTAINER_multihashmap_create (max_destination_mappings * 2, GNUNET_NO);
2973 destination_heap = GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN);
2974 channel_map = GNUNET_CONTAINER_multihashmap_create (max_channel_mappings * 2, GNUNET_NO);
2975 channel_heap = GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN);
2978 vpn_argv[0] = GNUNET_strdup ("vpn-gnunet");
2979 if (GNUNET_SYSERR ==
2980 GNUNET_CONFIGURATION_get_value_string (cfg, "VPN", "IFNAME", &ifname))
2982 GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, "VPN", "IFNAME");
2983 GNUNET_SCHEDULER_shutdown ();
2986 vpn_argv[1] = ifname;
2988 if (GNUNET_OK == GNUNET_NETWORK_test_pf (PF_INET6))
2990 if ( (GNUNET_SYSERR ==
2991 GNUNET_CONFIGURATION_get_value_string (cfg, "VPN", "IPV6ADDR",
2993 (1 != inet_pton (AF_INET6, ipv6addr, &v6))) )
2995 GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, "VPN", "IPV6ADDR",
2996 _("Must specify valid IPv6 address"));
2997 GNUNET_SCHEDULER_shutdown ();
2998 GNUNET_free_non_null (ipv6addr);
3001 vpn_argv[2] = ipv6addr;
3002 ipv6prefix_s = NULL;
3003 if (GNUNET_SYSERR ==
3004 GNUNET_CONFIGURATION_get_value_string (cfg, "VPN", "IPV6PREFIX",
3007 GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, "VPN", "IPV6PREFIX");
3008 GNUNET_SCHEDULER_shutdown ();
3009 GNUNET_free_non_null (ipv6prefix_s);
3012 vpn_argv[3] = ipv6prefix_s;
3014 GNUNET_CONFIGURATION_get_value_number (cfg, "VPN",
3017 (ipv6prefix >= 127) )
3019 GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, "VPN", "IPV4MASK",
3020 _("Must specify valid IPv6 mask"));
3021 GNUNET_SCHEDULER_shutdown ();
3027 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
3028 _("IPv6 support disabled as this system does not support IPv6\n"));
3029 vpn_argv[2] = GNUNET_strdup ("-");
3030 vpn_argv[3] = GNUNET_strdup ("-");
3032 if (GNUNET_OK == GNUNET_NETWORK_test_pf (PF_INET))
3035 if ( (GNUNET_SYSERR ==
3036 GNUNET_CONFIGURATION_get_value_string (cfg, "vpn", "IPV4ADDR",
3038 (1 != inet_pton (AF_INET, ipv4addr, &v4))) )
3040 GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, "VPN", "IPV4ADDR",
3041 _("Must specify valid IPv4 address"));
3042 GNUNET_SCHEDULER_shutdown ();
3043 GNUNET_free_non_null (ipv4addr);
3046 vpn_argv[4] = ipv4addr;
3048 if ( (GNUNET_SYSERR ==
3049 GNUNET_CONFIGURATION_get_value_string (cfg, "vpn", "IPV4MASK",
3051 (1 != inet_pton (AF_INET, ipv4mask, &v4))) )
3053 GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, "VPN", "IPV4MASK",
3054 _("Must specify valid IPv4 mask"));
3055 GNUNET_SCHEDULER_shutdown ();
3056 GNUNET_free_non_null (ipv4mask);
3059 vpn_argv[5] = ipv4mask;
3063 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
3064 _("IPv4 support disabled as this system does not support IPv4\n"));
3065 vpn_argv[4] = GNUNET_strdup ("-");
3066 vpn_argv[5] = GNUNET_strdup ("-");
3071 GNUNET_CADET_connect (cfg_, NULL,
3076 helper_handle = GNUNET_HELPER_start (GNUNET_NO,
3077 "gnunet-helper-vpn", vpn_argv,
3078 &message_token, NULL, NULL);
3079 nc = GNUNET_SERVER_notification_context_create (server, 1);
3080 GNUNET_SERVER_add_handlers (server, service_handlers);
3081 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &cleanup, cls);
3086 * The main function of the VPN service.
3088 * @param argc number of arguments from the command line
3089 * @param argv command line arguments
3090 * @return 0 ok, 1 on error
3093 main (int argc, char *const *argv)
3095 return (GNUNET_OK ==
3096 GNUNET_SERVICE_run (argc, argv, "vpn",
3097 GNUNET_SERVICE_OPTION_NONE,
3098 &run, NULL)) ? global_ret : 1;
3101 /* end of gnunet-service-vpn.c */