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 search for destination %s complete!\n",
750 print_channel_destination (&ts->destination),
754 apptype = GNUNET_APPLICATION_TYPE_IPV4_GATEWAY;
757 apptype = GNUNET_APPLICATION_TYPE_IPV6_GATEWAY;
763 ts->channel = GNUNET_CADET_channel_create (cadet_handle,
767 GNUNET_CADET_OPTION_DEFAULT);
772 * Initialize the given destination entry's cadet channel.
774 * @param dt destination channel for which we need to setup a channel
775 * @param client_af address family of the address returned to the client
776 * @return channel state of the channel that was created
778 static struct ChannelState *
779 create_channel_to_destination (struct DestinationChannel *dt,
782 struct ChannelState *ts;
783 unsigned int apptype;
785 GNUNET_STATISTICS_update (stats,
786 gettext_noop ("# Cadet channels created"),
788 GNUNET_assert (NULL == dt->ts);
792 apptype = GNUNET_APPLICATION_TYPE_IPV4_GATEWAY;
795 apptype = GNUNET_APPLICATION_TYPE_IPV6_GATEWAY;
801 ts = GNUNET_new (struct ChannelState);
803 ts->destination = *dt->destination;
804 ts->destination.heap_node = NULL; /* copy is NOT in destination heap */
806 ts->destination_container = dt; /* we are referenced from dt */
807 if (dt->destination->is_service)
809 ts->channel = GNUNET_CADET_channel_create (cadet_handle,
811 &dt->destination->details.service_destination.target,
813 GNUNET_CADET_OPTION_DEFAULT);
814 if (NULL == ts->channel)
816 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
817 _("Failed to setup cadet channel!\n"));
821 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
822 "Creating channel to peer %s offering service %s\n",
823 GNUNET_i2s (&dt->destination->details.service_destination.target),
824 GNUNET_h2s (&dt->destination->details.service_destination.service_descriptor));
830 switch (dt->destination->details.exit_destination.af)
834 char address[GNUNET_TUN_IPV4_REGEXLEN];
836 GNUNET_TUN_ipv4toregexsearch (&dt->destination->details.exit_destination.ip.v4,
837 dt->destination_port,
839 GNUNET_asprintf (&policy,
841 GNUNET_APPLICATION_TYPE_EXIT_REGEX_PREFIX,
847 char address[GNUNET_TUN_IPV6_REGEXLEN];
849 GNUNET_TUN_ipv6toregexsearch (&dt->destination->details.exit_destination.ip.v6,
850 dt->destination_port,
852 GNUNET_asprintf (&policy,
854 GNUNET_APPLICATION_TYPE_EXIT_REGEX_PREFIX,
863 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
864 "Requesting connect by string: %s\n",
866 ts->search = GNUNET_REGEX_search (cfg,
868 &handle_regex_result,
870 GNUNET_free (policy);
877 * We have too many active channels. Clean up the oldest channel.
879 * @param except channel that must NOT be cleaned up, even if it is the oldest
882 expire_channel (struct ChannelState *except)
884 struct ChannelState *ts;
886 ts = GNUNET_CONTAINER_heap_peek (channel_heap);
887 GNUNET_assert (NULL != ts);
889 return; /* can't do this */
890 free_channel_state (ts);
895 * Route a packet via cadet to the given destination.
897 * @param destination description of the destination
898 * @param af address family on this end (AF_INET or AF_INET6)
899 * @param protocol IPPROTO_TCP or IPPROTO_UDP or IPPROTO_ICMP or IPPROTO_ICMPV6
900 * @param source_ip source IP used by the sender (struct in_addr or struct in6_addr)
901 * @param destination_ip destination IP used by the sender (struct in_addr or struct in6_addr)
902 * @param payload payload of the packet after the IP header
903 * @param payload_length number of bytes in @a payload
906 route_packet (struct DestinationEntry *destination,
909 const void *source_ip,
910 const void *destination_ip,
912 size_t payload_length)
914 struct GNUNET_HashCode key;
915 struct ChannelState *ts;
916 struct ChannelMessageQueueEntry *tnq;
920 const struct GNUNET_TUN_UdpHeader *udp;
921 const struct GNUNET_TUN_TcpHeader *tcp;
922 const struct GNUNET_TUN_IcmpHeader *icmp;
923 struct DestinationChannel *dt;
924 uint16_t source_port;
925 uint16_t destination_port;
931 if (payload_length < sizeof (struct GNUNET_TUN_UdpHeader))
937 tcp = NULL; /* make compiler happy */
938 icmp = NULL; /* make compiler happy */
940 if (udp->len < sizeof (struct GNUNET_TUN_UdpHeader))
945 source_port = ntohs (udp->source_port);
946 destination_port = ntohs (udp->destination_port);
947 get_channel_key_from_ips (af,
958 if (payload_length < sizeof (struct GNUNET_TUN_TcpHeader))
964 udp = NULL; /* make compiler happy */
965 icmp = NULL; /* make compiler happy */
967 if (tcp->off * 4 < sizeof (struct GNUNET_TUN_TcpHeader))
972 source_port = ntohs (tcp->source_port);
973 destination_port = ntohs (tcp->destination_port);
974 get_channel_key_from_ips (af,
986 if ( (AF_INET == af) ^ (protocol == IPPROTO_ICMP) )
991 if (payload_length < sizeof (struct GNUNET_TUN_IcmpHeader))
997 tcp = NULL; /* make compiler happy */
998 udp = NULL; /* make compiler happy */
1001 destination_port = 0;
1002 get_channel_key_from_ips (af,
1012 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1013 _("Protocol %u not supported, dropping\n"),
1014 (unsigned int) protocol);
1018 if (! destination->is_service)
1020 switch (destination->details.exit_destination.af)
1023 alen = sizeof (struct in_addr);
1026 alen = sizeof (struct in6_addr);
1033 char sbuf[INET6_ADDRSTRLEN];
1034 char dbuf[INET6_ADDRSTRLEN];
1035 char xbuf[INET6_ADDRSTRLEN];
1037 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1038 "Routing %s packet from %s:%u -> %s:%u to destination %s:%u\n",
1039 (protocol == IPPROTO_TCP) ? "TCP" : "UDP",
1040 inet_ntop (af, source_ip, sbuf, sizeof (sbuf)),
1042 inet_ntop (af, destination_ip, dbuf, sizeof (dbuf)),
1044 inet_ntop (destination->details.exit_destination.af,
1045 &destination->details.exit_destination.ip,
1046 xbuf, sizeof (xbuf)),
1049 for (dt = destination->dt_head; NULL != dt; dt = dt->next)
1050 if (dt->destination_port == destination_port)
1056 char sbuf[INET6_ADDRSTRLEN];
1057 char dbuf[INET6_ADDRSTRLEN];
1059 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1060 "Routing %s packet from %s:%u -> %s:%u to service %s at peer %s\n",
1061 (protocol == IPPROTO_TCP) ? "TCP" : "UDP",
1062 inet_ntop (af, source_ip, sbuf, sizeof (sbuf)),
1064 inet_ntop (af, destination_ip, dbuf, sizeof (dbuf)),
1066 GNUNET_h2s (&destination->details.service_destination.service_descriptor),
1067 GNUNET_i2s (&destination->details.service_destination.target));
1069 dt = destination->dt_head;
1073 dt = GNUNET_new (struct DestinationChannel);
1074 dt->destination = destination;
1075 GNUNET_CONTAINER_DLL_insert (destination->dt_head,
1076 destination->dt_tail,
1078 dt->destination_port = destination_port;
1081 /* see if we have an existing channel for this destination */
1082 ts = GNUNET_CONTAINER_multihashmap_get (channel_map,
1086 /* need to either use the existing channel from the destination (if still
1087 available) or create a fresh one */
1088 is_new = GNUNET_YES;
1090 ts = create_channel_to_destination (dt, af);
1096 ts->destination_container = NULL; /* no longer 'contained' */
1097 /* now bind existing "unbound" channel to our IP/port tuple */
1098 ts->protocol = protocol;
1102 ts->source_ip.v4 = * (const struct in_addr *) source_ip;
1103 ts->destination_ip.v4 = * (const struct in_addr *) destination_ip;
1107 ts->source_ip.v6 = * (const struct in6_addr *) source_ip;
1108 ts->destination_ip.v6 = * (const struct in6_addr *) destination_ip;
1110 ts->source_port = source_port;
1111 ts->destination_port = destination_port;
1112 ts->heap_node = GNUNET_CONTAINER_heap_insert (channel_heap,
1114 GNUNET_TIME_absolute_get ().abs_value_us);
1115 GNUNET_assert (GNUNET_YES ==
1116 GNUNET_CONTAINER_multihashmap_put (channel_map,
1119 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
1120 GNUNET_STATISTICS_update (stats,
1121 gettext_noop ("# Active channels"),
1123 while (GNUNET_CONTAINER_multihashmap_size (channel_map) > max_channel_mappings)
1124 expire_channel (ts);
1129 GNUNET_CONTAINER_heap_update_cost (channel_heap,
1131 GNUNET_TIME_absolute_get ().abs_value_us);
1133 if (NULL == ts->channel)
1135 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1136 "Packet dropped, channel to %s not yet ready (%s)\n",
1137 print_channel_destination (&ts->destination),
1138 (NULL == ts->search)
1139 ? "EXIT search failed"
1140 : "EXIT search active");
1141 GNUNET_STATISTICS_update (stats,
1142 gettext_noop ("# Packets dropped (channel not yet online)"),
1148 /* send via channel */
1152 if (destination->is_service)
1154 struct GNUNET_EXIT_UdpServiceMessage *usm;
1156 mlen = sizeof (struct GNUNET_EXIT_UdpServiceMessage) +
1157 payload_length - sizeof (struct GNUNET_TUN_UdpHeader);
1158 if (mlen >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1163 tnq = GNUNET_malloc (sizeof (struct ChannelMessageQueueEntry) + mlen);
1166 usm = (struct GNUNET_EXIT_UdpServiceMessage *) &tnq[1];
1167 usm->header.size = htons ((uint16_t) mlen);
1168 usm->header.type = htons (GNUNET_MESSAGE_TYPE_VPN_UDP_TO_SERVICE);
1169 /* if the source port is below 32000, we assume it has a special
1170 meaning; if not, we pick a random port (this is a heuristic) */
1171 usm->source_port = (ntohs (udp->source_port) < 32000) ? udp->source_port : 0;
1172 usm->destination_port = udp->destination_port;
1173 usm->service_descriptor = destination->details.service_destination.service_descriptor;
1176 payload_length - sizeof (struct GNUNET_TUN_UdpHeader));
1180 struct GNUNET_EXIT_UdpInternetMessage *uim;
1181 struct in_addr *ip4dst;
1182 struct in6_addr *ip6dst;
1185 mlen = sizeof (struct GNUNET_EXIT_UdpInternetMessage) +
1186 alen + payload_length - sizeof (struct GNUNET_TUN_UdpHeader);
1187 if (mlen >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1192 tnq = GNUNET_malloc (sizeof (struct ChannelMessageQueueEntry) + mlen);
1195 uim = (struct GNUNET_EXIT_UdpInternetMessage *) &tnq[1];
1196 uim->header.size = htons ((uint16_t) mlen);
1197 uim->header.type = htons (GNUNET_MESSAGE_TYPE_VPN_UDP_TO_INTERNET);
1198 uim->af = htonl (destination->details.exit_destination.af);
1199 uim->source_port = (ntohs (udp->source_port) < 32000) ? udp->source_port : 0;
1200 uim->destination_port = udp->destination_port;
1201 switch (destination->details.exit_destination.af)
1204 ip4dst = (struct in_addr *) &uim[1];
1205 *ip4dst = destination->details.exit_destination.ip.v4;
1206 payload = &ip4dst[1];
1209 ip6dst = (struct in6_addr *) &uim[1];
1210 *ip6dst = destination->details.exit_destination.ip.v6;
1211 payload = &ip6dst[1];
1218 payload_length - sizeof (struct GNUNET_TUN_UdpHeader));
1224 if (destination->is_service)
1226 struct GNUNET_EXIT_TcpServiceStartMessage *tsm;
1228 mlen = sizeof (struct GNUNET_EXIT_TcpServiceStartMessage) +
1229 payload_length - sizeof (struct GNUNET_TUN_TcpHeader);
1230 if (mlen >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1235 tnq = GNUNET_malloc (sizeof (struct ChannelMessageQueueEntry) + mlen);
1238 tsm = (struct GNUNET_EXIT_TcpServiceStartMessage *) &tnq[1];
1239 tsm->header.size = htons ((uint16_t) mlen);
1240 tsm->header.type = htons (GNUNET_MESSAGE_TYPE_VPN_TCP_TO_SERVICE_START);
1241 tsm->reserved = htonl (0);
1242 tsm->service_descriptor = destination->details.service_destination.service_descriptor;
1243 tsm->tcp_header = *tcp;
1246 payload_length - sizeof (struct GNUNET_TUN_TcpHeader));
1250 struct GNUNET_EXIT_TcpInternetStartMessage *tim;
1251 struct in_addr *ip4dst;
1252 struct in6_addr *ip6dst;
1255 mlen = sizeof (struct GNUNET_EXIT_TcpInternetStartMessage) +
1256 alen + payload_length - sizeof (struct GNUNET_TUN_TcpHeader);
1257 if (mlen >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1262 tnq = GNUNET_malloc (sizeof (struct ChannelMessageQueueEntry) + mlen);
1265 tim = (struct GNUNET_EXIT_TcpInternetStartMessage *) &tnq[1];
1266 tim->header.size = htons ((uint16_t) mlen);
1267 tim->header.type = htons (GNUNET_MESSAGE_TYPE_VPN_TCP_TO_INTERNET_START);
1268 tim->af = htonl (destination->details.exit_destination.af);
1269 tim->tcp_header = *tcp;
1270 switch (destination->details.exit_destination.af)
1273 ip4dst = (struct in_addr *) &tim[1];
1274 *ip4dst = destination->details.exit_destination.ip.v4;
1275 payload = &ip4dst[1];
1278 ip6dst = (struct in6_addr *) &tim[1];
1279 *ip6dst = destination->details.exit_destination.ip.v6;
1280 payload = &ip6dst[1];
1287 payload_length - sizeof (struct GNUNET_TUN_TcpHeader));
1292 struct GNUNET_EXIT_TcpDataMessage *tdm;
1294 mlen = sizeof (struct GNUNET_EXIT_TcpDataMessage) +
1295 payload_length - sizeof (struct GNUNET_TUN_TcpHeader);
1296 if (mlen >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1301 tnq = GNUNET_malloc (sizeof (struct ChannelMessageQueueEntry) + mlen);
1304 tdm = (struct GNUNET_EXIT_TcpDataMessage *) &tnq[1];
1305 tdm->header.size = htons ((uint16_t) mlen);
1306 tdm->header.type = htons (GNUNET_MESSAGE_TYPE_VPN_TCP_DATA_TO_EXIT);
1307 tdm->reserved = htonl (0);
1308 tdm->tcp_header = *tcp;
1311 payload_length - sizeof (struct GNUNET_TUN_TcpHeader));
1315 case IPPROTO_ICMPV6:
1316 if (destination->is_service)
1318 struct GNUNET_EXIT_IcmpServiceMessage *ism;
1320 mlen = sizeof (struct GNUNET_EXIT_IcmpServiceMessage) +
1321 payload_length - sizeof (struct GNUNET_TUN_IcmpHeader);
1322 if (mlen >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1327 tnq = GNUNET_malloc (sizeof (struct ChannelMessageQueueEntry) + mlen);
1329 ism = (struct GNUNET_EXIT_IcmpServiceMessage *) &tnq[1];
1330 ism->header.type = htons (GNUNET_MESSAGE_TYPE_VPN_ICMP_TO_SERVICE);
1331 ism->af = htonl (af); /* need to tell destination ICMP protocol family! */
1332 ism->service_descriptor = destination->details.service_destination.service_descriptor;
1333 ism->icmp_header = *icmp;
1334 /* ICMP protocol translation will be done by the receiver (as we don't know
1335 the target AF); however, we still need to possibly discard the payload
1336 depending on the ICMP type */
1342 case GNUNET_TUN_ICMPTYPE_ECHO_REPLY:
1343 case GNUNET_TUN_ICMPTYPE_ECHO_REQUEST:
1345 case GNUNET_TUN_ICMPTYPE_DESTINATION_UNREACHABLE:
1346 case GNUNET_TUN_ICMPTYPE_SOURCE_QUENCH:
1347 case GNUNET_TUN_ICMPTYPE_TIME_EXCEEDED:
1348 /* throw away ICMP payload, won't be useful for the other side anyway */
1349 payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
1352 GNUNET_STATISTICS_update (stats,
1353 gettext_noop ("# ICMPv4 packets dropped (not allowed)"),
1357 /* end of AF_INET */
1362 case GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE:
1363 case GNUNET_TUN_ICMPTYPE6_PACKET_TOO_BIG:
1364 case GNUNET_TUN_ICMPTYPE6_TIME_EXCEEDED:
1365 case GNUNET_TUN_ICMPTYPE6_PARAMETER_PROBLEM:
1366 /* throw away ICMP payload, won't be useful for the other side anyway */
1367 payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
1369 case GNUNET_TUN_ICMPTYPE6_ECHO_REQUEST:
1370 case GNUNET_TUN_ICMPTYPE6_ECHO_REPLY:
1373 GNUNET_STATISTICS_update (stats,
1374 gettext_noop ("# ICMPv6 packets dropped (not allowed)"),
1378 /* end of AF_INET6 */
1385 /* update length calculations, as payload_length may have changed */
1386 mlen = sizeof (struct GNUNET_EXIT_IcmpServiceMessage) +
1387 alen + payload_length - sizeof (struct GNUNET_TUN_IcmpHeader);
1389 ism->header.size = htons ((uint16_t) mlen);
1390 /* finally, copy payload (if there is any left...) */
1393 payload_length - sizeof (struct GNUNET_TUN_IcmpHeader));
1397 struct GNUNET_EXIT_IcmpInternetMessage *iim;
1398 struct in_addr *ip4dst;
1399 struct in6_addr *ip6dst;
1402 mlen = sizeof (struct GNUNET_EXIT_IcmpInternetMessage) +
1403 alen + payload_length - sizeof (struct GNUNET_TUN_IcmpHeader);
1404 if (mlen >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1409 tnq = GNUNET_malloc (sizeof (struct ChannelMessageQueueEntry) + mlen);
1411 iim = (struct GNUNET_EXIT_IcmpInternetMessage *) &tnq[1];
1412 iim->header.type = htons (GNUNET_MESSAGE_TYPE_VPN_ICMP_TO_INTERNET);
1413 iim->icmp_header = *icmp;
1414 /* Perform ICMP protocol-translation (depending on destination AF and source AF)
1415 and throw away ICMP payload depending on ICMP message type */
1421 case GNUNET_TUN_ICMPTYPE_ECHO_REPLY:
1422 if (destination->details.exit_destination.af == AF_INET6)
1423 iim->icmp_header.type = GNUNET_TUN_ICMPTYPE6_ECHO_REPLY;
1425 case GNUNET_TUN_ICMPTYPE_ECHO_REQUEST:
1426 if (destination->details.exit_destination.af == AF_INET6)
1427 iim->icmp_header.type = GNUNET_TUN_ICMPTYPE6_ECHO_REQUEST;
1429 case GNUNET_TUN_ICMPTYPE_DESTINATION_UNREACHABLE:
1430 if (destination->details.exit_destination.af == AF_INET6)
1431 iim->icmp_header.type = GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE;
1432 /* throw away IP-payload, exit will have to make it up anyway */
1433 payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
1435 case GNUNET_TUN_ICMPTYPE_TIME_EXCEEDED:
1436 if (destination->details.exit_destination.af == AF_INET6)
1437 iim->icmp_header.type = GNUNET_TUN_ICMPTYPE6_TIME_EXCEEDED;
1438 /* throw away IP-payload, exit will have to make it up anyway */
1439 payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
1441 case GNUNET_TUN_ICMPTYPE_SOURCE_QUENCH:
1442 if (destination->details.exit_destination.af == AF_INET6)
1444 GNUNET_STATISTICS_update (stats,
1445 gettext_noop ("# ICMPv4 packets dropped (impossible PT to v6)"),
1450 /* throw away IP-payload, exit will have to make it up anyway */
1451 payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
1454 GNUNET_STATISTICS_update (stats,
1455 gettext_noop ("# ICMPv4 packets dropped (type not allowed)"),
1460 /* end of AF_INET */
1465 case GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE:
1466 if (destination->details.exit_destination.af == AF_INET6)
1467 iim->icmp_header.type = GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE;
1468 /* throw away IP-payload, exit will have to make it up anyway */
1469 payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
1471 case GNUNET_TUN_ICMPTYPE6_TIME_EXCEEDED:
1472 if (destination->details.exit_destination.af == AF_INET)
1473 iim->icmp_header.type = GNUNET_TUN_ICMPTYPE_TIME_EXCEEDED;
1474 /* throw away IP-payload, exit will have to make it up anyway */
1475 payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
1477 case GNUNET_TUN_ICMPTYPE6_PACKET_TOO_BIG:
1478 if (destination->details.exit_destination.af == AF_INET)
1480 GNUNET_STATISTICS_update (stats,
1481 gettext_noop ("# ICMPv6 packets dropped (impossible PT to v4)"),
1486 /* throw away IP-payload, exit will have to make it up anyway */
1487 payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
1489 case GNUNET_TUN_ICMPTYPE6_PARAMETER_PROBLEM:
1490 if (destination->details.exit_destination.af == AF_INET)
1492 GNUNET_STATISTICS_update (stats,
1493 gettext_noop ("# ICMPv6 packets dropped (impossible PT to v4)"),
1498 /* throw away IP-payload, exit will have to make it up anyway */
1499 payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
1501 case GNUNET_TUN_ICMPTYPE6_ECHO_REQUEST:
1502 if (destination->details.exit_destination.af == AF_INET)
1503 iim->icmp_header.type = GNUNET_TUN_ICMPTYPE_ECHO_REQUEST;
1505 case GNUNET_TUN_ICMPTYPE6_ECHO_REPLY:
1506 if (destination->details.exit_destination.af == AF_INET)
1507 iim->icmp_header.type = GNUNET_TUN_ICMPTYPE_ECHO_REPLY;
1510 GNUNET_STATISTICS_update (stats,
1511 gettext_noop ("# ICMPv6 packets dropped (type not allowed)"),
1516 /* end of AF_INET6 */
1521 /* update length calculations, as payload_length may have changed */
1522 mlen = sizeof (struct GNUNET_EXIT_IcmpInternetMessage) +
1523 alen + payload_length - sizeof (struct GNUNET_TUN_IcmpHeader);
1525 iim->header.size = htons ((uint16_t) mlen);
1527 /* need to tell destination ICMP protocol family! */
1528 iim->af = htonl (destination->details.exit_destination.af);
1529 switch (destination->details.exit_destination.af)
1532 ip4dst = (struct in_addr *) &iim[1];
1533 *ip4dst = destination->details.exit_destination.ip.v4;
1534 payload = &ip4dst[1];
1537 ip6dst = (struct in6_addr *) &iim[1];
1538 *ip6dst = destination->details.exit_destination.ip.v6;
1539 payload = &ip6dst[1];
1546 payload_length - sizeof (struct GNUNET_TUN_IcmpHeader));
1550 /* not supported above, how can we get here !? */
1554 send_to_channel (tnq, ts);
1559 * Receive packets from the helper-process (someone send to the local
1560 * virtual channel interface). Find the destination mapping, and if it
1561 * exists, identify the correct CADET channel (or possibly create it)
1562 * and forward the packet.
1564 * @param cls closure, NULL
1565 * @param client NULL
1566 * @param message message we got from the client (VPN channel interface)
1569 message_token (void *cls,
1571 const struct GNUNET_MessageHeader *message)
1573 const struct GNUNET_TUN_Layer2PacketHeader *tun;
1575 struct GNUNET_HashCode key;
1576 struct DestinationEntry *de;
1578 GNUNET_STATISTICS_update (stats,
1579 gettext_noop ("# Packets received from TUN interface"),
1581 mlen = ntohs (message->size);
1582 if ( (ntohs (message->type) != GNUNET_MESSAGE_TYPE_VPN_HELPER) ||
1583 (mlen < sizeof (struct GNUNET_MessageHeader) + sizeof (struct GNUNET_TUN_Layer2PacketHeader)) )
1588 tun = (const struct GNUNET_TUN_Layer2PacketHeader *) &message[1];
1589 mlen -= (sizeof (struct GNUNET_MessageHeader) + sizeof (struct GNUNET_TUN_Layer2PacketHeader));
1590 switch (ntohs (tun->proto))
1594 const struct GNUNET_TUN_IPv6Header *pkt6;
1596 if (mlen < sizeof (struct GNUNET_TUN_IPv6Header))
1602 pkt6 = (const struct GNUNET_TUN_IPv6Header *) &tun[1];
1603 get_destination_key_from_ip (AF_INET6,
1604 &pkt6->destination_address,
1606 de = GNUNET_CONTAINER_multihashmap_get (destination_map, &key);
1609 char buf[INET6_ADDRSTRLEN];
1611 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1612 _("Packet received for unmapped destination `%s' (dropping it)\n"),
1613 inet_ntop (AF_INET6,
1614 &pkt6->destination_address,
1622 &pkt6->source_address,
1623 &pkt6->destination_address,
1625 mlen - sizeof (struct GNUNET_TUN_IPv6Header));
1630 struct GNUNET_TUN_IPv4Header *pkt4;
1632 if (mlen < sizeof (struct GNUNET_TUN_IPv4Header))
1638 pkt4 = (struct GNUNET_TUN_IPv4Header *) &tun[1];
1639 get_destination_key_from_ip (AF_INET,
1640 &pkt4->destination_address,
1642 de = GNUNET_CONTAINER_multihashmap_get (destination_map, &key);
1645 char buf[INET_ADDRSTRLEN];
1647 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1648 _("Packet received for unmapped destination `%s' (dropping it)\n"),
1650 &pkt4->destination_address,
1655 if (pkt4->header_length * 4 != sizeof (struct GNUNET_TUN_IPv4Header))
1657 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1658 _("Received IPv4 packet with options (dropping it)\n"));
1664 &pkt4->source_address,
1665 &pkt4->destination_address,
1667 mlen - sizeof (struct GNUNET_TUN_IPv4Header));
1671 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1672 _("Received packet of unknown protocol %d from TUN (dropping it)\n"),
1673 (unsigned int) ntohs (tun->proto));
1681 * Synthesize a plausible ICMP payload for an ICMP error
1682 * response on the given channel.
1684 * @param ts channel information
1685 * @param ipp IPv4 header to fill in (ICMP payload)
1686 * @param udp "UDP" header to fill in (ICMP payload); might actually
1687 * also be the first 8 bytes of the TCP header
1690 make_up_icmpv4_payload (struct ChannelState *ts,
1691 struct GNUNET_TUN_IPv4Header *ipp,
1692 struct GNUNET_TUN_UdpHeader *udp)
1694 GNUNET_TUN_initialize_ipv4_header (ipp,
1696 sizeof (struct GNUNET_TUN_TcpHeader),
1698 &ts->destination_ip.v4);
1699 udp->source_port = htons (ts->source_port);
1700 udp->destination_port = htons (ts->destination_port);
1701 udp->len = htons (0);
1702 udp->crc = htons (0);
1707 * Synthesize a plausible ICMP payload for an ICMP error
1708 * response on the given channel.
1710 * @param ts channel information
1711 * @param ipp IPv6 header to fill in (ICMP payload)
1712 * @param udp "UDP" header to fill in (ICMP payload); might actually
1713 * also be the first 8 bytes of the TCP header
1716 make_up_icmpv6_payload (struct ChannelState *ts,
1717 struct GNUNET_TUN_IPv6Header *ipp,
1718 struct GNUNET_TUN_UdpHeader *udp)
1720 GNUNET_TUN_initialize_ipv6_header (ipp,
1722 sizeof (struct GNUNET_TUN_TcpHeader),
1724 &ts->destination_ip.v6);
1725 udp->source_port = htons (ts->source_port);
1726 udp->destination_port = htons (ts->destination_port);
1727 udp->len = htons (0);
1728 udp->crc = htons (0);
1733 * We got an ICMP packet back from the CADET channel. Pass it on to the
1734 * local virtual interface via the helper.
1736 * @param cls closure, NULL
1737 * @param channel connection to the other end
1738 * @param channel_ctx pointer to our 'struct ChannelState *'
1739 * @param message the actual message
1740 * @return #GNUNET_OK to keep the connection open,
1741 * #GNUNET_SYSERR to close it (signal serious error)
1744 receive_icmp_back (void *cls,
1745 struct GNUNET_CADET_Channel *channel,
1747 const struct GNUNET_MessageHeader *message)
1749 struct ChannelState *ts = *channel_ctx;
1750 const struct GNUNET_EXIT_IcmpToVPNMessage *i2v;
1753 GNUNET_STATISTICS_update (stats,
1754 gettext_noop ("# ICMP packets received from cadet"),
1756 mlen = ntohs (message->size);
1757 if (mlen < sizeof (struct GNUNET_EXIT_IcmpToVPNMessage))
1759 GNUNET_break_op (0);
1760 return GNUNET_SYSERR;
1762 if (NULL == ts->heap_node)
1764 GNUNET_break_op (0);
1765 return GNUNET_SYSERR;
1767 if (AF_UNSPEC == ts->af)
1769 GNUNET_break_op (0);
1770 return GNUNET_SYSERR;
1772 i2v = (const struct GNUNET_EXIT_IcmpToVPNMessage *) message;
1773 mlen -= sizeof (struct GNUNET_EXIT_IcmpToVPNMessage);
1775 char sbuf[INET6_ADDRSTRLEN];
1776 char dbuf[INET6_ADDRSTRLEN];
1778 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1779 "Received ICMP packet from cadet, sending %u bytes from %s -> %s via TUN\n",
1780 (unsigned int) mlen,
1781 inet_ntop (ts->af, &ts->destination_ip, sbuf, sizeof (sbuf)),
1782 inet_ntop (ts->af, &ts->source_ip, dbuf, sizeof (dbuf)));
1788 size_t size = sizeof (struct GNUNET_TUN_IPv4Header)
1789 + sizeof (struct GNUNET_TUN_IcmpHeader)
1790 + sizeof (struct GNUNET_MessageHeader) +
1791 sizeof (struct GNUNET_TUN_Layer2PacketHeader) +
1794 /* reserve some extra space in case we have an ICMP type here where
1795 we will need to make up the payload ourselves */
1796 char buf[size + sizeof (struct GNUNET_TUN_IPv4Header) + 8] GNUNET_ALIGN;
1797 struct GNUNET_MessageHeader *msg = (struct GNUNET_MessageHeader *) buf;
1798 struct GNUNET_TUN_Layer2PacketHeader *tun = (struct GNUNET_TUN_Layer2PacketHeader*) &msg[1];
1799 struct GNUNET_TUN_IPv4Header *ipv4 = (struct GNUNET_TUN_IPv4Header *) &tun[1];
1800 struct GNUNET_TUN_IcmpHeader *icmp = (struct GNUNET_TUN_IcmpHeader *) &ipv4[1];
1801 msg->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
1802 tun->flags = htons (0);
1803 tun->proto = htons (ETH_P_IPV4);
1804 GNUNET_TUN_initialize_ipv4_header (ipv4,
1806 sizeof (struct GNUNET_TUN_IcmpHeader) + mlen,
1807 &ts->destination_ip.v4,
1809 *icmp = i2v->icmp_header;
1813 /* For some ICMP types, we need to adjust (make up) the payload here.
1814 Also, depending on the AF used on the other side, we have to
1815 do ICMP PT (translate ICMP types) */
1816 switch (ntohl (i2v->af))
1821 case GNUNET_TUN_ICMPTYPE_ECHO_REPLY:
1822 case GNUNET_TUN_ICMPTYPE_ECHO_REQUEST:
1824 case GNUNET_TUN_ICMPTYPE_DESTINATION_UNREACHABLE:
1825 case GNUNET_TUN_ICMPTYPE_SOURCE_QUENCH:
1826 case GNUNET_TUN_ICMPTYPE_TIME_EXCEEDED:
1828 struct GNUNET_TUN_IPv4Header *ipp = (struct GNUNET_TUN_IPv4Header *) &icmp[1];
1829 struct GNUNET_TUN_UdpHeader *udp = (struct GNUNET_TUN_UdpHeader *) &ipp[1];
1833 /* sender did not strip ICMP payload? */
1834 GNUNET_break_op (0);
1835 return GNUNET_SYSERR;
1837 size += sizeof (struct GNUNET_TUN_IPv4Header) + 8;
1838 GNUNET_assert (8 == sizeof (struct GNUNET_TUN_UdpHeader));
1839 make_up_icmpv4_payload (ts, ipp, udp);
1843 GNUNET_break_op (0);
1844 GNUNET_STATISTICS_update (stats,
1845 gettext_noop ("# ICMPv4 packets dropped (type not allowed)"),
1847 return GNUNET_SYSERR;
1852 /* ICMP PT 6-to-4 and possibly making up payloads */
1855 case GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE:
1856 icmp->type = GNUNET_TUN_ICMPTYPE_DESTINATION_UNREACHABLE;
1858 struct GNUNET_TUN_IPv4Header *ipp = (struct GNUNET_TUN_IPv4Header *) &icmp[1];
1859 struct GNUNET_TUN_UdpHeader *udp = (struct GNUNET_TUN_UdpHeader *) &ipp[1];
1863 /* sender did not strip ICMP payload? */
1864 GNUNET_break_op (0);
1865 return GNUNET_SYSERR;
1867 size += sizeof (struct GNUNET_TUN_IPv4Header) + 8;
1868 GNUNET_assert (8 == sizeof (struct GNUNET_TUN_UdpHeader));
1869 make_up_icmpv4_payload (ts, ipp, udp);
1872 case GNUNET_TUN_ICMPTYPE6_TIME_EXCEEDED:
1873 icmp->type = GNUNET_TUN_ICMPTYPE_TIME_EXCEEDED;
1875 struct GNUNET_TUN_IPv4Header *ipp = (struct GNUNET_TUN_IPv4Header *) &icmp[1];
1876 struct GNUNET_TUN_UdpHeader *udp = (struct GNUNET_TUN_UdpHeader *) &ipp[1];
1880 /* sender did not strip ICMP payload? */
1881 GNUNET_break_op (0);
1882 return GNUNET_SYSERR;
1884 size += sizeof (struct GNUNET_TUN_IPv4Header) + 8;
1885 GNUNET_assert (8 == sizeof (struct GNUNET_TUN_UdpHeader));
1886 make_up_icmpv4_payload (ts, ipp, udp);
1889 case GNUNET_TUN_ICMPTYPE6_PACKET_TOO_BIG:
1890 case GNUNET_TUN_ICMPTYPE6_PARAMETER_PROBLEM:
1891 GNUNET_STATISTICS_update (stats,
1892 gettext_noop ("# ICMPv6 packets dropped (impossible PT to v4)"),
1895 case GNUNET_TUN_ICMPTYPE6_ECHO_REQUEST:
1896 icmp->type = GNUNET_TUN_ICMPTYPE_ECHO_REQUEST;
1898 case GNUNET_TUN_ICMPTYPE6_ECHO_REPLY:
1899 icmp->type = GNUNET_TUN_ICMPTYPE_ECHO_REPLY;
1902 GNUNET_break_op (0);
1903 GNUNET_STATISTICS_update (stats,
1904 gettext_noop ("# ICMPv6 packets dropped (type not allowed)"),
1906 return GNUNET_SYSERR;
1911 GNUNET_break_op (0);
1912 return GNUNET_SYSERR;
1914 msg->size = htons (size);
1915 GNUNET_TUN_calculate_icmp_checksum (icmp,
1918 (void) GNUNET_HELPER_send (helper_handle,
1927 size_t size = sizeof (struct GNUNET_TUN_IPv6Header)
1928 + sizeof (struct GNUNET_TUN_IcmpHeader)
1929 + sizeof (struct GNUNET_MessageHeader) +
1930 sizeof (struct GNUNET_TUN_Layer2PacketHeader) +
1933 char buf[size + sizeof (struct GNUNET_TUN_IPv6Header) + 8] GNUNET_ALIGN;
1934 struct GNUNET_MessageHeader *msg = (struct GNUNET_MessageHeader *) buf;
1935 struct GNUNET_TUN_Layer2PacketHeader *tun = (struct GNUNET_TUN_Layer2PacketHeader*) &msg[1];
1936 struct GNUNET_TUN_IPv6Header *ipv6 = (struct GNUNET_TUN_IPv6Header *) &tun[1];
1937 struct GNUNET_TUN_IcmpHeader *icmp = (struct GNUNET_TUN_IcmpHeader *) &ipv6[1];
1938 msg->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
1939 tun->flags = htons (0);
1940 tun->proto = htons (ETH_P_IPV6);
1941 GNUNET_TUN_initialize_ipv6_header (ipv6,
1943 sizeof (struct GNUNET_TUN_IcmpHeader) + mlen,
1944 &ts->destination_ip.v6,
1946 *icmp = i2v->icmp_header;
1951 /* For some ICMP types, we need to adjust (make up) the payload here.
1952 Also, depending on the AF used on the other side, we have to
1953 do ICMP PT (translate ICMP types) */
1954 switch (ntohl (i2v->af))
1957 /* ICMP PT 4-to-6 and possibly making up payloads */
1960 case GNUNET_TUN_ICMPTYPE_ECHO_REPLY:
1961 icmp->type = GNUNET_TUN_ICMPTYPE6_ECHO_REPLY;
1963 case GNUNET_TUN_ICMPTYPE_ECHO_REQUEST:
1964 icmp->type = GNUNET_TUN_ICMPTYPE6_ECHO_REQUEST;
1966 case GNUNET_TUN_ICMPTYPE_DESTINATION_UNREACHABLE:
1967 icmp->type = GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE;
1969 struct GNUNET_TUN_IPv6Header *ipp = (struct GNUNET_TUN_IPv6Header *) &icmp[1];
1970 struct GNUNET_TUN_UdpHeader *udp = (struct GNUNET_TUN_UdpHeader *) &ipp[1];
1974 /* sender did not strip ICMP payload? */
1975 GNUNET_break_op (0);
1976 return GNUNET_SYSERR;
1978 size += sizeof (struct GNUNET_TUN_IPv6Header) + 8;
1979 GNUNET_assert (8 == sizeof (struct GNUNET_TUN_UdpHeader));
1980 make_up_icmpv6_payload (ts, ipp, udp);
1983 case GNUNET_TUN_ICMPTYPE_TIME_EXCEEDED:
1984 icmp->type = GNUNET_TUN_ICMPTYPE6_TIME_EXCEEDED;
1986 struct GNUNET_TUN_IPv6Header *ipp = (struct GNUNET_TUN_IPv6Header *) &icmp[1];
1987 struct GNUNET_TUN_UdpHeader *udp = (struct GNUNET_TUN_UdpHeader *) &ipp[1];
1991 /* sender did not strip ICMP payload? */
1992 GNUNET_break_op (0);
1993 return GNUNET_SYSERR;
1995 size += sizeof (struct GNUNET_TUN_IPv6Header) + 8;
1996 GNUNET_assert (8 == sizeof (struct GNUNET_TUN_UdpHeader));
1997 make_up_icmpv6_payload (ts, ipp, udp);
2000 case GNUNET_TUN_ICMPTYPE_SOURCE_QUENCH:
2001 GNUNET_STATISTICS_update (stats,
2002 gettext_noop ("# ICMPv4 packets dropped (impossible PT to v6)"),
2006 GNUNET_break_op (0);
2007 GNUNET_STATISTICS_update (stats,
2008 gettext_noop ("# ICMPv4 packets dropped (type not allowed)"),
2010 return GNUNET_SYSERR;
2017 case GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE:
2018 case GNUNET_TUN_ICMPTYPE6_TIME_EXCEEDED:
2019 case GNUNET_TUN_ICMPTYPE6_PACKET_TOO_BIG:
2020 case GNUNET_TUN_ICMPTYPE6_PARAMETER_PROBLEM:
2022 struct GNUNET_TUN_IPv6Header *ipp = (struct GNUNET_TUN_IPv6Header *) &icmp[1];
2023 struct GNUNET_TUN_UdpHeader *udp = (struct GNUNET_TUN_UdpHeader *) &ipp[1];
2027 /* sender did not strip ICMP payload? */
2028 GNUNET_break_op (0);
2029 return GNUNET_SYSERR;
2031 size += sizeof (struct GNUNET_TUN_IPv6Header) + 8;
2032 GNUNET_assert (8 == sizeof (struct GNUNET_TUN_UdpHeader));
2033 make_up_icmpv6_payload (ts, ipp, udp);
2036 case GNUNET_TUN_ICMPTYPE6_ECHO_REQUEST:
2039 GNUNET_break_op (0);
2040 GNUNET_STATISTICS_update (stats,
2041 gettext_noop ("# ICMPv6 packets dropped (type not allowed)"),
2043 return GNUNET_SYSERR;
2048 GNUNET_break_op (0);
2049 return GNUNET_SYSERR;
2051 msg->size = htons (size);
2052 GNUNET_TUN_calculate_icmp_checksum (icmp,
2054 (void) GNUNET_HELPER_send (helper_handle,
2064 GNUNET_CONTAINER_heap_update_cost (channel_heap,
2066 GNUNET_TIME_absolute_get ().abs_value_us);
2072 * We got a UDP packet back from the CADET channel. Pass it on to the
2073 * local virtual interface via the helper.
2075 * @param cls closure, NULL
2076 * @param channel connection to the other end
2077 * @param channel_ctx pointer to our 'struct ChannelState *'
2078 * @param message the actual message
2079 * @return #GNUNET_OK to keep the connection open,
2080 * #GNUNET_SYSERR to close it (signal serious error)
2083 receive_udp_back (void *cls,
2084 struct GNUNET_CADET_Channel *channel,
2086 const struct GNUNET_MessageHeader *message)
2088 struct ChannelState *ts = *channel_ctx;
2089 const struct GNUNET_EXIT_UdpReplyMessage *reply;
2092 GNUNET_STATISTICS_update (stats,
2093 gettext_noop ("# UDP packets received from cadet"),
2095 mlen = ntohs (message->size);
2096 if (mlen < sizeof (struct GNUNET_EXIT_UdpReplyMessage))
2098 GNUNET_break_op (0);
2099 return GNUNET_SYSERR;
2101 if (NULL == ts->heap_node)
2103 GNUNET_break_op (0);
2104 return GNUNET_SYSERR;
2106 if (AF_UNSPEC == ts->af)
2108 GNUNET_break_op (0);
2109 return GNUNET_SYSERR;
2111 reply = (const struct GNUNET_EXIT_UdpReplyMessage *) message;
2112 mlen -= sizeof (struct GNUNET_EXIT_UdpReplyMessage);
2114 char sbuf[INET6_ADDRSTRLEN];
2115 char dbuf[INET6_ADDRSTRLEN];
2117 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2118 "Received UDP reply from cadet, sending %u bytes from %s:%u -> %s:%u via TUN\n",
2119 (unsigned int) mlen,
2120 inet_ntop (ts->af, &ts->destination_ip, sbuf, sizeof (sbuf)),
2121 ts->destination_port,
2122 inet_ntop (ts->af, &ts->source_ip, dbuf, sizeof (dbuf)),
2129 size_t size = sizeof (struct GNUNET_TUN_IPv4Header)
2130 + sizeof (struct GNUNET_TUN_UdpHeader)
2131 + sizeof (struct GNUNET_MessageHeader) +
2132 sizeof (struct GNUNET_TUN_Layer2PacketHeader) +
2135 char buf[size] GNUNET_ALIGN;
2136 struct GNUNET_MessageHeader *msg = (struct GNUNET_MessageHeader *) buf;
2137 struct GNUNET_TUN_Layer2PacketHeader *tun = (struct GNUNET_TUN_Layer2PacketHeader*) &msg[1];
2138 struct GNUNET_TUN_IPv4Header *ipv4 = (struct GNUNET_TUN_IPv4Header *) &tun[1];
2139 struct GNUNET_TUN_UdpHeader *udp = (struct GNUNET_TUN_UdpHeader *) &ipv4[1];
2140 msg->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
2141 msg->size = htons (size);
2142 tun->flags = htons (0);
2143 tun->proto = htons (ETH_P_IPV4);
2144 GNUNET_TUN_initialize_ipv4_header (ipv4,
2146 sizeof (struct GNUNET_TUN_UdpHeader) + mlen,
2147 &ts->destination_ip.v4,
2149 if (0 == ntohs (reply->source_port))
2150 udp->source_port = htons (ts->destination_port);
2152 udp->source_port = reply->source_port;
2153 if (0 == ntohs (reply->destination_port))
2154 udp->destination_port = htons (ts->source_port);
2156 udp->destination_port = reply->destination_port;
2157 udp->len = htons (mlen + sizeof (struct GNUNET_TUN_UdpHeader));
2158 GNUNET_TUN_calculate_udp4_checksum (ipv4,
2165 (void) GNUNET_HELPER_send (helper_handle,
2174 size_t size = sizeof (struct GNUNET_TUN_IPv6Header)
2175 + sizeof (struct GNUNET_TUN_UdpHeader)
2176 + sizeof (struct GNUNET_MessageHeader) +
2177 sizeof (struct GNUNET_TUN_Layer2PacketHeader) +
2180 char buf[size] GNUNET_ALIGN;
2181 struct GNUNET_MessageHeader *msg = (struct GNUNET_MessageHeader *) buf;
2182 struct GNUNET_TUN_Layer2PacketHeader *tun = (struct GNUNET_TUN_Layer2PacketHeader*) &msg[1];
2183 struct GNUNET_TUN_IPv6Header *ipv6 = (struct GNUNET_TUN_IPv6Header *) &tun[1];
2184 struct GNUNET_TUN_UdpHeader *udp = (struct GNUNET_TUN_UdpHeader *) &ipv6[1];
2185 msg->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
2186 msg->size = htons (size);
2187 tun->flags = htons (0);
2188 tun->proto = htons (ETH_P_IPV6);
2189 GNUNET_TUN_initialize_ipv6_header (ipv6,
2191 sizeof (struct GNUNET_TUN_UdpHeader) + mlen,
2192 &ts->destination_ip.v6,
2194 if (0 == ntohs (reply->source_port))
2195 udp->source_port = htons (ts->destination_port);
2197 udp->source_port = reply->source_port;
2198 if (0 == ntohs (reply->destination_port))
2199 udp->destination_port = htons (ts->source_port);
2201 udp->destination_port = reply->destination_port;
2202 udp->len = htons (mlen + sizeof (struct GNUNET_TUN_UdpHeader));
2203 GNUNET_TUN_calculate_udp6_checksum (ipv6,
2209 (void) GNUNET_HELPER_send (helper_handle,
2219 GNUNET_CONTAINER_heap_update_cost (channel_heap,
2221 GNUNET_TIME_absolute_get ().abs_value_us);
2227 * We got a TCP packet back from the CADET channel. Pass it on to the
2228 * local virtual interface via the helper.
2230 * @param cls closure, NULL
2231 * @param channel connection to the other end
2232 * @param channel_ctx pointer to our `struct ChannelState *`
2233 * @param message the actual message
2234 * @return #GNUNET_OK to keep the connection open,
2235 * #GNUNET_SYSERR to close it (signal serious error)
2238 receive_tcp_back (void *cls,
2239 struct GNUNET_CADET_Channel *channel,
2241 const struct GNUNET_MessageHeader *message)
2243 struct ChannelState *ts = *channel_ctx;
2244 const struct GNUNET_EXIT_TcpDataMessage *data;
2247 GNUNET_STATISTICS_update (stats,
2248 gettext_noop ("# TCP packets received from cadet"),
2250 mlen = ntohs (message->size);
2251 if (mlen < sizeof (struct GNUNET_EXIT_TcpDataMessage))
2253 GNUNET_break_op (0);
2254 return GNUNET_SYSERR;
2256 if (NULL == ts->heap_node)
2258 GNUNET_break_op (0);
2259 return GNUNET_SYSERR;
2261 data = (const struct GNUNET_EXIT_TcpDataMessage *) message;
2262 mlen -= sizeof (struct GNUNET_EXIT_TcpDataMessage);
2264 char sbuf[INET6_ADDRSTRLEN];
2265 char dbuf[INET6_ADDRSTRLEN];
2267 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2268 "Received TCP reply from cadet, sending %u bytes from %s:%u -> %s:%u via TUN\n",
2269 (unsigned int) mlen,
2270 inet_ntop (ts->af, &ts->destination_ip, sbuf, sizeof (sbuf)),
2271 ts->destination_port,
2272 inet_ntop (ts->af, &ts->source_ip, dbuf, sizeof (dbuf)),
2275 if (data->tcp_header.off * 4 < sizeof (struct GNUNET_TUN_TcpHeader))
2277 GNUNET_break_op (0);
2278 return GNUNET_SYSERR;
2284 size_t size = sizeof (struct GNUNET_TUN_IPv4Header)
2285 + sizeof (struct GNUNET_TUN_TcpHeader)
2286 + sizeof (struct GNUNET_MessageHeader) +
2287 sizeof (struct GNUNET_TUN_Layer2PacketHeader) +
2290 char buf[size] GNUNET_ALIGN;
2291 struct GNUNET_MessageHeader *msg = (struct GNUNET_MessageHeader *) buf;
2292 struct GNUNET_TUN_Layer2PacketHeader *tun = (struct GNUNET_TUN_Layer2PacketHeader*) &msg[1];
2293 struct GNUNET_TUN_IPv4Header *ipv4 = (struct GNUNET_TUN_IPv4Header *) &tun[1];
2294 struct GNUNET_TUN_TcpHeader *tcp = (struct GNUNET_TUN_TcpHeader *) &ipv4[1];
2295 msg->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
2296 msg->size = htons (size);
2297 tun->flags = htons (0);
2298 tun->proto = htons (ETH_P_IPV4);
2299 GNUNET_TUN_initialize_ipv4_header (ipv4,
2301 sizeof (struct GNUNET_TUN_TcpHeader) + mlen,
2302 &ts->destination_ip.v4,
2304 *tcp = data->tcp_header;
2305 tcp->source_port = htons (ts->destination_port);
2306 tcp->destination_port = htons (ts->source_port);
2307 GNUNET_TUN_calculate_tcp4_checksum (ipv4,
2314 (void) GNUNET_HELPER_send (helper_handle,
2323 size_t size = sizeof (struct GNUNET_TUN_IPv6Header)
2324 + sizeof (struct GNUNET_TUN_TcpHeader)
2325 + sizeof (struct GNUNET_MessageHeader) +
2326 sizeof (struct GNUNET_TUN_Layer2PacketHeader) +
2329 char buf[size] GNUNET_ALIGN;
2330 struct GNUNET_MessageHeader *msg = (struct GNUNET_MessageHeader *) buf;
2331 struct GNUNET_TUN_Layer2PacketHeader *tun = (struct GNUNET_TUN_Layer2PacketHeader*) &msg[1];
2332 struct GNUNET_TUN_IPv6Header *ipv6 = (struct GNUNET_TUN_IPv6Header *) &tun[1];
2333 struct GNUNET_TUN_TcpHeader *tcp = (struct GNUNET_TUN_TcpHeader *) &ipv6[1];
2334 msg->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
2335 msg->size = htons (size);
2336 tun->flags = htons (0);
2337 tun->proto = htons (ETH_P_IPV6);
2338 GNUNET_TUN_initialize_ipv6_header (ipv6,
2340 sizeof (struct GNUNET_TUN_TcpHeader) + mlen,
2341 &ts->destination_ip.v6,
2343 *tcp = data->tcp_header;
2344 tcp->source_port = htons (ts->destination_port);
2345 tcp->destination_port = htons (ts->source_port);
2346 GNUNET_TUN_calculate_tcp6_checksum (ipv6,
2353 (void) GNUNET_HELPER_send (helper_handle,
2361 GNUNET_CONTAINER_heap_update_cost (channel_heap,
2363 GNUNET_TIME_absolute_get ().abs_value_us);
2369 * Allocate an IPv4 address from the range of the channel
2370 * for a new redirection.
2372 * @param v4 where to store the address
2373 * @return #GNUNET_OK on success,
2374 * #GNUNET_SYSERR on error
2377 allocate_v4_address (struct in_addr *v4)
2379 const char *ipv4addr = vpn_argv[4];
2380 const char *ipv4mask = vpn_argv[5];
2381 struct in_addr addr;
2382 struct in_addr mask;
2384 struct GNUNET_HashCode key;
2387 GNUNET_assert (1 == inet_pton (AF_INET, ipv4addr, &addr));
2388 GNUNET_assert (1 == inet_pton (AF_INET, ipv4mask, &mask));
2389 /* Given 192.168.0.1/255.255.0.0, we want a mask
2390 of '192.168.255.255', thus: */
2391 mask.s_addr = addr.s_addr | ~mask.s_addr;
2398 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
2399 _("Failed to find unallocated IPv4 address in VPN's range\n"));
2400 return GNUNET_SYSERR;
2402 /* Pick random IPv4 address within the subnet, except 'addr' or 'mask' itself */
2403 rnd.s_addr = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
2405 v4->s_addr = (addr.s_addr | rnd.s_addr) & mask.s_addr;
2406 get_destination_key_from_ip (AF_INET,
2410 while ( (GNUNET_YES ==
2411 GNUNET_CONTAINER_multihashmap_contains (destination_map,
2413 (v4->s_addr == addr.s_addr) ||
2414 (v4->s_addr == mask.s_addr) );
2420 * Allocate an IPv6 address from the range of the channel
2421 * for a new redirection.
2423 * @param v6 where to store the address
2424 * @return #GNUNET_OK on success,
2425 * #GNUNET_SYSERR on error
2428 allocate_v6_address (struct in6_addr *v6)
2430 const char *ipv6addr = vpn_argv[2];
2431 struct in6_addr addr;
2432 struct in6_addr mask;
2433 struct in6_addr rnd;
2435 struct GNUNET_HashCode key;
2438 GNUNET_assert (1 == inet_pton (AF_INET6, ipv6addr, &addr));
2439 GNUNET_assert (ipv6prefix < 128);
2440 /* Given ABCD::/96, we want a mask of 'ABCD::FFFF:FFFF,
2443 for (i=127;i>=ipv6prefix;i--)
2444 mask.s6_addr[i / 8] |= (1 << (i % 8));
2446 /* Pick random IPv6 address within the subnet, except 'addr' or 'mask' itself */
2453 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
2454 _("Failed to find unallocated IPv6 address in VPN's range\n"));
2455 return GNUNET_SYSERR;
2460 rnd.s6_addr[i] = (unsigned char) GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
2463 = (addr.s6_addr[i] | rnd.s6_addr[i]) & mask.s6_addr[i];
2465 get_destination_key_from_ip (AF_INET6,
2469 while ( (GNUNET_YES ==
2470 GNUNET_CONTAINER_multihashmap_contains (destination_map,
2474 sizeof (struct in6_addr))) ||
2477 sizeof (struct in6_addr))) );
2483 * Free resources occupied by a destination entry.
2485 * @param de entry to free
2488 free_destination_entry (struct DestinationEntry *de)
2490 struct DestinationChannel *dt;
2492 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2493 "Cleaning up destination entry\n");
2494 GNUNET_STATISTICS_update (stats,
2495 gettext_noop ("# Active destinations"),
2497 while (NULL != (dt = de->dt_head))
2499 GNUNET_CONTAINER_DLL_remove (de->dt_head,
2504 free_channel_state (dt->ts);
2505 GNUNET_assert (NULL == dt->ts);
2509 if (NULL != de->heap_node)
2511 GNUNET_CONTAINER_heap_remove_node (de->heap_node);
2512 de->heap_node = NULL;
2513 GNUNET_assert (GNUNET_YES ==
2514 GNUNET_CONTAINER_multihashmap_remove (destination_map,
2523 * We have too many active destinations. Clean up the oldest destination.
2525 * @param except destination that must NOT be cleaned up, even if it is the oldest
2528 expire_destination (struct DestinationEntry *except)
2530 struct DestinationEntry *de;
2532 de = GNUNET_CONTAINER_heap_peek (destination_heap);
2533 GNUNET_assert (NULL != de);
2535 return; /* can't do this */
2536 free_destination_entry (de);
2541 * Allocate an IP address for the response.
2543 * @param result_af desired address family; set to the actual
2544 * address family; can initially be AF_UNSPEC if there
2545 * is no preference; will be set to AF_UNSPEC if the
2547 * @param addr set to either v4 or v6 depending on which
2548 * storage location was used; set to NULL if allocation failed
2549 * @param v4 storage space for an IPv4 address
2550 * @param v6 storage space for an IPv6 address
2551 * @return #GNUNET_OK normally, #GNUNET_SYSERR if `* result_af` was
2552 * an unsupported address family (not AF_INET, AF_INET6 or AF_UNSPEC)
2555 allocate_response_ip (int *result_af,
2558 struct in6_addr *v6)
2565 allocate_v4_address (v4))
2566 *result_af = AF_UNSPEC;
2572 allocate_v6_address (v6))
2573 *result_af = AF_UNSPEC;
2579 allocate_v4_address (v4))
2582 *result_af = AF_INET;
2584 else if (GNUNET_OK ==
2585 allocate_v6_address (v6))
2588 *result_af = AF_INET6;
2593 return GNUNET_SYSERR;
2600 * A client asks us to setup a redirection via some exit node to a
2601 * particular IP. Setup the redirection and give the client the
2605 * @param client requesting client
2606 * @param message redirection request (a `struct RedirectToIpRequestMessage`)
2609 service_redirect_to_ip (void *cls,
2610 struct GNUNET_SERVER_Client *client,
2611 const struct GNUNET_MessageHeader *message)
2615 const struct RedirectToIpRequestMessage *msg;
2621 struct DestinationEntry *de;
2622 struct GNUNET_HashCode key;
2624 /* validate and parse request */
2625 mlen = ntohs (message->size);
2626 if (mlen < sizeof (struct RedirectToIpRequestMessage))
2629 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2632 alen = mlen - sizeof (struct RedirectToIpRequestMessage);
2633 msg = (const struct RedirectToIpRequestMessage *) message;
2634 addr_af = (int) htonl (msg->addr_af);
2638 if (alen != sizeof (struct in_addr))
2641 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2646 if (alen != sizeof (struct in6_addr))
2649 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2655 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2659 /* allocate response IP */
2660 result_af = (int) htonl (msg->result_af);
2661 if (GNUNET_OK != allocate_response_ip (&result_af,
2665 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2668 /* send reply with our IP address */
2669 send_client_reply (client,
2673 if (result_af == AF_UNSPEC)
2675 /* failure, we're done */
2676 GNUNET_SERVER_receive_done (client, GNUNET_OK);
2681 char sbuf[INET6_ADDRSTRLEN];
2682 char dbuf[INET6_ADDRSTRLEN];
2684 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2685 "Allocated address %s for redirection via exit to %s\n",
2686 inet_ntop (result_af, addr, sbuf, sizeof (sbuf)),
2688 &msg[1], dbuf, sizeof (dbuf)));
2691 /* setup destination record */
2692 de = GNUNET_new (struct DestinationEntry);
2693 de->is_service = GNUNET_NO;
2694 de->details.exit_destination.af = addr_af;
2695 memcpy (&de->details.exit_destination.ip,
2698 get_destination_key_from_ip (result_af,
2702 GNUNET_assert (GNUNET_OK ==
2703 GNUNET_CONTAINER_multihashmap_put (destination_map,
2706 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE));
2707 de->heap_node = GNUNET_CONTAINER_heap_insert (destination_heap,
2709 GNUNET_TIME_absolute_ntoh (msg->expiration_time).abs_value_us);
2710 GNUNET_STATISTICS_update (stats,
2711 gettext_noop ("# Active destinations"),
2713 while (GNUNET_CONTAINER_multihashmap_size (destination_map) > max_destination_mappings)
2714 expire_destination (de);
2715 GNUNET_SERVER_receive_done (client, GNUNET_OK);
2720 * A client asks us to setup a redirection to a particular peer
2721 * offering a service. Setup the redirection and give the client the
2725 * @param client requesting client
2726 * @param message redirection request (a `struct RedirectToPeerRequestMessage`)
2729 service_redirect_to_service (void *cls,
2730 struct GNUNET_SERVER_Client *client,
2731 const struct GNUNET_MessageHeader *message)
2733 const struct RedirectToServiceRequestMessage *msg;
2738 struct DestinationEntry *de;
2739 struct GNUNET_HashCode key;
2740 struct ChannelState *ts;
2741 struct DestinationChannel *dt;
2744 msg = (const struct RedirectToServiceRequestMessage *) message;
2746 /* allocate response IP */
2747 result_af = (int) htonl (msg->result_af);
2748 if (GNUNET_OK != allocate_response_ip (&result_af,
2752 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2755 send_client_reply (client,
2759 if (result_af == AF_UNSPEC)
2761 /* failure, we're done */
2762 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2763 _("Failed to allocate IP address for new destination\n"));
2764 GNUNET_SERVER_receive_done (client, GNUNET_OK);
2769 char sbuf[INET6_ADDRSTRLEN];
2771 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2772 "Allocated address %s for redirection to service %s on peer %s\n",
2773 inet_ntop (result_af, addr, sbuf, sizeof (sbuf)),
2774 GNUNET_h2s (&msg->service_descriptor),
2775 GNUNET_i2s (&msg->target));
2778 /* setup destination record */
2779 de = GNUNET_new (struct DestinationEntry);
2780 de->is_service = GNUNET_YES;
2781 de->details.service_destination.service_descriptor = msg->service_descriptor;
2782 de->details.service_destination.target = msg->target;
2783 get_destination_key_from_ip (result_af,
2787 GNUNET_assert (GNUNET_OK ==
2788 GNUNET_CONTAINER_multihashmap_put (destination_map,
2791 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE));
2792 de->heap_node = GNUNET_CONTAINER_heap_insert (destination_heap,
2794 GNUNET_TIME_absolute_ntoh (msg->expiration_time).abs_value_us);
2795 while (GNUNET_CONTAINER_multihashmap_size (destination_map) > max_destination_mappings)
2796 expire_destination (de);
2798 dt = GNUNET_new (struct DestinationChannel);
2799 dt->destination = de;
2800 GNUNET_CONTAINER_DLL_insert (de->dt_head,
2803 ts = create_channel_to_destination (dt,
2808 ts->destination_ip.v4 = v4;
2811 ts->destination_ip.v6 = v6;
2817 GNUNET_SERVER_receive_done (client, GNUNET_OK);
2822 * Function called whenever a channel is destroyed. Should clean up
2823 * any associated state.
2825 * @param cls closure (set from #GNUNET_CADET_connect)
2826 * @param channel connection to the other end (henceforth invalid)
2827 * @param channel_ctx place where local state associated
2828 * with the channel is stored (our `struct ChannelState`)
2831 channel_cleaner (void *cls,
2832 const struct GNUNET_CADET_Channel *channel,
2835 struct ChannelState *ts = channel_ctx;
2837 ts->channel = NULL; /* we must not call GNUNET_CADET_channel_destroy() anymore */
2838 free_channel_state (ts);
2843 * Free memory occupied by an entry in the destination map.
2847 * @param value a `struct DestinationEntry *`
2848 * @return #GNUNET_OK (continue to iterate)
2851 cleanup_destination (void *cls,
2852 const struct GNUNET_HashCode *key,
2855 struct DestinationEntry *de = value;
2857 free_destination_entry (de);
2863 * Free memory occupied by an entry in the channel map.
2867 * @param value a `struct ChannelState *`
2868 * @return #GNUNET_OK (continue to iterate)
2871 cleanup_channel (void *cls,
2872 const struct GNUNET_HashCode *key,
2875 struct ChannelState *ts = value;
2877 free_channel_state (ts);
2883 * Function scheduled as very last function, cleans up after us
2890 const struct GNUNET_SCHEDULER_TaskContext *tc)
2894 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2895 "VPN is shutting down\n");
2896 if (NULL != destination_map)
2898 GNUNET_CONTAINER_multihashmap_iterate (destination_map,
2899 &cleanup_destination,
2901 GNUNET_CONTAINER_multihashmap_destroy (destination_map);
2902 destination_map = NULL;
2904 if (NULL != destination_heap)
2906 GNUNET_CONTAINER_heap_destroy (destination_heap);
2907 destination_heap = NULL;
2909 if (NULL != channel_map)
2911 GNUNET_CONTAINER_multihashmap_iterate (channel_map,
2914 GNUNET_CONTAINER_multihashmap_destroy (channel_map);
2917 if (NULL != channel_heap)
2919 GNUNET_CONTAINER_heap_destroy (channel_heap);
2920 channel_heap = NULL;
2922 if (NULL != cadet_handle)
2924 GNUNET_CADET_disconnect (cadet_handle);
2925 cadet_handle = NULL;
2927 if (NULL != helper_handle)
2929 GNUNET_HELPER_stop (helper_handle, GNUNET_NO);
2930 helper_handle = NULL;
2934 GNUNET_SERVER_notification_context_destroy (nc);
2939 GNUNET_STATISTICS_destroy (stats, GNUNET_NO);
2943 GNUNET_free_non_null (vpn_argv[i]);
2948 * Main function that will be run by the scheduler.
2950 * @param cls closure
2951 * @param server the initialized server
2952 * @param cfg_ configuration
2956 struct GNUNET_SERVER_Handle *server,
2957 const struct GNUNET_CONFIGURATION_Handle *cfg_)
2959 static const struct GNUNET_SERVER_MessageHandler service_handlers[] = {
2960 /* callback, cls, type, size */
2961 { &service_redirect_to_ip, NULL, GNUNET_MESSAGE_TYPE_VPN_CLIENT_REDIRECT_TO_IP, 0},
2962 { &service_redirect_to_service, NULL,
2963 GNUNET_MESSAGE_TYPE_VPN_CLIENT_REDIRECT_TO_SERVICE,
2964 sizeof (struct RedirectToServiceRequestMessage) },
2967 static const struct GNUNET_CADET_MessageHandler cadet_handlers[] = {
2968 { &receive_udp_back, GNUNET_MESSAGE_TYPE_VPN_UDP_REPLY, 0},
2969 { &receive_tcp_back, GNUNET_MESSAGE_TYPE_VPN_TCP_DATA_TO_VPN, 0},
2970 { &receive_icmp_back, GNUNET_MESSAGE_TYPE_VPN_ICMP_TO_VPN, 0},
2982 binary = GNUNET_OS_get_libexec_binary_path ("gnunet-helper-vpn");
2985 GNUNET_OS_check_helper_binary (binary,
2987 "-d gnunet-vpn - - 169.1.3.3.7 255.255.255.0")) //ipv4 only please!
2989 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2990 "`%s' is not SUID, refusing to run.\n",
2991 "gnunet-helper-vpn");
2992 GNUNET_free (binary);
2994 /* we won't "really" exit here, as the 'service' is still running;
2995 however, as no handlers are registered, the service won't do
2999 GNUNET_free (binary);
3001 stats = GNUNET_STATISTICS_create ("vpn", cfg);
3003 GNUNET_CONFIGURATION_get_value_number (cfg, "VPN", "MAX_MAPPING",
3004 &max_destination_mappings))
3005 max_destination_mappings = 200;
3007 GNUNET_CONFIGURATION_get_value_number (cfg, "VPN", "MAX_TUNNELS",
3008 &max_channel_mappings))
3009 max_channel_mappings = 200;
3011 destination_map = GNUNET_CONTAINER_multihashmap_create (max_destination_mappings * 2, GNUNET_NO);
3012 destination_heap = GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN);
3013 channel_map = GNUNET_CONTAINER_multihashmap_create (max_channel_mappings * 2, GNUNET_NO);
3014 channel_heap = GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN);
3017 vpn_argv[0] = GNUNET_strdup ("vpn-gnunet");
3018 if (GNUNET_SYSERR ==
3019 GNUNET_CONFIGURATION_get_value_string (cfg, "VPN", "IFNAME", &ifname))
3021 GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, "VPN", "IFNAME");
3022 GNUNET_SCHEDULER_shutdown ();
3025 vpn_argv[1] = ifname;
3027 if (GNUNET_OK == GNUNET_NETWORK_test_pf (PF_INET6))
3029 if ( (GNUNET_SYSERR ==
3030 GNUNET_CONFIGURATION_get_value_string (cfg, "VPN", "IPV6ADDR",
3032 (1 != inet_pton (AF_INET6, ipv6addr, &v6))) )
3034 GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, "VPN", "IPV6ADDR",
3035 _("Must specify valid IPv6 address"));
3036 GNUNET_SCHEDULER_shutdown ();
3037 GNUNET_free_non_null (ipv6addr);
3040 vpn_argv[2] = ipv6addr;
3041 ipv6prefix_s = NULL;
3042 if (GNUNET_SYSERR ==
3043 GNUNET_CONFIGURATION_get_value_string (cfg, "VPN", "IPV6PREFIX",
3046 GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, "VPN", "IPV6PREFIX");
3047 GNUNET_SCHEDULER_shutdown ();
3048 GNUNET_free_non_null (ipv6prefix_s);
3051 vpn_argv[3] = ipv6prefix_s;
3053 GNUNET_CONFIGURATION_get_value_number (cfg, "VPN",
3056 (ipv6prefix >= 127) )
3058 GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, "VPN", "IPV4MASK",
3059 _("Must specify valid IPv6 mask"));
3060 GNUNET_SCHEDULER_shutdown ();
3066 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
3067 _("IPv6 support disabled as this system does not support IPv6\n"));
3068 vpn_argv[2] = GNUNET_strdup ("-");
3069 vpn_argv[3] = GNUNET_strdup ("-");
3071 if (GNUNET_OK == GNUNET_NETWORK_test_pf (PF_INET))
3074 if ( (GNUNET_SYSERR ==
3075 GNUNET_CONFIGURATION_get_value_string (cfg, "vpn", "IPV4ADDR",
3077 (1 != inet_pton (AF_INET, ipv4addr, &v4))) )
3079 GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, "VPN", "IPV4ADDR",
3080 _("Must specify valid IPv4 address"));
3081 GNUNET_SCHEDULER_shutdown ();
3082 GNUNET_free_non_null (ipv4addr);
3085 vpn_argv[4] = ipv4addr;
3087 if ( (GNUNET_SYSERR ==
3088 GNUNET_CONFIGURATION_get_value_string (cfg, "vpn", "IPV4MASK",
3090 (1 != inet_pton (AF_INET, ipv4mask, &v4))) )
3092 GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, "VPN", "IPV4MASK",
3093 _("Must specify valid IPv4 mask"));
3094 GNUNET_SCHEDULER_shutdown ();
3095 GNUNET_free_non_null (ipv4mask);
3098 vpn_argv[5] = ipv4mask;
3102 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
3103 _("IPv4 support disabled as this system does not support IPv4\n"));
3104 vpn_argv[4] = GNUNET_strdup ("-");
3105 vpn_argv[5] = GNUNET_strdup ("-");
3110 GNUNET_CADET_connect (cfg_, NULL,
3115 helper_handle = GNUNET_HELPER_start (GNUNET_NO,
3116 "gnunet-helper-vpn", vpn_argv,
3117 &message_token, NULL, NULL);
3118 nc = GNUNET_SERVER_notification_context_create (server, 1);
3119 GNUNET_SERVER_add_handlers (server, service_handlers);
3120 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &cleanup, cls);
3125 * The main function of the VPN service.
3127 * @param argc number of arguments from the command line
3128 * @param argv command line arguments
3129 * @return 0 ok, 1 on error
3132 main (int argc, char *const *argv)
3134 return (GNUNET_OK ==
3135 GNUNET_SERVICE_run (argc, argv, "vpn",
3136 GNUNET_SERVICE_OPTION_NONE,
3137 &run, NULL)) ? global_ret : 1;
3140 /* end of gnunet-service-vpn.c */