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_STATISTICS_update (stats,
1101 gettext_noop ("# Packets dropped (channel not yet online)"),
1107 /* send via channel */
1111 if (destination->is_service)
1113 struct GNUNET_EXIT_UdpServiceMessage *usm;
1115 mlen = sizeof (struct GNUNET_EXIT_UdpServiceMessage) +
1116 payload_length - sizeof (struct GNUNET_TUN_UdpHeader);
1117 if (mlen >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1122 tnq = GNUNET_malloc (sizeof (struct ChannelMessageQueueEntry) + mlen);
1125 usm = (struct GNUNET_EXIT_UdpServiceMessage *) &tnq[1];
1126 usm->header.size = htons ((uint16_t) mlen);
1127 usm->header.type = htons (GNUNET_MESSAGE_TYPE_VPN_UDP_TO_SERVICE);
1128 /* if the source port is below 32000, we assume it has a special
1129 meaning; if not, we pick a random port (this is a heuristic) */
1130 usm->source_port = (ntohs (udp->source_port) < 32000) ? udp->source_port : 0;
1131 usm->destination_port = udp->destination_port;
1132 usm->service_descriptor = destination->details.service_destination.service_descriptor;
1135 payload_length - sizeof (struct GNUNET_TUN_UdpHeader));
1139 struct GNUNET_EXIT_UdpInternetMessage *uim;
1140 struct in_addr *ip4dst;
1141 struct in6_addr *ip6dst;
1144 mlen = sizeof (struct GNUNET_EXIT_UdpInternetMessage) +
1145 alen + payload_length - sizeof (struct GNUNET_TUN_UdpHeader);
1146 if (mlen >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1151 tnq = GNUNET_malloc (sizeof (struct ChannelMessageQueueEntry) + mlen);
1154 uim = (struct GNUNET_EXIT_UdpInternetMessage *) &tnq[1];
1155 uim->header.size = htons ((uint16_t) mlen);
1156 uim->header.type = htons (GNUNET_MESSAGE_TYPE_VPN_UDP_TO_INTERNET);
1157 uim->af = htonl (destination->details.exit_destination.af);
1158 uim->source_port = (ntohs (udp->source_port) < 32000) ? udp->source_port : 0;
1159 uim->destination_port = udp->destination_port;
1160 switch (destination->details.exit_destination.af)
1163 ip4dst = (struct in_addr *) &uim[1];
1164 *ip4dst = destination->details.exit_destination.ip.v4;
1165 payload = &ip4dst[1];
1168 ip6dst = (struct in6_addr *) &uim[1];
1169 *ip6dst = destination->details.exit_destination.ip.v6;
1170 payload = &ip6dst[1];
1177 payload_length - sizeof (struct GNUNET_TUN_UdpHeader));
1183 if (destination->is_service)
1185 struct GNUNET_EXIT_TcpServiceStartMessage *tsm;
1187 mlen = sizeof (struct GNUNET_EXIT_TcpServiceStartMessage) +
1188 payload_length - sizeof (struct GNUNET_TUN_TcpHeader);
1189 if (mlen >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1194 tnq = GNUNET_malloc (sizeof (struct ChannelMessageQueueEntry) + mlen);
1197 tsm = (struct GNUNET_EXIT_TcpServiceStartMessage *) &tnq[1];
1198 tsm->header.size = htons ((uint16_t) mlen);
1199 tsm->header.type = htons (GNUNET_MESSAGE_TYPE_VPN_TCP_TO_SERVICE_START);
1200 tsm->reserved = htonl (0);
1201 tsm->service_descriptor = destination->details.service_destination.service_descriptor;
1202 tsm->tcp_header = *tcp;
1205 payload_length - sizeof (struct GNUNET_TUN_TcpHeader));
1209 struct GNUNET_EXIT_TcpInternetStartMessage *tim;
1210 struct in_addr *ip4dst;
1211 struct in6_addr *ip6dst;
1214 mlen = sizeof (struct GNUNET_EXIT_TcpInternetStartMessage) +
1215 alen + payload_length - sizeof (struct GNUNET_TUN_TcpHeader);
1216 if (mlen >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1221 tnq = GNUNET_malloc (sizeof (struct ChannelMessageQueueEntry) + mlen);
1224 tim = (struct GNUNET_EXIT_TcpInternetStartMessage *) &tnq[1];
1225 tim->header.size = htons ((uint16_t) mlen);
1226 tim->header.type = htons (GNUNET_MESSAGE_TYPE_VPN_TCP_TO_INTERNET_START);
1227 tim->af = htonl (destination->details.exit_destination.af);
1228 tim->tcp_header = *tcp;
1229 switch (destination->details.exit_destination.af)
1232 ip4dst = (struct in_addr *) &tim[1];
1233 *ip4dst = destination->details.exit_destination.ip.v4;
1234 payload = &ip4dst[1];
1237 ip6dst = (struct in6_addr *) &tim[1];
1238 *ip6dst = destination->details.exit_destination.ip.v6;
1239 payload = &ip6dst[1];
1246 payload_length - sizeof (struct GNUNET_TUN_TcpHeader));
1251 struct GNUNET_EXIT_TcpDataMessage *tdm;
1253 mlen = sizeof (struct GNUNET_EXIT_TcpDataMessage) +
1254 payload_length - sizeof (struct GNUNET_TUN_TcpHeader);
1255 if (mlen >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1260 tnq = GNUNET_malloc (sizeof (struct ChannelMessageQueueEntry) + mlen);
1263 tdm = (struct GNUNET_EXIT_TcpDataMessage *) &tnq[1];
1264 tdm->header.size = htons ((uint16_t) mlen);
1265 tdm->header.type = htons (GNUNET_MESSAGE_TYPE_VPN_TCP_DATA_TO_EXIT);
1266 tdm->reserved = htonl (0);
1267 tdm->tcp_header = *tcp;
1270 payload_length - sizeof (struct GNUNET_TUN_TcpHeader));
1274 case IPPROTO_ICMPV6:
1275 if (destination->is_service)
1277 struct GNUNET_EXIT_IcmpServiceMessage *ism;
1279 mlen = sizeof (struct GNUNET_EXIT_IcmpServiceMessage) +
1280 payload_length - sizeof (struct GNUNET_TUN_IcmpHeader);
1281 if (mlen >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1286 tnq = GNUNET_malloc (sizeof (struct ChannelMessageQueueEntry) + mlen);
1288 ism = (struct GNUNET_EXIT_IcmpServiceMessage *) &tnq[1];
1289 ism->header.type = htons (GNUNET_MESSAGE_TYPE_VPN_ICMP_TO_SERVICE);
1290 ism->af = htonl (af); /* need to tell destination ICMP protocol family! */
1291 ism->service_descriptor = destination->details.service_destination.service_descriptor;
1292 ism->icmp_header = *icmp;
1293 /* ICMP protocol translation will be done by the receiver (as we don't know
1294 the target AF); however, we still need to possibly discard the payload
1295 depending on the ICMP type */
1301 case GNUNET_TUN_ICMPTYPE_ECHO_REPLY:
1302 case GNUNET_TUN_ICMPTYPE_ECHO_REQUEST:
1304 case GNUNET_TUN_ICMPTYPE_DESTINATION_UNREACHABLE:
1305 case GNUNET_TUN_ICMPTYPE_SOURCE_QUENCH:
1306 case GNUNET_TUN_ICMPTYPE_TIME_EXCEEDED:
1307 /* throw away ICMP payload, won't be useful for the other side anyway */
1308 payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
1311 GNUNET_STATISTICS_update (stats,
1312 gettext_noop ("# ICMPv4 packets dropped (not allowed)"),
1316 /* end of AF_INET */
1321 case GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE:
1322 case GNUNET_TUN_ICMPTYPE6_PACKET_TOO_BIG:
1323 case GNUNET_TUN_ICMPTYPE6_TIME_EXCEEDED:
1324 case GNUNET_TUN_ICMPTYPE6_PARAMETER_PROBLEM:
1325 /* throw away ICMP payload, won't be useful for the other side anyway */
1326 payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
1328 case GNUNET_TUN_ICMPTYPE6_ECHO_REQUEST:
1329 case GNUNET_TUN_ICMPTYPE6_ECHO_REPLY:
1332 GNUNET_STATISTICS_update (stats,
1333 gettext_noop ("# ICMPv6 packets dropped (not allowed)"),
1337 /* end of AF_INET6 */
1344 /* update length calculations, as payload_length may have changed */
1345 mlen = sizeof (struct GNUNET_EXIT_IcmpServiceMessage) +
1346 alen + payload_length - sizeof (struct GNUNET_TUN_IcmpHeader);
1348 ism->header.size = htons ((uint16_t) mlen);
1349 /* finally, copy payload (if there is any left...) */
1352 payload_length - sizeof (struct GNUNET_TUN_IcmpHeader));
1356 struct GNUNET_EXIT_IcmpInternetMessage *iim;
1357 struct in_addr *ip4dst;
1358 struct in6_addr *ip6dst;
1361 mlen = sizeof (struct GNUNET_EXIT_IcmpInternetMessage) +
1362 alen + payload_length - sizeof (struct GNUNET_TUN_IcmpHeader);
1363 if (mlen >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1368 tnq = GNUNET_malloc (sizeof (struct ChannelMessageQueueEntry) + mlen);
1370 iim = (struct GNUNET_EXIT_IcmpInternetMessage *) &tnq[1];
1371 iim->header.type = htons (GNUNET_MESSAGE_TYPE_VPN_ICMP_TO_INTERNET);
1372 iim->icmp_header = *icmp;
1373 /* Perform ICMP protocol-translation (depending on destination AF and source AF)
1374 and throw away ICMP payload depending on ICMP message type */
1380 case GNUNET_TUN_ICMPTYPE_ECHO_REPLY:
1381 if (destination->details.exit_destination.af == AF_INET6)
1382 iim->icmp_header.type = GNUNET_TUN_ICMPTYPE6_ECHO_REPLY;
1384 case GNUNET_TUN_ICMPTYPE_ECHO_REQUEST:
1385 if (destination->details.exit_destination.af == AF_INET6)
1386 iim->icmp_header.type = GNUNET_TUN_ICMPTYPE6_ECHO_REQUEST;
1388 case GNUNET_TUN_ICMPTYPE_DESTINATION_UNREACHABLE:
1389 if (destination->details.exit_destination.af == AF_INET6)
1390 iim->icmp_header.type = GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE;
1391 /* throw away IP-payload, exit will have to make it up anyway */
1392 payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
1394 case GNUNET_TUN_ICMPTYPE_TIME_EXCEEDED:
1395 if (destination->details.exit_destination.af == AF_INET6)
1396 iim->icmp_header.type = GNUNET_TUN_ICMPTYPE6_TIME_EXCEEDED;
1397 /* throw away IP-payload, exit will have to make it up anyway */
1398 payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
1400 case GNUNET_TUN_ICMPTYPE_SOURCE_QUENCH:
1401 if (destination->details.exit_destination.af == AF_INET6)
1403 GNUNET_STATISTICS_update (stats,
1404 gettext_noop ("# ICMPv4 packets dropped (impossible PT to v6)"),
1409 /* throw away IP-payload, exit will have to make it up anyway */
1410 payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
1413 GNUNET_STATISTICS_update (stats,
1414 gettext_noop ("# ICMPv4 packets dropped (type not allowed)"),
1419 /* end of AF_INET */
1424 case GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE:
1425 if (destination->details.exit_destination.af == AF_INET6)
1426 iim->icmp_header.type = GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE;
1427 /* throw away IP-payload, exit will have to make it up anyway */
1428 payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
1430 case GNUNET_TUN_ICMPTYPE6_TIME_EXCEEDED:
1431 if (destination->details.exit_destination.af == AF_INET)
1432 iim->icmp_header.type = GNUNET_TUN_ICMPTYPE_TIME_EXCEEDED;
1433 /* throw away IP-payload, exit will have to make it up anyway */
1434 payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
1436 case GNUNET_TUN_ICMPTYPE6_PACKET_TOO_BIG:
1437 if (destination->details.exit_destination.af == AF_INET)
1439 GNUNET_STATISTICS_update (stats,
1440 gettext_noop ("# ICMPv6 packets dropped (impossible PT to v4)"),
1445 /* throw away IP-payload, exit will have to make it up anyway */
1446 payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
1448 case GNUNET_TUN_ICMPTYPE6_PARAMETER_PROBLEM:
1449 if (destination->details.exit_destination.af == AF_INET)
1451 GNUNET_STATISTICS_update (stats,
1452 gettext_noop ("# ICMPv6 packets dropped (impossible PT to v4)"),
1457 /* throw away IP-payload, exit will have to make it up anyway */
1458 payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
1460 case GNUNET_TUN_ICMPTYPE6_ECHO_REQUEST:
1461 if (destination->details.exit_destination.af == AF_INET)
1462 iim->icmp_header.type = GNUNET_TUN_ICMPTYPE_ECHO_REQUEST;
1464 case GNUNET_TUN_ICMPTYPE6_ECHO_REPLY:
1465 if (destination->details.exit_destination.af == AF_INET)
1466 iim->icmp_header.type = GNUNET_TUN_ICMPTYPE_ECHO_REPLY;
1469 GNUNET_STATISTICS_update (stats,
1470 gettext_noop ("# ICMPv6 packets dropped (type not allowed)"),
1475 /* end of AF_INET6 */
1480 /* update length calculations, as payload_length may have changed */
1481 mlen = sizeof (struct GNUNET_EXIT_IcmpInternetMessage) +
1482 alen + payload_length - sizeof (struct GNUNET_TUN_IcmpHeader);
1484 iim->header.size = htons ((uint16_t) mlen);
1486 /* need to tell destination ICMP protocol family! */
1487 iim->af = htonl (destination->details.exit_destination.af);
1488 switch (destination->details.exit_destination.af)
1491 ip4dst = (struct in_addr *) &iim[1];
1492 *ip4dst = destination->details.exit_destination.ip.v4;
1493 payload = &ip4dst[1];
1496 ip6dst = (struct in6_addr *) &iim[1];
1497 *ip6dst = destination->details.exit_destination.ip.v6;
1498 payload = &ip6dst[1];
1505 payload_length - sizeof (struct GNUNET_TUN_IcmpHeader));
1509 /* not supported above, how can we get here !? */
1513 send_to_channel (tnq, ts);
1518 * Receive packets from the helper-process (someone send to the local
1519 * virtual channel interface). Find the destination mapping, and if it
1520 * exists, identify the correct CADET channel (or possibly create it)
1521 * and forward the packet.
1523 * @param cls closure, NULL
1524 * @param client NULL
1525 * @param message message we got from the client (VPN channel interface)
1528 message_token (void *cls,
1530 const struct GNUNET_MessageHeader *message)
1532 const struct GNUNET_TUN_Layer2PacketHeader *tun;
1534 struct GNUNET_HashCode key;
1535 struct DestinationEntry *de;
1537 GNUNET_STATISTICS_update (stats,
1538 gettext_noop ("# Packets received from TUN interface"),
1540 mlen = ntohs (message->size);
1541 if ( (ntohs (message->type) != GNUNET_MESSAGE_TYPE_VPN_HELPER) ||
1542 (mlen < sizeof (struct GNUNET_MessageHeader) + sizeof (struct GNUNET_TUN_Layer2PacketHeader)) )
1547 tun = (const struct GNUNET_TUN_Layer2PacketHeader *) &message[1];
1548 mlen -= (sizeof (struct GNUNET_MessageHeader) + sizeof (struct GNUNET_TUN_Layer2PacketHeader));
1549 switch (ntohs (tun->proto))
1553 const struct GNUNET_TUN_IPv6Header *pkt6;
1555 if (mlen < sizeof (struct GNUNET_TUN_IPv6Header))
1561 pkt6 = (const struct GNUNET_TUN_IPv6Header *) &tun[1];
1562 get_destination_key_from_ip (AF_INET6,
1563 &pkt6->destination_address,
1565 de = GNUNET_CONTAINER_multihashmap_get (destination_map, &key);
1568 char buf[INET6_ADDRSTRLEN];
1570 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1571 _("Packet received for unmapped destination `%s' (dropping it)\n"),
1572 inet_ntop (AF_INET6,
1573 &pkt6->destination_address,
1581 &pkt6->source_address,
1582 &pkt6->destination_address,
1584 mlen - sizeof (struct GNUNET_TUN_IPv6Header));
1589 struct GNUNET_TUN_IPv4Header *pkt4;
1591 if (mlen < sizeof (struct GNUNET_TUN_IPv4Header))
1597 pkt4 = (struct GNUNET_TUN_IPv4Header *) &tun[1];
1598 get_destination_key_from_ip (AF_INET,
1599 &pkt4->destination_address,
1601 de = GNUNET_CONTAINER_multihashmap_get (destination_map, &key);
1604 char buf[INET_ADDRSTRLEN];
1606 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1607 _("Packet received for unmapped destination `%s' (dropping it)\n"),
1609 &pkt4->destination_address,
1614 if (pkt4->header_length * 4 != sizeof (struct GNUNET_TUN_IPv4Header))
1616 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1617 _("Received IPv4 packet with options (dropping it)\n"));
1623 &pkt4->source_address,
1624 &pkt4->destination_address,
1626 mlen - sizeof (struct GNUNET_TUN_IPv4Header));
1630 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1631 _("Received packet of unknown protocol %d from TUN (dropping it)\n"),
1632 (unsigned int) ntohs (tun->proto));
1640 * Synthesize a plausible ICMP payload for an ICMP error
1641 * response on the given channel.
1643 * @param ts channel information
1644 * @param ipp IPv4 header to fill in (ICMP payload)
1645 * @param udp "UDP" header to fill in (ICMP payload); might actually
1646 * also be the first 8 bytes of the TCP header
1649 make_up_icmpv4_payload (struct ChannelState *ts,
1650 struct GNUNET_TUN_IPv4Header *ipp,
1651 struct GNUNET_TUN_UdpHeader *udp)
1653 GNUNET_TUN_initialize_ipv4_header (ipp,
1655 sizeof (struct GNUNET_TUN_TcpHeader),
1657 &ts->destination_ip.v4);
1658 udp->source_port = htons (ts->source_port);
1659 udp->destination_port = htons (ts->destination_port);
1660 udp->len = htons (0);
1661 udp->crc = htons (0);
1666 * Synthesize a plausible ICMP payload for an ICMP error
1667 * response on the given channel.
1669 * @param ts channel information
1670 * @param ipp IPv6 header to fill in (ICMP payload)
1671 * @param udp "UDP" header to fill in (ICMP payload); might actually
1672 * also be the first 8 bytes of the TCP header
1675 make_up_icmpv6_payload (struct ChannelState *ts,
1676 struct GNUNET_TUN_IPv6Header *ipp,
1677 struct GNUNET_TUN_UdpHeader *udp)
1679 GNUNET_TUN_initialize_ipv6_header (ipp,
1681 sizeof (struct GNUNET_TUN_TcpHeader),
1683 &ts->destination_ip.v6);
1684 udp->source_port = htons (ts->source_port);
1685 udp->destination_port = htons (ts->destination_port);
1686 udp->len = htons (0);
1687 udp->crc = htons (0);
1692 * We got an ICMP packet back from the CADET channel. Pass it on to the
1693 * local virtual interface via the helper.
1695 * @param cls closure, NULL
1696 * @param channel connection to the other end
1697 * @param channel_ctx pointer to our 'struct ChannelState *'
1698 * @param message the actual message
1699 * @return #GNUNET_OK to keep the connection open,
1700 * #GNUNET_SYSERR to close it (signal serious error)
1703 receive_icmp_back (void *cls,
1704 struct GNUNET_CADET_Channel *channel,
1706 const struct GNUNET_MessageHeader *message)
1708 struct ChannelState *ts = *channel_ctx;
1709 const struct GNUNET_EXIT_IcmpToVPNMessage *i2v;
1712 GNUNET_STATISTICS_update (stats,
1713 gettext_noop ("# ICMP packets received from cadet"),
1715 mlen = ntohs (message->size);
1716 if (mlen < sizeof (struct GNUNET_EXIT_IcmpToVPNMessage))
1718 GNUNET_break_op (0);
1719 return GNUNET_SYSERR;
1721 if (NULL == ts->heap_node)
1723 GNUNET_break_op (0);
1724 return GNUNET_SYSERR;
1726 if (AF_UNSPEC == ts->af)
1728 GNUNET_break_op (0);
1729 return GNUNET_SYSERR;
1731 i2v = (const struct GNUNET_EXIT_IcmpToVPNMessage *) message;
1732 mlen -= sizeof (struct GNUNET_EXIT_IcmpToVPNMessage);
1734 char sbuf[INET6_ADDRSTRLEN];
1735 char dbuf[INET6_ADDRSTRLEN];
1737 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1738 "Received ICMP packet from cadet, sending %u bytes from %s -> %s via TUN\n",
1739 (unsigned int) mlen,
1740 inet_ntop (ts->af, &ts->destination_ip, sbuf, sizeof (sbuf)),
1741 inet_ntop (ts->af, &ts->source_ip, dbuf, sizeof (dbuf)));
1747 size_t size = sizeof (struct GNUNET_TUN_IPv4Header)
1748 + sizeof (struct GNUNET_TUN_IcmpHeader)
1749 + sizeof (struct GNUNET_MessageHeader) +
1750 sizeof (struct GNUNET_TUN_Layer2PacketHeader) +
1753 /* reserve some extra space in case we have an ICMP type here where
1754 we will need to make up the payload ourselves */
1755 char buf[size + sizeof (struct GNUNET_TUN_IPv4Header) + 8] GNUNET_ALIGN;
1756 struct GNUNET_MessageHeader *msg = (struct GNUNET_MessageHeader *) buf;
1757 struct GNUNET_TUN_Layer2PacketHeader *tun = (struct GNUNET_TUN_Layer2PacketHeader*) &msg[1];
1758 struct GNUNET_TUN_IPv4Header *ipv4 = (struct GNUNET_TUN_IPv4Header *) &tun[1];
1759 struct GNUNET_TUN_IcmpHeader *icmp = (struct GNUNET_TUN_IcmpHeader *) &ipv4[1];
1760 msg->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
1761 tun->flags = htons (0);
1762 tun->proto = htons (ETH_P_IPV4);
1763 GNUNET_TUN_initialize_ipv4_header (ipv4,
1765 sizeof (struct GNUNET_TUN_IcmpHeader) + mlen,
1766 &ts->destination_ip.v4,
1768 *icmp = i2v->icmp_header;
1772 /* For some ICMP types, we need to adjust (make up) the payload here.
1773 Also, depending on the AF used on the other side, we have to
1774 do ICMP PT (translate ICMP types) */
1775 switch (ntohl (i2v->af))
1780 case GNUNET_TUN_ICMPTYPE_ECHO_REPLY:
1781 case GNUNET_TUN_ICMPTYPE_ECHO_REQUEST:
1783 case GNUNET_TUN_ICMPTYPE_DESTINATION_UNREACHABLE:
1784 case GNUNET_TUN_ICMPTYPE_SOURCE_QUENCH:
1785 case GNUNET_TUN_ICMPTYPE_TIME_EXCEEDED:
1787 struct GNUNET_TUN_IPv4Header *ipp = (struct GNUNET_TUN_IPv4Header *) &icmp[1];
1788 struct GNUNET_TUN_UdpHeader *udp = (struct GNUNET_TUN_UdpHeader *) &ipp[1];
1792 /* sender did not strip ICMP payload? */
1793 GNUNET_break_op (0);
1794 return GNUNET_SYSERR;
1796 size += sizeof (struct GNUNET_TUN_IPv4Header) + 8;
1797 GNUNET_assert (8 == sizeof (struct GNUNET_TUN_UdpHeader));
1798 make_up_icmpv4_payload (ts, ipp, udp);
1802 GNUNET_break_op (0);
1803 GNUNET_STATISTICS_update (stats,
1804 gettext_noop ("# ICMPv4 packets dropped (type not allowed)"),
1806 return GNUNET_SYSERR;
1811 /* ICMP PT 6-to-4 and possibly making up payloads */
1814 case GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE:
1815 icmp->type = GNUNET_TUN_ICMPTYPE_DESTINATION_UNREACHABLE;
1817 struct GNUNET_TUN_IPv4Header *ipp = (struct GNUNET_TUN_IPv4Header *) &icmp[1];
1818 struct GNUNET_TUN_UdpHeader *udp = (struct GNUNET_TUN_UdpHeader *) &ipp[1];
1822 /* sender did not strip ICMP payload? */
1823 GNUNET_break_op (0);
1824 return GNUNET_SYSERR;
1826 size += sizeof (struct GNUNET_TUN_IPv4Header) + 8;
1827 GNUNET_assert (8 == sizeof (struct GNUNET_TUN_UdpHeader));
1828 make_up_icmpv4_payload (ts, ipp, udp);
1831 case GNUNET_TUN_ICMPTYPE6_TIME_EXCEEDED:
1832 icmp->type = GNUNET_TUN_ICMPTYPE_TIME_EXCEEDED;
1834 struct GNUNET_TUN_IPv4Header *ipp = (struct GNUNET_TUN_IPv4Header *) &icmp[1];
1835 struct GNUNET_TUN_UdpHeader *udp = (struct GNUNET_TUN_UdpHeader *) &ipp[1];
1839 /* sender did not strip ICMP payload? */
1840 GNUNET_break_op (0);
1841 return GNUNET_SYSERR;
1843 size += sizeof (struct GNUNET_TUN_IPv4Header) + 8;
1844 GNUNET_assert (8 == sizeof (struct GNUNET_TUN_UdpHeader));
1845 make_up_icmpv4_payload (ts, ipp, udp);
1848 case GNUNET_TUN_ICMPTYPE6_PACKET_TOO_BIG:
1849 case GNUNET_TUN_ICMPTYPE6_PARAMETER_PROBLEM:
1850 GNUNET_STATISTICS_update (stats,
1851 gettext_noop ("# ICMPv6 packets dropped (impossible PT to v4)"),
1854 case GNUNET_TUN_ICMPTYPE6_ECHO_REQUEST:
1855 icmp->type = GNUNET_TUN_ICMPTYPE_ECHO_REQUEST;
1857 case GNUNET_TUN_ICMPTYPE6_ECHO_REPLY:
1858 icmp->type = GNUNET_TUN_ICMPTYPE_ECHO_REPLY;
1861 GNUNET_break_op (0);
1862 GNUNET_STATISTICS_update (stats,
1863 gettext_noop ("# ICMPv6 packets dropped (type not allowed)"),
1865 return GNUNET_SYSERR;
1870 GNUNET_break_op (0);
1871 return GNUNET_SYSERR;
1873 msg->size = htons (size);
1874 GNUNET_TUN_calculate_icmp_checksum (icmp,
1877 (void) GNUNET_HELPER_send (helper_handle,
1886 size_t size = sizeof (struct GNUNET_TUN_IPv6Header)
1887 + sizeof (struct GNUNET_TUN_IcmpHeader)
1888 + sizeof (struct GNUNET_MessageHeader) +
1889 sizeof (struct GNUNET_TUN_Layer2PacketHeader) +
1892 char buf[size + sizeof (struct GNUNET_TUN_IPv6Header) + 8] GNUNET_ALIGN;
1893 struct GNUNET_MessageHeader *msg = (struct GNUNET_MessageHeader *) buf;
1894 struct GNUNET_TUN_Layer2PacketHeader *tun = (struct GNUNET_TUN_Layer2PacketHeader*) &msg[1];
1895 struct GNUNET_TUN_IPv6Header *ipv6 = (struct GNUNET_TUN_IPv6Header *) &tun[1];
1896 struct GNUNET_TUN_IcmpHeader *icmp = (struct GNUNET_TUN_IcmpHeader *) &ipv6[1];
1897 msg->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
1898 tun->flags = htons (0);
1899 tun->proto = htons (ETH_P_IPV6);
1900 GNUNET_TUN_initialize_ipv6_header (ipv6,
1902 sizeof (struct GNUNET_TUN_IcmpHeader) + mlen,
1903 &ts->destination_ip.v6,
1905 *icmp = i2v->icmp_header;
1910 /* For some ICMP types, we need to adjust (make up) the payload here.
1911 Also, depending on the AF used on the other side, we have to
1912 do ICMP PT (translate ICMP types) */
1913 switch (ntohl (i2v->af))
1916 /* ICMP PT 4-to-6 and possibly making up payloads */
1919 case GNUNET_TUN_ICMPTYPE_ECHO_REPLY:
1920 icmp->type = GNUNET_TUN_ICMPTYPE6_ECHO_REPLY;
1922 case GNUNET_TUN_ICMPTYPE_ECHO_REQUEST:
1923 icmp->type = GNUNET_TUN_ICMPTYPE6_ECHO_REQUEST;
1925 case GNUNET_TUN_ICMPTYPE_DESTINATION_UNREACHABLE:
1926 icmp->type = GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE;
1928 struct GNUNET_TUN_IPv6Header *ipp = (struct GNUNET_TUN_IPv6Header *) &icmp[1];
1929 struct GNUNET_TUN_UdpHeader *udp = (struct GNUNET_TUN_UdpHeader *) &ipp[1];
1933 /* sender did not strip ICMP payload? */
1934 GNUNET_break_op (0);
1935 return GNUNET_SYSERR;
1937 size += sizeof (struct GNUNET_TUN_IPv6Header) + 8;
1938 GNUNET_assert (8 == sizeof (struct GNUNET_TUN_UdpHeader));
1939 make_up_icmpv6_payload (ts, ipp, udp);
1942 case GNUNET_TUN_ICMPTYPE_TIME_EXCEEDED:
1943 icmp->type = GNUNET_TUN_ICMPTYPE6_TIME_EXCEEDED;
1945 struct GNUNET_TUN_IPv6Header *ipp = (struct GNUNET_TUN_IPv6Header *) &icmp[1];
1946 struct GNUNET_TUN_UdpHeader *udp = (struct GNUNET_TUN_UdpHeader *) &ipp[1];
1950 /* sender did not strip ICMP payload? */
1951 GNUNET_break_op (0);
1952 return GNUNET_SYSERR;
1954 size += sizeof (struct GNUNET_TUN_IPv6Header) + 8;
1955 GNUNET_assert (8 == sizeof (struct GNUNET_TUN_UdpHeader));
1956 make_up_icmpv6_payload (ts, ipp, udp);
1959 case GNUNET_TUN_ICMPTYPE_SOURCE_QUENCH:
1960 GNUNET_STATISTICS_update (stats,
1961 gettext_noop ("# ICMPv4 packets dropped (impossible PT to v6)"),
1965 GNUNET_break_op (0);
1966 GNUNET_STATISTICS_update (stats,
1967 gettext_noop ("# ICMPv4 packets dropped (type not allowed)"),
1969 return GNUNET_SYSERR;
1976 case GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE:
1977 case GNUNET_TUN_ICMPTYPE6_TIME_EXCEEDED:
1978 case GNUNET_TUN_ICMPTYPE6_PACKET_TOO_BIG:
1979 case GNUNET_TUN_ICMPTYPE6_PARAMETER_PROBLEM:
1981 struct GNUNET_TUN_IPv6Header *ipp = (struct GNUNET_TUN_IPv6Header *) &icmp[1];
1982 struct GNUNET_TUN_UdpHeader *udp = (struct GNUNET_TUN_UdpHeader *) &ipp[1];
1986 /* sender did not strip ICMP payload? */
1987 GNUNET_break_op (0);
1988 return GNUNET_SYSERR;
1990 size += sizeof (struct GNUNET_TUN_IPv6Header) + 8;
1991 GNUNET_assert (8 == sizeof (struct GNUNET_TUN_UdpHeader));
1992 make_up_icmpv6_payload (ts, ipp, udp);
1995 case GNUNET_TUN_ICMPTYPE6_ECHO_REQUEST:
1998 GNUNET_break_op (0);
1999 GNUNET_STATISTICS_update (stats,
2000 gettext_noop ("# ICMPv6 packets dropped (type not allowed)"),
2002 return GNUNET_SYSERR;
2007 GNUNET_break_op (0);
2008 return GNUNET_SYSERR;
2010 msg->size = htons (size);
2011 GNUNET_TUN_calculate_icmp_checksum (icmp,
2013 (void) GNUNET_HELPER_send (helper_handle,
2023 GNUNET_CONTAINER_heap_update_cost (channel_heap,
2025 GNUNET_TIME_absolute_get ().abs_value_us);
2031 * We got a UDP packet back from the CADET channel. Pass it on to the
2032 * local virtual interface via the helper.
2034 * @param cls closure, NULL
2035 * @param channel connection to the other end
2036 * @param channel_ctx pointer to our 'struct ChannelState *'
2037 * @param message the actual message
2038 * @return #GNUNET_OK to keep the connection open,
2039 * #GNUNET_SYSERR to close it (signal serious error)
2042 receive_udp_back (void *cls,
2043 struct GNUNET_CADET_Channel *channel,
2045 const struct GNUNET_MessageHeader *message)
2047 struct ChannelState *ts = *channel_ctx;
2048 const struct GNUNET_EXIT_UdpReplyMessage *reply;
2051 GNUNET_STATISTICS_update (stats,
2052 gettext_noop ("# UDP packets received from cadet"),
2054 mlen = ntohs (message->size);
2055 if (mlen < sizeof (struct GNUNET_EXIT_UdpReplyMessage))
2057 GNUNET_break_op (0);
2058 return GNUNET_SYSERR;
2060 if (NULL == ts->heap_node)
2062 GNUNET_break_op (0);
2063 return GNUNET_SYSERR;
2065 if (AF_UNSPEC == ts->af)
2067 GNUNET_break_op (0);
2068 return GNUNET_SYSERR;
2070 reply = (const struct GNUNET_EXIT_UdpReplyMessage *) message;
2071 mlen -= sizeof (struct GNUNET_EXIT_UdpReplyMessage);
2073 char sbuf[INET6_ADDRSTRLEN];
2074 char dbuf[INET6_ADDRSTRLEN];
2076 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2077 "Received UDP reply from cadet, sending %u bytes from %s:%u -> %s:%u via TUN\n",
2078 (unsigned int) mlen,
2079 inet_ntop (ts->af, &ts->destination_ip, sbuf, sizeof (sbuf)),
2080 ts->destination_port,
2081 inet_ntop (ts->af, &ts->source_ip, dbuf, sizeof (dbuf)),
2088 size_t size = sizeof (struct GNUNET_TUN_IPv4Header)
2089 + sizeof (struct GNUNET_TUN_UdpHeader)
2090 + sizeof (struct GNUNET_MessageHeader) +
2091 sizeof (struct GNUNET_TUN_Layer2PacketHeader) +
2094 char buf[size] GNUNET_ALIGN;
2095 struct GNUNET_MessageHeader *msg = (struct GNUNET_MessageHeader *) buf;
2096 struct GNUNET_TUN_Layer2PacketHeader *tun = (struct GNUNET_TUN_Layer2PacketHeader*) &msg[1];
2097 struct GNUNET_TUN_IPv4Header *ipv4 = (struct GNUNET_TUN_IPv4Header *) &tun[1];
2098 struct GNUNET_TUN_UdpHeader *udp = (struct GNUNET_TUN_UdpHeader *) &ipv4[1];
2099 msg->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
2100 msg->size = htons (size);
2101 tun->flags = htons (0);
2102 tun->proto = htons (ETH_P_IPV4);
2103 GNUNET_TUN_initialize_ipv4_header (ipv4,
2105 sizeof (struct GNUNET_TUN_UdpHeader) + mlen,
2106 &ts->destination_ip.v4,
2108 if (0 == ntohs (reply->source_port))
2109 udp->source_port = htons (ts->destination_port);
2111 udp->source_port = reply->source_port;
2112 if (0 == ntohs (reply->destination_port))
2113 udp->destination_port = htons (ts->source_port);
2115 udp->destination_port = reply->destination_port;
2116 udp->len = htons (mlen + sizeof (struct GNUNET_TUN_UdpHeader));
2117 GNUNET_TUN_calculate_udp4_checksum (ipv4,
2124 (void) GNUNET_HELPER_send (helper_handle,
2133 size_t size = sizeof (struct GNUNET_TUN_IPv6Header)
2134 + sizeof (struct GNUNET_TUN_UdpHeader)
2135 + sizeof (struct GNUNET_MessageHeader) +
2136 sizeof (struct GNUNET_TUN_Layer2PacketHeader) +
2139 char buf[size] GNUNET_ALIGN;
2140 struct GNUNET_MessageHeader *msg = (struct GNUNET_MessageHeader *) buf;
2141 struct GNUNET_TUN_Layer2PacketHeader *tun = (struct GNUNET_TUN_Layer2PacketHeader*) &msg[1];
2142 struct GNUNET_TUN_IPv6Header *ipv6 = (struct GNUNET_TUN_IPv6Header *) &tun[1];
2143 struct GNUNET_TUN_UdpHeader *udp = (struct GNUNET_TUN_UdpHeader *) &ipv6[1];
2144 msg->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
2145 msg->size = htons (size);
2146 tun->flags = htons (0);
2147 tun->proto = htons (ETH_P_IPV6);
2148 GNUNET_TUN_initialize_ipv6_header (ipv6,
2150 sizeof (struct GNUNET_TUN_UdpHeader) + mlen,
2151 &ts->destination_ip.v6,
2153 if (0 == ntohs (reply->source_port))
2154 udp->source_port = htons (ts->destination_port);
2156 udp->source_port = reply->source_port;
2157 if (0 == ntohs (reply->destination_port))
2158 udp->destination_port = htons (ts->source_port);
2160 udp->destination_port = reply->destination_port;
2161 udp->len = htons (mlen + sizeof (struct GNUNET_TUN_UdpHeader));
2162 GNUNET_TUN_calculate_udp6_checksum (ipv6,
2168 (void) GNUNET_HELPER_send (helper_handle,
2178 GNUNET_CONTAINER_heap_update_cost (channel_heap,
2180 GNUNET_TIME_absolute_get ().abs_value_us);
2186 * We got a TCP packet back from the CADET channel. Pass it on to the
2187 * local virtual interface via the helper.
2189 * @param cls closure, NULL
2190 * @param channel connection to the other end
2191 * @param channel_ctx pointer to our `struct ChannelState *`
2192 * @param message the actual message
2193 * @return #GNUNET_OK to keep the connection open,
2194 * #GNUNET_SYSERR to close it (signal serious error)
2197 receive_tcp_back (void *cls,
2198 struct GNUNET_CADET_Channel *channel,
2200 const struct GNUNET_MessageHeader *message)
2202 struct ChannelState *ts = *channel_ctx;
2203 const struct GNUNET_EXIT_TcpDataMessage *data;
2206 GNUNET_STATISTICS_update (stats,
2207 gettext_noop ("# TCP packets received from cadet"),
2209 mlen = ntohs (message->size);
2210 if (mlen < sizeof (struct GNUNET_EXIT_TcpDataMessage))
2212 GNUNET_break_op (0);
2213 return GNUNET_SYSERR;
2215 if (NULL == ts->heap_node)
2217 GNUNET_break_op (0);
2218 return GNUNET_SYSERR;
2220 data = (const struct GNUNET_EXIT_TcpDataMessage *) message;
2221 mlen -= sizeof (struct GNUNET_EXIT_TcpDataMessage);
2223 char sbuf[INET6_ADDRSTRLEN];
2224 char dbuf[INET6_ADDRSTRLEN];
2226 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2227 "Received TCP reply from cadet, sending %u bytes from %s:%u -> %s:%u via TUN\n",
2228 (unsigned int) mlen,
2229 inet_ntop (ts->af, &ts->destination_ip, sbuf, sizeof (sbuf)),
2230 ts->destination_port,
2231 inet_ntop (ts->af, &ts->source_ip, dbuf, sizeof (dbuf)),
2234 if (data->tcp_header.off * 4 < sizeof (struct GNUNET_TUN_TcpHeader))
2236 GNUNET_break_op (0);
2237 return GNUNET_SYSERR;
2243 size_t size = sizeof (struct GNUNET_TUN_IPv4Header)
2244 + sizeof (struct GNUNET_TUN_TcpHeader)
2245 + sizeof (struct GNUNET_MessageHeader) +
2246 sizeof (struct GNUNET_TUN_Layer2PacketHeader) +
2249 char buf[size] GNUNET_ALIGN;
2250 struct GNUNET_MessageHeader *msg = (struct GNUNET_MessageHeader *) buf;
2251 struct GNUNET_TUN_Layer2PacketHeader *tun = (struct GNUNET_TUN_Layer2PacketHeader*) &msg[1];
2252 struct GNUNET_TUN_IPv4Header *ipv4 = (struct GNUNET_TUN_IPv4Header *) &tun[1];
2253 struct GNUNET_TUN_TcpHeader *tcp = (struct GNUNET_TUN_TcpHeader *) &ipv4[1];
2254 msg->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
2255 msg->size = htons (size);
2256 tun->flags = htons (0);
2257 tun->proto = htons (ETH_P_IPV4);
2258 GNUNET_TUN_initialize_ipv4_header (ipv4,
2260 sizeof (struct GNUNET_TUN_TcpHeader) + mlen,
2261 &ts->destination_ip.v4,
2263 *tcp = data->tcp_header;
2264 tcp->source_port = htons (ts->destination_port);
2265 tcp->destination_port = htons (ts->source_port);
2266 GNUNET_TUN_calculate_tcp4_checksum (ipv4,
2273 (void) GNUNET_HELPER_send (helper_handle,
2282 size_t size = sizeof (struct GNUNET_TUN_IPv6Header)
2283 + sizeof (struct GNUNET_TUN_TcpHeader)
2284 + sizeof (struct GNUNET_MessageHeader) +
2285 sizeof (struct GNUNET_TUN_Layer2PacketHeader) +
2288 char buf[size] GNUNET_ALIGN;
2289 struct GNUNET_MessageHeader *msg = (struct GNUNET_MessageHeader *) buf;
2290 struct GNUNET_TUN_Layer2PacketHeader *tun = (struct GNUNET_TUN_Layer2PacketHeader*) &msg[1];
2291 struct GNUNET_TUN_IPv6Header *ipv6 = (struct GNUNET_TUN_IPv6Header *) &tun[1];
2292 struct GNUNET_TUN_TcpHeader *tcp = (struct GNUNET_TUN_TcpHeader *) &ipv6[1];
2293 msg->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
2294 msg->size = htons (size);
2295 tun->flags = htons (0);
2296 tun->proto = htons (ETH_P_IPV6);
2297 GNUNET_TUN_initialize_ipv6_header (ipv6,
2299 sizeof (struct GNUNET_TUN_TcpHeader) + mlen,
2300 &ts->destination_ip.v6,
2302 *tcp = data->tcp_header;
2303 tcp->source_port = htons (ts->destination_port);
2304 tcp->destination_port = htons (ts->source_port);
2305 GNUNET_TUN_calculate_tcp6_checksum (ipv6,
2312 (void) GNUNET_HELPER_send (helper_handle,
2320 GNUNET_CONTAINER_heap_update_cost (channel_heap,
2322 GNUNET_TIME_absolute_get ().abs_value_us);
2328 * Allocate an IPv4 address from the range of the channel
2329 * for a new redirection.
2331 * @param v4 where to store the address
2332 * @return #GNUNET_OK on success,
2333 * #GNUNET_SYSERR on error
2336 allocate_v4_address (struct in_addr *v4)
2338 const char *ipv4addr = vpn_argv[4];
2339 const char *ipv4mask = vpn_argv[5];
2340 struct in_addr addr;
2341 struct in_addr mask;
2343 struct GNUNET_HashCode key;
2346 GNUNET_assert (1 == inet_pton (AF_INET, ipv4addr, &addr));
2347 GNUNET_assert (1 == inet_pton (AF_INET, ipv4mask, &mask));
2348 /* Given 192.168.0.1/255.255.0.0, we want a mask
2349 of '192.168.255.255', thus: */
2350 mask.s_addr = addr.s_addr | ~mask.s_addr;
2357 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
2358 _("Failed to find unallocated IPv4 address in VPN's range\n"));
2359 return GNUNET_SYSERR;
2361 /* Pick random IPv4 address within the subnet, except 'addr' or 'mask' itself */
2362 rnd.s_addr = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
2364 v4->s_addr = (addr.s_addr | rnd.s_addr) & mask.s_addr;
2365 get_destination_key_from_ip (AF_INET,
2369 while ( (GNUNET_YES ==
2370 GNUNET_CONTAINER_multihashmap_contains (destination_map,
2372 (v4->s_addr == addr.s_addr) ||
2373 (v4->s_addr == mask.s_addr) );
2379 * Allocate an IPv6 address from the range of the channel
2380 * for a new redirection.
2382 * @param v6 where to store the address
2383 * @return #GNUNET_OK on success,
2384 * #GNUNET_SYSERR on error
2387 allocate_v6_address (struct in6_addr *v6)
2389 const char *ipv6addr = vpn_argv[2];
2390 struct in6_addr addr;
2391 struct in6_addr mask;
2392 struct in6_addr rnd;
2394 struct GNUNET_HashCode key;
2397 GNUNET_assert (1 == inet_pton (AF_INET6, ipv6addr, &addr));
2398 GNUNET_assert (ipv6prefix < 128);
2399 /* Given ABCD::/96, we want a mask of 'ABCD::FFFF:FFFF,
2402 for (i=127;i>=ipv6prefix;i--)
2403 mask.s6_addr[i / 8] |= (1 << (i % 8));
2405 /* Pick random IPv6 address within the subnet, except 'addr' or 'mask' itself */
2412 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
2413 _("Failed to find unallocated IPv6 address in VPN's range\n"));
2414 return GNUNET_SYSERR;
2419 rnd.s6_addr[i] = (unsigned char) GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
2422 = (addr.s6_addr[i] | rnd.s6_addr[i]) & mask.s6_addr[i];
2424 get_destination_key_from_ip (AF_INET6,
2428 while ( (GNUNET_YES ==
2429 GNUNET_CONTAINER_multihashmap_contains (destination_map,
2433 sizeof (struct in6_addr))) ||
2436 sizeof (struct in6_addr))) );
2442 * Free resources occupied by a destination entry.
2444 * @param de entry to free
2447 free_destination_entry (struct DestinationEntry *de)
2449 struct DestinationChannel *dt;
2451 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2452 "Cleaning up destination entry\n");
2453 GNUNET_STATISTICS_update (stats,
2454 gettext_noop ("# Active destinations"),
2456 while (NULL != (dt = de->dt_head))
2458 GNUNET_CONTAINER_DLL_remove (de->dt_head,
2463 free_channel_state (dt->ts);
2464 GNUNET_assert (NULL == dt->ts);
2468 if (NULL != de->heap_node)
2470 GNUNET_CONTAINER_heap_remove_node (de->heap_node);
2471 de->heap_node = NULL;
2472 GNUNET_assert (GNUNET_YES ==
2473 GNUNET_CONTAINER_multihashmap_remove (destination_map,
2482 * We have too many active destinations. Clean up the oldest destination.
2484 * @param except destination that must NOT be cleaned up, even if it is the oldest
2487 expire_destination (struct DestinationEntry *except)
2489 struct DestinationEntry *de;
2491 de = GNUNET_CONTAINER_heap_peek (destination_heap);
2492 GNUNET_assert (NULL != de);
2494 return; /* can't do this */
2495 free_destination_entry (de);
2500 * Allocate an IP address for the response.
2502 * @param result_af desired address family; set to the actual
2503 * address family; can initially be AF_UNSPEC if there
2504 * is no preference; will be set to AF_UNSPEC if the
2506 * @param addr set to either v4 or v6 depending on which
2507 * storage location was used; set to NULL if allocation failed
2508 * @param v4 storage space for an IPv4 address
2509 * @param v6 storage space for an IPv6 address
2510 * @return #GNUNET_OK normally, #GNUNET_SYSERR if `* result_af` was
2511 * an unsupported address family (not AF_INET, AF_INET6 or AF_UNSPEC)
2514 allocate_response_ip (int *result_af,
2517 struct in6_addr *v6)
2524 allocate_v4_address (v4))
2525 *result_af = AF_UNSPEC;
2531 allocate_v6_address (v6))
2532 *result_af = AF_UNSPEC;
2538 allocate_v4_address (v4))
2541 *result_af = AF_INET;
2543 else if (GNUNET_OK ==
2544 allocate_v6_address (v6))
2547 *result_af = AF_INET6;
2552 return GNUNET_SYSERR;
2559 * A client asks us to setup a redirection via some exit node to a
2560 * particular IP. Setup the redirection and give the client the
2564 * @param client requesting client
2565 * @param message redirection request (a `struct RedirectToIpRequestMessage`)
2568 service_redirect_to_ip (void *cls,
2569 struct GNUNET_SERVER_Client *client,
2570 const struct GNUNET_MessageHeader *message)
2574 const struct RedirectToIpRequestMessage *msg;
2580 struct DestinationEntry *de;
2581 struct GNUNET_HashCode key;
2583 /* validate and parse request */
2584 mlen = ntohs (message->size);
2585 if (mlen < sizeof (struct RedirectToIpRequestMessage))
2588 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2591 alen = mlen - sizeof (struct RedirectToIpRequestMessage);
2592 msg = (const struct RedirectToIpRequestMessage *) message;
2593 addr_af = (int) htonl (msg->addr_af);
2597 if (alen != sizeof (struct in_addr))
2600 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2605 if (alen != sizeof (struct in6_addr))
2608 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2614 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2618 /* allocate response IP */
2619 result_af = (int) htonl (msg->result_af);
2620 if (GNUNET_OK != allocate_response_ip (&result_af,
2624 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2627 /* send reply with our IP address */
2628 send_client_reply (client,
2632 if (result_af == AF_UNSPEC)
2634 /* failure, we're done */
2635 GNUNET_SERVER_receive_done (client, GNUNET_OK);
2640 char sbuf[INET6_ADDRSTRLEN];
2641 char dbuf[INET6_ADDRSTRLEN];
2643 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2644 "Allocated address %s for redirection via exit to %s\n",
2645 inet_ntop (result_af, addr, sbuf, sizeof (sbuf)),
2647 &msg[1], dbuf, sizeof (dbuf)));
2650 /* setup destination record */
2651 de = GNUNET_new (struct DestinationEntry);
2652 de->is_service = GNUNET_NO;
2653 de->details.exit_destination.af = addr_af;
2654 memcpy (&de->details.exit_destination.ip,
2657 get_destination_key_from_ip (result_af,
2661 GNUNET_assert (GNUNET_OK ==
2662 GNUNET_CONTAINER_multihashmap_put (destination_map,
2665 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE));
2666 de->heap_node = GNUNET_CONTAINER_heap_insert (destination_heap,
2668 GNUNET_TIME_absolute_ntoh (msg->expiration_time).abs_value_us);
2669 GNUNET_STATISTICS_update (stats,
2670 gettext_noop ("# Active destinations"),
2672 while (GNUNET_CONTAINER_multihashmap_size (destination_map) > max_destination_mappings)
2673 expire_destination (de);
2674 GNUNET_SERVER_receive_done (client, GNUNET_OK);
2679 * A client asks us to setup a redirection to a particular peer
2680 * offering a service. Setup the redirection and give the client the
2684 * @param client requesting client
2685 * @param message redirection request (a `struct RedirectToPeerRequestMessage`)
2688 service_redirect_to_service (void *cls,
2689 struct GNUNET_SERVER_Client *client,
2690 const struct GNUNET_MessageHeader *message)
2692 const struct RedirectToServiceRequestMessage *msg;
2697 struct DestinationEntry *de;
2698 struct GNUNET_HashCode key;
2699 struct ChannelState *ts;
2700 struct DestinationChannel *dt;
2703 msg = (const struct RedirectToServiceRequestMessage *) message;
2705 /* allocate response IP */
2706 result_af = (int) htonl (msg->result_af);
2707 if (GNUNET_OK != allocate_response_ip (&result_af,
2711 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2714 send_client_reply (client,
2718 if (result_af == AF_UNSPEC)
2720 /* failure, we're done */
2721 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2722 _("Failed to allocate IP address for new destination\n"));
2723 GNUNET_SERVER_receive_done (client, GNUNET_OK);
2728 char sbuf[INET6_ADDRSTRLEN];
2730 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2731 "Allocated address %s for redirection to service %s on peer %s\n",
2732 inet_ntop (result_af, addr, sbuf, sizeof (sbuf)),
2733 GNUNET_h2s (&msg->service_descriptor),
2734 GNUNET_i2s (&msg->target));
2737 /* setup destination record */
2738 de = GNUNET_new (struct DestinationEntry);
2739 de->is_service = GNUNET_YES;
2740 de->details.service_destination.service_descriptor = msg->service_descriptor;
2741 de->details.service_destination.target = msg->target;
2742 get_destination_key_from_ip (result_af,
2746 GNUNET_assert (GNUNET_OK ==
2747 GNUNET_CONTAINER_multihashmap_put (destination_map,
2750 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE));
2751 de->heap_node = GNUNET_CONTAINER_heap_insert (destination_heap,
2753 GNUNET_TIME_absolute_ntoh (msg->expiration_time).abs_value_us);
2754 while (GNUNET_CONTAINER_multihashmap_size (destination_map) > max_destination_mappings)
2755 expire_destination (de);
2757 dt = GNUNET_new (struct DestinationChannel);
2758 dt->destination = de;
2759 GNUNET_CONTAINER_DLL_insert (de->dt_head,
2762 ts = create_channel_to_destination (dt,
2767 ts->destination_ip.v4 = v4;
2770 ts->destination_ip.v6 = v6;
2776 GNUNET_SERVER_receive_done (client, GNUNET_OK);
2781 * Function called whenever a channel is destroyed. Should clean up
2782 * any associated state.
2784 * @param cls closure (set from #GNUNET_CADET_connect)
2785 * @param channel connection to the other end (henceforth invalid)
2786 * @param channel_ctx place where local state associated
2787 * with the channel is stored (our `struct ChannelState`)
2790 channel_cleaner (void *cls,
2791 const struct GNUNET_CADET_Channel *channel,
2794 struct ChannelState *ts = channel_ctx;
2796 ts->channel = NULL; /* we must not call GNUNET_CADET_channel_destroy() anymore */
2797 free_channel_state (ts);
2802 * Free memory occupied by an entry in the destination map.
2806 * @param value a `struct DestinationEntry *`
2807 * @return #GNUNET_OK (continue to iterate)
2810 cleanup_destination (void *cls,
2811 const struct GNUNET_HashCode *key,
2814 struct DestinationEntry *de = value;
2816 free_destination_entry (de);
2822 * Free memory occupied by an entry in the channel map.
2826 * @param value a `struct ChannelState *`
2827 * @return #GNUNET_OK (continue to iterate)
2830 cleanup_channel (void *cls,
2831 const struct GNUNET_HashCode *key,
2834 struct ChannelState *ts = value;
2836 free_channel_state (ts);
2842 * Function scheduled as very last function, cleans up after us
2849 const struct GNUNET_SCHEDULER_TaskContext *tc)
2853 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2854 "VPN is shutting down\n");
2855 if (NULL != destination_map)
2857 GNUNET_CONTAINER_multihashmap_iterate (destination_map,
2858 &cleanup_destination,
2860 GNUNET_CONTAINER_multihashmap_destroy (destination_map);
2861 destination_map = NULL;
2863 if (NULL != destination_heap)
2865 GNUNET_CONTAINER_heap_destroy (destination_heap);
2866 destination_heap = NULL;
2868 if (NULL != channel_map)
2870 GNUNET_CONTAINER_multihashmap_iterate (channel_map,
2873 GNUNET_CONTAINER_multihashmap_destroy (channel_map);
2876 if (NULL != channel_heap)
2878 GNUNET_CONTAINER_heap_destroy (channel_heap);
2879 channel_heap = NULL;
2881 if (NULL != cadet_handle)
2883 GNUNET_CADET_disconnect (cadet_handle);
2884 cadet_handle = NULL;
2886 if (NULL != helper_handle)
2888 GNUNET_HELPER_stop (helper_handle, GNUNET_NO);
2889 helper_handle = NULL;
2893 GNUNET_SERVER_notification_context_destroy (nc);
2898 GNUNET_STATISTICS_destroy (stats, GNUNET_NO);
2902 GNUNET_free_non_null (vpn_argv[i]);
2907 * Main function that will be run by the scheduler.
2909 * @param cls closure
2910 * @param server the initialized server
2911 * @param cfg_ configuration
2915 struct GNUNET_SERVER_Handle *server,
2916 const struct GNUNET_CONFIGURATION_Handle *cfg_)
2918 static const struct GNUNET_SERVER_MessageHandler service_handlers[] = {
2919 /* callback, cls, type, size */
2920 { &service_redirect_to_ip, NULL, GNUNET_MESSAGE_TYPE_VPN_CLIENT_REDIRECT_TO_IP, 0},
2921 { &service_redirect_to_service, NULL,
2922 GNUNET_MESSAGE_TYPE_VPN_CLIENT_REDIRECT_TO_SERVICE,
2923 sizeof (struct RedirectToServiceRequestMessage) },
2926 static const struct GNUNET_CADET_MessageHandler cadet_handlers[] = {
2927 { &receive_udp_back, GNUNET_MESSAGE_TYPE_VPN_UDP_REPLY, 0},
2928 { &receive_tcp_back, GNUNET_MESSAGE_TYPE_VPN_TCP_DATA_TO_VPN, 0},
2929 { &receive_icmp_back, GNUNET_MESSAGE_TYPE_VPN_ICMP_TO_VPN, 0},
2941 binary = GNUNET_OS_get_libexec_binary_path ("gnunet-helper-vpn");
2944 GNUNET_OS_check_helper_binary (binary,
2946 "-d gnunet-vpn - - 169.1.3.3.7 255.255.255.0")) //ipv4 only please!
2948 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2949 "`%s' is not SUID, refusing to run.\n",
2950 "gnunet-helper-vpn");
2951 GNUNET_free (binary);
2953 /* we won't "really" exit here, as the 'service' is still running;
2954 however, as no handlers are registered, the service won't do
2958 GNUNET_free (binary);
2960 stats = GNUNET_STATISTICS_create ("vpn", cfg);
2962 GNUNET_CONFIGURATION_get_value_number (cfg, "VPN", "MAX_MAPPING",
2963 &max_destination_mappings))
2964 max_destination_mappings = 200;
2966 GNUNET_CONFIGURATION_get_value_number (cfg, "VPN", "MAX_TUNNELS",
2967 &max_channel_mappings))
2968 max_channel_mappings = 200;
2970 destination_map = GNUNET_CONTAINER_multihashmap_create (max_destination_mappings * 2, GNUNET_NO);
2971 destination_heap = GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN);
2972 channel_map = GNUNET_CONTAINER_multihashmap_create (max_channel_mappings * 2, GNUNET_NO);
2973 channel_heap = GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN);
2976 vpn_argv[0] = GNUNET_strdup ("vpn-gnunet");
2977 if (GNUNET_SYSERR ==
2978 GNUNET_CONFIGURATION_get_value_string (cfg, "VPN", "IFNAME", &ifname))
2980 GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, "VPN", "IFNAME");
2981 GNUNET_SCHEDULER_shutdown ();
2984 vpn_argv[1] = ifname;
2986 if (GNUNET_OK == GNUNET_NETWORK_test_pf (PF_INET6))
2988 if ( (GNUNET_SYSERR ==
2989 GNUNET_CONFIGURATION_get_value_string (cfg, "VPN", "IPV6ADDR",
2991 (1 != inet_pton (AF_INET6, ipv6addr, &v6))) )
2993 GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, "VPN", "IPV6ADDR",
2994 _("Must specify valid IPv6 address"));
2995 GNUNET_SCHEDULER_shutdown ();
2996 GNUNET_free_non_null (ipv6addr);
2999 vpn_argv[2] = ipv6addr;
3000 ipv6prefix_s = NULL;
3001 if (GNUNET_SYSERR ==
3002 GNUNET_CONFIGURATION_get_value_string (cfg, "VPN", "IPV6PREFIX",
3005 GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, "VPN", "IPV6PREFIX");
3006 GNUNET_SCHEDULER_shutdown ();
3007 GNUNET_free_non_null (ipv6prefix_s);
3010 vpn_argv[3] = ipv6prefix_s;
3012 GNUNET_CONFIGURATION_get_value_number (cfg, "VPN",
3015 (ipv6prefix >= 127) )
3017 GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, "VPN", "IPV4MASK",
3018 _("Must specify valid IPv6 mask"));
3019 GNUNET_SCHEDULER_shutdown ();
3025 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
3026 _("IPv6 support disabled as this system does not support IPv6\n"));
3027 vpn_argv[2] = GNUNET_strdup ("-");
3028 vpn_argv[3] = GNUNET_strdup ("-");
3030 if (GNUNET_OK == GNUNET_NETWORK_test_pf (PF_INET))
3033 if ( (GNUNET_SYSERR ==
3034 GNUNET_CONFIGURATION_get_value_string (cfg, "vpn", "IPV4ADDR",
3036 (1 != inet_pton (AF_INET, ipv4addr, &v4))) )
3038 GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, "VPN", "IPV4ADDR",
3039 _("Must specify valid IPv4 address"));
3040 GNUNET_SCHEDULER_shutdown ();
3041 GNUNET_free_non_null (ipv4addr);
3044 vpn_argv[4] = ipv4addr;
3046 if ( (GNUNET_SYSERR ==
3047 GNUNET_CONFIGURATION_get_value_string (cfg, "vpn", "IPV4MASK",
3049 (1 != inet_pton (AF_INET, ipv4mask, &v4))) )
3051 GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, "VPN", "IPV4MASK",
3052 _("Must specify valid IPv4 mask"));
3053 GNUNET_SCHEDULER_shutdown ();
3054 GNUNET_free_non_null (ipv4mask);
3057 vpn_argv[5] = ipv4mask;
3061 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
3062 _("IPv4 support disabled as this system does not support IPv4\n"));
3063 vpn_argv[4] = GNUNET_strdup ("-");
3064 vpn_argv[5] = GNUNET_strdup ("-");
3069 GNUNET_CADET_connect (cfg_, NULL,
3074 helper_handle = GNUNET_HELPER_start (GNUNET_NO,
3075 "gnunet-helper-vpn", vpn_argv,
3076 &message_token, NULL, NULL);
3077 nc = GNUNET_SERVER_notification_context_create (server, 1);
3078 GNUNET_SERVER_add_handlers (server, service_handlers);
3079 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &cleanup, cls);
3084 * The main function of the VPN service.
3086 * @param argc number of arguments from the command line
3087 * @param argv command line arguments
3088 * @return 0 ok, 1 on error
3091 main (int argc, char *const *argv)
3093 return (GNUNET_OK ==
3094 GNUNET_SERVICE_run (argc, argv, "vpn",
3095 GNUNET_SERVICE_OPTION_NONE,
3096 &run, NULL)) ? global_ret : 1;
3099 /* end of gnunet-service-vpn.c */