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(GNUNET_TIME_UNIT_MINUTES, 30)
72 * How frequently do we re-announce the DNS exit in the DHT?
74 #define DHT_PUT_FREQUENCY GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_MINUTES, 15)
77 * How long do we typically sign the DNS exit advertisement for?
79 #define DNS_ADVERTISEMENT_TIMEOUT GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_HOURS, 3)
83 * Generic logging shorthand
85 #define LOG(kind, ...) \
86 GNUNET_log_from(kind, "exit", __VA_ARGS__);
90 * Information about an address.
92 struct SocketAddress {
94 * AF_INET or AF_INET6.
99 * Remote address information.
103 * Address, if af is AF_INET.
108 * Address, if af is AF_INET6.
110 struct in6_addr ipv6;
114 * IPPROTO_TCP or IPPROTO_UDP;
119 * Remote port, in host byte order!
126 * This struct is saved into the services-hashmap to represent
127 * a service this peer is specifically offering an exit for
128 * (for a specific domain name).
130 struct LocalService {
132 * Remote address to use for the service.
134 struct SocketAddress address;
137 * Descriptor for the service (CADET port).
139 struct GNUNET_HashCode descriptor;
142 * DNS name of the service.
147 * Open port with CADET.
149 struct GNUNET_CADET_Port *port;
152 * #GNUNET_YES if this is a UDP service, otherwise TCP.
159 * Information we use to track a connection (the classical 6-tuple of
160 * IP-version, protocol, source-IP, destination-IP, source-port and
163 struct RedirectInformation {
165 * Address information for the other party (equivalent of the
166 * arguments one would give to "connect").
168 struct SocketAddress remote_address;
171 * Address information we used locally (AF and proto must match
172 * "remote_address"). Equivalent of the arguments one would give to
175 struct SocketAddress local_address;
178 Note 1: additional information might be added here in the
179 future to support protocols that require special handling,
182 Note 2: we might also sometimes not match on all components
183 of the tuple, to support protocols where things do not always
190 * This struct is saved into #connections_map to allow finding the
191 * right channel given an IP packet from TUN. It is also associated
192 * with the channel's closure so we can find it again for the next
193 * message from the channel.
195 struct ChannelState {
197 * Cadet channel that is used for this connection.
199 struct GNUNET_CADET_Channel *channel;
202 * Who is the other end of this channel.
203 * FIXME is this needed? Only used for debugging messages
205 struct GNUNET_PeerIdentity peer;
208 * #GNUNET_NO if this is a channel for TCP/UDP,
209 * #GNUNET_YES if this is a channel for DNS,
210 * #GNUNET_SYSERR if the channel is not yet initialized.
217 * Heap node for this state in the connections_heap.
219 struct GNUNET_CONTAINER_HeapNode *heap_node;
222 * Key this state has in the #connections_map.
224 struct GNUNET_HashCode state_key;
227 * Associated service record, or NULL for no service.
229 struct LocalService *serv;
232 * Primary redirection information for this connection.
234 struct RedirectInformation ri;
239 * Socket we are using to transmit this request (must match if we receive
242 struct GNUNET_DNSSTUB_RequestSocket *rs;
245 * Original DNS request ID as used by the client.
247 uint16_t original_id;
250 * DNS request ID that we used for forwarding.
259 * Return value from 'main'.
261 static int global_ret;
264 * Handle to our regex announcement for IPv4.
266 static struct GNUNET_REGEX_Announcement *regex4;
269 * Handle to our regex announcement for IPv4.
271 static struct GNUNET_REGEX_Announcement *regex6;
274 * The handle to the configuration used throughout the process
276 static const struct GNUNET_CONFIGURATION_Handle *cfg;
279 * The handle to the helper
281 static struct GNUNET_HELPER_Handle *helper_handle;
284 * Arguments to the exit helper.
286 static char *exit_argv[8];
289 * IPv6 address of our TUN interface.
291 static struct in6_addr exit_ipv6addr;
294 * IPv6 prefix (0..127) from configuration file.
296 static unsigned long long ipv6prefix;
299 * IPv4 address of our TUN interface.
301 static struct in_addr exit_ipv4addr;
304 * IPv4 netmask of our TUN interface.
306 static struct in_addr exit_ipv4mask;
311 static struct GNUNET_STATISTICS_Handle *stats;
314 * The handle to cadet
316 static struct GNUNET_CADET_Handle *cadet_handle;
319 * This hashmaps contains the mapping from peer, service-descriptor,
320 * source-port and destination-port to a struct ChannelState
322 static struct GNUNET_CONTAINER_MultiHashMap *connections_map;
325 * Heap so we can quickly find "old" connections.
327 static struct GNUNET_CONTAINER_Heap *connections_heap;
330 * If there are at least this many connections, old ones will be removed
332 static unsigned long long max_connections;
335 * This hashmaps saves interesting things about the configured services
337 static struct GNUNET_CONTAINER_MultiHashMap *services;
340 * Array of all open DNS requests from channels.
342 static struct ChannelState *channels[UINT16_MAX + 1];
345 * Handle to the DNS Stub resolver.
347 static struct GNUNET_DNSSTUB_Context *dnsstub;
350 * Handle for ongoing DHT PUT operations to advertise exit service.
352 static struct GNUNET_DHT_PutHandle *dht_put;
357 static struct GNUNET_DHT_Handle *dht;
360 * Task for doing DHT PUTs to advertise exit service.
362 static struct GNUNET_SCHEDULER_Task *dht_task;
365 * Advertisement message we put into the DHT to advertise us
368 static struct GNUNET_DNS_Advertisement dns_advertisement;
371 * Key we store the DNS advertismenet under.
373 static struct GNUNET_HashCode dht_put_key;
376 * Private key for this peer.
378 static struct GNUNET_CRYPTO_EddsaPrivateKey *peer_key;
383 static struct GNUNET_CADET_Port *dns_port;
386 * Port for IPv4 exit.
388 static struct GNUNET_CADET_Port *cadet_port4;
391 * Port for IPv6 exit.
393 static struct GNUNET_CADET_Port *cadet_port6;
396 * Are we an IPv4-exit?
398 static int ipv4_exit;
401 * Are we an IPv6-exit?
403 static int ipv6_exit;
406 * Do we support IPv4 at all on the TUN interface?
408 static int ipv4_enabled;
411 * Do we support IPv6 at all on the TUN interface?
413 static int ipv6_enabled;
416 GNUNET_NETWORK_STRUCT_BEGIN
419 * Message with a DNS response.
421 struct DnsResponseMessage {
423 * GNUnet header, of type #GNUNET_MESSAGE_TYPE_VPN_DNS_FROM_INTERNET
425 struct GNUNET_MessageHeader header;
430 struct GNUNET_TUN_DnsHeader dns;
432 /* Followed by more DNS payload */
435 GNUNET_NETWORK_STRUCT_END
439 * Callback called from DNSSTUB resolver when a resolution
443 * @param dns the response itself
444 * @param r number of bytes in @a dns
447 process_dns_result(void *cls,
448 const struct GNUNET_TUN_DnsHeader *dns,
451 struct ChannelState *ts;
452 struct GNUNET_MQ_Envelope *env;
453 struct DnsResponseMessage *resp;
455 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
456 "Processing DNS result from stub resolver\n");
457 GNUNET_assert(NULL == cls);
460 /* Handle case that this is a reply to a request from a CADET DNS channel */
461 ts = channels[dns->id];
464 LOG(GNUNET_ERROR_TYPE_DEBUG,
465 "Got a response from the stub resolver for DNS request received via CADET!\n");
466 channels[dns->id] = NULL;
467 env = GNUNET_MQ_msg_extra(resp,
468 r - sizeof(struct GNUNET_TUN_DnsHeader),
469 GNUNET_MESSAGE_TYPE_VPN_DNS_FROM_INTERNET);
470 GNUNET_memcpy(&resp->dns,
473 resp->dns.id = ts->specifics.dns.original_id;
474 GNUNET_MQ_send(GNUNET_CADET_get_mq(ts->channel),
480 * Check a request via cadet to perform a DNS query.
482 * @param cls our `struct ChannelState *`
483 * @param msg the actual message
484 * @return #GNUNET_OK to keep the connection open,
485 * #GNUNET_SYSERR to close it (signal serious error)
488 check_dns_request(void *cls,
489 const struct DnsResponseMessage *msg)
491 struct ChannelState *ts = cls;
496 return GNUNET_SYSERR;
498 if (GNUNET_NO == ts->is_dns)
501 return GNUNET_SYSERR;
508 * Process a request via cadet to perform a DNS query.
510 * @param cls our `struct ChannelState *`
511 * @param msg the actual message
514 handle_dns_request(void *cls,
515 const struct DnsResponseMessage *msg)
517 struct ChannelState *ts = cls;
518 size_t mlen = ntohs(msg->header.size);
519 size_t dlen = mlen - sizeof(struct GNUNET_MessageHeader);
520 char buf[dlen] GNUNET_ALIGN;
521 struct GNUNET_TUN_DnsHeader *dout;
523 if (GNUNET_SYSERR == ts->is_dns)
525 /* channel is DNS from now on */
526 ts->is_dns = GNUNET_YES;
528 ts->specifics.dns.original_id = msg->dns.id;
529 if (channels[ts->specifics.dns.my_id] == ts)
530 channels[ts->specifics.dns.my_id] = NULL;
531 ts->specifics.dns.my_id = (uint16_t)GNUNET_CRYPTO_random_u32(GNUNET_CRYPTO_QUALITY_WEAK,
533 channels[ts->specifics.dns.my_id] = ts;
537 dout = (struct GNUNET_TUN_DnsHeader *)buf;
538 dout->id = ts->specifics.dns.my_id;
539 ts->specifics.dns.rs = GNUNET_DNSSTUB_resolve(dnsstub,
544 if (NULL == ts->specifics.dns.rs)
549 GNUNET_CADET_receive_done(ts->channel);
554 * Given IP information about a connection, calculate the respective
555 * hash we would use for the #connections_map.
557 * @param hash resulting hash
558 * @param ri information about the connection
561 hash_redirect_info(struct GNUNET_HashCode *hash,
562 const struct RedirectInformation *ri)
568 sizeof(struct GNUNET_HashCode));
569 /* the GNUnet hashmap only uses the first sizeof(unsigned int) of the hash,
570 so we put the IP address in there (and hope for few collisions) */
572 switch (ri->remote_address.af)
576 &ri->remote_address.address.ipv4,
577 sizeof(struct in_addr));
578 off += sizeof(struct in_addr);
583 &ri->remote_address.address.ipv6,
584 sizeof(struct in6_addr));
585 off += sizeof(struct in_addr);
592 &ri->remote_address.port,
594 off += sizeof(uint16_t);
595 switch (ri->local_address.af)
599 &ri->local_address.address.ipv4,
600 sizeof(struct in_addr));
601 off += sizeof(struct in_addr);
606 &ri->local_address.address.ipv6,
607 sizeof(struct in6_addr));
608 off += sizeof(struct in_addr);
615 &ri->local_address.port,
617 off += sizeof(uint16_t);
619 &ri->remote_address.proto,
621 /* off += sizeof (uint8_t); */
626 * Get our connection tracking state. Warns if it does not exists,
627 * refreshes the timestamp if it does exist.
629 * @param af address family
630 * @param protocol IPPROTO_UDP or IPPROTO_TCP
631 * @param destination_ip target IP
632 * @param destination_port target port
633 * @param local_ip local IP
634 * @param local_port local port
635 * @param state_key set to hash's state if non-NULL
636 * @return NULL if we have no tracking information for this tuple
638 static struct ChannelState *
639 get_redirect_state(int af,
641 const void *destination_ip,
642 uint16_t destination_port,
643 const void *local_ip,
645 struct GNUNET_HashCode *state_key)
647 struct RedirectInformation ri;
648 struct GNUNET_HashCode key;
649 struct ChannelState *state;
651 if (((af == AF_INET) && (protocol == IPPROTO_ICMP)) ||
652 ((af == AF_INET6) && (protocol == IPPROTO_ICMPV6)))
655 destination_port = 0;
658 ri.remote_address.af = af;
660 ri.remote_address.address.ipv4 = *((struct in_addr*)destination_ip);
662 ri.remote_address.address.ipv6 = *((struct in6_addr*)destination_ip);
663 ri.remote_address.port = destination_port;
664 ri.remote_address.proto = protocol;
665 ri.local_address.af = af;
667 ri.local_address.address.ipv4 = *((struct in_addr*)local_ip);
669 ri.local_address.address.ipv6 = *((struct in6_addr*)local_ip);
670 ri.local_address.port = local_port;
671 ri.local_address.proto = protocol;
672 hash_redirect_info(&key,
674 if (NULL != state_key)
676 state = GNUNET_CONTAINER_multihashmap_get(connections_map,
680 /* Mark this connection as freshly used */
681 if (NULL == state_key)
682 GNUNET_CONTAINER_heap_update_cost(state->specifics.tcp_udp.heap_node,
683 GNUNET_TIME_absolute_get().abs_value_us);
690 * Check a request via cadet to send a request to a TCP service
691 * offered by this system.
693 * @param cls our `struct ChannelState *`
694 * @param start the actual message
695 * @return #GNUNET_OK to keep the connection open,
696 * #GNUNET_SYSERR to close it (signal serious error)
699 check_tcp_service(void *cls,
700 const struct GNUNET_EXIT_TcpServiceStartMessage *start)
702 struct ChannelState *state = cls;
707 return GNUNET_SYSERR;
709 if (GNUNET_YES == state->is_dns)
712 return GNUNET_SYSERR;
714 if (NULL == state->specifics.tcp_udp.serv)
717 return GNUNET_SYSERR;
719 if (NULL != state->specifics.tcp_udp.heap_node)
722 return GNUNET_SYSERR;
724 if (start->tcp_header.off * 4 < sizeof(struct GNUNET_TUN_TcpHeader))
727 return GNUNET_SYSERR;
734 * Prepare an IPv4 packet for transmission via the TUN interface.
735 * Initializes the IP header and calculates checksums (IP+UDP/TCP).
736 * For UDP, the UDP header will be fully created, whereas for TCP
737 * only the ports and checksum will be filled in. So for TCP,
738 * a skeleton TCP header must be part of the provided payload.
740 * @param payload payload of the packet (starting with UDP payload or
741 * TCP header, depending on protocol)
742 * @param payload_length number of bytes in @a payload
743 * @param protocol IPPROTO_UDP or IPPROTO_TCP
744 * @param tcp_header skeleton of the TCP header, NULL for UDP
745 * @param src_address source address to use (IP and port)
746 * @param dst_address destination address to use (IP and port)
747 * @param pkt4 where to write the assembled packet; must
748 * contain enough space for the IP header, UDP/TCP header
752 prepare_ipv4_packet(const void *payload,
753 size_t payload_length,
755 const struct GNUNET_TUN_TcpHeader *tcp_header,
756 const struct SocketAddress *src_address,
757 const struct SocketAddress *dst_address,
758 struct GNUNET_TUN_IPv4Header *pkt4)
762 len = payload_length;
766 len += sizeof(struct GNUNET_TUN_UdpHeader);
770 len += sizeof(struct GNUNET_TUN_TcpHeader);
771 GNUNET_assert(NULL != tcp_header);
778 if (len + sizeof(struct GNUNET_TUN_IPv4Header) > UINT16_MAX)
784 GNUNET_TUN_initialize_ipv4_header(pkt4,
787 &src_address->address.ipv4,
788 &dst_address->address.ipv4);
793 struct GNUNET_TUN_UdpHeader *pkt4_udp = (struct GNUNET_TUN_UdpHeader *)&pkt4[1];
795 pkt4_udp->source_port = htons(src_address->port);
796 pkt4_udp->destination_port = htons(dst_address->port);
797 pkt4_udp->len = htons((uint16_t)payload_length);
798 GNUNET_TUN_calculate_udp4_checksum(pkt4,
802 GNUNET_memcpy(&pkt4_udp[1],
810 struct GNUNET_TUN_TcpHeader *pkt4_tcp = (struct GNUNET_TUN_TcpHeader *)&pkt4[1];
812 *pkt4_tcp = *tcp_header;
813 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
814 "Sending TCP packet from port %u to port %u\n",
817 pkt4_tcp->source_port = htons(src_address->port);
818 pkt4_tcp->destination_port = htons(dst_address->port);
819 GNUNET_TUN_calculate_tcp4_checksum(pkt4,
823 GNUNET_memcpy(&pkt4_tcp[1],
836 * Prepare an IPv6 packet for transmission via the TUN interface.
837 * Initializes the IP header and calculates checksums (IP+UDP/TCP).
838 * For UDP, the UDP header will be fully created, whereas for TCP
839 * only the ports and checksum will be filled in. So for TCP,
840 * a skeleton TCP header must be part of the provided payload.
842 * @param payload payload of the packet (starting with UDP payload or
843 * TCP header, depending on protocol)
844 * @param payload_length number of bytes in @a payload
845 * @param protocol IPPROTO_UDP or IPPROTO_TCP
846 * @param tcp_header skeleton TCP header data to send, NULL for UDP
847 * @param src_address source address to use (IP and port)
848 * @param dst_address destination address to use (IP and port)
849 * @param pkt6 where to write the assembled packet; must
850 * contain enough space for the IP header, UDP/TCP header
854 prepare_ipv6_packet(const void *payload,
855 size_t payload_length,
857 const struct GNUNET_TUN_TcpHeader *tcp_header,
858 const struct SocketAddress *src_address,
859 const struct SocketAddress *dst_address,
860 struct GNUNET_TUN_IPv6Header *pkt6)
864 len = payload_length;
868 len += sizeof(struct GNUNET_TUN_UdpHeader);
872 len += sizeof(struct GNUNET_TUN_TcpHeader);
879 if (len > UINT16_MAX)
885 GNUNET_TUN_initialize_ipv6_header(pkt6,
888 &src_address->address.ipv6,
889 &dst_address->address.ipv6);
895 struct GNUNET_TUN_UdpHeader *pkt6_udp = (struct GNUNET_TUN_UdpHeader *)&pkt6[1];
897 pkt6_udp->source_port = htons(src_address->port);
898 pkt6_udp->destination_port = htons(dst_address->port);
899 pkt6_udp->len = htons((uint16_t)payload_length);
900 GNUNET_TUN_calculate_udp6_checksum(pkt6,
904 GNUNET_memcpy(&pkt6_udp[1],
912 struct GNUNET_TUN_TcpHeader *pkt6_tcp = (struct GNUNET_TUN_TcpHeader *)&pkt6[1];
914 /* GNUNET_memcpy first here as some TCP header fields are initialized this way! */
915 *pkt6_tcp = *tcp_header;
916 pkt6_tcp->source_port = htons(src_address->port);
917 pkt6_tcp->destination_port = htons(dst_address->port);
918 GNUNET_TUN_calculate_tcp6_checksum(pkt6,
922 GNUNET_memcpy(&pkt6_tcp[1],
936 * Send a TCP packet via the TUN interface.
938 * @param destination_address IP and port to use for the TCP packet's destination
939 * @param source_address IP and port to use for the TCP packet's source
940 * @param tcp_header header template to use
941 * @param payload payload of the TCP packet
942 * @param payload_length number of bytes in @a payload
945 send_tcp_packet_via_tun(const struct SocketAddress *destination_address,
946 const struct SocketAddress *source_address,
947 const struct GNUNET_TUN_TcpHeader *tcp_header,
949 size_t payload_length)
953 GNUNET_STATISTICS_update(stats,
954 gettext_noop("# TCP packets sent via TUN"),
957 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
958 "Sending packet with %u bytes TCP payload via TUN\n",
959 (unsigned int)payload_length);
960 len = sizeof(struct GNUNET_MessageHeader) + sizeof(struct GNUNET_TUN_Layer2PacketHeader);
961 switch (source_address->af)
964 len += sizeof(struct GNUNET_TUN_IPv4Header);
968 len += sizeof(struct GNUNET_TUN_IPv6Header);
975 len += sizeof(struct GNUNET_TUN_TcpHeader);
976 len += payload_length;
977 if (len >= GNUNET_MAX_MESSAGE_SIZE)
983 char buf[len] GNUNET_ALIGN;
984 struct GNUNET_MessageHeader *hdr;
985 struct GNUNET_TUN_Layer2PacketHeader *tun;
987 hdr = (struct GNUNET_MessageHeader *)buf;
988 hdr->type = htons(GNUNET_MESSAGE_TYPE_VPN_HELPER);
989 hdr->size = htons(len);
990 tun = (struct GNUNET_TUN_Layer2PacketHeader*)&hdr[1];
991 tun->flags = htons(0);
992 switch (source_address->af)
996 struct GNUNET_TUN_IPv4Header *ipv4
997 = (struct GNUNET_TUN_IPv4Header*)&tun[1];
999 tun->proto = htons(ETH_P_IPV4);
1000 prepare_ipv4_packet(payload,
1005 destination_address,
1012 struct GNUNET_TUN_IPv6Header *ipv6
1013 = (struct GNUNET_TUN_IPv6Header*)&tun[1];
1015 tun->proto = htons(ETH_P_IPV6);
1016 prepare_ipv6_packet(payload,
1021 destination_address,
1030 if (NULL != helper_handle)
1031 (void)GNUNET_HELPER_send(helper_handle,
1032 (const struct GNUNET_MessageHeader*)buf,
1041 * Send an ICMP packet via the TUN interface.
1043 * @param destination_address IP to use for the ICMP packet's destination
1044 * @param source_address IP to use for the ICMP packet's source
1045 * @param icmp_header ICMP header to send
1046 * @param payload payload of the ICMP packet (does NOT include ICMP header)
1047 * @param payload_length number of bytes of data in @a payload
1050 send_icmp_packet_via_tun(const struct SocketAddress *destination_address,
1051 const struct SocketAddress *source_address,
1052 const struct GNUNET_TUN_IcmpHeader *icmp_header,
1053 const void *payload, size_t payload_length)
1056 struct GNUNET_TUN_IcmpHeader *icmp;
1058 GNUNET_STATISTICS_update(stats,
1059 gettext_noop("# ICMP packets sent via TUN"),
1061 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1062 "Sending packet with %u bytes ICMP payload via TUN\n",
1063 (unsigned int)payload_length);
1064 len = sizeof(struct GNUNET_MessageHeader) + sizeof(struct GNUNET_TUN_Layer2PacketHeader);
1065 switch (destination_address->af)
1068 len += sizeof(struct GNUNET_TUN_IPv4Header);
1072 len += sizeof(struct GNUNET_TUN_IPv6Header);
1079 len += sizeof(struct GNUNET_TUN_IcmpHeader);
1080 len += payload_length;
1081 if (len >= GNUNET_MAX_MESSAGE_SIZE)
1087 char buf[len] GNUNET_ALIGN;
1088 struct GNUNET_MessageHeader *hdr;
1089 struct GNUNET_TUN_Layer2PacketHeader *tun;
1091 hdr = (struct GNUNET_MessageHeader *)buf;
1092 hdr->type = htons(GNUNET_MESSAGE_TYPE_VPN_HELPER);
1093 hdr->size = htons(len);
1094 tun = (struct GNUNET_TUN_Layer2PacketHeader*)&hdr[1];
1095 tun->flags = htons(0);
1096 switch (source_address->af)
1100 struct GNUNET_TUN_IPv4Header * ipv4 = (struct GNUNET_TUN_IPv4Header*)&tun[1];
1102 tun->proto = htons(ETH_P_IPV4);
1103 GNUNET_TUN_initialize_ipv4_header(ipv4,
1105 sizeof(struct GNUNET_TUN_IcmpHeader) + payload_length,
1106 &source_address->address.ipv4,
1107 &destination_address->address.ipv4);
1108 icmp = (struct GNUNET_TUN_IcmpHeader*)&ipv4[1];
1114 struct GNUNET_TUN_IPv6Header * ipv6 = (struct GNUNET_TUN_IPv6Header*)&tun[1];
1116 tun->proto = htons(ETH_P_IPV6);
1117 GNUNET_TUN_initialize_ipv6_header(ipv6,
1119 sizeof(struct GNUNET_TUN_IcmpHeader) + payload_length,
1120 &source_address->address.ipv6,
1121 &destination_address->address.ipv6);
1122 icmp = (struct GNUNET_TUN_IcmpHeader*)&ipv6[1];
1130 *icmp = *icmp_header;
1131 GNUNET_memcpy(&icmp[1],
1134 GNUNET_TUN_calculate_icmp_checksum(icmp,
1137 if (NULL != helper_handle)
1138 (void)GNUNET_HELPER_send(helper_handle,
1139 (const struct GNUNET_MessageHeader*)buf,
1147 * We need to create a (unique) fresh local address (IP+port).
1150 * @param af desired address family
1151 * @param proto desired protocol (IPPROTO_UDP or IPPROTO_TCP)
1152 * @param local_address address to initialize
1155 setup_fresh_address(int af,
1157 struct SocketAddress *local_address)
1159 local_address->af = af;
1160 local_address->proto = (uint8_t)proto;
1161 /* default "local" port range is often 32768--61000,
1162 so we pick a random value in that range */
1163 if (((af == AF_INET) && (proto == IPPROTO_ICMP)) ||
1164 ((af == AF_INET6) && (proto == IPPROTO_ICMPV6)))
1165 local_address->port = 0;
1168 = (uint16_t)32768 + GNUNET_CRYPTO_random_u32(GNUNET_CRYPTO_QUALITY_WEAK,
1174 struct in_addr addr;
1175 struct in_addr mask;
1178 addr = exit_ipv4addr;
1179 mask = exit_ipv4mask;
1180 if (0 == ~mask.s_addr)
1182 /* only one valid IP anyway */
1183 local_address->address.ipv4 = addr;
1186 /* Given 192.168.0.1/255.255.0.0, we want a mask
1187 of '192.168.255.255', thus: */
1188 mask.s_addr = addr.s_addr | ~mask.s_addr;
1189 /* Pick random IPv4 address within the subnet, except 'addr' or 'mask' itself */
1192 rnd.s_addr = GNUNET_CRYPTO_random_u32(GNUNET_CRYPTO_QUALITY_WEAK,
1194 local_address->address.ipv4.s_addr = (addr.s_addr | rnd.s_addr) & mask.s_addr;
1196 while ((local_address->address.ipv4.s_addr == addr.s_addr) ||
1197 (local_address->address.ipv4.s_addr == mask.s_addr));
1203 struct in6_addr addr;
1204 struct in6_addr mask;
1205 struct in6_addr rnd;
1208 addr = exit_ipv6addr;
1209 GNUNET_assert(ipv6prefix < 128);
1210 if (ipv6prefix == 127)
1212 /* only one valid IP anyway */
1213 local_address->address.ipv6 = addr;
1216 /* Given ABCD::/96, we want a mask of 'ABCD::FFFF:FFFF,
1219 for (i = 127; i >= ipv6prefix; i--)
1220 mask.s6_addr[i / 8] |= (1 << (i % 8));
1222 /* Pick random IPv6 address within the subnet, except 'addr' or 'mask' itself */
1225 for (i = 0; i < 16; i++)
1227 rnd.s6_addr[i] = (unsigned char)GNUNET_CRYPTO_random_u32(GNUNET_CRYPTO_QUALITY_WEAK,
1229 local_address->address.ipv6.s6_addr[i]
1230 = (addr.s6_addr[i] | rnd.s6_addr[i]) & mask.s6_addr[i];
1233 while ((0 == GNUNET_memcmp(&local_address->address.ipv6,
1235 (0 == GNUNET_memcmp(&local_address->address.ipv6,
1247 * We are starting a fresh connection (TCP or UDP) and need
1248 * to pick a source port and IP address (within the correct
1249 * range and address family) to associate replies with the
1250 * connection / correct cadet channel. This function generates
1251 * a "fresh" source IP and source port number for a connection
1252 * After picking a good source address, this function sets up
1253 * the state in the 'connections_map' and 'connections_heap'
1254 * to allow finding the state when needed later. The function
1255 * also makes sure that we remain within memory limits by
1256 * cleaning up 'old' states.
1258 * @param state skeleton state to setup a record for; should
1259 * 'state->specifics.tcp_udp.ri.remote_address' filled in so that
1260 * this code can determine which AF/protocol is
1261 * going to be used (the 'channel' should also
1262 * already be set); after calling this function,
1263 * heap_node and the local_address will be
1264 * also initialized (heap_node != NULL can be
1265 * used to test if a state has been fully setup).
1268 setup_state_record(struct ChannelState *state)
1270 struct GNUNET_HashCode key;
1271 struct ChannelState *s;
1273 /* generate fresh, unique address */
1276 if (NULL == state->specifics.tcp_udp.serv)
1277 setup_fresh_address(state->specifics.tcp_udp.ri.remote_address.af,
1278 state->specifics.tcp_udp.ri.remote_address.proto,
1279 &state->specifics.tcp_udp.ri.local_address);
1281 setup_fresh_address(state->specifics.tcp_udp.serv->address.af,
1282 state->specifics.tcp_udp.serv->address.proto,
1283 &state->specifics.tcp_udp.ri.local_address);
1286 get_redirect_state(state->specifics.tcp_udp.ri.remote_address.af,
1287 state->specifics.tcp_udp.ri.remote_address.proto,
1288 &state->specifics.tcp_udp.ri.remote_address.address,
1289 state->specifics.tcp_udp.ri.remote_address.port,
1290 &state->specifics.tcp_udp.ri.local_address.address,
1291 state->specifics.tcp_udp.ri.local_address.port,
1294 char buf[INET6_ADDRSTRLEN];
1295 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1296 "Picked local address %s:%u for new connection\n",
1297 inet_ntop(state->specifics.tcp_udp.ri.local_address.af,
1298 &state->specifics.tcp_udp.ri.local_address.address,
1301 (unsigned int)state->specifics.tcp_udp.ri.local_address.port);
1303 state->specifics.tcp_udp.state_key = key;
1304 GNUNET_assert(GNUNET_OK ==
1305 GNUNET_CONTAINER_multihashmap_put(connections_map,
1307 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
1308 state->specifics.tcp_udp.heap_node
1309 = GNUNET_CONTAINER_heap_insert(connections_heap,
1311 GNUNET_TIME_absolute_get().abs_value_us);
1312 while (GNUNET_CONTAINER_heap_get_size(connections_heap) > max_connections)
1314 s = GNUNET_CONTAINER_heap_remove_root(connections_heap);
1315 GNUNET_assert(state != s);
1316 s->specifics.tcp_udp.heap_node = NULL;
1317 GNUNET_CADET_channel_destroy(s->channel);
1318 GNUNET_assert(GNUNET_OK ==
1319 GNUNET_CONTAINER_multihashmap_remove(connections_map,
1320 &s->specifics.tcp_udp.state_key,
1328 * Send a UDP packet via the TUN interface.
1330 * @param destination_address IP and port to use for the UDP packet's destination
1331 * @param source_address IP and port to use for the UDP packet's source
1332 * @param payload payload of the UDP packet (does NOT include UDP header)
1333 * @param payload_length number of bytes of data in @a payload
1336 send_udp_packet_via_tun(const struct SocketAddress *destination_address,
1337 const struct SocketAddress *source_address,
1338 const void *payload, size_t payload_length)
1342 GNUNET_STATISTICS_update(stats,
1343 gettext_noop("# UDP packets sent via TUN"),
1345 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1346 "Sending packet with %u bytes UDP payload via TUN\n",
1347 (unsigned int)payload_length);
1348 len = sizeof(struct GNUNET_MessageHeader) + sizeof(struct GNUNET_TUN_Layer2PacketHeader);
1349 switch (source_address->af)
1352 len += sizeof(struct GNUNET_TUN_IPv4Header);
1356 len += sizeof(struct GNUNET_TUN_IPv6Header);
1363 len += sizeof(struct GNUNET_TUN_UdpHeader);
1364 len += payload_length;
1365 if (len >= GNUNET_MAX_MESSAGE_SIZE)
1371 char buf[len] GNUNET_ALIGN;
1372 struct GNUNET_MessageHeader *hdr;
1373 struct GNUNET_TUN_Layer2PacketHeader *tun;
1375 hdr = (struct GNUNET_MessageHeader *)buf;
1376 hdr->type = htons(GNUNET_MESSAGE_TYPE_VPN_HELPER);
1377 hdr->size = htons(len);
1378 tun = (struct GNUNET_TUN_Layer2PacketHeader*)&hdr[1];
1379 tun->flags = htons(0);
1380 switch (source_address->af)
1384 struct GNUNET_TUN_IPv4Header * ipv4 = (struct GNUNET_TUN_IPv4Header*)&tun[1];
1386 tun->proto = htons(ETH_P_IPV4);
1387 prepare_ipv4_packet(payload,
1392 destination_address,
1399 struct GNUNET_TUN_IPv6Header * ipv6 = (struct GNUNET_TUN_IPv6Header*)&tun[1];
1401 tun->proto = htons(ETH_P_IPV6);
1402 prepare_ipv6_packet(payload,
1407 destination_address,
1416 if (NULL != helper_handle)
1417 (void)GNUNET_HELPER_send(helper_handle,
1418 (const struct GNUNET_MessageHeader*)buf,
1426 * Check a request to forward UDP data to the Internet via this peer.
1428 * @param cls our `struct ChannelState *`
1429 * @param msg the actual message
1430 * @return #GNUNET_OK to keep the connection open,
1431 * #GNUNET_SYSERR to close it (signal serious error)
1434 check_udp_remote(void *cls,
1435 const struct GNUNET_EXIT_UdpInternetMessage *msg)
1437 struct ChannelState *state = cls;
1439 if (GNUNET_YES == state->is_dns)
1442 return GNUNET_SYSERR;
1449 * Process a request to forward UDP data to the Internet via this peer.
1451 * @param cls our `struct ChannelState *`
1452 * @param msg the actual message
1455 handle_udp_remote(void *cls,
1456 const struct GNUNET_EXIT_UdpInternetMessage *msg)
1458 struct ChannelState *state = cls;
1459 uint16_t pkt_len = ntohs(msg->header.size) - sizeof(struct GNUNET_EXIT_UdpInternetMessage);
1460 const struct in_addr *v4;
1461 const struct in6_addr *v6;
1462 const void *payload;
1465 if (GNUNET_SYSERR == state->is_dns)
1467 /* channel is UDP/TCP from now on */
1468 state->is_dns = GNUNET_NO;
1470 GNUNET_STATISTICS_update(stats,
1471 gettext_noop("# Bytes received from CADET"),
1472 pkt_len, GNUNET_NO);
1473 GNUNET_STATISTICS_update(stats,
1474 gettext_noop("# UDP IP-exit requests received via cadet"),
1476 af = (int)ntohl(msg->af);
1477 state->specifics.tcp_udp.ri.remote_address.af = af;
1481 if (pkt_len < sizeof(struct in_addr))
1491 v4 = (const struct in_addr*)&msg[1];
1493 pkt_len -= sizeof(struct in_addr);
1494 state->specifics.tcp_udp.ri.remote_address.address.ipv4 = *v4;
1498 if (pkt_len < sizeof(struct in6_addr))
1508 v6 = (const struct in6_addr*)&msg[1];
1510 pkt_len -= sizeof(struct in6_addr);
1511 state->specifics.tcp_udp.ri.remote_address.address.ipv6 = *v6;
1519 char buf[INET6_ADDRSTRLEN];
1520 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1521 "Received data from %s for forwarding to UDP %s:%u\n",
1522 GNUNET_i2s(&state->peer),
1524 &state->specifics.tcp_udp.ri.remote_address.address,
1526 (unsigned int)ntohs(msg->destination_port));
1528 state->specifics.tcp_udp.ri.remote_address.proto = IPPROTO_UDP;
1529 state->specifics.tcp_udp.ri.remote_address.port = msg->destination_port;
1530 if (NULL == state->specifics.tcp_udp.heap_node)
1531 setup_state_record(state);
1532 if (0 != ntohs(msg->source_port))
1533 state->specifics.tcp_udp.ri.local_address.port = msg->source_port;
1534 send_udp_packet_via_tun(&state->specifics.tcp_udp.ri.remote_address,
1535 &state->specifics.tcp_udp.ri.local_address,
1538 GNUNET_CADET_receive_done(state->channel);
1543 * Check a request via cadet to send a request to a UDP service
1544 * offered by this system.
1546 * @param cls our `struct ChannelState *`
1547 * @param msg the actual message
1548 * @return #GNUNET_OK to keep the connection open,
1549 * #GNUNET_SYSERR to close it (signal serious error)
1552 check_udp_service(void *cls,
1553 const struct GNUNET_EXIT_UdpServiceMessage *msg)
1555 struct ChannelState *state = cls;
1557 if (NULL == state->specifics.tcp_udp.serv)
1560 return GNUNET_SYSERR;
1567 * Process a request via cadet to send a request to a UDP service
1568 * offered by this system.
1570 * @param cls our `struct ChannelState *`
1571 * @param msg the actual message
1574 handle_udp_service(void *cls,
1575 const struct GNUNET_EXIT_UdpServiceMessage *msg)
1577 struct ChannelState *state = cls;
1578 uint16_t pkt_len = ntohs(msg->header.size) - sizeof(struct GNUNET_EXIT_UdpServiceMessage);
1580 GNUNET_STATISTICS_update(stats,
1581 gettext_noop("# Bytes received from CADET"),
1582 pkt_len, GNUNET_NO);
1583 GNUNET_STATISTICS_update(stats,
1584 gettext_noop("# UDP service requests received via cadet"),
1586 LOG(GNUNET_ERROR_TYPE_DEBUG,
1587 "Received data from %s for forwarding to UDP service %s on port %u\n",
1588 GNUNET_i2s(&state->peer),
1589 GNUNET_h2s(&state->specifics.tcp_udp.serv->descriptor),
1590 (unsigned int)ntohs(msg->destination_port));
1591 setup_state_record(state);
1592 if (0 != ntohs(msg->source_port))
1593 state->specifics.tcp_udp.ri.local_address.port = msg->source_port;
1594 send_udp_packet_via_tun(&state->specifics.tcp_udp.ri.remote_address,
1595 &state->specifics.tcp_udp.ri.local_address,
1598 GNUNET_CADET_receive_done(state->channel);
1603 * Process a request via cadet to send a request to a TCP service
1604 * offered by this system.
1606 * @param cls our `struct ChannelState *`
1607 * @param start the actual message
1608 * @return #GNUNET_OK to keep the connection open,
1609 * #GNUNET_SYSERR to close it (signal serious error)
1612 handle_tcp_service(void *cls,
1613 const struct GNUNET_EXIT_TcpServiceStartMessage *start)
1615 struct ChannelState *state = cls;
1616 uint16_t pkt_len = ntohs(start->header.size) - sizeof(struct GNUNET_EXIT_TcpServiceStartMessage);
1618 if (GNUNET_SYSERR == state->is_dns)
1620 /* channel is UDP/TCP from now on */
1621 state->is_dns = GNUNET_NO;
1623 GNUNET_STATISTICS_update(stats,
1624 gettext_noop("# TCP service creation requests received via cadet"),
1627 GNUNET_STATISTICS_update(stats,
1628 gettext_noop("# Bytes received from CADET"),
1631 GNUNET_break_op(ntohl(start->reserved) == 0);
1632 /* setup fresh connection */
1633 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1634 "Received data from %s for forwarding to TCP service %s on port %u\n",
1635 GNUNET_i2s(&state->peer),
1636 GNUNET_h2s(&state->specifics.tcp_udp.serv->descriptor),
1637 (unsigned int)ntohs(start->tcp_header.destination_port));
1638 setup_state_record(state);
1639 send_tcp_packet_via_tun(&state->specifics.tcp_udp.ri.remote_address,
1640 &state->specifics.tcp_udp.ri.local_address,
1644 GNUNET_CADET_receive_done(state->channel);
1649 * Check a request to forward TCP data to the Internet via this peer.
1651 * @param cls our `struct ChannelState *`
1652 * @param start the actual message
1653 * @return #GNUNET_OK to keep the connection open,
1654 * #GNUNET_SYSERR to close it (signal serious error)
1657 check_tcp_remote(void *cls,
1658 const struct GNUNET_EXIT_TcpInternetStartMessage *start)
1660 struct ChannelState *state = cls;
1665 return GNUNET_SYSERR;
1667 if (GNUNET_YES == state->is_dns)
1670 return GNUNET_SYSERR;
1672 if ((NULL != state->specifics.tcp_udp.serv) ||
1673 (NULL != state->specifics.tcp_udp.heap_node))
1676 return GNUNET_SYSERR;
1678 if (start->tcp_header.off * 4 < sizeof(struct GNUNET_TUN_TcpHeader))
1681 return GNUNET_SYSERR;
1688 * Process a request to forward TCP data to the Internet via this peer.
1690 * @param cls our `struct ChannelState *`
1691 * @param start the actual message
1694 handle_tcp_remote(void *cls,
1695 const struct GNUNET_EXIT_TcpInternetStartMessage *start)
1697 struct ChannelState *state = cls;
1698 uint16_t pkt_len = ntohs(start->header.size) - sizeof(struct GNUNET_EXIT_TcpInternetStartMessage);
1699 const struct in_addr *v4;
1700 const struct in6_addr *v6;
1701 const void *payload;
1704 if (GNUNET_SYSERR == state->is_dns)
1706 /* channel is UDP/TCP from now on */
1707 state->is_dns = GNUNET_NO;
1709 GNUNET_STATISTICS_update(stats,
1710 gettext_noop("# Bytes received from CADET"),
1711 pkt_len, GNUNET_NO);
1712 GNUNET_STATISTICS_update(stats,
1713 gettext_noop("# TCP IP-exit creation requests received via cadet"),
1715 af = (int)ntohl(start->af);
1716 state->specifics.tcp_udp.ri.remote_address.af = af;
1720 if (pkt_len < sizeof(struct in_addr))
1730 v4 = (const struct in_addr*)&start[1];
1732 pkt_len -= sizeof(struct in_addr);
1733 state->specifics.tcp_udp.ri.remote_address.address.ipv4 = *v4;
1737 if (pkt_len < sizeof(struct in6_addr))
1747 v6 = (const struct in6_addr*)&start[1];
1749 pkt_len -= sizeof(struct in6_addr);
1750 state->specifics.tcp_udp.ri.remote_address.address.ipv6 = *v6;
1758 char buf[INET6_ADDRSTRLEN];
1759 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1760 "Received payload from %s for existing TCP stream to %s:%u\n",
1761 GNUNET_i2s(&state->peer),
1763 &state->specifics.tcp_udp.ri.remote_address.address,
1765 (unsigned int)ntohs(start->tcp_header.destination_port));
1767 state->specifics.tcp_udp.ri.remote_address.proto = IPPROTO_TCP;
1768 state->specifics.tcp_udp.ri.remote_address.port = ntohs(start->tcp_header.destination_port);
1769 setup_state_record(state);
1770 send_tcp_packet_via_tun(&state->specifics.tcp_udp.ri.remote_address,
1771 &state->specifics.tcp_udp.ri.local_address,
1775 GNUNET_CADET_receive_done(state->channel);
1780 * Check a request to forward TCP data on an established
1781 * connection via this peer.
1783 * @param cls our `struct ChannelState *`
1784 * @param message the actual message
1785 * @return #GNUNET_OK to keep the connection open,
1786 * #GNUNET_SYSERR to close it (signal serious error)
1789 check_tcp_data(void *cls,
1790 const struct GNUNET_EXIT_TcpDataMessage *data)
1792 struct ChannelState *state = cls;
1794 if ((NULL == state) ||
1795 (NULL == state->specifics.tcp_udp.heap_node))
1797 /* connection should have been up! */
1798 GNUNET_STATISTICS_update(stats,
1799 gettext_noop("# TCP DATA requests dropped (no session)"),
1802 return GNUNET_SYSERR;
1804 if (data->tcp_header.off * 4 < sizeof(struct GNUNET_TUN_TcpHeader))
1807 return GNUNET_SYSERR;
1809 if (GNUNET_YES == state->is_dns)
1812 return GNUNET_SYSERR;
1819 * Process a request to forward TCP data on an established
1820 * connection via this peer.
1822 * @param cls our `struct ChannelState *`
1823 * @param message the actual message
1826 handle_tcp_data(void *cls,
1827 const struct GNUNET_EXIT_TcpDataMessage *data)
1829 struct ChannelState *state = cls;
1830 uint16_t pkt_len = ntohs(data->header.size) - sizeof(struct GNUNET_EXIT_TcpDataMessage);
1832 GNUNET_STATISTICS_update(stats,
1833 gettext_noop("# Bytes received from CADET"),
1834 pkt_len, GNUNET_NO);
1835 GNUNET_STATISTICS_update(stats,
1836 gettext_noop("# TCP data requests received via cadet"),
1838 if (GNUNET_SYSERR == state->is_dns)
1840 /* channel is UDP/TCP from now on */
1841 state->is_dns = GNUNET_NO;
1844 GNUNET_break_op(ntohl(data->reserved) == 0);
1846 char buf[INET6_ADDRSTRLEN];
1847 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1848 "Received additional %u bytes of data from %s for TCP stream to %s:%u\n",
1850 GNUNET_i2s(&state->peer),
1851 inet_ntop(state->specifics.tcp_udp.ri.remote_address.af,
1852 &state->specifics.tcp_udp.ri.remote_address.address,
1854 (unsigned int)state->specifics.tcp_udp.ri.remote_address.port);
1857 send_tcp_packet_via_tun(&state->specifics.tcp_udp.ri.remote_address,
1858 &state->specifics.tcp_udp.ri.local_address,
1861 GNUNET_CADET_receive_done(state->channel);
1866 * Synthesize a plausible ICMP payload for an ICMPv4 error
1867 * response on the given channel.
1869 * @param state channel information
1870 * @param ipp IPv6 header to fill in (ICMP payload)
1871 * @param udp "UDP" header to fill in (ICMP payload); might actually
1872 * also be the first 8 bytes of the TCP header
1875 make_up_icmpv4_payload(struct ChannelState *state,
1876 struct GNUNET_TUN_IPv4Header *ipp,
1877 struct GNUNET_TUN_UdpHeader *udp)
1879 GNUNET_TUN_initialize_ipv4_header(ipp,
1880 state->specifics.tcp_udp.ri.remote_address.proto,
1881 sizeof(struct GNUNET_TUN_TcpHeader),
1882 &state->specifics.tcp_udp.ri.remote_address.address.ipv4,
1883 &state->specifics.tcp_udp.ri.local_address.address.ipv4);
1884 udp->source_port = htons(state->specifics.tcp_udp.ri.remote_address.port);
1885 udp->destination_port = htons(state->specifics.tcp_udp.ri.local_address.port);
1886 udp->len = htons(0);
1887 udp->crc = htons(0);
1892 * Synthesize a plausible ICMP payload for an ICMPv6 error
1893 * response on the given channel.
1895 * @param state channel information
1896 * @param ipp IPv6 header to fill in (ICMP payload)
1897 * @param udp "UDP" header to fill in (ICMP payload); might actually
1898 * also be the first 8 bytes of the TCP header
1901 make_up_icmpv6_payload(struct ChannelState *state,
1902 struct GNUNET_TUN_IPv6Header *ipp,
1903 struct GNUNET_TUN_UdpHeader *udp)
1905 GNUNET_TUN_initialize_ipv6_header(ipp,
1906 state->specifics.tcp_udp.ri.remote_address.proto,
1907 sizeof(struct GNUNET_TUN_TcpHeader),
1908 &state->specifics.tcp_udp.ri.remote_address.address.ipv6,
1909 &state->specifics.tcp_udp.ri.local_address.address.ipv6);
1910 udp->source_port = htons(state->specifics.tcp_udp.ri.remote_address.port);
1911 udp->destination_port = htons(state->specifics.tcp_udp.ri.local_address.port);
1912 udp->len = htons(0);
1913 udp->crc = htons(0);
1918 * Check a request to forward ICMP data to the Internet via this peer.
1920 * @param cls our `struct ChannelState *`
1921 * @param msg the actual message
1922 * @return #GNUNET_OK to keep the connection open,
1923 * #GNUNET_SYSERR to close it (signal serious error)
1926 check_icmp_remote(void *cls,
1927 const struct GNUNET_EXIT_IcmpInternetMessage *msg)
1929 struct ChannelState *state = cls;
1931 if (GNUNET_YES == state->is_dns)
1934 return GNUNET_SYSERR;
1941 * Process a request to forward ICMP data to the Internet via this peer.
1943 * @param cls our `struct ChannelState *`
1944 * @param msg the actual message
1947 handle_icmp_remote(void *cls,
1948 const struct GNUNET_EXIT_IcmpInternetMessage *msg)
1950 struct ChannelState *state = cls;
1951 uint16_t pkt_len = ntohs(msg->header.size) - sizeof(struct GNUNET_EXIT_IcmpInternetMessage);
1952 const struct in_addr *v4;
1953 const struct in6_addr *v6;
1954 const void *payload;
1955 char buf[sizeof(struct GNUNET_TUN_IPv6Header) + 8] GNUNET_ALIGN;
1958 if (GNUNET_SYSERR == state->is_dns)
1960 /* channel is UDP/TCP from now on */
1961 state->is_dns = GNUNET_NO;
1963 GNUNET_STATISTICS_update(stats,
1964 gettext_noop("# Bytes received from CADET"),
1965 pkt_len, GNUNET_NO);
1966 GNUNET_STATISTICS_update(stats,
1967 gettext_noop("# ICMP IP-exit requests received via cadet"),
1970 af = (int)ntohl(msg->af);
1971 if ((NULL != state->specifics.tcp_udp.heap_node) &&
1972 (af != state->specifics.tcp_udp.ri.remote_address.af))
1974 /* other peer switched AF on this channel; not allowed */
1982 if (pkt_len < sizeof(struct in_addr))
1992 v4 = (const struct in_addr*)&msg[1];
1994 pkt_len -= sizeof(struct in_addr);
1995 state->specifics.tcp_udp.ri.remote_address.address.ipv4 = *v4;
1996 if (NULL == state->specifics.tcp_udp.heap_node)
1998 state->specifics.tcp_udp.ri.remote_address.af = af;
1999 state->specifics.tcp_udp.ri.remote_address.proto = IPPROTO_ICMP;
2000 setup_state_record(state);
2002 /* check that ICMP type is something we want to support
2003 and possibly make up payload! */
2004 switch (msg->icmp_header.type)
2006 case GNUNET_TUN_ICMPTYPE_ECHO_REPLY:
2007 case GNUNET_TUN_ICMPTYPE_ECHO_REQUEST:
2010 case GNUNET_TUN_ICMPTYPE_DESTINATION_UNREACHABLE:
2011 case GNUNET_TUN_ICMPTYPE_SOURCE_QUENCH:
2012 case GNUNET_TUN_ICMPTYPE_TIME_EXCEEDED:
2018 /* make up payload */
2020 struct GNUNET_TUN_IPv4Header *ipp = (struct GNUNET_TUN_IPv4Header *)buf;
2021 struct GNUNET_TUN_UdpHeader *udp = (struct GNUNET_TUN_UdpHeader *)&ipp[1];
2023 GNUNET_assert(8 == sizeof(struct GNUNET_TUN_UdpHeader));
2024 pkt_len = sizeof(struct GNUNET_TUN_IPv4Header) + 8;
2025 make_up_icmpv4_payload(state,
2034 GNUNET_STATISTICS_update(stats,
2035 gettext_noop("# ICMPv4 packets dropped (type not allowed)"),
2043 if (pkt_len < sizeof(struct in6_addr))
2053 v6 = (const struct in6_addr*)&msg[1];
2055 pkt_len -= sizeof(struct in6_addr);
2056 state->specifics.tcp_udp.ri.remote_address.address.ipv6 = *v6;
2057 if (NULL == state->specifics.tcp_udp.heap_node)
2059 state->specifics.tcp_udp.ri.remote_address.af = af;
2060 state->specifics.tcp_udp.ri.remote_address.proto = IPPROTO_ICMPV6;
2061 setup_state_record(state);
2063 /* check that ICMP type is something we want to support
2064 and possibly make up payload! */
2065 switch (msg->icmp_header.type)
2067 case GNUNET_TUN_ICMPTYPE6_ECHO_REPLY:
2068 case GNUNET_TUN_ICMPTYPE6_ECHO_REQUEST:
2071 case GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE:
2072 case GNUNET_TUN_ICMPTYPE6_PACKET_TOO_BIG:
2073 case GNUNET_TUN_ICMPTYPE6_TIME_EXCEEDED:
2074 case GNUNET_TUN_ICMPTYPE6_PARAMETER_PROBLEM:
2080 /* make up payload */
2082 struct GNUNET_TUN_IPv6Header *ipp = (struct GNUNET_TUN_IPv6Header *)buf;
2083 struct GNUNET_TUN_UdpHeader *udp = (struct GNUNET_TUN_UdpHeader *)&ipp[1];
2085 GNUNET_assert(8 == sizeof(struct GNUNET_TUN_UdpHeader));
2086 pkt_len = sizeof(struct GNUNET_TUN_IPv6Header) + 8;
2087 make_up_icmpv6_payload(state,
2096 GNUNET_STATISTICS_update(stats,
2097 gettext_noop("# ICMPv6 packets dropped (type not allowed)"),
2111 char buf[INET6_ADDRSTRLEN];
2112 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2113 "Received ICMP data from %s for forwarding to %s\n",
2114 GNUNET_i2s(&state->peer),
2116 &state->specifics.tcp_udp.ri.remote_address.address,
2119 send_icmp_packet_via_tun(&state->specifics.tcp_udp.ri.remote_address,
2120 &state->specifics.tcp_udp.ri.local_address,
2123 GNUNET_CADET_receive_done(state->channel);
2128 * Setup ICMP payload for ICMP error messages. Called
2129 * for both IPv4 and IPv6 addresses.
2131 * @param state context for creating the IP Packet
2132 * @param buf where to create the payload, has at least
2133 * sizeof (struct GNUNET_TUN_IPv6Header) + 8 bytes
2134 * @return number of bytes of payload we created in buf
2137 make_up_icmp_service_payload(struct ChannelState *state,
2140 switch (state->specifics.tcp_udp.serv->address.af)
2144 struct GNUNET_TUN_IPv4Header *ipv4;
2145 struct GNUNET_TUN_UdpHeader *udp;
2147 ipv4 = (struct GNUNET_TUN_IPv4Header *)buf;
2148 udp = (struct GNUNET_TUN_UdpHeader *)&ipv4[1];
2149 make_up_icmpv4_payload(state,
2152 GNUNET_assert(8 == sizeof(struct GNUNET_TUN_UdpHeader));
2153 return sizeof(struct GNUNET_TUN_IPv4Header) + 8;
2159 struct GNUNET_TUN_IPv6Header *ipv6;
2160 struct GNUNET_TUN_UdpHeader *udp;
2162 ipv6 = (struct GNUNET_TUN_IPv6Header *)buf;
2163 udp = (struct GNUNET_TUN_UdpHeader *)&ipv6[1];
2164 make_up_icmpv6_payload(state,
2167 GNUNET_assert(8 == sizeof(struct GNUNET_TUN_UdpHeader));
2168 return sizeof(struct GNUNET_TUN_IPv6Header) + 8;
2180 * Check a request via cadet to send ICMP data to a service
2181 * offered by this system.
2183 * @param cls our `struct ChannelState *`
2184 * @param msg the actual message
2185 * @return #GNUNET_OK to keep the connection open,
2186 * #GNUNET_SYSERR to close it (signal serious error)
2189 check_icmp_service(void *cls,
2190 const struct GNUNET_EXIT_IcmpServiceMessage *msg)
2192 struct ChannelState *state = cls;
2194 if (GNUNET_YES == state->is_dns)
2197 return GNUNET_SYSERR;
2199 if (NULL == state->specifics.tcp_udp.serv)
2202 return GNUNET_SYSERR;
2209 * Process a request via cadet to send ICMP data to a service
2210 * offered by this system.
2212 * @param cls our `struct ChannelState *`
2213 * @param msg the actual message
2216 handle_icmp_service(void *cls,
2217 const struct GNUNET_EXIT_IcmpServiceMessage *msg)
2219 struct ChannelState *state = cls;
2220 uint16_t pkt_len = ntohs(msg->header.size) - sizeof(struct GNUNET_EXIT_IcmpServiceMessage);
2221 struct GNUNET_TUN_IcmpHeader icmp;
2222 char buf[sizeof(struct GNUNET_TUN_IPv6Header) + 8] GNUNET_ALIGN;
2223 const void *payload;
2225 GNUNET_STATISTICS_update(stats,
2226 gettext_noop("# Bytes received from CADET"),
2227 pkt_len, GNUNET_NO);
2228 GNUNET_STATISTICS_update(stats,
2229 gettext_noop("# ICMP service requests received via cadet"),
2231 /* check that we got at least a valid header */
2232 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2233 "Received data from %s for forwarding to ICMP service %s\n",
2234 GNUNET_i2s(&state->peer),
2235 GNUNET_h2s(&state->specifics.tcp_udp.serv->descriptor));
2236 icmp = msg->icmp_header;
2238 state->specifics.tcp_udp.ri.remote_address
2239 = state->specifics.tcp_udp.serv->address;
2240 setup_state_record(state);
2242 /* check that ICMP type is something we want to support,
2243 perform ICMP PT if needed ans possibly make up payload */
2247 switch (msg->icmp_header.type)
2249 case GNUNET_TUN_ICMPTYPE_ECHO_REPLY:
2250 if (state->specifics.tcp_udp.serv->address.af == AF_INET6)
2251 icmp.type = GNUNET_TUN_ICMPTYPE6_ECHO_REPLY;
2254 case GNUNET_TUN_ICMPTYPE_ECHO_REQUEST:
2255 if (state->specifics.tcp_udp.serv->address.af == AF_INET6)
2256 icmp.type = GNUNET_TUN_ICMPTYPE6_ECHO_REQUEST;
2259 case GNUNET_TUN_ICMPTYPE_DESTINATION_UNREACHABLE:
2260 if (state->specifics.tcp_udp.serv->address.af == AF_INET6)
2261 icmp.type = GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE;
2268 pkt_len = make_up_icmp_service_payload(state, buf);
2271 case GNUNET_TUN_ICMPTYPE_TIME_EXCEEDED:
2272 if (state->specifics.tcp_udp.serv->address.af == AF_INET6)
2273 icmp.type = GNUNET_TUN_ICMPTYPE6_TIME_EXCEEDED;
2280 pkt_len = make_up_icmp_service_payload(state, buf);
2283 case GNUNET_TUN_ICMPTYPE_SOURCE_QUENCH:
2284 if (state->specifics.tcp_udp.serv->address.af == AF_INET6)
2286 GNUNET_STATISTICS_update(stats,
2287 gettext_noop("# ICMPv4 packets dropped (impossible PT to v6)"),
2297 pkt_len = make_up_icmp_service_payload(state, buf);
2302 GNUNET_STATISTICS_update(stats,
2303 gettext_noop("# ICMPv4 packets dropped (type not allowed)"),
2307 /* end of AF_INET */
2311 switch (msg->icmp_header.type)
2313 case GNUNET_TUN_ICMPTYPE6_ECHO_REPLY:
2314 if (state->specifics.tcp_udp.serv->address.af == AF_INET)
2315 icmp.type = GNUNET_TUN_ICMPTYPE_ECHO_REPLY;
2318 case GNUNET_TUN_ICMPTYPE6_ECHO_REQUEST:
2319 if (state->specifics.tcp_udp.serv->address.af == AF_INET)
2320 icmp.type = GNUNET_TUN_ICMPTYPE_ECHO_REQUEST;
2323 case GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE:
2324 if (state->specifics.tcp_udp.serv->address.af == AF_INET)
2325 icmp.type = GNUNET_TUN_ICMPTYPE_DESTINATION_UNREACHABLE;
2332 pkt_len = make_up_icmp_service_payload(state, buf);
2335 case GNUNET_TUN_ICMPTYPE6_TIME_EXCEEDED:
2336 if (state->specifics.tcp_udp.serv->address.af == AF_INET)
2337 icmp.type = GNUNET_TUN_ICMPTYPE_TIME_EXCEEDED;
2344 pkt_len = make_up_icmp_service_payload(state, buf);
2347 case GNUNET_TUN_ICMPTYPE6_PACKET_TOO_BIG:
2348 case GNUNET_TUN_ICMPTYPE6_PARAMETER_PROBLEM:
2349 if (state->specifics.tcp_udp.serv->address.af == AF_INET)
2351 GNUNET_STATISTICS_update(stats,
2352 gettext_noop("# ICMPv6 packets dropped (impossible PT to v4)"),
2362 pkt_len = make_up_icmp_service_payload(state, buf);
2367 GNUNET_STATISTICS_update(stats,
2368 gettext_noop("# ICMPv6 packets dropped (type not allowed)"),
2372 /* end of AF_INET6 */
2380 send_icmp_packet_via_tun(&state->specifics.tcp_udp.ri.remote_address,
2381 &state->specifics.tcp_udp.ri.local_address,
2385 GNUNET_CADET_receive_done(state->channel);
2390 * Free memory associated with a service record.
2393 * @param key service descriptor
2394 * @param value service record to free
2395 * @return #GNUNET_OK
2398 free_service_record(void *cls,
2399 const struct GNUNET_HashCode *key,
2402 struct LocalService *service = value;
2404 GNUNET_assert(GNUNET_YES ==
2405 GNUNET_CONTAINER_multihashmap_remove(services,
2408 GNUNET_CADET_close_port(service->port);
2409 GNUNET_free_non_null(service->name);
2410 GNUNET_free(service);
2416 * Callback from CADET for new channels.
2418 * @param cls closure
2419 * @param channel new handle to the channel
2420 * @param initiator peer that started the channel
2421 * @return initial channel context for the channel
2424 new_service_channel(void *cls,
2425 struct GNUNET_CADET_Channel *channel,
2426 const struct GNUNET_PeerIdentity *initiator)
2428 struct LocalService *ls = cls;
2429 struct ChannelState *s = GNUNET_new(struct ChannelState);
2431 s->peer = *initiator;
2432 GNUNET_STATISTICS_update(stats,
2433 gettext_noop("# Inbound CADET channels created"),
2436 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2437 "Received inbound channel from `%s'\n",
2438 GNUNET_i2s(initiator));
2439 s->channel = channel;
2440 s->specifics.tcp_udp.serv = ls;
2441 s->specifics.tcp_udp.ri.remote_address = ls->address;
2447 * Function called by cadet whenever an inbound channel is destroyed.
2448 * Should clean up any associated state.
2450 * @param cls our `struct ChannelState *`
2451 * @param channel connection to the other end (henceforth invalid)
2454 clean_channel(void *cls,
2455 const struct GNUNET_CADET_Channel *channel)
2457 struct ChannelState *s = cls;
2459 LOG(GNUNET_ERROR_TYPE_DEBUG,
2460 "Channel destroyed\n");
2461 if (GNUNET_SYSERR == s->is_dns)
2466 if (GNUNET_YES == s->is_dns)
2468 if (channels[s->specifics.dns.my_id] == s)
2469 channels[s->specifics.dns.my_id] = NULL;
2473 if (NULL != s->specifics.tcp_udp.heap_node)
2475 GNUNET_assert(GNUNET_YES ==
2476 GNUNET_CONTAINER_multihashmap_remove(connections_map,
2477 &s->specifics.tcp_udp.state_key,
2479 GNUNET_CONTAINER_heap_remove_node(s->specifics.tcp_udp.heap_node);
2480 s->specifics.tcp_udp.heap_node = NULL;
2488 * Given a service descriptor and a destination port, find the
2489 * respective service entry.
2491 * @param proto IPPROTO_TCP or IPPROTO_UDP
2492 * @param name name of the service
2493 * @param destination_port destination port
2494 * @param service service information record to store (service->name will be set).
2497 store_service(int proto,
2499 uint16_t destination_port,
2500 struct LocalService *service)
2502 struct GNUNET_MQ_MessageHandler handlers[] = {
2503 GNUNET_MQ_hd_var_size(icmp_service,
2504 GNUNET_MESSAGE_TYPE_VPN_ICMP_TO_SERVICE,
2505 struct GNUNET_EXIT_IcmpServiceMessage,
2507 GNUNET_MQ_hd_var_size(udp_service,
2508 GNUNET_MESSAGE_TYPE_VPN_UDP_TO_SERVICE,
2509 struct GNUNET_EXIT_UdpServiceMessage,
2511 GNUNET_MQ_hd_var_size(tcp_service,
2512 GNUNET_MESSAGE_TYPE_VPN_TCP_TO_SERVICE_START,
2513 struct GNUNET_EXIT_TcpServiceStartMessage,
2515 GNUNET_MQ_hd_var_size(tcp_data,
2516 GNUNET_MESSAGE_TYPE_VPN_TCP_DATA_TO_EXIT,
2517 struct GNUNET_EXIT_TcpDataMessage,
2519 GNUNET_MQ_handler_end()
2522 struct GNUNET_HashCode cadet_port;
2524 service->name = GNUNET_strdup(name);
2525 GNUNET_TUN_service_name_to_hash(name,
2526 &service->descriptor);
2527 GNUNET_TUN_compute_service_cadet_port(&service->descriptor,
2530 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2531 "Opening CADET port %s for SERVICE exit %s on port %u\n",
2532 GNUNET_h2s(&cadet_port),
2534 (unsigned int)destination_port);
2535 service->port = GNUNET_CADET_open_port(cadet_handle,
2537 &new_service_channel,
2542 service->is_udp = (IPPROTO_UDP == proto);
2544 GNUNET_CONTAINER_multihashmap_put(services,
2547 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY))
2549 GNUNET_CADET_close_port(service->port);
2550 GNUNET_free_non_null(service->name);
2551 GNUNET_free(service);
2552 GNUNET_log(GNUNET_ERROR_TYPE_WARNING,
2553 _("Got duplicate service records for `%s:%u'\n"),
2555 (unsigned int)destination_port);
2561 * Send the given packet via the cadet channel.
2563 * @param s channel destination
2564 * @param env message to queue
2567 send_packet_to_cadet_channel(struct ChannelState *s,
2568 struct GNUNET_MQ_Envelope *env)
2570 GNUNET_assert(NULL != s);
2571 GNUNET_STATISTICS_update(stats,
2572 gettext_noop("# Messages transmitted via cadet channels"),
2575 GNUNET_MQ_send(GNUNET_CADET_get_mq(s->channel),
2581 * @brief Handles an ICMP packet received from the helper.
2583 * @param icmp A pointer to the Packet
2584 * @param pktlen number of bytes in @a icmp
2585 * @param af address family (AFINET or AF_INET6)
2586 * @param destination_ip destination IP-address of the IP packet (should
2587 * be our local address)
2588 * @param source_ip original source IP-address of the IP packet (should
2589 * be the original destination address)
2592 icmp_from_helper(const struct GNUNET_TUN_IcmpHeader *icmp,
2595 const void *destination_ip,
2596 const void *source_ip)
2598 struct ChannelState *state;
2599 struct GNUNET_MQ_Envelope *env;
2600 struct GNUNET_EXIT_IcmpToVPNMessage *i2v;
2601 const struct GNUNET_TUN_IPv4Header *ipv4;
2602 const struct GNUNET_TUN_IPv6Header *ipv6;
2603 const struct GNUNET_TUN_UdpHeader *udp;
2604 uint16_t source_port;
2605 uint16_t destination_port;
2609 char sbuf[INET6_ADDRSTRLEN];
2610 char dbuf[INET6_ADDRSTRLEN];
2611 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2612 "Received ICMP packet going from %s to %s\n",
2615 sbuf, sizeof(sbuf)),
2618 dbuf, sizeof(dbuf)));
2621 if (pktlen < sizeof(struct GNUNET_TUN_IcmpHeader))
2628 /* Find out if this is an ICMP packet in response to an existing
2629 TCP/UDP packet and if so, figure out ports / protocol of the
2630 existing session from the IP data in the ICMP payload */
2632 destination_port = 0;
2636 protocol = IPPROTO_ICMP;
2639 case GNUNET_TUN_ICMPTYPE_ECHO_REPLY:
2640 case GNUNET_TUN_ICMPTYPE_ECHO_REQUEST:
2643 case GNUNET_TUN_ICMPTYPE_DESTINATION_UNREACHABLE:
2644 case GNUNET_TUN_ICMPTYPE_SOURCE_QUENCH:
2645 case GNUNET_TUN_ICMPTYPE_TIME_EXCEEDED:
2647 sizeof(struct GNUNET_TUN_IcmpHeader) +
2648 sizeof(struct GNUNET_TUN_IPv4Header) + 8)
2654 ipv4 = (const struct GNUNET_TUN_IPv4Header *)&icmp[1];
2655 protocol = ipv4->protocol;
2656 /* could be TCP or UDP, but both have the ports in the right
2657 place, so that doesn't matter here */
2658 udp = (const struct GNUNET_TUN_UdpHeader *)&ipv4[1];
2659 /* swap ports, as they are from the original message */
2660 destination_port = ntohs(udp->source_port);
2661 source_port = ntohs(udp->destination_port);
2662 /* throw away ICMP payload, won't be useful for the other side anyway */
2663 pktlen = sizeof(struct GNUNET_TUN_IcmpHeader);
2667 GNUNET_STATISTICS_update(stats,
2668 gettext_noop("# ICMPv4 packets dropped (type not allowed)"),
2675 protocol = IPPROTO_ICMPV6;
2678 case GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE:
2679 case GNUNET_TUN_ICMPTYPE6_PACKET_TOO_BIG:
2680 case GNUNET_TUN_ICMPTYPE6_TIME_EXCEEDED:
2681 case GNUNET_TUN_ICMPTYPE6_PARAMETER_PROBLEM:
2683 sizeof(struct GNUNET_TUN_IcmpHeader) +
2684 sizeof(struct GNUNET_TUN_IPv6Header) + 8)
2690 ipv6 = (const struct GNUNET_TUN_IPv6Header *)&icmp[1];
2691 protocol = ipv6->next_header;
2692 /* could be TCP or UDP, but both have the ports in the right
2693 place, so that doesn't matter here */
2694 udp = (const struct GNUNET_TUN_UdpHeader *)&ipv6[1];
2695 /* swap ports, as they are from the original message */
2696 destination_port = ntohs(udp->source_port);
2697 source_port = ntohs(udp->destination_port);
2698 /* throw away ICMP payload, won't be useful for the other side anyway */
2699 pktlen = sizeof(struct GNUNET_TUN_IcmpHeader);
2702 case GNUNET_TUN_ICMPTYPE6_ECHO_REQUEST:
2703 case GNUNET_TUN_ICMPTYPE6_ECHO_REPLY:
2707 GNUNET_STATISTICS_update(stats,
2708 gettext_noop("# ICMPv6 packets dropped (type not allowed)"),
2720 state = get_redirect_state(af,
2729 case IPPROTO_ICMPV6:
2730 state = get_redirect_state(af,
2740 state = get_redirect_state(af,
2750 state = get_redirect_state(af,
2760 GNUNET_STATISTICS_update(stats,
2761 gettext_noop("# ICMP packets dropped (not allowed)"),
2768 GNUNET_log(GNUNET_ERROR_TYPE_INFO,
2769 _("ICMP Packet dropped, have no matching connection information\n"));
2772 env = GNUNET_MQ_msg_extra(i2v,
2773 pktlen - sizeof(struct GNUNET_TUN_IcmpHeader),
2774 GNUNET_MESSAGE_TYPE_VPN_ICMP_TO_VPN);
2775 i2v->af = htonl(af);
2776 GNUNET_memcpy(&i2v->icmp_header,
2779 send_packet_to_cadet_channel(state,
2785 * @brief Handles an UDP packet received from the helper.
2787 * @param udp A pointer to the Packet
2788 * @param pktlen number of bytes in 'udp'
2789 * @param af address family (AFINET or AF_INET6)
2790 * @param destination_ip destination IP-address of the IP packet (should
2791 * be our local address)
2792 * @param source_ip original source IP-address of the IP packet (should
2793 * be the original destination address)
2796 udp_from_helper(const struct GNUNET_TUN_UdpHeader *udp,
2799 const void *destination_ip,
2800 const void *source_ip)
2802 struct ChannelState *state;
2803 struct GNUNET_MQ_Envelope *env;
2804 struct GNUNET_EXIT_UdpReplyMessage *urm;
2807 char sbuf[INET6_ADDRSTRLEN];
2808 char dbuf[INET6_ADDRSTRLEN];
2810 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2811 "Received UDP packet going from %s:%u to %s:%u\n",
2814 sbuf, sizeof(sbuf)),
2815 (unsigned int)ntohs(udp->source_port),
2818 dbuf, sizeof(dbuf)),
2819 (unsigned int)ntohs(udp->destination_port));
2822 if (pktlen < sizeof(struct GNUNET_TUN_UdpHeader))
2828 if (pktlen != ntohs(udp->len))
2834 state = get_redirect_state(af,
2837 ntohs(udp->source_port),
2839 ntohs(udp->destination_port),
2843 GNUNET_log(GNUNET_ERROR_TYPE_INFO,
2844 _("UDP Packet dropped, have no matching connection information\n"));
2847 env = GNUNET_MQ_msg_extra(urm,
2848 pktlen - sizeof(struct GNUNET_TUN_UdpHeader),
2849 GNUNET_MESSAGE_TYPE_VPN_UDP_REPLY);
2850 urm->source_port = htons(0);
2851 urm->destination_port = htons(0);
2852 GNUNET_memcpy(&urm[1],
2854 pktlen - sizeof(struct GNUNET_TUN_UdpHeader));
2855 send_packet_to_cadet_channel(state,
2861 * @brief Handles a TCP packet received from the helper.
2863 * @param tcp A pointer to the Packet
2864 * @param pktlen the length of the packet, including its TCP header
2865 * @param af address family (AFINET or AF_INET6)
2866 * @param destination_ip destination IP-address of the IP packet (should
2867 * be our local address)
2868 * @param source_ip original source IP-address of the IP packet (should
2869 * be the original destination address)
2872 tcp_from_helper(const struct GNUNET_TUN_TcpHeader *tcp,
2875 const void *destination_ip,
2876 const void *source_ip)
2878 struct ChannelState *state;
2879 char buf[pktlen] GNUNET_ALIGN;
2880 struct GNUNET_TUN_TcpHeader *mtcp;
2881 struct GNUNET_EXIT_TcpDataMessage *tdm;
2882 struct GNUNET_MQ_Envelope *env;
2886 char sbuf[INET6_ADDRSTRLEN];
2887 char dbuf[INET6_ADDRSTRLEN];
2888 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2889 "Received TCP packet with %u bytes going from %s:%u to %s:%u\n",
2890 (unsigned int)(pktlen - sizeof(struct GNUNET_TUN_TcpHeader)),
2893 sbuf, sizeof(sbuf)),
2894 (unsigned int)ntohs(tcp->source_port),
2897 dbuf, sizeof(dbuf)),
2898 (unsigned int)ntohs(tcp->destination_port));
2901 if (pktlen < sizeof(struct GNUNET_TUN_TcpHeader))
2907 state = get_redirect_state(af,
2910 ntohs(tcp->source_port),
2912 ntohs(tcp->destination_port),
2916 GNUNET_log(GNUNET_ERROR_TYPE_INFO,
2917 _("TCP Packet dropped, have no matching connection information\n"));
2921 /* mug port numbers and crc to avoid information leakage;
2922 sender will need to lookup the correct values anyway */
2923 GNUNET_memcpy(buf, tcp, pktlen);
2924 mtcp = (struct GNUNET_TUN_TcpHeader *)buf;
2925 mtcp->source_port = 0;
2926 mtcp->destination_port = 0;
2929 mlen = sizeof(struct GNUNET_EXIT_TcpDataMessage) + (pktlen - sizeof(struct GNUNET_TUN_TcpHeader));
2930 if (mlen >= GNUNET_MAX_MESSAGE_SIZE)
2935 env = GNUNET_MQ_msg_extra(tdm,
2936 pktlen - sizeof(struct GNUNET_TUN_TcpHeader),
2937 GNUNET_MESSAGE_TYPE_VPN_TCP_DATA_TO_VPN);
2938 tdm->reserved = htonl(0);
2939 GNUNET_memcpy(&tdm->tcp_header,
2942 send_packet_to_cadet_channel(state,
2948 * Receive packets from the helper-process
2951 * @param message message received from helper
2954 message_token(void *cls GNUNET_UNUSED,
2955 const struct GNUNET_MessageHeader *message)
2957 const struct GNUNET_TUN_Layer2PacketHeader *pkt_tun;
2960 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2961 "Got %u-byte message of type %u from gnunet-helper-exit\n",
2962 ntohs(message->size),
2963 ntohs(message->type));
2964 GNUNET_STATISTICS_update(stats,
2965 gettext_noop("# Packets received from TUN"),
2967 if (ntohs(message->type) != GNUNET_MESSAGE_TYPE_VPN_HELPER)
2972 size = ntohs(message->size);
2973 if (size < sizeof(struct GNUNET_TUN_Layer2PacketHeader) + sizeof(struct GNUNET_MessageHeader))
2978 GNUNET_STATISTICS_update(stats,
2979 gettext_noop("# Bytes received from TUN"),
2981 pkt_tun = (const struct GNUNET_TUN_Layer2PacketHeader *)&message[1];
2982 size -= sizeof(struct GNUNET_TUN_Layer2PacketHeader) + sizeof(struct GNUNET_MessageHeader);
2983 switch (ntohs(pkt_tun->proto))
2987 const struct GNUNET_TUN_IPv4Header *pkt4;
2989 if (size < sizeof(struct GNUNET_TUN_IPv4Header))
2991 /* Kernel to blame? */
2995 pkt4 = (const struct GNUNET_TUN_IPv4Header *)&pkt_tun[1];
2996 if (size != ntohs(pkt4->total_length))
2998 /* Kernel to blame? */
3002 if (pkt4->header_length * 4 != sizeof(struct GNUNET_TUN_IPv4Header))
3004 GNUNET_log(GNUNET_ERROR_TYPE_WARNING,
3005 _("IPv4 packet options received. Ignored.\n"));
3009 size -= sizeof(struct GNUNET_TUN_IPv4Header);
3010 switch (pkt4->protocol)
3013 udp_from_helper((const struct GNUNET_TUN_UdpHeader *)&pkt4[1], size,
3015 &pkt4->destination_address,
3016 &pkt4->source_address);
3020 tcp_from_helper((const struct GNUNET_TUN_TcpHeader *)&pkt4[1], size,
3022 &pkt4->destination_address,
3023 &pkt4->source_address);
3027 icmp_from_helper((const struct GNUNET_TUN_IcmpHeader *)&pkt4[1], size,
3029 &pkt4->destination_address,
3030 &pkt4->source_address);
3034 GNUNET_log(GNUNET_ERROR_TYPE_WARNING,
3035 _("IPv4 packet with unsupported next header %u received. Ignored.\n"),
3036 (int)pkt4->protocol);
3044 const struct GNUNET_TUN_IPv6Header *pkt6;
3046 if (size < sizeof(struct GNUNET_TUN_IPv6Header))
3048 /* Kernel to blame? */
3052 pkt6 = (struct GNUNET_TUN_IPv6Header *)&pkt_tun[1];
3053 if (size != ntohs(pkt6->payload_length) + sizeof(struct GNUNET_TUN_IPv6Header))
3055 /* Kernel to blame? */
3059 size -= sizeof(struct GNUNET_TUN_IPv6Header);
3060 switch (pkt6->next_header)
3063 udp_from_helper((const struct GNUNET_TUN_UdpHeader *)&pkt6[1], size,
3065 &pkt6->destination_address,
3066 &pkt6->source_address);
3070 tcp_from_helper((const struct GNUNET_TUN_TcpHeader *)&pkt6[1], size,
3072 &pkt6->destination_address,
3073 &pkt6->source_address);
3076 case IPPROTO_ICMPV6:
3077 icmp_from_helper((const struct GNUNET_TUN_IcmpHeader *)&pkt6[1], size,
3079 &pkt6->destination_address,
3080 &pkt6->source_address);
3084 GNUNET_log(GNUNET_ERROR_TYPE_WARNING,
3085 _("IPv6 packet with unsupported next header %d received. Ignored.\n"),
3093 GNUNET_log(GNUNET_ERROR_TYPE_WARNING,
3094 _("Packet from unknown protocol %u received. Ignored.\n"),
3095 ntohs(pkt_tun->proto));
3103 * Callback from CADET for new channels.
3105 * @param cls closure
3106 * @param channel new handle to the channel
3107 * @param initiator peer that started the channel
3108 * @return initial channel context for the channel
3111 new_channel(void *cls,
3112 struct GNUNET_CADET_Channel *channel,
3113 const struct GNUNET_PeerIdentity *initiator)
3115 struct ChannelState *s = GNUNET_new(struct ChannelState);
3117 s->is_dns = GNUNET_SYSERR;
3118 s->peer = *initiator;
3119 GNUNET_STATISTICS_update(stats,
3120 gettext_noop("# Inbound CADET channels created"),
3123 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
3124 "Received inbound channel from `%s'\n",
3125 GNUNET_i2s(initiator));
3126 s->channel = channel;
3132 * Function that frees everything from a hashmap
3136 * @param value value to free
3139 free_iterate(void *cls,
3140 const struct GNUNET_HashCode * hash,
3149 * Function scheduled as very last function if the service
3150 * disabled itself because the helper is not installed
3151 * properly. Does nothing, except for keeping the
3152 * service process alive by virtue of being scheduled.
3155 * @param tc scheduler context
3158 dummy_task(void *cls)
3160 /* just terminate */
3165 * Function scheduled as very last function, cleans up after us
3174 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
3175 "Exit service is shutting down now\n");
3177 if (NULL != helper_handle)
3179 GNUNET_HELPER_stop(helper_handle, GNUNET_NO);
3180 helper_handle = NULL;
3184 GNUNET_REGEX_announce_cancel(regex4);
3189 GNUNET_REGEX_announce_cancel(regex6);
3192 if (NULL != services)
3194 GNUNET_CONTAINER_multihashmap_iterate(services,
3195 &free_service_record,
3197 GNUNET_CONTAINER_multihashmap_destroy(services);
3199 if (NULL != dns_port)
3201 GNUNET_CADET_close_port(dns_port);
3204 if (NULL != cadet_port4)
3206 GNUNET_CADET_close_port(cadet_port4);
3209 if (NULL != cadet_port6)
3211 GNUNET_CADET_close_port(cadet_port6);
3214 if (NULL != cadet_handle)
3216 GNUNET_CADET_disconnect(cadet_handle);
3217 cadet_handle = NULL;
3219 if (NULL != connections_map)
3221 GNUNET_CONTAINER_multihashmap_iterate(connections_map,
3224 GNUNET_CONTAINER_multihashmap_destroy(connections_map);
3225 connections_map = NULL;
3227 if (NULL != connections_heap)
3229 GNUNET_CONTAINER_heap_destroy(connections_heap);
3230 connections_heap = NULL;
3232 if (NULL != dnsstub)
3234 GNUNET_DNSSTUB_stop(dnsstub);
3237 if (NULL != peer_key)
3239 GNUNET_free(peer_key);
3242 if (NULL != dht_task)
3244 GNUNET_SCHEDULER_cancel(dht_task);
3247 if (NULL != dht_put)
3249 GNUNET_DHT_put_cancel(dht_put);
3254 GNUNET_DHT_disconnect(dht);
3259 GNUNET_STATISTICS_destroy(stats,
3263 for (i = 0; i < 8; i++)
3264 GNUNET_free_non_null(exit_argv[i]);
3269 * Add services to the service map.
3271 * @param proto IPPROTO_TCP or IPPROTO_UDP
3272 * @param cpy copy of the service descriptor (can be mutilated)
3273 * @param name DNS name of the service
3276 add_services(int proto,
3283 struct LocalService *serv;
3287 slen = strlen(name);
3288 GNUNET_assert(slen >= 8);
3289 n = GNUNET_strndup(name, slen - 8 /* remove .gnunet. */);
3291 for (redirect = strtok(cpy, " ;"); redirect != NULL;
3292 redirect = strtok(NULL, " ;"))
3294 if (NULL == (hostname = strstr(redirect, ":")))
3296 GNUNET_log(GNUNET_ERROR_TYPE_WARNING,
3297 _("Option `%s' for domain `%s' is not formatted correctly!\n"),
3304 if (NULL == (hostport = strstr(hostname, ":")))
3306 GNUNET_log(GNUNET_ERROR_TYPE_WARNING,
3307 _("Option `%s' for domain `%s' is not formatted correctly!\n"),
3315 int local_port = atoi(redirect);
3316 int remote_port = atoi(hostport);
3318 if (!((local_port > 0) && (local_port < 65536)))
3320 GNUNET_log(GNUNET_ERROR_TYPE_WARNING,
3321 _("`%s' is not a valid port number (for domain `%s')!"),
3326 if (!((remote_port > 0) && (remote_port < 65536)))
3328 GNUNET_log(GNUNET_ERROR_TYPE_WARNING,
3329 _("`%s' is not a valid port number (for domain `%s')!"),
3335 serv = GNUNET_new(struct LocalService);
3336 serv->address.proto = proto;
3337 serv->address.port = remote_port;
3338 if (0 == strcmp("localhost4",
3341 const char *ip4addr = exit_argv[5];
3343 serv->address.af = AF_INET;
3344 GNUNET_assert(1 == inet_pton(AF_INET,
3346 &serv->address.address.ipv4));
3348 else if (0 == strcmp("localhost6",
3351 const char *ip6addr = exit_argv[3];
3353 serv->address.af = AF_INET6;
3354 GNUNET_assert(1 == inet_pton(AF_INET6,
3356 &serv->address.address.ipv6));
3360 struct addrinfo *res;
3363 ret = getaddrinfo(hostname,
3367 if ((0 != ret) || (NULL == res))
3369 GNUNET_log(GNUNET_ERROR_TYPE_WARNING,
3370 _("No addresses found for hostname `%s' of service `%s'!\n"),
3377 serv->address.af = res->ai_family;
3378 switch (res->ai_family)
3383 GNUNET_log(GNUNET_ERROR_TYPE_WARNING,
3384 _("Service `%s' configured for IPv4, but IPv4 is disabled!\n"),
3390 serv->address.address.ipv4
3391 = ((struct sockaddr_in *)res->ai_addr)->sin_addr;
3397 GNUNET_log(GNUNET_ERROR_TYPE_WARNING,
3398 _("Service `%s' configured for IPv4, but IPv4 is disabled!\n"),
3404 serv->address.address.ipv6
3405 = ((struct sockaddr_in6 *)res->ai_addr)->sin6_addr;
3410 GNUNET_log(GNUNET_ERROR_TYPE_WARNING,
3411 _("No IP addresses found for hostname `%s' of service `%s'!\n"),
3419 store_service(proto,
3429 * Reads the configuration and populates #udp_services and #tcp_services
3432 * @param section name of section in config
3435 read_service_conf(void *cls,
3436 const char *section)
3440 if ((strlen(section) < 8) ||
3441 (0 != strcmp(".gnunet.", section + (strlen(section) - 8))))
3444 GNUNET_CONFIGURATION_get_value_string(cfg,
3449 add_services(IPPROTO_UDP,
3455 GNUNET_CONFIGURATION_get_value_string(cfg,
3460 add_services(IPPROTO_TCP,
3469 * We are running a DNS exit service, advertise it in the
3470 * DHT. This task is run periodically to do the DHT PUT.
3472 * @param cls closure
3475 do_dht_put(void *cls);
3479 * Function called when the DHT PUT operation is complete.
3480 * Schedules the next PUT.
3482 * @param cls closure, NULL
3485 dht_put_cont(void *cls)
3492 * We are running a DNS exit service, advertise it in the
3493 * DHT. This task is run periodically to do the DHT PUT.
3495 * @param cls closure
3498 do_dht_put(void *cls)
3500 struct GNUNET_TIME_Absolute expiration;
3502 dht_task = GNUNET_SCHEDULER_add_delayed(DHT_PUT_FREQUENCY,
3505 expiration = GNUNET_TIME_absolute_ntoh(dns_advertisement.expiration_time);
3506 if (GNUNET_TIME_absolute_get_remaining(expiration).rel_value_us <
3507 GNUNET_TIME_UNIT_HOURS.rel_value_us)
3509 /* refresh advertisement */
3510 expiration = GNUNET_TIME_relative_to_absolute(DNS_ADVERTISEMENT_TIMEOUT);
3511 dns_advertisement.expiration_time = GNUNET_TIME_absolute_hton(expiration);
3512 GNUNET_assert(GNUNET_OK ==
3513 GNUNET_CRYPTO_eddsa_sign(peer_key,
3514 &dns_advertisement.purpose,
3515 &dns_advertisement.signature));
3517 if (NULL != dht_put)
3518 GNUNET_DHT_put_cancel(dht_put);
3519 dht_put = GNUNET_DHT_put(dht,
3521 1 /* replication */,
3523 GNUNET_BLOCK_TYPE_DNS,
3524 sizeof(struct GNUNET_DNS_Advertisement),
3533 * Figure out which IP versions we should support (and which
3534 * are supported by the OS) according to our configuration.
3539 ipv4_exit = GNUNET_CONFIGURATION_get_value_yesno(cfg,
3542 ipv6_exit = GNUNET_CONFIGURATION_get_value_yesno(cfg,
3545 ipv4_enabled = GNUNET_CONFIGURATION_get_value_yesno(cfg,
3548 ipv6_enabled = GNUNET_CONFIGURATION_get_value_yesno(cfg,
3551 if ((ipv4_exit || ipv4_enabled) &&
3552 GNUNET_OK != GNUNET_NETWORK_test_pf(PF_INET))
3554 GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
3555 _("This system does not support IPv4, will disable IPv4 functions despite them being enabled in the configuration\n"));
3556 ipv4_exit = GNUNET_NO;
3557 ipv4_enabled = GNUNET_NO;
3559 if ((ipv6_exit || ipv6_enabled) &&
3560 GNUNET_OK != GNUNET_NETWORK_test_pf(PF_INET6))
3562 GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
3563 _("This system does not support IPv6, will disable IPv6 functions despite them being enabled in the configuration\n"));
3564 ipv6_exit = GNUNET_NO;
3565 ipv6_enabled = GNUNET_NO;
3567 if (ipv4_exit && (!ipv4_enabled))
3569 GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
3570 _("Cannot enable IPv4 exit but disable IPv4 on TUN interface, will use ENABLE_IPv4=YES\n"));
3571 ipv4_enabled = GNUNET_YES;
3573 if (ipv6_exit && (!ipv6_enabled))
3575 GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
3576 _("Cannot enable IPv6 exit but disable IPv6 on TUN interface, will use ENABLE_IPv6=YES\n"));
3577 ipv6_enabled = GNUNET_YES;
3583 * Helper function to open the CADET port for DNS exits and to
3584 * advertise the DNS exit (if applicable).
3587 advertise_dns_exit()
3589 struct GNUNET_MQ_MessageHandler handlers[] = {
3590 GNUNET_MQ_hd_var_size(dns_request,
3591 GNUNET_MESSAGE_TYPE_VPN_DNS_TO_INTERNET,
3592 struct DnsResponseMessage,
3594 GNUNET_MQ_handler_end()
3597 struct GNUNET_HashCode port;
3600 GNUNET_CONFIGURATION_get_value_yesno(cfg,
3604 GNUNET_assert(NULL != (dnsstub = GNUNET_DNSSTUB_start(128)));
3606 /* TODO: support using multiple DNS resolvers */
3608 GNUNET_CONFIGURATION_get_value_string(cfg,
3613 GNUNET_DNSSTUB_add_dns_ip(dnsstub,
3616 GNUNET_log_config_invalid(GNUNET_ERROR_TYPE_ERROR,
3619 _("need a valid IPv4 or IPv6 address\n"));
3620 GNUNET_free_non_null(dns_exit);
3624 GNUNET_CRYPTO_hash(GNUNET_APPLICATION_PORT_INTERNET_RESOLVER,
3625 strlen(GNUNET_APPLICATION_PORT_INTERNET_RESOLVER),
3627 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
3628 "Opening CADET port %s for DNS exit service\n",
3630 dns_port = GNUNET_CADET_open_port(cadet_handle,
3637 /* advertise exit */
3638 dht = GNUNET_DHT_connect(cfg,
3640 peer_key = GNUNET_CRYPTO_eddsa_key_create_from_configuration(cfg);
3641 GNUNET_CRYPTO_eddsa_key_get_public(peer_key,
3642 &dns_advertisement.peer.public_key);
3643 dns_advertisement.purpose.size = htonl(sizeof(struct GNUNET_DNS_Advertisement) -
3644 sizeof(struct GNUNET_CRYPTO_EddsaSignature));
3645 dns_advertisement.purpose.purpose = htonl(GNUNET_SIGNATURE_PURPOSE_DNS_RECORD);
3646 GNUNET_CRYPTO_hash("dns",
3649 dht_task = GNUNET_SCHEDULER_add_now(&do_dht_put,
3651 GNUNET_free(dns_exit);
3656 * Initialize #exit_argv.
3658 * @return #GNUNET_OK on success, #GNUNET_SYSERR if we should shutdown
3661 setup_exit_helper_args()
3670 exit_argv[0] = GNUNET_strdup("exit-gnunet");
3671 if (GNUNET_SYSERR ==
3672 GNUNET_CONFIGURATION_get_value_string(cfg,
3677 GNUNET_log_config_missing(GNUNET_ERROR_TYPE_ERROR,
3680 return GNUNET_SYSERR;
3682 exit_argv[1] = tun_ifname;
3685 if (GNUNET_SYSERR ==
3686 GNUNET_CONFIGURATION_get_value_string(cfg,
3691 GNUNET_log_config_missing(GNUNET_ERROR_TYPE_ERROR,
3694 return GNUNET_SYSERR;
3696 exit_argv[2] = exit_ifname;
3700 exit_argv[2] = GNUNET_strdup("-");
3703 if (GNUNET_YES == ipv6_enabled)
3706 if ((GNUNET_SYSERR ==
3707 GNUNET_CONFIGURATION_get_value_string(cfg,
3711 (1 != inet_pton(AF_INET6,
3715 GNUNET_log_config_missing(GNUNET_ERROR_TYPE_ERROR,
3718 GNUNET_free_non_null(ipv6addr);
3719 return GNUNET_SYSERR;
3721 exit_argv[3] = ipv6addr;
3722 if (GNUNET_SYSERR ==
3723 GNUNET_CONFIGURATION_get_value_string(cfg,
3728 GNUNET_log_config_missing(GNUNET_ERROR_TYPE_ERROR,
3731 return GNUNET_SYSERR;
3733 exit_argv[4] = ipv6prefix_s;
3735 GNUNET_CONFIGURATION_get_value_number(cfg,
3739 (ipv6prefix >= 127))
3741 GNUNET_log_config_invalid(GNUNET_ERROR_TYPE_ERROR,
3744 _("Must be a number"));
3745 return GNUNET_SYSERR;
3750 /* IPv6 explicitly disabled */
3751 exit_argv[3] = GNUNET_strdup("-");
3752 exit_argv[4] = GNUNET_strdup("-");
3754 if (GNUNET_YES == ipv4_enabled)
3757 if ((GNUNET_SYSERR ==
3758 GNUNET_CONFIGURATION_get_value_string(cfg,
3762 (1 != inet_pton(AF_INET,
3766 GNUNET_log_config_missing(GNUNET_ERROR_TYPE_ERROR,
3769 GNUNET_free_non_null(ipv4addr);
3770 return GNUNET_SYSERR;
3772 exit_argv[5] = ipv4addr;
3774 if ((GNUNET_SYSERR ==
3775 GNUNET_CONFIGURATION_get_value_string(cfg,
3779 (1 != inet_pton(AF_INET,
3783 GNUNET_log_config_missing(GNUNET_ERROR_TYPE_ERROR,
3786 GNUNET_free_non_null(ipv4mask);
3787 return GNUNET_SYSERR;
3789 exit_argv[6] = ipv4mask;
3793 /* IPv4 explicitly disabled */
3794 exit_argv[5] = GNUNET_strdup("-");
3795 exit_argv[6] = GNUNET_strdup("-");
3797 exit_argv[7] = NULL;
3803 * @brief Main function that will be run by the scheduler.
3805 * @param cls closure
3806 * @param args remaining command-line arguments
3807 * @param cfgfile name of the configuration file used (for saving, can be NULL!)
3808 * @param cfg_ configuration
3813 const char *cfgfile,
3814 const struct GNUNET_CONFIGURATION_Handle *cfg_)
3816 struct GNUNET_MQ_MessageHandler handlers[] = {
3817 GNUNET_MQ_hd_var_size(icmp_remote,
3818 GNUNET_MESSAGE_TYPE_VPN_ICMP_TO_INTERNET,
3819 struct GNUNET_EXIT_IcmpInternetMessage,
3821 GNUNET_MQ_hd_var_size(udp_remote,
3822 GNUNET_MESSAGE_TYPE_VPN_UDP_TO_INTERNET,
3823 struct GNUNET_EXIT_UdpInternetMessage,
3825 GNUNET_MQ_hd_var_size(tcp_remote,
3826 GNUNET_MESSAGE_TYPE_VPN_TCP_TO_INTERNET_START,
3827 struct GNUNET_EXIT_TcpInternetStartMessage,
3829 GNUNET_MQ_hd_var_size(tcp_data,
3830 GNUNET_MESSAGE_TYPE_VPN_TCP_DATA_TO_EXIT,
3831 struct GNUNET_EXIT_TcpDataMessage,
3833 GNUNET_MQ_handler_end()
3835 struct GNUNET_HashCode port;
3839 char *prefixed_regex;
3843 GNUNET_CONFIGURATION_get_value_number(cfg,
3847 max_connections = 1024;
3849 binary = GNUNET_OS_get_suid_binary_path(cfg, "gnunet-helper-exit");
3850 if ((ipv4_exit) || (ipv6_exit))
3853 GNUNET_OS_check_helper_binary(binary,
3855 "gnunet-vpn - - - 169.1.3.7 255.255.255.0")) //no nat, ipv4 only
3857 GNUNET_free(binary);
3858 GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
3859 _("`%s' is not SUID or the path is invalid, EXIT will not work\n"),
3860 "gnunet-helper-exit");
3861 GNUNET_SCHEDULER_add_shutdown(&dummy_task,
3867 if (!(ipv4_enabled || ipv6_enabled))
3869 GNUNET_free(binary);
3870 GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
3871 _("No useful service enabled. Exiting.\n"));
3872 GNUNET_SCHEDULER_shutdown();
3876 GNUNET_SCHEDULER_add_shutdown(&cleanup,
3878 stats = GNUNET_STATISTICS_create("exit",
3880 cadet_handle = GNUNET_CADET_connect(cfg);
3881 if (NULL == cadet_handle)
3883 GNUNET_free(binary);
3884 GNUNET_SCHEDULER_shutdown();
3887 advertise_dns_exit();
3889 setup_exit_helper_args())
3891 GNUNET_free(binary);
3892 GNUNET_SCHEDULER_shutdown();
3896 services = GNUNET_CONTAINER_multihashmap_create(65536,
3898 connections_map = GNUNET_CONTAINER_multihashmap_create(65536,
3900 connections_heap = GNUNET_CONTAINER_heap_create(GNUNET_CONTAINER_HEAP_ORDER_MIN);
3901 GNUNET_CONFIGURATION_iterate_sections(cfg,
3905 /* Cadet handle acquired, now open ports and announce regular
3906 expressions matching our exit */
3907 if ((GNUNET_YES == ipv4_enabled) &&
3908 (GNUNET_YES == ipv4_exit))
3910 GNUNET_CRYPTO_hash(GNUNET_APPLICATION_PORT_IPV4_GATEWAY,
3911 strlen(GNUNET_APPLICATION_PORT_IPV4_GATEWAY),
3913 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
3914 "Opening CADET port %s for IPv4 gateway service\n",
3916 cadet_port4 = GNUNET_CADET_open_port(cadet_handle,
3925 GNUNET_CONFIGURATION_get_value_string(cfg,
3927 "EXIT_RANGE_IPV4_POLICY",
3931 regex = GNUNET_TUN_ipv4policy2regex(policy);
3932 GNUNET_free_non_null(policy);
3935 (void)GNUNET_asprintf(&prefixed_regex,
3937 GNUNET_APPLICATION_TYPE_EXIT_REGEX_PREFIX,
3939 regex4 = GNUNET_REGEX_announce(cfg,
3941 REGEX_REFRESH_FREQUENCY,
3942 REGEX_MAX_PATH_LEN_IPV4);
3944 GNUNET_free(prefixed_regex);
3948 if ((GNUNET_YES == ipv6_enabled) && (GNUNET_YES == ipv6_exit))
3950 GNUNET_CRYPTO_hash(GNUNET_APPLICATION_PORT_IPV6_GATEWAY,
3951 strlen(GNUNET_APPLICATION_PORT_IPV6_GATEWAY),
3953 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
3954 "Opening CADET port %s for IPv6 gateway service\n",
3956 cadet_port6 = GNUNET_CADET_open_port(cadet_handle,
3965 GNUNET_CONFIGURATION_get_value_string(cfg,
3967 "EXIT_RANGE_IPV6_POLICY",
3971 regex = GNUNET_TUN_ipv6policy2regex(policy);
3972 GNUNET_free_non_null(policy);
3975 (void)GNUNET_asprintf(&prefixed_regex,
3977 GNUNET_APPLICATION_TYPE_EXIT_REGEX_PREFIX,
3979 regex6 = GNUNET_REGEX_announce(cfg,
3981 REGEX_REFRESH_FREQUENCY,
3982 REGEX_MAX_PATH_LEN_IPV6);
3984 GNUNET_free(prefixed_regex);
3987 helper_handle = GNUNET_HELPER_start(GNUNET_NO,
3993 GNUNET_free(binary);
4000 * @param argc number of arguments from the command line
4001 * @param argv command line arguments
4002 * @return 0 ok, 1 on error
4008 static const struct GNUNET_GETOPT_CommandLineOption options[] = {
4009 GNUNET_GETOPT_OPTION_END
4013 GNUNET_STRINGS_get_utf8_args(argc,
4019 return (GNUNET_OK ==
4020 GNUNET_PROGRAM_run(argc,
4022 "gnunet-daemon-exit",
4023 gettext_noop("Daemon to run to provide an IP exit node for the VPN"),
4026 NULL)) ? global_ret : 1;
4030 /* end of gnunet-daemon-exit.c */