2 This file is part of GNUnet.
3 Copyright (C) 2010-2013, 2017 Christian Grothoff
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your 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 Affero General Public License for more details.
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
18 SPDX-License-Identifier: AGPL3.0-or-later
22 * @file exit/gnunet-daemon-exit.c
23 * @brief tool to allow IP traffic exit from the GNUnet cadet to the Internet
24 * @author Philipp Toelke
25 * @author Christian Grothoff
31 * - which code should advertise services? the service model is right
32 * now a bit odd, especially as this code DOES the exit and knows
33 * the DNS "name", but OTOH this is clearly NOT the place to advertise
34 * the service's existence; maybe the daemon should turn into a
35 * service with an API to add local-exit services dynamically?
38 #include "gnunet_util_lib.h"
39 #include "gnunet_protocols.h"
40 #include "gnunet_applications.h"
41 #include "gnunet_dht_service.h"
42 #include "gnunet_cadet_service.h"
43 #include "gnunet_dnsparser_lib.h"
44 #include "gnunet_dnsstub_lib.h"
45 #include "gnunet_statistics_service.h"
46 #include "gnunet_constants.h"
47 #include "gnunet_signatures.h"
48 #include "gnunet_tun_lib.h"
49 #include "gnunet_regex_service.h"
51 #include "block_dns.h"
55 * Maximum path compression length for cadet regex announcing for IPv4 address
58 #define REGEX_MAX_PATH_LEN_IPV4 4
61 * Maximum path compression length for cadet regex announcing for IPv6 address
64 #define REGEX_MAX_PATH_LEN_IPV6 8
67 * How frequently do we re-announce the regex for the exit?
69 #define REGEX_REFRESH_FREQUENCY GNUNET_TIME_relative_multiply ( \
70 GNUNET_TIME_UNIT_MINUTES, 30)
73 * How frequently do we re-announce the DNS exit in the DHT?
75 #define DHT_PUT_FREQUENCY GNUNET_TIME_relative_multiply ( \
76 GNUNET_TIME_UNIT_MINUTES, 15)
79 * How long do we typically sign the DNS exit advertisement for?
81 #define DNS_ADVERTISEMENT_TIMEOUT GNUNET_TIME_relative_multiply ( \
82 GNUNET_TIME_UNIT_HOURS, 3)
86 * Generic logging shorthand
88 #define LOG(kind, ...) \
89 GNUNET_log_from (kind, "exit", __VA_ARGS__);
93 * Information about an address.
98 * AF_INET or AF_INET6.
103 * Remote address information.
108 * Address, if af is AF_INET.
113 * Address, if af is AF_INET6.
115 struct in6_addr ipv6;
119 * IPPROTO_TCP or IPPROTO_UDP;
124 * Remote port, in host byte order!
131 * This struct is saved into the services-hashmap to represent
132 * a service this peer is specifically offering an exit for
133 * (for a specific domain name).
138 * Remote address to use for the service.
140 struct SocketAddress address;
143 * Descriptor for the service (CADET port).
145 struct GNUNET_HashCode descriptor;
148 * DNS name of the service.
153 * Open port with CADET.
155 struct GNUNET_CADET_Port *port;
158 * #GNUNET_YES if this is a UDP service, otherwise TCP.
165 * Information we use to track a connection (the classical 6-tuple of
166 * IP-version, protocol, source-IP, destination-IP, source-port and
169 struct RedirectInformation
172 * Address information for the other party (equivalent of the
173 * arguments one would give to "connect").
175 struct SocketAddress remote_address;
178 * Address information we used locally (AF and proto must match
179 * "remote_address"). Equivalent of the arguments one would give to
182 struct SocketAddress local_address;
185 Note 1: additional information might be added here in the
186 future to support protocols that require special handling,
189 Note 2: we might also sometimes not match on all components
190 of the tuple, to support protocols where things do not always
197 * This struct is saved into #connections_map to allow finding the
198 * right channel given an IP packet from TUN. It is also associated
199 * with the channel's closure so we can find it again for the next
200 * message from the channel.
205 * Cadet channel that is used for this connection.
207 struct GNUNET_CADET_Channel *channel;
210 * Who is the other end of this channel.
211 * FIXME is this needed? Only used for debugging messages
213 struct GNUNET_PeerIdentity peer;
216 * #GNUNET_NO if this is a channel for TCP/UDP,
217 * #GNUNET_YES if this is a channel for DNS,
218 * #GNUNET_SYSERR if the channel is not yet initialized.
227 * Heap node for this state in the connections_heap.
229 struct GNUNET_CONTAINER_HeapNode *heap_node;
232 * Key this state has in the #connections_map.
234 struct GNUNET_HashCode state_key;
237 * Associated service record, or NULL for no service.
239 struct LocalService *serv;
242 * Primary redirection information for this connection.
244 struct RedirectInformation ri;
250 * Socket we are using to transmit this request (must match if we receive
253 struct GNUNET_DNSSTUB_RequestSocket *rs;
256 * Original DNS request ID as used by the client.
258 uint16_t original_id;
261 * DNS request ID that we used for forwarding.
270 * Return value from 'main'.
272 static int global_ret;
275 * Handle to our regex announcement for IPv4.
277 static struct GNUNET_REGEX_Announcement *regex4;
280 * Handle to our regex announcement for IPv4.
282 static struct GNUNET_REGEX_Announcement *regex6;
285 * The handle to the configuration used throughout the process
287 static const struct GNUNET_CONFIGURATION_Handle *cfg;
290 * The handle to the helper
292 static struct GNUNET_HELPER_Handle *helper_handle;
295 * Arguments to the exit helper.
297 static char *exit_argv[8];
300 * IPv6 address of our TUN interface.
302 static struct in6_addr exit_ipv6addr;
305 * IPv6 prefix (0..127) from configuration file.
307 static unsigned long long ipv6prefix;
310 * IPv4 address of our TUN interface.
312 static struct in_addr exit_ipv4addr;
315 * IPv4 netmask of our TUN interface.
317 static struct in_addr exit_ipv4mask;
322 static struct GNUNET_STATISTICS_Handle *stats;
325 * The handle to cadet
327 static struct GNUNET_CADET_Handle *cadet_handle;
330 * This hashmaps contains the mapping from peer, service-descriptor,
331 * source-port and destination-port to a struct ChannelState
333 static struct GNUNET_CONTAINER_MultiHashMap *connections_map;
336 * Heap so we can quickly find "old" connections.
338 static struct GNUNET_CONTAINER_Heap *connections_heap;
341 * If there are at least this many connections, old ones will be removed
343 static unsigned long long max_connections;
346 * This hashmaps saves interesting things about the configured services
348 static struct GNUNET_CONTAINER_MultiHashMap *services;
351 * Array of all open DNS requests from channels.
353 static struct ChannelState *channels[UINT16_MAX + 1];
356 * Handle to the DNS Stub resolver.
358 static struct GNUNET_DNSSTUB_Context *dnsstub;
361 * Handle for ongoing DHT PUT operations to advertise exit service.
363 static struct GNUNET_DHT_PutHandle *dht_put;
368 static struct GNUNET_DHT_Handle *dht;
371 * Task for doing DHT PUTs to advertise exit service.
373 static struct GNUNET_SCHEDULER_Task *dht_task;
376 * Advertisement message we put into the DHT to advertise us
379 static struct GNUNET_DNS_Advertisement dns_advertisement;
382 * Key we store the DNS advertismenet under.
384 static struct GNUNET_HashCode dht_put_key;
387 * Private key for this peer.
389 static struct GNUNET_CRYPTO_EddsaPrivateKey *peer_key;
394 static struct GNUNET_CADET_Port *dns_port;
397 * Port for IPv4 exit.
399 static struct GNUNET_CADET_Port *cadet_port4;
402 * Port for IPv6 exit.
404 static struct GNUNET_CADET_Port *cadet_port6;
407 * Are we an IPv4-exit?
409 static int ipv4_exit;
412 * Are we an IPv6-exit?
414 static int ipv6_exit;
417 * Do we support IPv4 at all on the TUN interface?
419 static int ipv4_enabled;
422 * Do we support IPv6 at all on the TUN interface?
424 static int ipv6_enabled;
427 GNUNET_NETWORK_STRUCT_BEGIN
430 * Message with a DNS response.
432 struct DnsResponseMessage
435 * GNUnet header, of type #GNUNET_MESSAGE_TYPE_VPN_DNS_FROM_INTERNET
437 struct GNUNET_MessageHeader header;
442 struct GNUNET_TUN_DnsHeader dns;
444 /* Followed by more DNS payload */
447 GNUNET_NETWORK_STRUCT_END
451 * Callback called from DNSSTUB resolver when a resolution
455 * @param dns the response itself
456 * @param r number of bytes in @a dns
459 process_dns_result (void *cls,
460 const struct GNUNET_TUN_DnsHeader *dns,
463 struct ChannelState *ts;
464 struct GNUNET_MQ_Envelope *env;
465 struct DnsResponseMessage *resp;
467 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
468 "Processing DNS result from stub resolver\n");
469 GNUNET_assert (NULL == cls);
472 /* Handle case that this is a reply to a request from a CADET DNS channel */
473 ts = channels[dns->id];
476 LOG (GNUNET_ERROR_TYPE_DEBUG,
477 "Got a response from the stub resolver for DNS request received via CADET!\n");
478 channels[dns->id] = NULL;
479 env = GNUNET_MQ_msg_extra (resp,
480 r - sizeof(struct GNUNET_TUN_DnsHeader),
481 GNUNET_MESSAGE_TYPE_VPN_DNS_FROM_INTERNET);
482 GNUNET_memcpy (&resp->dns,
485 resp->dns.id = ts->specifics.dns.original_id;
486 GNUNET_MQ_send (GNUNET_CADET_get_mq (ts->channel),
492 * Check a request via cadet to perform a DNS query.
494 * @param cls our `struct ChannelState *`
495 * @param msg the actual message
496 * @return #GNUNET_OK to keep the connection open,
497 * #GNUNET_SYSERR to close it (signal serious error)
500 check_dns_request (void *cls,
501 const struct DnsResponseMessage *msg)
503 struct ChannelState *ts = cls;
508 return GNUNET_SYSERR;
510 if (GNUNET_NO == ts->is_dns)
513 return GNUNET_SYSERR;
520 * Process a request via cadet to perform a DNS query.
522 * @param cls our `struct ChannelState *`
523 * @param msg the actual message
526 handle_dns_request (void *cls,
527 const struct DnsResponseMessage *msg)
529 struct ChannelState *ts = cls;
530 size_t mlen = ntohs (msg->header.size);
531 size_t dlen = mlen - sizeof(struct GNUNET_MessageHeader);
532 char buf[dlen] GNUNET_ALIGN;
533 struct GNUNET_TUN_DnsHeader *dout;
535 if (GNUNET_SYSERR == ts->is_dns)
537 /* channel is DNS from now on */
538 ts->is_dns = GNUNET_YES;
540 ts->specifics.dns.original_id = msg->dns.id;
541 if (channels[ts->specifics.dns.my_id] == ts)
542 channels[ts->specifics.dns.my_id] = NULL;
543 ts->specifics.dns.my_id = (uint16_t) GNUNET_CRYPTO_random_u32 (
544 GNUNET_CRYPTO_QUALITY_WEAK,
547 channels[ts->specifics.dns.my_id] = ts;
551 dout = (struct GNUNET_TUN_DnsHeader *) buf;
552 dout->id = ts->specifics.dns.my_id;
553 ts->specifics.dns.rs = GNUNET_DNSSTUB_resolve (dnsstub,
558 if (NULL == ts->specifics.dns.rs)
563 GNUNET_CADET_receive_done (ts->channel);
568 * Given IP information about a connection, calculate the respective
569 * hash we would use for the #connections_map.
571 * @param hash resulting hash
572 * @param ri information about the connection
575 hash_redirect_info (struct GNUNET_HashCode *hash,
576 const struct RedirectInformation *ri)
582 sizeof(struct GNUNET_HashCode));
583 /* the GNUnet hashmap only uses the first sizeof(unsigned int) of the hash,
584 so we put the IP address in there (and hope for few collisions) */
586 switch (ri->remote_address.af)
590 &ri->remote_address.address.ipv4,
591 sizeof(struct in_addr));
592 off += sizeof(struct in_addr);
597 &ri->remote_address.address.ipv6,
598 sizeof(struct in6_addr));
599 off += sizeof(struct in_addr);
606 &ri->remote_address.port,
608 off += sizeof(uint16_t);
609 switch (ri->local_address.af)
613 &ri->local_address.address.ipv4,
614 sizeof(struct in_addr));
615 off += sizeof(struct in_addr);
620 &ri->local_address.address.ipv6,
621 sizeof(struct in6_addr));
622 off += sizeof(struct in_addr);
629 &ri->local_address.port,
631 off += sizeof(uint16_t);
633 &ri->remote_address.proto,
635 /* off += sizeof (uint8_t); */
640 * Get our connection tracking state. Warns if it does not exists,
641 * refreshes the timestamp if it does exist.
643 * @param af address family
644 * @param protocol IPPROTO_UDP or IPPROTO_TCP
645 * @param destination_ip target IP
646 * @param destination_port target port
647 * @param local_ip local IP
648 * @param local_port local port
649 * @param state_key set to hash's state if non-NULL
650 * @return NULL if we have no tracking information for this tuple
652 static struct ChannelState *
653 get_redirect_state (int af,
655 const void *destination_ip,
656 uint16_t destination_port,
657 const void *local_ip,
659 struct GNUNET_HashCode *state_key)
661 struct RedirectInformation ri;
662 struct GNUNET_HashCode key;
663 struct ChannelState *state;
665 if (((af == AF_INET) && (protocol == IPPROTO_ICMP)) ||
666 ((af == AF_INET6) && (protocol == IPPROTO_ICMPV6)))
669 destination_port = 0;
672 ri.remote_address.af = af;
674 ri.remote_address.address.ipv4 = *((struct in_addr*) destination_ip);
676 ri.remote_address.address.ipv6 = *((struct in6_addr*) destination_ip);
677 ri.remote_address.port = destination_port;
678 ri.remote_address.proto = protocol;
679 ri.local_address.af = af;
681 ri.local_address.address.ipv4 = *((struct in_addr*) local_ip);
683 ri.local_address.address.ipv6 = *((struct in6_addr*) local_ip);
684 ri.local_address.port = local_port;
685 ri.local_address.proto = protocol;
686 hash_redirect_info (&key,
688 if (NULL != state_key)
690 state = GNUNET_CONTAINER_multihashmap_get (connections_map,
694 /* Mark this connection as freshly used */
695 if (NULL == state_key)
696 GNUNET_CONTAINER_heap_update_cost (state->specifics.tcp_udp.heap_node,
697 GNUNET_TIME_absolute_get ().abs_value_us);
703 * Check a request via cadet to send a request to a TCP service
704 * offered by this system.
706 * @param cls our `struct ChannelState *`
707 * @param start the actual message
708 * @return #GNUNET_OK to keep the connection open,
709 * #GNUNET_SYSERR to close it (signal serious error)
712 check_tcp_service (void *cls,
713 const struct GNUNET_EXIT_TcpServiceStartMessage *start)
715 struct ChannelState *state = cls;
720 return GNUNET_SYSERR;
722 if (GNUNET_YES == state->is_dns)
725 return GNUNET_SYSERR;
727 if (NULL == state->specifics.tcp_udp.serv)
730 return GNUNET_SYSERR;
732 if (NULL != state->specifics.tcp_udp.heap_node)
735 return GNUNET_SYSERR;
737 if (start->tcp_header.off * 4 < sizeof(struct GNUNET_TUN_TcpHeader))
740 return GNUNET_SYSERR;
747 * Prepare an IPv4 packet for transmission via the TUN interface.
748 * Initializes the IP header and calculates checksums (IP+UDP/TCP).
749 * For UDP, the UDP header will be fully created, whereas for TCP
750 * only the ports and checksum will be filled in. So for TCP,
751 * a skeleton TCP header must be part of the provided payload.
753 * @param payload payload of the packet (starting with UDP payload or
754 * TCP header, depending on protocol)
755 * @param payload_length number of bytes in @a payload
756 * @param protocol IPPROTO_UDP or IPPROTO_TCP
757 * @param tcp_header skeleton of the TCP header, NULL for UDP
758 * @param src_address source address to use (IP and port)
759 * @param dst_address destination address to use (IP and port)
760 * @param pkt4 where to write the assembled packet; must
761 * contain enough space for the IP header, UDP/TCP header
765 prepare_ipv4_packet (const void *payload,
766 size_t payload_length,
768 const struct GNUNET_TUN_TcpHeader *tcp_header,
769 const struct SocketAddress *src_address,
770 const struct SocketAddress *dst_address,
771 struct GNUNET_TUN_IPv4Header *pkt4)
775 len = payload_length;
779 len += sizeof(struct GNUNET_TUN_UdpHeader);
783 len += sizeof(struct GNUNET_TUN_TcpHeader);
784 GNUNET_assert (NULL != tcp_header);
791 if (len + sizeof(struct GNUNET_TUN_IPv4Header) > UINT16_MAX)
797 GNUNET_TUN_initialize_ipv4_header (pkt4,
800 &src_address->address.ipv4,
801 &dst_address->address.ipv4);
806 struct GNUNET_TUN_UdpHeader *pkt4_udp = (struct
807 GNUNET_TUN_UdpHeader *) &pkt4[1];
809 pkt4_udp->source_port = htons (src_address->port);
810 pkt4_udp->destination_port = htons (dst_address->port);
811 pkt4_udp->len = htons ((uint16_t) payload_length);
812 GNUNET_TUN_calculate_udp4_checksum (pkt4,
816 GNUNET_memcpy (&pkt4_udp[1],
824 struct GNUNET_TUN_TcpHeader *pkt4_tcp = (struct
825 GNUNET_TUN_TcpHeader *) &pkt4[1];
827 *pkt4_tcp = *tcp_header;
828 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
829 "Sending TCP packet from port %u to port %u\n",
832 pkt4_tcp->source_port = htons (src_address->port);
833 pkt4_tcp->destination_port = htons (dst_address->port);
834 GNUNET_TUN_calculate_tcp4_checksum (pkt4,
838 GNUNET_memcpy (&pkt4_tcp[1],
851 * Prepare an IPv6 packet for transmission via the TUN interface.
852 * Initializes the IP header and calculates checksums (IP+UDP/TCP).
853 * For UDP, the UDP header will be fully created, whereas for TCP
854 * only the ports and checksum will be filled in. So for TCP,
855 * a skeleton TCP header must be part of the provided payload.
857 * @param payload payload of the packet (starting with UDP payload or
858 * TCP header, depending on protocol)
859 * @param payload_length number of bytes in @a payload
860 * @param protocol IPPROTO_UDP or IPPROTO_TCP
861 * @param tcp_header skeleton TCP header data to send, NULL for UDP
862 * @param src_address source address to use (IP and port)
863 * @param dst_address destination address to use (IP and port)
864 * @param pkt6 where to write the assembled packet; must
865 * contain enough space for the IP header, UDP/TCP header
869 prepare_ipv6_packet (const void *payload,
870 size_t payload_length,
872 const struct GNUNET_TUN_TcpHeader *tcp_header,
873 const struct SocketAddress *src_address,
874 const struct SocketAddress *dst_address,
875 struct GNUNET_TUN_IPv6Header *pkt6)
879 len = payload_length;
883 len += sizeof(struct GNUNET_TUN_UdpHeader);
887 len += sizeof(struct GNUNET_TUN_TcpHeader);
894 if (len > UINT16_MAX)
900 GNUNET_TUN_initialize_ipv6_header (pkt6,
903 &src_address->address.ipv6,
904 &dst_address->address.ipv6);
910 struct GNUNET_TUN_UdpHeader *pkt6_udp = (struct
911 GNUNET_TUN_UdpHeader *) &pkt6[1];
913 pkt6_udp->source_port = htons (src_address->port);
914 pkt6_udp->destination_port = htons (dst_address->port);
915 pkt6_udp->len = htons ((uint16_t) payload_length);
916 GNUNET_TUN_calculate_udp6_checksum (pkt6,
920 GNUNET_memcpy (&pkt6_udp[1],
928 struct GNUNET_TUN_TcpHeader *pkt6_tcp = (struct
929 GNUNET_TUN_TcpHeader *) &pkt6[1];
931 /* GNUNET_memcpy first here as some TCP header fields are initialized this way! */
932 *pkt6_tcp = *tcp_header;
933 pkt6_tcp->source_port = htons (src_address->port);
934 pkt6_tcp->destination_port = htons (dst_address->port);
935 GNUNET_TUN_calculate_tcp6_checksum (pkt6,
939 GNUNET_memcpy (&pkt6_tcp[1],
953 * Send a TCP packet via the TUN interface.
955 * @param destination_address IP and port to use for the TCP packet's destination
956 * @param source_address IP and port to use for the TCP packet's source
957 * @param tcp_header header template to use
958 * @param payload payload of the TCP packet
959 * @param payload_length number of bytes in @a payload
962 send_tcp_packet_via_tun (const struct SocketAddress *destination_address,
963 const struct SocketAddress *source_address,
964 const struct GNUNET_TUN_TcpHeader *tcp_header,
966 size_t payload_length)
970 GNUNET_STATISTICS_update (stats,
971 gettext_noop ("# TCP packets sent via TUN"),
974 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
975 "Sending packet with %u bytes TCP payload via TUN\n",
976 (unsigned int) payload_length);
977 len = sizeof(struct GNUNET_MessageHeader) + sizeof(struct
978 GNUNET_TUN_Layer2PacketHeader);
979 switch (source_address->af)
982 len += sizeof(struct GNUNET_TUN_IPv4Header);
986 len += sizeof(struct GNUNET_TUN_IPv6Header);
993 len += sizeof(struct GNUNET_TUN_TcpHeader);
994 len += payload_length;
995 if (len >= GNUNET_MAX_MESSAGE_SIZE)
1001 char buf[len] GNUNET_ALIGN;
1002 struct GNUNET_MessageHeader *hdr;
1003 struct GNUNET_TUN_Layer2PacketHeader *tun;
1005 hdr = (struct GNUNET_MessageHeader *) buf;
1006 hdr->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
1007 hdr->size = htons (len);
1008 tun = (struct GNUNET_TUN_Layer2PacketHeader*) &hdr[1];
1009 tun->flags = htons (0);
1010 switch (source_address->af)
1014 struct GNUNET_TUN_IPv4Header *ipv4
1015 = (struct GNUNET_TUN_IPv4Header*) &tun[1];
1017 tun->proto = htons (ETH_P_IPV4);
1018 prepare_ipv4_packet (payload,
1023 destination_address,
1030 struct GNUNET_TUN_IPv6Header *ipv6
1031 = (struct GNUNET_TUN_IPv6Header*) &tun[1];
1033 tun->proto = htons (ETH_P_IPV6);
1034 prepare_ipv6_packet (payload,
1039 destination_address,
1048 if (NULL != helper_handle)
1049 (void) GNUNET_HELPER_send (helper_handle,
1050 (const struct GNUNET_MessageHeader*) buf,
1059 * Send an ICMP packet via the TUN interface.
1061 * @param destination_address IP to use for the ICMP packet's destination
1062 * @param source_address IP to use for the ICMP packet's source
1063 * @param icmp_header ICMP header to send
1064 * @param payload payload of the ICMP packet (does NOT include ICMP header)
1065 * @param payload_length number of bytes of data in @a payload
1068 send_icmp_packet_via_tun (const struct SocketAddress *destination_address,
1069 const struct SocketAddress *source_address,
1070 const struct GNUNET_TUN_IcmpHeader *icmp_header,
1071 const void *payload, size_t payload_length)
1074 struct GNUNET_TUN_IcmpHeader *icmp;
1076 GNUNET_STATISTICS_update (stats,
1077 gettext_noop ("# ICMP packets sent via TUN"),
1079 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1080 "Sending packet with %u bytes ICMP payload via TUN\n",
1081 (unsigned int) payload_length);
1082 len = sizeof(struct GNUNET_MessageHeader) + sizeof(struct
1083 GNUNET_TUN_Layer2PacketHeader);
1084 switch (destination_address->af)
1087 len += sizeof(struct GNUNET_TUN_IPv4Header);
1091 len += sizeof(struct GNUNET_TUN_IPv6Header);
1098 len += sizeof(struct GNUNET_TUN_IcmpHeader);
1099 len += payload_length;
1100 if (len >= GNUNET_MAX_MESSAGE_SIZE)
1106 char buf[len] GNUNET_ALIGN;
1107 struct GNUNET_MessageHeader *hdr;
1108 struct GNUNET_TUN_Layer2PacketHeader *tun;
1110 hdr = (struct GNUNET_MessageHeader *) buf;
1111 hdr->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
1112 hdr->size = htons (len);
1113 tun = (struct GNUNET_TUN_Layer2PacketHeader*) &hdr[1];
1114 tun->flags = htons (0);
1115 switch (source_address->af)
1119 struct GNUNET_TUN_IPv4Header *ipv4 = (struct
1120 GNUNET_TUN_IPv4Header*) &tun[1];
1122 tun->proto = htons (ETH_P_IPV4);
1123 GNUNET_TUN_initialize_ipv4_header (ipv4,
1126 GNUNET_TUN_IcmpHeader)
1128 &source_address->address.ipv4,
1129 &destination_address->address.ipv4);
1130 icmp = (struct GNUNET_TUN_IcmpHeader*) &ipv4[1];
1136 struct GNUNET_TUN_IPv6Header *ipv6 = (struct
1137 GNUNET_TUN_IPv6Header*) &tun[1];
1139 tun->proto = htons (ETH_P_IPV6);
1140 GNUNET_TUN_initialize_ipv6_header (ipv6,
1143 GNUNET_TUN_IcmpHeader)
1145 &source_address->address.ipv6,
1146 &destination_address->address.ipv6);
1147 icmp = (struct GNUNET_TUN_IcmpHeader*) &ipv6[1];
1155 *icmp = *icmp_header;
1156 GNUNET_memcpy (&icmp[1],
1159 GNUNET_TUN_calculate_icmp_checksum (icmp,
1162 if (NULL != helper_handle)
1163 (void) GNUNET_HELPER_send (helper_handle,
1164 (const struct GNUNET_MessageHeader*) buf,
1172 * We need to create a (unique) fresh local address (IP+port).
1175 * @param af desired address family
1176 * @param proto desired protocol (IPPROTO_UDP or IPPROTO_TCP)
1177 * @param local_address address to initialize
1180 setup_fresh_address (int af,
1182 struct SocketAddress *local_address)
1184 local_address->af = af;
1185 local_address->proto = (uint8_t) proto;
1186 /* default "local" port range is often 32768--61000,
1187 so we pick a random value in that range */
1188 if (((af == AF_INET) && (proto == IPPROTO_ICMP)) ||
1189 ((af == AF_INET6) && (proto == IPPROTO_ICMPV6)))
1190 local_address->port = 0;
1193 = (uint16_t) 32768 + GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
1199 struct in_addr addr;
1200 struct in_addr mask;
1203 addr = exit_ipv4addr;
1204 mask = exit_ipv4mask;
1205 if (0 == ~mask.s_addr)
1207 /* only one valid IP anyway */
1208 local_address->address.ipv4 = addr;
1211 /* Given 192.168.0.1/255.255.0.0, we want a mask
1212 of '192.168.255.255', thus: */
1213 mask.s_addr = addr.s_addr | ~mask.s_addr;
1214 /* Pick random IPv4 address within the subnet, except 'addr' or 'mask' itself */
1217 rnd.s_addr = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
1219 local_address->address.ipv4.s_addr = (addr.s_addr | rnd.s_addr)
1222 while ((local_address->address.ipv4.s_addr == addr.s_addr) ||
1223 (local_address->address.ipv4.s_addr == mask.s_addr));
1229 struct in6_addr addr;
1230 struct in6_addr mask;
1231 struct in6_addr rnd;
1234 addr = exit_ipv6addr;
1235 GNUNET_assert (ipv6prefix < 128);
1236 if (ipv6prefix == 127)
1238 /* only one valid IP anyway */
1239 local_address->address.ipv6 = addr;
1242 /* Given ABCD::/96, we want a mask of 'ABCD::FFFF:FFFF,
1245 for (i = 127; i >= ipv6prefix; i--)
1246 mask.s6_addr[i / 8] |= (1 << (i % 8));
1248 /* Pick random IPv6 address within the subnet, except 'addr' or 'mask' itself */
1251 for (i = 0; i < 16; i++)
1253 rnd.s6_addr[i] = (unsigned char) GNUNET_CRYPTO_random_u32 (
1254 GNUNET_CRYPTO_QUALITY_WEAK,
1256 local_address->address.ipv6.s6_addr[i]
1257 = (addr.s6_addr[i] | rnd.s6_addr[i]) & mask.s6_addr[i];
1260 while ((0 == GNUNET_memcmp (&local_address->address.ipv6,
1262 (0 == GNUNET_memcmp (&local_address->address.ipv6,
1274 * We are starting a fresh connection (TCP or UDP) and need
1275 * to pick a source port and IP address (within the correct
1276 * range and address family) to associate replies with the
1277 * connection / correct cadet channel. This function generates
1278 * a "fresh" source IP and source port number for a connection
1279 * After picking a good source address, this function sets up
1280 * the state in the 'connections_map' and 'connections_heap'
1281 * to allow finding the state when needed later. The function
1282 * also makes sure that we remain within memory limits by
1283 * cleaning up 'old' states.
1285 * @param state skeleton state to setup a record for; should
1286 * 'state->specifics.tcp_udp.ri.remote_address' filled in so that
1287 * this code can determine which AF/protocol is
1288 * going to be used (the 'channel' should also
1289 * already be set); after calling this function,
1290 * heap_node and the local_address will be
1291 * also initialized (heap_node != NULL can be
1292 * used to test if a state has been fully setup).
1295 setup_state_record (struct ChannelState *state)
1297 struct GNUNET_HashCode key;
1298 struct ChannelState *s;
1300 /* generate fresh, unique address */
1303 if (NULL == state->specifics.tcp_udp.serv)
1304 setup_fresh_address (state->specifics.tcp_udp.ri.remote_address.af,
1305 state->specifics.tcp_udp.ri.remote_address.proto,
1306 &state->specifics.tcp_udp.ri.local_address);
1308 setup_fresh_address (state->specifics.tcp_udp.serv->address.af,
1309 state->specifics.tcp_udp.serv->address.proto,
1310 &state->specifics.tcp_udp.ri.local_address);
1313 get_redirect_state (state->specifics.tcp_udp.ri.remote_address.af,
1314 state->specifics.tcp_udp.ri.remote_address.proto,
1315 &state->specifics.tcp_udp.ri.remote_address.address,
1316 state->specifics.tcp_udp.ri.remote_address.port,
1317 &state->specifics.tcp_udp.ri.local_address.address,
1318 state->specifics.tcp_udp.ri.local_address.port,
1321 char buf[INET6_ADDRSTRLEN];
1322 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1323 "Picked local address %s:%u for new connection\n",
1324 inet_ntop (state->specifics.tcp_udp.ri.local_address.af,
1325 &state->specifics.tcp_udp.ri.local_address.address,
1328 (unsigned int) state->specifics.tcp_udp.ri.local_address.port);
1330 state->specifics.tcp_udp.state_key = key;
1331 GNUNET_assert (GNUNET_OK ==
1332 GNUNET_CONTAINER_multihashmap_put (connections_map,
1334 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
1335 state->specifics.tcp_udp.heap_node
1336 = GNUNET_CONTAINER_heap_insert (connections_heap,
1338 GNUNET_TIME_absolute_get ().abs_value_us);
1339 while (GNUNET_CONTAINER_heap_get_size (connections_heap) > max_connections)
1341 s = GNUNET_CONTAINER_heap_remove_root (connections_heap);
1342 GNUNET_assert (state != s);
1343 s->specifics.tcp_udp.heap_node = NULL;
1344 GNUNET_CADET_channel_destroy (s->channel);
1345 GNUNET_assert (GNUNET_OK ==
1346 GNUNET_CONTAINER_multihashmap_remove (connections_map,
1347 &s->specifics.tcp_udp.
1356 * Send a UDP packet via the TUN interface.
1358 * @param destination_address IP and port to use for the UDP packet's destination
1359 * @param source_address IP and port to use for the UDP packet's source
1360 * @param payload payload of the UDP packet (does NOT include UDP header)
1361 * @param payload_length number of bytes of data in @a payload
1364 send_udp_packet_via_tun (const struct SocketAddress *destination_address,
1365 const struct SocketAddress *source_address,
1366 const void *payload, size_t payload_length)
1370 GNUNET_STATISTICS_update (stats,
1371 gettext_noop ("# UDP packets sent via TUN"),
1373 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1374 "Sending packet with %u bytes UDP payload via TUN\n",
1375 (unsigned int) payload_length);
1376 len = sizeof(struct GNUNET_MessageHeader) + sizeof(struct
1377 GNUNET_TUN_Layer2PacketHeader);
1378 switch (source_address->af)
1381 len += sizeof(struct GNUNET_TUN_IPv4Header);
1385 len += sizeof(struct GNUNET_TUN_IPv6Header);
1392 len += sizeof(struct GNUNET_TUN_UdpHeader);
1393 len += payload_length;
1394 if (len >= GNUNET_MAX_MESSAGE_SIZE)
1400 char buf[len] GNUNET_ALIGN;
1401 struct GNUNET_MessageHeader *hdr;
1402 struct GNUNET_TUN_Layer2PacketHeader *tun;
1404 hdr = (struct GNUNET_MessageHeader *) buf;
1405 hdr->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
1406 hdr->size = htons (len);
1407 tun = (struct GNUNET_TUN_Layer2PacketHeader*) &hdr[1];
1408 tun->flags = htons (0);
1409 switch (source_address->af)
1413 struct GNUNET_TUN_IPv4Header *ipv4 = (struct
1414 GNUNET_TUN_IPv4Header*) &tun[1];
1416 tun->proto = htons (ETH_P_IPV4);
1417 prepare_ipv4_packet (payload,
1422 destination_address,
1429 struct GNUNET_TUN_IPv6Header *ipv6 = (struct
1430 GNUNET_TUN_IPv6Header*) &tun[1];
1432 tun->proto = htons (ETH_P_IPV6);
1433 prepare_ipv6_packet (payload,
1438 destination_address,
1447 if (NULL != helper_handle)
1448 (void) GNUNET_HELPER_send (helper_handle,
1449 (const struct GNUNET_MessageHeader*) buf,
1457 * Check a request to forward UDP data to the Internet via this peer.
1459 * @param cls our `struct ChannelState *`
1460 * @param msg the actual message
1461 * @return #GNUNET_OK to keep the connection open,
1462 * #GNUNET_SYSERR to close it (signal serious error)
1465 check_udp_remote (void *cls,
1466 const struct GNUNET_EXIT_UdpInternetMessage *msg)
1468 struct ChannelState *state = cls;
1470 if (GNUNET_YES == state->is_dns)
1472 GNUNET_break_op (0);
1473 return GNUNET_SYSERR;
1480 * Process a request to forward UDP data to the Internet via this peer.
1482 * @param cls our `struct ChannelState *`
1483 * @param msg the actual message
1486 handle_udp_remote (void *cls,
1487 const struct GNUNET_EXIT_UdpInternetMessage *msg)
1489 struct ChannelState *state = cls;
1490 uint16_t pkt_len = ntohs (msg->header.size) - sizeof(struct
1491 GNUNET_EXIT_UdpInternetMessage);
1492 const struct in_addr *v4;
1493 const struct in6_addr *v6;
1494 const void *payload;
1497 if (GNUNET_SYSERR == state->is_dns)
1499 /* channel is UDP/TCP from now on */
1500 state->is_dns = GNUNET_NO;
1502 GNUNET_STATISTICS_update (stats,
1503 gettext_noop ("# Bytes received from CADET"),
1504 pkt_len, GNUNET_NO);
1505 GNUNET_STATISTICS_update (stats,
1507 "# UDP IP-exit requests received via cadet"),
1509 af = (int) ntohl (msg->af);
1510 state->specifics.tcp_udp.ri.remote_address.af = af;
1514 if (pkt_len < sizeof(struct in_addr))
1516 GNUNET_break_op (0);
1521 GNUNET_break_op (0);
1524 v4 = (const struct in_addr*) &msg[1];
1526 pkt_len -= sizeof(struct in_addr);
1527 state->specifics.tcp_udp.ri.remote_address.address.ipv4 = *v4;
1531 if (pkt_len < sizeof(struct in6_addr))
1533 GNUNET_break_op (0);
1538 GNUNET_break_op (0);
1541 v6 = (const struct in6_addr*) &msg[1];
1543 pkt_len -= sizeof(struct in6_addr);
1544 state->specifics.tcp_udp.ri.remote_address.address.ipv6 = *v6;
1548 GNUNET_break_op (0);
1552 char buf[INET6_ADDRSTRLEN];
1553 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1554 "Received data from %s for forwarding to UDP %s:%u\n",
1555 GNUNET_i2s (&state->peer),
1557 &state->specifics.tcp_udp.ri.remote_address.address,
1559 (unsigned int) ntohs (msg->destination_port));
1561 state->specifics.tcp_udp.ri.remote_address.proto = IPPROTO_UDP;
1562 state->specifics.tcp_udp.ri.remote_address.port = msg->destination_port;
1563 if (NULL == state->specifics.tcp_udp.heap_node)
1564 setup_state_record (state);
1565 if (0 != ntohs (msg->source_port))
1566 state->specifics.tcp_udp.ri.local_address.port = msg->source_port;
1567 send_udp_packet_via_tun (&state->specifics.tcp_udp.ri.remote_address,
1568 &state->specifics.tcp_udp.ri.local_address,
1571 GNUNET_CADET_receive_done (state->channel);
1576 * Check a request via cadet to send a request to a UDP service
1577 * offered by this system.
1579 * @param cls our `struct ChannelState *`
1580 * @param msg the actual message
1581 * @return #GNUNET_OK to keep the connection open,
1582 * #GNUNET_SYSERR to close it (signal serious error)
1585 check_udp_service (void *cls,
1586 const struct GNUNET_EXIT_UdpServiceMessage *msg)
1588 struct ChannelState *state = cls;
1590 if (NULL == state->specifics.tcp_udp.serv)
1592 GNUNET_break_op (0);
1593 return GNUNET_SYSERR;
1600 * Process a request via cadet to send a request to a UDP service
1601 * offered by this system.
1603 * @param cls our `struct ChannelState *`
1604 * @param msg the actual message
1607 handle_udp_service (void *cls,
1608 const struct GNUNET_EXIT_UdpServiceMessage *msg)
1610 struct ChannelState *state = cls;
1611 uint16_t pkt_len = ntohs (msg->header.size) - sizeof(struct
1612 GNUNET_EXIT_UdpServiceMessage);
1614 GNUNET_STATISTICS_update (stats,
1615 gettext_noop ("# Bytes received from CADET"),
1616 pkt_len, GNUNET_NO);
1617 GNUNET_STATISTICS_update (stats,
1619 "# UDP service requests received via cadet"),
1621 LOG (GNUNET_ERROR_TYPE_DEBUG,
1622 "Received data from %s for forwarding to UDP service %s on port %u\n",
1623 GNUNET_i2s (&state->peer),
1624 GNUNET_h2s (&state->specifics.tcp_udp.serv->descriptor),
1625 (unsigned int) ntohs (msg->destination_port));
1626 setup_state_record (state);
1627 if (0 != ntohs (msg->source_port))
1628 state->specifics.tcp_udp.ri.local_address.port = msg->source_port;
1629 send_udp_packet_via_tun (&state->specifics.tcp_udp.ri.remote_address,
1630 &state->specifics.tcp_udp.ri.local_address,
1633 GNUNET_CADET_receive_done (state->channel);
1638 * Process a request via cadet to send a request to a TCP service
1639 * offered by this system.
1641 * @param cls our `struct ChannelState *`
1642 * @param start the actual message
1643 * @return #GNUNET_OK to keep the connection open,
1644 * #GNUNET_SYSERR to close it (signal serious error)
1647 handle_tcp_service (void *cls,
1648 const struct GNUNET_EXIT_TcpServiceStartMessage *start)
1650 struct ChannelState *state = cls;
1651 uint16_t pkt_len = ntohs (start->header.size) - sizeof(struct
1652 GNUNET_EXIT_TcpServiceStartMessage);
1654 if (GNUNET_SYSERR == state->is_dns)
1656 /* channel is UDP/TCP from now on */
1657 state->is_dns = GNUNET_NO;
1659 GNUNET_STATISTICS_update (stats,
1661 "# TCP service creation requests received via cadet"),
1664 GNUNET_STATISTICS_update (stats,
1665 gettext_noop ("# Bytes received from CADET"),
1668 GNUNET_break_op (ntohl (start->reserved) == 0);
1669 /* setup fresh connection */
1670 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1671 "Received data from %s for forwarding to TCP service %s on port %u\n",
1672 GNUNET_i2s (&state->peer),
1673 GNUNET_h2s (&state->specifics.tcp_udp.serv->descriptor),
1674 (unsigned int) ntohs (start->tcp_header.destination_port));
1675 setup_state_record (state);
1676 send_tcp_packet_via_tun (&state->specifics.tcp_udp.ri.remote_address,
1677 &state->specifics.tcp_udp.ri.local_address,
1681 GNUNET_CADET_receive_done (state->channel);
1686 * Check a request to forward TCP data to the Internet via this peer.
1688 * @param cls our `struct ChannelState *`
1689 * @param start the actual message
1690 * @return #GNUNET_OK to keep the connection open,
1691 * #GNUNET_SYSERR to close it (signal serious error)
1694 check_tcp_remote (void *cls,
1695 const struct GNUNET_EXIT_TcpInternetStartMessage *start)
1697 struct ChannelState *state = cls;
1701 GNUNET_break_op (0);
1702 return GNUNET_SYSERR;
1704 if (GNUNET_YES == state->is_dns)
1706 GNUNET_break_op (0);
1707 return GNUNET_SYSERR;
1709 if ((NULL != state->specifics.tcp_udp.serv) ||
1710 (NULL != state->specifics.tcp_udp.heap_node))
1712 GNUNET_break_op (0);
1713 return GNUNET_SYSERR;
1715 if (start->tcp_header.off * 4 < sizeof(struct GNUNET_TUN_TcpHeader))
1717 GNUNET_break_op (0);
1718 return GNUNET_SYSERR;
1725 * Process a request to forward TCP data to the Internet via this peer.
1727 * @param cls our `struct ChannelState *`
1728 * @param start the actual message
1731 handle_tcp_remote (void *cls,
1732 const struct GNUNET_EXIT_TcpInternetStartMessage *start)
1734 struct ChannelState *state = cls;
1735 uint16_t pkt_len = ntohs (start->header.size) - sizeof(struct
1736 GNUNET_EXIT_TcpInternetStartMessage);
1737 const struct in_addr *v4;
1738 const struct in6_addr *v6;
1739 const void *payload;
1742 if (GNUNET_SYSERR == state->is_dns)
1744 /* channel is UDP/TCP from now on */
1745 state->is_dns = GNUNET_NO;
1747 GNUNET_STATISTICS_update (stats,
1748 gettext_noop ("# Bytes received from CADET"),
1749 pkt_len, GNUNET_NO);
1750 GNUNET_STATISTICS_update (stats,
1752 "# TCP IP-exit creation requests received via cadet"),
1754 af = (int) ntohl (start->af);
1755 state->specifics.tcp_udp.ri.remote_address.af = af;
1759 if (pkt_len < sizeof(struct in_addr))
1761 GNUNET_break_op (0);
1766 GNUNET_break_op (0);
1769 v4 = (const struct in_addr*) &start[1];
1771 pkt_len -= sizeof(struct in_addr);
1772 state->specifics.tcp_udp.ri.remote_address.address.ipv4 = *v4;
1776 if (pkt_len < sizeof(struct in6_addr))
1778 GNUNET_break_op (0);
1783 GNUNET_break_op (0);
1786 v6 = (const struct in6_addr*) &start[1];
1788 pkt_len -= sizeof(struct in6_addr);
1789 state->specifics.tcp_udp.ri.remote_address.address.ipv6 = *v6;
1793 GNUNET_break_op (0);
1797 char buf[INET6_ADDRSTRLEN];
1798 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1799 "Received payload from %s for existing TCP stream to %s:%u\n",
1800 GNUNET_i2s (&state->peer),
1802 &state->specifics.tcp_udp.ri.remote_address.address,
1804 (unsigned int) ntohs (start->tcp_header.destination_port));
1806 state->specifics.tcp_udp.ri.remote_address.proto = IPPROTO_TCP;
1807 state->specifics.tcp_udp.ri.remote_address.port = ntohs (
1808 start->tcp_header.destination_port);
1809 setup_state_record (state);
1810 send_tcp_packet_via_tun (&state->specifics.tcp_udp.ri.remote_address,
1811 &state->specifics.tcp_udp.ri.local_address,
1815 GNUNET_CADET_receive_done (state->channel);
1820 * Check a request to forward TCP data on an established
1821 * connection via this peer.
1823 * @param cls our `struct ChannelState *`
1824 * @param message the actual message
1825 * @return #GNUNET_OK to keep the connection open,
1826 * #GNUNET_SYSERR to close it (signal serious error)
1829 check_tcp_data (void *cls,
1830 const struct GNUNET_EXIT_TcpDataMessage *data)
1832 struct ChannelState *state = cls;
1834 if ((NULL == state) ||
1835 (NULL == state->specifics.tcp_udp.heap_node))
1837 /* connection should have been up! */
1838 GNUNET_STATISTICS_update (stats,
1840 "# TCP DATA requests dropped (no session)"),
1842 GNUNET_break_op (0);
1843 return GNUNET_SYSERR;
1845 if (data->tcp_header.off * 4 < sizeof(struct GNUNET_TUN_TcpHeader))
1847 GNUNET_break_op (0);
1848 return GNUNET_SYSERR;
1850 if (GNUNET_YES == state->is_dns)
1852 GNUNET_break_op (0);
1853 return GNUNET_SYSERR;
1860 * Process a request to forward TCP data on an established
1861 * connection via this peer.
1863 * @param cls our `struct ChannelState *`
1864 * @param message the actual message
1867 handle_tcp_data (void *cls,
1868 const struct GNUNET_EXIT_TcpDataMessage *data)
1870 struct ChannelState *state = cls;
1871 uint16_t pkt_len = ntohs (data->header.size) - sizeof(struct
1872 GNUNET_EXIT_TcpDataMessage);
1874 GNUNET_STATISTICS_update (stats,
1875 gettext_noop ("# Bytes received from CADET"),
1876 pkt_len, GNUNET_NO);
1877 GNUNET_STATISTICS_update (stats,
1879 "# TCP data requests received via cadet"),
1881 if (GNUNET_SYSERR == state->is_dns)
1883 /* channel is UDP/TCP from now on */
1884 state->is_dns = GNUNET_NO;
1887 GNUNET_break_op (ntohl (data->reserved) == 0);
1889 char buf[INET6_ADDRSTRLEN];
1890 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1891 "Received additional %u bytes of data from %s for TCP stream to %s:%u\n",
1893 GNUNET_i2s (&state->peer),
1894 inet_ntop (state->specifics.tcp_udp.ri.remote_address.af,
1895 &state->specifics.tcp_udp.ri.remote_address.address,
1897 (unsigned int) state->specifics.tcp_udp.ri.remote_address.port);
1900 send_tcp_packet_via_tun (&state->specifics.tcp_udp.ri.remote_address,
1901 &state->specifics.tcp_udp.ri.local_address,
1904 GNUNET_CADET_receive_done (state->channel);
1909 * Synthesize a plausible ICMP payload for an ICMPv4 error
1910 * response on the given channel.
1912 * @param state channel information
1913 * @param ipp IPv6 header to fill in (ICMP payload)
1914 * @param udp "UDP" header to fill in (ICMP payload); might actually
1915 * also be the first 8 bytes of the TCP header
1918 make_up_icmpv4_payload (struct ChannelState *state,
1919 struct GNUNET_TUN_IPv4Header *ipp,
1920 struct GNUNET_TUN_UdpHeader *udp)
1922 GNUNET_TUN_initialize_ipv4_header (ipp,
1923 state->specifics.tcp_udp.ri.remote_address.
1925 sizeof(struct GNUNET_TUN_TcpHeader),
1926 &state->specifics.tcp_udp.ri.remote_address
1928 &state->specifics.tcp_udp.ri.local_address.
1930 udp->source_port = htons (state->specifics.tcp_udp.ri.remote_address.port);
1931 udp->destination_port = htons (
1932 state->specifics.tcp_udp.ri.local_address.port);
1933 udp->len = htons (0);
1934 udp->crc = htons (0);
1939 * Synthesize a plausible ICMP payload for an ICMPv6 error
1940 * response on the given channel.
1942 * @param state channel information
1943 * @param ipp IPv6 header to fill in (ICMP payload)
1944 * @param udp "UDP" header to fill in (ICMP payload); might actually
1945 * also be the first 8 bytes of the TCP header
1948 make_up_icmpv6_payload (struct ChannelState *state,
1949 struct GNUNET_TUN_IPv6Header *ipp,
1950 struct GNUNET_TUN_UdpHeader *udp)
1952 GNUNET_TUN_initialize_ipv6_header (ipp,
1953 state->specifics.tcp_udp.ri.remote_address.
1955 sizeof(struct GNUNET_TUN_TcpHeader),
1956 &state->specifics.tcp_udp.ri.remote_address
1958 &state->specifics.tcp_udp.ri.local_address.
1960 udp->source_port = htons (state->specifics.tcp_udp.ri.remote_address.port);
1961 udp->destination_port = htons (
1962 state->specifics.tcp_udp.ri.local_address.port);
1963 udp->len = htons (0);
1964 udp->crc = htons (0);
1969 * Check a request to forward ICMP data to the Internet via this peer.
1971 * @param cls our `struct ChannelState *`
1972 * @param msg the actual message
1973 * @return #GNUNET_OK to keep the connection open,
1974 * #GNUNET_SYSERR to close it (signal serious error)
1977 check_icmp_remote (void *cls,
1978 const struct GNUNET_EXIT_IcmpInternetMessage *msg)
1980 struct ChannelState *state = cls;
1982 if (GNUNET_YES == state->is_dns)
1984 GNUNET_break_op (0);
1985 return GNUNET_SYSERR;
1992 * Process a request to forward ICMP data to the Internet via this peer.
1994 * @param cls our `struct ChannelState *`
1995 * @param msg the actual message
1998 handle_icmp_remote (void *cls,
1999 const struct GNUNET_EXIT_IcmpInternetMessage *msg)
2001 struct ChannelState *state = cls;
2002 uint16_t pkt_len = ntohs (msg->header.size) - sizeof(struct
2003 GNUNET_EXIT_IcmpInternetMessage);
2004 const struct in_addr *v4;
2005 const struct in6_addr *v6;
2006 const void *payload;
2007 char buf[sizeof(struct GNUNET_TUN_IPv6Header) + 8] GNUNET_ALIGN;
2010 if (GNUNET_SYSERR == state->is_dns)
2012 /* channel is UDP/TCP from now on */
2013 state->is_dns = GNUNET_NO;
2015 GNUNET_STATISTICS_update (stats,
2016 gettext_noop ("# Bytes received from CADET"),
2017 pkt_len, GNUNET_NO);
2018 GNUNET_STATISTICS_update (stats,
2020 "# ICMP IP-exit requests received via cadet"),
2023 af = (int) ntohl (msg->af);
2024 if ((NULL != state->specifics.tcp_udp.heap_node) &&
2025 (af != state->specifics.tcp_udp.ri.remote_address.af))
2027 /* other peer switched AF on this channel; not allowed */
2028 GNUNET_break_op (0);
2035 if (pkt_len < sizeof(struct in_addr))
2037 GNUNET_break_op (0);
2042 GNUNET_break_op (0);
2045 v4 = (const struct in_addr*) &msg[1];
2047 pkt_len -= sizeof(struct in_addr);
2048 state->specifics.tcp_udp.ri.remote_address.address.ipv4 = *v4;
2049 if (NULL == state->specifics.tcp_udp.heap_node)
2051 state->specifics.tcp_udp.ri.remote_address.af = af;
2052 state->specifics.tcp_udp.ri.remote_address.proto = IPPROTO_ICMP;
2053 setup_state_record (state);
2055 /* check that ICMP type is something we want to support
2056 and possibly make up payload! */
2057 switch (msg->icmp_header.type)
2059 case GNUNET_TUN_ICMPTYPE_ECHO_REPLY:
2060 case GNUNET_TUN_ICMPTYPE_ECHO_REQUEST:
2063 case GNUNET_TUN_ICMPTYPE_DESTINATION_UNREACHABLE:
2064 case GNUNET_TUN_ICMPTYPE_SOURCE_QUENCH:
2065 case GNUNET_TUN_ICMPTYPE_TIME_EXCEEDED:
2068 GNUNET_break_op (0);
2071 /* make up payload */
2073 struct GNUNET_TUN_IPv4Header *ipp = (struct
2074 GNUNET_TUN_IPv4Header *) buf;
2075 struct GNUNET_TUN_UdpHeader *udp = (struct
2076 GNUNET_TUN_UdpHeader *) &ipp[1];
2078 GNUNET_assert (8 == sizeof(struct GNUNET_TUN_UdpHeader));
2079 pkt_len = sizeof(struct GNUNET_TUN_IPv4Header) + 8;
2080 make_up_icmpv4_payload (state,
2088 GNUNET_break_op (0);
2089 GNUNET_STATISTICS_update (stats,
2091 "# ICMPv4 packets dropped (type not allowed)"),
2099 if (pkt_len < sizeof(struct in6_addr))
2101 GNUNET_break_op (0);
2106 GNUNET_break_op (0);
2109 v6 = (const struct in6_addr*) &msg[1];
2111 pkt_len -= sizeof(struct in6_addr);
2112 state->specifics.tcp_udp.ri.remote_address.address.ipv6 = *v6;
2113 if (NULL == state->specifics.tcp_udp.heap_node)
2115 state->specifics.tcp_udp.ri.remote_address.af = af;
2116 state->specifics.tcp_udp.ri.remote_address.proto = IPPROTO_ICMPV6;
2117 setup_state_record (state);
2119 /* check that ICMP type is something we want to support
2120 and possibly make up payload! */
2121 switch (msg->icmp_header.type)
2123 case GNUNET_TUN_ICMPTYPE6_ECHO_REPLY:
2124 case GNUNET_TUN_ICMPTYPE6_ECHO_REQUEST:
2127 case GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE:
2128 case GNUNET_TUN_ICMPTYPE6_PACKET_TOO_BIG:
2129 case GNUNET_TUN_ICMPTYPE6_TIME_EXCEEDED:
2130 case GNUNET_TUN_ICMPTYPE6_PARAMETER_PROBLEM:
2133 GNUNET_break_op (0);
2136 /* make up payload */
2138 struct GNUNET_TUN_IPv6Header *ipp = (struct
2139 GNUNET_TUN_IPv6Header *) buf;
2140 struct GNUNET_TUN_UdpHeader *udp = (struct
2141 GNUNET_TUN_UdpHeader *) &ipp[1];
2143 GNUNET_assert (8 == sizeof(struct GNUNET_TUN_UdpHeader));
2144 pkt_len = sizeof(struct GNUNET_TUN_IPv6Header) + 8;
2145 make_up_icmpv6_payload (state,
2153 GNUNET_break_op (0);
2154 GNUNET_STATISTICS_update (stats,
2156 "# ICMPv6 packets dropped (type not allowed)"),
2165 GNUNET_break_op (0);
2170 char buf[INET6_ADDRSTRLEN];
2171 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2172 "Received ICMP data from %s for forwarding to %s\n",
2173 GNUNET_i2s (&state->peer),
2175 &state->specifics.tcp_udp.ri.remote_address.address,
2178 send_icmp_packet_via_tun (&state->specifics.tcp_udp.ri.remote_address,
2179 &state->specifics.tcp_udp.ri.local_address,
2182 GNUNET_CADET_receive_done (state->channel);
2187 * Setup ICMP payload for ICMP error messages. Called
2188 * for both IPv4 and IPv6 addresses.
2190 * @param state context for creating the IP Packet
2191 * @param buf where to create the payload, has at least
2192 * sizeof (struct GNUNET_TUN_IPv6Header) + 8 bytes
2193 * @return number of bytes of payload we created in buf
2196 make_up_icmp_service_payload (struct ChannelState *state,
2199 switch (state->specifics.tcp_udp.serv->address.af)
2203 struct GNUNET_TUN_IPv4Header *ipv4;
2204 struct GNUNET_TUN_UdpHeader *udp;
2206 ipv4 = (struct GNUNET_TUN_IPv4Header *) buf;
2207 udp = (struct GNUNET_TUN_UdpHeader *) &ipv4[1];
2208 make_up_icmpv4_payload (state,
2211 GNUNET_assert (8 == sizeof(struct GNUNET_TUN_UdpHeader));
2212 return sizeof(struct GNUNET_TUN_IPv4Header) + 8;
2218 struct GNUNET_TUN_IPv6Header *ipv6;
2219 struct GNUNET_TUN_UdpHeader *udp;
2221 ipv6 = (struct GNUNET_TUN_IPv6Header *) buf;
2222 udp = (struct GNUNET_TUN_UdpHeader *) &ipv6[1];
2223 make_up_icmpv6_payload (state,
2226 GNUNET_assert (8 == sizeof(struct GNUNET_TUN_UdpHeader));
2227 return sizeof(struct GNUNET_TUN_IPv6Header) + 8;
2239 * Check a request via cadet to send ICMP data to a service
2240 * offered by this system.
2242 * @param cls our `struct ChannelState *`
2243 * @param msg the actual message
2244 * @return #GNUNET_OK to keep the connection open,
2245 * #GNUNET_SYSERR to close it (signal serious error)
2248 check_icmp_service (void *cls,
2249 const struct GNUNET_EXIT_IcmpServiceMessage *msg)
2251 struct ChannelState *state = cls;
2253 if (GNUNET_YES == state->is_dns)
2255 GNUNET_break_op (0);
2256 return GNUNET_SYSERR;
2258 if (NULL == state->specifics.tcp_udp.serv)
2260 GNUNET_break_op (0);
2261 return GNUNET_SYSERR;
2268 * Process a request via cadet to send ICMP data to a service
2269 * offered by this system.
2271 * @param cls our `struct ChannelState *`
2272 * @param msg the actual message
2275 handle_icmp_service (void *cls,
2276 const struct GNUNET_EXIT_IcmpServiceMessage *msg)
2278 struct ChannelState *state = cls;
2279 uint16_t pkt_len = ntohs (msg->header.size) - sizeof(struct
2280 GNUNET_EXIT_IcmpServiceMessage);
2281 struct GNUNET_TUN_IcmpHeader icmp;
2282 char buf[sizeof(struct GNUNET_TUN_IPv6Header) + 8] GNUNET_ALIGN;
2283 const void *payload;
2285 GNUNET_STATISTICS_update (stats,
2286 gettext_noop ("# Bytes received from CADET"),
2287 pkt_len, GNUNET_NO);
2288 GNUNET_STATISTICS_update (stats,
2290 "# ICMP service requests received via cadet"),
2292 /* check that we got at least a valid header */
2293 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2294 "Received data from %s for forwarding to ICMP service %s\n",
2295 GNUNET_i2s (&state->peer),
2296 GNUNET_h2s (&state->specifics.tcp_udp.serv->descriptor));
2297 icmp = msg->icmp_header;
2299 state->specifics.tcp_udp.ri.remote_address
2300 = state->specifics.tcp_udp.serv->address;
2301 setup_state_record (state);
2303 /* check that ICMP type is something we want to support,
2304 perform ICMP PT if needed ans possibly make up payload */
2308 switch (msg->icmp_header.type)
2310 case GNUNET_TUN_ICMPTYPE_ECHO_REPLY:
2311 if (state->specifics.tcp_udp.serv->address.af == AF_INET6)
2312 icmp.type = GNUNET_TUN_ICMPTYPE6_ECHO_REPLY;
2315 case GNUNET_TUN_ICMPTYPE_ECHO_REQUEST:
2316 if (state->specifics.tcp_udp.serv->address.af == AF_INET6)
2317 icmp.type = GNUNET_TUN_ICMPTYPE6_ECHO_REQUEST;
2320 case GNUNET_TUN_ICMPTYPE_DESTINATION_UNREACHABLE:
2321 if (state->specifics.tcp_udp.serv->address.af == AF_INET6)
2322 icmp.type = GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE;
2325 GNUNET_break_op (0);
2329 pkt_len = make_up_icmp_service_payload (state, buf);
2332 case GNUNET_TUN_ICMPTYPE_TIME_EXCEEDED:
2333 if (state->specifics.tcp_udp.serv->address.af == AF_INET6)
2334 icmp.type = GNUNET_TUN_ICMPTYPE6_TIME_EXCEEDED;
2337 GNUNET_break_op (0);
2341 pkt_len = make_up_icmp_service_payload (state, buf);
2344 case GNUNET_TUN_ICMPTYPE_SOURCE_QUENCH:
2345 if (state->specifics.tcp_udp.serv->address.af == AF_INET6)
2347 GNUNET_STATISTICS_update (stats,
2349 "# ICMPv4 packets dropped (impossible PT to v6)"),
2355 GNUNET_break_op (0);
2359 pkt_len = make_up_icmp_service_payload (state, buf);
2363 GNUNET_break_op (0);
2364 GNUNET_STATISTICS_update (stats,
2366 "# ICMPv4 packets dropped (type not allowed)"),
2370 /* end of AF_INET */
2374 switch (msg->icmp_header.type)
2376 case GNUNET_TUN_ICMPTYPE6_ECHO_REPLY:
2377 if (state->specifics.tcp_udp.serv->address.af == AF_INET)
2378 icmp.type = GNUNET_TUN_ICMPTYPE_ECHO_REPLY;
2381 case GNUNET_TUN_ICMPTYPE6_ECHO_REQUEST:
2382 if (state->specifics.tcp_udp.serv->address.af == AF_INET)
2383 icmp.type = GNUNET_TUN_ICMPTYPE_ECHO_REQUEST;
2386 case GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE:
2387 if (state->specifics.tcp_udp.serv->address.af == AF_INET)
2388 icmp.type = GNUNET_TUN_ICMPTYPE_DESTINATION_UNREACHABLE;
2391 GNUNET_break_op (0);
2395 pkt_len = make_up_icmp_service_payload (state, buf);
2398 case GNUNET_TUN_ICMPTYPE6_TIME_EXCEEDED:
2399 if (state->specifics.tcp_udp.serv->address.af == AF_INET)
2400 icmp.type = GNUNET_TUN_ICMPTYPE_TIME_EXCEEDED;
2403 GNUNET_break_op (0);
2407 pkt_len = make_up_icmp_service_payload (state, buf);
2410 case GNUNET_TUN_ICMPTYPE6_PACKET_TOO_BIG:
2411 case GNUNET_TUN_ICMPTYPE6_PARAMETER_PROBLEM:
2412 if (state->specifics.tcp_udp.serv->address.af == AF_INET)
2414 GNUNET_STATISTICS_update (stats,
2416 "# ICMPv6 packets dropped (impossible PT to v4)"),
2422 GNUNET_break_op (0);
2426 pkt_len = make_up_icmp_service_payload (state, buf);
2430 GNUNET_break_op (0);
2431 GNUNET_STATISTICS_update (stats,
2433 "# ICMPv6 packets dropped (type not allowed)"),
2437 /* end of AF_INET6 */
2441 GNUNET_break_op (0);
2445 send_icmp_packet_via_tun (&state->specifics.tcp_udp.ri.remote_address,
2446 &state->specifics.tcp_udp.ri.local_address,
2450 GNUNET_CADET_receive_done (state->channel);
2455 * Free memory associated with a service record.
2458 * @param key service descriptor
2459 * @param value service record to free
2460 * @return #GNUNET_OK
2463 free_service_record (void *cls,
2464 const struct GNUNET_HashCode *key,
2467 struct LocalService *service = value;
2469 GNUNET_assert (GNUNET_YES ==
2470 GNUNET_CONTAINER_multihashmap_remove (services,
2473 GNUNET_CADET_close_port (service->port);
2474 GNUNET_free_non_null (service->name);
2475 GNUNET_free (service);
2481 * Callback from CADET for new channels.
2483 * @param cls closure
2484 * @param channel new handle to the channel
2485 * @param initiator peer that started the channel
2486 * @return initial channel context for the channel
2489 new_service_channel (void *cls,
2490 struct GNUNET_CADET_Channel *channel,
2491 const struct GNUNET_PeerIdentity *initiator)
2493 struct LocalService *ls = cls;
2494 struct ChannelState *s = GNUNET_new (struct ChannelState);
2496 s->peer = *initiator;
2497 GNUNET_STATISTICS_update (stats,
2498 gettext_noop ("# Inbound CADET channels created"),
2501 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2502 "Received inbound channel from `%s'\n",
2503 GNUNET_i2s (initiator));
2504 s->channel = channel;
2505 s->specifics.tcp_udp.serv = ls;
2506 s->specifics.tcp_udp.ri.remote_address = ls->address;
2512 * Function called by cadet whenever an inbound channel is destroyed.
2513 * Should clean up any associated state.
2515 * @param cls our `struct ChannelState *`
2516 * @param channel connection to the other end (henceforth invalid)
2519 clean_channel (void *cls,
2520 const struct GNUNET_CADET_Channel *channel)
2522 struct ChannelState *s = cls;
2524 LOG (GNUNET_ERROR_TYPE_DEBUG,
2525 "Channel destroyed\n");
2526 if (GNUNET_SYSERR == s->is_dns)
2531 if (GNUNET_YES == s->is_dns)
2533 if (channels[s->specifics.dns.my_id] == s)
2534 channels[s->specifics.dns.my_id] = NULL;
2538 if (NULL != s->specifics.tcp_udp.heap_node)
2540 GNUNET_assert (GNUNET_YES ==
2541 GNUNET_CONTAINER_multihashmap_remove (connections_map,
2542 &s->specifics.tcp_udp
2545 GNUNET_CONTAINER_heap_remove_node (s->specifics.tcp_udp.heap_node);
2546 s->specifics.tcp_udp.heap_node = NULL;
2554 * Given a service descriptor and a destination port, find the
2555 * respective service entry.
2557 * @param proto IPPROTO_TCP or IPPROTO_UDP
2558 * @param name name of the service
2559 * @param destination_port destination port
2560 * @param service service information record to store (service->name will be set).
2563 store_service (int proto,
2565 uint16_t destination_port,
2566 struct LocalService *service)
2568 struct GNUNET_MQ_MessageHandler handlers[] = {
2569 GNUNET_MQ_hd_var_size (icmp_service,
2570 GNUNET_MESSAGE_TYPE_VPN_ICMP_TO_SERVICE,
2571 struct GNUNET_EXIT_IcmpServiceMessage,
2573 GNUNET_MQ_hd_var_size (udp_service,
2574 GNUNET_MESSAGE_TYPE_VPN_UDP_TO_SERVICE,
2575 struct GNUNET_EXIT_UdpServiceMessage,
2577 GNUNET_MQ_hd_var_size (tcp_service,
2578 GNUNET_MESSAGE_TYPE_VPN_TCP_TO_SERVICE_START,
2579 struct GNUNET_EXIT_TcpServiceStartMessage,
2581 GNUNET_MQ_hd_var_size (tcp_data,
2582 GNUNET_MESSAGE_TYPE_VPN_TCP_DATA_TO_EXIT,
2583 struct GNUNET_EXIT_TcpDataMessage,
2585 GNUNET_MQ_handler_end ()
2588 struct GNUNET_HashCode cadet_port;
2590 service->name = GNUNET_strdup (name);
2591 GNUNET_TUN_service_name_to_hash (name,
2592 &service->descriptor);
2593 GNUNET_TUN_compute_service_cadet_port (&service->descriptor,
2596 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2597 "Opening CADET port %s for SERVICE exit %s on port %u\n",
2598 GNUNET_h2s (&cadet_port),
2600 (unsigned int) destination_port);
2601 service->port = GNUNET_CADET_open_port (cadet_handle,
2603 &new_service_channel,
2608 service->is_udp = (IPPROTO_UDP == proto);
2610 GNUNET_CONTAINER_multihashmap_put (services,
2613 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY))
2615 GNUNET_CADET_close_port (service->port);
2616 GNUNET_free_non_null (service->name);
2617 GNUNET_free (service);
2618 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
2619 _ ("Got duplicate service records for `%s:%u'\n"),
2621 (unsigned int) destination_port);
2627 * Send the given packet via the cadet channel.
2629 * @param s channel destination
2630 * @param env message to queue
2633 send_packet_to_cadet_channel (struct ChannelState *s,
2634 struct GNUNET_MQ_Envelope *env)
2636 GNUNET_assert (NULL != s);
2637 GNUNET_STATISTICS_update (stats,
2639 "# Messages transmitted via cadet channels"),
2642 GNUNET_MQ_send (GNUNET_CADET_get_mq (s->channel),
2648 * @brief Handles an ICMP packet received from the helper.
2650 * @param icmp A pointer to the Packet
2651 * @param pktlen number of bytes in @a icmp
2652 * @param af address family (AFINET or AF_INET6)
2653 * @param destination_ip destination IP-address of the IP packet (should
2654 * be our local address)
2655 * @param source_ip original source IP-address of the IP packet (should
2656 * be the original destination address)
2659 icmp_from_helper (const struct GNUNET_TUN_IcmpHeader *icmp,
2662 const void *destination_ip,
2663 const void *source_ip)
2665 struct ChannelState *state;
2666 struct GNUNET_MQ_Envelope *env;
2667 struct GNUNET_EXIT_IcmpToVPNMessage *i2v;
2668 const struct GNUNET_TUN_IPv4Header *ipv4;
2669 const struct GNUNET_TUN_IPv6Header *ipv6;
2670 const struct GNUNET_TUN_UdpHeader *udp;
2671 uint16_t source_port;
2672 uint16_t destination_port;
2676 char sbuf[INET6_ADDRSTRLEN];
2677 char dbuf[INET6_ADDRSTRLEN];
2678 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2679 "Received ICMP packet going from %s to %s\n",
2682 sbuf, sizeof(sbuf)),
2685 dbuf, sizeof(dbuf)));
2688 if (pktlen < sizeof(struct GNUNET_TUN_IcmpHeader))
2695 /* Find out if this is an ICMP packet in response to an existing
2696 TCP/UDP packet and if so, figure out ports / protocol of the
2697 existing session from the IP data in the ICMP payload */
2699 destination_port = 0;
2703 protocol = IPPROTO_ICMP;
2706 case GNUNET_TUN_ICMPTYPE_ECHO_REPLY:
2707 case GNUNET_TUN_ICMPTYPE_ECHO_REQUEST:
2710 case GNUNET_TUN_ICMPTYPE_DESTINATION_UNREACHABLE:
2711 case GNUNET_TUN_ICMPTYPE_SOURCE_QUENCH:
2712 case GNUNET_TUN_ICMPTYPE_TIME_EXCEEDED:
2714 sizeof(struct GNUNET_TUN_IcmpHeader)
2715 + sizeof(struct GNUNET_TUN_IPv4Header) + 8)
2721 ipv4 = (const struct GNUNET_TUN_IPv4Header *) &icmp[1];
2722 protocol = ipv4->protocol;
2723 /* could be TCP or UDP, but both have the ports in the right
2724 place, so that doesn't matter here */
2725 udp = (const struct GNUNET_TUN_UdpHeader *) &ipv4[1];
2726 /* swap ports, as they are from the original message */
2727 destination_port = ntohs (udp->source_port);
2728 source_port = ntohs (udp->destination_port);
2729 /* throw away ICMP payload, won't be useful for the other side anyway */
2730 pktlen = sizeof(struct GNUNET_TUN_IcmpHeader);
2734 GNUNET_STATISTICS_update (stats,
2736 "# ICMPv4 packets dropped (type not allowed)"),
2743 protocol = IPPROTO_ICMPV6;
2746 case GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE:
2747 case GNUNET_TUN_ICMPTYPE6_PACKET_TOO_BIG:
2748 case GNUNET_TUN_ICMPTYPE6_TIME_EXCEEDED:
2749 case GNUNET_TUN_ICMPTYPE6_PARAMETER_PROBLEM:
2751 sizeof(struct GNUNET_TUN_IcmpHeader)
2752 + sizeof(struct GNUNET_TUN_IPv6Header) + 8)
2758 ipv6 = (const struct GNUNET_TUN_IPv6Header *) &icmp[1];
2759 protocol = ipv6->next_header;
2760 /* could be TCP or UDP, but both have the ports in the right
2761 place, so that doesn't matter here */
2762 udp = (const struct GNUNET_TUN_UdpHeader *) &ipv6[1];
2763 /* swap ports, as they are from the original message */
2764 destination_port = ntohs (udp->source_port);
2765 source_port = ntohs (udp->destination_port);
2766 /* throw away ICMP payload, won't be useful for the other side anyway */
2767 pktlen = sizeof(struct GNUNET_TUN_IcmpHeader);
2770 case GNUNET_TUN_ICMPTYPE6_ECHO_REQUEST:
2771 case GNUNET_TUN_ICMPTYPE6_ECHO_REPLY:
2775 GNUNET_STATISTICS_update (stats,
2777 "# ICMPv6 packets dropped (type not allowed)"),
2789 state = get_redirect_state (af,
2798 case IPPROTO_ICMPV6:
2799 state = get_redirect_state (af,
2809 state = get_redirect_state (af,
2819 state = get_redirect_state (af,
2829 GNUNET_STATISTICS_update (stats,
2831 "# ICMP packets dropped (not allowed)"),
2838 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
2840 "ICMP Packet dropped, have no matching connection information\n"));
2843 env = GNUNET_MQ_msg_extra (i2v,
2844 pktlen - sizeof(struct GNUNET_TUN_IcmpHeader),
2845 GNUNET_MESSAGE_TYPE_VPN_ICMP_TO_VPN);
2846 i2v->af = htonl (af);
2847 GNUNET_memcpy (&i2v->icmp_header,
2850 send_packet_to_cadet_channel (state,
2856 * @brief Handles an UDP packet received from the helper.
2858 * @param udp A pointer to the Packet
2859 * @param pktlen number of bytes in 'udp'
2860 * @param af address family (AFINET or AF_INET6)
2861 * @param destination_ip destination IP-address of the IP packet (should
2862 * be our local address)
2863 * @param source_ip original source IP-address of the IP packet (should
2864 * be the original destination address)
2867 udp_from_helper (const struct GNUNET_TUN_UdpHeader *udp,
2870 const void *destination_ip,
2871 const void *source_ip)
2873 struct ChannelState *state;
2874 struct GNUNET_MQ_Envelope *env;
2875 struct GNUNET_EXIT_UdpReplyMessage *urm;
2878 char sbuf[INET6_ADDRSTRLEN];
2879 char dbuf[INET6_ADDRSTRLEN];
2881 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2882 "Received UDP packet going from %s:%u to %s:%u\n",
2885 sbuf, sizeof(sbuf)),
2886 (unsigned int) ntohs (udp->source_port),
2889 dbuf, sizeof(dbuf)),
2890 (unsigned int) ntohs (udp->destination_port));
2893 if (pktlen < sizeof(struct GNUNET_TUN_UdpHeader))
2899 if (pktlen != ntohs (udp->len))
2905 state = get_redirect_state (af,
2908 ntohs (udp->source_port),
2910 ntohs (udp->destination_port),
2914 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
2916 "UDP Packet dropped, have no matching connection information\n"));
2919 env = GNUNET_MQ_msg_extra (urm,
2920 pktlen - sizeof(struct GNUNET_TUN_UdpHeader),
2921 GNUNET_MESSAGE_TYPE_VPN_UDP_REPLY);
2922 urm->source_port = htons (0);
2923 urm->destination_port = htons (0);
2924 GNUNET_memcpy (&urm[1],
2926 pktlen - sizeof(struct GNUNET_TUN_UdpHeader));
2927 send_packet_to_cadet_channel (state,
2933 * @brief Handles a TCP packet received from the helper.
2935 * @param tcp A pointer to the Packet
2936 * @param pktlen the length of the packet, including its TCP header
2937 * @param af address family (AFINET or AF_INET6)
2938 * @param destination_ip destination IP-address of the IP packet (should
2939 * be our local address)
2940 * @param source_ip original source IP-address of the IP packet (should
2941 * be the original destination address)
2944 tcp_from_helper (const struct GNUNET_TUN_TcpHeader *tcp,
2947 const void *destination_ip,
2948 const void *source_ip)
2950 struct ChannelState *state;
2951 char buf[pktlen] GNUNET_ALIGN;
2952 struct GNUNET_TUN_TcpHeader *mtcp;
2953 struct GNUNET_EXIT_TcpDataMessage *tdm;
2954 struct GNUNET_MQ_Envelope *env;
2958 char sbuf[INET6_ADDRSTRLEN];
2959 char dbuf[INET6_ADDRSTRLEN];
2960 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2961 "Received TCP packet with %u bytes going from %s:%u to %s:%u\n",
2962 (unsigned int) (pktlen - sizeof(struct GNUNET_TUN_TcpHeader)),
2965 sbuf, sizeof(sbuf)),
2966 (unsigned int) ntohs (tcp->source_port),
2969 dbuf, sizeof(dbuf)),
2970 (unsigned int) ntohs (tcp->destination_port));
2973 if (pktlen < sizeof(struct GNUNET_TUN_TcpHeader))
2979 state = get_redirect_state (af,
2982 ntohs (tcp->source_port),
2984 ntohs (tcp->destination_port),
2988 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
2990 "TCP Packet dropped, have no matching connection information\n"));
2994 /* mug port numbers and crc to avoid information leakage;
2995 sender will need to lookup the correct values anyway */
2996 GNUNET_memcpy (buf, tcp, pktlen);
2997 mtcp = (struct GNUNET_TUN_TcpHeader *) buf;
2998 mtcp->source_port = 0;
2999 mtcp->destination_port = 0;
3002 mlen = sizeof(struct GNUNET_EXIT_TcpDataMessage) + (pktlen - sizeof(struct
3003 GNUNET_TUN_TcpHeader));
3004 if (mlen >= GNUNET_MAX_MESSAGE_SIZE)
3009 env = GNUNET_MQ_msg_extra (tdm,
3010 pktlen - sizeof(struct GNUNET_TUN_TcpHeader),
3011 GNUNET_MESSAGE_TYPE_VPN_TCP_DATA_TO_VPN);
3012 tdm->reserved = htonl (0);
3013 GNUNET_memcpy (&tdm->tcp_header,
3016 send_packet_to_cadet_channel (state,
3022 * Receive packets from the helper-process
3025 * @param message message received from helper
3028 message_token (void *cls GNUNET_UNUSED,
3029 const struct GNUNET_MessageHeader *message)
3031 const struct GNUNET_TUN_Layer2PacketHeader *pkt_tun;
3034 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3035 "Got %u-byte message of type %u from gnunet-helper-exit\n",
3036 ntohs (message->size),
3037 ntohs (message->type));
3038 GNUNET_STATISTICS_update (stats,
3039 gettext_noop ("# Packets received from TUN"),
3041 if (ntohs (message->type) != GNUNET_MESSAGE_TYPE_VPN_HELPER)
3046 size = ntohs (message->size);
3047 if (size < sizeof(struct GNUNET_TUN_Layer2PacketHeader) + sizeof(struct
3048 GNUNET_MessageHeader))
3053 GNUNET_STATISTICS_update (stats,
3054 gettext_noop ("# Bytes received from TUN"),
3056 pkt_tun = (const struct GNUNET_TUN_Layer2PacketHeader *) &message[1];
3057 size -= sizeof(struct GNUNET_TUN_Layer2PacketHeader) + sizeof(struct
3058 GNUNET_MessageHeader);
3059 switch (ntohs (pkt_tun->proto))
3063 const struct GNUNET_TUN_IPv4Header *pkt4;
3065 if (size < sizeof(struct GNUNET_TUN_IPv4Header))
3067 /* Kernel to blame? */
3071 pkt4 = (const struct GNUNET_TUN_IPv4Header *) &pkt_tun[1];
3072 if (size != ntohs (pkt4->total_length))
3074 /* Kernel to blame? */
3078 if (pkt4->header_length * 4 != sizeof(struct GNUNET_TUN_IPv4Header))
3080 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
3081 _ ("IPv4 packet options received. Ignored.\n"));
3085 size -= sizeof(struct GNUNET_TUN_IPv4Header);
3086 switch (pkt4->protocol)
3089 udp_from_helper ((const struct GNUNET_TUN_UdpHeader *) &pkt4[1], size,
3091 &pkt4->destination_address,
3092 &pkt4->source_address);
3096 tcp_from_helper ((const struct GNUNET_TUN_TcpHeader *) &pkt4[1], size,
3098 &pkt4->destination_address,
3099 &pkt4->source_address);
3103 icmp_from_helper ((const struct GNUNET_TUN_IcmpHeader *) &pkt4[1], size,
3105 &pkt4->destination_address,
3106 &pkt4->source_address);
3110 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
3112 "IPv4 packet with unsupported next header %u received. Ignored.\n"),
3113 (int) pkt4->protocol);
3121 const struct GNUNET_TUN_IPv6Header *pkt6;
3123 if (size < sizeof(struct GNUNET_TUN_IPv6Header))
3125 /* Kernel to blame? */
3129 pkt6 = (struct GNUNET_TUN_IPv6Header *) &pkt_tun[1];
3130 if (size != ntohs (pkt6->payload_length) + sizeof(struct
3131 GNUNET_TUN_IPv6Header))
3133 /* Kernel to blame? */
3137 size -= sizeof(struct GNUNET_TUN_IPv6Header);
3138 switch (pkt6->next_header)
3141 udp_from_helper ((const struct GNUNET_TUN_UdpHeader *) &pkt6[1], size,
3143 &pkt6->destination_address,
3144 &pkt6->source_address);
3148 tcp_from_helper ((const struct GNUNET_TUN_TcpHeader *) &pkt6[1], size,
3150 &pkt6->destination_address,
3151 &pkt6->source_address);
3154 case IPPROTO_ICMPV6:
3155 icmp_from_helper ((const struct GNUNET_TUN_IcmpHeader *) &pkt6[1], size,
3157 &pkt6->destination_address,
3158 &pkt6->source_address);
3162 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
3164 "IPv6 packet with unsupported next header %d received. Ignored.\n"),
3172 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
3173 _ ("Packet from unknown protocol %u received. Ignored.\n"),
3174 ntohs (pkt_tun->proto));
3182 * Callback from CADET for new channels.
3184 * @param cls closure
3185 * @param channel new handle to the channel
3186 * @param initiator peer that started the channel
3187 * @return initial channel context for the channel
3190 new_channel (void *cls,
3191 struct GNUNET_CADET_Channel *channel,
3192 const struct GNUNET_PeerIdentity *initiator)
3194 struct ChannelState *s = GNUNET_new (struct ChannelState);
3196 s->is_dns = GNUNET_SYSERR;
3197 s->peer = *initiator;
3198 GNUNET_STATISTICS_update (stats,
3199 gettext_noop ("# Inbound CADET channels created"),
3202 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3203 "Received inbound channel from `%s'\n",
3204 GNUNET_i2s (initiator));
3205 s->channel = channel;
3211 * Function that frees everything from a hashmap
3215 * @param value value to free
3218 free_iterate (void *cls,
3219 const struct GNUNET_HashCode *hash,
3222 GNUNET_free (value);
3228 * Function scheduled as very last function if the service
3229 * disabled itself because the helper is not installed
3230 * properly. Does nothing, except for keeping the
3231 * service process alive by virtue of being scheduled.
3234 * @param tc scheduler context
3237 dummy_task (void *cls)
3239 /* just terminate */
3244 * Function scheduled as very last function, cleans up after us
3253 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3254 "Exit service is shutting down now\n");
3256 if (NULL != helper_handle)
3258 GNUNET_HELPER_stop (helper_handle, GNUNET_NO);
3259 helper_handle = NULL;
3263 GNUNET_REGEX_announce_cancel (regex4);
3268 GNUNET_REGEX_announce_cancel (regex6);
3271 if (NULL != services)
3273 GNUNET_CONTAINER_multihashmap_iterate (services,
3274 &free_service_record,
3276 GNUNET_CONTAINER_multihashmap_destroy (services);
3278 if (NULL != dns_port)
3280 GNUNET_CADET_close_port (dns_port);
3283 if (NULL != cadet_port4)
3285 GNUNET_CADET_close_port (cadet_port4);
3288 if (NULL != cadet_port6)
3290 GNUNET_CADET_close_port (cadet_port6);
3293 if (NULL != cadet_handle)
3295 GNUNET_CADET_disconnect (cadet_handle);
3296 cadet_handle = NULL;
3298 if (NULL != connections_map)
3300 GNUNET_CONTAINER_multihashmap_iterate (connections_map,
3303 GNUNET_CONTAINER_multihashmap_destroy (connections_map);
3304 connections_map = NULL;
3306 if (NULL != connections_heap)
3308 GNUNET_CONTAINER_heap_destroy (connections_heap);
3309 connections_heap = NULL;
3311 if (NULL != dnsstub)
3313 GNUNET_DNSSTUB_stop (dnsstub);
3316 if (NULL != peer_key)
3318 GNUNET_free (peer_key);
3321 if (NULL != dht_task)
3323 GNUNET_SCHEDULER_cancel (dht_task);
3326 if (NULL != dht_put)
3328 GNUNET_DHT_put_cancel (dht_put);
3333 GNUNET_DHT_disconnect (dht);
3338 GNUNET_STATISTICS_destroy (stats,
3342 for (i = 0; i < 8; i++)
3343 GNUNET_free_non_null (exit_argv[i]);
3348 * Add services to the service map.
3350 * @param proto IPPROTO_TCP or IPPROTO_UDP
3351 * @param cpy copy of the service descriptor (can be mutilated)
3352 * @param name DNS name of the service
3355 add_services (int proto,
3362 struct LocalService *serv;
3366 slen = strlen (name);
3367 GNUNET_assert (slen >= 8);
3368 n = GNUNET_strndup (name, slen - 8 /* remove .gnunet. */);
3370 for (redirect = strtok (cpy, " ;"); redirect != NULL;
3371 redirect = strtok (NULL, " ;"))
3373 if (NULL == (hostname = strstr (redirect, ":")))
3375 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
3377 "Option `%s' for domain `%s' is not formatted correctly!\n"),
3384 if (NULL == (hostport = strstr (hostname, ":")))
3386 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
3388 "Option `%s' for domain `%s' is not formatted correctly!\n"),
3396 int local_port = atoi (redirect);
3397 int remote_port = atoi (hostport);
3399 if (! ((local_port > 0) && (local_port < 65536)))
3401 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
3402 _ ("`%s' is not a valid port number (for domain `%s')!"),
3407 if (! ((remote_port > 0) && (remote_port < 65536)))
3409 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
3410 _ ("`%s' is not a valid port number (for domain `%s')!"),
3416 serv = GNUNET_new (struct LocalService);
3417 serv->address.proto = proto;
3418 serv->address.port = remote_port;
3419 if (0 == strcmp ("localhost4",
3422 const char *ip4addr = exit_argv[5];
3424 serv->address.af = AF_INET;
3425 GNUNET_assert (1 == inet_pton (AF_INET,
3427 &serv->address.address.ipv4));
3429 else if (0 == strcmp ("localhost6",
3432 const char *ip6addr = exit_argv[3];
3434 serv->address.af = AF_INET6;
3435 GNUNET_assert (1 == inet_pton (AF_INET6,
3437 &serv->address.address.ipv6));
3441 struct addrinfo *res;
3444 ret = getaddrinfo (hostname,
3448 if ((0 != ret) || (NULL == res))
3450 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
3452 "No addresses found for hostname `%s' of service `%s'!\n"),
3459 serv->address.af = res->ai_family;
3460 switch (res->ai_family)
3465 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
3467 "Service `%s' configured for IPv4, but IPv4 is disabled!\n"),
3473 serv->address.address.ipv4
3474 = ((struct sockaddr_in *) res->ai_addr)->sin_addr;
3480 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
3482 "Service `%s' configured for IPv4, but IPv4 is disabled!\n"),
3488 serv->address.address.ipv6
3489 = ((struct sockaddr_in6 *) res->ai_addr)->sin6_addr;
3494 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
3496 "No IP addresses found for hostname `%s' of service `%s'!\n"),
3504 store_service (proto,
3514 * Reads the configuration and populates #udp_services and #tcp_services
3517 * @param section name of section in config
3520 read_service_conf (void *cls,
3521 const char *section)
3525 if ((strlen (section) < 8) ||
3526 (0 != strcmp (".gnunet.", section + (strlen (section) - 8))))
3529 GNUNET_CONFIGURATION_get_value_string (cfg,
3534 add_services (IPPROTO_UDP,
3540 GNUNET_CONFIGURATION_get_value_string (cfg,
3545 add_services (IPPROTO_TCP,
3554 * We are running a DNS exit service, advertise it in the
3555 * DHT. This task is run periodically to do the DHT PUT.
3557 * @param cls closure
3560 do_dht_put (void *cls);
3564 * Function called when the DHT PUT operation is complete.
3565 * Schedules the next PUT.
3567 * @param cls closure, NULL
3570 dht_put_cont (void *cls)
3577 * We are running a DNS exit service, advertise it in the
3578 * DHT. This task is run periodically to do the DHT PUT.
3580 * @param cls closure
3583 do_dht_put (void *cls)
3585 struct GNUNET_TIME_Absolute expiration;
3587 dht_task = GNUNET_SCHEDULER_add_delayed (DHT_PUT_FREQUENCY,
3590 expiration = GNUNET_TIME_absolute_ntoh (dns_advertisement.expiration_time);
3591 if (GNUNET_TIME_absolute_get_remaining (expiration).rel_value_us <
3592 GNUNET_TIME_UNIT_HOURS.rel_value_us)
3594 /* refresh advertisement */
3595 expiration = GNUNET_TIME_relative_to_absolute (DNS_ADVERTISEMENT_TIMEOUT);
3596 dns_advertisement.expiration_time = GNUNET_TIME_absolute_hton (expiration);
3597 GNUNET_assert (GNUNET_OK ==
3598 GNUNET_CRYPTO_eddsa_sign (peer_key,
3599 &dns_advertisement.purpose,
3600 &dns_advertisement.signature));
3602 if (NULL != dht_put)
3603 GNUNET_DHT_put_cancel (dht_put);
3604 dht_put = GNUNET_DHT_put (dht,
3606 1 /* replication */,
3608 GNUNET_BLOCK_TYPE_DNS,
3609 sizeof(struct GNUNET_DNS_Advertisement),
3618 * Figure out which IP versions we should support (and which
3619 * are supported by the OS) according to our configuration.
3624 ipv4_exit = GNUNET_CONFIGURATION_get_value_yesno (cfg,
3627 ipv6_exit = GNUNET_CONFIGURATION_get_value_yesno (cfg,
3630 ipv4_enabled = GNUNET_CONFIGURATION_get_value_yesno (cfg,
3633 ipv6_enabled = GNUNET_CONFIGURATION_get_value_yesno (cfg,
3636 if ((ipv4_exit || ipv4_enabled) &&
3637 (GNUNET_OK != GNUNET_NETWORK_test_pf (PF_INET)) )
3639 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
3641 "This system does not support IPv4, will disable IPv4 functions despite them being enabled in the configuration\n"));
3642 ipv4_exit = GNUNET_NO;
3643 ipv4_enabled = GNUNET_NO;
3645 if ((ipv6_exit || ipv6_enabled) &&
3646 (GNUNET_OK != GNUNET_NETWORK_test_pf (PF_INET6)) )
3648 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
3650 "This system does not support IPv6, will disable IPv6 functions despite them being enabled in the configuration\n"));
3651 ipv6_exit = GNUNET_NO;
3652 ipv6_enabled = GNUNET_NO;
3654 if (ipv4_exit && (! ipv4_enabled))
3656 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
3658 "Cannot enable IPv4 exit but disable IPv4 on TUN interface, will use ENABLE_IPv4=YES\n"));
3659 ipv4_enabled = GNUNET_YES;
3661 if (ipv6_exit && (! ipv6_enabled))
3663 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
3665 "Cannot enable IPv6 exit but disable IPv6 on TUN interface, will use ENABLE_IPv6=YES\n"));
3666 ipv6_enabled = GNUNET_YES;
3672 * Helper function to open the CADET port for DNS exits and to
3673 * advertise the DNS exit (if applicable).
3676 advertise_dns_exit ()
3678 struct GNUNET_MQ_MessageHandler handlers[] = {
3679 GNUNET_MQ_hd_var_size (dns_request,
3680 GNUNET_MESSAGE_TYPE_VPN_DNS_TO_INTERNET,
3681 struct DnsResponseMessage,
3683 GNUNET_MQ_handler_end ()
3686 struct GNUNET_HashCode port;
3689 GNUNET_CONFIGURATION_get_value_yesno (cfg,
3693 GNUNET_assert (NULL != (dnsstub = GNUNET_DNSSTUB_start (128)));
3695 /* TODO: support using multiple DNS resolvers */
3697 GNUNET_CONFIGURATION_get_value_string (cfg,
3702 GNUNET_DNSSTUB_add_dns_ip (dnsstub,
3705 GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
3708 _ ("need a valid IPv4 or IPv6 address\n"));
3709 GNUNET_free_non_null (dns_exit);
3713 GNUNET_CRYPTO_hash (GNUNET_APPLICATION_PORT_INTERNET_RESOLVER,
3714 strlen (GNUNET_APPLICATION_PORT_INTERNET_RESOLVER),
3716 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3717 "Opening CADET port %s for DNS exit service\n",
3718 GNUNET_h2s (&port));
3719 dns_port = GNUNET_CADET_open_port (cadet_handle,
3726 /* advertise exit */
3727 dht = GNUNET_DHT_connect (cfg,
3729 peer_key = GNUNET_CRYPTO_eddsa_key_create_from_configuration (cfg);
3730 GNUNET_CRYPTO_eddsa_key_get_public (peer_key,
3731 &dns_advertisement.peer.public_key);
3732 dns_advertisement.purpose.size = htonl (sizeof(struct
3733 GNUNET_DNS_Advertisement)
3735 GNUNET_CRYPTO_EddsaSignature));
3736 dns_advertisement.purpose.purpose = htonl (
3737 GNUNET_SIGNATURE_PURPOSE_DNS_RECORD);
3738 GNUNET_CRYPTO_hash ("dns",
3741 dht_task = GNUNET_SCHEDULER_add_now (&do_dht_put,
3743 GNUNET_free (dns_exit);
3748 * Initialize #exit_argv.
3750 * @return #GNUNET_OK on success, #GNUNET_SYSERR if we should shutdown
3753 setup_exit_helper_args ()
3762 exit_argv[0] = GNUNET_strdup ("exit-gnunet");
3763 if (GNUNET_SYSERR ==
3764 GNUNET_CONFIGURATION_get_value_string (cfg,
3769 GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
3772 return GNUNET_SYSERR;
3774 exit_argv[1] = tun_ifname;
3777 if (GNUNET_SYSERR ==
3778 GNUNET_CONFIGURATION_get_value_string (cfg,
3783 GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
3786 return GNUNET_SYSERR;
3788 exit_argv[2] = exit_ifname;
3792 exit_argv[2] = GNUNET_strdup ("-");
3795 if (GNUNET_YES == ipv6_enabled)
3798 if (((GNUNET_SYSERR ==
3799 GNUNET_CONFIGURATION_get_value_string (cfg,
3803 (1 != inet_pton (AF_INET6,
3807 GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
3810 GNUNET_free_non_null (ipv6addr);
3811 return GNUNET_SYSERR;
3813 exit_argv[3] = ipv6addr;
3814 if (GNUNET_SYSERR ==
3815 GNUNET_CONFIGURATION_get_value_string (cfg,
3820 GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
3823 return GNUNET_SYSERR;
3825 exit_argv[4] = ipv6prefix_s;
3827 GNUNET_CONFIGURATION_get_value_number (cfg,
3831 (ipv6prefix >= 127))
3833 GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
3836 _ ("Must be a number"));
3837 return GNUNET_SYSERR;
3842 /* IPv6 explicitly disabled */
3843 exit_argv[3] = GNUNET_strdup ("-");
3844 exit_argv[4] = GNUNET_strdup ("-");
3846 if (GNUNET_YES == ipv4_enabled)
3849 if (((GNUNET_SYSERR ==
3850 GNUNET_CONFIGURATION_get_value_string (cfg,
3854 (1 != inet_pton (AF_INET,
3858 GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
3861 GNUNET_free_non_null (ipv4addr);
3862 return GNUNET_SYSERR;
3864 exit_argv[5] = ipv4addr;
3866 if (((GNUNET_SYSERR ==
3867 GNUNET_CONFIGURATION_get_value_string (cfg,
3871 (1 != inet_pton (AF_INET,
3875 GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
3878 GNUNET_free_non_null (ipv4mask);
3879 return GNUNET_SYSERR;
3881 exit_argv[6] = ipv4mask;
3885 /* IPv4 explicitly disabled */
3886 exit_argv[5] = GNUNET_strdup ("-");
3887 exit_argv[6] = GNUNET_strdup ("-");
3889 exit_argv[7] = NULL;
3895 * @brief Main function that will be run by the scheduler.
3897 * @param cls closure
3898 * @param args remaining command-line arguments
3899 * @param cfgfile name of the configuration file used (for saving, can be NULL!)
3900 * @param cfg_ configuration
3905 const char *cfgfile,
3906 const struct GNUNET_CONFIGURATION_Handle *cfg_)
3908 struct GNUNET_MQ_MessageHandler handlers[] = {
3909 GNUNET_MQ_hd_var_size (icmp_remote,
3910 GNUNET_MESSAGE_TYPE_VPN_ICMP_TO_INTERNET,
3911 struct GNUNET_EXIT_IcmpInternetMessage,
3913 GNUNET_MQ_hd_var_size (udp_remote,
3914 GNUNET_MESSAGE_TYPE_VPN_UDP_TO_INTERNET,
3915 struct GNUNET_EXIT_UdpInternetMessage,
3917 GNUNET_MQ_hd_var_size (tcp_remote,
3918 GNUNET_MESSAGE_TYPE_VPN_TCP_TO_INTERNET_START,
3919 struct GNUNET_EXIT_TcpInternetStartMessage,
3921 GNUNET_MQ_hd_var_size (tcp_data,
3922 GNUNET_MESSAGE_TYPE_VPN_TCP_DATA_TO_EXIT,
3923 struct GNUNET_EXIT_TcpDataMessage,
3925 GNUNET_MQ_handler_end ()
3927 struct GNUNET_HashCode port;
3931 char *prefixed_regex;
3935 GNUNET_CONFIGURATION_get_value_number (cfg,
3939 max_connections = 1024;
3940 parse_ip_options ();
3941 binary = GNUNET_OS_get_suid_binary_path (cfg, "gnunet-helper-exit");
3942 if ((ipv4_exit) || (ipv6_exit))
3945 GNUNET_OS_check_helper_binary (binary,
3947 "gnunet-vpn - - - 169.1.3.7 255.255.255.0")) // no nat, ipv4 only
3949 GNUNET_free (binary);
3950 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
3952 "`%s' is not SUID or the path is invalid, EXIT will not work\n"),
3953 "gnunet-helper-exit");
3954 GNUNET_SCHEDULER_add_shutdown (&dummy_task,
3960 if (! (ipv4_enabled || ipv6_enabled))
3962 GNUNET_free (binary);
3963 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
3964 _ ("No useful service enabled. Exiting.\n"));
3965 GNUNET_SCHEDULER_shutdown ();
3969 GNUNET_SCHEDULER_add_shutdown (&cleanup,
3971 stats = GNUNET_STATISTICS_create ("exit",
3973 cadet_handle = GNUNET_CADET_connect (cfg);
3974 if (NULL == cadet_handle)
3976 GNUNET_free (binary);
3977 GNUNET_SCHEDULER_shutdown ();
3980 advertise_dns_exit ();
3982 setup_exit_helper_args ())
3984 GNUNET_free (binary);
3985 GNUNET_SCHEDULER_shutdown ();
3989 services = GNUNET_CONTAINER_multihashmap_create (65536,
3991 connections_map = GNUNET_CONTAINER_multihashmap_create (65536,
3993 connections_heap = GNUNET_CONTAINER_heap_create (
3994 GNUNET_CONTAINER_HEAP_ORDER_MIN);
3995 GNUNET_CONFIGURATION_iterate_sections (cfg,
3999 /* Cadet handle acquired, now open ports and announce regular
4000 expressions matching our exit */
4001 if ((GNUNET_YES == ipv4_enabled) &&
4002 (GNUNET_YES == ipv4_exit))
4004 GNUNET_CRYPTO_hash (GNUNET_APPLICATION_PORT_IPV4_GATEWAY,
4005 strlen (GNUNET_APPLICATION_PORT_IPV4_GATEWAY),
4007 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
4008 "Opening CADET port %s for IPv4 gateway service\n",
4009 GNUNET_h2s (&port));
4010 cadet_port4 = GNUNET_CADET_open_port (cadet_handle,
4019 GNUNET_CONFIGURATION_get_value_string (cfg,
4021 "EXIT_RANGE_IPV4_POLICY",
4025 regex = GNUNET_TUN_ipv4policy2regex (policy);
4026 GNUNET_free_non_null (policy);
4029 (void) GNUNET_asprintf (&prefixed_regex,
4031 GNUNET_APPLICATION_TYPE_EXIT_REGEX_PREFIX,
4033 regex4 = GNUNET_REGEX_announce (cfg,
4035 REGEX_REFRESH_FREQUENCY,
4036 REGEX_MAX_PATH_LEN_IPV4);
4037 GNUNET_free (regex);
4038 GNUNET_free (prefixed_regex);
4042 if ((GNUNET_YES == ipv6_enabled) && (GNUNET_YES == ipv6_exit))
4044 GNUNET_CRYPTO_hash (GNUNET_APPLICATION_PORT_IPV6_GATEWAY,
4045 strlen (GNUNET_APPLICATION_PORT_IPV6_GATEWAY),
4047 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
4048 "Opening CADET port %s for IPv6 gateway service\n",
4049 GNUNET_h2s (&port));
4050 cadet_port6 = GNUNET_CADET_open_port (cadet_handle,
4059 GNUNET_CONFIGURATION_get_value_string (cfg,
4061 "EXIT_RANGE_IPV6_POLICY",
4065 regex = GNUNET_TUN_ipv6policy2regex (policy);
4066 GNUNET_free_non_null (policy);
4069 (void) GNUNET_asprintf (&prefixed_regex,
4071 GNUNET_APPLICATION_TYPE_EXIT_REGEX_PREFIX,
4073 regex6 = GNUNET_REGEX_announce (cfg,
4075 REGEX_REFRESH_FREQUENCY,
4076 REGEX_MAX_PATH_LEN_IPV6);
4077 GNUNET_free (regex);
4078 GNUNET_free (prefixed_regex);
4081 helper_handle = GNUNET_HELPER_start (GNUNET_NO,
4087 GNUNET_free (binary);
4094 * @param argc number of arguments from the command line
4095 * @param argv command line arguments
4096 * @return 0 ok, 1 on error
4102 static const struct GNUNET_GETOPT_CommandLineOption options[] = {
4103 GNUNET_GETOPT_OPTION_END
4107 GNUNET_STRINGS_get_utf8_args (argc,
4113 return (GNUNET_OK ==
4114 GNUNET_PROGRAM_run (argc,
4116 "gnunet-daemon-exit",
4118 "Daemon to run to provide an IP exit node for the VPN"),
4121 NULL)) ? global_ret : 1;
4125 /* end of gnunet-daemon-exit.c */