2 This file is part of GNUnet.
3 Copyright (C) 2010, 2011, 2012, 2016, 2017 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., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301, 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 * Destination port this channel state is used for.
89 uint16_t destination_port;
95 * Information we track for each IP address to determine which channel
96 * to send the traffic over to the destination.
98 struct DestinationEntry
102 * Key under which this entry is in the 'destination_map' (only valid
103 * if 'heap_node != NULL').
105 struct GNUNET_HashCode key;
108 * Head of DLL of channels associated with this destination.
110 struct DestinationChannel *dt_head;
113 * Tail of DLL of channels associated with this destination.
115 struct DestinationChannel *dt_tail;
118 * Entry for this entry in the destination_heap.
120 struct GNUNET_CONTAINER_HeapNode *heap_node;
123 * #GNUNET_NO if this is a channel to an Internet-exit,
124 * #GNUNET_YES if this channel is to a service.
129 * Details about the connection (depending on is_service).
137 * The description of the service (only used for service channels).
139 struct GNUNET_HashCode service_descriptor;
142 * Peer offering the service.
144 struct GNUNET_PeerIdentity target;
146 } service_destination;
152 * Address family used (AF_INET or AF_INET6).
157 * IP address of the ultimate destination (only used for exit channels).
162 * Address if af is AF_INET.
167 * Address if af is AF_INET6.
180 * A messages we have in queue for a particular channel.
182 struct ChannelMessageQueueEntry
185 * This is a doubly-linked list.
187 struct ChannelMessageQueueEntry *next;
190 * This is a doubly-linked list.
192 struct ChannelMessageQueueEntry *prev;
195 * Number of bytes in @e msg.
200 * Message to transmit, allocated at the end of this struct.
207 * State we keep for each of our channels.
213 * Information about the channel to use, NULL if no channel
214 * is available right now.
216 struct GNUNET_CADET_Channel *channel;
219 * Active query with REGEX to locate exit.
221 struct GNUNET_REGEX_Search *search;
224 * Entry for this entry in the channel_heap, NULL as long as this
225 * channel state is not fully bound.
227 struct GNUNET_CONTAINER_HeapNode *heap_node;
230 * Head of list of messages scheduled for transmission.
232 struct ChannelMessageQueueEntry *tmq_head;
235 * Tail of list of messages scheduled for transmission.
237 struct ChannelMessageQueueEntry *tmq_tail;
240 * Destination to which this channel leads. Note that
241 * this struct is NOT in the destination_map (but a
242 * local copy) and that the 'heap_node' should always
245 struct DestinationEntry destination;
248 * Addess family used for this channel on the local TUN interface.
253 * Is this channel new (#GNUNET_NO), or did we exchange messages with the
254 * other side already (#GNUNET_YES)?
259 * Length of the doubly linked 'tmq_head/tmq_tail' list.
261 unsigned int tmq_length;
264 * IPPROTO_TCP or IPPROTO_UDP once bound.
269 * IP address of the source on our end, initially uninitialized.
274 * Address if af is AF_INET.
279 * Address if af is AF_INET6.
286 * Destination IP address used by the source on our end (this is the IP
287 * that we pick freely within the VPN's channel IP range).
292 * Address if af is AF_INET.
297 * Address if af is AF_INET6.
304 * Source port used by the sender on our end; 0 for uninitialized.
306 uint16_t source_port;
309 * Destination port used by the sender on our end; 0 for uninitialized.
311 uint16_t destination_port;
317 * Return value from #main().
319 static int global_ret;
322 * Configuration we use.
324 static const struct GNUNET_CONFIGURATION_Handle *cfg;
327 * Handle to the cadet service.
329 static struct GNUNET_CADET_Handle *cadet_handle;
332 * Map from IP address to destination information (possibly with a
333 * CADET channel handle for fast setup).
335 static struct GNUNET_CONTAINER_MultiHashMap *destination_map;
338 * Min-Heap sorted by activity time to expire old mappings.
340 static struct GNUNET_CONTAINER_Heap *destination_heap;
343 * Map from source and destination address (IP+port) to connection
344 * information (mostly with the respective CADET channel handle).
346 static struct GNUNET_CONTAINER_MultiHashMap *channel_map;
349 * Min-Heap sorted by activity time to expire old mappings; values are
350 * of type 'struct ChannelState'.
352 static struct GNUNET_CONTAINER_Heap *channel_heap;
357 static struct GNUNET_STATISTICS_Handle *stats;
360 * The handle to the VPN helper process "gnunet-helper-vpn".
362 static struct GNUNET_HELPER_Handle *helper_handle;
365 * Arguments to the vpn helper.
367 static char *vpn_argv[7];
370 * Length of the prefix of the VPN's IPv6 network.
372 static unsigned long long ipv6prefix;
375 * If there are more than this number of address-mappings, old ones
378 static unsigned long long max_destination_mappings;
381 * If there are more than this number of open channels, old ones
384 static unsigned long long max_channel_mappings;
388 * Compute the key under which we would store an entry in the
389 * #destination_map for the given IP address.
391 * @param af address family (AF_INET or AF_INET6)
392 * @param address IP address, struct in_addr or struct in6_addr
393 * @param key where to store the key
396 get_destination_key_from_ip (int af,
398 struct GNUNET_HashCode *key)
403 GNUNET_CRYPTO_hash (address,
404 sizeof (struct in_addr),
408 GNUNET_CRYPTO_hash (address,
409 sizeof (struct in6_addr),
420 * Compute the key under which we would store an entry in the
421 * channel_map for the given socket address pair.
423 * @param af address family (AF_INET or AF_INET6)
424 * @param protocol IPPROTO_TCP or IPPROTO_UDP
425 * @param source_ip sender's source IP, struct in_addr or struct in6_addr
426 * @param source_port sender's source port
427 * @param destination_ip sender's destination IP, struct in_addr or struct in6_addr
428 * @param destination_port sender's destination port
429 * @param key where to store the key
432 get_channel_key_from_ips (int af,
434 const void *source_ip,
435 uint16_t source_port,
436 const void *destination_ip,
437 uint16_t destination_port,
438 struct GNUNET_HashCode *key)
442 memset (key, 0, sizeof (struct GNUNET_HashCode));
443 /* the GNUnet hashmap only uses the first sizeof(unsigned int) of the hash,
444 so we put the ports in there (and hope for few collisions) */
446 GNUNET_memcpy (off, &source_port, sizeof (uint16_t));
447 off += sizeof (uint16_t);
448 GNUNET_memcpy (off, &destination_port, sizeof (uint16_t));
449 off += sizeof (uint16_t);
453 GNUNET_memcpy (off, source_ip, sizeof (struct in_addr));
454 off += sizeof (struct in_addr);
455 GNUNET_memcpy (off, destination_ip, sizeof (struct in_addr));
456 off += sizeof (struct in_addr);
459 GNUNET_memcpy (off, source_ip, sizeof (struct in6_addr));
460 off += sizeof (struct in6_addr);
461 GNUNET_memcpy (off, destination_ip, sizeof (struct in6_addr));
462 off += sizeof (struct in6_addr);
468 GNUNET_memcpy (off, &protocol, sizeof (uint8_t));
469 /* off += sizeof (uint8_t); */
474 * Notify the client about the result of its request.
476 * @param client client to notify
477 * @param request_id original request ID to include in response
478 * @param result_af resulting address family
479 * @param addr resulting IP address
482 send_client_reply (struct GNUNET_SERVICE_Client *client,
487 struct GNUNET_MQ_Envelope *env;
488 struct RedirectToIpResponseMessage *res;
494 rlen = sizeof (struct in_addr);
497 rlen = sizeof (struct in6_addr);
506 env = GNUNET_MQ_msg_extra (res,
508 GNUNET_MESSAGE_TYPE_VPN_CLIENT_USE_IP);
509 res->result_af = htonl (result_af);
510 res->request_id = request_id;
511 GNUNET_memcpy (&res[1],
514 GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq (client),
520 * Free resources associated with a channel state.
522 * @param ts state to free
525 free_channel_state (struct ChannelState *ts)
527 struct GNUNET_HashCode key;
528 struct ChannelMessageQueueEntry *tnq;
529 struct GNUNET_CADET_Channel *channel;
531 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
532 "Cleaning up channel state\n");
533 if (NULL != (channel = ts->channel))
536 GNUNET_CADET_channel_destroy (channel);
539 GNUNET_STATISTICS_update (stats,
540 gettext_noop ("# Active channels"),
542 while (NULL != (tnq = ts->tmq_head))
544 GNUNET_CONTAINER_DLL_remove (ts->tmq_head,
550 GNUNET_assert (0 == ts->tmq_length);
551 GNUNET_assert (NULL == ts->destination.heap_node);
552 if (NULL != ts->search)
554 GNUNET_REGEX_search_cancel (ts->search);
557 if (NULL != ts->heap_node)
559 GNUNET_CONTAINER_heap_remove_node (ts->heap_node);
560 ts->heap_node = NULL;
561 get_channel_key_from_ips (ts->af,
566 ts->destination_port,
568 GNUNET_assert (GNUNET_YES ==
569 GNUNET_CONTAINER_multihashmap_remove (channel_map,
578 * Add the given message to the given channel and trigger the
579 * transmission process.
581 * @param ts channel to queue the message for
582 * @param env message to queue
585 send_to_channel (struct ChannelState *ts,
586 struct GNUNET_MQ_Envelope *env)
588 struct GNUNET_MQ_Handle *mq;
590 GNUNET_assert (NULL != ts->channel);
591 mq = GNUNET_CADET_get_mq (ts->channel);
594 if (GNUNET_MQ_get_length (mq) > MAX_MESSAGE_QUEUE_SIZE)
596 env = GNUNET_MQ_unsent_head (mq);
597 GNUNET_assert (NULL != env);
598 GNUNET_STATISTICS_update (stats,
599 gettext_noop ("# Messages dropped in cadet queue (overflow)"),
602 GNUNET_MQ_discard (env);
608 * Output destination of a channel for diagnostics.
610 * @param de destination to process
611 * @return diagnostic string describing destination
614 print_channel_destination (const struct DestinationEntry *de)
616 static char dest[256];
620 GNUNET_snprintf (dest,
623 GNUNET_i2s (&de->details.service_destination.target),
624 GNUNET_h2s (&de->details.service_destination.service_descriptor));
628 inet_ntop (de->details.exit_destination.af,
629 &de->details.exit_destination.ip,
638 * Function called whenever a channel is destroyed. Should clean up
639 * any associated state.
641 * @param cls our `struct ChannelState`
642 * @param channel connection to the other end (henceforth invalid)
645 channel_cleaner (void *cls,
646 const struct GNUNET_CADET_Channel *channel)
648 struct ChannelState *ts = cls;
650 ts->channel = NULL; /* we must not call GNUNET_CADET_channel_destroy() anymore */
651 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
652 "CADET notified us about death of channel to `%s'\n",
653 print_channel_destination (&ts->destination));
654 free_channel_state (ts);
659 * Synthesize a plausible ICMP payload for an ICMP error
660 * response on the given channel.
662 * @param ts channel information
663 * @param ipp IPv4 header to fill in (ICMP payload)
664 * @param udp "UDP" header to fill in (ICMP payload); might actually
665 * also be the first 8 bytes of the TCP header
668 make_up_icmpv4_payload (struct ChannelState *ts,
669 struct GNUNET_TUN_IPv4Header *ipp,
670 struct GNUNET_TUN_UdpHeader *udp)
672 GNUNET_TUN_initialize_ipv4_header (ipp,
674 sizeof (struct GNUNET_TUN_TcpHeader),
676 &ts->destination_ip.v4);
677 udp->source_port = htons (ts->source_port);
678 udp->destination_port = htons (ts->destination_port);
679 udp->len = htons (0);
680 udp->crc = htons (0);
685 * Synthesize a plausible ICMP payload for an ICMP error
686 * response on the given channel.
688 * @param ts channel information
689 * @param ipp IPv6 header to fill in (ICMP payload)
690 * @param udp "UDP" header to fill in (ICMP payload); might actually
691 * also be the first 8 bytes of the TCP header
694 make_up_icmpv6_payload (struct ChannelState *ts,
695 struct GNUNET_TUN_IPv6Header *ipp,
696 struct GNUNET_TUN_UdpHeader *udp)
698 GNUNET_TUN_initialize_ipv6_header (ipp,
700 sizeof (struct GNUNET_TUN_TcpHeader),
702 &ts->destination_ip.v6);
703 udp->source_port = htons (ts->source_port);
704 udp->destination_port = htons (ts->destination_port);
705 udp->len = htons (0);
706 udp->crc = htons (0);
711 * We got an ICMP packet back from the CADET channel. Check it is OK.
713 * @param cls our `struct ChannelState *`
714 * @param message the actual message
715 * @return #GNUNET_OK to keep the connection open,
716 * #GNUNET_SYSERR to close it (signal serious error)
719 check_icmp_back (void *cls,
720 const struct GNUNET_EXIT_IcmpToVPNMessage *i2v)
722 struct ChannelState *ts = cls;
724 if (NULL == ts->heap_node)
727 return GNUNET_SYSERR;
729 if (AF_UNSPEC == ts->af)
732 return GNUNET_SYSERR;
739 * We got an ICMP packet back from the CADET channel. Pass it on to the
740 * local virtual interface via the helper.
742 * @param cls our `struct ChannelState *`
743 * @param message the actual message
746 handle_icmp_back (void *cls,
747 const struct GNUNET_EXIT_IcmpToVPNMessage *i2v)
749 struct ChannelState *ts = cls;
752 GNUNET_STATISTICS_update (stats,
753 gettext_noop ("# ICMP packets received from cadet"),
756 mlen = ntohs (i2v->header.size) - sizeof (struct GNUNET_EXIT_IcmpToVPNMessage);
758 char sbuf[INET6_ADDRSTRLEN];
759 char dbuf[INET6_ADDRSTRLEN];
761 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
762 "Received ICMP packet from cadet, sending %u bytes from %s -> %s via TUN\n",
764 inet_ntop (ts->af, &ts->destination_ip, sbuf, sizeof (sbuf)),
765 inet_ntop (ts->af, &ts->source_ip, dbuf, sizeof (dbuf)));
771 size_t size = sizeof (struct GNUNET_TUN_IPv4Header)
772 + sizeof (struct GNUNET_TUN_IcmpHeader)
773 + sizeof (struct GNUNET_MessageHeader) +
774 sizeof (struct GNUNET_TUN_Layer2PacketHeader) +
777 /* reserve some extra space in case we have an ICMP type here where
778 we will need to make up the payload ourselves */
779 char buf[size + sizeof (struct GNUNET_TUN_IPv4Header) + 8] GNUNET_ALIGN;
780 struct GNUNET_MessageHeader *msg = (struct GNUNET_MessageHeader *) buf;
781 struct GNUNET_TUN_Layer2PacketHeader *tun = (struct GNUNET_TUN_Layer2PacketHeader*) &msg[1];
782 struct GNUNET_TUN_IPv4Header *ipv4 = (struct GNUNET_TUN_IPv4Header *) &tun[1];
783 struct GNUNET_TUN_IcmpHeader *icmp = (struct GNUNET_TUN_IcmpHeader *) &ipv4[1];
784 msg->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
785 tun->flags = htons (0);
786 tun->proto = htons (ETH_P_IPV4);
787 GNUNET_TUN_initialize_ipv4_header (ipv4,
789 sizeof (struct GNUNET_TUN_IcmpHeader) + mlen,
790 &ts->destination_ip.v4,
792 *icmp = i2v->icmp_header;
793 GNUNET_memcpy (&icmp[1],
796 /* For some ICMP types, we need to adjust (make up) the payload here.
797 Also, depending on the AF used on the other side, we have to
798 do ICMP PT (translate ICMP types) */
799 switch (ntohl (i2v->af))
804 case GNUNET_TUN_ICMPTYPE_ECHO_REPLY:
805 case GNUNET_TUN_ICMPTYPE_ECHO_REQUEST:
807 case GNUNET_TUN_ICMPTYPE_DESTINATION_UNREACHABLE:
808 case GNUNET_TUN_ICMPTYPE_SOURCE_QUENCH:
809 case GNUNET_TUN_ICMPTYPE_TIME_EXCEEDED:
811 struct GNUNET_TUN_IPv4Header *ipp = (struct GNUNET_TUN_IPv4Header *) &icmp[1];
812 struct GNUNET_TUN_UdpHeader *udp = (struct GNUNET_TUN_UdpHeader *) &ipp[1];
816 /* sender did not strip ICMP payload? */
820 size += sizeof (struct GNUNET_TUN_IPv4Header) + 8;
821 GNUNET_assert (8 == sizeof (struct GNUNET_TUN_UdpHeader));
822 make_up_icmpv4_payload (ts, ipp, udp);
827 GNUNET_STATISTICS_update (stats,
828 gettext_noop ("# ICMPv4 packets dropped (type not allowed)"),
835 /* ICMP PT 6-to-4 and possibly making up payloads */
838 case GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE:
839 icmp->type = GNUNET_TUN_ICMPTYPE_DESTINATION_UNREACHABLE;
841 struct GNUNET_TUN_IPv4Header *ipp = (struct GNUNET_TUN_IPv4Header *) &icmp[1];
842 struct GNUNET_TUN_UdpHeader *udp = (struct GNUNET_TUN_UdpHeader *) &ipp[1];
846 /* sender did not strip ICMP payload? */
850 size += sizeof (struct GNUNET_TUN_IPv4Header) + 8;
851 GNUNET_assert (8 == sizeof (struct GNUNET_TUN_UdpHeader));
852 make_up_icmpv4_payload (ts, ipp, udp);
855 case GNUNET_TUN_ICMPTYPE6_TIME_EXCEEDED:
856 icmp->type = GNUNET_TUN_ICMPTYPE_TIME_EXCEEDED;
858 struct GNUNET_TUN_IPv4Header *ipp = (struct GNUNET_TUN_IPv4Header *) &icmp[1];
859 struct GNUNET_TUN_UdpHeader *udp = (struct GNUNET_TUN_UdpHeader *) &ipp[1];
863 /* sender did not strip ICMP payload? */
867 size += sizeof (struct GNUNET_TUN_IPv4Header) + 8;
868 GNUNET_assert (8 == sizeof (struct GNUNET_TUN_UdpHeader));
869 make_up_icmpv4_payload (ts, ipp, udp);
872 case GNUNET_TUN_ICMPTYPE6_PACKET_TOO_BIG:
873 case GNUNET_TUN_ICMPTYPE6_PARAMETER_PROBLEM:
874 GNUNET_STATISTICS_update (stats,
875 gettext_noop ("# ICMPv6 packets dropped (impossible PT to v4)"),
878 case GNUNET_TUN_ICMPTYPE6_ECHO_REQUEST:
879 icmp->type = GNUNET_TUN_ICMPTYPE_ECHO_REQUEST;
881 case GNUNET_TUN_ICMPTYPE6_ECHO_REPLY:
882 icmp->type = GNUNET_TUN_ICMPTYPE_ECHO_REPLY;
886 GNUNET_STATISTICS_update (stats,
887 gettext_noop ("# ICMPv6 packets dropped (type not allowed)"),
897 msg->size = htons (size);
898 GNUNET_TUN_calculate_icmp_checksum (icmp,
901 (void) GNUNET_HELPER_send (helper_handle,
910 size_t size = sizeof (struct GNUNET_TUN_IPv6Header)
911 + sizeof (struct GNUNET_TUN_IcmpHeader)
912 + sizeof (struct GNUNET_MessageHeader) +
913 sizeof (struct GNUNET_TUN_Layer2PacketHeader) +
916 char buf[size + sizeof (struct GNUNET_TUN_IPv6Header) + 8] GNUNET_ALIGN;
917 struct GNUNET_MessageHeader *msg = (struct GNUNET_MessageHeader *) buf;
918 struct GNUNET_TUN_Layer2PacketHeader *tun = (struct GNUNET_TUN_Layer2PacketHeader*) &msg[1];
919 struct GNUNET_TUN_IPv6Header *ipv6 = (struct GNUNET_TUN_IPv6Header *) &tun[1];
920 struct GNUNET_TUN_IcmpHeader *icmp = (struct GNUNET_TUN_IcmpHeader *) &ipv6[1];
921 msg->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
922 tun->flags = htons (0);
923 tun->proto = htons (ETH_P_IPV6);
924 GNUNET_TUN_initialize_ipv6_header (ipv6,
926 sizeof (struct GNUNET_TUN_IcmpHeader) + mlen,
927 &ts->destination_ip.v6,
929 *icmp = i2v->icmp_header;
930 GNUNET_memcpy (&icmp[1],
934 /* For some ICMP types, we need to adjust (make up) the payload here.
935 Also, depending on the AF used on the other side, we have to
936 do ICMP PT (translate ICMP types) */
937 switch (ntohl (i2v->af))
940 /* ICMP PT 4-to-6 and possibly making up payloads */
943 case GNUNET_TUN_ICMPTYPE_ECHO_REPLY:
944 icmp->type = GNUNET_TUN_ICMPTYPE6_ECHO_REPLY;
946 case GNUNET_TUN_ICMPTYPE_ECHO_REQUEST:
947 icmp->type = GNUNET_TUN_ICMPTYPE6_ECHO_REQUEST;
949 case GNUNET_TUN_ICMPTYPE_DESTINATION_UNREACHABLE:
950 icmp->type = GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE;
952 struct GNUNET_TUN_IPv6Header *ipp = (struct GNUNET_TUN_IPv6Header *) &icmp[1];
953 struct GNUNET_TUN_UdpHeader *udp = (struct GNUNET_TUN_UdpHeader *) &ipp[1];
957 /* sender did not strip ICMP payload? */
961 size += sizeof (struct GNUNET_TUN_IPv6Header) + 8;
962 GNUNET_assert (8 == sizeof (struct GNUNET_TUN_UdpHeader));
963 make_up_icmpv6_payload (ts, ipp, udp);
966 case GNUNET_TUN_ICMPTYPE_TIME_EXCEEDED:
967 icmp->type = GNUNET_TUN_ICMPTYPE6_TIME_EXCEEDED;
969 struct GNUNET_TUN_IPv6Header *ipp = (struct GNUNET_TUN_IPv6Header *) &icmp[1];
970 struct GNUNET_TUN_UdpHeader *udp = (struct GNUNET_TUN_UdpHeader *) &ipp[1];
974 /* sender did not strip ICMP payload? */
978 size += sizeof (struct GNUNET_TUN_IPv6Header) + 8;
979 GNUNET_assert (8 == sizeof (struct GNUNET_TUN_UdpHeader));
980 make_up_icmpv6_payload (ts, ipp, udp);
983 case GNUNET_TUN_ICMPTYPE_SOURCE_QUENCH:
984 GNUNET_STATISTICS_update (stats,
985 gettext_noop ("# ICMPv4 packets dropped (impossible PT to v6)"),
990 GNUNET_STATISTICS_update (stats,
991 gettext_noop ("# ICMPv4 packets dropped (type not allowed)"),
1000 case GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE:
1001 case GNUNET_TUN_ICMPTYPE6_TIME_EXCEEDED:
1002 case GNUNET_TUN_ICMPTYPE6_PACKET_TOO_BIG:
1003 case GNUNET_TUN_ICMPTYPE6_PARAMETER_PROBLEM:
1005 struct GNUNET_TUN_IPv6Header *ipp = (struct GNUNET_TUN_IPv6Header *) &icmp[1];
1006 struct GNUNET_TUN_UdpHeader *udp = (struct GNUNET_TUN_UdpHeader *) &ipp[1];
1010 /* sender did not strip ICMP payload? */
1011 GNUNET_break_op (0);
1014 size += sizeof (struct GNUNET_TUN_IPv6Header) + 8;
1015 GNUNET_assert (8 == sizeof (struct GNUNET_TUN_UdpHeader));
1016 make_up_icmpv6_payload (ts, ipp, udp);
1019 case GNUNET_TUN_ICMPTYPE6_ECHO_REQUEST:
1022 GNUNET_break_op (0);
1023 GNUNET_STATISTICS_update (stats,
1024 gettext_noop ("# ICMPv6 packets dropped (type not allowed)"),
1031 GNUNET_break_op (0);
1034 msg->size = htons (size);
1035 GNUNET_TUN_calculate_icmp_checksum (icmp,
1037 (void) GNUNET_HELPER_send (helper_handle,
1047 GNUNET_CONTAINER_heap_update_cost (ts->heap_node,
1048 GNUNET_TIME_absolute_get ().abs_value_us);
1049 GNUNET_CADET_receive_done (ts->channel);
1054 * We got a UDP packet back from the CADET channel. Check that it is OK.
1056 * @param cls our `struct ChannelState *`
1057 * @param reply the actual message
1058 * @return #GNUNET_OK to keep the connection open,
1059 * #GNUNET_SYSERR to close it (signal serious error)
1062 check_udp_back (void *cls,
1063 const struct GNUNET_EXIT_UdpReplyMessage *reply)
1065 struct ChannelState *ts = cls;
1067 if (NULL == ts->heap_node)
1069 GNUNET_break_op (0);
1070 return GNUNET_SYSERR;
1072 if (AF_UNSPEC == ts->af)
1074 GNUNET_break_op (0);
1075 return GNUNET_SYSERR;
1082 * We got a UDP packet back from the CADET channel. Pass it on to the
1083 * local virtual interface via the helper.
1085 * @param cls our `struct ChannelState *`
1086 * @param reply the actual message
1089 handle_udp_back (void *cls,
1090 const struct GNUNET_EXIT_UdpReplyMessage *reply)
1092 struct ChannelState *ts = cls;
1095 GNUNET_STATISTICS_update (stats,
1096 gettext_noop ("# UDP packets received from cadet"),
1099 mlen = ntohs (reply->header.size) - sizeof (struct GNUNET_EXIT_UdpReplyMessage);
1101 char sbuf[INET6_ADDRSTRLEN];
1102 char dbuf[INET6_ADDRSTRLEN];
1104 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1105 "Received UDP reply from cadet, sending %u bytes from [%s]:%u -> [%s]:%u via TUN\n",
1106 (unsigned int) mlen,
1107 inet_ntop (ts->af, &ts->destination_ip, sbuf, sizeof (sbuf)),
1108 ts->destination_port,
1109 inet_ntop (ts->af, &ts->source_ip, dbuf, sizeof (dbuf)),
1116 size_t size = sizeof (struct GNUNET_TUN_IPv4Header)
1117 + sizeof (struct GNUNET_TUN_UdpHeader)
1118 + sizeof (struct GNUNET_MessageHeader) +
1119 sizeof (struct GNUNET_TUN_Layer2PacketHeader) +
1122 char buf[size] GNUNET_ALIGN;
1123 struct GNUNET_MessageHeader *msg = (struct GNUNET_MessageHeader *) buf;
1124 struct GNUNET_TUN_Layer2PacketHeader *tun = (struct GNUNET_TUN_Layer2PacketHeader*) &msg[1];
1125 struct GNUNET_TUN_IPv4Header *ipv4 = (struct GNUNET_TUN_IPv4Header *) &tun[1];
1126 struct GNUNET_TUN_UdpHeader *udp = (struct GNUNET_TUN_UdpHeader *) &ipv4[1];
1127 msg->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
1128 msg->size = htons (size);
1129 tun->flags = htons (0);
1130 tun->proto = htons (ETH_P_IPV4);
1131 GNUNET_TUN_initialize_ipv4_header (ipv4,
1133 sizeof (struct GNUNET_TUN_UdpHeader) + mlen,
1134 &ts->destination_ip.v4,
1136 if (0 == ntohs (reply->source_port))
1137 udp->source_port = htons (ts->destination_port);
1139 udp->source_port = reply->source_port;
1140 if (0 == ntohs (reply->destination_port))
1141 udp->destination_port = htons (ts->source_port);
1143 udp->destination_port = reply->destination_port;
1144 udp->len = htons (mlen + sizeof (struct GNUNET_TUN_UdpHeader));
1145 GNUNET_TUN_calculate_udp4_checksum (ipv4,
1149 GNUNET_memcpy (&udp[1],
1152 (void) GNUNET_HELPER_send (helper_handle,
1161 size_t size = sizeof (struct GNUNET_TUN_IPv6Header)
1162 + sizeof (struct GNUNET_TUN_UdpHeader)
1163 + sizeof (struct GNUNET_MessageHeader) +
1164 sizeof (struct GNUNET_TUN_Layer2PacketHeader) +
1167 char buf[size] GNUNET_ALIGN;
1168 struct GNUNET_MessageHeader *msg = (struct GNUNET_MessageHeader *) buf;
1169 struct GNUNET_TUN_Layer2PacketHeader *tun = (struct GNUNET_TUN_Layer2PacketHeader*) &msg[1];
1170 struct GNUNET_TUN_IPv6Header *ipv6 = (struct GNUNET_TUN_IPv6Header *) &tun[1];
1171 struct GNUNET_TUN_UdpHeader *udp = (struct GNUNET_TUN_UdpHeader *) &ipv6[1];
1172 msg->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
1173 msg->size = htons (size);
1174 tun->flags = htons (0);
1175 tun->proto = htons (ETH_P_IPV6);
1176 GNUNET_TUN_initialize_ipv6_header (ipv6,
1178 sizeof (struct GNUNET_TUN_UdpHeader) + mlen,
1179 &ts->destination_ip.v6,
1181 if (0 == ntohs (reply->source_port))
1182 udp->source_port = htons (ts->destination_port);
1184 udp->source_port = reply->source_port;
1185 if (0 == ntohs (reply->destination_port))
1186 udp->destination_port = htons (ts->source_port);
1188 udp->destination_port = reply->destination_port;
1189 udp->len = htons (mlen + sizeof (struct GNUNET_TUN_UdpHeader));
1190 GNUNET_TUN_calculate_udp6_checksum (ipv6,
1193 GNUNET_memcpy (&udp[1],
1196 (void) GNUNET_HELPER_send (helper_handle,
1206 GNUNET_CONTAINER_heap_update_cost (ts->heap_node,
1207 GNUNET_TIME_absolute_get ().abs_value_us);
1208 GNUNET_CADET_receive_done (ts->channel);
1213 * We got a TCP packet back from the CADET channel. Check it is OK.
1215 * @param cls our `struct ChannelState *`
1216 * @param data the actual message
1217 * @return #GNUNET_OK to keep the connection open,
1218 * #GNUNET_SYSERR to close it (signal serious error)
1221 check_tcp_back (void *cls,
1222 const struct GNUNET_EXIT_TcpDataMessage *data)
1224 struct ChannelState *ts = cls;
1226 if (NULL == ts->heap_node)
1228 GNUNET_break_op (0);
1229 return GNUNET_SYSERR;
1231 if (data->tcp_header.off * 4 < sizeof (struct GNUNET_TUN_TcpHeader))
1233 GNUNET_break_op (0);
1234 return GNUNET_SYSERR;
1241 * We got a TCP packet back from the CADET channel. Pass it on to the
1242 * local virtual interface via the helper.
1244 * @param cls our `struct ChannelState *`
1245 * @param data the actual message
1248 handle_tcp_back (void *cls,
1249 const struct GNUNET_EXIT_TcpDataMessage *data)
1251 struct ChannelState *ts = cls;
1254 GNUNET_STATISTICS_update (stats,
1255 gettext_noop ("# TCP packets received from cadet"),
1258 mlen = ntohs (data->header.size) - sizeof (struct GNUNET_EXIT_TcpDataMessage);
1260 char sbuf[INET6_ADDRSTRLEN];
1261 char dbuf[INET6_ADDRSTRLEN];
1263 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1264 "Received TCP reply from cadet, sending %u bytes from [%s]:%u -> [%s]:%u via TUN\n",
1265 (unsigned int) mlen,
1266 inet_ntop (ts->af, &ts->destination_ip, sbuf, sizeof (sbuf)),
1267 ts->destination_port,
1268 inet_ntop (ts->af, &ts->source_ip, dbuf, sizeof (dbuf)),
1275 size_t size = sizeof (struct GNUNET_TUN_IPv4Header)
1276 + sizeof (struct GNUNET_TUN_TcpHeader)
1277 + sizeof (struct GNUNET_MessageHeader) +
1278 sizeof (struct GNUNET_TUN_Layer2PacketHeader) +
1281 char buf[size] GNUNET_ALIGN;
1282 struct GNUNET_MessageHeader *msg = (struct GNUNET_MessageHeader *) buf;
1283 struct GNUNET_TUN_Layer2PacketHeader *tun = (struct GNUNET_TUN_Layer2PacketHeader*) &msg[1];
1284 struct GNUNET_TUN_IPv4Header *ipv4 = (struct GNUNET_TUN_IPv4Header *) &tun[1];
1285 struct GNUNET_TUN_TcpHeader *tcp = (struct GNUNET_TUN_TcpHeader *) &ipv4[1];
1286 msg->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
1287 msg->size = htons (size);
1288 tun->flags = htons (0);
1289 tun->proto = htons (ETH_P_IPV4);
1290 GNUNET_TUN_initialize_ipv4_header (ipv4,
1292 sizeof (struct GNUNET_TUN_TcpHeader) + mlen,
1293 &ts->destination_ip.v4,
1295 *tcp = data->tcp_header;
1296 tcp->source_port = htons (ts->destination_port);
1297 tcp->destination_port = htons (ts->source_port);
1298 GNUNET_TUN_calculate_tcp4_checksum (ipv4,
1302 GNUNET_memcpy (&tcp[1],
1305 (void) GNUNET_HELPER_send (helper_handle,
1314 size_t size = sizeof (struct GNUNET_TUN_IPv6Header)
1315 + sizeof (struct GNUNET_TUN_TcpHeader)
1316 + sizeof (struct GNUNET_MessageHeader) +
1317 sizeof (struct GNUNET_TUN_Layer2PacketHeader) +
1320 char buf[size] GNUNET_ALIGN;
1321 struct GNUNET_MessageHeader *msg = (struct GNUNET_MessageHeader *) buf;
1322 struct GNUNET_TUN_Layer2PacketHeader *tun = (struct GNUNET_TUN_Layer2PacketHeader*) &msg[1];
1323 struct GNUNET_TUN_IPv6Header *ipv6 = (struct GNUNET_TUN_IPv6Header *) &tun[1];
1324 struct GNUNET_TUN_TcpHeader *tcp = (struct GNUNET_TUN_TcpHeader *) &ipv6[1];
1325 msg->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
1326 msg->size = htons (size);
1327 tun->flags = htons (0);
1328 tun->proto = htons (ETH_P_IPV6);
1329 GNUNET_TUN_initialize_ipv6_header (ipv6,
1331 sizeof (struct GNUNET_TUN_TcpHeader) + mlen,
1332 &ts->destination_ip.v6,
1334 *tcp = data->tcp_header;
1335 tcp->source_port = htons (ts->destination_port);
1336 tcp->destination_port = htons (ts->source_port);
1337 GNUNET_TUN_calculate_tcp6_checksum (ipv6,
1341 GNUNET_memcpy (&tcp[1],
1344 (void) GNUNET_HELPER_send (helper_handle,
1352 GNUNET_CONTAINER_heap_update_cost (ts->heap_node,
1353 GNUNET_TIME_absolute_get ().abs_value_us);
1354 GNUNET_CADET_receive_done (ts->channel);
1359 * Create a channel for @a ts to @a target at @a port
1361 * @param ts channel state to create the channel for
1362 * @param target peer to connect to
1363 * @param port destination port
1364 * @return the channel handle
1366 static struct GNUNET_CADET_Channel *
1367 create_channel (struct ChannelState *ts,
1368 const struct GNUNET_PeerIdentity *target,
1369 const struct GNUNET_HashCode *port)
1371 struct GNUNET_MQ_MessageHandler cadet_handlers[] = {
1372 GNUNET_MQ_hd_var_size (udp_back,
1373 GNUNET_MESSAGE_TYPE_VPN_UDP_REPLY,
1374 struct GNUNET_EXIT_UdpReplyMessage,
1376 GNUNET_MQ_hd_var_size (tcp_back,
1377 GNUNET_MESSAGE_TYPE_VPN_TCP_DATA_TO_VPN,
1378 struct GNUNET_EXIT_TcpDataMessage,
1380 GNUNET_MQ_hd_var_size (icmp_back,
1381 GNUNET_MESSAGE_TYPE_VPN_ICMP_TO_VPN,
1382 struct GNUNET_EXIT_IcmpToVPNMessage,
1384 GNUNET_MQ_handler_end()
1387 return GNUNET_CADET_channel_creatE (cadet_handle,
1391 GNUNET_CADET_OPTION_DEFAULT,
1399 * Regex has found a potential exit peer for us; consider using it.
1401 * @param cls the `struct ChannelState`
1402 * @param id Peer providing a regex that matches the string.
1403 * @param get_path Path of the get request.
1404 * @param get_path_length Lenght of @a get_path.
1405 * @param put_path Path of the put request.
1406 * @param put_path_length Length of the @a put_path.
1409 handle_regex_result (void *cls,
1410 const struct GNUNET_PeerIdentity *id,
1411 const struct GNUNET_PeerIdentity *get_path,
1412 unsigned int get_path_length,
1413 const struct GNUNET_PeerIdentity *put_path,
1414 unsigned int put_path_length)
1416 struct ChannelState *ts = cls;
1417 struct GNUNET_HashCode port;
1419 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1420 "Exit %s found for destination %s!\n",
1422 print_channel_destination (&ts->destination));
1423 GNUNET_REGEX_search_cancel (ts->search);
1428 /* these must match the strings used in gnunet-daemon-exit */
1429 GNUNET_CRYPTO_hash (GNUNET_APPLICATION_PORT_IPV4_GATEWAY,
1430 strlen (GNUNET_APPLICATION_PORT_IPV4_GATEWAY),
1434 /* these must match the strings used in gnunet-daemon-exit */
1435 GNUNET_CRYPTO_hash (GNUNET_APPLICATION_PORT_IPV6_GATEWAY,
1436 strlen (GNUNET_APPLICATION_PORT_IPV6_GATEWAY),
1443 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1444 "Creating tunnel to %s for destination %s!\n",
1446 print_channel_destination (&ts->destination));
1447 ts->channel = create_channel (ts,
1454 * Initialize the given destination entry's cadet channel.
1456 * @param dt destination channel for which we need to setup a channel
1457 * @param client_af address family of the address returned to the client
1458 * @return channel state of the channel that was created
1460 static struct ChannelState *
1461 create_channel_to_destination (struct DestinationChannel *dt,
1464 struct ChannelState *ts;
1466 GNUNET_STATISTICS_update (stats,
1467 gettext_noop ("# Cadet channels created"),
1470 ts = GNUNET_new (struct ChannelState);
1472 ts->destination = *dt->destination;
1473 ts->destination.heap_node = NULL; /* copy is NOT in destination heap */
1474 ts->destination_port = dt->destination_port;
1475 if (dt->destination->is_service)
1477 struct GNUNET_HashCode cadet_port;
1479 GNUNET_TUN_compute_service_cadet_port (&ts->destination.details.service_destination.service_descriptor,
1480 ts->destination_port,
1482 ts->channel = create_channel (ts,
1483 &dt->destination->details.service_destination.target,
1486 if (NULL == ts->channel)
1492 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1493 "Creating channel to peer %s offering service %s on port %u\n",
1494 GNUNET_i2s (&dt->destination->details.service_destination.target),
1495 GNUNET_h2s (&ts->destination.details.service_destination.service_descriptor),
1496 (unsigned int) ts->destination_port);
1502 switch (dt->destination->details.exit_destination.af)
1506 char address[GNUNET_TUN_IPV4_REGEXLEN];
1508 GNUNET_TUN_ipv4toregexsearch (&dt->destination->details.exit_destination.ip.v4,
1509 dt->destination_port,
1511 GNUNET_asprintf (&policy,
1513 GNUNET_APPLICATION_TYPE_EXIT_REGEX_PREFIX,
1519 char address[GNUNET_TUN_IPV6_REGEXLEN];
1521 GNUNET_TUN_ipv6toregexsearch (&dt->destination->details.exit_destination.ip.v6,
1522 dt->destination_port,
1524 GNUNET_asprintf (&policy,
1526 GNUNET_APPLICATION_TYPE_EXIT_REGEX_PREFIX,
1535 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1536 "Requesting connect by string: %s\n",
1538 ts->search = GNUNET_REGEX_search (cfg,
1540 &handle_regex_result,
1542 GNUNET_free (policy);
1549 * We have too many active channels. Clean up the oldest channel.
1551 * @param except channel that must NOT be cleaned up, even if it is the oldest
1554 expire_channel (struct ChannelState *except)
1556 struct ChannelState *ts;
1558 ts = GNUNET_CONTAINER_heap_peek (channel_heap);
1559 GNUNET_assert (NULL != ts);
1561 return; /* can't do this */
1562 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1563 "Tearing down expired channel to %s\n",
1564 print_channel_destination (&except->destination));
1565 free_channel_state (ts);
1570 * Route a packet via cadet to the given destination.
1572 * @param destination description of the destination
1573 * @param af address family on this end (AF_INET or AF_INET6)
1574 * @param protocol IPPROTO_TCP or IPPROTO_UDP or IPPROTO_ICMP or IPPROTO_ICMPV6
1575 * @param source_ip source IP used by the sender (struct in_addr or struct in6_addr)
1576 * @param destination_ip destination IP used by the sender (struct in_addr or struct in6_addr)
1577 * @param payload payload of the packet after the IP header
1578 * @param payload_length number of bytes in @a payload
1581 route_packet (struct DestinationEntry *destination,
1584 const void *source_ip,
1585 const void *destination_ip,
1586 const void *payload,
1587 size_t payload_length)
1589 struct GNUNET_HashCode key;
1590 struct ChannelState *ts;
1593 struct GNUNET_MQ_Envelope *env;
1594 const struct GNUNET_TUN_UdpHeader *udp;
1595 const struct GNUNET_TUN_TcpHeader *tcp;
1596 const struct GNUNET_TUN_IcmpHeader *icmp;
1597 struct DestinationChannel *dt;
1598 uint16_t source_port;
1599 uint16_t destination_port;
1605 if (payload_length < sizeof (struct GNUNET_TUN_UdpHeader))
1611 tcp = NULL; /* make compiler happy */
1612 icmp = NULL; /* make compiler happy */
1614 if (udp->len < sizeof (struct GNUNET_TUN_UdpHeader))
1616 GNUNET_break_op (0);
1619 source_port = ntohs (udp->source_port);
1620 destination_port = ntohs (udp->destination_port);
1621 get_channel_key_from_ips (af,
1632 if (payload_length < sizeof (struct GNUNET_TUN_TcpHeader))
1638 udp = NULL; /* make compiler happy */
1639 icmp = NULL; /* make compiler happy */
1641 if (tcp->off * 4 < sizeof (struct GNUNET_TUN_TcpHeader))
1643 GNUNET_break_op (0);
1646 source_port = ntohs (tcp->source_port);
1647 destination_port = ntohs (tcp->destination_port);
1648 get_channel_key_from_ips (af,
1658 case IPPROTO_ICMPV6:
1660 if ( (AF_INET == af) ^ (protocol == IPPROTO_ICMP) )
1665 if (payload_length < sizeof (struct GNUNET_TUN_IcmpHeader))
1671 tcp = NULL; /* make compiler happy */
1672 udp = NULL; /* make compiler happy */
1675 destination_port = 0;
1676 get_channel_key_from_ips (af,
1686 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1687 _("Protocol %u not supported, dropping\n"),
1688 (unsigned int) protocol);
1692 if (! destination->is_service)
1694 switch (destination->details.exit_destination.af)
1697 alen = sizeof (struct in_addr);
1700 alen = sizeof (struct in6_addr);
1707 char sbuf[INET6_ADDRSTRLEN];
1708 char dbuf[INET6_ADDRSTRLEN];
1709 char xbuf[INET6_ADDRSTRLEN];
1711 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1712 "Routing %s packet from [%s]:%u -> [%s]:%u to destination [%s]:%u\n",
1713 (protocol == IPPROTO_TCP) ? "TCP" : "UDP",
1724 inet_ntop (destination->details.exit_destination.af,
1725 &destination->details.exit_destination.ip,
1726 xbuf, sizeof (xbuf)),
1729 for (dt = destination->dt_head; NULL != dt; dt = dt->next)
1730 if (dt->destination_port == destination_port)
1736 char sbuf[INET6_ADDRSTRLEN];
1737 char dbuf[INET6_ADDRSTRLEN];
1739 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1740 "Routing %s packet from [%s]:%u -> [%s]:%u to service %s at peer %s\n",
1741 (protocol == IPPROTO_TCP) ? "TCP" : "UDP",
1752 GNUNET_h2s (&destination->details.service_destination.service_descriptor),
1753 GNUNET_i2s (&destination->details.service_destination.target));
1755 for (dt = destination->dt_head; NULL != dt; dt = dt->next)
1756 if (dt->destination_port == destination_port)
1761 dt = GNUNET_new (struct DestinationChannel);
1762 dt->destination = destination;
1763 GNUNET_CONTAINER_DLL_insert (destination->dt_head,
1764 destination->dt_tail,
1766 dt->destination_port = destination_port;
1769 /* see if we have an existing channel for this destination */
1770 ts = GNUNET_CONTAINER_multihashmap_get (channel_map,
1774 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1775 "Creating new channel for key %s\n",
1777 /* need to either use the existing channel from the destination (if still
1778 available) or create a fresh one */
1779 ts = create_channel_to_destination (dt,
1783 /* now bind existing "unbound" channel to our IP/port tuple */
1784 ts->protocol = protocol;
1788 ts->source_ip.v4 = * (const struct in_addr *) source_ip;
1789 ts->destination_ip.v4 = * (const struct in_addr *) destination_ip;
1793 ts->source_ip.v6 = * (const struct in6_addr *) source_ip;
1794 ts->destination_ip.v6 = * (const struct in6_addr *) destination_ip;
1796 ts->source_port = source_port;
1797 ts->destination_port = destination_port;
1798 ts->heap_node = GNUNET_CONTAINER_heap_insert (channel_heap,
1800 GNUNET_TIME_absolute_get ().abs_value_us);
1801 GNUNET_assert (GNUNET_YES ==
1802 GNUNET_CONTAINER_multihashmap_put (channel_map,
1805 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
1806 GNUNET_STATISTICS_update (stats,
1807 gettext_noop ("# Active channels"),
1809 while (GNUNET_CONTAINER_multihashmap_size (channel_map) > max_channel_mappings)
1810 expire_channel (ts);
1814 GNUNET_CONTAINER_heap_update_cost (ts->heap_node,
1815 GNUNET_TIME_absolute_get ().abs_value_us);
1817 if (NULL == ts->channel)
1819 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1820 "Packet dropped, channel to %s not yet ready (%s)\n",
1821 print_channel_destination (&ts->destination),
1822 (NULL == ts->search)
1823 ? "EXIT search failed"
1824 : "EXIT search active");
1825 GNUNET_STATISTICS_update (stats,
1826 gettext_noop ("# Packets dropped (channel not yet online)"),
1832 /* send via channel */
1836 if (destination->is_service)
1838 struct GNUNET_EXIT_UdpServiceMessage *usm;
1840 mlen = sizeof (struct GNUNET_EXIT_UdpServiceMessage) +
1841 payload_length - sizeof (struct GNUNET_TUN_UdpHeader);
1842 if (mlen >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1847 env = GNUNET_MQ_msg_extra (usm,
1848 payload_length - sizeof (struct GNUNET_TUN_UdpHeader),
1849 GNUNET_MESSAGE_TYPE_VPN_UDP_TO_SERVICE);
1850 /* if the source port is below 32000, we assume it has a special
1851 meaning; if not, we pick a random port (this is a heuristic) */
1852 usm->source_port = (ntohs (udp->source_port) < 32000) ? udp->source_port : 0;
1853 usm->destination_port = udp->destination_port;
1854 GNUNET_memcpy (&usm[1],
1856 payload_length - sizeof (struct GNUNET_TUN_UdpHeader));
1860 struct GNUNET_EXIT_UdpInternetMessage *uim;
1861 struct in_addr *ip4dst;
1862 struct in6_addr *ip6dst;
1865 mlen = sizeof (struct GNUNET_EXIT_UdpInternetMessage) +
1866 alen + payload_length - sizeof (struct GNUNET_TUN_UdpHeader);
1867 if (mlen >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1872 env = GNUNET_MQ_msg_extra (uim,
1873 payload_length + alen - sizeof (struct GNUNET_TUN_UdpHeader),
1874 GNUNET_MESSAGE_TYPE_VPN_UDP_TO_INTERNET);
1875 uim->af = htonl (destination->details.exit_destination.af);
1876 uim->source_port = (ntohs (udp->source_port) < 32000) ? udp->source_port : 0;
1877 uim->destination_port = udp->destination_port;
1878 switch (destination->details.exit_destination.af)
1881 ip4dst = (struct in_addr *) &uim[1];
1882 *ip4dst = destination->details.exit_destination.ip.v4;
1883 payload = &ip4dst[1];
1886 ip6dst = (struct in6_addr *) &uim[1];
1887 *ip6dst = destination->details.exit_destination.ip.v6;
1888 payload = &ip6dst[1];
1893 GNUNET_memcpy (payload,
1895 payload_length - sizeof (struct GNUNET_TUN_UdpHeader));
1899 if (GNUNET_NO == ts->is_established)
1901 if (destination->is_service)
1903 struct GNUNET_EXIT_TcpServiceStartMessage *tsm;
1905 mlen = sizeof (struct GNUNET_EXIT_TcpServiceStartMessage) +
1906 payload_length - sizeof (struct GNUNET_TUN_TcpHeader);
1907 if (mlen >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1912 env = GNUNET_MQ_msg_extra (tsm,
1913 payload_length - sizeof (struct GNUNET_TUN_TcpHeader),
1914 GNUNET_MESSAGE_TYPE_VPN_TCP_TO_SERVICE_START);
1915 tsm->reserved = htonl (0);
1916 tsm->tcp_header = *tcp;
1917 GNUNET_memcpy (&tsm[1],
1919 payload_length - sizeof (struct GNUNET_TUN_TcpHeader));
1923 struct GNUNET_EXIT_TcpInternetStartMessage *tim;
1924 struct in_addr *ip4dst;
1925 struct in6_addr *ip6dst;
1928 mlen = sizeof (struct GNUNET_EXIT_TcpInternetStartMessage) +
1929 alen + payload_length - sizeof (struct GNUNET_TUN_TcpHeader);
1930 if (mlen >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1935 env = GNUNET_MQ_msg_extra (tim,
1936 payload_length + alen - sizeof (struct GNUNET_TUN_TcpHeader),
1937 GNUNET_MESSAGE_TYPE_VPN_TCP_TO_INTERNET_START);
1938 tim->af = htonl (destination->details.exit_destination.af);
1939 tim->tcp_header = *tcp;
1940 switch (destination->details.exit_destination.af)
1943 ip4dst = (struct in_addr *) &tim[1];
1944 *ip4dst = destination->details.exit_destination.ip.v4;
1945 payload = &ip4dst[1];
1948 ip6dst = (struct in6_addr *) &tim[1];
1949 *ip6dst = destination->details.exit_destination.ip.v6;
1950 payload = &ip6dst[1];
1955 GNUNET_memcpy (payload,
1957 payload_length - sizeof (struct GNUNET_TUN_TcpHeader));
1962 struct GNUNET_EXIT_TcpDataMessage *tdm;
1964 mlen = sizeof (struct GNUNET_EXIT_TcpDataMessage) +
1965 payload_length - sizeof (struct GNUNET_TUN_TcpHeader);
1966 if (mlen >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1971 env = GNUNET_MQ_msg_extra (tdm,
1972 payload_length - sizeof (struct GNUNET_TUN_TcpHeader),
1973 GNUNET_MESSAGE_TYPE_VPN_TCP_DATA_TO_EXIT);
1974 tdm->reserved = htonl (0);
1975 tdm->tcp_header = *tcp;
1976 GNUNET_memcpy (&tdm[1],
1978 payload_length - sizeof (struct GNUNET_TUN_TcpHeader));
1982 case IPPROTO_ICMPV6:
1983 if (destination->is_service)
1985 struct GNUNET_EXIT_IcmpServiceMessage *ism;
1987 /* ICMP protocol translation will be done by the receiver (as we don't know
1988 the target AF); however, we still need to possibly discard the payload
1989 depending on the ICMP type */
1995 case GNUNET_TUN_ICMPTYPE_ECHO_REPLY:
1996 case GNUNET_TUN_ICMPTYPE_ECHO_REQUEST:
1998 case GNUNET_TUN_ICMPTYPE_DESTINATION_UNREACHABLE:
1999 case GNUNET_TUN_ICMPTYPE_SOURCE_QUENCH:
2000 case GNUNET_TUN_ICMPTYPE_TIME_EXCEEDED:
2001 /* throw away ICMP payload, won't be useful for the other side anyway */
2002 payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
2005 GNUNET_STATISTICS_update (stats,
2006 gettext_noop ("# ICMPv4 packets dropped (not allowed)"),
2010 /* end of AF_INET */
2015 case GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE:
2016 case GNUNET_TUN_ICMPTYPE6_PACKET_TOO_BIG:
2017 case GNUNET_TUN_ICMPTYPE6_TIME_EXCEEDED:
2018 case GNUNET_TUN_ICMPTYPE6_PARAMETER_PROBLEM:
2019 /* throw away ICMP payload, won't be useful for the other side anyway */
2020 payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
2022 case GNUNET_TUN_ICMPTYPE6_ECHO_REQUEST:
2023 case GNUNET_TUN_ICMPTYPE6_ECHO_REPLY:
2026 GNUNET_STATISTICS_update (stats,
2027 gettext_noop ("# ICMPv6 packets dropped (not allowed)"),
2031 /* end of AF_INET6 */
2038 /* update length calculations, as payload_length may have changed */
2039 mlen = sizeof (struct GNUNET_EXIT_IcmpServiceMessage) +
2040 alen + payload_length - sizeof (struct GNUNET_TUN_IcmpHeader);
2041 if (mlen >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
2047 env = GNUNET_MQ_msg_extra (ism,
2048 payload_length - sizeof (struct GNUNET_TUN_IcmpHeader),
2049 GNUNET_MESSAGE_TYPE_VPN_ICMP_TO_SERVICE);
2050 ism->af = htonl (af); /* need to tell destination ICMP protocol family! */
2051 ism->icmp_header = *icmp;
2052 GNUNET_memcpy (&ism[1],
2054 payload_length - sizeof (struct GNUNET_TUN_IcmpHeader));
2058 struct GNUNET_EXIT_IcmpInternetMessage *iim;
2059 struct in_addr *ip4dst;
2060 struct in6_addr *ip6dst;
2064 /* Perform ICMP protocol-translation (depending on destination AF and source AF)
2065 and throw away ICMP payload depending on ICMP message type */
2071 case GNUNET_TUN_ICMPTYPE_ECHO_REPLY:
2072 if (destination->details.exit_destination.af == AF_INET6)
2073 new_type = GNUNET_TUN_ICMPTYPE6_ECHO_REPLY;
2075 case GNUNET_TUN_ICMPTYPE_ECHO_REQUEST:
2076 if (destination->details.exit_destination.af == AF_INET6)
2077 new_type = GNUNET_TUN_ICMPTYPE6_ECHO_REQUEST;
2079 case GNUNET_TUN_ICMPTYPE_DESTINATION_UNREACHABLE:
2080 if (destination->details.exit_destination.af == AF_INET6)
2081 new_type = GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE;
2082 /* throw away IP-payload, exit will have to make it up anyway */
2083 payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
2085 case GNUNET_TUN_ICMPTYPE_TIME_EXCEEDED:
2086 if (destination->details.exit_destination.af == AF_INET6)
2087 new_type = GNUNET_TUN_ICMPTYPE6_TIME_EXCEEDED;
2088 /* throw away IP-payload, exit will have to make it up anyway */
2089 payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
2091 case GNUNET_TUN_ICMPTYPE_SOURCE_QUENCH:
2092 if (destination->details.exit_destination.af == AF_INET6)
2094 GNUNET_STATISTICS_update (stats,
2095 gettext_noop ("# ICMPv4 packets dropped (impossible PT to v6)"),
2099 /* throw away IP-payload, exit will have to make it up anyway */
2100 payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
2103 GNUNET_STATISTICS_update (stats,
2104 gettext_noop ("# ICMPv4 packets dropped (type not allowed)"),
2108 /* end of AF_INET */
2113 case GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE:
2114 if (destination->details.exit_destination.af == AF_INET6)
2115 new_type = GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE;
2116 /* throw away IP-payload, exit will have to make it up anyway */
2117 payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
2119 case GNUNET_TUN_ICMPTYPE6_TIME_EXCEEDED:
2120 if (destination->details.exit_destination.af == AF_INET)
2121 new_type = GNUNET_TUN_ICMPTYPE_TIME_EXCEEDED;
2122 /* throw away IP-payload, exit will have to make it up anyway */
2123 payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
2125 case GNUNET_TUN_ICMPTYPE6_PACKET_TOO_BIG:
2126 if (destination->details.exit_destination.af == AF_INET)
2128 GNUNET_STATISTICS_update (stats,
2129 gettext_noop ("# ICMPv6 packets dropped (impossible PT to v4)"),
2133 /* throw away IP-payload, exit will have to make it up anyway */
2134 payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
2136 case GNUNET_TUN_ICMPTYPE6_PARAMETER_PROBLEM:
2137 if (destination->details.exit_destination.af == AF_INET)
2139 GNUNET_STATISTICS_update (stats,
2140 gettext_noop ("# ICMPv6 packets dropped (impossible PT to v4)"),
2144 /* throw away IP-payload, exit will have to make it up anyway */
2145 payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
2147 case GNUNET_TUN_ICMPTYPE6_ECHO_REQUEST:
2148 if (destination->details.exit_destination.af == AF_INET)
2149 new_type = GNUNET_TUN_ICMPTYPE_ECHO_REQUEST;
2151 case GNUNET_TUN_ICMPTYPE6_ECHO_REPLY:
2152 if (destination->details.exit_destination.af == AF_INET)
2153 new_type = GNUNET_TUN_ICMPTYPE_ECHO_REPLY;
2156 GNUNET_STATISTICS_update (stats,
2157 gettext_noop ("# ICMPv6 packets dropped (type not allowed)"),
2161 /* end of AF_INET6 */
2167 /* update length calculations, as payload_length may have changed */
2168 mlen = sizeof (struct GNUNET_EXIT_IcmpInternetMessage) +
2169 alen + payload_length - sizeof (struct GNUNET_TUN_IcmpHeader);
2170 if (mlen >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
2175 env = GNUNET_MQ_msg_extra (iim,
2176 alen + payload_length - sizeof (struct GNUNET_TUN_IcmpHeader),
2177 GNUNET_MESSAGE_TYPE_VPN_ICMP_TO_INTERNET);
2178 iim->icmp_header = *icmp;
2179 iim->icmp_header.type = new_type;
2180 iim->af = htonl (destination->details.exit_destination.af);
2181 switch (destination->details.exit_destination.af)
2184 ip4dst = (struct in_addr *) &iim[1];
2185 *ip4dst = destination->details.exit_destination.ip.v4;
2186 payload = &ip4dst[1];
2189 ip6dst = (struct in6_addr *) &iim[1];
2190 *ip6dst = destination->details.exit_destination.ip.v6;
2191 payload = &ip6dst[1];
2196 GNUNET_memcpy (payload,
2198 payload_length - sizeof (struct GNUNET_TUN_IcmpHeader));
2202 /* not supported above, how can we get here !? */
2206 ts->is_established = GNUNET_YES;
2207 send_to_channel (ts,
2213 * Receive packets from the helper-process (someone send to the local
2214 * virtual channel interface). Find the destination mapping, and if it
2215 * exists, identify the correct CADET channel (or possibly create it)
2216 * and forward the packet.
2218 * @param cls closure, NULL
2219 * @param client NULL
2220 * @param message message we got from the client (VPN channel interface)
2223 message_token (void *cls,
2225 const struct GNUNET_MessageHeader *message)
2227 const struct GNUNET_TUN_Layer2PacketHeader *tun;
2229 struct GNUNET_HashCode key;
2230 struct DestinationEntry *de;
2232 GNUNET_STATISTICS_update (stats,
2233 gettext_noop ("# Packets received from TUN interface"),
2235 mlen = ntohs (message->size);
2236 if ( (ntohs (message->type) != GNUNET_MESSAGE_TYPE_VPN_HELPER) ||
2237 (mlen < sizeof (struct GNUNET_MessageHeader) + sizeof (struct GNUNET_TUN_Layer2PacketHeader)) )
2242 tun = (const struct GNUNET_TUN_Layer2PacketHeader *) &message[1];
2243 mlen -= (sizeof (struct GNUNET_MessageHeader) + sizeof (struct GNUNET_TUN_Layer2PacketHeader));
2244 switch (ntohs (tun->proto))
2248 const struct GNUNET_TUN_IPv6Header *pkt6;
2250 if (mlen < sizeof (struct GNUNET_TUN_IPv6Header))
2256 pkt6 = (const struct GNUNET_TUN_IPv6Header *) &tun[1];
2257 get_destination_key_from_ip (AF_INET6,
2258 &pkt6->destination_address,
2260 de = GNUNET_CONTAINER_multihashmap_get (destination_map, &key);
2263 char buf[INET6_ADDRSTRLEN];
2265 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
2266 _("Packet received for unmapped destination `%s' (dropping it)\n"),
2267 inet_ntop (AF_INET6,
2268 &pkt6->destination_address,
2276 &pkt6->source_address,
2277 &pkt6->destination_address,
2279 mlen - sizeof (struct GNUNET_TUN_IPv6Header));
2284 struct GNUNET_TUN_IPv4Header *pkt4;
2286 if (mlen < sizeof (struct GNUNET_TUN_IPv4Header))
2292 pkt4 = (struct GNUNET_TUN_IPv4Header *) &tun[1];
2293 get_destination_key_from_ip (AF_INET,
2294 &pkt4->destination_address,
2296 de = GNUNET_CONTAINER_multihashmap_get (destination_map, &key);
2299 char buf[INET_ADDRSTRLEN];
2301 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
2302 _("Packet received for unmapped destination `%s' (dropping it)\n"),
2304 &pkt4->destination_address,
2309 if (pkt4->header_length * 4 != sizeof (struct GNUNET_TUN_IPv4Header))
2311 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
2312 _("Received IPv4 packet with options (dropping it)\n"));
2318 &pkt4->source_address,
2319 &pkt4->destination_address,
2321 mlen - sizeof (struct GNUNET_TUN_IPv4Header));
2325 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
2326 _("Received packet of unknown protocol %d from TUN (dropping it)\n"),
2327 (unsigned int) ntohs (tun->proto));
2335 * Allocate an IPv4 address from the range of the channel
2336 * for a new redirection.
2338 * @param v4 where to store the address
2339 * @return #GNUNET_OK on success,
2340 * #GNUNET_SYSERR on error
2343 allocate_v4_address (struct in_addr *v4)
2345 const char *ipv4addr = vpn_argv[4];
2346 const char *ipv4mask = vpn_argv[5];
2347 struct in_addr addr;
2348 struct in_addr mask;
2350 struct GNUNET_HashCode key;
2353 GNUNET_assert (1 == inet_pton (AF_INET, ipv4addr, &addr));
2354 GNUNET_assert (1 == inet_pton (AF_INET, ipv4mask, &mask));
2355 /* Given 192.168.0.1/255.255.0.0, we want a mask
2356 of '192.168.255.255', thus: */
2357 mask.s_addr = addr.s_addr | ~mask.s_addr;
2364 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
2365 _("Failed to find unallocated IPv4 address in VPN's range\n"));
2366 return GNUNET_SYSERR;
2368 /* Pick random IPv4 address within the subnet, except 'addr' or 'mask' itself */
2369 rnd.s_addr = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
2371 v4->s_addr = (addr.s_addr | rnd.s_addr) & mask.s_addr;
2372 get_destination_key_from_ip (AF_INET,
2376 while ( (GNUNET_YES ==
2377 GNUNET_CONTAINER_multihashmap_contains (destination_map,
2379 (v4->s_addr == addr.s_addr) ||
2380 (v4->s_addr == mask.s_addr) );
2386 * Allocate an IPv6 address from the range of the channel
2387 * for a new redirection.
2389 * @param v6 where to store the address
2390 * @return #GNUNET_OK on success,
2391 * #GNUNET_SYSERR on error
2394 allocate_v6_address (struct in6_addr *v6)
2396 const char *ipv6addr = vpn_argv[2];
2397 struct in6_addr addr;
2398 struct in6_addr mask;
2399 struct in6_addr rnd;
2401 struct GNUNET_HashCode key;
2404 GNUNET_assert (1 == inet_pton (AF_INET6, ipv6addr, &addr));
2405 GNUNET_assert (ipv6prefix < 128);
2406 /* Given ABCD::/96, we want a mask of 'ABCD::FFFF:FFFF,
2409 for (i=127;i>=ipv6prefix;i--)
2410 mask.s6_addr[i / 8] |= (1 << (i % 8));
2412 /* Pick random IPv6 address within the subnet, except 'addr' or 'mask' itself */
2419 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
2420 _("Failed to find unallocated IPv6 address in VPN's range\n"));
2421 return GNUNET_SYSERR;
2426 rnd.s6_addr[i] = (unsigned char) GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
2429 = (addr.s6_addr[i] | rnd.s6_addr[i]) & mask.s6_addr[i];
2431 get_destination_key_from_ip (AF_INET6,
2435 while ( (GNUNET_YES ==
2436 GNUNET_CONTAINER_multihashmap_contains (destination_map,
2440 sizeof (struct in6_addr))) ||
2443 sizeof (struct in6_addr))) );
2449 * Free resources occupied by a destination entry.
2451 * @param de entry to free
2454 free_destination_entry (struct DestinationEntry *de)
2456 struct DestinationChannel *dt;
2458 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2459 "Cleaning up destination entry `%s'\n",
2460 print_channel_destination (de));
2461 GNUNET_STATISTICS_update (stats,
2462 gettext_noop ("# Active destinations"),
2464 while (NULL != (dt = de->dt_head))
2466 GNUNET_CONTAINER_DLL_remove (de->dt_head,
2471 if (NULL != de->heap_node)
2473 GNUNET_CONTAINER_heap_remove_node (de->heap_node);
2474 de->heap_node = NULL;
2475 GNUNET_assert (GNUNET_YES ==
2476 GNUNET_CONTAINER_multihashmap_remove (destination_map,
2485 * We have too many active destinations. Clean up the oldest destination.
2487 * @param except destination that must NOT be cleaned up, even if it is the oldest
2490 expire_destination (struct DestinationEntry *except)
2492 struct DestinationEntry *de;
2494 de = GNUNET_CONTAINER_heap_peek (destination_heap);
2495 GNUNET_assert (NULL != de);
2497 return; /* can't do this */
2498 free_destination_entry (de);
2503 * Allocate an IP address for the response.
2505 * @param result_af desired address family; set to the actual
2506 * address family; can initially be AF_UNSPEC if there
2507 * is no preference; will be set to AF_UNSPEC if the
2509 * @param addr set to either v4 or v6 depending on which
2510 * storage location was used; set to NULL if allocation failed
2511 * @param v4 storage space for an IPv4 address
2512 * @param v6 storage space for an IPv6 address
2513 * @return #GNUNET_OK normally, #GNUNET_SYSERR if `* result_af` was
2514 * an unsupported address family (not AF_INET, AF_INET6 or AF_UNSPEC)
2517 allocate_response_ip (int *result_af,
2520 struct in6_addr *v6)
2527 allocate_v4_address (v4))
2528 *result_af = AF_UNSPEC;
2534 allocate_v6_address (v6))
2535 *result_af = AF_UNSPEC;
2541 allocate_v4_address (v4))
2544 *result_af = AF_INET;
2546 else if (GNUNET_OK ==
2547 allocate_v6_address (v6))
2550 *result_af = AF_INET6;
2555 return GNUNET_SYSERR;
2562 * A client asks us to setup a redirection via some exit node to a
2563 * particular IP. Check if @a msg is well-formed.
2566 * @param cls client requesting client
2567 * @param msg redirection request
2568 * @return #GNUNET_OK if @a msg is well-formed
2571 check_client_redirect_to_ip (void *cls,
2572 const struct RedirectToIpRequestMessage *msg)
2577 alen = ntohs (msg->header.size) - sizeof (struct RedirectToIpRequestMessage);
2578 addr_af = (int) htonl (msg->addr_af);
2582 if (alen != sizeof (struct in_addr))
2585 return GNUNET_SYSERR;
2589 if (alen != sizeof (struct in6_addr))
2592 return GNUNET_SYSERR;
2597 return GNUNET_SYSERR;
2604 * A client asks us to setup a redirection via some exit node to a
2605 * particular IP. Setup the redirection and give the client the
2608 * @param cls client requesting client
2609 * @param msg redirection request
2612 handle_client_redirect_to_ip (void *cls,
2613 const struct RedirectToIpRequestMessage *msg)
2615 struct GNUNET_SERVICE_Client *client = cls;
2622 struct DestinationEntry *de;
2623 struct GNUNET_HashCode key;
2625 alen = ntohs (msg->header.size) - sizeof (struct RedirectToIpRequestMessage);
2626 addr_af = (int) htonl (msg->addr_af);
2627 /* allocate response IP */
2628 result_af = (int) htonl (msg->result_af);
2629 if (GNUNET_OK != allocate_response_ip (&result_af,
2633 GNUNET_SERVICE_client_drop (client);
2636 /* send reply with our IP address */
2637 send_client_reply (client,
2641 if (result_af == AF_UNSPEC)
2643 /* failure, we're done */
2644 GNUNET_SERVICE_client_continue (client);
2649 char sbuf[INET6_ADDRSTRLEN];
2650 char dbuf[INET6_ADDRSTRLEN];
2652 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2653 "Allocated address %s for redirection via exit to %s\n",
2654 inet_ntop (result_af,
2664 /* setup destination record */
2665 de = GNUNET_new (struct DestinationEntry);
2666 de->is_service = GNUNET_NO;
2667 de->details.exit_destination.af = addr_af;
2668 GNUNET_memcpy (&de->details.exit_destination.ip,
2671 get_destination_key_from_ip (result_af,
2675 GNUNET_assert (GNUNET_OK ==
2676 GNUNET_CONTAINER_multihashmap_put (destination_map,
2679 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE));
2680 de->heap_node = GNUNET_CONTAINER_heap_insert (destination_heap,
2682 GNUNET_TIME_absolute_ntoh (msg->expiration_time).abs_value_us);
2683 GNUNET_STATISTICS_update (stats,
2684 gettext_noop ("# Active destinations"),
2686 while (GNUNET_CONTAINER_multihashmap_size (destination_map) > max_destination_mappings)
2687 expire_destination (de);
2688 GNUNET_SERVICE_client_continue (client);
2693 * A client asks us to setup a redirection to a particular peer
2694 * offering a service. Setup the redirection and give the client the
2697 * @param cls requesting client
2698 * @param msg redirection request
2701 handle_client_redirect_to_service (void *cls,
2702 const struct RedirectToServiceRequestMessage *msg)
2704 struct GNUNET_SERVICE_Client *client = cls;
2709 struct DestinationEntry *de;
2710 struct GNUNET_HashCode key;
2711 struct DestinationChannel *dt;
2713 /* allocate response IP */
2714 result_af = (int) htonl (msg->result_af);
2716 allocate_response_ip (&result_af,
2722 GNUNET_SERVICE_client_drop (client);
2725 send_client_reply (client,
2729 if (result_af == AF_UNSPEC)
2731 /* failure, we're done */
2732 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2733 _("Failed to allocate IP address for new destination\n"));
2734 GNUNET_SERVICE_client_continue (client);
2739 char sbuf[INET6_ADDRSTRLEN];
2741 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2742 "Allocated address %s for redirection to service %s on peer %s\n",
2743 inet_ntop (result_af,
2747 GNUNET_h2s (&msg->service_descriptor),
2748 GNUNET_i2s (&msg->target));
2751 /* setup destination record */
2752 de = GNUNET_new (struct DestinationEntry);
2753 de->is_service = GNUNET_YES;
2754 de->details.service_destination.target = msg->target;
2755 de->details.service_destination.service_descriptor = msg->service_descriptor;
2756 get_destination_key_from_ip (result_af,
2760 GNUNET_assert (GNUNET_OK ==
2761 GNUNET_CONTAINER_multihashmap_put (destination_map,
2764 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE));
2766 = GNUNET_CONTAINER_heap_insert (destination_heap,
2768 GNUNET_TIME_absolute_ntoh (msg->expiration_time).abs_value_us);
2769 while (GNUNET_CONTAINER_multihashmap_size (destination_map) > max_destination_mappings)
2770 expire_destination (de);
2772 dt = GNUNET_new (struct DestinationChannel);
2773 dt->destination = de;
2774 GNUNET_CONTAINER_DLL_insert (de->dt_head,
2778 GNUNET_SERVICE_client_continue (client);
2784 * Free memory occupied by an entry in the destination map.
2788 * @param value a `struct DestinationEntry *`
2789 * @return #GNUNET_OK (continue to iterate)
2792 cleanup_destination (void *cls,
2793 const struct GNUNET_HashCode *key,
2796 struct DestinationEntry *de = value;
2798 free_destination_entry (de);
2804 * Free memory occupied by an entry in the channel map.
2808 * @param value a `struct ChannelState *`
2809 * @return #GNUNET_OK (continue to iterate)
2812 cleanup_channel (void *cls,
2813 const struct GNUNET_HashCode *key,
2816 struct ChannelState *ts = value;
2818 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2819 "Tearing down channel to `%s' during cleanup\n",
2820 print_channel_destination (&ts->destination));
2821 free_channel_state (ts);
2827 * Function scheduled as very last function, cleans up after us
2836 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2837 "VPN is shutting down\n");
2838 if (NULL != destination_map)
2840 GNUNET_CONTAINER_multihashmap_iterate (destination_map,
2841 &cleanup_destination,
2843 GNUNET_CONTAINER_multihashmap_destroy (destination_map);
2844 destination_map = NULL;
2846 if (NULL != destination_heap)
2848 GNUNET_CONTAINER_heap_destroy (destination_heap);
2849 destination_heap = NULL;
2851 if (NULL != channel_map)
2853 GNUNET_CONTAINER_multihashmap_iterate (channel_map,
2856 GNUNET_CONTAINER_multihashmap_destroy (channel_map);
2859 if (NULL != channel_heap)
2861 GNUNET_CONTAINER_heap_destroy (channel_heap);
2862 channel_heap = NULL;
2864 if (NULL != cadet_handle)
2866 GNUNET_CADET_disconnect (cadet_handle);
2867 cadet_handle = NULL;
2869 if (NULL != helper_handle)
2871 GNUNET_HELPER_kill (helper_handle, GNUNET_NO);
2872 GNUNET_HELPER_wait (helper_handle);
2873 helper_handle = NULL;
2877 GNUNET_STATISTICS_destroy (stats, GNUNET_NO);
2881 GNUNET_free_non_null (vpn_argv[i]);
2886 * Callback called when a client connects to the service.
2888 * @param cls closure for the service
2889 * @param c the new client that connected to the service
2890 * @param mq the message queue used to send messages to the client
2894 client_connect_cb (void *cls,
2895 struct GNUNET_SERVICE_Client *c,
2896 struct GNUNET_MQ_Handle *mq)
2903 * Callback called when a client disconnected from the service
2905 * @param cls closure for the service
2906 * @param c the client that disconnected
2907 * @param internal_cls should be equal to @a c
2910 client_disconnect_cb (void *cls,
2911 struct GNUNET_SERVICE_Client *c,
2914 GNUNET_assert (c == internal_cls);
2919 * Main function that will be run by the scheduler.
2921 * @param cls closure
2922 * @param cfg_ configuration
2923 * @param service the initialized service
2927 const struct GNUNET_CONFIGURATION_Handle *cfg_,
2928 struct GNUNET_SERVICE_Handle *service)
2939 binary = GNUNET_OS_get_libexec_binary_path ("gnunet-helper-vpn");
2942 GNUNET_OS_check_helper_binary (binary,
2944 "-d gnunet-vpn - - 169.1.3.3.7 255.255.255.0")) //ipv4 only please!
2946 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2947 "`%s' is not SUID, refusing to run.\n",
2948 "gnunet-helper-vpn");
2949 GNUNET_free (binary);
2951 /* we won't "really" exit here, as the 'service' is still running;
2952 however, as no handlers are registered, the service won't do
2956 GNUNET_free (binary);
2958 stats = GNUNET_STATISTICS_create ("vpn", cfg);
2960 GNUNET_CONFIGURATION_get_value_number (cfg,
2963 &max_destination_mappings))
2964 max_destination_mappings = 200;
2966 GNUNET_CONFIGURATION_get_value_number (cfg,
2969 &max_channel_mappings))
2970 max_channel_mappings = 200;
2972 destination_map = GNUNET_CONTAINER_multihashmap_create (max_destination_mappings * 2, GNUNET_NO);
2973 destination_heap = GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN);
2974 channel_map = GNUNET_CONTAINER_multihashmap_create (max_channel_mappings * 2, GNUNET_NO);
2975 channel_heap = GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN);
2978 vpn_argv[0] = GNUNET_strdup ("vpn-gnunet");
2979 if (GNUNET_SYSERR ==
2980 GNUNET_CONFIGURATION_get_value_string (cfg, "VPN", "IFNAME", &ifname))
2982 GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, "VPN", "IFNAME");
2983 GNUNET_SCHEDULER_shutdown ();
2986 vpn_argv[1] = ifname;
2988 if (GNUNET_OK == GNUNET_NETWORK_test_pf (PF_INET6))
2990 if ( (GNUNET_SYSERR ==
2991 GNUNET_CONFIGURATION_get_value_string (cfg, "VPN", "IPV6ADDR",
2993 (1 != inet_pton (AF_INET6, ipv6addr, &v6))) )
2995 GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, "VPN", "IPV6ADDR",
2996 _("Must specify valid IPv6 address"));
2997 GNUNET_SCHEDULER_shutdown ();
2998 GNUNET_free_non_null (ipv6addr);
3001 vpn_argv[2] = ipv6addr;
3002 ipv6prefix_s = NULL;
3003 if (GNUNET_SYSERR ==
3004 GNUNET_CONFIGURATION_get_value_string (cfg, "VPN", "IPV6PREFIX",
3007 GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, "VPN", "IPV6PREFIX");
3008 GNUNET_SCHEDULER_shutdown ();
3009 GNUNET_free_non_null (ipv6prefix_s);
3012 vpn_argv[3] = ipv6prefix_s;
3014 GNUNET_CONFIGURATION_get_value_number (cfg, "VPN",
3017 (ipv6prefix >= 127) )
3019 GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, "VPN", "IPV4MASK",
3020 _("Must specify valid IPv6 mask"));
3021 GNUNET_SCHEDULER_shutdown ();
3027 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
3028 _("IPv6 support disabled as this system does not support IPv6\n"));
3029 vpn_argv[2] = GNUNET_strdup ("-");
3030 vpn_argv[3] = GNUNET_strdup ("-");
3032 if (GNUNET_OK == GNUNET_NETWORK_test_pf (PF_INET))
3035 if ( (GNUNET_SYSERR ==
3036 GNUNET_CONFIGURATION_get_value_string (cfg, "vpn", "IPV4ADDR",
3038 (1 != inet_pton (AF_INET, ipv4addr, &v4))) )
3040 GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, "VPN", "IPV4ADDR",
3041 _("Must specify valid IPv4 address"));
3042 GNUNET_SCHEDULER_shutdown ();
3043 GNUNET_free_non_null (ipv4addr);
3046 vpn_argv[4] = ipv4addr;
3048 if ( (GNUNET_SYSERR ==
3049 GNUNET_CONFIGURATION_get_value_string (cfg, "vpn", "IPV4MASK",
3051 (1 != inet_pton (AF_INET, ipv4mask, &v4))) )
3053 GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, "VPN", "IPV4MASK",
3054 _("Must specify valid IPv4 mask"));
3055 GNUNET_SCHEDULER_shutdown ();
3056 GNUNET_free_non_null (ipv4mask);
3059 vpn_argv[5] = ipv4mask;
3063 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
3064 _("IPv4 support disabled as this system does not support IPv4\n"));
3065 vpn_argv[4] = GNUNET_strdup ("-");
3066 vpn_argv[5] = GNUNET_strdup ("-");
3070 cadet_handle = GNUNET_CADET_connecT (cfg_);
3071 // FIXME never opens ports???
3072 helper_handle = GNUNET_HELPER_start (GNUNET_NO,
3073 "gnunet-helper-vpn", vpn_argv,
3074 &message_token, NULL, NULL);
3075 GNUNET_SCHEDULER_add_shutdown (&cleanup,
3081 * Define "main" method using service macro.
3085 GNUNET_SERVICE_OPTION_NONE,
3088 &client_disconnect_cb,
3090 GNUNET_MQ_hd_var_size (client_redirect_to_ip,
3091 GNUNET_MESSAGE_TYPE_VPN_CLIENT_REDIRECT_TO_IP,
3092 struct RedirectToIpRequestMessage,
3094 GNUNET_MQ_hd_fixed_size (client_redirect_to_service,
3095 GNUNET_MESSAGE_TYPE_VPN_CLIENT_REDIRECT_TO_SERVICE,
3096 struct RedirectToServiceRequestMessage,
3098 GNUNET_MQ_handler_end ());
3101 /* end of gnunet-service-vpn.c */