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 free_channel_state (ts);
900 * Route a packet via cadet to the given destination.
902 * @param destination description of the destination
903 * @param af address family on this end (AF_INET or AF_INET6)
904 * @param protocol IPPROTO_TCP or IPPROTO_UDP or IPPROTO_ICMP or IPPROTO_ICMPV6
905 * @param source_ip source IP used by the sender (struct in_addr or struct in6_addr)
906 * @param destination_ip destination IP used by the sender (struct in_addr or struct in6_addr)
907 * @param payload payload of the packet after the IP header
908 * @param payload_length number of bytes in @a payload
911 route_packet (struct DestinationEntry *destination,
914 const void *source_ip,
915 const void *destination_ip,
917 size_t payload_length)
919 struct GNUNET_HashCode key;
920 struct ChannelState *ts;
921 struct ChannelMessageQueueEntry *tnq;
925 const struct GNUNET_TUN_UdpHeader *udp;
926 const struct GNUNET_TUN_TcpHeader *tcp;
927 const struct GNUNET_TUN_IcmpHeader *icmp;
928 struct DestinationChannel *dt;
929 uint16_t source_port;
930 uint16_t destination_port;
936 if (payload_length < sizeof (struct GNUNET_TUN_UdpHeader))
942 tcp = NULL; /* make compiler happy */
943 icmp = NULL; /* make compiler happy */
945 if (udp->len < sizeof (struct GNUNET_TUN_UdpHeader))
950 source_port = ntohs (udp->source_port);
951 destination_port = ntohs (udp->destination_port);
952 get_channel_key_from_ips (af,
963 if (payload_length < sizeof (struct GNUNET_TUN_TcpHeader))
969 udp = NULL; /* make compiler happy */
970 icmp = NULL; /* make compiler happy */
972 if (tcp->off * 4 < sizeof (struct GNUNET_TUN_TcpHeader))
977 source_port = ntohs (tcp->source_port);
978 destination_port = ntohs (tcp->destination_port);
979 get_channel_key_from_ips (af,
991 if ( (AF_INET == af) ^ (protocol == IPPROTO_ICMP) )
996 if (payload_length < sizeof (struct GNUNET_TUN_IcmpHeader))
1002 tcp = NULL; /* make compiler happy */
1003 udp = NULL; /* make compiler happy */
1006 destination_port = 0;
1007 get_channel_key_from_ips (af,
1017 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1018 _("Protocol %u not supported, dropping\n"),
1019 (unsigned int) protocol);
1023 if (! destination->is_service)
1025 switch (destination->details.exit_destination.af)
1028 alen = sizeof (struct in_addr);
1031 alen = sizeof (struct in6_addr);
1038 char sbuf[INET6_ADDRSTRLEN];
1039 char dbuf[INET6_ADDRSTRLEN];
1040 char xbuf[INET6_ADDRSTRLEN];
1042 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1043 "Routing %s packet from %s:%u -> %s:%u to destination %s:%u\n",
1044 (protocol == IPPROTO_TCP) ? "TCP" : "UDP",
1045 inet_ntop (af, source_ip, sbuf, sizeof (sbuf)),
1047 inet_ntop (af, destination_ip, dbuf, sizeof (dbuf)),
1049 inet_ntop (destination->details.exit_destination.af,
1050 &destination->details.exit_destination.ip,
1051 xbuf, sizeof (xbuf)),
1054 for (dt = destination->dt_head; NULL != dt; dt = dt->next)
1055 if (dt->destination_port == destination_port)
1061 char sbuf[INET6_ADDRSTRLEN];
1062 char dbuf[INET6_ADDRSTRLEN];
1064 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1065 "Routing %s packet from %s:%u -> %s:%u to service %s at peer %s\n",
1066 (protocol == IPPROTO_TCP) ? "TCP" : "UDP",
1067 inet_ntop (af, source_ip, sbuf, sizeof (sbuf)),
1069 inet_ntop (af, destination_ip, dbuf, sizeof (dbuf)),
1071 GNUNET_h2s (&destination->details.service_destination.service_descriptor),
1072 GNUNET_i2s (&destination->details.service_destination.target));
1074 dt = destination->dt_head;
1078 dt = GNUNET_new (struct DestinationChannel);
1079 dt->destination = destination;
1080 GNUNET_CONTAINER_DLL_insert (destination->dt_head,
1081 destination->dt_tail,
1083 dt->destination_port = destination_port;
1086 /* see if we have an existing channel for this destination */
1087 ts = GNUNET_CONTAINER_multihashmap_get (channel_map,
1091 /* need to either use the existing channel from the destination (if still
1092 available) or create a fresh one */
1093 is_new = GNUNET_YES;
1095 ts = create_channel_to_destination (dt, af);
1101 ts->destination_container = NULL; /* no longer 'contained' */
1102 /* now bind existing "unbound" channel to our IP/port tuple */
1103 ts->protocol = protocol;
1107 ts->source_ip.v4 = * (const struct in_addr *) source_ip;
1108 ts->destination_ip.v4 = * (const struct in_addr *) destination_ip;
1112 ts->source_ip.v6 = * (const struct in6_addr *) source_ip;
1113 ts->destination_ip.v6 = * (const struct in6_addr *) destination_ip;
1115 ts->source_port = source_port;
1116 ts->destination_port = destination_port;
1117 ts->heap_node = GNUNET_CONTAINER_heap_insert (channel_heap,
1119 GNUNET_TIME_absolute_get ().abs_value_us);
1120 GNUNET_assert (GNUNET_YES ==
1121 GNUNET_CONTAINER_multihashmap_put (channel_map,
1124 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
1125 GNUNET_STATISTICS_update (stats,
1126 gettext_noop ("# Active channels"),
1128 while (GNUNET_CONTAINER_multihashmap_size (channel_map) > max_channel_mappings)
1129 expire_channel (ts);
1134 GNUNET_CONTAINER_heap_update_cost (channel_heap,
1136 GNUNET_TIME_absolute_get ().abs_value_us);
1138 if (NULL == ts->channel)
1140 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1141 "Packet dropped, channel to %s not yet ready (%s)\n",
1142 print_channel_destination (&ts->destination),
1143 (NULL == ts->search)
1144 ? "EXIT search failed"
1145 : "EXIT search active");
1146 GNUNET_STATISTICS_update (stats,
1147 gettext_noop ("# Packets dropped (channel not yet online)"),
1153 /* send via channel */
1157 if (destination->is_service)
1159 struct GNUNET_EXIT_UdpServiceMessage *usm;
1161 mlen = sizeof (struct GNUNET_EXIT_UdpServiceMessage) +
1162 payload_length - sizeof (struct GNUNET_TUN_UdpHeader);
1163 if (mlen >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1168 tnq = GNUNET_malloc (sizeof (struct ChannelMessageQueueEntry) + mlen);
1171 usm = (struct GNUNET_EXIT_UdpServiceMessage *) &tnq[1];
1172 usm->header.size = htons ((uint16_t) mlen);
1173 usm->header.type = htons (GNUNET_MESSAGE_TYPE_VPN_UDP_TO_SERVICE);
1174 /* if the source port is below 32000, we assume it has a special
1175 meaning; if not, we pick a random port (this is a heuristic) */
1176 usm->source_port = (ntohs (udp->source_port) < 32000) ? udp->source_port : 0;
1177 usm->destination_port = udp->destination_port;
1178 usm->service_descriptor = destination->details.service_destination.service_descriptor;
1181 payload_length - sizeof (struct GNUNET_TUN_UdpHeader));
1185 struct GNUNET_EXIT_UdpInternetMessage *uim;
1186 struct in_addr *ip4dst;
1187 struct in6_addr *ip6dst;
1190 mlen = sizeof (struct GNUNET_EXIT_UdpInternetMessage) +
1191 alen + payload_length - sizeof (struct GNUNET_TUN_UdpHeader);
1192 if (mlen >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1197 tnq = GNUNET_malloc (sizeof (struct ChannelMessageQueueEntry) + mlen);
1200 uim = (struct GNUNET_EXIT_UdpInternetMessage *) &tnq[1];
1201 uim->header.size = htons ((uint16_t) mlen);
1202 uim->header.type = htons (GNUNET_MESSAGE_TYPE_VPN_UDP_TO_INTERNET);
1203 uim->af = htonl (destination->details.exit_destination.af);
1204 uim->source_port = (ntohs (udp->source_port) < 32000) ? udp->source_port : 0;
1205 uim->destination_port = udp->destination_port;
1206 switch (destination->details.exit_destination.af)
1209 ip4dst = (struct in_addr *) &uim[1];
1210 *ip4dst = destination->details.exit_destination.ip.v4;
1211 payload = &ip4dst[1];
1214 ip6dst = (struct in6_addr *) &uim[1];
1215 *ip6dst = destination->details.exit_destination.ip.v6;
1216 payload = &ip6dst[1];
1223 payload_length - sizeof (struct GNUNET_TUN_UdpHeader));
1229 if (destination->is_service)
1231 struct GNUNET_EXIT_TcpServiceStartMessage *tsm;
1233 mlen = sizeof (struct GNUNET_EXIT_TcpServiceStartMessage) +
1234 payload_length - sizeof (struct GNUNET_TUN_TcpHeader);
1235 if (mlen >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1240 tnq = GNUNET_malloc (sizeof (struct ChannelMessageQueueEntry) + mlen);
1243 tsm = (struct GNUNET_EXIT_TcpServiceStartMessage *) &tnq[1];
1244 tsm->header.size = htons ((uint16_t) mlen);
1245 tsm->header.type = htons (GNUNET_MESSAGE_TYPE_VPN_TCP_TO_SERVICE_START);
1246 tsm->reserved = htonl (0);
1247 tsm->service_descriptor = destination->details.service_destination.service_descriptor;
1248 tsm->tcp_header = *tcp;
1251 payload_length - sizeof (struct GNUNET_TUN_TcpHeader));
1255 struct GNUNET_EXIT_TcpInternetStartMessage *tim;
1256 struct in_addr *ip4dst;
1257 struct in6_addr *ip6dst;
1260 mlen = sizeof (struct GNUNET_EXIT_TcpInternetStartMessage) +
1261 alen + payload_length - sizeof (struct GNUNET_TUN_TcpHeader);
1262 if (mlen >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1267 tnq = GNUNET_malloc (sizeof (struct ChannelMessageQueueEntry) + mlen);
1270 tim = (struct GNUNET_EXIT_TcpInternetStartMessage *) &tnq[1];
1271 tim->header.size = htons ((uint16_t) mlen);
1272 tim->header.type = htons (GNUNET_MESSAGE_TYPE_VPN_TCP_TO_INTERNET_START);
1273 tim->af = htonl (destination->details.exit_destination.af);
1274 tim->tcp_header = *tcp;
1275 switch (destination->details.exit_destination.af)
1278 ip4dst = (struct in_addr *) &tim[1];
1279 *ip4dst = destination->details.exit_destination.ip.v4;
1280 payload = &ip4dst[1];
1283 ip6dst = (struct in6_addr *) &tim[1];
1284 *ip6dst = destination->details.exit_destination.ip.v6;
1285 payload = &ip6dst[1];
1292 payload_length - sizeof (struct GNUNET_TUN_TcpHeader));
1297 struct GNUNET_EXIT_TcpDataMessage *tdm;
1299 mlen = sizeof (struct GNUNET_EXIT_TcpDataMessage) +
1300 payload_length - sizeof (struct GNUNET_TUN_TcpHeader);
1301 if (mlen >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1306 tnq = GNUNET_malloc (sizeof (struct ChannelMessageQueueEntry) + mlen);
1309 tdm = (struct GNUNET_EXIT_TcpDataMessage *) &tnq[1];
1310 tdm->header.size = htons ((uint16_t) mlen);
1311 tdm->header.type = htons (GNUNET_MESSAGE_TYPE_VPN_TCP_DATA_TO_EXIT);
1312 tdm->reserved = htonl (0);
1313 tdm->tcp_header = *tcp;
1316 payload_length - sizeof (struct GNUNET_TUN_TcpHeader));
1320 case IPPROTO_ICMPV6:
1321 if (destination->is_service)
1323 struct GNUNET_EXIT_IcmpServiceMessage *ism;
1325 mlen = sizeof (struct GNUNET_EXIT_IcmpServiceMessage) +
1326 payload_length - sizeof (struct GNUNET_TUN_IcmpHeader);
1327 if (mlen >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1332 tnq = GNUNET_malloc (sizeof (struct ChannelMessageQueueEntry) + mlen);
1334 ism = (struct GNUNET_EXIT_IcmpServiceMessage *) &tnq[1];
1335 ism->header.type = htons (GNUNET_MESSAGE_TYPE_VPN_ICMP_TO_SERVICE);
1336 ism->af = htonl (af); /* need to tell destination ICMP protocol family! */
1337 ism->service_descriptor = destination->details.service_destination.service_descriptor;
1338 ism->icmp_header = *icmp;
1339 /* ICMP protocol translation will be done by the receiver (as we don't know
1340 the target AF); however, we still need to possibly discard the payload
1341 depending on the ICMP type */
1347 case GNUNET_TUN_ICMPTYPE_ECHO_REPLY:
1348 case GNUNET_TUN_ICMPTYPE_ECHO_REQUEST:
1350 case GNUNET_TUN_ICMPTYPE_DESTINATION_UNREACHABLE:
1351 case GNUNET_TUN_ICMPTYPE_SOURCE_QUENCH:
1352 case GNUNET_TUN_ICMPTYPE_TIME_EXCEEDED:
1353 /* throw away ICMP payload, won't be useful for the other side anyway */
1354 payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
1357 GNUNET_STATISTICS_update (stats,
1358 gettext_noop ("# ICMPv4 packets dropped (not allowed)"),
1362 /* end of AF_INET */
1367 case GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE:
1368 case GNUNET_TUN_ICMPTYPE6_PACKET_TOO_BIG:
1369 case GNUNET_TUN_ICMPTYPE6_TIME_EXCEEDED:
1370 case GNUNET_TUN_ICMPTYPE6_PARAMETER_PROBLEM:
1371 /* throw away ICMP payload, won't be useful for the other side anyway */
1372 payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
1374 case GNUNET_TUN_ICMPTYPE6_ECHO_REQUEST:
1375 case GNUNET_TUN_ICMPTYPE6_ECHO_REPLY:
1378 GNUNET_STATISTICS_update (stats,
1379 gettext_noop ("# ICMPv6 packets dropped (not allowed)"),
1383 /* end of AF_INET6 */
1390 /* update length calculations, as payload_length may have changed */
1391 mlen = sizeof (struct GNUNET_EXIT_IcmpServiceMessage) +
1392 alen + payload_length - sizeof (struct GNUNET_TUN_IcmpHeader);
1394 ism->header.size = htons ((uint16_t) mlen);
1395 /* finally, copy payload (if there is any left...) */
1398 payload_length - sizeof (struct GNUNET_TUN_IcmpHeader));
1402 struct GNUNET_EXIT_IcmpInternetMessage *iim;
1403 struct in_addr *ip4dst;
1404 struct in6_addr *ip6dst;
1407 mlen = sizeof (struct GNUNET_EXIT_IcmpInternetMessage) +
1408 alen + payload_length - sizeof (struct GNUNET_TUN_IcmpHeader);
1409 if (mlen >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1414 tnq = GNUNET_malloc (sizeof (struct ChannelMessageQueueEntry) + mlen);
1416 iim = (struct GNUNET_EXIT_IcmpInternetMessage *) &tnq[1];
1417 iim->header.type = htons (GNUNET_MESSAGE_TYPE_VPN_ICMP_TO_INTERNET);
1418 iim->icmp_header = *icmp;
1419 /* Perform ICMP protocol-translation (depending on destination AF and source AF)
1420 and throw away ICMP payload depending on ICMP message type */
1426 case GNUNET_TUN_ICMPTYPE_ECHO_REPLY:
1427 if (destination->details.exit_destination.af == AF_INET6)
1428 iim->icmp_header.type = GNUNET_TUN_ICMPTYPE6_ECHO_REPLY;
1430 case GNUNET_TUN_ICMPTYPE_ECHO_REQUEST:
1431 if (destination->details.exit_destination.af == AF_INET6)
1432 iim->icmp_header.type = GNUNET_TUN_ICMPTYPE6_ECHO_REQUEST;
1434 case GNUNET_TUN_ICMPTYPE_DESTINATION_UNREACHABLE:
1435 if (destination->details.exit_destination.af == AF_INET6)
1436 iim->icmp_header.type = GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE;
1437 /* throw away IP-payload, exit will have to make it up anyway */
1438 payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
1440 case GNUNET_TUN_ICMPTYPE_TIME_EXCEEDED:
1441 if (destination->details.exit_destination.af == AF_INET6)
1442 iim->icmp_header.type = GNUNET_TUN_ICMPTYPE6_TIME_EXCEEDED;
1443 /* throw away IP-payload, exit will have to make it up anyway */
1444 payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
1446 case GNUNET_TUN_ICMPTYPE_SOURCE_QUENCH:
1447 if (destination->details.exit_destination.af == AF_INET6)
1449 GNUNET_STATISTICS_update (stats,
1450 gettext_noop ("# ICMPv4 packets dropped (impossible PT to v6)"),
1455 /* throw away IP-payload, exit will have to make it up anyway */
1456 payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
1459 GNUNET_STATISTICS_update (stats,
1460 gettext_noop ("# ICMPv4 packets dropped (type not allowed)"),
1465 /* end of AF_INET */
1470 case GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE:
1471 if (destination->details.exit_destination.af == AF_INET6)
1472 iim->icmp_header.type = GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE;
1473 /* throw away IP-payload, exit will have to make it up anyway */
1474 payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
1476 case GNUNET_TUN_ICMPTYPE6_TIME_EXCEEDED:
1477 if (destination->details.exit_destination.af == AF_INET)
1478 iim->icmp_header.type = GNUNET_TUN_ICMPTYPE_TIME_EXCEEDED;
1479 /* throw away IP-payload, exit will have to make it up anyway */
1480 payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
1482 case GNUNET_TUN_ICMPTYPE6_PACKET_TOO_BIG:
1483 if (destination->details.exit_destination.af == AF_INET)
1485 GNUNET_STATISTICS_update (stats,
1486 gettext_noop ("# ICMPv6 packets dropped (impossible PT to v4)"),
1491 /* throw away IP-payload, exit will have to make it up anyway */
1492 payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
1494 case GNUNET_TUN_ICMPTYPE6_PARAMETER_PROBLEM:
1495 if (destination->details.exit_destination.af == AF_INET)
1497 GNUNET_STATISTICS_update (stats,
1498 gettext_noop ("# ICMPv6 packets dropped (impossible PT to v4)"),
1503 /* throw away IP-payload, exit will have to make it up anyway */
1504 payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
1506 case GNUNET_TUN_ICMPTYPE6_ECHO_REQUEST:
1507 if (destination->details.exit_destination.af == AF_INET)
1508 iim->icmp_header.type = GNUNET_TUN_ICMPTYPE_ECHO_REQUEST;
1510 case GNUNET_TUN_ICMPTYPE6_ECHO_REPLY:
1511 if (destination->details.exit_destination.af == AF_INET)
1512 iim->icmp_header.type = GNUNET_TUN_ICMPTYPE_ECHO_REPLY;
1515 GNUNET_STATISTICS_update (stats,
1516 gettext_noop ("# ICMPv6 packets dropped (type not allowed)"),
1521 /* end of AF_INET6 */
1526 /* update length calculations, as payload_length may have changed */
1527 mlen = sizeof (struct GNUNET_EXIT_IcmpInternetMessage) +
1528 alen + payload_length - sizeof (struct GNUNET_TUN_IcmpHeader);
1530 iim->header.size = htons ((uint16_t) mlen);
1532 /* need to tell destination ICMP protocol family! */
1533 iim->af = htonl (destination->details.exit_destination.af);
1534 switch (destination->details.exit_destination.af)
1537 ip4dst = (struct in_addr *) &iim[1];
1538 *ip4dst = destination->details.exit_destination.ip.v4;
1539 payload = &ip4dst[1];
1542 ip6dst = (struct in6_addr *) &iim[1];
1543 *ip6dst = destination->details.exit_destination.ip.v6;
1544 payload = &ip6dst[1];
1551 payload_length - sizeof (struct GNUNET_TUN_IcmpHeader));
1555 /* not supported above, how can we get here !? */
1559 send_to_channel (tnq, ts);
1564 * Receive packets from the helper-process (someone send to the local
1565 * virtual channel interface). Find the destination mapping, and if it
1566 * exists, identify the correct CADET channel (or possibly create it)
1567 * and forward the packet.
1569 * @param cls closure, NULL
1570 * @param client NULL
1571 * @param message message we got from the client (VPN channel interface)
1574 message_token (void *cls,
1576 const struct GNUNET_MessageHeader *message)
1578 const struct GNUNET_TUN_Layer2PacketHeader *tun;
1580 struct GNUNET_HashCode key;
1581 struct DestinationEntry *de;
1583 GNUNET_STATISTICS_update (stats,
1584 gettext_noop ("# Packets received from TUN interface"),
1586 mlen = ntohs (message->size);
1587 if ( (ntohs (message->type) != GNUNET_MESSAGE_TYPE_VPN_HELPER) ||
1588 (mlen < sizeof (struct GNUNET_MessageHeader) + sizeof (struct GNUNET_TUN_Layer2PacketHeader)) )
1593 tun = (const struct GNUNET_TUN_Layer2PacketHeader *) &message[1];
1594 mlen -= (sizeof (struct GNUNET_MessageHeader) + sizeof (struct GNUNET_TUN_Layer2PacketHeader));
1595 switch (ntohs (tun->proto))
1599 const struct GNUNET_TUN_IPv6Header *pkt6;
1601 if (mlen < sizeof (struct GNUNET_TUN_IPv6Header))
1607 pkt6 = (const struct GNUNET_TUN_IPv6Header *) &tun[1];
1608 get_destination_key_from_ip (AF_INET6,
1609 &pkt6->destination_address,
1611 de = GNUNET_CONTAINER_multihashmap_get (destination_map, &key);
1614 char buf[INET6_ADDRSTRLEN];
1616 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1617 _("Packet received for unmapped destination `%s' (dropping it)\n"),
1618 inet_ntop (AF_INET6,
1619 &pkt6->destination_address,
1627 &pkt6->source_address,
1628 &pkt6->destination_address,
1630 mlen - sizeof (struct GNUNET_TUN_IPv6Header));
1635 struct GNUNET_TUN_IPv4Header *pkt4;
1637 if (mlen < sizeof (struct GNUNET_TUN_IPv4Header))
1643 pkt4 = (struct GNUNET_TUN_IPv4Header *) &tun[1];
1644 get_destination_key_from_ip (AF_INET,
1645 &pkt4->destination_address,
1647 de = GNUNET_CONTAINER_multihashmap_get (destination_map, &key);
1650 char buf[INET_ADDRSTRLEN];
1652 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1653 _("Packet received for unmapped destination `%s' (dropping it)\n"),
1655 &pkt4->destination_address,
1660 if (pkt4->header_length * 4 != sizeof (struct GNUNET_TUN_IPv4Header))
1662 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1663 _("Received IPv4 packet with options (dropping it)\n"));
1669 &pkt4->source_address,
1670 &pkt4->destination_address,
1672 mlen - sizeof (struct GNUNET_TUN_IPv4Header));
1676 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1677 _("Received packet of unknown protocol %d from TUN (dropping it)\n"),
1678 (unsigned int) ntohs (tun->proto));
1686 * Synthesize a plausible ICMP payload for an ICMP error
1687 * response on the given channel.
1689 * @param ts channel information
1690 * @param ipp IPv4 header to fill in (ICMP payload)
1691 * @param udp "UDP" header to fill in (ICMP payload); might actually
1692 * also be the first 8 bytes of the TCP header
1695 make_up_icmpv4_payload (struct ChannelState *ts,
1696 struct GNUNET_TUN_IPv4Header *ipp,
1697 struct GNUNET_TUN_UdpHeader *udp)
1699 GNUNET_TUN_initialize_ipv4_header (ipp,
1701 sizeof (struct GNUNET_TUN_TcpHeader),
1703 &ts->destination_ip.v4);
1704 udp->source_port = htons (ts->source_port);
1705 udp->destination_port = htons (ts->destination_port);
1706 udp->len = htons (0);
1707 udp->crc = htons (0);
1712 * Synthesize a plausible ICMP payload for an ICMP error
1713 * response on the given channel.
1715 * @param ts channel information
1716 * @param ipp IPv6 header to fill in (ICMP payload)
1717 * @param udp "UDP" header to fill in (ICMP payload); might actually
1718 * also be the first 8 bytes of the TCP header
1721 make_up_icmpv6_payload (struct ChannelState *ts,
1722 struct GNUNET_TUN_IPv6Header *ipp,
1723 struct GNUNET_TUN_UdpHeader *udp)
1725 GNUNET_TUN_initialize_ipv6_header (ipp,
1727 sizeof (struct GNUNET_TUN_TcpHeader),
1729 &ts->destination_ip.v6);
1730 udp->source_port = htons (ts->source_port);
1731 udp->destination_port = htons (ts->destination_port);
1732 udp->len = htons (0);
1733 udp->crc = htons (0);
1738 * We got an ICMP packet back from the CADET channel. Pass it on to the
1739 * local virtual interface via the helper.
1741 * @param cls closure, NULL
1742 * @param channel connection to the other end
1743 * @param channel_ctx pointer to our 'struct ChannelState *'
1744 * @param message the actual message
1745 * @return #GNUNET_OK to keep the connection open,
1746 * #GNUNET_SYSERR to close it (signal serious error)
1749 receive_icmp_back (void *cls,
1750 struct GNUNET_CADET_Channel *channel,
1752 const struct GNUNET_MessageHeader *message)
1754 struct ChannelState *ts = *channel_ctx;
1755 const struct GNUNET_EXIT_IcmpToVPNMessage *i2v;
1758 GNUNET_STATISTICS_update (stats,
1759 gettext_noop ("# ICMP packets received from cadet"),
1761 mlen = ntohs (message->size);
1762 if (mlen < sizeof (struct GNUNET_EXIT_IcmpToVPNMessage))
1764 GNUNET_break_op (0);
1765 return GNUNET_SYSERR;
1767 if (NULL == ts->heap_node)
1769 GNUNET_break_op (0);
1770 return GNUNET_SYSERR;
1772 if (AF_UNSPEC == ts->af)
1774 GNUNET_break_op (0);
1775 return GNUNET_SYSERR;
1777 i2v = (const struct GNUNET_EXIT_IcmpToVPNMessage *) message;
1778 mlen -= sizeof (struct GNUNET_EXIT_IcmpToVPNMessage);
1780 char sbuf[INET6_ADDRSTRLEN];
1781 char dbuf[INET6_ADDRSTRLEN];
1783 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1784 "Received ICMP packet from cadet, sending %u bytes from %s -> %s via TUN\n",
1785 (unsigned int) mlen,
1786 inet_ntop (ts->af, &ts->destination_ip, sbuf, sizeof (sbuf)),
1787 inet_ntop (ts->af, &ts->source_ip, dbuf, sizeof (dbuf)));
1793 size_t size = sizeof (struct GNUNET_TUN_IPv4Header)
1794 + sizeof (struct GNUNET_TUN_IcmpHeader)
1795 + sizeof (struct GNUNET_MessageHeader) +
1796 sizeof (struct GNUNET_TUN_Layer2PacketHeader) +
1799 /* reserve some extra space in case we have an ICMP type here where
1800 we will need to make up the payload ourselves */
1801 char buf[size + sizeof (struct GNUNET_TUN_IPv4Header) + 8] GNUNET_ALIGN;
1802 struct GNUNET_MessageHeader *msg = (struct GNUNET_MessageHeader *) buf;
1803 struct GNUNET_TUN_Layer2PacketHeader *tun = (struct GNUNET_TUN_Layer2PacketHeader*) &msg[1];
1804 struct GNUNET_TUN_IPv4Header *ipv4 = (struct GNUNET_TUN_IPv4Header *) &tun[1];
1805 struct GNUNET_TUN_IcmpHeader *icmp = (struct GNUNET_TUN_IcmpHeader *) &ipv4[1];
1806 msg->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
1807 tun->flags = htons (0);
1808 tun->proto = htons (ETH_P_IPV4);
1809 GNUNET_TUN_initialize_ipv4_header (ipv4,
1811 sizeof (struct GNUNET_TUN_IcmpHeader) + mlen,
1812 &ts->destination_ip.v4,
1814 *icmp = i2v->icmp_header;
1818 /* For some ICMP types, we need to adjust (make up) the payload here.
1819 Also, depending on the AF used on the other side, we have to
1820 do ICMP PT (translate ICMP types) */
1821 switch (ntohl (i2v->af))
1826 case GNUNET_TUN_ICMPTYPE_ECHO_REPLY:
1827 case GNUNET_TUN_ICMPTYPE_ECHO_REQUEST:
1829 case GNUNET_TUN_ICMPTYPE_DESTINATION_UNREACHABLE:
1830 case GNUNET_TUN_ICMPTYPE_SOURCE_QUENCH:
1831 case GNUNET_TUN_ICMPTYPE_TIME_EXCEEDED:
1833 struct GNUNET_TUN_IPv4Header *ipp = (struct GNUNET_TUN_IPv4Header *) &icmp[1];
1834 struct GNUNET_TUN_UdpHeader *udp = (struct GNUNET_TUN_UdpHeader *) &ipp[1];
1838 /* sender did not strip ICMP payload? */
1839 GNUNET_break_op (0);
1840 return GNUNET_SYSERR;
1842 size += sizeof (struct GNUNET_TUN_IPv4Header) + 8;
1843 GNUNET_assert (8 == sizeof (struct GNUNET_TUN_UdpHeader));
1844 make_up_icmpv4_payload (ts, ipp, udp);
1848 GNUNET_break_op (0);
1849 GNUNET_STATISTICS_update (stats,
1850 gettext_noop ("# ICMPv4 packets dropped (type not allowed)"),
1852 return GNUNET_SYSERR;
1857 /* ICMP PT 6-to-4 and possibly making up payloads */
1860 case GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE:
1861 icmp->type = GNUNET_TUN_ICMPTYPE_DESTINATION_UNREACHABLE;
1863 struct GNUNET_TUN_IPv4Header *ipp = (struct GNUNET_TUN_IPv4Header *) &icmp[1];
1864 struct GNUNET_TUN_UdpHeader *udp = (struct GNUNET_TUN_UdpHeader *) &ipp[1];
1868 /* sender did not strip ICMP payload? */
1869 GNUNET_break_op (0);
1870 return GNUNET_SYSERR;
1872 size += sizeof (struct GNUNET_TUN_IPv4Header) + 8;
1873 GNUNET_assert (8 == sizeof (struct GNUNET_TUN_UdpHeader));
1874 make_up_icmpv4_payload (ts, ipp, udp);
1877 case GNUNET_TUN_ICMPTYPE6_TIME_EXCEEDED:
1878 icmp->type = GNUNET_TUN_ICMPTYPE_TIME_EXCEEDED;
1880 struct GNUNET_TUN_IPv4Header *ipp = (struct GNUNET_TUN_IPv4Header *) &icmp[1];
1881 struct GNUNET_TUN_UdpHeader *udp = (struct GNUNET_TUN_UdpHeader *) &ipp[1];
1885 /* sender did not strip ICMP payload? */
1886 GNUNET_break_op (0);
1887 return GNUNET_SYSERR;
1889 size += sizeof (struct GNUNET_TUN_IPv4Header) + 8;
1890 GNUNET_assert (8 == sizeof (struct GNUNET_TUN_UdpHeader));
1891 make_up_icmpv4_payload (ts, ipp, udp);
1894 case GNUNET_TUN_ICMPTYPE6_PACKET_TOO_BIG:
1895 case GNUNET_TUN_ICMPTYPE6_PARAMETER_PROBLEM:
1896 GNUNET_STATISTICS_update (stats,
1897 gettext_noop ("# ICMPv6 packets dropped (impossible PT to v4)"),
1900 case GNUNET_TUN_ICMPTYPE6_ECHO_REQUEST:
1901 icmp->type = GNUNET_TUN_ICMPTYPE_ECHO_REQUEST;
1903 case GNUNET_TUN_ICMPTYPE6_ECHO_REPLY:
1904 icmp->type = GNUNET_TUN_ICMPTYPE_ECHO_REPLY;
1907 GNUNET_break_op (0);
1908 GNUNET_STATISTICS_update (stats,
1909 gettext_noop ("# ICMPv6 packets dropped (type not allowed)"),
1911 return GNUNET_SYSERR;
1916 GNUNET_break_op (0);
1917 return GNUNET_SYSERR;
1919 msg->size = htons (size);
1920 GNUNET_TUN_calculate_icmp_checksum (icmp,
1923 (void) GNUNET_HELPER_send (helper_handle,
1932 size_t size = sizeof (struct GNUNET_TUN_IPv6Header)
1933 + sizeof (struct GNUNET_TUN_IcmpHeader)
1934 + sizeof (struct GNUNET_MessageHeader) +
1935 sizeof (struct GNUNET_TUN_Layer2PacketHeader) +
1938 char buf[size + sizeof (struct GNUNET_TUN_IPv6Header) + 8] GNUNET_ALIGN;
1939 struct GNUNET_MessageHeader *msg = (struct GNUNET_MessageHeader *) buf;
1940 struct GNUNET_TUN_Layer2PacketHeader *tun = (struct GNUNET_TUN_Layer2PacketHeader*) &msg[1];
1941 struct GNUNET_TUN_IPv6Header *ipv6 = (struct GNUNET_TUN_IPv6Header *) &tun[1];
1942 struct GNUNET_TUN_IcmpHeader *icmp = (struct GNUNET_TUN_IcmpHeader *) &ipv6[1];
1943 msg->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
1944 tun->flags = htons (0);
1945 tun->proto = htons (ETH_P_IPV6);
1946 GNUNET_TUN_initialize_ipv6_header (ipv6,
1948 sizeof (struct GNUNET_TUN_IcmpHeader) + mlen,
1949 &ts->destination_ip.v6,
1951 *icmp = i2v->icmp_header;
1956 /* For some ICMP types, we need to adjust (make up) the payload here.
1957 Also, depending on the AF used on the other side, we have to
1958 do ICMP PT (translate ICMP types) */
1959 switch (ntohl (i2v->af))
1962 /* ICMP PT 4-to-6 and possibly making up payloads */
1965 case GNUNET_TUN_ICMPTYPE_ECHO_REPLY:
1966 icmp->type = GNUNET_TUN_ICMPTYPE6_ECHO_REPLY;
1968 case GNUNET_TUN_ICMPTYPE_ECHO_REQUEST:
1969 icmp->type = GNUNET_TUN_ICMPTYPE6_ECHO_REQUEST;
1971 case GNUNET_TUN_ICMPTYPE_DESTINATION_UNREACHABLE:
1972 icmp->type = GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE;
1974 struct GNUNET_TUN_IPv6Header *ipp = (struct GNUNET_TUN_IPv6Header *) &icmp[1];
1975 struct GNUNET_TUN_UdpHeader *udp = (struct GNUNET_TUN_UdpHeader *) &ipp[1];
1979 /* sender did not strip ICMP payload? */
1980 GNUNET_break_op (0);
1981 return GNUNET_SYSERR;
1983 size += sizeof (struct GNUNET_TUN_IPv6Header) + 8;
1984 GNUNET_assert (8 == sizeof (struct GNUNET_TUN_UdpHeader));
1985 make_up_icmpv6_payload (ts, ipp, udp);
1988 case GNUNET_TUN_ICMPTYPE_TIME_EXCEEDED:
1989 icmp->type = GNUNET_TUN_ICMPTYPE6_TIME_EXCEEDED;
1991 struct GNUNET_TUN_IPv6Header *ipp = (struct GNUNET_TUN_IPv6Header *) &icmp[1];
1992 struct GNUNET_TUN_UdpHeader *udp = (struct GNUNET_TUN_UdpHeader *) &ipp[1];
1996 /* sender did not strip ICMP payload? */
1997 GNUNET_break_op (0);
1998 return GNUNET_SYSERR;
2000 size += sizeof (struct GNUNET_TUN_IPv6Header) + 8;
2001 GNUNET_assert (8 == sizeof (struct GNUNET_TUN_UdpHeader));
2002 make_up_icmpv6_payload (ts, ipp, udp);
2005 case GNUNET_TUN_ICMPTYPE_SOURCE_QUENCH:
2006 GNUNET_STATISTICS_update (stats,
2007 gettext_noop ("# ICMPv4 packets dropped (impossible PT to v6)"),
2011 GNUNET_break_op (0);
2012 GNUNET_STATISTICS_update (stats,
2013 gettext_noop ("# ICMPv4 packets dropped (type not allowed)"),
2015 return GNUNET_SYSERR;
2022 case GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE:
2023 case GNUNET_TUN_ICMPTYPE6_TIME_EXCEEDED:
2024 case GNUNET_TUN_ICMPTYPE6_PACKET_TOO_BIG:
2025 case GNUNET_TUN_ICMPTYPE6_PARAMETER_PROBLEM:
2027 struct GNUNET_TUN_IPv6Header *ipp = (struct GNUNET_TUN_IPv6Header *) &icmp[1];
2028 struct GNUNET_TUN_UdpHeader *udp = (struct GNUNET_TUN_UdpHeader *) &ipp[1];
2032 /* sender did not strip ICMP payload? */
2033 GNUNET_break_op (0);
2034 return GNUNET_SYSERR;
2036 size += sizeof (struct GNUNET_TUN_IPv6Header) + 8;
2037 GNUNET_assert (8 == sizeof (struct GNUNET_TUN_UdpHeader));
2038 make_up_icmpv6_payload (ts, ipp, udp);
2041 case GNUNET_TUN_ICMPTYPE6_ECHO_REQUEST:
2044 GNUNET_break_op (0);
2045 GNUNET_STATISTICS_update (stats,
2046 gettext_noop ("# ICMPv6 packets dropped (type not allowed)"),
2048 return GNUNET_SYSERR;
2053 GNUNET_break_op (0);
2054 return GNUNET_SYSERR;
2056 msg->size = htons (size);
2057 GNUNET_TUN_calculate_icmp_checksum (icmp,
2059 (void) GNUNET_HELPER_send (helper_handle,
2069 GNUNET_CONTAINER_heap_update_cost (channel_heap,
2071 GNUNET_TIME_absolute_get ().abs_value_us);
2077 * We got a UDP packet back from the CADET channel. Pass it on to the
2078 * local virtual interface via the helper.
2080 * @param cls closure, NULL
2081 * @param channel connection to the other end
2082 * @param channel_ctx pointer to our 'struct ChannelState *'
2083 * @param message the actual message
2084 * @return #GNUNET_OK to keep the connection open,
2085 * #GNUNET_SYSERR to close it (signal serious error)
2088 receive_udp_back (void *cls,
2089 struct GNUNET_CADET_Channel *channel,
2091 const struct GNUNET_MessageHeader *message)
2093 struct ChannelState *ts = *channel_ctx;
2094 const struct GNUNET_EXIT_UdpReplyMessage *reply;
2097 GNUNET_STATISTICS_update (stats,
2098 gettext_noop ("# UDP packets received from cadet"),
2100 mlen = ntohs (message->size);
2101 if (mlen < sizeof (struct GNUNET_EXIT_UdpReplyMessage))
2103 GNUNET_break_op (0);
2104 return GNUNET_SYSERR;
2106 if (NULL == ts->heap_node)
2108 GNUNET_break_op (0);
2109 return GNUNET_SYSERR;
2111 if (AF_UNSPEC == ts->af)
2113 GNUNET_break_op (0);
2114 return GNUNET_SYSERR;
2116 reply = (const struct GNUNET_EXIT_UdpReplyMessage *) message;
2117 mlen -= sizeof (struct GNUNET_EXIT_UdpReplyMessage);
2119 char sbuf[INET6_ADDRSTRLEN];
2120 char dbuf[INET6_ADDRSTRLEN];
2122 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2123 "Received UDP reply from cadet, sending %u bytes from %s:%u -> %s:%u via TUN\n",
2124 (unsigned int) mlen,
2125 inet_ntop (ts->af, &ts->destination_ip, sbuf, sizeof (sbuf)),
2126 ts->destination_port,
2127 inet_ntop (ts->af, &ts->source_ip, dbuf, sizeof (dbuf)),
2134 size_t size = sizeof (struct GNUNET_TUN_IPv4Header)
2135 + sizeof (struct GNUNET_TUN_UdpHeader)
2136 + sizeof (struct GNUNET_MessageHeader) +
2137 sizeof (struct GNUNET_TUN_Layer2PacketHeader) +
2140 char buf[size] GNUNET_ALIGN;
2141 struct GNUNET_MessageHeader *msg = (struct GNUNET_MessageHeader *) buf;
2142 struct GNUNET_TUN_Layer2PacketHeader *tun = (struct GNUNET_TUN_Layer2PacketHeader*) &msg[1];
2143 struct GNUNET_TUN_IPv4Header *ipv4 = (struct GNUNET_TUN_IPv4Header *) &tun[1];
2144 struct GNUNET_TUN_UdpHeader *udp = (struct GNUNET_TUN_UdpHeader *) &ipv4[1];
2145 msg->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
2146 msg->size = htons (size);
2147 tun->flags = htons (0);
2148 tun->proto = htons (ETH_P_IPV4);
2149 GNUNET_TUN_initialize_ipv4_header (ipv4,
2151 sizeof (struct GNUNET_TUN_UdpHeader) + mlen,
2152 &ts->destination_ip.v4,
2154 if (0 == ntohs (reply->source_port))
2155 udp->source_port = htons (ts->destination_port);
2157 udp->source_port = reply->source_port;
2158 if (0 == ntohs (reply->destination_port))
2159 udp->destination_port = htons (ts->source_port);
2161 udp->destination_port = reply->destination_port;
2162 udp->len = htons (mlen + sizeof (struct GNUNET_TUN_UdpHeader));
2163 GNUNET_TUN_calculate_udp4_checksum (ipv4,
2170 (void) GNUNET_HELPER_send (helper_handle,
2179 size_t size = sizeof (struct GNUNET_TUN_IPv6Header)
2180 + sizeof (struct GNUNET_TUN_UdpHeader)
2181 + sizeof (struct GNUNET_MessageHeader) +
2182 sizeof (struct GNUNET_TUN_Layer2PacketHeader) +
2185 char buf[size] GNUNET_ALIGN;
2186 struct GNUNET_MessageHeader *msg = (struct GNUNET_MessageHeader *) buf;
2187 struct GNUNET_TUN_Layer2PacketHeader *tun = (struct GNUNET_TUN_Layer2PacketHeader*) &msg[1];
2188 struct GNUNET_TUN_IPv6Header *ipv6 = (struct GNUNET_TUN_IPv6Header *) &tun[1];
2189 struct GNUNET_TUN_UdpHeader *udp = (struct GNUNET_TUN_UdpHeader *) &ipv6[1];
2190 msg->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
2191 msg->size = htons (size);
2192 tun->flags = htons (0);
2193 tun->proto = htons (ETH_P_IPV6);
2194 GNUNET_TUN_initialize_ipv6_header (ipv6,
2196 sizeof (struct GNUNET_TUN_UdpHeader) + mlen,
2197 &ts->destination_ip.v6,
2199 if (0 == ntohs (reply->source_port))
2200 udp->source_port = htons (ts->destination_port);
2202 udp->source_port = reply->source_port;
2203 if (0 == ntohs (reply->destination_port))
2204 udp->destination_port = htons (ts->source_port);
2206 udp->destination_port = reply->destination_port;
2207 udp->len = htons (mlen + sizeof (struct GNUNET_TUN_UdpHeader));
2208 GNUNET_TUN_calculate_udp6_checksum (ipv6,
2214 (void) GNUNET_HELPER_send (helper_handle,
2224 GNUNET_CONTAINER_heap_update_cost (channel_heap,
2226 GNUNET_TIME_absolute_get ().abs_value_us);
2232 * We got a TCP packet back from the CADET channel. Pass it on to the
2233 * local virtual interface via the helper.
2235 * @param cls closure, NULL
2236 * @param channel connection to the other end
2237 * @param channel_ctx pointer to our `struct ChannelState *`
2238 * @param message the actual message
2239 * @return #GNUNET_OK to keep the connection open,
2240 * #GNUNET_SYSERR to close it (signal serious error)
2243 receive_tcp_back (void *cls,
2244 struct GNUNET_CADET_Channel *channel,
2246 const struct GNUNET_MessageHeader *message)
2248 struct ChannelState *ts = *channel_ctx;
2249 const struct GNUNET_EXIT_TcpDataMessage *data;
2252 GNUNET_STATISTICS_update (stats,
2253 gettext_noop ("# TCP packets received from cadet"),
2255 mlen = ntohs (message->size);
2256 if (mlen < sizeof (struct GNUNET_EXIT_TcpDataMessage))
2258 GNUNET_break_op (0);
2259 return GNUNET_SYSERR;
2261 if (NULL == ts->heap_node)
2263 GNUNET_break_op (0);
2264 return GNUNET_SYSERR;
2266 data = (const struct GNUNET_EXIT_TcpDataMessage *) message;
2267 mlen -= sizeof (struct GNUNET_EXIT_TcpDataMessage);
2269 char sbuf[INET6_ADDRSTRLEN];
2270 char dbuf[INET6_ADDRSTRLEN];
2272 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2273 "Received TCP reply from cadet, sending %u bytes from %s:%u -> %s:%u via TUN\n",
2274 (unsigned int) mlen,
2275 inet_ntop (ts->af, &ts->destination_ip, sbuf, sizeof (sbuf)),
2276 ts->destination_port,
2277 inet_ntop (ts->af, &ts->source_ip, dbuf, sizeof (dbuf)),
2280 if (data->tcp_header.off * 4 < sizeof (struct GNUNET_TUN_TcpHeader))
2282 GNUNET_break_op (0);
2283 return GNUNET_SYSERR;
2289 size_t size = sizeof (struct GNUNET_TUN_IPv4Header)
2290 + sizeof (struct GNUNET_TUN_TcpHeader)
2291 + sizeof (struct GNUNET_MessageHeader) +
2292 sizeof (struct GNUNET_TUN_Layer2PacketHeader) +
2295 char buf[size] GNUNET_ALIGN;
2296 struct GNUNET_MessageHeader *msg = (struct GNUNET_MessageHeader *) buf;
2297 struct GNUNET_TUN_Layer2PacketHeader *tun = (struct GNUNET_TUN_Layer2PacketHeader*) &msg[1];
2298 struct GNUNET_TUN_IPv4Header *ipv4 = (struct GNUNET_TUN_IPv4Header *) &tun[1];
2299 struct GNUNET_TUN_TcpHeader *tcp = (struct GNUNET_TUN_TcpHeader *) &ipv4[1];
2300 msg->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
2301 msg->size = htons (size);
2302 tun->flags = htons (0);
2303 tun->proto = htons (ETH_P_IPV4);
2304 GNUNET_TUN_initialize_ipv4_header (ipv4,
2306 sizeof (struct GNUNET_TUN_TcpHeader) + mlen,
2307 &ts->destination_ip.v4,
2309 *tcp = data->tcp_header;
2310 tcp->source_port = htons (ts->destination_port);
2311 tcp->destination_port = htons (ts->source_port);
2312 GNUNET_TUN_calculate_tcp4_checksum (ipv4,
2319 (void) GNUNET_HELPER_send (helper_handle,
2328 size_t size = sizeof (struct GNUNET_TUN_IPv6Header)
2329 + sizeof (struct GNUNET_TUN_TcpHeader)
2330 + sizeof (struct GNUNET_MessageHeader) +
2331 sizeof (struct GNUNET_TUN_Layer2PacketHeader) +
2334 char buf[size] GNUNET_ALIGN;
2335 struct GNUNET_MessageHeader *msg = (struct GNUNET_MessageHeader *) buf;
2336 struct GNUNET_TUN_Layer2PacketHeader *tun = (struct GNUNET_TUN_Layer2PacketHeader*) &msg[1];
2337 struct GNUNET_TUN_IPv6Header *ipv6 = (struct GNUNET_TUN_IPv6Header *) &tun[1];
2338 struct GNUNET_TUN_TcpHeader *tcp = (struct GNUNET_TUN_TcpHeader *) &ipv6[1];
2339 msg->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
2340 msg->size = htons (size);
2341 tun->flags = htons (0);
2342 tun->proto = htons (ETH_P_IPV6);
2343 GNUNET_TUN_initialize_ipv6_header (ipv6,
2345 sizeof (struct GNUNET_TUN_TcpHeader) + mlen,
2346 &ts->destination_ip.v6,
2348 *tcp = data->tcp_header;
2349 tcp->source_port = htons (ts->destination_port);
2350 tcp->destination_port = htons (ts->source_port);
2351 GNUNET_TUN_calculate_tcp6_checksum (ipv6,
2358 (void) GNUNET_HELPER_send (helper_handle,
2366 GNUNET_CONTAINER_heap_update_cost (channel_heap,
2368 GNUNET_TIME_absolute_get ().abs_value_us);
2374 * Allocate an IPv4 address from the range of the channel
2375 * for a new redirection.
2377 * @param v4 where to store the address
2378 * @return #GNUNET_OK on success,
2379 * #GNUNET_SYSERR on error
2382 allocate_v4_address (struct in_addr *v4)
2384 const char *ipv4addr = vpn_argv[4];
2385 const char *ipv4mask = vpn_argv[5];
2386 struct in_addr addr;
2387 struct in_addr mask;
2389 struct GNUNET_HashCode key;
2392 GNUNET_assert (1 == inet_pton (AF_INET, ipv4addr, &addr));
2393 GNUNET_assert (1 == inet_pton (AF_INET, ipv4mask, &mask));
2394 /* Given 192.168.0.1/255.255.0.0, we want a mask
2395 of '192.168.255.255', thus: */
2396 mask.s_addr = addr.s_addr | ~mask.s_addr;
2403 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
2404 _("Failed to find unallocated IPv4 address in VPN's range\n"));
2405 return GNUNET_SYSERR;
2407 /* Pick random IPv4 address within the subnet, except 'addr' or 'mask' itself */
2408 rnd.s_addr = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
2410 v4->s_addr = (addr.s_addr | rnd.s_addr) & mask.s_addr;
2411 get_destination_key_from_ip (AF_INET,
2415 while ( (GNUNET_YES ==
2416 GNUNET_CONTAINER_multihashmap_contains (destination_map,
2418 (v4->s_addr == addr.s_addr) ||
2419 (v4->s_addr == mask.s_addr) );
2425 * Allocate an IPv6 address from the range of the channel
2426 * for a new redirection.
2428 * @param v6 where to store the address
2429 * @return #GNUNET_OK on success,
2430 * #GNUNET_SYSERR on error
2433 allocate_v6_address (struct in6_addr *v6)
2435 const char *ipv6addr = vpn_argv[2];
2436 struct in6_addr addr;
2437 struct in6_addr mask;
2438 struct in6_addr rnd;
2440 struct GNUNET_HashCode key;
2443 GNUNET_assert (1 == inet_pton (AF_INET6, ipv6addr, &addr));
2444 GNUNET_assert (ipv6prefix < 128);
2445 /* Given ABCD::/96, we want a mask of 'ABCD::FFFF:FFFF,
2448 for (i=127;i>=ipv6prefix;i--)
2449 mask.s6_addr[i / 8] |= (1 << (i % 8));
2451 /* Pick random IPv6 address within the subnet, except 'addr' or 'mask' itself */
2458 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
2459 _("Failed to find unallocated IPv6 address in VPN's range\n"));
2460 return GNUNET_SYSERR;
2465 rnd.s6_addr[i] = (unsigned char) GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
2468 = (addr.s6_addr[i] | rnd.s6_addr[i]) & mask.s6_addr[i];
2470 get_destination_key_from_ip (AF_INET6,
2474 while ( (GNUNET_YES ==
2475 GNUNET_CONTAINER_multihashmap_contains (destination_map,
2479 sizeof (struct in6_addr))) ||
2482 sizeof (struct in6_addr))) );
2488 * Free resources occupied by a destination entry.
2490 * @param de entry to free
2493 free_destination_entry (struct DestinationEntry *de)
2495 struct DestinationChannel *dt;
2497 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2498 "Cleaning up destination entry\n");
2499 GNUNET_STATISTICS_update (stats,
2500 gettext_noop ("# Active destinations"),
2502 while (NULL != (dt = de->dt_head))
2504 GNUNET_CONTAINER_DLL_remove (de->dt_head,
2509 free_channel_state (dt->ts);
2510 GNUNET_assert (NULL == dt->ts);
2514 if (NULL != de->heap_node)
2516 GNUNET_CONTAINER_heap_remove_node (de->heap_node);
2517 de->heap_node = NULL;
2518 GNUNET_assert (GNUNET_YES ==
2519 GNUNET_CONTAINER_multihashmap_remove (destination_map,
2528 * We have too many active destinations. Clean up the oldest destination.
2530 * @param except destination that must NOT be cleaned up, even if it is the oldest
2533 expire_destination (struct DestinationEntry *except)
2535 struct DestinationEntry *de;
2537 de = GNUNET_CONTAINER_heap_peek (destination_heap);
2538 GNUNET_assert (NULL != de);
2540 return; /* can't do this */
2541 free_destination_entry (de);
2546 * Allocate an IP address for the response.
2548 * @param result_af desired address family; set to the actual
2549 * address family; can initially be AF_UNSPEC if there
2550 * is no preference; will be set to AF_UNSPEC if the
2552 * @param addr set to either v4 or v6 depending on which
2553 * storage location was used; set to NULL if allocation failed
2554 * @param v4 storage space for an IPv4 address
2555 * @param v6 storage space for an IPv6 address
2556 * @return #GNUNET_OK normally, #GNUNET_SYSERR if `* result_af` was
2557 * an unsupported address family (not AF_INET, AF_INET6 or AF_UNSPEC)
2560 allocate_response_ip (int *result_af,
2563 struct in6_addr *v6)
2570 allocate_v4_address (v4))
2571 *result_af = AF_UNSPEC;
2577 allocate_v6_address (v6))
2578 *result_af = AF_UNSPEC;
2584 allocate_v4_address (v4))
2587 *result_af = AF_INET;
2589 else if (GNUNET_OK ==
2590 allocate_v6_address (v6))
2593 *result_af = AF_INET6;
2598 return GNUNET_SYSERR;
2605 * A client asks us to setup a redirection via some exit node to a
2606 * particular IP. Setup the redirection and give the client the
2610 * @param client requesting client
2611 * @param message redirection request (a `struct RedirectToIpRequestMessage`)
2614 service_redirect_to_ip (void *cls,
2615 struct GNUNET_SERVER_Client *client,
2616 const struct GNUNET_MessageHeader *message)
2620 const struct RedirectToIpRequestMessage *msg;
2626 struct DestinationEntry *de;
2627 struct GNUNET_HashCode key;
2629 /* validate and parse request */
2630 mlen = ntohs (message->size);
2631 if (mlen < sizeof (struct RedirectToIpRequestMessage))
2634 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2637 alen = mlen - sizeof (struct RedirectToIpRequestMessage);
2638 msg = (const struct RedirectToIpRequestMessage *) message;
2639 addr_af = (int) htonl (msg->addr_af);
2643 if (alen != sizeof (struct in_addr))
2646 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2651 if (alen != sizeof (struct in6_addr))
2654 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2660 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2664 /* allocate response IP */
2665 result_af = (int) htonl (msg->result_af);
2666 if (GNUNET_OK != allocate_response_ip (&result_af,
2670 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2673 /* send reply with our IP address */
2674 send_client_reply (client,
2678 if (result_af == AF_UNSPEC)
2680 /* failure, we're done */
2681 GNUNET_SERVER_receive_done (client, GNUNET_OK);
2686 char sbuf[INET6_ADDRSTRLEN];
2687 char dbuf[INET6_ADDRSTRLEN];
2689 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2690 "Allocated address %s for redirection via exit to %s\n",
2691 inet_ntop (result_af, addr, sbuf, sizeof (sbuf)),
2693 &msg[1], dbuf, sizeof (dbuf)));
2696 /* setup destination record */
2697 de = GNUNET_new (struct DestinationEntry);
2698 de->is_service = GNUNET_NO;
2699 de->details.exit_destination.af = addr_af;
2700 memcpy (&de->details.exit_destination.ip,
2703 get_destination_key_from_ip (result_af,
2707 GNUNET_assert (GNUNET_OK ==
2708 GNUNET_CONTAINER_multihashmap_put (destination_map,
2711 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE));
2712 de->heap_node = GNUNET_CONTAINER_heap_insert (destination_heap,
2714 GNUNET_TIME_absolute_ntoh (msg->expiration_time).abs_value_us);
2715 GNUNET_STATISTICS_update (stats,
2716 gettext_noop ("# Active destinations"),
2718 while (GNUNET_CONTAINER_multihashmap_size (destination_map) > max_destination_mappings)
2719 expire_destination (de);
2720 GNUNET_SERVER_receive_done (client, GNUNET_OK);
2725 * A client asks us to setup a redirection to a particular peer
2726 * offering a service. Setup the redirection and give the client the
2730 * @param client requesting client
2731 * @param message redirection request (a `struct RedirectToPeerRequestMessage`)
2734 service_redirect_to_service (void *cls,
2735 struct GNUNET_SERVER_Client *client,
2736 const struct GNUNET_MessageHeader *message)
2738 const struct RedirectToServiceRequestMessage *msg;
2743 struct DestinationEntry *de;
2744 struct GNUNET_HashCode key;
2745 struct ChannelState *ts;
2746 struct DestinationChannel *dt;
2749 msg = (const struct RedirectToServiceRequestMessage *) message;
2751 /* allocate response IP */
2752 result_af = (int) htonl (msg->result_af);
2753 if (GNUNET_OK != allocate_response_ip (&result_af,
2757 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2760 send_client_reply (client,
2764 if (result_af == AF_UNSPEC)
2766 /* failure, we're done */
2767 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2768 _("Failed to allocate IP address for new destination\n"));
2769 GNUNET_SERVER_receive_done (client, GNUNET_OK);
2774 char sbuf[INET6_ADDRSTRLEN];
2776 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2777 "Allocated address %s for redirection to service %s on peer %s\n",
2778 inet_ntop (result_af, addr, sbuf, sizeof (sbuf)),
2779 GNUNET_h2s (&msg->service_descriptor),
2780 GNUNET_i2s (&msg->target));
2783 /* setup destination record */
2784 de = GNUNET_new (struct DestinationEntry);
2785 de->is_service = GNUNET_YES;
2786 de->details.service_destination.service_descriptor = msg->service_descriptor;
2787 de->details.service_destination.target = msg->target;
2788 get_destination_key_from_ip (result_af,
2792 GNUNET_assert (GNUNET_OK ==
2793 GNUNET_CONTAINER_multihashmap_put (destination_map,
2796 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE));
2797 de->heap_node = GNUNET_CONTAINER_heap_insert (destination_heap,
2799 GNUNET_TIME_absolute_ntoh (msg->expiration_time).abs_value_us);
2800 while (GNUNET_CONTAINER_multihashmap_size (destination_map) > max_destination_mappings)
2801 expire_destination (de);
2803 dt = GNUNET_new (struct DestinationChannel);
2804 dt->destination = de;
2805 GNUNET_CONTAINER_DLL_insert (de->dt_head,
2808 ts = create_channel_to_destination (dt,
2813 ts->destination_ip.v4 = v4;
2816 ts->destination_ip.v6 = v6;
2822 GNUNET_SERVER_receive_done (client, GNUNET_OK);
2827 * Function called whenever a channel is destroyed. Should clean up
2828 * any associated state.
2830 * @param cls closure (set from #GNUNET_CADET_connect)
2831 * @param channel connection to the other end (henceforth invalid)
2832 * @param channel_ctx place where local state associated
2833 * with the channel is stored (our `struct ChannelState`)
2836 channel_cleaner (void *cls,
2837 const struct GNUNET_CADET_Channel *channel,
2840 struct ChannelState *ts = channel_ctx;
2842 ts->channel = NULL; /* we must not call GNUNET_CADET_channel_destroy() anymore */
2843 free_channel_state (ts);
2848 * Free memory occupied by an entry in the destination map.
2852 * @param value a `struct DestinationEntry *`
2853 * @return #GNUNET_OK (continue to iterate)
2856 cleanup_destination (void *cls,
2857 const struct GNUNET_HashCode *key,
2860 struct DestinationEntry *de = value;
2862 free_destination_entry (de);
2868 * Free memory occupied by an entry in the channel map.
2872 * @param value a `struct ChannelState *`
2873 * @return #GNUNET_OK (continue to iterate)
2876 cleanup_channel (void *cls,
2877 const struct GNUNET_HashCode *key,
2880 struct ChannelState *ts = value;
2882 free_channel_state (ts);
2888 * Function scheduled as very last function, cleans up after us
2895 const struct GNUNET_SCHEDULER_TaskContext *tc)
2899 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2900 "VPN is shutting down\n");
2901 if (NULL != destination_map)
2903 GNUNET_CONTAINER_multihashmap_iterate (destination_map,
2904 &cleanup_destination,
2906 GNUNET_CONTAINER_multihashmap_destroy (destination_map);
2907 destination_map = NULL;
2909 if (NULL != destination_heap)
2911 GNUNET_CONTAINER_heap_destroy (destination_heap);
2912 destination_heap = NULL;
2914 if (NULL != channel_map)
2916 GNUNET_CONTAINER_multihashmap_iterate (channel_map,
2919 GNUNET_CONTAINER_multihashmap_destroy (channel_map);
2922 if (NULL != channel_heap)
2924 GNUNET_CONTAINER_heap_destroy (channel_heap);
2925 channel_heap = NULL;
2927 if (NULL != cadet_handle)
2929 GNUNET_CADET_disconnect (cadet_handle);
2930 cadet_handle = NULL;
2932 if (NULL != helper_handle)
2934 GNUNET_HELPER_stop (helper_handle, GNUNET_NO);
2935 helper_handle = NULL;
2939 GNUNET_SERVER_notification_context_destroy (nc);
2944 GNUNET_STATISTICS_destroy (stats, GNUNET_NO);
2948 GNUNET_free_non_null (vpn_argv[i]);
2953 * Main function that will be run by the scheduler.
2955 * @param cls closure
2956 * @param server the initialized server
2957 * @param cfg_ configuration
2961 struct GNUNET_SERVER_Handle *server,
2962 const struct GNUNET_CONFIGURATION_Handle *cfg_)
2964 static const struct GNUNET_SERVER_MessageHandler service_handlers[] = {
2965 /* callback, cls, type, size */
2966 { &service_redirect_to_ip, NULL, GNUNET_MESSAGE_TYPE_VPN_CLIENT_REDIRECT_TO_IP, 0},
2967 { &service_redirect_to_service, NULL,
2968 GNUNET_MESSAGE_TYPE_VPN_CLIENT_REDIRECT_TO_SERVICE,
2969 sizeof (struct RedirectToServiceRequestMessage) },
2972 static const struct GNUNET_CADET_MessageHandler cadet_handlers[] = {
2973 { &receive_udp_back, GNUNET_MESSAGE_TYPE_VPN_UDP_REPLY, 0},
2974 { &receive_tcp_back, GNUNET_MESSAGE_TYPE_VPN_TCP_DATA_TO_VPN, 0},
2975 { &receive_icmp_back, GNUNET_MESSAGE_TYPE_VPN_ICMP_TO_VPN, 0},
2987 binary = GNUNET_OS_get_libexec_binary_path ("gnunet-helper-vpn");
2990 GNUNET_OS_check_helper_binary (binary,
2992 "-d gnunet-vpn - - 169.1.3.3.7 255.255.255.0")) //ipv4 only please!
2994 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2995 "`%s' is not SUID, refusing to run.\n",
2996 "gnunet-helper-vpn");
2997 GNUNET_free (binary);
2999 /* we won't "really" exit here, as the 'service' is still running;
3000 however, as no handlers are registered, the service won't do
3004 GNUNET_free (binary);
3006 stats = GNUNET_STATISTICS_create ("vpn", cfg);
3008 GNUNET_CONFIGURATION_get_value_number (cfg, "VPN", "MAX_MAPPING",
3009 &max_destination_mappings))
3010 max_destination_mappings = 200;
3012 GNUNET_CONFIGURATION_get_value_number (cfg, "VPN", "MAX_TUNNELS",
3013 &max_channel_mappings))
3014 max_channel_mappings = 200;
3016 destination_map = GNUNET_CONTAINER_multihashmap_create (max_destination_mappings * 2, GNUNET_NO);
3017 destination_heap = GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN);
3018 channel_map = GNUNET_CONTAINER_multihashmap_create (max_channel_mappings * 2, GNUNET_NO);
3019 channel_heap = GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN);
3022 vpn_argv[0] = GNUNET_strdup ("vpn-gnunet");
3023 if (GNUNET_SYSERR ==
3024 GNUNET_CONFIGURATION_get_value_string (cfg, "VPN", "IFNAME", &ifname))
3026 GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, "VPN", "IFNAME");
3027 GNUNET_SCHEDULER_shutdown ();
3030 vpn_argv[1] = ifname;
3032 if (GNUNET_OK == GNUNET_NETWORK_test_pf (PF_INET6))
3034 if ( (GNUNET_SYSERR ==
3035 GNUNET_CONFIGURATION_get_value_string (cfg, "VPN", "IPV6ADDR",
3037 (1 != inet_pton (AF_INET6, ipv6addr, &v6))) )
3039 GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, "VPN", "IPV6ADDR",
3040 _("Must specify valid IPv6 address"));
3041 GNUNET_SCHEDULER_shutdown ();
3042 GNUNET_free_non_null (ipv6addr);
3045 vpn_argv[2] = ipv6addr;
3046 ipv6prefix_s = NULL;
3047 if (GNUNET_SYSERR ==
3048 GNUNET_CONFIGURATION_get_value_string (cfg, "VPN", "IPV6PREFIX",
3051 GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, "VPN", "IPV6PREFIX");
3052 GNUNET_SCHEDULER_shutdown ();
3053 GNUNET_free_non_null (ipv6prefix_s);
3056 vpn_argv[3] = ipv6prefix_s;
3058 GNUNET_CONFIGURATION_get_value_number (cfg, "VPN",
3061 (ipv6prefix >= 127) )
3063 GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, "VPN", "IPV4MASK",
3064 _("Must specify valid IPv6 mask"));
3065 GNUNET_SCHEDULER_shutdown ();
3071 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
3072 _("IPv6 support disabled as this system does not support IPv6\n"));
3073 vpn_argv[2] = GNUNET_strdup ("-");
3074 vpn_argv[3] = GNUNET_strdup ("-");
3076 if (GNUNET_OK == GNUNET_NETWORK_test_pf (PF_INET))
3079 if ( (GNUNET_SYSERR ==
3080 GNUNET_CONFIGURATION_get_value_string (cfg, "vpn", "IPV4ADDR",
3082 (1 != inet_pton (AF_INET, ipv4addr, &v4))) )
3084 GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, "VPN", "IPV4ADDR",
3085 _("Must specify valid IPv4 address"));
3086 GNUNET_SCHEDULER_shutdown ();
3087 GNUNET_free_non_null (ipv4addr);
3090 vpn_argv[4] = ipv4addr;
3092 if ( (GNUNET_SYSERR ==
3093 GNUNET_CONFIGURATION_get_value_string (cfg, "vpn", "IPV4MASK",
3095 (1 != inet_pton (AF_INET, ipv4mask, &v4))) )
3097 GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, "VPN", "IPV4MASK",
3098 _("Must specify valid IPv4 mask"));
3099 GNUNET_SCHEDULER_shutdown ();
3100 GNUNET_free_non_null (ipv4mask);
3103 vpn_argv[5] = ipv4mask;
3107 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
3108 _("IPv4 support disabled as this system does not support IPv4\n"));
3109 vpn_argv[4] = GNUNET_strdup ("-");
3110 vpn_argv[5] = GNUNET_strdup ("-");
3115 GNUNET_CADET_connect (cfg_, NULL,
3120 helper_handle = GNUNET_HELPER_start (GNUNET_NO,
3121 "gnunet-helper-vpn", vpn_argv,
3122 &message_token, NULL, NULL);
3123 nc = GNUNET_SERVER_notification_context_create (server, 1);
3124 GNUNET_SERVER_add_handlers (server, service_handlers);
3125 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &cleanup, cls);
3130 * The main function of the VPN service.
3132 * @param argc number of arguments from the command line
3133 * @param argv command line arguments
3134 * @return 0 ok, 1 on error
3137 main (int argc, char *const *argv)
3139 return (GNUNET_OK ==
3140 GNUNET_SERVICE_run (argc, argv, "vpn",
3141 GNUNET_SERVICE_OPTION_NONE,
3142 &run, NULL)) ? global_ret : 1;
3145 /* end of gnunet-service-vpn.c */