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 * Output destination of a channel for diagnostics.
698 * @param de destination to process
699 * @return diagnostic string describing destination
702 print_channel_destination (const struct DestinationEntry *de)
704 static char dest[256];
708 GNUNET_snprintf (dest,
711 GNUNET_i2s (&de->details.service_destination.target),
712 GNUNET_h2s (&de->details.service_destination.service_descriptor));
716 inet_ntop (de->details.exit_destination.af,
717 &de->details.exit_destination.ip,
726 * Regex has found a potential exit peer for us; consider using it.
728 * @param cls the `struct ChannelState`
729 * @param id Peer providing a regex that matches the string.
730 * @param get_path Path of the get request.
731 * @param get_path_length Lenght of @a get_path.
732 * @param put_path Path of the put request.
733 * @param put_path_length Length of the @a put_path.
736 handle_regex_result (void *cls,
737 const struct GNUNET_PeerIdentity *id,
738 const struct GNUNET_PeerIdentity *get_path,
739 unsigned int get_path_length,
740 const struct GNUNET_PeerIdentity *put_path,
741 unsigned int put_path_length)
743 struct ChannelState *ts = cls;
744 unsigned int apptype;
746 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
747 "Exit %s found for destination %s!\n",
749 print_channel_destination (&ts->destination));
750 GNUNET_REGEX_search_cancel (ts->search);
755 apptype = GNUNET_APPLICATION_TYPE_IPV4_GATEWAY;
758 apptype = GNUNET_APPLICATION_TYPE_IPV6_GATEWAY;
764 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
765 "Creating tunnel to %s for destination %s!\n",
767 print_channel_destination (&ts->destination));
768 ts->channel = GNUNET_CADET_channel_create (cadet_handle,
772 GNUNET_CADET_OPTION_DEFAULT);
777 * Initialize the given destination entry's cadet channel.
779 * @param dt destination channel for which we need to setup a channel
780 * @param client_af address family of the address returned to the client
781 * @return channel state of the channel that was created
783 static struct ChannelState *
784 create_channel_to_destination (struct DestinationChannel *dt,
787 struct ChannelState *ts;
788 unsigned int apptype;
790 GNUNET_STATISTICS_update (stats,
791 gettext_noop ("# Cadet channels created"),
793 GNUNET_assert (NULL == dt->ts);
797 apptype = GNUNET_APPLICATION_TYPE_IPV4_GATEWAY;
800 apptype = GNUNET_APPLICATION_TYPE_IPV6_GATEWAY;
806 ts = GNUNET_new (struct ChannelState);
808 ts->destination = *dt->destination;
809 ts->destination.heap_node = NULL; /* copy is NOT in destination heap */
811 ts->destination_container = dt; /* we are referenced from dt */
812 if (dt->destination->is_service)
814 ts->channel = GNUNET_CADET_channel_create (cadet_handle,
816 &dt->destination->details.service_destination.target,
818 GNUNET_CADET_OPTION_DEFAULT);
819 if (NULL == ts->channel)
821 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
822 _("Failed to setup cadet channel!\n"));
826 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
827 "Creating channel to peer %s offering service %s\n",
828 GNUNET_i2s (&dt->destination->details.service_destination.target),
829 GNUNET_h2s (&dt->destination->details.service_destination.service_descriptor));
835 switch (dt->destination->details.exit_destination.af)
839 char address[GNUNET_TUN_IPV4_REGEXLEN];
841 GNUNET_TUN_ipv4toregexsearch (&dt->destination->details.exit_destination.ip.v4,
842 dt->destination_port,
844 GNUNET_asprintf (&policy,
846 GNUNET_APPLICATION_TYPE_EXIT_REGEX_PREFIX,
852 char address[GNUNET_TUN_IPV6_REGEXLEN];
854 GNUNET_TUN_ipv6toregexsearch (&dt->destination->details.exit_destination.ip.v6,
855 dt->destination_port,
857 GNUNET_asprintf (&policy,
859 GNUNET_APPLICATION_TYPE_EXIT_REGEX_PREFIX,
868 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
869 "Requesting connect by string: %s\n",
871 ts->search = GNUNET_REGEX_search (cfg,
873 &handle_regex_result,
875 GNUNET_free (policy);
882 * We have too many active channels. Clean up the oldest channel.
884 * @param except channel that must NOT be cleaned up, even if it is the oldest
887 expire_channel (struct ChannelState *except)
889 struct ChannelState *ts;
891 ts = GNUNET_CONTAINER_heap_peek (channel_heap);
892 GNUNET_assert (NULL != ts);
894 return; /* can't do this */
895 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
896 "Tearing down expired channel to %s\n",
897 print_channel_destination (&except->destination));
898 free_channel_state (ts);
903 * Route a packet via cadet to the given destination.
905 * @param destination description of the destination
906 * @param af address family on this end (AF_INET or AF_INET6)
907 * @param protocol IPPROTO_TCP or IPPROTO_UDP or IPPROTO_ICMP or IPPROTO_ICMPV6
908 * @param source_ip source IP used by the sender (struct in_addr or struct in6_addr)
909 * @param destination_ip destination IP used by the sender (struct in_addr or struct in6_addr)
910 * @param payload payload of the packet after the IP header
911 * @param payload_length number of bytes in @a payload
914 route_packet (struct DestinationEntry *destination,
917 const void *source_ip,
918 const void *destination_ip,
920 size_t payload_length)
922 struct GNUNET_HashCode key;
923 struct ChannelState *ts;
924 struct ChannelMessageQueueEntry *tnq;
928 const struct GNUNET_TUN_UdpHeader *udp;
929 const struct GNUNET_TUN_TcpHeader *tcp;
930 const struct GNUNET_TUN_IcmpHeader *icmp;
931 struct DestinationChannel *dt;
932 uint16_t source_port;
933 uint16_t destination_port;
939 if (payload_length < sizeof (struct GNUNET_TUN_UdpHeader))
945 tcp = NULL; /* make compiler happy */
946 icmp = NULL; /* make compiler happy */
948 if (udp->len < sizeof (struct GNUNET_TUN_UdpHeader))
953 source_port = ntohs (udp->source_port);
954 destination_port = ntohs (udp->destination_port);
955 get_channel_key_from_ips (af,
966 if (payload_length < sizeof (struct GNUNET_TUN_TcpHeader))
972 udp = NULL; /* make compiler happy */
973 icmp = NULL; /* make compiler happy */
975 if (tcp->off * 4 < sizeof (struct GNUNET_TUN_TcpHeader))
980 source_port = ntohs (tcp->source_port);
981 destination_port = ntohs (tcp->destination_port);
982 get_channel_key_from_ips (af,
994 if ( (AF_INET == af) ^ (protocol == IPPROTO_ICMP) )
999 if (payload_length < sizeof (struct GNUNET_TUN_IcmpHeader))
1005 tcp = NULL; /* make compiler happy */
1006 udp = NULL; /* make compiler happy */
1009 destination_port = 0;
1010 get_channel_key_from_ips (af,
1020 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1021 _("Protocol %u not supported, dropping\n"),
1022 (unsigned int) protocol);
1026 if (! destination->is_service)
1028 switch (destination->details.exit_destination.af)
1031 alen = sizeof (struct in_addr);
1034 alen = sizeof (struct in6_addr);
1041 char sbuf[INET6_ADDRSTRLEN];
1042 char dbuf[INET6_ADDRSTRLEN];
1043 char xbuf[INET6_ADDRSTRLEN];
1045 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1046 "Routing %s packet from %s:%u -> %s:%u to destination %s:%u\n",
1047 (protocol == IPPROTO_TCP) ? "TCP" : "UDP",
1048 inet_ntop (af, source_ip, sbuf, sizeof (sbuf)),
1050 inet_ntop (af, destination_ip, dbuf, sizeof (dbuf)),
1052 inet_ntop (destination->details.exit_destination.af,
1053 &destination->details.exit_destination.ip,
1054 xbuf, sizeof (xbuf)),
1057 for (dt = destination->dt_head; NULL != dt; dt = dt->next)
1058 if (dt->destination_port == destination_port)
1064 char sbuf[INET6_ADDRSTRLEN];
1065 char dbuf[INET6_ADDRSTRLEN];
1067 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1068 "Routing %s packet from %s:%u -> %s:%u to service %s at peer %s\n",
1069 (protocol == IPPROTO_TCP) ? "TCP" : "UDP",
1070 inet_ntop (af, source_ip, sbuf, sizeof (sbuf)),
1072 inet_ntop (af, destination_ip, dbuf, sizeof (dbuf)),
1074 GNUNET_h2s (&destination->details.service_destination.service_descriptor),
1075 GNUNET_i2s (&destination->details.service_destination.target));
1077 dt = destination->dt_head;
1081 dt = GNUNET_new (struct DestinationChannel);
1082 dt->destination = destination;
1083 GNUNET_CONTAINER_DLL_insert (destination->dt_head,
1084 destination->dt_tail,
1086 dt->destination_port = destination_port;
1089 /* see if we have an existing channel for this destination */
1090 ts = GNUNET_CONTAINER_multihashmap_get (channel_map,
1094 /* need to either use the existing channel from the destination (if still
1095 available) or create a fresh one */
1096 is_new = GNUNET_YES;
1098 ts = create_channel_to_destination (dt, af);
1104 ts->destination_container = NULL; /* no longer 'contained' */
1105 /* now bind existing "unbound" channel to our IP/port tuple */
1106 ts->protocol = protocol;
1110 ts->source_ip.v4 = * (const struct in_addr *) source_ip;
1111 ts->destination_ip.v4 = * (const struct in_addr *) destination_ip;
1115 ts->source_ip.v6 = * (const struct in6_addr *) source_ip;
1116 ts->destination_ip.v6 = * (const struct in6_addr *) destination_ip;
1118 ts->source_port = source_port;
1119 ts->destination_port = destination_port;
1120 ts->heap_node = GNUNET_CONTAINER_heap_insert (channel_heap,
1122 GNUNET_TIME_absolute_get ().abs_value_us);
1123 GNUNET_assert (GNUNET_YES ==
1124 GNUNET_CONTAINER_multihashmap_put (channel_map,
1127 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
1128 GNUNET_STATISTICS_update (stats,
1129 gettext_noop ("# Active channels"),
1131 while (GNUNET_CONTAINER_multihashmap_size (channel_map) > max_channel_mappings)
1132 expire_channel (ts);
1137 GNUNET_CONTAINER_heap_update_cost (channel_heap,
1139 GNUNET_TIME_absolute_get ().abs_value_us);
1141 if (NULL == ts->channel)
1143 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1144 "Packet dropped, channel to %s not yet ready (%s)\n",
1145 print_channel_destination (&ts->destination),
1146 (NULL == ts->search)
1147 ? "EXIT search failed"
1148 : "EXIT search active");
1149 GNUNET_STATISTICS_update (stats,
1150 gettext_noop ("# Packets dropped (channel not yet online)"),
1156 /* send via channel */
1160 if (destination->is_service)
1162 struct GNUNET_EXIT_UdpServiceMessage *usm;
1164 mlen = sizeof (struct GNUNET_EXIT_UdpServiceMessage) +
1165 payload_length - sizeof (struct GNUNET_TUN_UdpHeader);
1166 if (mlen >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1171 tnq = GNUNET_malloc (sizeof (struct ChannelMessageQueueEntry) + mlen);
1174 usm = (struct GNUNET_EXIT_UdpServiceMessage *) &tnq[1];
1175 usm->header.size = htons ((uint16_t) mlen);
1176 usm->header.type = htons (GNUNET_MESSAGE_TYPE_VPN_UDP_TO_SERVICE);
1177 /* if the source port is below 32000, we assume it has a special
1178 meaning; if not, we pick a random port (this is a heuristic) */
1179 usm->source_port = (ntohs (udp->source_port) < 32000) ? udp->source_port : 0;
1180 usm->destination_port = udp->destination_port;
1181 usm->service_descriptor = destination->details.service_destination.service_descriptor;
1184 payload_length - sizeof (struct GNUNET_TUN_UdpHeader));
1188 struct GNUNET_EXIT_UdpInternetMessage *uim;
1189 struct in_addr *ip4dst;
1190 struct in6_addr *ip6dst;
1193 mlen = sizeof (struct GNUNET_EXIT_UdpInternetMessage) +
1194 alen + payload_length - sizeof (struct GNUNET_TUN_UdpHeader);
1195 if (mlen >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1200 tnq = GNUNET_malloc (sizeof (struct ChannelMessageQueueEntry) + mlen);
1203 uim = (struct GNUNET_EXIT_UdpInternetMessage *) &tnq[1];
1204 uim->header.size = htons ((uint16_t) mlen);
1205 uim->header.type = htons (GNUNET_MESSAGE_TYPE_VPN_UDP_TO_INTERNET);
1206 uim->af = htonl (destination->details.exit_destination.af);
1207 uim->source_port = (ntohs (udp->source_port) < 32000) ? udp->source_port : 0;
1208 uim->destination_port = udp->destination_port;
1209 switch (destination->details.exit_destination.af)
1212 ip4dst = (struct in_addr *) &uim[1];
1213 *ip4dst = destination->details.exit_destination.ip.v4;
1214 payload = &ip4dst[1];
1217 ip6dst = (struct in6_addr *) &uim[1];
1218 *ip6dst = destination->details.exit_destination.ip.v6;
1219 payload = &ip6dst[1];
1226 payload_length - sizeof (struct GNUNET_TUN_UdpHeader));
1232 if (destination->is_service)
1234 struct GNUNET_EXIT_TcpServiceStartMessage *tsm;
1236 mlen = sizeof (struct GNUNET_EXIT_TcpServiceStartMessage) +
1237 payload_length - sizeof (struct GNUNET_TUN_TcpHeader);
1238 if (mlen >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1243 tnq = GNUNET_malloc (sizeof (struct ChannelMessageQueueEntry) + mlen);
1246 tsm = (struct GNUNET_EXIT_TcpServiceStartMessage *) &tnq[1];
1247 tsm->header.size = htons ((uint16_t) mlen);
1248 tsm->header.type = htons (GNUNET_MESSAGE_TYPE_VPN_TCP_TO_SERVICE_START);
1249 tsm->reserved = htonl (0);
1250 tsm->service_descriptor = destination->details.service_destination.service_descriptor;
1251 tsm->tcp_header = *tcp;
1254 payload_length - sizeof (struct GNUNET_TUN_TcpHeader));
1258 struct GNUNET_EXIT_TcpInternetStartMessage *tim;
1259 struct in_addr *ip4dst;
1260 struct in6_addr *ip6dst;
1263 mlen = sizeof (struct GNUNET_EXIT_TcpInternetStartMessage) +
1264 alen + payload_length - sizeof (struct GNUNET_TUN_TcpHeader);
1265 if (mlen >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1270 tnq = GNUNET_malloc (sizeof (struct ChannelMessageQueueEntry) + mlen);
1273 tim = (struct GNUNET_EXIT_TcpInternetStartMessage *) &tnq[1];
1274 tim->header.size = htons ((uint16_t) mlen);
1275 tim->header.type = htons (GNUNET_MESSAGE_TYPE_VPN_TCP_TO_INTERNET_START);
1276 tim->af = htonl (destination->details.exit_destination.af);
1277 tim->tcp_header = *tcp;
1278 switch (destination->details.exit_destination.af)
1281 ip4dst = (struct in_addr *) &tim[1];
1282 *ip4dst = destination->details.exit_destination.ip.v4;
1283 payload = &ip4dst[1];
1286 ip6dst = (struct in6_addr *) &tim[1];
1287 *ip6dst = destination->details.exit_destination.ip.v6;
1288 payload = &ip6dst[1];
1295 payload_length - sizeof (struct GNUNET_TUN_TcpHeader));
1300 struct GNUNET_EXIT_TcpDataMessage *tdm;
1302 mlen = sizeof (struct GNUNET_EXIT_TcpDataMessage) +
1303 payload_length - sizeof (struct GNUNET_TUN_TcpHeader);
1304 if (mlen >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1309 tnq = GNUNET_malloc (sizeof (struct ChannelMessageQueueEntry) + mlen);
1312 tdm = (struct GNUNET_EXIT_TcpDataMessage *) &tnq[1];
1313 tdm->header.size = htons ((uint16_t) mlen);
1314 tdm->header.type = htons (GNUNET_MESSAGE_TYPE_VPN_TCP_DATA_TO_EXIT);
1315 tdm->reserved = htonl (0);
1316 tdm->tcp_header = *tcp;
1319 payload_length - sizeof (struct GNUNET_TUN_TcpHeader));
1323 case IPPROTO_ICMPV6:
1324 if (destination->is_service)
1326 struct GNUNET_EXIT_IcmpServiceMessage *ism;
1328 mlen = sizeof (struct GNUNET_EXIT_IcmpServiceMessage) +
1329 payload_length - sizeof (struct GNUNET_TUN_IcmpHeader);
1330 if (mlen >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1335 tnq = GNUNET_malloc (sizeof (struct ChannelMessageQueueEntry) + mlen);
1337 ism = (struct GNUNET_EXIT_IcmpServiceMessage *) &tnq[1];
1338 ism->header.type = htons (GNUNET_MESSAGE_TYPE_VPN_ICMP_TO_SERVICE);
1339 ism->af = htonl (af); /* need to tell destination ICMP protocol family! */
1340 ism->service_descriptor = destination->details.service_destination.service_descriptor;
1341 ism->icmp_header = *icmp;
1342 /* ICMP protocol translation will be done by the receiver (as we don't know
1343 the target AF); however, we still need to possibly discard the payload
1344 depending on the ICMP type */
1350 case GNUNET_TUN_ICMPTYPE_ECHO_REPLY:
1351 case GNUNET_TUN_ICMPTYPE_ECHO_REQUEST:
1353 case GNUNET_TUN_ICMPTYPE_DESTINATION_UNREACHABLE:
1354 case GNUNET_TUN_ICMPTYPE_SOURCE_QUENCH:
1355 case GNUNET_TUN_ICMPTYPE_TIME_EXCEEDED:
1356 /* throw away ICMP payload, won't be useful for the other side anyway */
1357 payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
1360 GNUNET_STATISTICS_update (stats,
1361 gettext_noop ("# ICMPv4 packets dropped (not allowed)"),
1365 /* end of AF_INET */
1370 case GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE:
1371 case GNUNET_TUN_ICMPTYPE6_PACKET_TOO_BIG:
1372 case GNUNET_TUN_ICMPTYPE6_TIME_EXCEEDED:
1373 case GNUNET_TUN_ICMPTYPE6_PARAMETER_PROBLEM:
1374 /* throw away ICMP payload, won't be useful for the other side anyway */
1375 payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
1377 case GNUNET_TUN_ICMPTYPE6_ECHO_REQUEST:
1378 case GNUNET_TUN_ICMPTYPE6_ECHO_REPLY:
1381 GNUNET_STATISTICS_update (stats,
1382 gettext_noop ("# ICMPv6 packets dropped (not allowed)"),
1386 /* end of AF_INET6 */
1393 /* update length calculations, as payload_length may have changed */
1394 mlen = sizeof (struct GNUNET_EXIT_IcmpServiceMessage) +
1395 alen + payload_length - sizeof (struct GNUNET_TUN_IcmpHeader);
1397 ism->header.size = htons ((uint16_t) mlen);
1398 /* finally, copy payload (if there is any left...) */
1401 payload_length - sizeof (struct GNUNET_TUN_IcmpHeader));
1405 struct GNUNET_EXIT_IcmpInternetMessage *iim;
1406 struct in_addr *ip4dst;
1407 struct in6_addr *ip6dst;
1410 mlen = sizeof (struct GNUNET_EXIT_IcmpInternetMessage) +
1411 alen + payload_length - sizeof (struct GNUNET_TUN_IcmpHeader);
1412 if (mlen >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1417 tnq = GNUNET_malloc (sizeof (struct ChannelMessageQueueEntry) + mlen);
1419 iim = (struct GNUNET_EXIT_IcmpInternetMessage *) &tnq[1];
1420 iim->header.type = htons (GNUNET_MESSAGE_TYPE_VPN_ICMP_TO_INTERNET);
1421 iim->icmp_header = *icmp;
1422 /* Perform ICMP protocol-translation (depending on destination AF and source AF)
1423 and throw away ICMP payload depending on ICMP message type */
1429 case GNUNET_TUN_ICMPTYPE_ECHO_REPLY:
1430 if (destination->details.exit_destination.af == AF_INET6)
1431 iim->icmp_header.type = GNUNET_TUN_ICMPTYPE6_ECHO_REPLY;
1433 case GNUNET_TUN_ICMPTYPE_ECHO_REQUEST:
1434 if (destination->details.exit_destination.af == AF_INET6)
1435 iim->icmp_header.type = GNUNET_TUN_ICMPTYPE6_ECHO_REQUEST;
1437 case GNUNET_TUN_ICMPTYPE_DESTINATION_UNREACHABLE:
1438 if (destination->details.exit_destination.af == AF_INET6)
1439 iim->icmp_header.type = GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE;
1440 /* throw away IP-payload, exit will have to make it up anyway */
1441 payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
1443 case GNUNET_TUN_ICMPTYPE_TIME_EXCEEDED:
1444 if (destination->details.exit_destination.af == AF_INET6)
1445 iim->icmp_header.type = GNUNET_TUN_ICMPTYPE6_TIME_EXCEEDED;
1446 /* throw away IP-payload, exit will have to make it up anyway */
1447 payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
1449 case GNUNET_TUN_ICMPTYPE_SOURCE_QUENCH:
1450 if (destination->details.exit_destination.af == AF_INET6)
1452 GNUNET_STATISTICS_update (stats,
1453 gettext_noop ("# ICMPv4 packets dropped (impossible PT to v6)"),
1458 /* throw away IP-payload, exit will have to make it up anyway */
1459 payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
1462 GNUNET_STATISTICS_update (stats,
1463 gettext_noop ("# ICMPv4 packets dropped (type not allowed)"),
1468 /* end of AF_INET */
1473 case GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE:
1474 if (destination->details.exit_destination.af == AF_INET6)
1475 iim->icmp_header.type = GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE;
1476 /* throw away IP-payload, exit will have to make it up anyway */
1477 payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
1479 case GNUNET_TUN_ICMPTYPE6_TIME_EXCEEDED:
1480 if (destination->details.exit_destination.af == AF_INET)
1481 iim->icmp_header.type = GNUNET_TUN_ICMPTYPE_TIME_EXCEEDED;
1482 /* throw away IP-payload, exit will have to make it up anyway */
1483 payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
1485 case GNUNET_TUN_ICMPTYPE6_PACKET_TOO_BIG:
1486 if (destination->details.exit_destination.af == AF_INET)
1488 GNUNET_STATISTICS_update (stats,
1489 gettext_noop ("# ICMPv6 packets dropped (impossible PT to v4)"),
1494 /* throw away IP-payload, exit will have to make it up anyway */
1495 payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
1497 case GNUNET_TUN_ICMPTYPE6_PARAMETER_PROBLEM:
1498 if (destination->details.exit_destination.af == AF_INET)
1500 GNUNET_STATISTICS_update (stats,
1501 gettext_noop ("# ICMPv6 packets dropped (impossible PT to v4)"),
1506 /* throw away IP-payload, exit will have to make it up anyway */
1507 payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
1509 case GNUNET_TUN_ICMPTYPE6_ECHO_REQUEST:
1510 if (destination->details.exit_destination.af == AF_INET)
1511 iim->icmp_header.type = GNUNET_TUN_ICMPTYPE_ECHO_REQUEST;
1513 case GNUNET_TUN_ICMPTYPE6_ECHO_REPLY:
1514 if (destination->details.exit_destination.af == AF_INET)
1515 iim->icmp_header.type = GNUNET_TUN_ICMPTYPE_ECHO_REPLY;
1518 GNUNET_STATISTICS_update (stats,
1519 gettext_noop ("# ICMPv6 packets dropped (type not allowed)"),
1524 /* end of AF_INET6 */
1529 /* update length calculations, as payload_length may have changed */
1530 mlen = sizeof (struct GNUNET_EXIT_IcmpInternetMessage) +
1531 alen + payload_length - sizeof (struct GNUNET_TUN_IcmpHeader);
1533 iim->header.size = htons ((uint16_t) mlen);
1535 /* need to tell destination ICMP protocol family! */
1536 iim->af = htonl (destination->details.exit_destination.af);
1537 switch (destination->details.exit_destination.af)
1540 ip4dst = (struct in_addr *) &iim[1];
1541 *ip4dst = destination->details.exit_destination.ip.v4;
1542 payload = &ip4dst[1];
1545 ip6dst = (struct in6_addr *) &iim[1];
1546 *ip6dst = destination->details.exit_destination.ip.v6;
1547 payload = &ip6dst[1];
1554 payload_length - sizeof (struct GNUNET_TUN_IcmpHeader));
1558 /* not supported above, how can we get here !? */
1562 send_to_channel (tnq, ts);
1567 * Receive packets from the helper-process (someone send to the local
1568 * virtual channel interface). Find the destination mapping, and if it
1569 * exists, identify the correct CADET channel (or possibly create it)
1570 * and forward the packet.
1572 * @param cls closure, NULL
1573 * @param client NULL
1574 * @param message message we got from the client (VPN channel interface)
1577 message_token (void *cls,
1579 const struct GNUNET_MessageHeader *message)
1581 const struct GNUNET_TUN_Layer2PacketHeader *tun;
1583 struct GNUNET_HashCode key;
1584 struct DestinationEntry *de;
1586 GNUNET_STATISTICS_update (stats,
1587 gettext_noop ("# Packets received from TUN interface"),
1589 mlen = ntohs (message->size);
1590 if ( (ntohs (message->type) != GNUNET_MESSAGE_TYPE_VPN_HELPER) ||
1591 (mlen < sizeof (struct GNUNET_MessageHeader) + sizeof (struct GNUNET_TUN_Layer2PacketHeader)) )
1596 tun = (const struct GNUNET_TUN_Layer2PacketHeader *) &message[1];
1597 mlen -= (sizeof (struct GNUNET_MessageHeader) + sizeof (struct GNUNET_TUN_Layer2PacketHeader));
1598 switch (ntohs (tun->proto))
1602 const struct GNUNET_TUN_IPv6Header *pkt6;
1604 if (mlen < sizeof (struct GNUNET_TUN_IPv6Header))
1610 pkt6 = (const struct GNUNET_TUN_IPv6Header *) &tun[1];
1611 get_destination_key_from_ip (AF_INET6,
1612 &pkt6->destination_address,
1614 de = GNUNET_CONTAINER_multihashmap_get (destination_map, &key);
1617 char buf[INET6_ADDRSTRLEN];
1619 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1620 _("Packet received for unmapped destination `%s' (dropping it)\n"),
1621 inet_ntop (AF_INET6,
1622 &pkt6->destination_address,
1630 &pkt6->source_address,
1631 &pkt6->destination_address,
1633 mlen - sizeof (struct GNUNET_TUN_IPv6Header));
1638 struct GNUNET_TUN_IPv4Header *pkt4;
1640 if (mlen < sizeof (struct GNUNET_TUN_IPv4Header))
1646 pkt4 = (struct GNUNET_TUN_IPv4Header *) &tun[1];
1647 get_destination_key_from_ip (AF_INET,
1648 &pkt4->destination_address,
1650 de = GNUNET_CONTAINER_multihashmap_get (destination_map, &key);
1653 char buf[INET_ADDRSTRLEN];
1655 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1656 _("Packet received for unmapped destination `%s' (dropping it)\n"),
1658 &pkt4->destination_address,
1663 if (pkt4->header_length * 4 != sizeof (struct GNUNET_TUN_IPv4Header))
1665 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1666 _("Received IPv4 packet with options (dropping it)\n"));
1672 &pkt4->source_address,
1673 &pkt4->destination_address,
1675 mlen - sizeof (struct GNUNET_TUN_IPv4Header));
1679 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1680 _("Received packet of unknown protocol %d from TUN (dropping it)\n"),
1681 (unsigned int) ntohs (tun->proto));
1689 * Synthesize a plausible ICMP payload for an ICMP error
1690 * response on the given channel.
1692 * @param ts channel information
1693 * @param ipp IPv4 header to fill in (ICMP payload)
1694 * @param udp "UDP" header to fill in (ICMP payload); might actually
1695 * also be the first 8 bytes of the TCP header
1698 make_up_icmpv4_payload (struct ChannelState *ts,
1699 struct GNUNET_TUN_IPv4Header *ipp,
1700 struct GNUNET_TUN_UdpHeader *udp)
1702 GNUNET_TUN_initialize_ipv4_header (ipp,
1704 sizeof (struct GNUNET_TUN_TcpHeader),
1706 &ts->destination_ip.v4);
1707 udp->source_port = htons (ts->source_port);
1708 udp->destination_port = htons (ts->destination_port);
1709 udp->len = htons (0);
1710 udp->crc = htons (0);
1715 * Synthesize a plausible ICMP payload for an ICMP error
1716 * response on the given channel.
1718 * @param ts channel information
1719 * @param ipp IPv6 header to fill in (ICMP payload)
1720 * @param udp "UDP" header to fill in (ICMP payload); might actually
1721 * also be the first 8 bytes of the TCP header
1724 make_up_icmpv6_payload (struct ChannelState *ts,
1725 struct GNUNET_TUN_IPv6Header *ipp,
1726 struct GNUNET_TUN_UdpHeader *udp)
1728 GNUNET_TUN_initialize_ipv6_header (ipp,
1730 sizeof (struct GNUNET_TUN_TcpHeader),
1732 &ts->destination_ip.v6);
1733 udp->source_port = htons (ts->source_port);
1734 udp->destination_port = htons (ts->destination_port);
1735 udp->len = htons (0);
1736 udp->crc = htons (0);
1741 * We got an ICMP packet back from the CADET channel. Pass it on to the
1742 * local virtual interface via the helper.
1744 * @param cls closure, NULL
1745 * @param channel connection to the other end
1746 * @param channel_ctx pointer to our 'struct ChannelState *'
1747 * @param message the actual message
1748 * @return #GNUNET_OK to keep the connection open,
1749 * #GNUNET_SYSERR to close it (signal serious error)
1752 receive_icmp_back (void *cls,
1753 struct GNUNET_CADET_Channel *channel,
1755 const struct GNUNET_MessageHeader *message)
1757 struct ChannelState *ts = *channel_ctx;
1758 const struct GNUNET_EXIT_IcmpToVPNMessage *i2v;
1761 GNUNET_STATISTICS_update (stats,
1762 gettext_noop ("# ICMP packets received from cadet"),
1764 mlen = ntohs (message->size);
1765 if (mlen < sizeof (struct GNUNET_EXIT_IcmpToVPNMessage))
1767 GNUNET_break_op (0);
1768 return GNUNET_SYSERR;
1770 if (NULL == ts->heap_node)
1772 GNUNET_break_op (0);
1773 return GNUNET_SYSERR;
1775 if (AF_UNSPEC == ts->af)
1777 GNUNET_break_op (0);
1778 return GNUNET_SYSERR;
1780 i2v = (const struct GNUNET_EXIT_IcmpToVPNMessage *) message;
1781 mlen -= sizeof (struct GNUNET_EXIT_IcmpToVPNMessage);
1783 char sbuf[INET6_ADDRSTRLEN];
1784 char dbuf[INET6_ADDRSTRLEN];
1786 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1787 "Received ICMP packet from cadet, sending %u bytes from %s -> %s via TUN\n",
1788 (unsigned int) mlen,
1789 inet_ntop (ts->af, &ts->destination_ip, sbuf, sizeof (sbuf)),
1790 inet_ntop (ts->af, &ts->source_ip, dbuf, sizeof (dbuf)));
1796 size_t size = sizeof (struct GNUNET_TUN_IPv4Header)
1797 + sizeof (struct GNUNET_TUN_IcmpHeader)
1798 + sizeof (struct GNUNET_MessageHeader) +
1799 sizeof (struct GNUNET_TUN_Layer2PacketHeader) +
1802 /* reserve some extra space in case we have an ICMP type here where
1803 we will need to make up the payload ourselves */
1804 char buf[size + sizeof (struct GNUNET_TUN_IPv4Header) + 8] GNUNET_ALIGN;
1805 struct GNUNET_MessageHeader *msg = (struct GNUNET_MessageHeader *) buf;
1806 struct GNUNET_TUN_Layer2PacketHeader *tun = (struct GNUNET_TUN_Layer2PacketHeader*) &msg[1];
1807 struct GNUNET_TUN_IPv4Header *ipv4 = (struct GNUNET_TUN_IPv4Header *) &tun[1];
1808 struct GNUNET_TUN_IcmpHeader *icmp = (struct GNUNET_TUN_IcmpHeader *) &ipv4[1];
1809 msg->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
1810 tun->flags = htons (0);
1811 tun->proto = htons (ETH_P_IPV4);
1812 GNUNET_TUN_initialize_ipv4_header (ipv4,
1814 sizeof (struct GNUNET_TUN_IcmpHeader) + mlen,
1815 &ts->destination_ip.v4,
1817 *icmp = i2v->icmp_header;
1821 /* For some ICMP types, we need to adjust (make up) the payload here.
1822 Also, depending on the AF used on the other side, we have to
1823 do ICMP PT (translate ICMP types) */
1824 switch (ntohl (i2v->af))
1829 case GNUNET_TUN_ICMPTYPE_ECHO_REPLY:
1830 case GNUNET_TUN_ICMPTYPE_ECHO_REQUEST:
1832 case GNUNET_TUN_ICMPTYPE_DESTINATION_UNREACHABLE:
1833 case GNUNET_TUN_ICMPTYPE_SOURCE_QUENCH:
1834 case 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);
1851 GNUNET_break_op (0);
1852 GNUNET_STATISTICS_update (stats,
1853 gettext_noop ("# ICMPv4 packets dropped (type not allowed)"),
1855 return GNUNET_SYSERR;
1860 /* ICMP PT 6-to-4 and possibly making up payloads */
1863 case GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE:
1864 icmp->type = GNUNET_TUN_ICMPTYPE_DESTINATION_UNREACHABLE;
1866 struct GNUNET_TUN_IPv4Header *ipp = (struct GNUNET_TUN_IPv4Header *) &icmp[1];
1867 struct GNUNET_TUN_UdpHeader *udp = (struct GNUNET_TUN_UdpHeader *) &ipp[1];
1871 /* sender did not strip ICMP payload? */
1872 GNUNET_break_op (0);
1873 return GNUNET_SYSERR;
1875 size += sizeof (struct GNUNET_TUN_IPv4Header) + 8;
1876 GNUNET_assert (8 == sizeof (struct GNUNET_TUN_UdpHeader));
1877 make_up_icmpv4_payload (ts, ipp, udp);
1880 case GNUNET_TUN_ICMPTYPE6_TIME_EXCEEDED:
1881 icmp->type = GNUNET_TUN_ICMPTYPE_TIME_EXCEEDED;
1883 struct GNUNET_TUN_IPv4Header *ipp = (struct GNUNET_TUN_IPv4Header *) &icmp[1];
1884 struct GNUNET_TUN_UdpHeader *udp = (struct GNUNET_TUN_UdpHeader *) &ipp[1];
1888 /* sender did not strip ICMP payload? */
1889 GNUNET_break_op (0);
1890 return GNUNET_SYSERR;
1892 size += sizeof (struct GNUNET_TUN_IPv4Header) + 8;
1893 GNUNET_assert (8 == sizeof (struct GNUNET_TUN_UdpHeader));
1894 make_up_icmpv4_payload (ts, ipp, udp);
1897 case GNUNET_TUN_ICMPTYPE6_PACKET_TOO_BIG:
1898 case GNUNET_TUN_ICMPTYPE6_PARAMETER_PROBLEM:
1899 GNUNET_STATISTICS_update (stats,
1900 gettext_noop ("# ICMPv6 packets dropped (impossible PT to v4)"),
1903 case GNUNET_TUN_ICMPTYPE6_ECHO_REQUEST:
1904 icmp->type = GNUNET_TUN_ICMPTYPE_ECHO_REQUEST;
1906 case GNUNET_TUN_ICMPTYPE6_ECHO_REPLY:
1907 icmp->type = GNUNET_TUN_ICMPTYPE_ECHO_REPLY;
1910 GNUNET_break_op (0);
1911 GNUNET_STATISTICS_update (stats,
1912 gettext_noop ("# ICMPv6 packets dropped (type not allowed)"),
1914 return GNUNET_SYSERR;
1919 GNUNET_break_op (0);
1920 return GNUNET_SYSERR;
1922 msg->size = htons (size);
1923 GNUNET_TUN_calculate_icmp_checksum (icmp,
1926 (void) GNUNET_HELPER_send (helper_handle,
1935 size_t size = sizeof (struct GNUNET_TUN_IPv6Header)
1936 + sizeof (struct GNUNET_TUN_IcmpHeader)
1937 + sizeof (struct GNUNET_MessageHeader) +
1938 sizeof (struct GNUNET_TUN_Layer2PacketHeader) +
1941 char buf[size + sizeof (struct GNUNET_TUN_IPv6Header) + 8] GNUNET_ALIGN;
1942 struct GNUNET_MessageHeader *msg = (struct GNUNET_MessageHeader *) buf;
1943 struct GNUNET_TUN_Layer2PacketHeader *tun = (struct GNUNET_TUN_Layer2PacketHeader*) &msg[1];
1944 struct GNUNET_TUN_IPv6Header *ipv6 = (struct GNUNET_TUN_IPv6Header *) &tun[1];
1945 struct GNUNET_TUN_IcmpHeader *icmp = (struct GNUNET_TUN_IcmpHeader *) &ipv6[1];
1946 msg->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
1947 tun->flags = htons (0);
1948 tun->proto = htons (ETH_P_IPV6);
1949 GNUNET_TUN_initialize_ipv6_header (ipv6,
1951 sizeof (struct GNUNET_TUN_IcmpHeader) + mlen,
1952 &ts->destination_ip.v6,
1954 *icmp = i2v->icmp_header;
1959 /* For some ICMP types, we need to adjust (make up) the payload here.
1960 Also, depending on the AF used on the other side, we have to
1961 do ICMP PT (translate ICMP types) */
1962 switch (ntohl (i2v->af))
1965 /* ICMP PT 4-to-6 and possibly making up payloads */
1968 case GNUNET_TUN_ICMPTYPE_ECHO_REPLY:
1969 icmp->type = GNUNET_TUN_ICMPTYPE6_ECHO_REPLY;
1971 case GNUNET_TUN_ICMPTYPE_ECHO_REQUEST:
1972 icmp->type = GNUNET_TUN_ICMPTYPE6_ECHO_REQUEST;
1974 case GNUNET_TUN_ICMPTYPE_DESTINATION_UNREACHABLE:
1975 icmp->type = GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE;
1977 struct GNUNET_TUN_IPv6Header *ipp = (struct GNUNET_TUN_IPv6Header *) &icmp[1];
1978 struct GNUNET_TUN_UdpHeader *udp = (struct GNUNET_TUN_UdpHeader *) &ipp[1];
1982 /* sender did not strip ICMP payload? */
1983 GNUNET_break_op (0);
1984 return GNUNET_SYSERR;
1986 size += sizeof (struct GNUNET_TUN_IPv6Header) + 8;
1987 GNUNET_assert (8 == sizeof (struct GNUNET_TUN_UdpHeader));
1988 make_up_icmpv6_payload (ts, ipp, udp);
1991 case GNUNET_TUN_ICMPTYPE_TIME_EXCEEDED:
1992 icmp->type = GNUNET_TUN_ICMPTYPE6_TIME_EXCEEDED;
1994 struct GNUNET_TUN_IPv6Header *ipp = (struct GNUNET_TUN_IPv6Header *) &icmp[1];
1995 struct GNUNET_TUN_UdpHeader *udp = (struct GNUNET_TUN_UdpHeader *) &ipp[1];
1999 /* sender did not strip ICMP payload? */
2000 GNUNET_break_op (0);
2001 return GNUNET_SYSERR;
2003 size += sizeof (struct GNUNET_TUN_IPv6Header) + 8;
2004 GNUNET_assert (8 == sizeof (struct GNUNET_TUN_UdpHeader));
2005 make_up_icmpv6_payload (ts, ipp, udp);
2008 case GNUNET_TUN_ICMPTYPE_SOURCE_QUENCH:
2009 GNUNET_STATISTICS_update (stats,
2010 gettext_noop ("# ICMPv4 packets dropped (impossible PT to v6)"),
2014 GNUNET_break_op (0);
2015 GNUNET_STATISTICS_update (stats,
2016 gettext_noop ("# ICMPv4 packets dropped (type not allowed)"),
2018 return GNUNET_SYSERR;
2025 case GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE:
2026 case GNUNET_TUN_ICMPTYPE6_TIME_EXCEEDED:
2027 case GNUNET_TUN_ICMPTYPE6_PACKET_TOO_BIG:
2028 case GNUNET_TUN_ICMPTYPE6_PARAMETER_PROBLEM:
2030 struct GNUNET_TUN_IPv6Header *ipp = (struct GNUNET_TUN_IPv6Header *) &icmp[1];
2031 struct GNUNET_TUN_UdpHeader *udp = (struct GNUNET_TUN_UdpHeader *) &ipp[1];
2035 /* sender did not strip ICMP payload? */
2036 GNUNET_break_op (0);
2037 return GNUNET_SYSERR;
2039 size += sizeof (struct GNUNET_TUN_IPv6Header) + 8;
2040 GNUNET_assert (8 == sizeof (struct GNUNET_TUN_UdpHeader));
2041 make_up_icmpv6_payload (ts, ipp, udp);
2044 case GNUNET_TUN_ICMPTYPE6_ECHO_REQUEST:
2047 GNUNET_break_op (0);
2048 GNUNET_STATISTICS_update (stats,
2049 gettext_noop ("# ICMPv6 packets dropped (type not allowed)"),
2051 return GNUNET_SYSERR;
2056 GNUNET_break_op (0);
2057 return GNUNET_SYSERR;
2059 msg->size = htons (size);
2060 GNUNET_TUN_calculate_icmp_checksum (icmp,
2062 (void) GNUNET_HELPER_send (helper_handle,
2072 GNUNET_CONTAINER_heap_update_cost (channel_heap,
2074 GNUNET_TIME_absolute_get ().abs_value_us);
2080 * We got a UDP packet back from the CADET channel. Pass it on to the
2081 * local virtual interface via the helper.
2083 * @param cls closure, NULL
2084 * @param channel connection to the other end
2085 * @param channel_ctx pointer to our 'struct ChannelState *'
2086 * @param message the actual message
2087 * @return #GNUNET_OK to keep the connection open,
2088 * #GNUNET_SYSERR to close it (signal serious error)
2091 receive_udp_back (void *cls,
2092 struct GNUNET_CADET_Channel *channel,
2094 const struct GNUNET_MessageHeader *message)
2096 struct ChannelState *ts = *channel_ctx;
2097 const struct GNUNET_EXIT_UdpReplyMessage *reply;
2100 GNUNET_STATISTICS_update (stats,
2101 gettext_noop ("# UDP packets received from cadet"),
2103 mlen = ntohs (message->size);
2104 if (mlen < sizeof (struct GNUNET_EXIT_UdpReplyMessage))
2106 GNUNET_break_op (0);
2107 return GNUNET_SYSERR;
2109 if (NULL == ts->heap_node)
2111 GNUNET_break_op (0);
2112 return GNUNET_SYSERR;
2114 if (AF_UNSPEC == ts->af)
2116 GNUNET_break_op (0);
2117 return GNUNET_SYSERR;
2119 reply = (const struct GNUNET_EXIT_UdpReplyMessage *) message;
2120 mlen -= sizeof (struct GNUNET_EXIT_UdpReplyMessage);
2122 char sbuf[INET6_ADDRSTRLEN];
2123 char dbuf[INET6_ADDRSTRLEN];
2125 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2126 "Received UDP reply from cadet, sending %u bytes from %s:%u -> %s:%u via TUN\n",
2127 (unsigned int) mlen,
2128 inet_ntop (ts->af, &ts->destination_ip, sbuf, sizeof (sbuf)),
2129 ts->destination_port,
2130 inet_ntop (ts->af, &ts->source_ip, dbuf, sizeof (dbuf)),
2137 size_t size = sizeof (struct GNUNET_TUN_IPv4Header)
2138 + sizeof (struct GNUNET_TUN_UdpHeader)
2139 + sizeof (struct GNUNET_MessageHeader) +
2140 sizeof (struct GNUNET_TUN_Layer2PacketHeader) +
2143 char buf[size] GNUNET_ALIGN;
2144 struct GNUNET_MessageHeader *msg = (struct GNUNET_MessageHeader *) buf;
2145 struct GNUNET_TUN_Layer2PacketHeader *tun = (struct GNUNET_TUN_Layer2PacketHeader*) &msg[1];
2146 struct GNUNET_TUN_IPv4Header *ipv4 = (struct GNUNET_TUN_IPv4Header *) &tun[1];
2147 struct GNUNET_TUN_UdpHeader *udp = (struct GNUNET_TUN_UdpHeader *) &ipv4[1];
2148 msg->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
2149 msg->size = htons (size);
2150 tun->flags = htons (0);
2151 tun->proto = htons (ETH_P_IPV4);
2152 GNUNET_TUN_initialize_ipv4_header (ipv4,
2154 sizeof (struct GNUNET_TUN_UdpHeader) + mlen,
2155 &ts->destination_ip.v4,
2157 if (0 == ntohs (reply->source_port))
2158 udp->source_port = htons (ts->destination_port);
2160 udp->source_port = reply->source_port;
2161 if (0 == ntohs (reply->destination_port))
2162 udp->destination_port = htons (ts->source_port);
2164 udp->destination_port = reply->destination_port;
2165 udp->len = htons (mlen + sizeof (struct GNUNET_TUN_UdpHeader));
2166 GNUNET_TUN_calculate_udp4_checksum (ipv4,
2173 (void) GNUNET_HELPER_send (helper_handle,
2182 size_t size = sizeof (struct GNUNET_TUN_IPv6Header)
2183 + sizeof (struct GNUNET_TUN_UdpHeader)
2184 + sizeof (struct GNUNET_MessageHeader) +
2185 sizeof (struct GNUNET_TUN_Layer2PacketHeader) +
2188 char buf[size] GNUNET_ALIGN;
2189 struct GNUNET_MessageHeader *msg = (struct GNUNET_MessageHeader *) buf;
2190 struct GNUNET_TUN_Layer2PacketHeader *tun = (struct GNUNET_TUN_Layer2PacketHeader*) &msg[1];
2191 struct GNUNET_TUN_IPv6Header *ipv6 = (struct GNUNET_TUN_IPv6Header *) &tun[1];
2192 struct GNUNET_TUN_UdpHeader *udp = (struct GNUNET_TUN_UdpHeader *) &ipv6[1];
2193 msg->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
2194 msg->size = htons (size);
2195 tun->flags = htons (0);
2196 tun->proto = htons (ETH_P_IPV6);
2197 GNUNET_TUN_initialize_ipv6_header (ipv6,
2199 sizeof (struct GNUNET_TUN_UdpHeader) + mlen,
2200 &ts->destination_ip.v6,
2202 if (0 == ntohs (reply->source_port))
2203 udp->source_port = htons (ts->destination_port);
2205 udp->source_port = reply->source_port;
2206 if (0 == ntohs (reply->destination_port))
2207 udp->destination_port = htons (ts->source_port);
2209 udp->destination_port = reply->destination_port;
2210 udp->len = htons (mlen + sizeof (struct GNUNET_TUN_UdpHeader));
2211 GNUNET_TUN_calculate_udp6_checksum (ipv6,
2217 (void) GNUNET_HELPER_send (helper_handle,
2227 GNUNET_CONTAINER_heap_update_cost (channel_heap,
2229 GNUNET_TIME_absolute_get ().abs_value_us);
2235 * We got a TCP packet back from the CADET channel. Pass it on to the
2236 * local virtual interface via the helper.
2238 * @param cls closure, NULL
2239 * @param channel connection to the other end
2240 * @param channel_ctx pointer to our `struct ChannelState *`
2241 * @param message the actual message
2242 * @return #GNUNET_OK to keep the connection open,
2243 * #GNUNET_SYSERR to close it (signal serious error)
2246 receive_tcp_back (void *cls,
2247 struct GNUNET_CADET_Channel *channel,
2249 const struct GNUNET_MessageHeader *message)
2251 struct ChannelState *ts = *channel_ctx;
2252 const struct GNUNET_EXIT_TcpDataMessage *data;
2255 GNUNET_STATISTICS_update (stats,
2256 gettext_noop ("# TCP packets received from cadet"),
2258 mlen = ntohs (message->size);
2259 if (mlen < sizeof (struct GNUNET_EXIT_TcpDataMessage))
2261 GNUNET_break_op (0);
2262 return GNUNET_SYSERR;
2264 if (NULL == ts->heap_node)
2266 GNUNET_break_op (0);
2267 return GNUNET_SYSERR;
2269 data = (const struct GNUNET_EXIT_TcpDataMessage *) message;
2270 mlen -= sizeof (struct GNUNET_EXIT_TcpDataMessage);
2272 char sbuf[INET6_ADDRSTRLEN];
2273 char dbuf[INET6_ADDRSTRLEN];
2275 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2276 "Received TCP reply from cadet, sending %u bytes from %s:%u -> %s:%u via TUN\n",
2277 (unsigned int) mlen,
2278 inet_ntop (ts->af, &ts->destination_ip, sbuf, sizeof (sbuf)),
2279 ts->destination_port,
2280 inet_ntop (ts->af, &ts->source_ip, dbuf, sizeof (dbuf)),
2283 if (data->tcp_header.off * 4 < sizeof (struct GNUNET_TUN_TcpHeader))
2285 GNUNET_break_op (0);
2286 return GNUNET_SYSERR;
2292 size_t size = sizeof (struct GNUNET_TUN_IPv4Header)
2293 + sizeof (struct GNUNET_TUN_TcpHeader)
2294 + sizeof (struct GNUNET_MessageHeader) +
2295 sizeof (struct GNUNET_TUN_Layer2PacketHeader) +
2298 char buf[size] GNUNET_ALIGN;
2299 struct GNUNET_MessageHeader *msg = (struct GNUNET_MessageHeader *) buf;
2300 struct GNUNET_TUN_Layer2PacketHeader *tun = (struct GNUNET_TUN_Layer2PacketHeader*) &msg[1];
2301 struct GNUNET_TUN_IPv4Header *ipv4 = (struct GNUNET_TUN_IPv4Header *) &tun[1];
2302 struct GNUNET_TUN_TcpHeader *tcp = (struct GNUNET_TUN_TcpHeader *) &ipv4[1];
2303 msg->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
2304 msg->size = htons (size);
2305 tun->flags = htons (0);
2306 tun->proto = htons (ETH_P_IPV4);
2307 GNUNET_TUN_initialize_ipv4_header (ipv4,
2309 sizeof (struct GNUNET_TUN_TcpHeader) + mlen,
2310 &ts->destination_ip.v4,
2312 *tcp = data->tcp_header;
2313 tcp->source_port = htons (ts->destination_port);
2314 tcp->destination_port = htons (ts->source_port);
2315 GNUNET_TUN_calculate_tcp4_checksum (ipv4,
2322 (void) GNUNET_HELPER_send (helper_handle,
2331 size_t size = sizeof (struct GNUNET_TUN_IPv6Header)
2332 + sizeof (struct GNUNET_TUN_TcpHeader)
2333 + sizeof (struct GNUNET_MessageHeader) +
2334 sizeof (struct GNUNET_TUN_Layer2PacketHeader) +
2337 char buf[size] GNUNET_ALIGN;
2338 struct GNUNET_MessageHeader *msg = (struct GNUNET_MessageHeader *) buf;
2339 struct GNUNET_TUN_Layer2PacketHeader *tun = (struct GNUNET_TUN_Layer2PacketHeader*) &msg[1];
2340 struct GNUNET_TUN_IPv6Header *ipv6 = (struct GNUNET_TUN_IPv6Header *) &tun[1];
2341 struct GNUNET_TUN_TcpHeader *tcp = (struct GNUNET_TUN_TcpHeader *) &ipv6[1];
2342 msg->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
2343 msg->size = htons (size);
2344 tun->flags = htons (0);
2345 tun->proto = htons (ETH_P_IPV6);
2346 GNUNET_TUN_initialize_ipv6_header (ipv6,
2348 sizeof (struct GNUNET_TUN_TcpHeader) + mlen,
2349 &ts->destination_ip.v6,
2351 *tcp = data->tcp_header;
2352 tcp->source_port = htons (ts->destination_port);
2353 tcp->destination_port = htons (ts->source_port);
2354 GNUNET_TUN_calculate_tcp6_checksum (ipv6,
2361 (void) GNUNET_HELPER_send (helper_handle,
2369 GNUNET_CONTAINER_heap_update_cost (channel_heap,
2371 GNUNET_TIME_absolute_get ().abs_value_us);
2377 * Allocate an IPv4 address from the range of the channel
2378 * for a new redirection.
2380 * @param v4 where to store the address
2381 * @return #GNUNET_OK on success,
2382 * #GNUNET_SYSERR on error
2385 allocate_v4_address (struct in_addr *v4)
2387 const char *ipv4addr = vpn_argv[4];
2388 const char *ipv4mask = vpn_argv[5];
2389 struct in_addr addr;
2390 struct in_addr mask;
2392 struct GNUNET_HashCode key;
2395 GNUNET_assert (1 == inet_pton (AF_INET, ipv4addr, &addr));
2396 GNUNET_assert (1 == inet_pton (AF_INET, ipv4mask, &mask));
2397 /* Given 192.168.0.1/255.255.0.0, we want a mask
2398 of '192.168.255.255', thus: */
2399 mask.s_addr = addr.s_addr | ~mask.s_addr;
2406 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
2407 _("Failed to find unallocated IPv4 address in VPN's range\n"));
2408 return GNUNET_SYSERR;
2410 /* Pick random IPv4 address within the subnet, except 'addr' or 'mask' itself */
2411 rnd.s_addr = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
2413 v4->s_addr = (addr.s_addr | rnd.s_addr) & mask.s_addr;
2414 get_destination_key_from_ip (AF_INET,
2418 while ( (GNUNET_YES ==
2419 GNUNET_CONTAINER_multihashmap_contains (destination_map,
2421 (v4->s_addr == addr.s_addr) ||
2422 (v4->s_addr == mask.s_addr) );
2428 * Allocate an IPv6 address from the range of the channel
2429 * for a new redirection.
2431 * @param v6 where to store the address
2432 * @return #GNUNET_OK on success,
2433 * #GNUNET_SYSERR on error
2436 allocate_v6_address (struct in6_addr *v6)
2438 const char *ipv6addr = vpn_argv[2];
2439 struct in6_addr addr;
2440 struct in6_addr mask;
2441 struct in6_addr rnd;
2443 struct GNUNET_HashCode key;
2446 GNUNET_assert (1 == inet_pton (AF_INET6, ipv6addr, &addr));
2447 GNUNET_assert (ipv6prefix < 128);
2448 /* Given ABCD::/96, we want a mask of 'ABCD::FFFF:FFFF,
2451 for (i=127;i>=ipv6prefix;i--)
2452 mask.s6_addr[i / 8] |= (1 << (i % 8));
2454 /* Pick random IPv6 address within the subnet, except 'addr' or 'mask' itself */
2461 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
2462 _("Failed to find unallocated IPv6 address in VPN's range\n"));
2463 return GNUNET_SYSERR;
2468 rnd.s6_addr[i] = (unsigned char) GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
2471 = (addr.s6_addr[i] | rnd.s6_addr[i]) & mask.s6_addr[i];
2473 get_destination_key_from_ip (AF_INET6,
2477 while ( (GNUNET_YES ==
2478 GNUNET_CONTAINER_multihashmap_contains (destination_map,
2482 sizeof (struct in6_addr))) ||
2485 sizeof (struct in6_addr))) );
2491 * Free resources occupied by a destination entry.
2493 * @param de entry to free
2496 free_destination_entry (struct DestinationEntry *de)
2498 struct DestinationChannel *dt;
2500 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2501 "Cleaning up destination entry `%s'\n",
2502 print_channel_destination (de));
2503 GNUNET_STATISTICS_update (stats,
2504 gettext_noop ("# Active destinations"),
2506 while (NULL != (dt = de->dt_head))
2508 GNUNET_CONTAINER_DLL_remove (de->dt_head,
2513 free_channel_state (dt->ts);
2514 GNUNET_assert (NULL == dt->ts);
2518 if (NULL != de->heap_node)
2520 GNUNET_CONTAINER_heap_remove_node (de->heap_node);
2521 de->heap_node = NULL;
2522 GNUNET_assert (GNUNET_YES ==
2523 GNUNET_CONTAINER_multihashmap_remove (destination_map,
2532 * We have too many active destinations. Clean up the oldest destination.
2534 * @param except destination that must NOT be cleaned up, even if it is the oldest
2537 expire_destination (struct DestinationEntry *except)
2539 struct DestinationEntry *de;
2541 de = GNUNET_CONTAINER_heap_peek (destination_heap);
2542 GNUNET_assert (NULL != de);
2544 return; /* can't do this */
2545 free_destination_entry (de);
2550 * Allocate an IP address for the response.
2552 * @param result_af desired address family; set to the actual
2553 * address family; can initially be AF_UNSPEC if there
2554 * is no preference; will be set to AF_UNSPEC if the
2556 * @param addr set to either v4 or v6 depending on which
2557 * storage location was used; set to NULL if allocation failed
2558 * @param v4 storage space for an IPv4 address
2559 * @param v6 storage space for an IPv6 address
2560 * @return #GNUNET_OK normally, #GNUNET_SYSERR if `* result_af` was
2561 * an unsupported address family (not AF_INET, AF_INET6 or AF_UNSPEC)
2564 allocate_response_ip (int *result_af,
2567 struct in6_addr *v6)
2574 allocate_v4_address (v4))
2575 *result_af = AF_UNSPEC;
2581 allocate_v6_address (v6))
2582 *result_af = AF_UNSPEC;
2588 allocate_v4_address (v4))
2591 *result_af = AF_INET;
2593 else if (GNUNET_OK ==
2594 allocate_v6_address (v6))
2597 *result_af = AF_INET6;
2602 return GNUNET_SYSERR;
2609 * A client asks us to setup a redirection via some exit node to a
2610 * particular IP. Setup the redirection and give the client the
2614 * @param client requesting client
2615 * @param message redirection request (a `struct RedirectToIpRequestMessage`)
2618 service_redirect_to_ip (void *cls,
2619 struct GNUNET_SERVER_Client *client,
2620 const struct GNUNET_MessageHeader *message)
2624 const struct RedirectToIpRequestMessage *msg;
2630 struct DestinationEntry *de;
2631 struct GNUNET_HashCode key;
2633 /* validate and parse request */
2634 mlen = ntohs (message->size);
2635 if (mlen < sizeof (struct RedirectToIpRequestMessage))
2638 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2641 alen = mlen - sizeof (struct RedirectToIpRequestMessage);
2642 msg = (const struct RedirectToIpRequestMessage *) message;
2643 addr_af = (int) htonl (msg->addr_af);
2647 if (alen != sizeof (struct in_addr))
2650 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2655 if (alen != sizeof (struct in6_addr))
2658 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2664 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2668 /* allocate response IP */
2669 result_af = (int) htonl (msg->result_af);
2670 if (GNUNET_OK != allocate_response_ip (&result_af,
2674 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2677 /* send reply with our IP address */
2678 send_client_reply (client,
2682 if (result_af == AF_UNSPEC)
2684 /* failure, we're done */
2685 GNUNET_SERVER_receive_done (client, GNUNET_OK);
2690 char sbuf[INET6_ADDRSTRLEN];
2691 char dbuf[INET6_ADDRSTRLEN];
2693 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2694 "Allocated address %s for redirection via exit to %s\n",
2695 inet_ntop (result_af, addr, sbuf, sizeof (sbuf)),
2697 &msg[1], dbuf, sizeof (dbuf)));
2700 /* setup destination record */
2701 de = GNUNET_new (struct DestinationEntry);
2702 de->is_service = GNUNET_NO;
2703 de->details.exit_destination.af = addr_af;
2704 memcpy (&de->details.exit_destination.ip,
2707 get_destination_key_from_ip (result_af,
2711 GNUNET_assert (GNUNET_OK ==
2712 GNUNET_CONTAINER_multihashmap_put (destination_map,
2715 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE));
2716 de->heap_node = GNUNET_CONTAINER_heap_insert (destination_heap,
2718 GNUNET_TIME_absolute_ntoh (msg->expiration_time).abs_value_us);
2719 GNUNET_STATISTICS_update (stats,
2720 gettext_noop ("# Active destinations"),
2722 while (GNUNET_CONTAINER_multihashmap_size (destination_map) > max_destination_mappings)
2723 expire_destination (de);
2724 GNUNET_SERVER_receive_done (client, GNUNET_OK);
2729 * A client asks us to setup a redirection to a particular peer
2730 * offering a service. Setup the redirection and give the client the
2734 * @param client requesting client
2735 * @param message redirection request (a `struct RedirectToPeerRequestMessage`)
2738 service_redirect_to_service (void *cls,
2739 struct GNUNET_SERVER_Client *client,
2740 const struct GNUNET_MessageHeader *message)
2742 const struct RedirectToServiceRequestMessage *msg;
2747 struct DestinationEntry *de;
2748 struct GNUNET_HashCode key;
2749 struct ChannelState *ts;
2750 struct DestinationChannel *dt;
2753 msg = (const struct RedirectToServiceRequestMessage *) message;
2755 /* allocate response IP */
2756 result_af = (int) htonl (msg->result_af);
2757 if (GNUNET_OK != allocate_response_ip (&result_af,
2761 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2764 send_client_reply (client,
2768 if (result_af == AF_UNSPEC)
2770 /* failure, we're done */
2771 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2772 _("Failed to allocate IP address for new destination\n"));
2773 GNUNET_SERVER_receive_done (client, GNUNET_OK);
2778 char sbuf[INET6_ADDRSTRLEN];
2780 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2781 "Allocated address %s for redirection to service %s on peer %s\n",
2782 inet_ntop (result_af, addr, sbuf, sizeof (sbuf)),
2783 GNUNET_h2s (&msg->service_descriptor),
2784 GNUNET_i2s (&msg->target));
2787 /* setup destination record */
2788 de = GNUNET_new (struct DestinationEntry);
2789 de->is_service = GNUNET_YES;
2790 de->details.service_destination.service_descriptor = msg->service_descriptor;
2791 de->details.service_destination.target = msg->target;
2792 get_destination_key_from_ip (result_af,
2796 GNUNET_assert (GNUNET_OK ==
2797 GNUNET_CONTAINER_multihashmap_put (destination_map,
2800 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE));
2801 de->heap_node = GNUNET_CONTAINER_heap_insert (destination_heap,
2803 GNUNET_TIME_absolute_ntoh (msg->expiration_time).abs_value_us);
2804 while (GNUNET_CONTAINER_multihashmap_size (destination_map) > max_destination_mappings)
2805 expire_destination (de);
2807 dt = GNUNET_new (struct DestinationChannel);
2808 dt->destination = de;
2809 GNUNET_CONTAINER_DLL_insert (de->dt_head,
2812 ts = create_channel_to_destination (dt,
2817 ts->destination_ip.v4 = v4;
2820 ts->destination_ip.v6 = v6;
2826 GNUNET_SERVER_receive_done (client, GNUNET_OK);
2831 * Function called whenever a channel is destroyed. Should clean up
2832 * any associated state.
2834 * @param cls closure (set from #GNUNET_CADET_connect)
2835 * @param channel connection to the other end (henceforth invalid)
2836 * @param channel_ctx place where local state associated
2837 * with the channel is stored (our `struct ChannelState`)
2840 channel_cleaner (void *cls,
2841 const struct GNUNET_CADET_Channel *channel,
2844 struct ChannelState *ts = channel_ctx;
2846 ts->channel = NULL; /* we must not call GNUNET_CADET_channel_destroy() anymore */
2847 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2848 "CADET notified us about death of channel to `%s'\n",
2849 print_channel_destination (&ts->destination));
2850 free_channel_state (ts);
2855 * Free memory occupied by an entry in the destination map.
2859 * @param value a `struct DestinationEntry *`
2860 * @return #GNUNET_OK (continue to iterate)
2863 cleanup_destination (void *cls,
2864 const struct GNUNET_HashCode *key,
2867 struct DestinationEntry *de = value;
2869 free_destination_entry (de);
2875 * Free memory occupied by an entry in the channel map.
2879 * @param value a `struct ChannelState *`
2880 * @return #GNUNET_OK (continue to iterate)
2883 cleanup_channel (void *cls,
2884 const struct GNUNET_HashCode *key,
2887 struct ChannelState *ts = value;
2889 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2890 "Tearing down channel to `%s' during cleanup\n",
2891 print_channel_destination (&ts->destination));
2892 free_channel_state (ts);
2898 * Function scheduled as very last function, cleans up after us
2905 const struct GNUNET_SCHEDULER_TaskContext *tc)
2909 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2910 "VPN is shutting down\n");
2911 if (NULL != destination_map)
2913 GNUNET_CONTAINER_multihashmap_iterate (destination_map,
2914 &cleanup_destination,
2916 GNUNET_CONTAINER_multihashmap_destroy (destination_map);
2917 destination_map = NULL;
2919 if (NULL != destination_heap)
2921 GNUNET_CONTAINER_heap_destroy (destination_heap);
2922 destination_heap = NULL;
2924 if (NULL != channel_map)
2926 GNUNET_CONTAINER_multihashmap_iterate (channel_map,
2929 GNUNET_CONTAINER_multihashmap_destroy (channel_map);
2932 if (NULL != channel_heap)
2934 GNUNET_CONTAINER_heap_destroy (channel_heap);
2935 channel_heap = NULL;
2937 if (NULL != cadet_handle)
2939 GNUNET_CADET_disconnect (cadet_handle);
2940 cadet_handle = NULL;
2942 if (NULL != helper_handle)
2944 GNUNET_HELPER_stop (helper_handle, GNUNET_NO);
2945 helper_handle = NULL;
2949 GNUNET_SERVER_notification_context_destroy (nc);
2954 GNUNET_STATISTICS_destroy (stats, GNUNET_NO);
2958 GNUNET_free_non_null (vpn_argv[i]);
2963 * Main function that will be run by the scheduler.
2965 * @param cls closure
2966 * @param server the initialized server
2967 * @param cfg_ configuration
2971 struct GNUNET_SERVER_Handle *server,
2972 const struct GNUNET_CONFIGURATION_Handle *cfg_)
2974 static const struct GNUNET_SERVER_MessageHandler service_handlers[] = {
2975 /* callback, cls, type, size */
2976 { &service_redirect_to_ip, NULL, GNUNET_MESSAGE_TYPE_VPN_CLIENT_REDIRECT_TO_IP, 0},
2977 { &service_redirect_to_service, NULL,
2978 GNUNET_MESSAGE_TYPE_VPN_CLIENT_REDIRECT_TO_SERVICE,
2979 sizeof (struct RedirectToServiceRequestMessage) },
2982 static const struct GNUNET_CADET_MessageHandler cadet_handlers[] = {
2983 { &receive_udp_back, GNUNET_MESSAGE_TYPE_VPN_UDP_REPLY, 0},
2984 { &receive_tcp_back, GNUNET_MESSAGE_TYPE_VPN_TCP_DATA_TO_VPN, 0},
2985 { &receive_icmp_back, GNUNET_MESSAGE_TYPE_VPN_ICMP_TO_VPN, 0},
2997 binary = GNUNET_OS_get_libexec_binary_path ("gnunet-helper-vpn");
3000 GNUNET_OS_check_helper_binary (binary,
3002 "-d gnunet-vpn - - 169.1.3.3.7 255.255.255.0")) //ipv4 only please!
3004 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
3005 "`%s' is not SUID, refusing to run.\n",
3006 "gnunet-helper-vpn");
3007 GNUNET_free (binary);
3009 /* we won't "really" exit here, as the 'service' is still running;
3010 however, as no handlers are registered, the service won't do
3014 GNUNET_free (binary);
3016 stats = GNUNET_STATISTICS_create ("vpn", cfg);
3018 GNUNET_CONFIGURATION_get_value_number (cfg, "VPN", "MAX_MAPPING",
3019 &max_destination_mappings))
3020 max_destination_mappings = 200;
3022 GNUNET_CONFIGURATION_get_value_number (cfg, "VPN", "MAX_TUNNELS",
3023 &max_channel_mappings))
3024 max_channel_mappings = 200;
3026 destination_map = GNUNET_CONTAINER_multihashmap_create (max_destination_mappings * 2, GNUNET_NO);
3027 destination_heap = GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN);
3028 channel_map = GNUNET_CONTAINER_multihashmap_create (max_channel_mappings * 2, GNUNET_NO);
3029 channel_heap = GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN);
3032 vpn_argv[0] = GNUNET_strdup ("vpn-gnunet");
3033 if (GNUNET_SYSERR ==
3034 GNUNET_CONFIGURATION_get_value_string (cfg, "VPN", "IFNAME", &ifname))
3036 GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, "VPN", "IFNAME");
3037 GNUNET_SCHEDULER_shutdown ();
3040 vpn_argv[1] = ifname;
3042 if (GNUNET_OK == GNUNET_NETWORK_test_pf (PF_INET6))
3044 if ( (GNUNET_SYSERR ==
3045 GNUNET_CONFIGURATION_get_value_string (cfg, "VPN", "IPV6ADDR",
3047 (1 != inet_pton (AF_INET6, ipv6addr, &v6))) )
3049 GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, "VPN", "IPV6ADDR",
3050 _("Must specify valid IPv6 address"));
3051 GNUNET_SCHEDULER_shutdown ();
3052 GNUNET_free_non_null (ipv6addr);
3055 vpn_argv[2] = ipv6addr;
3056 ipv6prefix_s = NULL;
3057 if (GNUNET_SYSERR ==
3058 GNUNET_CONFIGURATION_get_value_string (cfg, "VPN", "IPV6PREFIX",
3061 GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, "VPN", "IPV6PREFIX");
3062 GNUNET_SCHEDULER_shutdown ();
3063 GNUNET_free_non_null (ipv6prefix_s);
3066 vpn_argv[3] = ipv6prefix_s;
3068 GNUNET_CONFIGURATION_get_value_number (cfg, "VPN",
3071 (ipv6prefix >= 127) )
3073 GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, "VPN", "IPV4MASK",
3074 _("Must specify valid IPv6 mask"));
3075 GNUNET_SCHEDULER_shutdown ();
3081 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
3082 _("IPv6 support disabled as this system does not support IPv6\n"));
3083 vpn_argv[2] = GNUNET_strdup ("-");
3084 vpn_argv[3] = GNUNET_strdup ("-");
3086 if (GNUNET_OK == GNUNET_NETWORK_test_pf (PF_INET))
3089 if ( (GNUNET_SYSERR ==
3090 GNUNET_CONFIGURATION_get_value_string (cfg, "vpn", "IPV4ADDR",
3092 (1 != inet_pton (AF_INET, ipv4addr, &v4))) )
3094 GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, "VPN", "IPV4ADDR",
3095 _("Must specify valid IPv4 address"));
3096 GNUNET_SCHEDULER_shutdown ();
3097 GNUNET_free_non_null (ipv4addr);
3100 vpn_argv[4] = ipv4addr;
3102 if ( (GNUNET_SYSERR ==
3103 GNUNET_CONFIGURATION_get_value_string (cfg, "vpn", "IPV4MASK",
3105 (1 != inet_pton (AF_INET, ipv4mask, &v4))) )
3107 GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, "VPN", "IPV4MASK",
3108 _("Must specify valid IPv4 mask"));
3109 GNUNET_SCHEDULER_shutdown ();
3110 GNUNET_free_non_null (ipv4mask);
3113 vpn_argv[5] = ipv4mask;
3117 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
3118 _("IPv4 support disabled as this system does not support IPv4\n"));
3119 vpn_argv[4] = GNUNET_strdup ("-");
3120 vpn_argv[5] = GNUNET_strdup ("-");
3125 GNUNET_CADET_connect (cfg_, NULL,
3130 helper_handle = GNUNET_HELPER_start (GNUNET_NO,
3131 "gnunet-helper-vpn", vpn_argv,
3132 &message_token, NULL, NULL);
3133 nc = GNUNET_SERVER_notification_context_create (server, 1);
3134 GNUNET_SERVER_add_handlers (server, service_handlers);
3135 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &cleanup, cls);
3140 * The main function of the VPN service.
3142 * @param argc number of arguments from the command line
3143 * @param argv command line arguments
3144 * @return 0 ok, 1 on error
3147 main (int argc, char *const *argv)
3149 return (GNUNET_OK ==
3150 GNUNET_SERVICE_run (argc, argv, "vpn",
3151 GNUNET_SERVICE_OPTION_NONE,
3152 &run, NULL)) ? global_ret : 1;
3155 /* end of gnunet-service-vpn.c */