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_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_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_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_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_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_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 new_type = icmp->type;
2065 /* Perform ICMP protocol-translation (depending on destination AF and source AF)
2066 and throw away ICMP payload depending on ICMP message type */
2072 case GNUNET_TUN_ICMPTYPE_ECHO_REPLY:
2073 if (destination->details.exit_destination.af == AF_INET6)
2074 new_type = GNUNET_TUN_ICMPTYPE6_ECHO_REPLY;
2076 case GNUNET_TUN_ICMPTYPE_ECHO_REQUEST:
2077 if (destination->details.exit_destination.af == AF_INET6)
2078 new_type = GNUNET_TUN_ICMPTYPE6_ECHO_REQUEST;
2080 case GNUNET_TUN_ICMPTYPE_DESTINATION_UNREACHABLE:
2081 if (destination->details.exit_destination.af == AF_INET6)
2082 new_type = GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE;
2083 /* throw away IP-payload, exit will have to make it up anyway */
2084 payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
2086 case GNUNET_TUN_ICMPTYPE_TIME_EXCEEDED:
2087 if (destination->details.exit_destination.af == AF_INET6)
2088 new_type = GNUNET_TUN_ICMPTYPE6_TIME_EXCEEDED;
2089 /* throw away IP-payload, exit will have to make it up anyway */
2090 payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
2092 case GNUNET_TUN_ICMPTYPE_SOURCE_QUENCH:
2093 if (destination->details.exit_destination.af == AF_INET6)
2095 GNUNET_STATISTICS_update (stats,
2096 gettext_noop ("# ICMPv4 packets dropped (impossible PT to v6)"),
2100 /* throw away IP-payload, exit will have to make it up anyway */
2101 payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
2104 GNUNET_STATISTICS_update (stats,
2105 gettext_noop ("# ICMPv4 packets dropped (type not allowed)"),
2109 /* end of AF_INET */
2114 case GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE:
2115 if (destination->details.exit_destination.af == AF_INET)
2116 new_type = GNUNET_TUN_ICMPTYPE_DESTINATION_UNREACHABLE;
2117 /* throw away IP-payload, exit will have to make it up anyway */
2118 payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
2120 case GNUNET_TUN_ICMPTYPE6_TIME_EXCEEDED:
2121 if (destination->details.exit_destination.af == AF_INET)
2122 new_type = GNUNET_TUN_ICMPTYPE_TIME_EXCEEDED;
2123 /* throw away IP-payload, exit will have to make it up anyway */
2124 payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
2126 case GNUNET_TUN_ICMPTYPE6_PACKET_TOO_BIG:
2127 if (destination->details.exit_destination.af == AF_INET)
2129 GNUNET_STATISTICS_update (stats,
2130 gettext_noop ("# ICMPv6 packets dropped (impossible PT to v4)"),
2134 /* throw away IP-payload, exit will have to make it up anyway */
2135 payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
2137 case GNUNET_TUN_ICMPTYPE6_PARAMETER_PROBLEM:
2138 if (destination->details.exit_destination.af == AF_INET)
2140 GNUNET_STATISTICS_update (stats,
2141 gettext_noop ("# ICMPv6 packets dropped (impossible PT to v4)"),
2145 /* throw away IP-payload, exit will have to make it up anyway */
2146 payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
2148 case GNUNET_TUN_ICMPTYPE6_ECHO_REQUEST:
2149 if (destination->details.exit_destination.af == AF_INET)
2150 new_type = GNUNET_TUN_ICMPTYPE_ECHO_REQUEST;
2152 case GNUNET_TUN_ICMPTYPE6_ECHO_REPLY:
2153 if (destination->details.exit_destination.af == AF_INET)
2154 new_type = GNUNET_TUN_ICMPTYPE_ECHO_REPLY;
2157 GNUNET_STATISTICS_update (stats,
2158 gettext_noop ("# ICMPv6 packets dropped (type not allowed)"),
2162 /* end of AF_INET6 */
2168 /* update length calculations, as payload_length may have changed */
2169 mlen = sizeof (struct GNUNET_EXIT_IcmpInternetMessage) +
2170 alen + payload_length - sizeof (struct GNUNET_TUN_IcmpHeader);
2171 if (mlen >= GNUNET_MAX_MESSAGE_SIZE)
2176 env = GNUNET_MQ_msg_extra (iim,
2177 alen + payload_length - sizeof (struct GNUNET_TUN_IcmpHeader),
2178 GNUNET_MESSAGE_TYPE_VPN_ICMP_TO_INTERNET);
2179 iim->icmp_header = *icmp;
2180 iim->icmp_header.type = new_type;
2181 iim->af = htonl (destination->details.exit_destination.af);
2182 switch (destination->details.exit_destination.af)
2185 ip4dst = (struct in_addr *) &iim[1];
2186 *ip4dst = destination->details.exit_destination.ip.v4;
2187 payload = &ip4dst[1];
2190 ip6dst = (struct in6_addr *) &iim[1];
2191 *ip6dst = destination->details.exit_destination.ip.v6;
2192 payload = &ip6dst[1];
2197 GNUNET_memcpy (payload,
2199 payload_length - sizeof (struct GNUNET_TUN_IcmpHeader));
2203 /* not supported above, how can we get here !? */
2207 ts->is_established = GNUNET_YES;
2208 send_to_channel (ts,
2214 * Receive packets from the helper-process (someone send to the local
2215 * virtual channel interface). Find the destination mapping, and if it
2216 * exists, identify the correct CADET channel (or possibly create it)
2217 * and forward the packet.
2219 * @param cls closure, NULL
2220 * @param message message we got from the client (VPN channel interface)
2223 message_token (void *cls,
2224 const struct GNUNET_MessageHeader *message)
2226 const struct GNUNET_TUN_Layer2PacketHeader *tun;
2228 struct GNUNET_HashCode key;
2229 struct DestinationEntry *de;
2231 GNUNET_STATISTICS_update (stats,
2232 gettext_noop ("# Packets received from TUN interface"),
2234 mlen = ntohs (message->size);
2235 if ( (ntohs (message->type) != GNUNET_MESSAGE_TYPE_VPN_HELPER) ||
2236 (mlen < sizeof (struct GNUNET_MessageHeader) + sizeof (struct GNUNET_TUN_Layer2PacketHeader)) )
2241 tun = (const struct GNUNET_TUN_Layer2PacketHeader *) &message[1];
2242 mlen -= (sizeof (struct GNUNET_MessageHeader) + sizeof (struct GNUNET_TUN_Layer2PacketHeader));
2243 switch (ntohs (tun->proto))
2247 const struct GNUNET_TUN_IPv6Header *pkt6;
2249 if (mlen < sizeof (struct GNUNET_TUN_IPv6Header))
2255 pkt6 = (const struct GNUNET_TUN_IPv6Header *) &tun[1];
2256 get_destination_key_from_ip (AF_INET6,
2257 &pkt6->destination_address,
2259 de = GNUNET_CONTAINER_multihashmap_get (destination_map, &key);
2262 char buf[INET6_ADDRSTRLEN];
2264 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
2265 _("Packet received for unmapped destination `%s' (dropping it)\n"),
2266 inet_ntop (AF_INET6,
2267 &pkt6->destination_address,
2275 &pkt6->source_address,
2276 &pkt6->destination_address,
2278 mlen - sizeof (struct GNUNET_TUN_IPv6Header));
2283 struct GNUNET_TUN_IPv4Header *pkt4;
2285 if (mlen < sizeof (struct GNUNET_TUN_IPv4Header))
2291 pkt4 = (struct GNUNET_TUN_IPv4Header *) &tun[1];
2292 get_destination_key_from_ip (AF_INET,
2293 &pkt4->destination_address,
2295 de = GNUNET_CONTAINER_multihashmap_get (destination_map, &key);
2298 char buf[INET_ADDRSTRLEN];
2300 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
2301 _("Packet received for unmapped destination `%s' (dropping it)\n"),
2303 &pkt4->destination_address,
2308 if (pkt4->header_length * 4 != sizeof (struct GNUNET_TUN_IPv4Header))
2310 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
2311 _("Received IPv4 packet with options (dropping it)\n"));
2317 &pkt4->source_address,
2318 &pkt4->destination_address,
2320 mlen - sizeof (struct GNUNET_TUN_IPv4Header));
2324 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
2325 _("Received packet of unknown protocol %d from TUN (dropping it)\n"),
2326 (unsigned int) ntohs (tun->proto));
2334 * Allocate an IPv4 address from the range of the channel
2335 * for a new redirection.
2337 * @param v4 where to store the address
2338 * @return #GNUNET_OK on success,
2339 * #GNUNET_SYSERR on error
2342 allocate_v4_address (struct in_addr *v4)
2344 const char *ipv4addr = vpn_argv[4];
2345 const char *ipv4mask = vpn_argv[5];
2346 struct in_addr addr;
2347 struct in_addr mask;
2349 struct GNUNET_HashCode key;
2352 GNUNET_assert (1 == inet_pton (AF_INET, ipv4addr, &addr));
2353 GNUNET_assert (1 == inet_pton (AF_INET, ipv4mask, &mask));
2354 /* Given 192.168.0.1/255.255.0.0, we want a mask
2355 of '192.168.255.255', thus: */
2356 mask.s_addr = addr.s_addr | ~mask.s_addr;
2363 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
2364 _("Failed to find unallocated IPv4 address in VPN's range\n"));
2365 return GNUNET_SYSERR;
2367 /* Pick random IPv4 address within the subnet, except 'addr' or 'mask' itself */
2368 rnd.s_addr = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
2370 v4->s_addr = (addr.s_addr | rnd.s_addr) & mask.s_addr;
2371 get_destination_key_from_ip (AF_INET,
2375 while ( (GNUNET_YES ==
2376 GNUNET_CONTAINER_multihashmap_contains (destination_map,
2378 (v4->s_addr == addr.s_addr) ||
2379 (v4->s_addr == mask.s_addr) );
2385 * Allocate an IPv6 address from the range of the channel
2386 * for a new redirection.
2388 * @param v6 where to store the address
2389 * @return #GNUNET_OK on success,
2390 * #GNUNET_SYSERR on error
2393 allocate_v6_address (struct in6_addr *v6)
2395 const char *ipv6addr = vpn_argv[2];
2396 struct in6_addr addr;
2397 struct in6_addr mask;
2398 struct in6_addr rnd;
2400 struct GNUNET_HashCode key;
2403 GNUNET_assert (1 == inet_pton (AF_INET6, ipv6addr, &addr));
2404 GNUNET_assert (ipv6prefix < 128);
2405 /* Given ABCD::/96, we want a mask of 'ABCD::FFFF:FFFF,
2408 for (i=127;i>=ipv6prefix;i--)
2409 mask.s6_addr[i / 8] |= (1 << (i % 8));
2411 /* Pick random IPv6 address within the subnet, except 'addr' or 'mask' itself */
2418 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
2419 _("Failed to find unallocated IPv6 address in VPN's range\n"));
2420 return GNUNET_SYSERR;
2425 rnd.s6_addr[i] = (unsigned char) GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
2428 = (addr.s6_addr[i] | rnd.s6_addr[i]) & mask.s6_addr[i];
2430 get_destination_key_from_ip (AF_INET6,
2434 while ( (GNUNET_YES ==
2435 GNUNET_CONTAINER_multihashmap_contains (destination_map,
2439 sizeof (struct in6_addr))) ||
2442 sizeof (struct in6_addr))) );
2448 * Free resources occupied by a destination entry.
2450 * @param de entry to free
2453 free_destination_entry (struct DestinationEntry *de)
2455 struct DestinationChannel *dt;
2457 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2458 "Cleaning up destination entry `%s'\n",
2459 print_channel_destination (de));
2460 GNUNET_STATISTICS_update (stats,
2461 gettext_noop ("# Active destinations"),
2463 while (NULL != (dt = de->dt_head))
2465 GNUNET_CONTAINER_DLL_remove (de->dt_head,
2470 if (NULL != de->heap_node)
2472 GNUNET_CONTAINER_heap_remove_node (de->heap_node);
2473 de->heap_node = NULL;
2474 GNUNET_assert (GNUNET_YES ==
2475 GNUNET_CONTAINER_multihashmap_remove (destination_map,
2484 * We have too many active destinations. Clean up the oldest destination.
2486 * @param except destination that must NOT be cleaned up, even if it is the oldest
2489 expire_destination (struct DestinationEntry *except)
2491 struct DestinationEntry *de;
2493 de = GNUNET_CONTAINER_heap_peek (destination_heap);
2494 GNUNET_assert (NULL != de);
2496 return; /* can't do this */
2497 free_destination_entry (de);
2502 * Allocate an IP address for the response.
2504 * @param result_af desired address family; set to the actual
2505 * address family; can initially be AF_UNSPEC if there
2506 * is no preference; will be set to AF_UNSPEC if the
2508 * @param addr set to either v4 or v6 depending on which
2509 * storage location was used; set to NULL if allocation failed
2510 * @param v4 storage space for an IPv4 address
2511 * @param v6 storage space for an IPv6 address
2512 * @return #GNUNET_OK normally, #GNUNET_SYSERR if `* result_af` was
2513 * an unsupported address family (not AF_INET, AF_INET6 or AF_UNSPEC)
2516 allocate_response_ip (int *result_af,
2519 struct in6_addr *v6)
2526 allocate_v4_address (v4))
2527 *result_af = AF_UNSPEC;
2533 allocate_v6_address (v6))
2534 *result_af = AF_UNSPEC;
2540 allocate_v4_address (v4))
2543 *result_af = AF_INET;
2545 else if (GNUNET_OK ==
2546 allocate_v6_address (v6))
2549 *result_af = AF_INET6;
2554 return GNUNET_SYSERR;
2561 * A client asks us to setup a redirection via some exit node to a
2562 * particular IP. Check if @a msg is well-formed.
2565 * @param cls client requesting client
2566 * @param msg redirection request
2567 * @return #GNUNET_OK if @a msg is well-formed
2570 check_client_redirect_to_ip (void *cls,
2571 const struct RedirectToIpRequestMessage *msg)
2576 alen = ntohs (msg->header.size) - sizeof (struct RedirectToIpRequestMessage);
2577 addr_af = (int) htonl (msg->addr_af);
2581 if (alen != sizeof (struct in_addr))
2584 return GNUNET_SYSERR;
2588 if (alen != sizeof (struct in6_addr))
2591 return GNUNET_SYSERR;
2596 return GNUNET_SYSERR;
2603 * A client asks us to setup a redirection via some exit node to a
2604 * particular IP. Setup the redirection and give the client the
2607 * @param cls client requesting client
2608 * @param msg redirection request
2611 handle_client_redirect_to_ip (void *cls,
2612 const struct RedirectToIpRequestMessage *msg)
2614 struct GNUNET_SERVICE_Client *client = cls;
2621 struct DestinationEntry *de;
2622 struct GNUNET_HashCode key;
2624 alen = ntohs (msg->header.size) - sizeof (struct RedirectToIpRequestMessage);
2625 addr_af = (int) htonl (msg->addr_af);
2626 /* allocate response IP */
2627 result_af = (int) htonl (msg->result_af);
2628 if (GNUNET_OK != allocate_response_ip (&result_af,
2632 GNUNET_SERVICE_client_drop (client);
2635 /* send reply with our IP address */
2636 send_client_reply (client,
2640 if (result_af == AF_UNSPEC)
2642 /* failure, we're done */
2643 GNUNET_SERVICE_client_continue (client);
2648 char sbuf[INET6_ADDRSTRLEN];
2649 char dbuf[INET6_ADDRSTRLEN];
2651 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2652 "Allocated address %s for redirection via exit to %s\n",
2653 inet_ntop (result_af,
2663 /* setup destination record */
2664 de = GNUNET_new (struct DestinationEntry);
2665 de->is_service = GNUNET_NO;
2666 de->details.exit_destination.af = addr_af;
2667 GNUNET_memcpy (&de->details.exit_destination.ip,
2670 get_destination_key_from_ip (result_af,
2674 GNUNET_assert (GNUNET_OK ==
2675 GNUNET_CONTAINER_multihashmap_put (destination_map,
2678 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE));
2679 de->heap_node = GNUNET_CONTAINER_heap_insert (destination_heap,
2681 GNUNET_TIME_absolute_ntoh (msg->expiration_time).abs_value_us);
2682 GNUNET_STATISTICS_update (stats,
2683 gettext_noop ("# Active destinations"),
2685 while (GNUNET_CONTAINER_multihashmap_size (destination_map) > max_destination_mappings)
2686 expire_destination (de);
2687 GNUNET_SERVICE_client_continue (client);
2692 * A client asks us to setup a redirection to a particular peer
2693 * offering a service. Setup the redirection and give the client the
2696 * @param cls requesting client
2697 * @param msg redirection request
2700 handle_client_redirect_to_service (void *cls,
2701 const struct RedirectToServiceRequestMessage *msg)
2703 struct GNUNET_SERVICE_Client *client = cls;
2708 struct DestinationEntry *de;
2709 struct GNUNET_HashCode key;
2710 struct DestinationChannel *dt;
2712 /* allocate response IP */
2713 result_af = (int) htonl (msg->result_af);
2715 allocate_response_ip (&result_af,
2721 GNUNET_SERVICE_client_drop (client);
2724 send_client_reply (client,
2728 if (result_af == AF_UNSPEC)
2730 /* failure, we're done */
2731 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2732 _("Failed to allocate IP address for new destination\n"));
2733 GNUNET_SERVICE_client_continue (client);
2738 char sbuf[INET6_ADDRSTRLEN];
2740 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2741 "Allocated address %s for redirection to service %s on peer %s\n",
2742 inet_ntop (result_af,
2746 GNUNET_h2s (&msg->service_descriptor),
2747 GNUNET_i2s (&msg->target));
2750 /* setup destination record */
2751 de = GNUNET_new (struct DestinationEntry);
2752 de->is_service = GNUNET_YES;
2753 de->details.service_destination.target = msg->target;
2754 de->details.service_destination.service_descriptor = msg->service_descriptor;
2755 get_destination_key_from_ip (result_af,
2759 GNUNET_assert (GNUNET_OK ==
2760 GNUNET_CONTAINER_multihashmap_put (destination_map,
2763 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE));
2765 = GNUNET_CONTAINER_heap_insert (destination_heap,
2767 GNUNET_TIME_absolute_ntoh (msg->expiration_time).abs_value_us);
2768 while (GNUNET_CONTAINER_multihashmap_size (destination_map) > max_destination_mappings)
2769 expire_destination (de);
2771 dt = GNUNET_new (struct DestinationChannel);
2772 dt->destination = de;
2773 GNUNET_CONTAINER_DLL_insert (de->dt_head,
2777 GNUNET_SERVICE_client_continue (client);
2783 * Free memory occupied by an entry in the destination map.
2787 * @param value a `struct DestinationEntry *`
2788 * @return #GNUNET_OK (continue to iterate)
2791 cleanup_destination (void *cls,
2792 const struct GNUNET_HashCode *key,
2795 struct DestinationEntry *de = value;
2797 free_destination_entry (de);
2803 * Free memory occupied by an entry in the channel map.
2807 * @param value a `struct ChannelState *`
2808 * @return #GNUNET_OK (continue to iterate)
2811 cleanup_channel (void *cls,
2812 const struct GNUNET_HashCode *key,
2815 struct ChannelState *ts = value;
2817 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2818 "Tearing down channel to `%s' during cleanup\n",
2819 print_channel_destination (&ts->destination));
2820 free_channel_state (ts);
2826 * Function scheduled as very last function, cleans up after us
2835 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2836 "VPN is shutting down\n");
2837 if (NULL != destination_map)
2839 GNUNET_CONTAINER_multihashmap_iterate (destination_map,
2840 &cleanup_destination,
2842 GNUNET_CONTAINER_multihashmap_destroy (destination_map);
2843 destination_map = NULL;
2845 if (NULL != destination_heap)
2847 GNUNET_CONTAINER_heap_destroy (destination_heap);
2848 destination_heap = NULL;
2850 if (NULL != channel_map)
2852 GNUNET_CONTAINER_multihashmap_iterate (channel_map,
2855 GNUNET_CONTAINER_multihashmap_destroy (channel_map);
2858 if (NULL != channel_heap)
2860 GNUNET_CONTAINER_heap_destroy (channel_heap);
2861 channel_heap = NULL;
2863 if (NULL != cadet_handle)
2865 GNUNET_CADET_disconnect (cadet_handle);
2866 cadet_handle = NULL;
2868 if (NULL != helper_handle)
2870 GNUNET_HELPER_kill (helper_handle, GNUNET_NO);
2871 GNUNET_HELPER_wait (helper_handle);
2872 helper_handle = NULL;
2876 GNUNET_STATISTICS_destroy (stats, GNUNET_NO);
2880 GNUNET_free_non_null (vpn_argv[i]);
2885 * Callback called when a client connects to the service.
2887 * @param cls closure for the service
2888 * @param c the new client that connected to the service
2889 * @param mq the message queue used to send messages to the client
2893 client_connect_cb (void *cls,
2894 struct GNUNET_SERVICE_Client *c,
2895 struct GNUNET_MQ_Handle *mq)
2902 * Callback called when a client disconnected from the service
2904 * @param cls closure for the service
2905 * @param c the client that disconnected
2906 * @param internal_cls should be equal to @a c
2909 client_disconnect_cb (void *cls,
2910 struct GNUNET_SERVICE_Client *c,
2913 GNUNET_assert (c == internal_cls);
2918 * Main function that will be run by the scheduler.
2920 * @param cls closure
2921 * @param cfg_ configuration
2922 * @param service the initialized service
2926 const struct GNUNET_CONFIGURATION_Handle *cfg_,
2927 struct GNUNET_SERVICE_Handle *service)
2938 binary = GNUNET_OS_get_libexec_binary_path ("gnunet-helper-vpn");
2941 GNUNET_OS_check_helper_binary (binary,
2943 "-d gnunet-vpn - - 169.1.3.3.7 255.255.255.0")) //ipv4 only please!
2945 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2946 "`%s' is not SUID, refusing to run.\n",
2947 "gnunet-helper-vpn");
2948 GNUNET_free (binary);
2950 /* we won't "really" exit here, as the 'service' is still running;
2951 however, as no handlers are registered, the service won't do
2955 GNUNET_free (binary);
2957 stats = GNUNET_STATISTICS_create ("vpn", cfg);
2959 GNUNET_CONFIGURATION_get_value_number (cfg,
2962 &max_destination_mappings))
2963 max_destination_mappings = 200;
2965 GNUNET_CONFIGURATION_get_value_number (cfg,
2968 &max_channel_mappings))
2969 max_channel_mappings = 200;
2971 destination_map = GNUNET_CONTAINER_multihashmap_create (max_destination_mappings * 2, GNUNET_NO);
2972 destination_heap = GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN);
2973 channel_map = GNUNET_CONTAINER_multihashmap_create (max_channel_mappings * 2, GNUNET_NO);
2974 channel_heap = GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN);
2977 vpn_argv[0] = GNUNET_strdup ("vpn-gnunet");
2978 if (GNUNET_SYSERR ==
2979 GNUNET_CONFIGURATION_get_value_string (cfg, "VPN", "IFNAME", &ifname))
2981 GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, "VPN", "IFNAME");
2982 GNUNET_SCHEDULER_shutdown ();
2985 vpn_argv[1] = ifname;
2987 if (GNUNET_OK == GNUNET_NETWORK_test_pf (PF_INET6))
2989 if ( (GNUNET_SYSERR ==
2990 GNUNET_CONFIGURATION_get_value_string (cfg, "VPN", "IPV6ADDR",
2992 (1 != inet_pton (AF_INET6, ipv6addr, &v6))) )
2994 GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, "VPN", "IPV6ADDR",
2995 _("Must specify valid IPv6 address"));
2996 GNUNET_SCHEDULER_shutdown ();
2997 GNUNET_free_non_null (ipv6addr);
3000 vpn_argv[2] = ipv6addr;
3001 ipv6prefix_s = NULL;
3002 if (GNUNET_SYSERR ==
3003 GNUNET_CONFIGURATION_get_value_string (cfg, "VPN", "IPV6PREFIX",
3006 GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, "VPN", "IPV6PREFIX");
3007 GNUNET_SCHEDULER_shutdown ();
3008 GNUNET_free_non_null (ipv6prefix_s);
3011 vpn_argv[3] = ipv6prefix_s;
3013 GNUNET_CONFIGURATION_get_value_number (cfg, "VPN",
3016 (ipv6prefix >= 127) )
3018 GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, "VPN", "IPV4MASK",
3019 _("Must specify valid IPv6 mask"));
3020 GNUNET_SCHEDULER_shutdown ();
3026 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
3027 _("IPv6 support disabled as this system does not support IPv6\n"));
3028 vpn_argv[2] = GNUNET_strdup ("-");
3029 vpn_argv[3] = GNUNET_strdup ("-");
3031 if (GNUNET_OK == GNUNET_NETWORK_test_pf (PF_INET))
3034 if ( (GNUNET_SYSERR ==
3035 GNUNET_CONFIGURATION_get_value_string (cfg, "vpn", "IPV4ADDR",
3037 (1 != inet_pton (AF_INET, ipv4addr, &v4))) )
3039 GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, "VPN", "IPV4ADDR",
3040 _("Must specify valid IPv4 address"));
3041 GNUNET_SCHEDULER_shutdown ();
3042 GNUNET_free_non_null (ipv4addr);
3045 vpn_argv[4] = ipv4addr;
3047 if ( (GNUNET_SYSERR ==
3048 GNUNET_CONFIGURATION_get_value_string (cfg, "vpn", "IPV4MASK",
3050 (1 != inet_pton (AF_INET, ipv4mask, &v4))) )
3052 GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, "VPN", "IPV4MASK",
3053 _("Must specify valid IPv4 mask"));
3054 GNUNET_SCHEDULER_shutdown ();
3055 GNUNET_free_non_null (ipv4mask);
3058 vpn_argv[5] = ipv4mask;
3062 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
3063 _("IPv4 support disabled as this system does not support IPv4\n"));
3064 vpn_argv[4] = GNUNET_strdup ("-");
3065 vpn_argv[5] = GNUNET_strdup ("-");
3069 cadet_handle = GNUNET_CADET_connect (cfg_);
3070 // FIXME never opens ports???
3071 helper_handle = GNUNET_HELPER_start (GNUNET_NO,
3072 "gnunet-helper-vpn", vpn_argv,
3073 &message_token, NULL, NULL);
3074 GNUNET_SCHEDULER_add_shutdown (&cleanup,
3080 * Define "main" method using service macro.
3084 GNUNET_SERVICE_OPTION_NONE,
3087 &client_disconnect_cb,
3089 GNUNET_MQ_hd_var_size (client_redirect_to_ip,
3090 GNUNET_MESSAGE_TYPE_VPN_CLIENT_REDIRECT_TO_IP,
3091 struct RedirectToIpRequestMessage,
3093 GNUNET_MQ_hd_fixed_size (client_redirect_to_service,
3094 GNUNET_MESSAGE_TYPE_VPN_CLIENT_REDIRECT_TO_SERVICE,
3095 struct RedirectToServiceRequestMessage,
3097 GNUNET_MQ_handler_end ());
3100 /* end of gnunet-service-vpn.c */