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_REGEX_search_cancel (ts->search);
748 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
749 "Exit %s found for destination %s!\n",
751 print_channel_destination (&ts->destination),
755 apptype = GNUNET_APPLICATION_TYPE_IPV4_GATEWAY;
758 apptype = GNUNET_APPLICATION_TYPE_IPV6_GATEWAY;
764 ts->channel = GNUNET_CADET_channel_create (cadet_handle,
768 GNUNET_CADET_OPTION_DEFAULT);
773 * Initialize the given destination entry's cadet channel.
775 * @param dt destination channel for which we need to setup a channel
776 * @param client_af address family of the address returned to the client
777 * @return channel state of the channel that was created
779 static struct ChannelState *
780 create_channel_to_destination (struct DestinationChannel *dt,
783 struct ChannelState *ts;
784 unsigned int apptype;
786 GNUNET_STATISTICS_update (stats,
787 gettext_noop ("# Cadet channels created"),
789 GNUNET_assert (NULL == dt->ts);
793 apptype = GNUNET_APPLICATION_TYPE_IPV4_GATEWAY;
796 apptype = GNUNET_APPLICATION_TYPE_IPV6_GATEWAY;
802 ts = GNUNET_new (struct ChannelState);
804 ts->destination = *dt->destination;
805 ts->destination.heap_node = NULL; /* copy is NOT in destination heap */
807 ts->destination_container = dt; /* we are referenced from dt */
808 if (dt->destination->is_service)
810 ts->channel = GNUNET_CADET_channel_create (cadet_handle,
812 &dt->destination->details.service_destination.target,
814 GNUNET_CADET_OPTION_DEFAULT);
815 if (NULL == ts->channel)
817 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
818 _("Failed to setup cadet channel!\n"));
822 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
823 "Creating channel to peer %s offering service %s\n",
824 GNUNET_i2s (&dt->destination->details.service_destination.target),
825 GNUNET_h2s (&dt->destination->details.service_destination.service_descriptor));
831 switch (dt->destination->details.exit_destination.af)
835 char address[GNUNET_TUN_IPV4_REGEXLEN];
837 GNUNET_TUN_ipv4toregexsearch (&dt->destination->details.exit_destination.ip.v4,
838 dt->destination_port,
840 GNUNET_asprintf (&policy,
842 GNUNET_APPLICATION_TYPE_EXIT_REGEX_PREFIX,
848 char address[GNUNET_TUN_IPV6_REGEXLEN];
850 GNUNET_TUN_ipv6toregexsearch (&dt->destination->details.exit_destination.ip.v6,
851 dt->destination_port,
853 GNUNET_asprintf (&policy,
855 GNUNET_APPLICATION_TYPE_EXIT_REGEX_PREFIX,
864 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
865 "Requesting connect by string: %s\n",
867 ts->search = GNUNET_REGEX_search (cfg,
869 &handle_regex_result,
871 GNUNET_free (policy);
878 * We have too many active channels. Clean up the oldest channel.
880 * @param except channel that must NOT be cleaned up, even if it is the oldest
883 expire_channel (struct ChannelState *except)
885 struct ChannelState *ts;
887 ts = GNUNET_CONTAINER_heap_peek (channel_heap);
888 GNUNET_assert (NULL != ts);
890 return; /* can't do this */
891 free_channel_state (ts);
896 * Route a packet via cadet to the given destination.
898 * @param destination description of the destination
899 * @param af address family on this end (AF_INET or AF_INET6)
900 * @param protocol IPPROTO_TCP or IPPROTO_UDP or IPPROTO_ICMP or IPPROTO_ICMPV6
901 * @param source_ip source IP used by the sender (struct in_addr or struct in6_addr)
902 * @param destination_ip destination IP used by the sender (struct in_addr or struct in6_addr)
903 * @param payload payload of the packet after the IP header
904 * @param payload_length number of bytes in @a payload
907 route_packet (struct DestinationEntry *destination,
910 const void *source_ip,
911 const void *destination_ip,
913 size_t payload_length)
915 struct GNUNET_HashCode key;
916 struct ChannelState *ts;
917 struct ChannelMessageQueueEntry *tnq;
921 const struct GNUNET_TUN_UdpHeader *udp;
922 const struct GNUNET_TUN_TcpHeader *tcp;
923 const struct GNUNET_TUN_IcmpHeader *icmp;
924 struct DestinationChannel *dt;
925 uint16_t source_port;
926 uint16_t destination_port;
932 if (payload_length < sizeof (struct GNUNET_TUN_UdpHeader))
938 tcp = NULL; /* make compiler happy */
939 icmp = NULL; /* make compiler happy */
941 if (udp->len < sizeof (struct GNUNET_TUN_UdpHeader))
946 source_port = ntohs (udp->source_port);
947 destination_port = ntohs (udp->destination_port);
948 get_channel_key_from_ips (af,
959 if (payload_length < sizeof (struct GNUNET_TUN_TcpHeader))
965 udp = NULL; /* make compiler happy */
966 icmp = NULL; /* make compiler happy */
968 if (tcp->off * 4 < sizeof (struct GNUNET_TUN_TcpHeader))
973 source_port = ntohs (tcp->source_port);
974 destination_port = ntohs (tcp->destination_port);
975 get_channel_key_from_ips (af,
987 if ( (AF_INET == af) ^ (protocol == IPPROTO_ICMP) )
992 if (payload_length < sizeof (struct GNUNET_TUN_IcmpHeader))
998 tcp = NULL; /* make compiler happy */
999 udp = NULL; /* make compiler happy */
1002 destination_port = 0;
1003 get_channel_key_from_ips (af,
1013 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1014 _("Protocol %u not supported, dropping\n"),
1015 (unsigned int) protocol);
1019 if (! destination->is_service)
1021 switch (destination->details.exit_destination.af)
1024 alen = sizeof (struct in_addr);
1027 alen = sizeof (struct in6_addr);
1034 char sbuf[INET6_ADDRSTRLEN];
1035 char dbuf[INET6_ADDRSTRLEN];
1036 char xbuf[INET6_ADDRSTRLEN];
1038 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1039 "Routing %s packet from %s:%u -> %s:%u to destination %s:%u\n",
1040 (protocol == IPPROTO_TCP) ? "TCP" : "UDP",
1041 inet_ntop (af, source_ip, sbuf, sizeof (sbuf)),
1043 inet_ntop (af, destination_ip, dbuf, sizeof (dbuf)),
1045 inet_ntop (destination->details.exit_destination.af,
1046 &destination->details.exit_destination.ip,
1047 xbuf, sizeof (xbuf)),
1050 for (dt = destination->dt_head; NULL != dt; dt = dt->next)
1051 if (dt->destination_port == destination_port)
1057 char sbuf[INET6_ADDRSTRLEN];
1058 char dbuf[INET6_ADDRSTRLEN];
1060 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1061 "Routing %s packet from %s:%u -> %s:%u to service %s at peer %s\n",
1062 (protocol == IPPROTO_TCP) ? "TCP" : "UDP",
1063 inet_ntop (af, source_ip, sbuf, sizeof (sbuf)),
1065 inet_ntop (af, destination_ip, dbuf, sizeof (dbuf)),
1067 GNUNET_h2s (&destination->details.service_destination.service_descriptor),
1068 GNUNET_i2s (&destination->details.service_destination.target));
1070 dt = destination->dt_head;
1074 dt = GNUNET_new (struct DestinationChannel);
1075 dt->destination = destination;
1076 GNUNET_CONTAINER_DLL_insert (destination->dt_head,
1077 destination->dt_tail,
1079 dt->destination_port = destination_port;
1082 /* see if we have an existing channel for this destination */
1083 ts = GNUNET_CONTAINER_multihashmap_get (channel_map,
1087 /* need to either use the existing channel from the destination (if still
1088 available) or create a fresh one */
1089 is_new = GNUNET_YES;
1091 ts = create_channel_to_destination (dt, af);
1097 ts->destination_container = NULL; /* no longer 'contained' */
1098 /* now bind existing "unbound" channel to our IP/port tuple */
1099 ts->protocol = protocol;
1103 ts->source_ip.v4 = * (const struct in_addr *) source_ip;
1104 ts->destination_ip.v4 = * (const struct in_addr *) destination_ip;
1108 ts->source_ip.v6 = * (const struct in6_addr *) source_ip;
1109 ts->destination_ip.v6 = * (const struct in6_addr *) destination_ip;
1111 ts->source_port = source_port;
1112 ts->destination_port = destination_port;
1113 ts->heap_node = GNUNET_CONTAINER_heap_insert (channel_heap,
1115 GNUNET_TIME_absolute_get ().abs_value_us);
1116 GNUNET_assert (GNUNET_YES ==
1117 GNUNET_CONTAINER_multihashmap_put (channel_map,
1120 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
1121 GNUNET_STATISTICS_update (stats,
1122 gettext_noop ("# Active channels"),
1124 while (GNUNET_CONTAINER_multihashmap_size (channel_map) > max_channel_mappings)
1125 expire_channel (ts);
1130 GNUNET_CONTAINER_heap_update_cost (channel_heap,
1132 GNUNET_TIME_absolute_get ().abs_value_us);
1134 if (NULL == ts->channel)
1136 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1137 "Packet dropped, channel to %s not yet ready (%s)\n",
1138 print_channel_destination (&ts->destination),
1139 (NULL == ts->search)
1140 ? "EXIT search failed"
1141 : "EXIT search active");
1142 GNUNET_STATISTICS_update (stats,
1143 gettext_noop ("# Packets dropped (channel not yet online)"),
1149 /* send via channel */
1153 if (destination->is_service)
1155 struct GNUNET_EXIT_UdpServiceMessage *usm;
1157 mlen = sizeof (struct GNUNET_EXIT_UdpServiceMessage) +
1158 payload_length - sizeof (struct GNUNET_TUN_UdpHeader);
1159 if (mlen >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1164 tnq = GNUNET_malloc (sizeof (struct ChannelMessageQueueEntry) + mlen);
1167 usm = (struct GNUNET_EXIT_UdpServiceMessage *) &tnq[1];
1168 usm->header.size = htons ((uint16_t) mlen);
1169 usm->header.type = htons (GNUNET_MESSAGE_TYPE_VPN_UDP_TO_SERVICE);
1170 /* if the source port is below 32000, we assume it has a special
1171 meaning; if not, we pick a random port (this is a heuristic) */
1172 usm->source_port = (ntohs (udp->source_port) < 32000) ? udp->source_port : 0;
1173 usm->destination_port = udp->destination_port;
1174 usm->service_descriptor = destination->details.service_destination.service_descriptor;
1177 payload_length - sizeof (struct GNUNET_TUN_UdpHeader));
1181 struct GNUNET_EXIT_UdpInternetMessage *uim;
1182 struct in_addr *ip4dst;
1183 struct in6_addr *ip6dst;
1186 mlen = sizeof (struct GNUNET_EXIT_UdpInternetMessage) +
1187 alen + payload_length - sizeof (struct GNUNET_TUN_UdpHeader);
1188 if (mlen >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1193 tnq = GNUNET_malloc (sizeof (struct ChannelMessageQueueEntry) + mlen);
1196 uim = (struct GNUNET_EXIT_UdpInternetMessage *) &tnq[1];
1197 uim->header.size = htons ((uint16_t) mlen);
1198 uim->header.type = htons (GNUNET_MESSAGE_TYPE_VPN_UDP_TO_INTERNET);
1199 uim->af = htonl (destination->details.exit_destination.af);
1200 uim->source_port = (ntohs (udp->source_port) < 32000) ? udp->source_port : 0;
1201 uim->destination_port = udp->destination_port;
1202 switch (destination->details.exit_destination.af)
1205 ip4dst = (struct in_addr *) &uim[1];
1206 *ip4dst = destination->details.exit_destination.ip.v4;
1207 payload = &ip4dst[1];
1210 ip6dst = (struct in6_addr *) &uim[1];
1211 *ip6dst = destination->details.exit_destination.ip.v6;
1212 payload = &ip6dst[1];
1219 payload_length - sizeof (struct GNUNET_TUN_UdpHeader));
1225 if (destination->is_service)
1227 struct GNUNET_EXIT_TcpServiceStartMessage *tsm;
1229 mlen = sizeof (struct GNUNET_EXIT_TcpServiceStartMessage) +
1230 payload_length - sizeof (struct GNUNET_TUN_TcpHeader);
1231 if (mlen >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1236 tnq = GNUNET_malloc (sizeof (struct ChannelMessageQueueEntry) + mlen);
1239 tsm = (struct GNUNET_EXIT_TcpServiceStartMessage *) &tnq[1];
1240 tsm->header.size = htons ((uint16_t) mlen);
1241 tsm->header.type = htons (GNUNET_MESSAGE_TYPE_VPN_TCP_TO_SERVICE_START);
1242 tsm->reserved = htonl (0);
1243 tsm->service_descriptor = destination->details.service_destination.service_descriptor;
1244 tsm->tcp_header = *tcp;
1247 payload_length - sizeof (struct GNUNET_TUN_TcpHeader));
1251 struct GNUNET_EXIT_TcpInternetStartMessage *tim;
1252 struct in_addr *ip4dst;
1253 struct in6_addr *ip6dst;
1256 mlen = sizeof (struct GNUNET_EXIT_TcpInternetStartMessage) +
1257 alen + payload_length - sizeof (struct GNUNET_TUN_TcpHeader);
1258 if (mlen >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1263 tnq = GNUNET_malloc (sizeof (struct ChannelMessageQueueEntry) + mlen);
1266 tim = (struct GNUNET_EXIT_TcpInternetStartMessage *) &tnq[1];
1267 tim->header.size = htons ((uint16_t) mlen);
1268 tim->header.type = htons (GNUNET_MESSAGE_TYPE_VPN_TCP_TO_INTERNET_START);
1269 tim->af = htonl (destination->details.exit_destination.af);
1270 tim->tcp_header = *tcp;
1271 switch (destination->details.exit_destination.af)
1274 ip4dst = (struct in_addr *) &tim[1];
1275 *ip4dst = destination->details.exit_destination.ip.v4;
1276 payload = &ip4dst[1];
1279 ip6dst = (struct in6_addr *) &tim[1];
1280 *ip6dst = destination->details.exit_destination.ip.v6;
1281 payload = &ip6dst[1];
1288 payload_length - sizeof (struct GNUNET_TUN_TcpHeader));
1293 struct GNUNET_EXIT_TcpDataMessage *tdm;
1295 mlen = sizeof (struct GNUNET_EXIT_TcpDataMessage) +
1296 payload_length - sizeof (struct GNUNET_TUN_TcpHeader);
1297 if (mlen >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1302 tnq = GNUNET_malloc (sizeof (struct ChannelMessageQueueEntry) + mlen);
1305 tdm = (struct GNUNET_EXIT_TcpDataMessage *) &tnq[1];
1306 tdm->header.size = htons ((uint16_t) mlen);
1307 tdm->header.type = htons (GNUNET_MESSAGE_TYPE_VPN_TCP_DATA_TO_EXIT);
1308 tdm->reserved = htonl (0);
1309 tdm->tcp_header = *tcp;
1312 payload_length - sizeof (struct GNUNET_TUN_TcpHeader));
1316 case IPPROTO_ICMPV6:
1317 if (destination->is_service)
1319 struct GNUNET_EXIT_IcmpServiceMessage *ism;
1321 mlen = sizeof (struct GNUNET_EXIT_IcmpServiceMessage) +
1322 payload_length - sizeof (struct GNUNET_TUN_IcmpHeader);
1323 if (mlen >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1328 tnq = GNUNET_malloc (sizeof (struct ChannelMessageQueueEntry) + mlen);
1330 ism = (struct GNUNET_EXIT_IcmpServiceMessage *) &tnq[1];
1331 ism->header.type = htons (GNUNET_MESSAGE_TYPE_VPN_ICMP_TO_SERVICE);
1332 ism->af = htonl (af); /* need to tell destination ICMP protocol family! */
1333 ism->service_descriptor = destination->details.service_destination.service_descriptor;
1334 ism->icmp_header = *icmp;
1335 /* ICMP protocol translation will be done by the receiver (as we don't know
1336 the target AF); however, we still need to possibly discard the payload
1337 depending on the ICMP type */
1343 case GNUNET_TUN_ICMPTYPE_ECHO_REPLY:
1344 case GNUNET_TUN_ICMPTYPE_ECHO_REQUEST:
1346 case GNUNET_TUN_ICMPTYPE_DESTINATION_UNREACHABLE:
1347 case GNUNET_TUN_ICMPTYPE_SOURCE_QUENCH:
1348 case GNUNET_TUN_ICMPTYPE_TIME_EXCEEDED:
1349 /* throw away ICMP payload, won't be useful for the other side anyway */
1350 payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
1353 GNUNET_STATISTICS_update (stats,
1354 gettext_noop ("# ICMPv4 packets dropped (not allowed)"),
1358 /* end of AF_INET */
1363 case GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE:
1364 case GNUNET_TUN_ICMPTYPE6_PACKET_TOO_BIG:
1365 case GNUNET_TUN_ICMPTYPE6_TIME_EXCEEDED:
1366 case GNUNET_TUN_ICMPTYPE6_PARAMETER_PROBLEM:
1367 /* throw away ICMP payload, won't be useful for the other side anyway */
1368 payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
1370 case GNUNET_TUN_ICMPTYPE6_ECHO_REQUEST:
1371 case GNUNET_TUN_ICMPTYPE6_ECHO_REPLY:
1374 GNUNET_STATISTICS_update (stats,
1375 gettext_noop ("# ICMPv6 packets dropped (not allowed)"),
1379 /* end of AF_INET6 */
1386 /* update length calculations, as payload_length may have changed */
1387 mlen = sizeof (struct GNUNET_EXIT_IcmpServiceMessage) +
1388 alen + payload_length - sizeof (struct GNUNET_TUN_IcmpHeader);
1390 ism->header.size = htons ((uint16_t) mlen);
1391 /* finally, copy payload (if there is any left...) */
1394 payload_length - sizeof (struct GNUNET_TUN_IcmpHeader));
1398 struct GNUNET_EXIT_IcmpInternetMessage *iim;
1399 struct in_addr *ip4dst;
1400 struct in6_addr *ip6dst;
1403 mlen = sizeof (struct GNUNET_EXIT_IcmpInternetMessage) +
1404 alen + payload_length - sizeof (struct GNUNET_TUN_IcmpHeader);
1405 if (mlen >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1410 tnq = GNUNET_malloc (sizeof (struct ChannelMessageQueueEntry) + mlen);
1412 iim = (struct GNUNET_EXIT_IcmpInternetMessage *) &tnq[1];
1413 iim->header.type = htons (GNUNET_MESSAGE_TYPE_VPN_ICMP_TO_INTERNET);
1414 iim->icmp_header = *icmp;
1415 /* Perform ICMP protocol-translation (depending on destination AF and source AF)
1416 and throw away ICMP payload depending on ICMP message type */
1422 case GNUNET_TUN_ICMPTYPE_ECHO_REPLY:
1423 if (destination->details.exit_destination.af == AF_INET6)
1424 iim->icmp_header.type = GNUNET_TUN_ICMPTYPE6_ECHO_REPLY;
1426 case GNUNET_TUN_ICMPTYPE_ECHO_REQUEST:
1427 if (destination->details.exit_destination.af == AF_INET6)
1428 iim->icmp_header.type = GNUNET_TUN_ICMPTYPE6_ECHO_REQUEST;
1430 case GNUNET_TUN_ICMPTYPE_DESTINATION_UNREACHABLE:
1431 if (destination->details.exit_destination.af == AF_INET6)
1432 iim->icmp_header.type = GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE;
1433 /* throw away IP-payload, exit will have to make it up anyway */
1434 payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
1436 case GNUNET_TUN_ICMPTYPE_TIME_EXCEEDED:
1437 if (destination->details.exit_destination.af == AF_INET6)
1438 iim->icmp_header.type = GNUNET_TUN_ICMPTYPE6_TIME_EXCEEDED;
1439 /* throw away IP-payload, exit will have to make it up anyway */
1440 payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
1442 case GNUNET_TUN_ICMPTYPE_SOURCE_QUENCH:
1443 if (destination->details.exit_destination.af == AF_INET6)
1445 GNUNET_STATISTICS_update (stats,
1446 gettext_noop ("# ICMPv4 packets dropped (impossible PT to v6)"),
1451 /* throw away IP-payload, exit will have to make it up anyway */
1452 payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
1455 GNUNET_STATISTICS_update (stats,
1456 gettext_noop ("# ICMPv4 packets dropped (type not allowed)"),
1461 /* end of AF_INET */
1466 case GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE:
1467 if (destination->details.exit_destination.af == AF_INET6)
1468 iim->icmp_header.type = GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE;
1469 /* throw away IP-payload, exit will have to make it up anyway */
1470 payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
1472 case GNUNET_TUN_ICMPTYPE6_TIME_EXCEEDED:
1473 if (destination->details.exit_destination.af == AF_INET)
1474 iim->icmp_header.type = GNUNET_TUN_ICMPTYPE_TIME_EXCEEDED;
1475 /* throw away IP-payload, exit will have to make it up anyway */
1476 payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
1478 case GNUNET_TUN_ICMPTYPE6_PACKET_TOO_BIG:
1479 if (destination->details.exit_destination.af == AF_INET)
1481 GNUNET_STATISTICS_update (stats,
1482 gettext_noop ("# ICMPv6 packets dropped (impossible PT to v4)"),
1487 /* throw away IP-payload, exit will have to make it up anyway */
1488 payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
1490 case GNUNET_TUN_ICMPTYPE6_PARAMETER_PROBLEM:
1491 if (destination->details.exit_destination.af == AF_INET)
1493 GNUNET_STATISTICS_update (stats,
1494 gettext_noop ("# ICMPv6 packets dropped (impossible PT to v4)"),
1499 /* throw away IP-payload, exit will have to make it up anyway */
1500 payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
1502 case GNUNET_TUN_ICMPTYPE6_ECHO_REQUEST:
1503 if (destination->details.exit_destination.af == AF_INET)
1504 iim->icmp_header.type = GNUNET_TUN_ICMPTYPE_ECHO_REQUEST;
1506 case GNUNET_TUN_ICMPTYPE6_ECHO_REPLY:
1507 if (destination->details.exit_destination.af == AF_INET)
1508 iim->icmp_header.type = GNUNET_TUN_ICMPTYPE_ECHO_REPLY;
1511 GNUNET_STATISTICS_update (stats,
1512 gettext_noop ("# ICMPv6 packets dropped (type not allowed)"),
1517 /* end of AF_INET6 */
1522 /* update length calculations, as payload_length may have changed */
1523 mlen = sizeof (struct GNUNET_EXIT_IcmpInternetMessage) +
1524 alen + payload_length - sizeof (struct GNUNET_TUN_IcmpHeader);
1526 iim->header.size = htons ((uint16_t) mlen);
1528 /* need to tell destination ICMP protocol family! */
1529 iim->af = htonl (destination->details.exit_destination.af);
1530 switch (destination->details.exit_destination.af)
1533 ip4dst = (struct in_addr *) &iim[1];
1534 *ip4dst = destination->details.exit_destination.ip.v4;
1535 payload = &ip4dst[1];
1538 ip6dst = (struct in6_addr *) &iim[1];
1539 *ip6dst = destination->details.exit_destination.ip.v6;
1540 payload = &ip6dst[1];
1547 payload_length - sizeof (struct GNUNET_TUN_IcmpHeader));
1551 /* not supported above, how can we get here !? */
1555 send_to_channel (tnq, ts);
1560 * Receive packets from the helper-process (someone send to the local
1561 * virtual channel interface). Find the destination mapping, and if it
1562 * exists, identify the correct CADET channel (or possibly create it)
1563 * and forward the packet.
1565 * @param cls closure, NULL
1566 * @param client NULL
1567 * @param message message we got from the client (VPN channel interface)
1570 message_token (void *cls,
1572 const struct GNUNET_MessageHeader *message)
1574 const struct GNUNET_TUN_Layer2PacketHeader *tun;
1576 struct GNUNET_HashCode key;
1577 struct DestinationEntry *de;
1579 GNUNET_STATISTICS_update (stats,
1580 gettext_noop ("# Packets received from TUN interface"),
1582 mlen = ntohs (message->size);
1583 if ( (ntohs (message->type) != GNUNET_MESSAGE_TYPE_VPN_HELPER) ||
1584 (mlen < sizeof (struct GNUNET_MessageHeader) + sizeof (struct GNUNET_TUN_Layer2PacketHeader)) )
1589 tun = (const struct GNUNET_TUN_Layer2PacketHeader *) &message[1];
1590 mlen -= (sizeof (struct GNUNET_MessageHeader) + sizeof (struct GNUNET_TUN_Layer2PacketHeader));
1591 switch (ntohs (tun->proto))
1595 const struct GNUNET_TUN_IPv6Header *pkt6;
1597 if (mlen < sizeof (struct GNUNET_TUN_IPv6Header))
1603 pkt6 = (const struct GNUNET_TUN_IPv6Header *) &tun[1];
1604 get_destination_key_from_ip (AF_INET6,
1605 &pkt6->destination_address,
1607 de = GNUNET_CONTAINER_multihashmap_get (destination_map, &key);
1610 char buf[INET6_ADDRSTRLEN];
1612 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1613 _("Packet received for unmapped destination `%s' (dropping it)\n"),
1614 inet_ntop (AF_INET6,
1615 &pkt6->destination_address,
1623 &pkt6->source_address,
1624 &pkt6->destination_address,
1626 mlen - sizeof (struct GNUNET_TUN_IPv6Header));
1631 struct GNUNET_TUN_IPv4Header *pkt4;
1633 if (mlen < sizeof (struct GNUNET_TUN_IPv4Header))
1639 pkt4 = (struct GNUNET_TUN_IPv4Header *) &tun[1];
1640 get_destination_key_from_ip (AF_INET,
1641 &pkt4->destination_address,
1643 de = GNUNET_CONTAINER_multihashmap_get (destination_map, &key);
1646 char buf[INET_ADDRSTRLEN];
1648 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1649 _("Packet received for unmapped destination `%s' (dropping it)\n"),
1651 &pkt4->destination_address,
1656 if (pkt4->header_length * 4 != sizeof (struct GNUNET_TUN_IPv4Header))
1658 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1659 _("Received IPv4 packet with options (dropping it)\n"));
1665 &pkt4->source_address,
1666 &pkt4->destination_address,
1668 mlen - sizeof (struct GNUNET_TUN_IPv4Header));
1672 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1673 _("Received packet of unknown protocol %d from TUN (dropping it)\n"),
1674 (unsigned int) ntohs (tun->proto));
1682 * Synthesize a plausible ICMP payload for an ICMP error
1683 * response on the given channel.
1685 * @param ts channel information
1686 * @param ipp IPv4 header to fill in (ICMP payload)
1687 * @param udp "UDP" header to fill in (ICMP payload); might actually
1688 * also be the first 8 bytes of the TCP header
1691 make_up_icmpv4_payload (struct ChannelState *ts,
1692 struct GNUNET_TUN_IPv4Header *ipp,
1693 struct GNUNET_TUN_UdpHeader *udp)
1695 GNUNET_TUN_initialize_ipv4_header (ipp,
1697 sizeof (struct GNUNET_TUN_TcpHeader),
1699 &ts->destination_ip.v4);
1700 udp->source_port = htons (ts->source_port);
1701 udp->destination_port = htons (ts->destination_port);
1702 udp->len = htons (0);
1703 udp->crc = htons (0);
1708 * Synthesize a plausible ICMP payload for an ICMP error
1709 * response on the given channel.
1711 * @param ts channel information
1712 * @param ipp IPv6 header to fill in (ICMP payload)
1713 * @param udp "UDP" header to fill in (ICMP payload); might actually
1714 * also be the first 8 bytes of the TCP header
1717 make_up_icmpv6_payload (struct ChannelState *ts,
1718 struct GNUNET_TUN_IPv6Header *ipp,
1719 struct GNUNET_TUN_UdpHeader *udp)
1721 GNUNET_TUN_initialize_ipv6_header (ipp,
1723 sizeof (struct GNUNET_TUN_TcpHeader),
1725 &ts->destination_ip.v6);
1726 udp->source_port = htons (ts->source_port);
1727 udp->destination_port = htons (ts->destination_port);
1728 udp->len = htons (0);
1729 udp->crc = htons (0);
1734 * We got an ICMP packet back from the CADET channel. Pass it on to the
1735 * local virtual interface via the helper.
1737 * @param cls closure, NULL
1738 * @param channel connection to the other end
1739 * @param channel_ctx pointer to our 'struct ChannelState *'
1740 * @param message the actual message
1741 * @return #GNUNET_OK to keep the connection open,
1742 * #GNUNET_SYSERR to close it (signal serious error)
1745 receive_icmp_back (void *cls,
1746 struct GNUNET_CADET_Channel *channel,
1748 const struct GNUNET_MessageHeader *message)
1750 struct ChannelState *ts = *channel_ctx;
1751 const struct GNUNET_EXIT_IcmpToVPNMessage *i2v;
1754 GNUNET_STATISTICS_update (stats,
1755 gettext_noop ("# ICMP packets received from cadet"),
1757 mlen = ntohs (message->size);
1758 if (mlen < sizeof (struct GNUNET_EXIT_IcmpToVPNMessage))
1760 GNUNET_break_op (0);
1761 return GNUNET_SYSERR;
1763 if (NULL == ts->heap_node)
1765 GNUNET_break_op (0);
1766 return GNUNET_SYSERR;
1768 if (AF_UNSPEC == ts->af)
1770 GNUNET_break_op (0);
1771 return GNUNET_SYSERR;
1773 i2v = (const struct GNUNET_EXIT_IcmpToVPNMessage *) message;
1774 mlen -= sizeof (struct GNUNET_EXIT_IcmpToVPNMessage);
1776 char sbuf[INET6_ADDRSTRLEN];
1777 char dbuf[INET6_ADDRSTRLEN];
1779 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1780 "Received ICMP packet from cadet, sending %u bytes from %s -> %s via TUN\n",
1781 (unsigned int) mlen,
1782 inet_ntop (ts->af, &ts->destination_ip, sbuf, sizeof (sbuf)),
1783 inet_ntop (ts->af, &ts->source_ip, dbuf, sizeof (dbuf)));
1789 size_t size = sizeof (struct GNUNET_TUN_IPv4Header)
1790 + sizeof (struct GNUNET_TUN_IcmpHeader)
1791 + sizeof (struct GNUNET_MessageHeader) +
1792 sizeof (struct GNUNET_TUN_Layer2PacketHeader) +
1795 /* reserve some extra space in case we have an ICMP type here where
1796 we will need to make up the payload ourselves */
1797 char buf[size + sizeof (struct GNUNET_TUN_IPv4Header) + 8] GNUNET_ALIGN;
1798 struct GNUNET_MessageHeader *msg = (struct GNUNET_MessageHeader *) buf;
1799 struct GNUNET_TUN_Layer2PacketHeader *tun = (struct GNUNET_TUN_Layer2PacketHeader*) &msg[1];
1800 struct GNUNET_TUN_IPv4Header *ipv4 = (struct GNUNET_TUN_IPv4Header *) &tun[1];
1801 struct GNUNET_TUN_IcmpHeader *icmp = (struct GNUNET_TUN_IcmpHeader *) &ipv4[1];
1802 msg->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
1803 tun->flags = htons (0);
1804 tun->proto = htons (ETH_P_IPV4);
1805 GNUNET_TUN_initialize_ipv4_header (ipv4,
1807 sizeof (struct GNUNET_TUN_IcmpHeader) + mlen,
1808 &ts->destination_ip.v4,
1810 *icmp = i2v->icmp_header;
1814 /* For some ICMP types, we need to adjust (make up) the payload here.
1815 Also, depending on the AF used on the other side, we have to
1816 do ICMP PT (translate ICMP types) */
1817 switch (ntohl (i2v->af))
1822 case GNUNET_TUN_ICMPTYPE_ECHO_REPLY:
1823 case GNUNET_TUN_ICMPTYPE_ECHO_REQUEST:
1825 case GNUNET_TUN_ICMPTYPE_DESTINATION_UNREACHABLE:
1826 case GNUNET_TUN_ICMPTYPE_SOURCE_QUENCH:
1827 case GNUNET_TUN_ICMPTYPE_TIME_EXCEEDED:
1829 struct GNUNET_TUN_IPv4Header *ipp = (struct GNUNET_TUN_IPv4Header *) &icmp[1];
1830 struct GNUNET_TUN_UdpHeader *udp = (struct GNUNET_TUN_UdpHeader *) &ipp[1];
1834 /* sender did not strip ICMP payload? */
1835 GNUNET_break_op (0);
1836 return GNUNET_SYSERR;
1838 size += sizeof (struct GNUNET_TUN_IPv4Header) + 8;
1839 GNUNET_assert (8 == sizeof (struct GNUNET_TUN_UdpHeader));
1840 make_up_icmpv4_payload (ts, ipp, udp);
1844 GNUNET_break_op (0);
1845 GNUNET_STATISTICS_update (stats,
1846 gettext_noop ("# ICMPv4 packets dropped (type not allowed)"),
1848 return GNUNET_SYSERR;
1853 /* ICMP PT 6-to-4 and possibly making up payloads */
1856 case GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE:
1857 icmp->type = GNUNET_TUN_ICMPTYPE_DESTINATION_UNREACHABLE;
1859 struct GNUNET_TUN_IPv4Header *ipp = (struct GNUNET_TUN_IPv4Header *) &icmp[1];
1860 struct GNUNET_TUN_UdpHeader *udp = (struct GNUNET_TUN_UdpHeader *) &ipp[1];
1864 /* sender did not strip ICMP payload? */
1865 GNUNET_break_op (0);
1866 return GNUNET_SYSERR;
1868 size += sizeof (struct GNUNET_TUN_IPv4Header) + 8;
1869 GNUNET_assert (8 == sizeof (struct GNUNET_TUN_UdpHeader));
1870 make_up_icmpv4_payload (ts, ipp, udp);
1873 case GNUNET_TUN_ICMPTYPE6_TIME_EXCEEDED:
1874 icmp->type = GNUNET_TUN_ICMPTYPE_TIME_EXCEEDED;
1876 struct GNUNET_TUN_IPv4Header *ipp = (struct GNUNET_TUN_IPv4Header *) &icmp[1];
1877 struct GNUNET_TUN_UdpHeader *udp = (struct GNUNET_TUN_UdpHeader *) &ipp[1];
1881 /* sender did not strip ICMP payload? */
1882 GNUNET_break_op (0);
1883 return GNUNET_SYSERR;
1885 size += sizeof (struct GNUNET_TUN_IPv4Header) + 8;
1886 GNUNET_assert (8 == sizeof (struct GNUNET_TUN_UdpHeader));
1887 make_up_icmpv4_payload (ts, ipp, udp);
1890 case GNUNET_TUN_ICMPTYPE6_PACKET_TOO_BIG:
1891 case GNUNET_TUN_ICMPTYPE6_PARAMETER_PROBLEM:
1892 GNUNET_STATISTICS_update (stats,
1893 gettext_noop ("# ICMPv6 packets dropped (impossible PT to v4)"),
1896 case GNUNET_TUN_ICMPTYPE6_ECHO_REQUEST:
1897 icmp->type = GNUNET_TUN_ICMPTYPE_ECHO_REQUEST;
1899 case GNUNET_TUN_ICMPTYPE6_ECHO_REPLY:
1900 icmp->type = GNUNET_TUN_ICMPTYPE_ECHO_REPLY;
1903 GNUNET_break_op (0);
1904 GNUNET_STATISTICS_update (stats,
1905 gettext_noop ("# ICMPv6 packets dropped (type not allowed)"),
1907 return GNUNET_SYSERR;
1912 GNUNET_break_op (0);
1913 return GNUNET_SYSERR;
1915 msg->size = htons (size);
1916 GNUNET_TUN_calculate_icmp_checksum (icmp,
1919 (void) GNUNET_HELPER_send (helper_handle,
1928 size_t size = sizeof (struct GNUNET_TUN_IPv6Header)
1929 + sizeof (struct GNUNET_TUN_IcmpHeader)
1930 + sizeof (struct GNUNET_MessageHeader) +
1931 sizeof (struct GNUNET_TUN_Layer2PacketHeader) +
1934 char buf[size + sizeof (struct GNUNET_TUN_IPv6Header) + 8] GNUNET_ALIGN;
1935 struct GNUNET_MessageHeader *msg = (struct GNUNET_MessageHeader *) buf;
1936 struct GNUNET_TUN_Layer2PacketHeader *tun = (struct GNUNET_TUN_Layer2PacketHeader*) &msg[1];
1937 struct GNUNET_TUN_IPv6Header *ipv6 = (struct GNUNET_TUN_IPv6Header *) &tun[1];
1938 struct GNUNET_TUN_IcmpHeader *icmp = (struct GNUNET_TUN_IcmpHeader *) &ipv6[1];
1939 msg->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
1940 tun->flags = htons (0);
1941 tun->proto = htons (ETH_P_IPV6);
1942 GNUNET_TUN_initialize_ipv6_header (ipv6,
1944 sizeof (struct GNUNET_TUN_IcmpHeader) + mlen,
1945 &ts->destination_ip.v6,
1947 *icmp = i2v->icmp_header;
1952 /* For some ICMP types, we need to adjust (make up) the payload here.
1953 Also, depending on the AF used on the other side, we have to
1954 do ICMP PT (translate ICMP types) */
1955 switch (ntohl (i2v->af))
1958 /* ICMP PT 4-to-6 and possibly making up payloads */
1961 case GNUNET_TUN_ICMPTYPE_ECHO_REPLY:
1962 icmp->type = GNUNET_TUN_ICMPTYPE6_ECHO_REPLY;
1964 case GNUNET_TUN_ICMPTYPE_ECHO_REQUEST:
1965 icmp->type = GNUNET_TUN_ICMPTYPE6_ECHO_REQUEST;
1967 case GNUNET_TUN_ICMPTYPE_DESTINATION_UNREACHABLE:
1968 icmp->type = GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE;
1970 struct GNUNET_TUN_IPv6Header *ipp = (struct GNUNET_TUN_IPv6Header *) &icmp[1];
1971 struct GNUNET_TUN_UdpHeader *udp = (struct GNUNET_TUN_UdpHeader *) &ipp[1];
1975 /* sender did not strip ICMP payload? */
1976 GNUNET_break_op (0);
1977 return GNUNET_SYSERR;
1979 size += sizeof (struct GNUNET_TUN_IPv6Header) + 8;
1980 GNUNET_assert (8 == sizeof (struct GNUNET_TUN_UdpHeader));
1981 make_up_icmpv6_payload (ts, ipp, udp);
1984 case GNUNET_TUN_ICMPTYPE_TIME_EXCEEDED:
1985 icmp->type = GNUNET_TUN_ICMPTYPE6_TIME_EXCEEDED;
1987 struct GNUNET_TUN_IPv6Header *ipp = (struct GNUNET_TUN_IPv6Header *) &icmp[1];
1988 struct GNUNET_TUN_UdpHeader *udp = (struct GNUNET_TUN_UdpHeader *) &ipp[1];
1992 /* sender did not strip ICMP payload? */
1993 GNUNET_break_op (0);
1994 return GNUNET_SYSERR;
1996 size += sizeof (struct GNUNET_TUN_IPv6Header) + 8;
1997 GNUNET_assert (8 == sizeof (struct GNUNET_TUN_UdpHeader));
1998 make_up_icmpv6_payload (ts, ipp, udp);
2001 case GNUNET_TUN_ICMPTYPE_SOURCE_QUENCH:
2002 GNUNET_STATISTICS_update (stats,
2003 gettext_noop ("# ICMPv4 packets dropped (impossible PT to v6)"),
2007 GNUNET_break_op (0);
2008 GNUNET_STATISTICS_update (stats,
2009 gettext_noop ("# ICMPv4 packets dropped (type not allowed)"),
2011 return GNUNET_SYSERR;
2018 case GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE:
2019 case GNUNET_TUN_ICMPTYPE6_TIME_EXCEEDED:
2020 case GNUNET_TUN_ICMPTYPE6_PACKET_TOO_BIG:
2021 case GNUNET_TUN_ICMPTYPE6_PARAMETER_PROBLEM:
2023 struct GNUNET_TUN_IPv6Header *ipp = (struct GNUNET_TUN_IPv6Header *) &icmp[1];
2024 struct GNUNET_TUN_UdpHeader *udp = (struct GNUNET_TUN_UdpHeader *) &ipp[1];
2028 /* sender did not strip ICMP payload? */
2029 GNUNET_break_op (0);
2030 return GNUNET_SYSERR;
2032 size += sizeof (struct GNUNET_TUN_IPv6Header) + 8;
2033 GNUNET_assert (8 == sizeof (struct GNUNET_TUN_UdpHeader));
2034 make_up_icmpv6_payload (ts, ipp, udp);
2037 case GNUNET_TUN_ICMPTYPE6_ECHO_REQUEST:
2040 GNUNET_break_op (0);
2041 GNUNET_STATISTICS_update (stats,
2042 gettext_noop ("# ICMPv6 packets dropped (type not allowed)"),
2044 return GNUNET_SYSERR;
2049 GNUNET_break_op (0);
2050 return GNUNET_SYSERR;
2052 msg->size = htons (size);
2053 GNUNET_TUN_calculate_icmp_checksum (icmp,
2055 (void) GNUNET_HELPER_send (helper_handle,
2065 GNUNET_CONTAINER_heap_update_cost (channel_heap,
2067 GNUNET_TIME_absolute_get ().abs_value_us);
2073 * We got a UDP packet back from the CADET channel. Pass it on to the
2074 * local virtual interface via the helper.
2076 * @param cls closure, NULL
2077 * @param channel connection to the other end
2078 * @param channel_ctx pointer to our 'struct ChannelState *'
2079 * @param message the actual message
2080 * @return #GNUNET_OK to keep the connection open,
2081 * #GNUNET_SYSERR to close it (signal serious error)
2084 receive_udp_back (void *cls,
2085 struct GNUNET_CADET_Channel *channel,
2087 const struct GNUNET_MessageHeader *message)
2089 struct ChannelState *ts = *channel_ctx;
2090 const struct GNUNET_EXIT_UdpReplyMessage *reply;
2093 GNUNET_STATISTICS_update (stats,
2094 gettext_noop ("# UDP packets received from cadet"),
2096 mlen = ntohs (message->size);
2097 if (mlen < sizeof (struct GNUNET_EXIT_UdpReplyMessage))
2099 GNUNET_break_op (0);
2100 return GNUNET_SYSERR;
2102 if (NULL == ts->heap_node)
2104 GNUNET_break_op (0);
2105 return GNUNET_SYSERR;
2107 if (AF_UNSPEC == ts->af)
2109 GNUNET_break_op (0);
2110 return GNUNET_SYSERR;
2112 reply = (const struct GNUNET_EXIT_UdpReplyMessage *) message;
2113 mlen -= sizeof (struct GNUNET_EXIT_UdpReplyMessage);
2115 char sbuf[INET6_ADDRSTRLEN];
2116 char dbuf[INET6_ADDRSTRLEN];
2118 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2119 "Received UDP reply from cadet, sending %u bytes from %s:%u -> %s:%u via TUN\n",
2120 (unsigned int) mlen,
2121 inet_ntop (ts->af, &ts->destination_ip, sbuf, sizeof (sbuf)),
2122 ts->destination_port,
2123 inet_ntop (ts->af, &ts->source_ip, dbuf, sizeof (dbuf)),
2130 size_t size = sizeof (struct GNUNET_TUN_IPv4Header)
2131 + sizeof (struct GNUNET_TUN_UdpHeader)
2132 + sizeof (struct GNUNET_MessageHeader) +
2133 sizeof (struct GNUNET_TUN_Layer2PacketHeader) +
2136 char buf[size] GNUNET_ALIGN;
2137 struct GNUNET_MessageHeader *msg = (struct GNUNET_MessageHeader *) buf;
2138 struct GNUNET_TUN_Layer2PacketHeader *tun = (struct GNUNET_TUN_Layer2PacketHeader*) &msg[1];
2139 struct GNUNET_TUN_IPv4Header *ipv4 = (struct GNUNET_TUN_IPv4Header *) &tun[1];
2140 struct GNUNET_TUN_UdpHeader *udp = (struct GNUNET_TUN_UdpHeader *) &ipv4[1];
2141 msg->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
2142 msg->size = htons (size);
2143 tun->flags = htons (0);
2144 tun->proto = htons (ETH_P_IPV4);
2145 GNUNET_TUN_initialize_ipv4_header (ipv4,
2147 sizeof (struct GNUNET_TUN_UdpHeader) + mlen,
2148 &ts->destination_ip.v4,
2150 if (0 == ntohs (reply->source_port))
2151 udp->source_port = htons (ts->destination_port);
2153 udp->source_port = reply->source_port;
2154 if (0 == ntohs (reply->destination_port))
2155 udp->destination_port = htons (ts->source_port);
2157 udp->destination_port = reply->destination_port;
2158 udp->len = htons (mlen + sizeof (struct GNUNET_TUN_UdpHeader));
2159 GNUNET_TUN_calculate_udp4_checksum (ipv4,
2166 (void) GNUNET_HELPER_send (helper_handle,
2175 size_t size = sizeof (struct GNUNET_TUN_IPv6Header)
2176 + sizeof (struct GNUNET_TUN_UdpHeader)
2177 + sizeof (struct GNUNET_MessageHeader) +
2178 sizeof (struct GNUNET_TUN_Layer2PacketHeader) +
2181 char buf[size] GNUNET_ALIGN;
2182 struct GNUNET_MessageHeader *msg = (struct GNUNET_MessageHeader *) buf;
2183 struct GNUNET_TUN_Layer2PacketHeader *tun = (struct GNUNET_TUN_Layer2PacketHeader*) &msg[1];
2184 struct GNUNET_TUN_IPv6Header *ipv6 = (struct GNUNET_TUN_IPv6Header *) &tun[1];
2185 struct GNUNET_TUN_UdpHeader *udp = (struct GNUNET_TUN_UdpHeader *) &ipv6[1];
2186 msg->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
2187 msg->size = htons (size);
2188 tun->flags = htons (0);
2189 tun->proto = htons (ETH_P_IPV6);
2190 GNUNET_TUN_initialize_ipv6_header (ipv6,
2192 sizeof (struct GNUNET_TUN_UdpHeader) + mlen,
2193 &ts->destination_ip.v6,
2195 if (0 == ntohs (reply->source_port))
2196 udp->source_port = htons (ts->destination_port);
2198 udp->source_port = reply->source_port;
2199 if (0 == ntohs (reply->destination_port))
2200 udp->destination_port = htons (ts->source_port);
2202 udp->destination_port = reply->destination_port;
2203 udp->len = htons (mlen + sizeof (struct GNUNET_TUN_UdpHeader));
2204 GNUNET_TUN_calculate_udp6_checksum (ipv6,
2210 (void) GNUNET_HELPER_send (helper_handle,
2220 GNUNET_CONTAINER_heap_update_cost (channel_heap,
2222 GNUNET_TIME_absolute_get ().abs_value_us);
2228 * We got a TCP packet back from the CADET channel. Pass it on to the
2229 * local virtual interface via the helper.
2231 * @param cls closure, NULL
2232 * @param channel connection to the other end
2233 * @param channel_ctx pointer to our `struct ChannelState *`
2234 * @param message the actual message
2235 * @return #GNUNET_OK to keep the connection open,
2236 * #GNUNET_SYSERR to close it (signal serious error)
2239 receive_tcp_back (void *cls,
2240 struct GNUNET_CADET_Channel *channel,
2242 const struct GNUNET_MessageHeader *message)
2244 struct ChannelState *ts = *channel_ctx;
2245 const struct GNUNET_EXIT_TcpDataMessage *data;
2248 GNUNET_STATISTICS_update (stats,
2249 gettext_noop ("# TCP packets received from cadet"),
2251 mlen = ntohs (message->size);
2252 if (mlen < sizeof (struct GNUNET_EXIT_TcpDataMessage))
2254 GNUNET_break_op (0);
2255 return GNUNET_SYSERR;
2257 if (NULL == ts->heap_node)
2259 GNUNET_break_op (0);
2260 return GNUNET_SYSERR;
2262 data = (const struct GNUNET_EXIT_TcpDataMessage *) message;
2263 mlen -= sizeof (struct GNUNET_EXIT_TcpDataMessage);
2265 char sbuf[INET6_ADDRSTRLEN];
2266 char dbuf[INET6_ADDRSTRLEN];
2268 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2269 "Received TCP reply from cadet, sending %u bytes from %s:%u -> %s:%u via TUN\n",
2270 (unsigned int) mlen,
2271 inet_ntop (ts->af, &ts->destination_ip, sbuf, sizeof (sbuf)),
2272 ts->destination_port,
2273 inet_ntop (ts->af, &ts->source_ip, dbuf, sizeof (dbuf)),
2276 if (data->tcp_header.off * 4 < sizeof (struct GNUNET_TUN_TcpHeader))
2278 GNUNET_break_op (0);
2279 return GNUNET_SYSERR;
2285 size_t size = sizeof (struct GNUNET_TUN_IPv4Header)
2286 + sizeof (struct GNUNET_TUN_TcpHeader)
2287 + sizeof (struct GNUNET_MessageHeader) +
2288 sizeof (struct GNUNET_TUN_Layer2PacketHeader) +
2291 char buf[size] GNUNET_ALIGN;
2292 struct GNUNET_MessageHeader *msg = (struct GNUNET_MessageHeader *) buf;
2293 struct GNUNET_TUN_Layer2PacketHeader *tun = (struct GNUNET_TUN_Layer2PacketHeader*) &msg[1];
2294 struct GNUNET_TUN_IPv4Header *ipv4 = (struct GNUNET_TUN_IPv4Header *) &tun[1];
2295 struct GNUNET_TUN_TcpHeader *tcp = (struct GNUNET_TUN_TcpHeader *) &ipv4[1];
2296 msg->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
2297 msg->size = htons (size);
2298 tun->flags = htons (0);
2299 tun->proto = htons (ETH_P_IPV4);
2300 GNUNET_TUN_initialize_ipv4_header (ipv4,
2302 sizeof (struct GNUNET_TUN_TcpHeader) + mlen,
2303 &ts->destination_ip.v4,
2305 *tcp = data->tcp_header;
2306 tcp->source_port = htons (ts->destination_port);
2307 tcp->destination_port = htons (ts->source_port);
2308 GNUNET_TUN_calculate_tcp4_checksum (ipv4,
2315 (void) GNUNET_HELPER_send (helper_handle,
2324 size_t size = sizeof (struct GNUNET_TUN_IPv6Header)
2325 + sizeof (struct GNUNET_TUN_TcpHeader)
2326 + sizeof (struct GNUNET_MessageHeader) +
2327 sizeof (struct GNUNET_TUN_Layer2PacketHeader) +
2330 char buf[size] GNUNET_ALIGN;
2331 struct GNUNET_MessageHeader *msg = (struct GNUNET_MessageHeader *) buf;
2332 struct GNUNET_TUN_Layer2PacketHeader *tun = (struct GNUNET_TUN_Layer2PacketHeader*) &msg[1];
2333 struct GNUNET_TUN_IPv6Header *ipv6 = (struct GNUNET_TUN_IPv6Header *) &tun[1];
2334 struct GNUNET_TUN_TcpHeader *tcp = (struct GNUNET_TUN_TcpHeader *) &ipv6[1];
2335 msg->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
2336 msg->size = htons (size);
2337 tun->flags = htons (0);
2338 tun->proto = htons (ETH_P_IPV6);
2339 GNUNET_TUN_initialize_ipv6_header (ipv6,
2341 sizeof (struct GNUNET_TUN_TcpHeader) + mlen,
2342 &ts->destination_ip.v6,
2344 *tcp = data->tcp_header;
2345 tcp->source_port = htons (ts->destination_port);
2346 tcp->destination_port = htons (ts->source_port);
2347 GNUNET_TUN_calculate_tcp6_checksum (ipv6,
2354 (void) GNUNET_HELPER_send (helper_handle,
2362 GNUNET_CONTAINER_heap_update_cost (channel_heap,
2364 GNUNET_TIME_absolute_get ().abs_value_us);
2370 * Allocate an IPv4 address from the range of the channel
2371 * for a new redirection.
2373 * @param v4 where to store the address
2374 * @return #GNUNET_OK on success,
2375 * #GNUNET_SYSERR on error
2378 allocate_v4_address (struct in_addr *v4)
2380 const char *ipv4addr = vpn_argv[4];
2381 const char *ipv4mask = vpn_argv[5];
2382 struct in_addr addr;
2383 struct in_addr mask;
2385 struct GNUNET_HashCode key;
2388 GNUNET_assert (1 == inet_pton (AF_INET, ipv4addr, &addr));
2389 GNUNET_assert (1 == inet_pton (AF_INET, ipv4mask, &mask));
2390 /* Given 192.168.0.1/255.255.0.0, we want a mask
2391 of '192.168.255.255', thus: */
2392 mask.s_addr = addr.s_addr | ~mask.s_addr;
2399 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
2400 _("Failed to find unallocated IPv4 address in VPN's range\n"));
2401 return GNUNET_SYSERR;
2403 /* Pick random IPv4 address within the subnet, except 'addr' or 'mask' itself */
2404 rnd.s_addr = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
2406 v4->s_addr = (addr.s_addr | rnd.s_addr) & mask.s_addr;
2407 get_destination_key_from_ip (AF_INET,
2411 while ( (GNUNET_YES ==
2412 GNUNET_CONTAINER_multihashmap_contains (destination_map,
2414 (v4->s_addr == addr.s_addr) ||
2415 (v4->s_addr == mask.s_addr) );
2421 * Allocate an IPv6 address from the range of the channel
2422 * for a new redirection.
2424 * @param v6 where to store the address
2425 * @return #GNUNET_OK on success,
2426 * #GNUNET_SYSERR on error
2429 allocate_v6_address (struct in6_addr *v6)
2431 const char *ipv6addr = vpn_argv[2];
2432 struct in6_addr addr;
2433 struct in6_addr mask;
2434 struct in6_addr rnd;
2436 struct GNUNET_HashCode key;
2439 GNUNET_assert (1 == inet_pton (AF_INET6, ipv6addr, &addr));
2440 GNUNET_assert (ipv6prefix < 128);
2441 /* Given ABCD::/96, we want a mask of 'ABCD::FFFF:FFFF,
2444 for (i=127;i>=ipv6prefix;i--)
2445 mask.s6_addr[i / 8] |= (1 << (i % 8));
2447 /* Pick random IPv6 address within the subnet, except 'addr' or 'mask' itself */
2454 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
2455 _("Failed to find unallocated IPv6 address in VPN's range\n"));
2456 return GNUNET_SYSERR;
2461 rnd.s6_addr[i] = (unsigned char) GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
2464 = (addr.s6_addr[i] | rnd.s6_addr[i]) & mask.s6_addr[i];
2466 get_destination_key_from_ip (AF_INET6,
2470 while ( (GNUNET_YES ==
2471 GNUNET_CONTAINER_multihashmap_contains (destination_map,
2475 sizeof (struct in6_addr))) ||
2478 sizeof (struct in6_addr))) );
2484 * Free resources occupied by a destination entry.
2486 * @param de entry to free
2489 free_destination_entry (struct DestinationEntry *de)
2491 struct DestinationChannel *dt;
2493 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2494 "Cleaning up destination entry\n");
2495 GNUNET_STATISTICS_update (stats,
2496 gettext_noop ("# Active destinations"),
2498 while (NULL != (dt = de->dt_head))
2500 GNUNET_CONTAINER_DLL_remove (de->dt_head,
2505 free_channel_state (dt->ts);
2506 GNUNET_assert (NULL == dt->ts);
2510 if (NULL != de->heap_node)
2512 GNUNET_CONTAINER_heap_remove_node (de->heap_node);
2513 de->heap_node = NULL;
2514 GNUNET_assert (GNUNET_YES ==
2515 GNUNET_CONTAINER_multihashmap_remove (destination_map,
2524 * We have too many active destinations. Clean up the oldest destination.
2526 * @param except destination that must NOT be cleaned up, even if it is the oldest
2529 expire_destination (struct DestinationEntry *except)
2531 struct DestinationEntry *de;
2533 de = GNUNET_CONTAINER_heap_peek (destination_heap);
2534 GNUNET_assert (NULL != de);
2536 return; /* can't do this */
2537 free_destination_entry (de);
2542 * Allocate an IP address for the response.
2544 * @param result_af desired address family; set to the actual
2545 * address family; can initially be AF_UNSPEC if there
2546 * is no preference; will be set to AF_UNSPEC if the
2548 * @param addr set to either v4 or v6 depending on which
2549 * storage location was used; set to NULL if allocation failed
2550 * @param v4 storage space for an IPv4 address
2551 * @param v6 storage space for an IPv6 address
2552 * @return #GNUNET_OK normally, #GNUNET_SYSERR if `* result_af` was
2553 * an unsupported address family (not AF_INET, AF_INET6 or AF_UNSPEC)
2556 allocate_response_ip (int *result_af,
2559 struct in6_addr *v6)
2566 allocate_v4_address (v4))
2567 *result_af = AF_UNSPEC;
2573 allocate_v6_address (v6))
2574 *result_af = AF_UNSPEC;
2580 allocate_v4_address (v4))
2583 *result_af = AF_INET;
2585 else if (GNUNET_OK ==
2586 allocate_v6_address (v6))
2589 *result_af = AF_INET6;
2594 return GNUNET_SYSERR;
2601 * A client asks us to setup a redirection via some exit node to a
2602 * particular IP. Setup the redirection and give the client the
2606 * @param client requesting client
2607 * @param message redirection request (a `struct RedirectToIpRequestMessage`)
2610 service_redirect_to_ip (void *cls,
2611 struct GNUNET_SERVER_Client *client,
2612 const struct GNUNET_MessageHeader *message)
2616 const struct RedirectToIpRequestMessage *msg;
2622 struct DestinationEntry *de;
2623 struct GNUNET_HashCode key;
2625 /* validate and parse request */
2626 mlen = ntohs (message->size);
2627 if (mlen < sizeof (struct RedirectToIpRequestMessage))
2630 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2633 alen = mlen - sizeof (struct RedirectToIpRequestMessage);
2634 msg = (const struct RedirectToIpRequestMessage *) message;
2635 addr_af = (int) htonl (msg->addr_af);
2639 if (alen != sizeof (struct in_addr))
2642 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2647 if (alen != sizeof (struct in6_addr))
2650 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2656 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2660 /* allocate response IP */
2661 result_af = (int) htonl (msg->result_af);
2662 if (GNUNET_OK != allocate_response_ip (&result_af,
2666 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2669 /* send reply with our IP address */
2670 send_client_reply (client,
2674 if (result_af == AF_UNSPEC)
2676 /* failure, we're done */
2677 GNUNET_SERVER_receive_done (client, GNUNET_OK);
2682 char sbuf[INET6_ADDRSTRLEN];
2683 char dbuf[INET6_ADDRSTRLEN];
2685 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2686 "Allocated address %s for redirection via exit to %s\n",
2687 inet_ntop (result_af, addr, sbuf, sizeof (sbuf)),
2689 &msg[1], dbuf, sizeof (dbuf)));
2692 /* setup destination record */
2693 de = GNUNET_new (struct DestinationEntry);
2694 de->is_service = GNUNET_NO;
2695 de->details.exit_destination.af = addr_af;
2696 memcpy (&de->details.exit_destination.ip,
2699 get_destination_key_from_ip (result_af,
2703 GNUNET_assert (GNUNET_OK ==
2704 GNUNET_CONTAINER_multihashmap_put (destination_map,
2707 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE));
2708 de->heap_node = GNUNET_CONTAINER_heap_insert (destination_heap,
2710 GNUNET_TIME_absolute_ntoh (msg->expiration_time).abs_value_us);
2711 GNUNET_STATISTICS_update (stats,
2712 gettext_noop ("# Active destinations"),
2714 while (GNUNET_CONTAINER_multihashmap_size (destination_map) > max_destination_mappings)
2715 expire_destination (de);
2716 GNUNET_SERVER_receive_done (client, GNUNET_OK);
2721 * A client asks us to setup a redirection to a particular peer
2722 * offering a service. Setup the redirection and give the client the
2726 * @param client requesting client
2727 * @param message redirection request (a `struct RedirectToPeerRequestMessage`)
2730 service_redirect_to_service (void *cls,
2731 struct GNUNET_SERVER_Client *client,
2732 const struct GNUNET_MessageHeader *message)
2734 const struct RedirectToServiceRequestMessage *msg;
2739 struct DestinationEntry *de;
2740 struct GNUNET_HashCode key;
2741 struct ChannelState *ts;
2742 struct DestinationChannel *dt;
2745 msg = (const struct RedirectToServiceRequestMessage *) message;
2747 /* allocate response IP */
2748 result_af = (int) htonl (msg->result_af);
2749 if (GNUNET_OK != allocate_response_ip (&result_af,
2753 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2756 send_client_reply (client,
2760 if (result_af == AF_UNSPEC)
2762 /* failure, we're done */
2763 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2764 _("Failed to allocate IP address for new destination\n"));
2765 GNUNET_SERVER_receive_done (client, GNUNET_OK);
2770 char sbuf[INET6_ADDRSTRLEN];
2772 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2773 "Allocated address %s for redirection to service %s on peer %s\n",
2774 inet_ntop (result_af, addr, sbuf, sizeof (sbuf)),
2775 GNUNET_h2s (&msg->service_descriptor),
2776 GNUNET_i2s (&msg->target));
2779 /* setup destination record */
2780 de = GNUNET_new (struct DestinationEntry);
2781 de->is_service = GNUNET_YES;
2782 de->details.service_destination.service_descriptor = msg->service_descriptor;
2783 de->details.service_destination.target = msg->target;
2784 get_destination_key_from_ip (result_af,
2788 GNUNET_assert (GNUNET_OK ==
2789 GNUNET_CONTAINER_multihashmap_put (destination_map,
2792 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE));
2793 de->heap_node = GNUNET_CONTAINER_heap_insert (destination_heap,
2795 GNUNET_TIME_absolute_ntoh (msg->expiration_time).abs_value_us);
2796 while (GNUNET_CONTAINER_multihashmap_size (destination_map) > max_destination_mappings)
2797 expire_destination (de);
2799 dt = GNUNET_new (struct DestinationChannel);
2800 dt->destination = de;
2801 GNUNET_CONTAINER_DLL_insert (de->dt_head,
2804 ts = create_channel_to_destination (dt,
2809 ts->destination_ip.v4 = v4;
2812 ts->destination_ip.v6 = v6;
2818 GNUNET_SERVER_receive_done (client, GNUNET_OK);
2823 * Function called whenever a channel is destroyed. Should clean up
2824 * any associated state.
2826 * @param cls closure (set from #GNUNET_CADET_connect)
2827 * @param channel connection to the other end (henceforth invalid)
2828 * @param channel_ctx place where local state associated
2829 * with the channel is stored (our `struct ChannelState`)
2832 channel_cleaner (void *cls,
2833 const struct GNUNET_CADET_Channel *channel,
2836 struct ChannelState *ts = channel_ctx;
2838 ts->channel = NULL; /* we must not call GNUNET_CADET_channel_destroy() anymore */
2839 free_channel_state (ts);
2844 * Free memory occupied by an entry in the destination map.
2848 * @param value a `struct DestinationEntry *`
2849 * @return #GNUNET_OK (continue to iterate)
2852 cleanup_destination (void *cls,
2853 const struct GNUNET_HashCode *key,
2856 struct DestinationEntry *de = value;
2858 free_destination_entry (de);
2864 * Free memory occupied by an entry in the channel map.
2868 * @param value a `struct ChannelState *`
2869 * @return #GNUNET_OK (continue to iterate)
2872 cleanup_channel (void *cls,
2873 const struct GNUNET_HashCode *key,
2876 struct ChannelState *ts = value;
2878 free_channel_state (ts);
2884 * Function scheduled as very last function, cleans up after us
2891 const struct GNUNET_SCHEDULER_TaskContext *tc)
2895 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2896 "VPN is shutting down\n");
2897 if (NULL != destination_map)
2899 GNUNET_CONTAINER_multihashmap_iterate (destination_map,
2900 &cleanup_destination,
2902 GNUNET_CONTAINER_multihashmap_destroy (destination_map);
2903 destination_map = NULL;
2905 if (NULL != destination_heap)
2907 GNUNET_CONTAINER_heap_destroy (destination_heap);
2908 destination_heap = NULL;
2910 if (NULL != channel_map)
2912 GNUNET_CONTAINER_multihashmap_iterate (channel_map,
2915 GNUNET_CONTAINER_multihashmap_destroy (channel_map);
2918 if (NULL != channel_heap)
2920 GNUNET_CONTAINER_heap_destroy (channel_heap);
2921 channel_heap = NULL;
2923 if (NULL != cadet_handle)
2925 GNUNET_CADET_disconnect (cadet_handle);
2926 cadet_handle = NULL;
2928 if (NULL != helper_handle)
2930 GNUNET_HELPER_stop (helper_handle, GNUNET_NO);
2931 helper_handle = NULL;
2935 GNUNET_SERVER_notification_context_destroy (nc);
2940 GNUNET_STATISTICS_destroy (stats, GNUNET_NO);
2944 GNUNET_free_non_null (vpn_argv[i]);
2949 * Main function that will be run by the scheduler.
2951 * @param cls closure
2952 * @param server the initialized server
2953 * @param cfg_ configuration
2957 struct GNUNET_SERVER_Handle *server,
2958 const struct GNUNET_CONFIGURATION_Handle *cfg_)
2960 static const struct GNUNET_SERVER_MessageHandler service_handlers[] = {
2961 /* callback, cls, type, size */
2962 { &service_redirect_to_ip, NULL, GNUNET_MESSAGE_TYPE_VPN_CLIENT_REDIRECT_TO_IP, 0},
2963 { &service_redirect_to_service, NULL,
2964 GNUNET_MESSAGE_TYPE_VPN_CLIENT_REDIRECT_TO_SERVICE,
2965 sizeof (struct RedirectToServiceRequestMessage) },
2968 static const struct GNUNET_CADET_MessageHandler cadet_handlers[] = {
2969 { &receive_udp_back, GNUNET_MESSAGE_TYPE_VPN_UDP_REPLY, 0},
2970 { &receive_tcp_back, GNUNET_MESSAGE_TYPE_VPN_TCP_DATA_TO_VPN, 0},
2971 { &receive_icmp_back, GNUNET_MESSAGE_TYPE_VPN_ICMP_TO_VPN, 0},
2983 binary = GNUNET_OS_get_libexec_binary_path ("gnunet-helper-vpn");
2986 GNUNET_OS_check_helper_binary (binary,
2988 "-d gnunet-vpn - - 169.1.3.3.7 255.255.255.0")) //ipv4 only please!
2990 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2991 "`%s' is not SUID, refusing to run.\n",
2992 "gnunet-helper-vpn");
2993 GNUNET_free (binary);
2995 /* we won't "really" exit here, as the 'service' is still running;
2996 however, as no handlers are registered, the service won't do
3000 GNUNET_free (binary);
3002 stats = GNUNET_STATISTICS_create ("vpn", cfg);
3004 GNUNET_CONFIGURATION_get_value_number (cfg, "VPN", "MAX_MAPPING",
3005 &max_destination_mappings))
3006 max_destination_mappings = 200;
3008 GNUNET_CONFIGURATION_get_value_number (cfg, "VPN", "MAX_TUNNELS",
3009 &max_channel_mappings))
3010 max_channel_mappings = 200;
3012 destination_map = GNUNET_CONTAINER_multihashmap_create (max_destination_mappings * 2, GNUNET_NO);
3013 destination_heap = GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN);
3014 channel_map = GNUNET_CONTAINER_multihashmap_create (max_channel_mappings * 2, GNUNET_NO);
3015 channel_heap = GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN);
3018 vpn_argv[0] = GNUNET_strdup ("vpn-gnunet");
3019 if (GNUNET_SYSERR ==
3020 GNUNET_CONFIGURATION_get_value_string (cfg, "VPN", "IFNAME", &ifname))
3022 GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, "VPN", "IFNAME");
3023 GNUNET_SCHEDULER_shutdown ();
3026 vpn_argv[1] = ifname;
3028 if (GNUNET_OK == GNUNET_NETWORK_test_pf (PF_INET6))
3030 if ( (GNUNET_SYSERR ==
3031 GNUNET_CONFIGURATION_get_value_string (cfg, "VPN", "IPV6ADDR",
3033 (1 != inet_pton (AF_INET6, ipv6addr, &v6))) )
3035 GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, "VPN", "IPV6ADDR",
3036 _("Must specify valid IPv6 address"));
3037 GNUNET_SCHEDULER_shutdown ();
3038 GNUNET_free_non_null (ipv6addr);
3041 vpn_argv[2] = ipv6addr;
3042 ipv6prefix_s = NULL;
3043 if (GNUNET_SYSERR ==
3044 GNUNET_CONFIGURATION_get_value_string (cfg, "VPN", "IPV6PREFIX",
3047 GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, "VPN", "IPV6PREFIX");
3048 GNUNET_SCHEDULER_shutdown ();
3049 GNUNET_free_non_null (ipv6prefix_s);
3052 vpn_argv[3] = ipv6prefix_s;
3054 GNUNET_CONFIGURATION_get_value_number (cfg, "VPN",
3057 (ipv6prefix >= 127) )
3059 GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, "VPN", "IPV4MASK",
3060 _("Must specify valid IPv6 mask"));
3061 GNUNET_SCHEDULER_shutdown ();
3067 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
3068 _("IPv6 support disabled as this system does not support IPv6\n"));
3069 vpn_argv[2] = GNUNET_strdup ("-");
3070 vpn_argv[3] = GNUNET_strdup ("-");
3072 if (GNUNET_OK == GNUNET_NETWORK_test_pf (PF_INET))
3075 if ( (GNUNET_SYSERR ==
3076 GNUNET_CONFIGURATION_get_value_string (cfg, "vpn", "IPV4ADDR",
3078 (1 != inet_pton (AF_INET, ipv4addr, &v4))) )
3080 GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, "VPN", "IPV4ADDR",
3081 _("Must specify valid IPv4 address"));
3082 GNUNET_SCHEDULER_shutdown ();
3083 GNUNET_free_non_null (ipv4addr);
3086 vpn_argv[4] = ipv4addr;
3088 if ( (GNUNET_SYSERR ==
3089 GNUNET_CONFIGURATION_get_value_string (cfg, "vpn", "IPV4MASK",
3091 (1 != inet_pton (AF_INET, ipv4mask, &v4))) )
3093 GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, "VPN", "IPV4MASK",
3094 _("Must specify valid IPv4 mask"));
3095 GNUNET_SCHEDULER_shutdown ();
3096 GNUNET_free_non_null (ipv4mask);
3099 vpn_argv[5] = ipv4mask;
3103 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
3104 _("IPv4 support disabled as this system does not support IPv4\n"));
3105 vpn_argv[4] = GNUNET_strdup ("-");
3106 vpn_argv[5] = GNUNET_strdup ("-");
3111 GNUNET_CADET_connect (cfg_, NULL,
3116 helper_handle = GNUNET_HELPER_start (GNUNET_NO,
3117 "gnunet-helper-vpn", vpn_argv,
3118 &message_token, NULL, NULL);
3119 nc = GNUNET_SERVER_notification_context_create (server, 1);
3120 GNUNET_SERVER_add_handlers (server, service_handlers);
3121 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &cleanup, cls);
3126 * The main function of the VPN service.
3128 * @param argc number of arguments from the command line
3129 * @param argv command line arguments
3130 * @return 0 ok, 1 on error
3133 main (int argc, char *const *argv)
3135 return (GNUNET_OK ==
3136 GNUNET_SERVICE_run (argc, argv, "vpn",
3137 GNUNET_SERVICE_OPTION_NONE,
3138 &run, NULL)) ? global_ret : 1;
3141 /* end of gnunet-service-vpn.c */