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 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.
17 * @file exit/gnunet-daemon-exit.c
18 * @brief tool to allow IP traffic exit from the GNUnet cadet to the Internet
19 * @author Philipp Toelke
20 * @author Christian Grothoff
26 * - which code should advertise services? the service model is right
27 * now a bit odd, especially as this code DOES the exit and knows
28 * the DNS "name", but OTOH this is clearly NOT the place to advertise
29 * the service's existence; maybe the daemon should turn into a
30 * service with an API to add local-exit services dynamically?
33 #include "gnunet_util_lib.h"
34 #include "gnunet_protocols.h"
35 #include "gnunet_applications.h"
36 #include "gnunet_dht_service.h"
37 #include "gnunet_cadet_service.h"
38 #include "gnunet_dnsparser_lib.h"
39 #include "gnunet_dnsstub_lib.h"
40 #include "gnunet_statistics_service.h"
41 #include "gnunet_constants.h"
42 #include "gnunet_signatures.h"
43 #include "gnunet_tun_lib.h"
44 #include "gnunet_regex_service.h"
46 #include "block_dns.h"
50 * Maximum path compression length for cadet regex announcing for IPv4 address
53 #define REGEX_MAX_PATH_LEN_IPV4 4
56 * Maximum path compression length for cadet regex announcing for IPv6 address
59 #define REGEX_MAX_PATH_LEN_IPV6 8
62 * How frequently do we re-announce the regex for the exit?
64 #define REGEX_REFRESH_FREQUENCY GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 30)
67 * How frequently do we re-announce the DNS exit in the DHT?
69 #define DHT_PUT_FREQUENCY GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 15)
72 * How long do we typically sign the DNS exit advertisement for?
74 #define DNS_ADVERTISEMENT_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_HOURS, 3)
78 * Generic logging shorthand
80 #define LOG(kind, ...) \
81 GNUNET_log_from (kind, "exit", __VA_ARGS__);
85 * Information about an address.
90 * AF_INET or AF_INET6.
95 * Remote address information.
100 * Address, if af is AF_INET.
105 * Address, if af is AF_INET6.
107 struct in6_addr ipv6;
111 * IPPROTO_TCP or IPPROTO_UDP;
116 * Remote port, in host byte order!
124 * This struct is saved into the services-hashmap to represent
125 * a service this peer is specifically offering an exit for
126 * (for a specific domain name).
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.
160 * Information we use to track a connection (the classical 6-tuple of
161 * IP-version, protocol, source-IP, destination-IP, source-port and
164 struct RedirectInformation
168 * Address information for the other party (equivalent of the
169 * arguments one would give to "connect").
171 struct SocketAddress remote_address;
174 * Address information we used locally (AF and proto must match
175 * "remote_address"). Equivalent of the arguments one would give to
178 struct SocketAddress local_address;
181 Note 1: additional information might be added here in the
182 future to support protocols that require special handling,
185 Note 2: we might also sometimes not match on all components
186 of the tuple, to support protocols where things do not always
193 * This struct is saved into #connections_map to allow finding the
194 * right channel given an IP packet from TUN. It is also associated
195 * with the channel's closure so we can find it again for the next
196 * message from the channel.
201 * Cadet channel that is used for this connection.
203 struct GNUNET_CADET_Channel *channel;
206 * Who is the other end of this channel.
207 * FIXME is this needed? Only used for debugging messages
209 struct GNUNET_PeerIdentity peer;
212 * #GNUNET_NO if this is a channel for TCP/UDP,
213 * #GNUNET_YES if this is a channel for DNS,
214 * #GNUNET_SYSERR if the channel is not yet initialized.
224 * Heap node for this state in the connections_heap.
226 struct GNUNET_CONTAINER_HeapNode *heap_node;
229 * Key this state has in the #connections_map.
231 struct GNUNET_HashCode state_key;
234 * Associated service record, or NULL for no service.
236 struct LocalService *serv;
239 * Primary redirection information for this connection.
241 struct RedirectInformation ri;
248 * Socket we are using to transmit this request (must match if we receive
251 struct GNUNET_DNSSTUB_RequestSocket *rs;
254 * Original DNS request ID as used by the client.
256 uint16_t original_id;
259 * DNS request ID that we used for forwarding.
271 * Return value from 'main'.
273 static int global_ret;
276 * Handle to our regex announcement for IPv4.
278 static struct GNUNET_REGEX_Announcement *regex4;
281 * Handle to our regex announcement for IPv4.
283 static struct GNUNET_REGEX_Announcement *regex6;
286 * The handle to the configuration used throughout the process
288 static const struct GNUNET_CONFIGURATION_Handle *cfg;
291 * The handle to the helper
293 static struct GNUNET_HELPER_Handle *helper_handle;
296 * Arguments to the exit helper.
298 static char *exit_argv[8];
301 * IPv6 address of our TUN interface.
303 static struct in6_addr exit_ipv6addr;
306 * IPv6 prefix (0..127) from configuration file.
308 static unsigned long long ipv6prefix;
311 * IPv4 address of our TUN interface.
313 static struct in_addr exit_ipv4addr;
316 * IPv4 netmask of our TUN interface.
318 static struct in_addr exit_ipv4mask;
323 static struct GNUNET_STATISTICS_Handle *stats;
326 * The handle to cadet
328 static struct GNUNET_CADET_Handle *cadet_handle;
331 * This hashmaps contains the mapping from peer, service-descriptor,
332 * source-port and destination-port to a struct ChannelState
334 static struct GNUNET_CONTAINER_MultiHashMap *connections_map;
337 * Heap so we can quickly find "old" connections.
339 static struct GNUNET_CONTAINER_Heap *connections_heap;
342 * If there are at least this many connections, old ones will be removed
344 static unsigned long long max_connections;
347 * This hashmaps saves interesting things about the configured services
349 static struct GNUNET_CONTAINER_MultiHashMap *services;
352 * Array of all open DNS requests from channels.
354 static struct ChannelState *channels[UINT16_MAX + 1];
357 * Handle to the DNS Stub resolver.
359 static struct GNUNET_DNSSTUB_Context *dnsstub;
362 * Handle for ongoing DHT PUT operations to advertise exit service.
364 static struct GNUNET_DHT_PutHandle *dht_put;
369 static struct GNUNET_DHT_Handle *dht;
372 * Task for doing DHT PUTs to advertise exit service.
374 static struct GNUNET_SCHEDULER_Task *dht_task;
377 * Advertisement message we put into the DHT to advertise us
380 static struct GNUNET_DNS_Advertisement dns_advertisement;
383 * Key we store the DNS advertismenet under.
385 static struct GNUNET_HashCode dht_put_key;
388 * Private key for this peer.
390 static struct GNUNET_CRYPTO_EddsaPrivateKey *peer_key;
395 static struct GNUNET_CADET_Port *dns_port;
398 * Port for IPv4 exit.
400 static struct GNUNET_CADET_Port *cadet_port4;
403 * Port for IPv6 exit.
405 static struct GNUNET_CADET_Port *cadet_port6;
408 * Are we an IPv4-exit?
410 static int ipv4_exit;
413 * Are we an IPv6-exit?
415 static int ipv6_exit;
418 * Do we support IPv4 at all on the TUN interface?
420 static int ipv4_enabled;
423 * Do we support IPv6 at all on the TUN interface?
425 static int ipv6_enabled;
428 GNUNET_NETWORK_STRUCT_BEGIN
431 * Message with a DNS response.
433 struct DnsResponseMessage
436 * GNUnet header, of type #GNUNET_MESSAGE_TYPE_VPN_DNS_FROM_INTERNET
438 struct GNUNET_MessageHeader header;
443 struct GNUNET_TUN_DnsHeader dns;
445 /* Followed by more DNS payload */
448 GNUNET_NETWORK_STRUCT_END
452 * Callback called from DNSSTUB resolver when a resolution
456 * @param dns the response itself
457 * @param r number of bytes in @a dns
460 process_dns_result (void *cls,
461 const struct GNUNET_TUN_DnsHeader *dns,
464 struct ChannelState *ts;
465 struct GNUNET_MQ_Envelope *env;
466 struct DnsResponseMessage *resp;
468 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
469 "Processing DNS result from stub resolver\n");
470 GNUNET_assert (NULL == cls);
473 /* Handle case that this is a reply to a request from a CADET DNS channel */
474 ts = channels[dns->id];
477 LOG (GNUNET_ERROR_TYPE_DEBUG,
478 "Got a response from the stub resolver for DNS request received via CADET!\n");
479 channels[dns->id] = NULL;
480 env = GNUNET_MQ_msg_extra (resp,
481 r - sizeof (struct GNUNET_TUN_DnsHeader),
482 GNUNET_MESSAGE_TYPE_VPN_DNS_FROM_INTERNET);
483 GNUNET_memcpy (&resp->dns,
486 resp->dns.id = ts->specifics.dns.original_id;
487 GNUNET_MQ_send (GNUNET_CADET_get_mq (ts->channel),
493 * Check a request via cadet to perform a DNS query.
495 * @param cls our `struct ChannelState *`
496 * @param msg the actual message
497 * @return #GNUNET_OK to keep the connection open,
498 * #GNUNET_SYSERR to close it (signal serious error)
501 check_dns_request (void *cls,
502 const struct DnsResponseMessage *msg)
504 struct ChannelState *ts = cls;
509 return GNUNET_SYSERR;
511 if (GNUNET_NO == ts->is_dns)
514 return GNUNET_SYSERR;
521 * Process a request via cadet to perform a DNS query.
523 * @param cls our `struct ChannelState *`
524 * @param msg the actual message
527 handle_dns_request (void *cls,
528 const struct DnsResponseMessage *msg)
530 struct ChannelState *ts = cls;
531 size_t mlen = ntohs (msg->header.size);
532 size_t dlen = mlen - sizeof (struct GNUNET_MessageHeader);
533 char buf[dlen] GNUNET_ALIGN;
534 struct GNUNET_TUN_DnsHeader *dout;
536 if (GNUNET_SYSERR == ts->is_dns)
538 /* channel is DNS from now on */
539 ts->is_dns = GNUNET_YES;
541 ts->specifics.dns.original_id = msg->dns.id;
542 if (channels[ts->specifics.dns.my_id] == ts)
543 channels[ts->specifics.dns.my_id] = NULL;
544 ts->specifics.dns.my_id = (uint16_t) GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
546 channels[ts->specifics.dns.my_id] = ts;
550 dout = (struct GNUNET_TUN_DnsHeader *) buf;
551 dout->id = ts->specifics.dns.my_id;
552 ts->specifics.dns.rs = GNUNET_DNSSTUB_resolve (dnsstub,
557 if (NULL == ts->specifics.dns.rs)
562 GNUNET_CADET_receive_done (ts->channel);
567 * Given IP information about a connection, calculate the respective
568 * hash we would use for the #connections_map.
570 * @param hash resulting hash
571 * @param ri information about the connection
574 hash_redirect_info (struct GNUNET_HashCode *hash,
575 const struct RedirectInformation *ri)
581 sizeof (struct GNUNET_HashCode));
582 /* the GNUnet hashmap only uses the first sizeof(unsigned int) of the hash,
583 so we put the IP address in there (and hope for few collisions) */
585 switch (ri->remote_address.af)
589 &ri->remote_address.address.ipv4,
590 sizeof (struct in_addr));
591 off += sizeof (struct in_addr);
595 &ri->remote_address.address.ipv6,
596 sizeof (struct in6_addr));
597 off += sizeof (struct in_addr);
603 &ri->remote_address.port,
605 off += sizeof (uint16_t);
606 switch (ri->local_address.af)
610 &ri->local_address.address.ipv4,
611 sizeof (struct in_addr));
612 off += sizeof (struct in_addr);
616 &ri->local_address.address.ipv6,
617 sizeof (struct in6_addr));
618 off += sizeof (struct in_addr);
624 &ri->local_address.port,
626 off += sizeof (uint16_t);
628 &ri->remote_address.proto,
630 /* off += sizeof (uint8_t); */
635 * Get our connection tracking state. Warns if it does not exists,
636 * refreshes the timestamp if it does exist.
638 * @param af address family
639 * @param protocol IPPROTO_UDP or IPPROTO_TCP
640 * @param destination_ip target IP
641 * @param destination_port target port
642 * @param local_ip local IP
643 * @param local_port local port
644 * @param state_key set to hash's state if non-NULL
645 * @return NULL if we have no tracking information for this tuple
647 static struct ChannelState *
648 get_redirect_state (int af,
650 const void *destination_ip,
651 uint16_t destination_port,
652 const void *local_ip,
654 struct GNUNET_HashCode *state_key)
656 struct RedirectInformation ri;
657 struct GNUNET_HashCode key;
658 struct ChannelState *state;
660 if ( ( (af == AF_INET) && (protocol == IPPROTO_ICMP) ) ||
661 ( (af == AF_INET6) && (protocol == IPPROTO_ICMPV6) ) )
664 destination_port = 0;
667 ri.remote_address.af = af;
669 ri.remote_address.address.ipv4 = *((struct in_addr*) destination_ip);
671 ri.remote_address.address.ipv6 = * ((struct in6_addr*) destination_ip);
672 ri.remote_address.port = destination_port;
673 ri.remote_address.proto = protocol;
674 ri.local_address.af = af;
676 ri.local_address.address.ipv4 = *((struct in_addr*) local_ip);
678 ri.local_address.address.ipv6 = * ((struct in6_addr*) local_ip);
679 ri.local_address.port = local_port;
680 ri.local_address.proto = protocol;
681 hash_redirect_info (&key,
683 if (NULL != state_key)
685 state = GNUNET_CONTAINER_multihashmap_get (connections_map,
689 /* Mark this connection as freshly used */
690 if (NULL == state_key)
691 GNUNET_CONTAINER_heap_update_cost (state->specifics.tcp_udp.heap_node,
692 GNUNET_TIME_absolute_get ().abs_value_us);
699 * Check a request via cadet to send a request to a TCP service
700 * offered by this system.
702 * @param cls our `struct ChannelState *`
703 * @param start the actual message
704 * @return #GNUNET_OK to keep the connection open,
705 * #GNUNET_SYSERR to close it (signal serious error)
708 check_tcp_service (void *cls,
709 const struct GNUNET_EXIT_TcpServiceStartMessage *start)
711 struct ChannelState *state = cls;
716 return GNUNET_SYSERR;
718 if (GNUNET_YES == state->is_dns)
721 return GNUNET_SYSERR;
723 if (NULL == state->specifics.tcp_udp.serv)
726 return GNUNET_SYSERR;
728 if (NULL != state->specifics.tcp_udp.heap_node)
731 return GNUNET_SYSERR;
733 if (start->tcp_header.off * 4 < sizeof (struct GNUNET_TUN_TcpHeader))
736 return GNUNET_SYSERR;
743 * Prepare an IPv4 packet for transmission via the TUN interface.
744 * Initializes the IP header and calculates checksums (IP+UDP/TCP).
745 * For UDP, the UDP header will be fully created, whereas for TCP
746 * only the ports and checksum will be filled in. So for TCP,
747 * a skeleton TCP header must be part of the provided payload.
749 * @param payload payload of the packet (starting with UDP payload or
750 * TCP header, depending on protocol)
751 * @param payload_length number of bytes in @a payload
752 * @param protocol IPPROTO_UDP or IPPROTO_TCP
753 * @param tcp_header skeleton of the TCP header, NULL for UDP
754 * @param src_address source address to use (IP and port)
755 * @param dst_address destination address to use (IP and port)
756 * @param pkt4 where to write the assembled packet; must
757 * contain enough space for the IP header, UDP/TCP header
761 prepare_ipv4_packet (const void *payload,
762 size_t payload_length,
764 const struct GNUNET_TUN_TcpHeader *tcp_header,
765 const struct SocketAddress *src_address,
766 const struct SocketAddress *dst_address,
767 struct GNUNET_TUN_IPv4Header *pkt4)
771 len = payload_length;
775 len += sizeof (struct GNUNET_TUN_UdpHeader);
778 len += sizeof (struct GNUNET_TUN_TcpHeader);
779 GNUNET_assert (NULL != tcp_header);
785 if (len + sizeof (struct GNUNET_TUN_IPv4Header) > UINT16_MAX)
791 GNUNET_TUN_initialize_ipv4_header (pkt4,
794 &src_address->address.ipv4,
795 &dst_address->address.ipv4);
800 struct GNUNET_TUN_UdpHeader *pkt4_udp = (struct GNUNET_TUN_UdpHeader *) &pkt4[1];
802 pkt4_udp->source_port = htons (src_address->port);
803 pkt4_udp->destination_port = htons (dst_address->port);
804 pkt4_udp->len = htons ((uint16_t) payload_length);
805 GNUNET_TUN_calculate_udp4_checksum (pkt4,
809 GNUNET_memcpy (&pkt4_udp[1],
816 struct GNUNET_TUN_TcpHeader *pkt4_tcp = (struct GNUNET_TUN_TcpHeader *) &pkt4[1];
818 *pkt4_tcp = *tcp_header;
819 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
820 "Sending TCP packet from port %u to port %u\n",
823 pkt4_tcp->source_port = htons (src_address->port);
824 pkt4_tcp->destination_port = htons (dst_address->port);
825 GNUNET_TUN_calculate_tcp4_checksum (pkt4,
829 GNUNET_memcpy (&pkt4_tcp[1],
841 * Prepare an IPv6 packet for transmission via the TUN interface.
842 * Initializes the IP header and calculates checksums (IP+UDP/TCP).
843 * For UDP, the UDP header will be fully created, whereas for TCP
844 * only the ports and checksum will be filled in. So for TCP,
845 * a skeleton TCP header must be part of the provided payload.
847 * @param payload payload of the packet (starting with UDP payload or
848 * TCP header, depending on protocol)
849 * @param payload_length number of bytes in @a payload
850 * @param protocol IPPROTO_UDP or IPPROTO_TCP
851 * @param tcp_header skeleton TCP header data to send, NULL for UDP
852 * @param src_address source address to use (IP and port)
853 * @param dst_address destination address to use (IP and port)
854 * @param pkt6 where to write the assembled packet; must
855 * contain enough space for the IP header, UDP/TCP header
859 prepare_ipv6_packet (const void *payload,
860 size_t payload_length,
862 const struct GNUNET_TUN_TcpHeader *tcp_header,
863 const struct SocketAddress *src_address,
864 const struct SocketAddress *dst_address,
865 struct GNUNET_TUN_IPv6Header *pkt6)
869 len = payload_length;
873 len += sizeof (struct GNUNET_TUN_UdpHeader);
876 len += sizeof (struct GNUNET_TUN_TcpHeader);
882 if (len > UINT16_MAX)
888 GNUNET_TUN_initialize_ipv6_header (pkt6,
891 &src_address->address.ipv6,
892 &dst_address->address.ipv6);
898 struct GNUNET_TUN_UdpHeader *pkt6_udp = (struct GNUNET_TUN_UdpHeader *) &pkt6[1];
900 pkt6_udp->source_port = htons (src_address->port);
901 pkt6_udp->destination_port = htons (dst_address->port);
902 pkt6_udp->len = htons ((uint16_t) payload_length);
903 GNUNET_TUN_calculate_udp6_checksum (pkt6,
907 GNUNET_memcpy (&pkt6_udp[1],
914 struct GNUNET_TUN_TcpHeader *pkt6_tcp = (struct GNUNET_TUN_TcpHeader *) &pkt6[1];
916 /* GNUNET_memcpy first here as some TCP header fields are initialized this way! */
917 *pkt6_tcp = *tcp_header;
918 pkt6_tcp->source_port = htons (src_address->port);
919 pkt6_tcp->destination_port = htons (dst_address->port);
920 GNUNET_TUN_calculate_tcp6_checksum (pkt6,
924 GNUNET_memcpy (&pkt6_tcp[1],
937 * Send a TCP packet via the TUN interface.
939 * @param destination_address IP and port to use for the TCP packet's destination
940 * @param source_address IP and port to use for the TCP packet's source
941 * @param tcp_header header template to use
942 * @param payload payload of the TCP packet
943 * @param payload_length number of bytes in @a payload
946 send_tcp_packet_via_tun (const struct SocketAddress *destination_address,
947 const struct SocketAddress *source_address,
948 const struct GNUNET_TUN_TcpHeader *tcp_header,
950 size_t payload_length)
954 GNUNET_STATISTICS_update (stats,
955 gettext_noop ("# TCP packets sent via TUN"),
958 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
959 "Sending packet with %u bytes TCP payload via TUN\n",
960 (unsigned int) payload_length);
961 len = sizeof (struct GNUNET_MessageHeader) + sizeof (struct GNUNET_TUN_Layer2PacketHeader);
962 switch (source_address->af)
965 len += sizeof (struct GNUNET_TUN_IPv4Header);
968 len += sizeof (struct GNUNET_TUN_IPv6Header);
974 len += sizeof (struct GNUNET_TUN_TcpHeader);
975 len += payload_length;
976 if (len >= GNUNET_MAX_MESSAGE_SIZE)
982 char buf[len] GNUNET_ALIGN;
983 struct GNUNET_MessageHeader *hdr;
984 struct GNUNET_TUN_Layer2PacketHeader *tun;
986 hdr = (struct GNUNET_MessageHeader *) buf;
987 hdr->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
988 hdr->size = htons (len);
989 tun = (struct GNUNET_TUN_Layer2PacketHeader*) &hdr[1];
990 tun->flags = htons (0);
991 switch (source_address->af)
995 struct GNUNET_TUN_IPv4Header *ipv4
996 = (struct GNUNET_TUN_IPv4Header*) &tun[1];
998 tun->proto = htons (ETH_P_IPV4);
999 prepare_ipv4_packet (payload,
1004 destination_address,
1010 struct GNUNET_TUN_IPv6Header *ipv6
1011 = (struct GNUNET_TUN_IPv6Header*) &tun[1];
1013 tun->proto = htons (ETH_P_IPV6);
1014 prepare_ipv6_packet (payload,
1019 destination_address,
1027 if (NULL != helper_handle)
1028 (void) GNUNET_HELPER_send (helper_handle,
1029 (const struct GNUNET_MessageHeader*) buf,
1038 * Send an ICMP packet via the TUN interface.
1040 * @param destination_address IP to use for the ICMP packet's destination
1041 * @param source_address IP to use for the ICMP packet's source
1042 * @param icmp_header ICMP header to send
1043 * @param payload payload of the ICMP packet (does NOT include ICMP header)
1044 * @param payload_length number of bytes of data in @a payload
1047 send_icmp_packet_via_tun (const struct SocketAddress *destination_address,
1048 const struct SocketAddress *source_address,
1049 const struct GNUNET_TUN_IcmpHeader *icmp_header,
1050 const void *payload, size_t payload_length)
1053 struct GNUNET_TUN_IcmpHeader *icmp;
1055 GNUNET_STATISTICS_update (stats,
1056 gettext_noop ("# ICMP packets sent via TUN"),
1058 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1059 "Sending packet with %u bytes ICMP payload via TUN\n",
1060 (unsigned int) payload_length);
1061 len = sizeof (struct GNUNET_MessageHeader) + sizeof (struct GNUNET_TUN_Layer2PacketHeader);
1062 switch (destination_address->af)
1065 len += sizeof (struct GNUNET_TUN_IPv4Header);
1068 len += sizeof (struct GNUNET_TUN_IPv6Header);
1074 len += sizeof (struct GNUNET_TUN_IcmpHeader);
1075 len += payload_length;
1076 if (len >= GNUNET_MAX_MESSAGE_SIZE)
1082 char buf[len] GNUNET_ALIGN;
1083 struct GNUNET_MessageHeader *hdr;
1084 struct GNUNET_TUN_Layer2PacketHeader *tun;
1086 hdr= (struct GNUNET_MessageHeader *) buf;
1087 hdr->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
1088 hdr->size = htons (len);
1089 tun = (struct GNUNET_TUN_Layer2PacketHeader*) &hdr[1];
1090 tun->flags = htons (0);
1091 switch (source_address->af)
1095 struct GNUNET_TUN_IPv4Header * ipv4 = (struct GNUNET_TUN_IPv4Header*) &tun[1];
1097 tun->proto = htons (ETH_P_IPV4);
1098 GNUNET_TUN_initialize_ipv4_header (ipv4,
1100 sizeof (struct GNUNET_TUN_IcmpHeader) + payload_length,
1101 &source_address->address.ipv4,
1102 &destination_address->address.ipv4);
1103 icmp = (struct GNUNET_TUN_IcmpHeader*) &ipv4[1];
1108 struct GNUNET_TUN_IPv6Header * ipv6 = (struct GNUNET_TUN_IPv6Header*) &tun[1];
1110 tun->proto = htons (ETH_P_IPV6);
1111 GNUNET_TUN_initialize_ipv6_header (ipv6,
1113 sizeof (struct GNUNET_TUN_IcmpHeader) + payload_length,
1114 &source_address->address.ipv6,
1115 &destination_address->address.ipv6);
1116 icmp = (struct GNUNET_TUN_IcmpHeader*) &ipv6[1];
1123 *icmp = *icmp_header;
1124 GNUNET_memcpy (&icmp[1],
1127 GNUNET_TUN_calculate_icmp_checksum (icmp,
1130 if (NULL != helper_handle)
1131 (void) GNUNET_HELPER_send (helper_handle,
1132 (const struct GNUNET_MessageHeader*) buf,
1140 * We need to create a (unique) fresh local address (IP+port).
1143 * @param af desired address family
1144 * @param proto desired protocol (IPPROTO_UDP or IPPROTO_TCP)
1145 * @param local_address address to initialize
1148 setup_fresh_address (int af,
1150 struct SocketAddress *local_address)
1152 local_address->af = af;
1153 local_address->proto = (uint8_t) proto;
1154 /* default "local" port range is often 32768--61000,
1155 so we pick a random value in that range */
1156 if ( ( (af == AF_INET) && (proto == IPPROTO_ICMP) ) ||
1157 ( (af == AF_INET6) && (proto == IPPROTO_ICMPV6) ) )
1158 local_address->port = 0;
1161 = (uint16_t) 32768 + GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
1167 struct in_addr addr;
1168 struct in_addr mask;
1171 addr = exit_ipv4addr;
1172 mask = exit_ipv4mask;
1173 if (0 == ~mask.s_addr)
1175 /* only one valid IP anyway */
1176 local_address->address.ipv4 = addr;
1179 /* Given 192.168.0.1/255.255.0.0, we want a mask
1180 of '192.168.255.255', thus: */
1181 mask.s_addr = addr.s_addr | ~mask.s_addr;
1182 /* Pick random IPv4 address within the subnet, except 'addr' or 'mask' itself */
1185 rnd.s_addr = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
1187 local_address->address.ipv4.s_addr = (addr.s_addr | rnd.s_addr) & mask.s_addr;
1189 while ( (local_address->address.ipv4.s_addr == addr.s_addr) ||
1190 (local_address->address.ipv4.s_addr == mask.s_addr) );
1195 struct in6_addr addr;
1196 struct in6_addr mask;
1197 struct in6_addr rnd;
1200 addr = exit_ipv6addr;
1201 GNUNET_assert (ipv6prefix < 128);
1202 if (ipv6prefix == 127)
1204 /* only one valid IP anyway */
1205 local_address->address.ipv6 = addr;
1208 /* Given ABCD::/96, we want a mask of 'ABCD::FFFF:FFFF,
1211 for (i=127;i>=ipv6prefix;i--)
1212 mask.s6_addr[i / 8] |= (1 << (i % 8));
1214 /* Pick random IPv6 address within the subnet, except 'addr' or 'mask' itself */
1219 rnd.s6_addr[i] = (unsigned char) GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
1221 local_address->address.ipv6.s6_addr[i]
1222 = (addr.s6_addr[i] | rnd.s6_addr[i]) & mask.s6_addr[i];
1225 while ( (0 == memcmp (&local_address->address.ipv6,
1227 sizeof (struct in6_addr))) ||
1228 (0 == memcmp (&local_address->address.ipv6,
1230 sizeof (struct in6_addr))) );
1240 * We are starting a fresh connection (TCP or UDP) and need
1241 * to pick a source port and IP address (within the correct
1242 * range and address family) to associate replies with the
1243 * connection / correct cadet channel. This function generates
1244 * a "fresh" source IP and source port number for a connection
1245 * After picking a good source address, this function sets up
1246 * the state in the 'connections_map' and 'connections_heap'
1247 * to allow finding the state when needed later. The function
1248 * also makes sure that we remain within memory limits by
1249 * cleaning up 'old' states.
1251 * @param state skeleton state to setup a record for; should
1252 * 'state->specifics.tcp_udp.ri.remote_address' filled in so that
1253 * this code can determine which AF/protocol is
1254 * going to be used (the 'channel' should also
1255 * already be set); after calling this function,
1256 * heap_node and the local_address will be
1257 * also initialized (heap_node != NULL can be
1258 * used to test if a state has been fully setup).
1261 setup_state_record (struct ChannelState *state)
1263 struct GNUNET_HashCode key;
1264 struct ChannelState *s;
1266 /* generate fresh, unique address */
1269 if (NULL == state->specifics.tcp_udp.serv)
1270 setup_fresh_address (state->specifics.tcp_udp.ri.remote_address.af,
1271 state->specifics.tcp_udp.ri.remote_address.proto,
1272 &state->specifics.tcp_udp.ri.local_address);
1274 setup_fresh_address (state->specifics.tcp_udp.serv->address.af,
1275 state->specifics.tcp_udp.serv->address.proto,
1276 &state->specifics.tcp_udp.ri.local_address);
1278 get_redirect_state (state->specifics.tcp_udp.ri.remote_address.af,
1279 state->specifics.tcp_udp.ri.remote_address.proto,
1280 &state->specifics.tcp_udp.ri.remote_address.address,
1281 state->specifics.tcp_udp.ri.remote_address.port,
1282 &state->specifics.tcp_udp.ri.local_address.address,
1283 state->specifics.tcp_udp.ri.local_address.port,
1286 char buf[INET6_ADDRSTRLEN];
1287 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1288 "Picked local address %s:%u for new connection\n",
1289 inet_ntop (state->specifics.tcp_udp.ri.local_address.af,
1290 &state->specifics.tcp_udp.ri.local_address.address,
1293 (unsigned int) state->specifics.tcp_udp.ri.local_address.port);
1295 state->specifics.tcp_udp.state_key = key;
1296 GNUNET_assert (GNUNET_OK ==
1297 GNUNET_CONTAINER_multihashmap_put (connections_map,
1299 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
1300 state->specifics.tcp_udp.heap_node
1301 = GNUNET_CONTAINER_heap_insert (connections_heap,
1303 GNUNET_TIME_absolute_get ().abs_value_us);
1304 while (GNUNET_CONTAINER_heap_get_size (connections_heap) > max_connections)
1306 s = GNUNET_CONTAINER_heap_remove_root (connections_heap);
1307 GNUNET_assert (state != s);
1308 s->specifics.tcp_udp.heap_node = NULL;
1309 GNUNET_CADET_channel_destroy (s->channel);
1310 GNUNET_assert (GNUNET_OK ==
1311 GNUNET_CONTAINER_multihashmap_remove (connections_map,
1312 &s->specifics.tcp_udp.state_key,
1320 * Send a UDP packet via the TUN interface.
1322 * @param destination_address IP and port to use for the UDP packet's destination
1323 * @param source_address IP and port to use for the UDP packet's source
1324 * @param payload payload of the UDP packet (does NOT include UDP header)
1325 * @param payload_length number of bytes of data in @a payload
1328 send_udp_packet_via_tun (const struct SocketAddress *destination_address,
1329 const struct SocketAddress *source_address,
1330 const void *payload, size_t payload_length)
1334 GNUNET_STATISTICS_update (stats,
1335 gettext_noop ("# UDP packets sent via TUN"),
1337 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1338 "Sending packet with %u bytes UDP payload via TUN\n",
1339 (unsigned int) payload_length);
1340 len = sizeof (struct GNUNET_MessageHeader) + sizeof (struct GNUNET_TUN_Layer2PacketHeader);
1341 switch (source_address->af)
1344 len += sizeof (struct GNUNET_TUN_IPv4Header);
1347 len += sizeof (struct GNUNET_TUN_IPv6Header);
1353 len += sizeof (struct GNUNET_TUN_UdpHeader);
1354 len += payload_length;
1355 if (len >= GNUNET_MAX_MESSAGE_SIZE)
1361 char buf[len] GNUNET_ALIGN;
1362 struct GNUNET_MessageHeader *hdr;
1363 struct GNUNET_TUN_Layer2PacketHeader *tun;
1365 hdr= (struct GNUNET_MessageHeader *) buf;
1366 hdr->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
1367 hdr->size = htons (len);
1368 tun = (struct GNUNET_TUN_Layer2PacketHeader*) &hdr[1];
1369 tun->flags = htons (0);
1370 switch (source_address->af)
1374 struct GNUNET_TUN_IPv4Header * ipv4 = (struct GNUNET_TUN_IPv4Header*) &tun[1];
1376 tun->proto = htons (ETH_P_IPV4);
1377 prepare_ipv4_packet (payload,
1382 destination_address,
1388 struct GNUNET_TUN_IPv6Header * ipv6 = (struct GNUNET_TUN_IPv6Header*) &tun[1];
1390 tun->proto = htons (ETH_P_IPV6);
1391 prepare_ipv6_packet (payload,
1396 destination_address,
1404 if (NULL != helper_handle)
1405 (void) GNUNET_HELPER_send (helper_handle,
1406 (const struct GNUNET_MessageHeader*) buf,
1414 * Check a request to forward UDP data to the Internet via this peer.
1416 * @param cls our `struct ChannelState *`
1417 * @param msg the actual message
1418 * @return #GNUNET_OK to keep the connection open,
1419 * #GNUNET_SYSERR to close it (signal serious error)
1422 check_udp_remote (void *cls,
1423 const struct GNUNET_EXIT_UdpInternetMessage *msg)
1425 struct ChannelState *state = cls;
1427 if (GNUNET_YES == state->is_dns)
1429 GNUNET_break_op (0);
1430 return GNUNET_SYSERR;
1437 * Process a request to forward UDP data to the Internet via this peer.
1439 * @param cls our `struct ChannelState *`
1440 * @param msg the actual message
1443 handle_udp_remote (void *cls,
1444 const struct GNUNET_EXIT_UdpInternetMessage *msg)
1446 struct ChannelState *state = cls;
1447 uint16_t pkt_len = ntohs (msg->header.size) - sizeof (struct GNUNET_EXIT_UdpInternetMessage);
1448 const struct in_addr *v4;
1449 const struct in6_addr *v6;
1450 const void *payload;
1453 if (GNUNET_SYSERR == state->is_dns)
1455 /* channel is UDP/TCP from now on */
1456 state->is_dns = GNUNET_NO;
1458 GNUNET_STATISTICS_update (stats,
1459 gettext_noop ("# Bytes received from CADET"),
1460 pkt_len, GNUNET_NO);
1461 GNUNET_STATISTICS_update (stats,
1462 gettext_noop ("# UDP IP-exit requests received via cadet"),
1464 af = (int) ntohl (msg->af);
1465 state->specifics.tcp_udp.ri.remote_address.af = af;
1469 if (pkt_len < sizeof (struct in_addr))
1471 GNUNET_break_op (0);
1476 GNUNET_break_op (0);
1479 v4 = (const struct in_addr*) &msg[1];
1481 pkt_len -= sizeof (struct in_addr);
1482 state->specifics.tcp_udp.ri.remote_address.address.ipv4 = *v4;
1485 if (pkt_len < sizeof (struct in6_addr))
1487 GNUNET_break_op (0);
1492 GNUNET_break_op (0);
1495 v6 = (const struct in6_addr*) &msg[1];
1497 pkt_len -= sizeof (struct in6_addr);
1498 state->specifics.tcp_udp.ri.remote_address.address.ipv6 = *v6;
1501 GNUNET_break_op (0);
1505 char buf[INET6_ADDRSTRLEN];
1506 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1507 "Received data from %s for forwarding to UDP %s:%u\n",
1508 GNUNET_i2s (&state->peer),
1510 &state->specifics.tcp_udp.ri.remote_address.address,
1512 (unsigned int) ntohs (msg->destination_port));
1514 state->specifics.tcp_udp.ri.remote_address.proto = IPPROTO_UDP;
1515 state->specifics.tcp_udp.ri.remote_address.port = msg->destination_port;
1516 if (NULL == state->specifics.tcp_udp.heap_node)
1517 setup_state_record (state);
1518 if (0 != ntohs (msg->source_port))
1519 state->specifics.tcp_udp.ri.local_address.port = msg->source_port;
1520 send_udp_packet_via_tun (&state->specifics.tcp_udp.ri.remote_address,
1521 &state->specifics.tcp_udp.ri.local_address,
1524 GNUNET_CADET_receive_done (state->channel);
1529 * Check a request via cadet to send a request to a UDP service
1530 * offered by this system.
1532 * @param cls our `struct ChannelState *`
1533 * @param msg the actual message
1534 * @return #GNUNET_OK to keep the connection open,
1535 * #GNUNET_SYSERR to close it (signal serious error)
1538 check_udp_service (void *cls,
1539 const struct GNUNET_EXIT_UdpServiceMessage *msg)
1541 struct ChannelState *state = cls;
1543 if (NULL == state->specifics.tcp_udp.serv)
1545 GNUNET_break_op (0);
1546 return GNUNET_SYSERR;
1553 * Process a request via cadet to send a request to a UDP service
1554 * offered by this system.
1556 * @param cls our `struct ChannelState *`
1557 * @param msg the actual message
1560 handle_udp_service (void *cls,
1561 const struct GNUNET_EXIT_UdpServiceMessage *msg)
1563 struct ChannelState *state = cls;
1564 uint16_t pkt_len = ntohs (msg->header.size) - sizeof (struct GNUNET_EXIT_UdpServiceMessage);
1566 GNUNET_STATISTICS_update (stats,
1567 gettext_noop ("# Bytes received from CADET"),
1568 pkt_len, GNUNET_NO);
1569 GNUNET_STATISTICS_update (stats,
1570 gettext_noop ("# UDP service requests received via cadet"),
1572 LOG (GNUNET_ERROR_TYPE_DEBUG,
1573 "Received data from %s for forwarding to UDP service %s on port %u\n",
1574 GNUNET_i2s (&state->peer),
1575 GNUNET_h2s (&state->specifics.tcp_udp.serv->descriptor),
1576 (unsigned int) ntohs (msg->destination_port));
1577 setup_state_record (state);
1578 if (0 != ntohs (msg->source_port))
1579 state->specifics.tcp_udp.ri.local_address.port = msg->source_port;
1580 send_udp_packet_via_tun (&state->specifics.tcp_udp.ri.remote_address,
1581 &state->specifics.tcp_udp.ri.local_address,
1584 GNUNET_CADET_receive_done (state->channel);
1589 * Process a request via cadet to send a request to a TCP service
1590 * offered by this system.
1592 * @param cls our `struct ChannelState *`
1593 * @param start the actual message
1594 * @return #GNUNET_OK to keep the connection open,
1595 * #GNUNET_SYSERR to close it (signal serious error)
1598 handle_tcp_service (void *cls,
1599 const struct GNUNET_EXIT_TcpServiceStartMessage *start)
1601 struct ChannelState *state = cls;
1602 uint16_t pkt_len = ntohs (start->header.size) - sizeof (struct GNUNET_EXIT_TcpServiceStartMessage);
1604 if (GNUNET_SYSERR == state->is_dns)
1606 /* channel is UDP/TCP from now on */
1607 state->is_dns = GNUNET_NO;
1609 GNUNET_STATISTICS_update (stats,
1610 gettext_noop ("# TCP service creation requests received via cadet"),
1613 GNUNET_STATISTICS_update (stats,
1614 gettext_noop ("# Bytes received from CADET"),
1617 GNUNET_break_op (ntohl (start->reserved) == 0);
1618 /* setup fresh connection */
1619 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1620 "Received data from %s for forwarding to TCP service %s on port %u\n",
1621 GNUNET_i2s (&state->peer),
1622 GNUNET_h2s (&state->specifics.tcp_udp.serv->descriptor),
1623 (unsigned int) ntohs (start->tcp_header.destination_port));
1624 setup_state_record (state);
1625 send_tcp_packet_via_tun (&state->specifics.tcp_udp.ri.remote_address,
1626 &state->specifics.tcp_udp.ri.local_address,
1630 GNUNET_CADET_receive_done (state->channel);
1635 * Check a request to forward TCP data to the Internet via this peer.
1637 * @param cls our `struct ChannelState *`
1638 * @param start the actual message
1639 * @return #GNUNET_OK to keep the connection open,
1640 * #GNUNET_SYSERR to close it (signal serious error)
1643 check_tcp_remote (void *cls,
1644 const struct GNUNET_EXIT_TcpInternetStartMessage *start)
1646 struct ChannelState *state = cls;
1650 GNUNET_break_op (0);
1651 return GNUNET_SYSERR;
1653 if (GNUNET_YES == state->is_dns)
1655 GNUNET_break_op (0);
1656 return GNUNET_SYSERR;
1658 if ( (NULL != state->specifics.tcp_udp.serv) ||
1659 (NULL != state->specifics.tcp_udp.heap_node) )
1661 GNUNET_break_op (0);
1662 return GNUNET_SYSERR;
1664 if (start->tcp_header.off * 4 < sizeof (struct GNUNET_TUN_TcpHeader))
1666 GNUNET_break_op (0);
1667 return GNUNET_SYSERR;
1674 * Process a request to forward TCP data to the Internet via this peer.
1676 * @param cls our `struct ChannelState *`
1677 * @param start the actual message
1680 handle_tcp_remote (void *cls,
1681 const struct GNUNET_EXIT_TcpInternetStartMessage *start)
1683 struct ChannelState *state = cls;
1684 uint16_t pkt_len = ntohs (start->header.size) - sizeof (struct GNUNET_EXIT_TcpInternetStartMessage);
1685 const struct in_addr *v4;
1686 const struct in6_addr *v6;
1687 const void *payload;
1690 if (GNUNET_SYSERR == state->is_dns)
1692 /* channel is UDP/TCP from now on */
1693 state->is_dns = GNUNET_NO;
1695 GNUNET_STATISTICS_update (stats,
1696 gettext_noop ("# Bytes received from CADET"),
1697 pkt_len, GNUNET_NO);
1698 GNUNET_STATISTICS_update (stats,
1699 gettext_noop ("# TCP IP-exit creation requests received via cadet"),
1701 af = (int) ntohl (start->af);
1702 state->specifics.tcp_udp.ri.remote_address.af = af;
1706 if (pkt_len < sizeof (struct in_addr))
1708 GNUNET_break_op (0);
1713 GNUNET_break_op (0);
1716 v4 = (const struct in_addr*) &start[1];
1718 pkt_len -= sizeof (struct in_addr);
1719 state->specifics.tcp_udp.ri.remote_address.address.ipv4 = *v4;
1722 if (pkt_len < sizeof (struct in6_addr))
1724 GNUNET_break_op (0);
1729 GNUNET_break_op (0);
1732 v6 = (const struct in6_addr*) &start[1];
1734 pkt_len -= sizeof (struct in6_addr);
1735 state->specifics.tcp_udp.ri.remote_address.address.ipv6 = *v6;
1738 GNUNET_break_op (0);
1742 char buf[INET6_ADDRSTRLEN];
1743 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1744 "Received payload from %s for existing TCP stream to %s:%u\n",
1745 GNUNET_i2s (&state->peer),
1747 &state->specifics.tcp_udp.ri.remote_address.address,
1749 (unsigned int) ntohs (start->tcp_header.destination_port));
1751 state->specifics.tcp_udp.ri.remote_address.proto = IPPROTO_TCP;
1752 state->specifics.tcp_udp.ri.remote_address.port = ntohs (start->tcp_header.destination_port);
1753 setup_state_record (state);
1754 send_tcp_packet_via_tun (&state->specifics.tcp_udp.ri.remote_address,
1755 &state->specifics.tcp_udp.ri.local_address,
1759 GNUNET_CADET_receive_done (state->channel);
1764 * Check a request to forward TCP data on an established
1765 * connection via this peer.
1767 * @param cls our `struct ChannelState *`
1768 * @param message the actual message
1769 * @return #GNUNET_OK to keep the connection open,
1770 * #GNUNET_SYSERR to close it (signal serious error)
1773 check_tcp_data (void *cls,
1774 const struct GNUNET_EXIT_TcpDataMessage *data)
1776 struct ChannelState *state = cls;
1778 if ( (NULL == state) ||
1779 (NULL == state->specifics.tcp_udp.heap_node) )
1781 /* connection should have been up! */
1782 GNUNET_STATISTICS_update (stats,
1783 gettext_noop ("# TCP DATA requests dropped (no session)"),
1785 GNUNET_break_op (0);
1786 return GNUNET_SYSERR;
1788 if (data->tcp_header.off * 4 < sizeof (struct GNUNET_TUN_TcpHeader))
1790 GNUNET_break_op (0);
1791 return GNUNET_SYSERR;
1793 if (GNUNET_YES == state->is_dns)
1795 GNUNET_break_op (0);
1796 return GNUNET_SYSERR;
1803 * Process a request to forward TCP data on an established
1804 * connection via this peer.
1806 * @param cls our `struct ChannelState *`
1807 * @param message the actual message
1810 handle_tcp_data (void *cls,
1811 const struct GNUNET_EXIT_TcpDataMessage *data)
1813 struct ChannelState *state = cls;
1814 uint16_t pkt_len = ntohs (data->header.size) - sizeof (struct GNUNET_EXIT_TcpDataMessage);
1816 GNUNET_STATISTICS_update (stats,
1817 gettext_noop ("# Bytes received from CADET"),
1818 pkt_len, GNUNET_NO);
1819 GNUNET_STATISTICS_update (stats,
1820 gettext_noop ("# TCP data requests received via cadet"),
1822 if (GNUNET_SYSERR == state->is_dns)
1824 /* channel is UDP/TCP from now on */
1825 state->is_dns = GNUNET_NO;
1828 GNUNET_break_op (ntohl (data->reserved) == 0);
1830 char buf[INET6_ADDRSTRLEN];
1831 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1832 "Received additional %u bytes of data from %s for TCP stream to %s:%u\n",
1834 GNUNET_i2s (&state->peer),
1835 inet_ntop (state->specifics.tcp_udp.ri.remote_address.af,
1836 &state->specifics.tcp_udp.ri.remote_address.address,
1838 (unsigned int) state->specifics.tcp_udp.ri.remote_address.port);
1841 send_tcp_packet_via_tun (&state->specifics.tcp_udp.ri.remote_address,
1842 &state->specifics.tcp_udp.ri.local_address,
1845 GNUNET_CADET_receive_done (state->channel);
1850 * Synthesize a plausible ICMP payload for an ICMPv4 error
1851 * response on the given channel.
1853 * @param state channel information
1854 * @param ipp IPv6 header to fill in (ICMP payload)
1855 * @param udp "UDP" header to fill in (ICMP payload); might actually
1856 * also be the first 8 bytes of the TCP header
1859 make_up_icmpv4_payload (struct ChannelState *state,
1860 struct GNUNET_TUN_IPv4Header *ipp,
1861 struct GNUNET_TUN_UdpHeader *udp)
1863 GNUNET_TUN_initialize_ipv4_header (ipp,
1864 state->specifics.tcp_udp.ri.remote_address.proto,
1865 sizeof (struct GNUNET_TUN_TcpHeader),
1866 &state->specifics.tcp_udp.ri.remote_address.address.ipv4,
1867 &state->specifics.tcp_udp.ri.local_address.address.ipv4);
1868 udp->source_port = htons (state->specifics.tcp_udp.ri.remote_address.port);
1869 udp->destination_port = htons (state->specifics.tcp_udp.ri.local_address.port);
1870 udp->len = htons (0);
1871 udp->crc = htons (0);
1876 * Synthesize a plausible ICMP payload for an ICMPv6 error
1877 * response on the given channel.
1879 * @param state channel information
1880 * @param ipp IPv6 header to fill in (ICMP payload)
1881 * @param udp "UDP" header to fill in (ICMP payload); might actually
1882 * also be the first 8 bytes of the TCP header
1885 make_up_icmpv6_payload (struct ChannelState *state,
1886 struct GNUNET_TUN_IPv6Header *ipp,
1887 struct GNUNET_TUN_UdpHeader *udp)
1889 GNUNET_TUN_initialize_ipv6_header (ipp,
1890 state->specifics.tcp_udp.ri.remote_address.proto,
1891 sizeof (struct GNUNET_TUN_TcpHeader),
1892 &state->specifics.tcp_udp.ri.remote_address.address.ipv6,
1893 &state->specifics.tcp_udp.ri.local_address.address.ipv6);
1894 udp->source_port = htons (state->specifics.tcp_udp.ri.remote_address.port);
1895 udp->destination_port = htons (state->specifics.tcp_udp.ri.local_address.port);
1896 udp->len = htons (0);
1897 udp->crc = htons (0);
1902 * Check a request to forward ICMP data to the Internet via this peer.
1904 * @param cls our `struct ChannelState *`
1905 * @param msg the actual message
1906 * @return #GNUNET_OK to keep the connection open,
1907 * #GNUNET_SYSERR to close it (signal serious error)
1910 check_icmp_remote (void *cls,
1911 const struct GNUNET_EXIT_IcmpInternetMessage *msg)
1913 struct ChannelState *state = cls;
1915 if (GNUNET_YES == state->is_dns)
1917 GNUNET_break_op (0);
1918 return GNUNET_SYSERR;
1925 * Process a request to forward ICMP data to the Internet via this peer.
1927 * @param cls our `struct ChannelState *`
1928 * @param msg the actual message
1931 handle_icmp_remote (void *cls,
1932 const struct GNUNET_EXIT_IcmpInternetMessage *msg)
1934 struct ChannelState *state = cls;
1935 uint16_t pkt_len = ntohs (msg->header.size) - sizeof (struct GNUNET_EXIT_IcmpInternetMessage);
1936 const struct in_addr *v4;
1937 const struct in6_addr *v6;
1938 const void *payload;
1939 char buf[sizeof (struct GNUNET_TUN_IPv6Header) + 8] GNUNET_ALIGN;
1942 if (GNUNET_SYSERR == state->is_dns)
1944 /* channel is UDP/TCP from now on */
1945 state->is_dns = GNUNET_NO;
1947 GNUNET_STATISTICS_update (stats,
1948 gettext_noop ("# Bytes received from CADET"),
1949 pkt_len, GNUNET_NO);
1950 GNUNET_STATISTICS_update (stats,
1951 gettext_noop ("# ICMP IP-exit requests received via cadet"),
1954 af = (int) ntohl (msg->af);
1955 if ( (NULL != state->specifics.tcp_udp.heap_node) &&
1956 (af != state->specifics.tcp_udp.ri.remote_address.af) )
1958 /* other peer switched AF on this channel; not allowed */
1959 GNUNET_break_op (0);
1966 if (pkt_len < sizeof (struct in_addr))
1968 GNUNET_break_op (0);
1973 GNUNET_break_op (0);
1976 v4 = (const struct in_addr*) &msg[1];
1978 pkt_len -= sizeof (struct in_addr);
1979 state->specifics.tcp_udp.ri.remote_address.address.ipv4 = *v4;
1980 if (NULL == state->specifics.tcp_udp.heap_node)
1982 state->specifics.tcp_udp.ri.remote_address.af = af;
1983 state->specifics.tcp_udp.ri.remote_address.proto = IPPROTO_ICMP;
1984 setup_state_record (state);
1986 /* check that ICMP type is something we want to support
1987 and possibly make up payload! */
1988 switch (msg->icmp_header.type)
1990 case GNUNET_TUN_ICMPTYPE_ECHO_REPLY:
1991 case GNUNET_TUN_ICMPTYPE_ECHO_REQUEST:
1993 case GNUNET_TUN_ICMPTYPE_DESTINATION_UNREACHABLE:
1994 case GNUNET_TUN_ICMPTYPE_SOURCE_QUENCH:
1995 case GNUNET_TUN_ICMPTYPE_TIME_EXCEEDED:
1998 GNUNET_break_op (0);
2001 /* make up payload */
2003 struct GNUNET_TUN_IPv4Header *ipp = (struct GNUNET_TUN_IPv4Header *) buf;
2004 struct GNUNET_TUN_UdpHeader *udp = (struct GNUNET_TUN_UdpHeader *) &ipp[1];
2006 GNUNET_assert (8 == sizeof (struct GNUNET_TUN_UdpHeader));
2007 pkt_len = sizeof (struct GNUNET_TUN_IPv4Header) + 8;
2008 make_up_icmpv4_payload (state,
2015 GNUNET_break_op (0);
2016 GNUNET_STATISTICS_update (stats,
2017 gettext_noop ("# ICMPv4 packets dropped (type not allowed)"),
2024 if (pkt_len < sizeof (struct in6_addr))
2026 GNUNET_break_op (0);
2031 GNUNET_break_op (0);
2034 v6 = (const struct in6_addr*) &msg[1];
2036 pkt_len -= sizeof (struct in6_addr);
2037 state->specifics.tcp_udp.ri.remote_address.address.ipv6 = *v6;
2038 if (NULL == state->specifics.tcp_udp.heap_node)
2040 state->specifics.tcp_udp.ri.remote_address.af = af;
2041 state->specifics.tcp_udp.ri.remote_address.proto = IPPROTO_ICMPV6;
2042 setup_state_record (state);
2044 /* check that ICMP type is something we want to support
2045 and possibly make up payload! */
2046 switch (msg->icmp_header.type)
2048 case GNUNET_TUN_ICMPTYPE6_ECHO_REPLY:
2049 case GNUNET_TUN_ICMPTYPE6_ECHO_REQUEST:
2051 case GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE:
2052 case GNUNET_TUN_ICMPTYPE6_PACKET_TOO_BIG:
2053 case GNUNET_TUN_ICMPTYPE6_TIME_EXCEEDED:
2054 case GNUNET_TUN_ICMPTYPE6_PARAMETER_PROBLEM:
2057 GNUNET_break_op (0);
2060 /* make up payload */
2062 struct GNUNET_TUN_IPv6Header *ipp = (struct GNUNET_TUN_IPv6Header *) buf;
2063 struct GNUNET_TUN_UdpHeader *udp = (struct GNUNET_TUN_UdpHeader *) &ipp[1];
2065 GNUNET_assert (8 == sizeof (struct GNUNET_TUN_UdpHeader));
2066 pkt_len = sizeof (struct GNUNET_TUN_IPv6Header) + 8;
2067 make_up_icmpv6_payload (state,
2074 GNUNET_break_op (0);
2075 GNUNET_STATISTICS_update (stats,
2076 gettext_noop ("# ICMPv6 packets dropped (type not allowed)"),
2084 GNUNET_break_op (0);
2089 char buf[INET6_ADDRSTRLEN];
2090 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2091 "Received ICMP data from %s for forwarding to %s\n",
2092 GNUNET_i2s (&state->peer),
2094 &state->specifics.tcp_udp.ri.remote_address.address,
2095 buf, sizeof (buf)));
2097 send_icmp_packet_via_tun (&state->specifics.tcp_udp.ri.remote_address,
2098 &state->specifics.tcp_udp.ri.local_address,
2101 GNUNET_CADET_receive_done (state->channel);
2106 * Setup ICMP payload for ICMP error messages. Called
2107 * for both IPv4 and IPv6 addresses.
2109 * @param state context for creating the IP Packet
2110 * @param buf where to create the payload, has at least
2111 * sizeof (struct GNUNET_TUN_IPv6Header) + 8 bytes
2112 * @return number of bytes of payload we created in buf
2115 make_up_icmp_service_payload (struct ChannelState *state,
2118 switch (state->specifics.tcp_udp.serv->address.af)
2122 struct GNUNET_TUN_IPv4Header *ipv4;
2123 struct GNUNET_TUN_UdpHeader *udp;
2125 ipv4 = (struct GNUNET_TUN_IPv4Header *)buf;
2126 udp = (struct GNUNET_TUN_UdpHeader *) &ipv4[1];
2127 make_up_icmpv4_payload (state,
2130 GNUNET_assert (8 == sizeof (struct GNUNET_TUN_UdpHeader));
2131 return sizeof (struct GNUNET_TUN_IPv4Header) + 8;
2136 struct GNUNET_TUN_IPv6Header *ipv6;
2137 struct GNUNET_TUN_UdpHeader *udp;
2139 ipv6 = (struct GNUNET_TUN_IPv6Header *)buf;
2140 udp = (struct GNUNET_TUN_UdpHeader *) &ipv6[1];
2141 make_up_icmpv6_payload (state,
2144 GNUNET_assert (8 == sizeof (struct GNUNET_TUN_UdpHeader));
2145 return sizeof (struct GNUNET_TUN_IPv6Header) + 8;
2156 * Check a request via cadet to send ICMP data to a service
2157 * offered by this system.
2159 * @param cls our `struct ChannelState *`
2160 * @param msg the actual message
2161 * @return #GNUNET_OK to keep the connection open,
2162 * #GNUNET_SYSERR to close it (signal serious error)
2165 check_icmp_service (void *cls,
2166 const struct GNUNET_EXIT_IcmpServiceMessage *msg)
2168 struct ChannelState *state = cls;
2170 if (GNUNET_YES == state->is_dns)
2172 GNUNET_break_op (0);
2173 return GNUNET_SYSERR;
2175 if (NULL == state->specifics.tcp_udp.serv)
2177 GNUNET_break_op (0);
2178 return GNUNET_SYSERR;
2185 * Process a request via cadet to send ICMP data to a service
2186 * offered by this system.
2188 * @param cls our `struct ChannelState *`
2189 * @param msg the actual message
2192 handle_icmp_service (void *cls,
2193 const struct GNUNET_EXIT_IcmpServiceMessage *msg)
2195 struct ChannelState *state = cls;
2196 uint16_t pkt_len = ntohs (msg->header.size) - sizeof (struct GNUNET_EXIT_IcmpServiceMessage);
2197 struct GNUNET_TUN_IcmpHeader icmp;
2198 char buf[sizeof (struct GNUNET_TUN_IPv6Header) + 8] GNUNET_ALIGN;
2199 const void *payload;
2201 GNUNET_STATISTICS_update (stats,
2202 gettext_noop ("# Bytes received from CADET"),
2203 pkt_len, GNUNET_NO);
2204 GNUNET_STATISTICS_update (stats,
2205 gettext_noop ("# ICMP service requests received via cadet"),
2207 /* check that we got at least a valid header */
2208 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2209 "Received data from %s for forwarding to ICMP service %s\n",
2210 GNUNET_i2s (&state->peer),
2211 GNUNET_h2s (&state->specifics.tcp_udp.serv->descriptor));
2212 icmp = msg->icmp_header;
2214 state->specifics.tcp_udp.ri.remote_address
2215 = state->specifics.tcp_udp.serv->address;
2216 setup_state_record (state);
2218 /* check that ICMP type is something we want to support,
2219 perform ICMP PT if needed ans possibly make up payload */
2223 switch (msg->icmp_header.type)
2225 case GNUNET_TUN_ICMPTYPE_ECHO_REPLY:
2226 if (state->specifics.tcp_udp.serv->address.af == AF_INET6)
2227 icmp.type = GNUNET_TUN_ICMPTYPE6_ECHO_REPLY;
2229 case GNUNET_TUN_ICMPTYPE_ECHO_REQUEST:
2230 if (state->specifics.tcp_udp.serv->address.af == AF_INET6)
2231 icmp.type = GNUNET_TUN_ICMPTYPE6_ECHO_REQUEST;
2233 case GNUNET_TUN_ICMPTYPE_DESTINATION_UNREACHABLE:
2234 if (state->specifics.tcp_udp.serv->address.af == AF_INET6)
2235 icmp.type = GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE;
2238 GNUNET_break_op (0);
2242 pkt_len = make_up_icmp_service_payload (state, buf);
2244 case GNUNET_TUN_ICMPTYPE_TIME_EXCEEDED:
2245 if (state->specifics.tcp_udp.serv->address.af == AF_INET6)
2246 icmp.type = GNUNET_TUN_ICMPTYPE6_TIME_EXCEEDED;
2249 GNUNET_break_op (0);
2253 pkt_len = make_up_icmp_service_payload (state, buf);
2255 case GNUNET_TUN_ICMPTYPE_SOURCE_QUENCH:
2256 if (state->specifics.tcp_udp.serv->address.af == AF_INET6)
2258 GNUNET_STATISTICS_update (stats,
2259 gettext_noop ("# ICMPv4 packets dropped (impossible PT to v6)"),
2265 GNUNET_break_op (0);
2269 pkt_len = make_up_icmp_service_payload (state, buf);
2272 GNUNET_break_op (0);
2273 GNUNET_STATISTICS_update (stats,
2274 gettext_noop ("# ICMPv4 packets dropped (type not allowed)"),
2278 /* end of AF_INET */
2281 switch (msg->icmp_header.type)
2283 case GNUNET_TUN_ICMPTYPE6_ECHO_REPLY:
2284 if (state->specifics.tcp_udp.serv->address.af == AF_INET)
2285 icmp.type = GNUNET_TUN_ICMPTYPE_ECHO_REPLY;
2287 case GNUNET_TUN_ICMPTYPE6_ECHO_REQUEST:
2288 if (state->specifics.tcp_udp.serv->address.af == AF_INET)
2289 icmp.type = GNUNET_TUN_ICMPTYPE_ECHO_REQUEST;
2291 case GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE:
2292 if (state->specifics.tcp_udp.serv->address.af == AF_INET)
2293 icmp.type = GNUNET_TUN_ICMPTYPE_DESTINATION_UNREACHABLE;
2296 GNUNET_break_op (0);
2300 pkt_len = make_up_icmp_service_payload (state, buf);
2302 case GNUNET_TUN_ICMPTYPE6_TIME_EXCEEDED:
2303 if (state->specifics.tcp_udp.serv->address.af == AF_INET)
2304 icmp.type = GNUNET_TUN_ICMPTYPE_TIME_EXCEEDED;
2307 GNUNET_break_op (0);
2311 pkt_len = make_up_icmp_service_payload (state, buf);
2313 case GNUNET_TUN_ICMPTYPE6_PACKET_TOO_BIG:
2314 case GNUNET_TUN_ICMPTYPE6_PARAMETER_PROBLEM:
2315 if (state->specifics.tcp_udp.serv->address.af == AF_INET)
2317 GNUNET_STATISTICS_update (stats,
2318 gettext_noop ("# ICMPv6 packets dropped (impossible PT to v4)"),
2324 GNUNET_break_op (0);
2328 pkt_len = make_up_icmp_service_payload (state, buf);
2331 GNUNET_break_op (0);
2332 GNUNET_STATISTICS_update (stats,
2333 gettext_noop ("# ICMPv6 packets dropped (type not allowed)"),
2337 /* end of AF_INET6 */
2340 GNUNET_break_op (0);
2344 send_icmp_packet_via_tun (&state->specifics.tcp_udp.ri.remote_address,
2345 &state->specifics.tcp_udp.ri.local_address,
2349 GNUNET_CADET_receive_done (state->channel);
2354 * Free memory associated with a service record.
2357 * @param key service descriptor
2358 * @param value service record to free
2359 * @return #GNUNET_OK
2362 free_service_record (void *cls,
2363 const struct GNUNET_HashCode *key,
2366 struct LocalService *service = value;
2368 GNUNET_assert (GNUNET_YES ==
2369 GNUNET_CONTAINER_multihashmap_remove (services,
2372 GNUNET_CADET_close_port (service->port);
2373 GNUNET_free_non_null (service->name);
2374 GNUNET_free (service);
2380 * Callback from CADET for new channels.
2382 * @param cls closure
2383 * @param channel new handle to the channel
2384 * @param initiator peer that started the channel
2385 * @return initial channel context for the channel
2388 new_service_channel (void *cls,
2389 struct GNUNET_CADET_Channel *channel,
2390 const struct GNUNET_PeerIdentity *initiator)
2392 struct LocalService *ls = cls;
2393 struct ChannelState *s = GNUNET_new (struct ChannelState);
2395 s->peer = *initiator;
2396 GNUNET_STATISTICS_update (stats,
2397 gettext_noop ("# Inbound CADET channels created"),
2400 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2401 "Received inbound channel from `%s'\n",
2402 GNUNET_i2s (initiator));
2403 s->channel = channel;
2404 s->specifics.tcp_udp.serv = ls;
2405 s->specifics.tcp_udp.ri.remote_address = ls->address;
2411 * Function called by cadet whenever an inbound channel is destroyed.
2412 * Should clean up any associated state.
2414 * @param cls our `struct ChannelState *`
2415 * @param channel connection to the other end (henceforth invalid)
2418 clean_channel (void *cls,
2419 const struct GNUNET_CADET_Channel *channel)
2421 struct ChannelState *s = cls;
2423 LOG (GNUNET_ERROR_TYPE_DEBUG,
2424 "Channel destroyed\n");
2425 if (GNUNET_SYSERR == s->is_dns)
2430 if (GNUNET_YES == s->is_dns)
2432 if (channels[s->specifics.dns.my_id] == s)
2433 channels[s->specifics.dns.my_id] = NULL;
2437 if (NULL != s->specifics.tcp_udp.heap_node)
2439 GNUNET_assert (GNUNET_YES ==
2440 GNUNET_CONTAINER_multihashmap_remove (connections_map,
2441 &s->specifics.tcp_udp.state_key,
2443 GNUNET_CONTAINER_heap_remove_node (s->specifics.tcp_udp.heap_node);
2444 s->specifics.tcp_udp.heap_node = NULL;
2452 * Given a service descriptor and a destination port, find the
2453 * respective service entry.
2455 * @param proto IPPROTO_TCP or IPPROTO_UDP
2456 * @param name name of the service
2457 * @param destination_port destination port
2458 * @param service service information record to store (service->name will be set).
2461 store_service (int proto,
2463 uint16_t destination_port,
2464 struct LocalService *service)
2466 struct GNUNET_MQ_MessageHandler handlers[] = {
2467 GNUNET_MQ_hd_var_size (icmp_service,
2468 GNUNET_MESSAGE_TYPE_VPN_ICMP_TO_SERVICE,
2469 struct GNUNET_EXIT_IcmpServiceMessage,
2471 GNUNET_MQ_hd_var_size (udp_service,
2472 GNUNET_MESSAGE_TYPE_VPN_UDP_TO_SERVICE,
2473 struct GNUNET_EXIT_UdpServiceMessage,
2475 GNUNET_MQ_hd_var_size (tcp_service,
2476 GNUNET_MESSAGE_TYPE_VPN_TCP_TO_SERVICE_START,
2477 struct GNUNET_EXIT_TcpServiceStartMessage,
2479 GNUNET_MQ_hd_var_size (tcp_data,
2480 GNUNET_MESSAGE_TYPE_VPN_TCP_DATA_TO_EXIT,
2481 struct GNUNET_EXIT_TcpDataMessage,
2483 GNUNET_MQ_handler_end ()
2486 struct GNUNET_HashCode cadet_port;
2488 service->name = GNUNET_strdup (name);
2489 GNUNET_TUN_service_name_to_hash (name,
2490 &service->descriptor);
2491 GNUNET_TUN_compute_service_cadet_port (&service->descriptor,
2494 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2495 "Opening CADET port %s for SERVICE exit %s on port %u\n",
2496 GNUNET_h2s (&cadet_port),
2498 (unsigned int) destination_port);
2499 service->port = GNUNET_CADET_open_port (cadet_handle,
2501 &new_service_channel,
2506 service->is_udp = (IPPROTO_UDP == proto);
2508 GNUNET_CONTAINER_multihashmap_put (services,
2511 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY))
2513 GNUNET_CADET_close_port (service->port);
2514 GNUNET_free_non_null (service->name);
2515 GNUNET_free (service);
2516 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
2517 _("Got duplicate service records for `%s:%u'\n"),
2519 (unsigned int) destination_port);
2525 * Send the given packet via the cadet channel.
2527 * @param s channel destination
2528 * @param env message to queue
2531 send_packet_to_cadet_channel (struct ChannelState *s,
2532 struct GNUNET_MQ_Envelope *env)
2534 GNUNET_assert (NULL != s);
2535 GNUNET_STATISTICS_update (stats,
2536 gettext_noop ("# Messages transmitted via cadet channels"),
2539 GNUNET_MQ_send (GNUNET_CADET_get_mq (s->channel),
2545 * @brief Handles an ICMP packet received from the helper.
2547 * @param icmp A pointer to the Packet
2548 * @param pktlen number of bytes in @a icmp
2549 * @param af address family (AFINET or AF_INET6)
2550 * @param destination_ip destination IP-address of the IP packet (should
2551 * be our local address)
2552 * @param source_ip original source IP-address of the IP packet (should
2553 * be the original destination address)
2556 icmp_from_helper (const struct GNUNET_TUN_IcmpHeader *icmp,
2559 const void *destination_ip,
2560 const void *source_ip)
2562 struct ChannelState *state;
2563 struct GNUNET_MQ_Envelope *env;
2564 struct GNUNET_EXIT_IcmpToVPNMessage *i2v;
2565 const struct GNUNET_TUN_IPv4Header *ipv4;
2566 const struct GNUNET_TUN_IPv6Header *ipv6;
2567 const struct GNUNET_TUN_UdpHeader *udp;
2568 uint16_t source_port;
2569 uint16_t destination_port;
2573 char sbuf[INET6_ADDRSTRLEN];
2574 char dbuf[INET6_ADDRSTRLEN];
2575 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2576 "Received ICMP packet going from %s to %s\n",
2579 sbuf, sizeof (sbuf)),
2582 dbuf, sizeof (dbuf)));
2584 if (pktlen < sizeof (struct GNUNET_TUN_IcmpHeader))
2591 /* Find out if this is an ICMP packet in response to an existing
2592 TCP/UDP packet and if so, figure out ports / protocol of the
2593 existing session from the IP data in the ICMP payload */
2595 destination_port = 0;
2599 protocol = IPPROTO_ICMP;
2602 case GNUNET_TUN_ICMPTYPE_ECHO_REPLY:
2603 case GNUNET_TUN_ICMPTYPE_ECHO_REQUEST:
2605 case GNUNET_TUN_ICMPTYPE_DESTINATION_UNREACHABLE:
2606 case GNUNET_TUN_ICMPTYPE_SOURCE_QUENCH:
2607 case GNUNET_TUN_ICMPTYPE_TIME_EXCEEDED:
2609 sizeof (struct GNUNET_TUN_IcmpHeader) +
2610 sizeof (struct GNUNET_TUN_IPv4Header) + 8)
2616 ipv4 = (const struct GNUNET_TUN_IPv4Header *) &icmp[1];
2617 protocol = ipv4->protocol;
2618 /* could be TCP or UDP, but both have the ports in the right
2619 place, so that doesn't matter here */
2620 udp = (const struct GNUNET_TUN_UdpHeader *) &ipv4[1];
2621 /* swap ports, as they are from the original message */
2622 destination_port = ntohs (udp->source_port);
2623 source_port = ntohs (udp->destination_port);
2624 /* throw away ICMP payload, won't be useful for the other side anyway */
2625 pktlen = sizeof (struct GNUNET_TUN_IcmpHeader);
2628 GNUNET_STATISTICS_update (stats,
2629 gettext_noop ("# ICMPv4 packets dropped (type not allowed)"),
2635 protocol = IPPROTO_ICMPV6;
2638 case GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE:
2639 case GNUNET_TUN_ICMPTYPE6_PACKET_TOO_BIG:
2640 case GNUNET_TUN_ICMPTYPE6_TIME_EXCEEDED:
2641 case GNUNET_TUN_ICMPTYPE6_PARAMETER_PROBLEM:
2643 sizeof (struct GNUNET_TUN_IcmpHeader) +
2644 sizeof (struct GNUNET_TUN_IPv6Header) + 8)
2650 ipv6 = (const struct GNUNET_TUN_IPv6Header *) &icmp[1];
2651 protocol = ipv6->next_header;
2652 /* could be TCP or UDP, but both have the ports in the right
2653 place, so that doesn't matter here */
2654 udp = (const struct GNUNET_TUN_UdpHeader *) &ipv6[1];
2655 /* swap ports, as they are from the original message */
2656 destination_port = ntohs (udp->source_port);
2657 source_port = ntohs (udp->destination_port);
2658 /* throw away ICMP payload, won't be useful for the other side anyway */
2659 pktlen = sizeof (struct GNUNET_TUN_IcmpHeader);
2661 case GNUNET_TUN_ICMPTYPE6_ECHO_REQUEST:
2662 case GNUNET_TUN_ICMPTYPE6_ECHO_REPLY:
2665 GNUNET_STATISTICS_update (stats,
2666 gettext_noop ("# ICMPv6 packets dropped (type not allowed)"),
2677 state = get_redirect_state (af,
2685 case IPPROTO_ICMPV6:
2686 state = get_redirect_state (af,
2695 state = get_redirect_state (af,
2704 state = get_redirect_state (af,
2713 GNUNET_STATISTICS_update (stats,
2714 gettext_noop ("# ICMP packets dropped (not allowed)"),
2721 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
2722 _("ICMP Packet dropped, have no matching connection information\n"));
2725 env = GNUNET_MQ_msg_extra (i2v,
2726 pktlen - sizeof (struct GNUNET_TUN_IcmpHeader),
2727 GNUNET_MESSAGE_TYPE_VPN_ICMP_TO_VPN);
2728 i2v->af = htonl (af);
2729 GNUNET_memcpy (&i2v->icmp_header,
2732 send_packet_to_cadet_channel (state,
2738 * @brief Handles an UDP packet received from the helper.
2740 * @param udp A pointer to the Packet
2741 * @param pktlen number of bytes in 'udp'
2742 * @param af address family (AFINET or AF_INET6)
2743 * @param destination_ip destination IP-address of the IP packet (should
2744 * be our local address)
2745 * @param source_ip original source IP-address of the IP packet (should
2746 * be the original destination address)
2749 udp_from_helper (const struct GNUNET_TUN_UdpHeader *udp,
2752 const void *destination_ip,
2753 const void *source_ip)
2755 struct ChannelState *state;
2756 struct GNUNET_MQ_Envelope *env;
2757 struct GNUNET_EXIT_UdpReplyMessage *urm;
2760 char sbuf[INET6_ADDRSTRLEN];
2761 char dbuf[INET6_ADDRSTRLEN];
2763 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2764 "Received UDP packet going from %s:%u to %s:%u\n",
2767 sbuf, sizeof (sbuf)),
2768 (unsigned int) ntohs (udp->source_port),
2771 dbuf, sizeof (dbuf)),
2772 (unsigned int) ntohs (udp->destination_port));
2774 if (pktlen < sizeof (struct GNUNET_TUN_UdpHeader))
2780 if (pktlen != ntohs (udp->len))
2786 state = get_redirect_state (af,
2789 ntohs (udp->source_port),
2791 ntohs (udp->destination_port),
2795 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
2796 _("UDP Packet dropped, have no matching connection information\n"));
2799 env = GNUNET_MQ_msg_extra (urm,
2800 pktlen - sizeof (struct GNUNET_TUN_UdpHeader),
2801 GNUNET_MESSAGE_TYPE_VPN_UDP_REPLY);
2802 urm->source_port = htons (0);
2803 urm->destination_port = htons (0);
2804 GNUNET_memcpy (&urm[1],
2806 pktlen - sizeof (struct GNUNET_TUN_UdpHeader));
2807 send_packet_to_cadet_channel (state,
2813 * @brief Handles a TCP packet received from the helper.
2815 * @param tcp A pointer to the Packet
2816 * @param pktlen the length of the packet, including its TCP header
2817 * @param af address family (AFINET or AF_INET6)
2818 * @param destination_ip destination IP-address of the IP packet (should
2819 * be our local address)
2820 * @param source_ip original source IP-address of the IP packet (should
2821 * be the original destination address)
2824 tcp_from_helper (const struct GNUNET_TUN_TcpHeader *tcp,
2827 const void *destination_ip,
2828 const void *source_ip)
2830 struct ChannelState *state;
2831 char buf[pktlen] GNUNET_ALIGN;
2832 struct GNUNET_TUN_TcpHeader *mtcp;
2833 struct GNUNET_EXIT_TcpDataMessage *tdm;
2834 struct GNUNET_MQ_Envelope *env;
2838 char sbuf[INET6_ADDRSTRLEN];
2839 char dbuf[INET6_ADDRSTRLEN];
2840 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2841 "Received TCP packet with %u bytes going from %s:%u to %s:%u\n",
2842 (unsigned int) (pktlen - sizeof (struct GNUNET_TUN_TcpHeader)),
2845 sbuf, sizeof (sbuf)),
2846 (unsigned int) ntohs (tcp->source_port),
2849 dbuf, sizeof (dbuf)),
2850 (unsigned int) ntohs (tcp->destination_port));
2852 if (pktlen < sizeof (struct GNUNET_TUN_TcpHeader))
2858 state = get_redirect_state (af,
2861 ntohs (tcp->source_port),
2863 ntohs (tcp->destination_port),
2867 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
2868 _("TCP Packet dropped, have no matching connection information\n"));
2872 /* mug port numbers and crc to avoid information leakage;
2873 sender will need to lookup the correct values anyway */
2874 GNUNET_memcpy (buf, tcp, pktlen);
2875 mtcp = (struct GNUNET_TUN_TcpHeader *) buf;
2876 mtcp->source_port = 0;
2877 mtcp->destination_port = 0;
2880 mlen = sizeof (struct GNUNET_EXIT_TcpDataMessage) + (pktlen - sizeof (struct GNUNET_TUN_TcpHeader));
2881 if (mlen >= GNUNET_MAX_MESSAGE_SIZE)
2886 env = GNUNET_MQ_msg_extra (tdm,
2887 pktlen - sizeof (struct GNUNET_TUN_TcpHeader),
2888 GNUNET_MESSAGE_TYPE_VPN_TCP_DATA_TO_VPN);
2889 tdm->reserved = htonl (0);
2890 GNUNET_memcpy (&tdm->tcp_header,
2893 send_packet_to_cadet_channel (state,
2899 * Receive packets from the helper-process
2902 * @param message message received from helper
2905 message_token (void *cls GNUNET_UNUSED,
2906 const struct GNUNET_MessageHeader *message)
2908 const struct GNUNET_TUN_Layer2PacketHeader *pkt_tun;
2911 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2912 "Got %u-byte message of type %u from gnunet-helper-exit\n",
2913 ntohs (message->size),
2914 ntohs (message->type));
2915 GNUNET_STATISTICS_update (stats,
2916 gettext_noop ("# Packets received from TUN"),
2918 if (ntohs (message->type) != GNUNET_MESSAGE_TYPE_VPN_HELPER)
2923 size = ntohs (message->size);
2924 if (size < sizeof (struct GNUNET_TUN_Layer2PacketHeader) + sizeof (struct GNUNET_MessageHeader))
2929 GNUNET_STATISTICS_update (stats,
2930 gettext_noop ("# Bytes received from TUN"),
2932 pkt_tun = (const struct GNUNET_TUN_Layer2PacketHeader *) &message[1];
2933 size -= sizeof (struct GNUNET_TUN_Layer2PacketHeader) + sizeof (struct GNUNET_MessageHeader);
2934 switch (ntohs (pkt_tun->proto))
2938 const struct GNUNET_TUN_IPv4Header *pkt4;
2940 if (size < sizeof (struct GNUNET_TUN_IPv4Header))
2942 /* Kernel to blame? */
2946 pkt4 = (const struct GNUNET_TUN_IPv4Header *) &pkt_tun[1];
2947 if (size != ntohs (pkt4->total_length))
2949 /* Kernel to blame? */
2953 if (pkt4->header_length * 4 != sizeof (struct GNUNET_TUN_IPv4Header))
2955 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
2956 _("IPv4 packet options received. Ignored.\n"));
2960 size -= sizeof (struct GNUNET_TUN_IPv4Header);
2961 switch (pkt4->protocol)
2964 udp_from_helper ((const struct GNUNET_TUN_UdpHeader *) &pkt4[1], size,
2966 &pkt4->destination_address,
2967 &pkt4->source_address);
2970 tcp_from_helper ((const struct GNUNET_TUN_TcpHeader *) &pkt4[1], size,
2972 &pkt4->destination_address,
2973 &pkt4->source_address);
2976 icmp_from_helper ((const struct GNUNET_TUN_IcmpHeader *) &pkt4[1], size,
2978 &pkt4->destination_address,
2979 &pkt4->source_address);
2982 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
2983 _("IPv4 packet with unsupported next header %u received. Ignored.\n"),
2984 (int) pkt4->protocol);
2991 const struct GNUNET_TUN_IPv6Header *pkt6;
2993 if (size < sizeof (struct GNUNET_TUN_IPv6Header))
2995 /* Kernel to blame? */
2999 pkt6 = (struct GNUNET_TUN_IPv6Header *) &pkt_tun[1];
3000 if (size != ntohs (pkt6->payload_length) + sizeof (struct GNUNET_TUN_IPv6Header))
3002 /* Kernel to blame? */
3006 size -= sizeof (struct GNUNET_TUN_IPv6Header);
3007 switch (pkt6->next_header)
3010 udp_from_helper ((const struct GNUNET_TUN_UdpHeader *) &pkt6[1], size,
3012 &pkt6->destination_address,
3013 &pkt6->source_address);
3016 tcp_from_helper ((const struct GNUNET_TUN_TcpHeader *) &pkt6[1], size,
3018 &pkt6->destination_address,
3019 &pkt6->source_address);
3021 case IPPROTO_ICMPV6:
3022 icmp_from_helper ((const struct GNUNET_TUN_IcmpHeader *) &pkt6[1], size,
3024 &pkt6->destination_address,
3025 &pkt6->source_address);
3028 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
3029 _("IPv6 packet with unsupported next header %d received. Ignored.\n"),
3036 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
3037 _("Packet from unknown protocol %u received. Ignored.\n"),
3038 ntohs (pkt_tun->proto));
3046 * Callback from CADET for new channels.
3048 * @param cls closure
3049 * @param channel new handle to the channel
3050 * @param initiator peer that started the channel
3051 * @return initial channel context for the channel
3054 new_channel (void *cls,
3055 struct GNUNET_CADET_Channel *channel,
3056 const struct GNUNET_PeerIdentity *initiator)
3058 struct ChannelState *s = GNUNET_new (struct ChannelState);
3060 s->is_dns = GNUNET_SYSERR;
3061 s->peer = *initiator;
3062 GNUNET_STATISTICS_update (stats,
3063 gettext_noop ("# Inbound CADET channels created"),
3066 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3067 "Received inbound channel from `%s'\n",
3068 GNUNET_i2s (initiator));
3069 s->channel = channel;
3075 * Function that frees everything from a hashmap
3079 * @param value value to free
3082 free_iterate (void *cls,
3083 const struct GNUNET_HashCode * hash,
3086 GNUNET_free (value);
3092 * Function scheduled as very last function if the service
3093 * disabled itself because the helper is not installed
3094 * properly. Does nothing, except for keeping the
3095 * service process alive by virtue of being scheduled.
3098 * @param tc scheduler context
3101 dummy_task (void *cls)
3103 /* just terminate */
3108 * Function scheduled as very last function, cleans up after us
3117 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3118 "Exit service is shutting down now\n");
3120 if (NULL != helper_handle)
3122 GNUNET_HELPER_stop (helper_handle, GNUNET_NO);
3123 helper_handle = NULL;
3127 GNUNET_REGEX_announce_cancel (regex4);
3132 GNUNET_REGEX_announce_cancel (regex6);
3135 if (NULL != services)
3137 GNUNET_CONTAINER_multihashmap_iterate (services,
3138 &free_service_record,
3140 GNUNET_CONTAINER_multihashmap_destroy (services);
3142 if (NULL != dns_port)
3144 GNUNET_CADET_close_port (dns_port);
3147 if (NULL != cadet_port4)
3149 GNUNET_CADET_close_port (cadet_port4);
3152 if (NULL != cadet_port6)
3154 GNUNET_CADET_close_port (cadet_port6);
3157 if (NULL != cadet_handle)
3159 GNUNET_CADET_disconnect (cadet_handle);
3160 cadet_handle = NULL;
3162 if (NULL != connections_map)
3164 GNUNET_CONTAINER_multihashmap_iterate (connections_map,
3167 GNUNET_CONTAINER_multihashmap_destroy (connections_map);
3168 connections_map = NULL;
3170 if (NULL != connections_heap)
3172 GNUNET_CONTAINER_heap_destroy (connections_heap);
3173 connections_heap = NULL;
3175 if (NULL != dnsstub)
3177 GNUNET_DNSSTUB_stop (dnsstub);
3180 if (NULL != peer_key)
3182 GNUNET_free (peer_key);
3185 if (NULL != dht_task)
3187 GNUNET_SCHEDULER_cancel (dht_task);
3190 if (NULL != dht_put)
3192 GNUNET_DHT_put_cancel (dht_put);
3197 GNUNET_DHT_disconnect (dht);
3202 GNUNET_STATISTICS_destroy (stats,
3207 GNUNET_free_non_null (exit_argv[i]);
3212 * Add services to the service map.
3214 * @param proto IPPROTO_TCP or IPPROTO_UDP
3215 * @param cpy copy of the service descriptor (can be mutilated)
3216 * @param name DNS name of the service
3219 add_services (int proto,
3226 struct LocalService *serv;
3230 slen = strlen (name);
3231 GNUNET_assert (slen >= 8);
3232 n = GNUNET_strndup (name, slen - 8 /* remove .gnunet. */);
3234 for (redirect = strtok (cpy, " ;"); redirect != NULL;
3235 redirect = strtok (NULL, " ;"))
3237 if (NULL == (hostname = strstr (redirect, ":")))
3239 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
3240 _("Option `%s' for domain `%s' is not formatted correctly!\n"),
3247 if (NULL == (hostport = strstr (hostname, ":")))
3249 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
3250 _("Option `%s' for domain `%s' is not formatted correctly!\n"),
3258 int local_port = atoi (redirect);
3259 int remote_port = atoi (hostport);
3261 if (! ((local_port > 0) && (local_port < 65536)))
3263 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
3264 _("`%s' is not a valid port number (for domain `%s')!"),
3269 if (! ((remote_port > 0) && (remote_port < 65536)))
3271 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
3272 _("`%s' is not a valid port number (for domain `%s')!"),
3278 serv = GNUNET_new (struct LocalService);
3279 serv->address.proto = proto;
3280 serv->address.port = remote_port;
3281 if (0 == strcmp ("localhost4",
3284 const char *ip4addr = exit_argv[5];
3286 serv->address.af = AF_INET;
3287 GNUNET_assert (1 == inet_pton (AF_INET,
3289 &serv->address.address.ipv4));
3291 else if (0 == strcmp ("localhost6",
3294 const char *ip6addr = exit_argv[3];
3296 serv->address.af = AF_INET6;
3297 GNUNET_assert (1 == inet_pton (AF_INET6,
3299 &serv->address.address.ipv6));
3303 struct addrinfo *res;
3306 ret = getaddrinfo (hostname,
3310 if ( (0 != ret) || (NULL == res) )
3312 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
3313 _("No addresses found for hostname `%s' of service `%s'!\n"),
3320 serv->address.af = res->ai_family;
3321 switch (res->ai_family)
3326 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
3327 _("Service `%s' configured for IPv4, but IPv4 is disabled!\n"),
3333 serv->address.address.ipv4
3334 = ((struct sockaddr_in *) res->ai_addr)->sin_addr;
3339 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
3340 _("Service `%s' configured for IPv4, but IPv4 is disabled!\n"),
3346 serv->address.address.ipv6
3347 = ((struct sockaddr_in6 *) res->ai_addr)->sin6_addr;
3351 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
3352 _("No IP addresses found for hostname `%s' of service `%s'!\n"),
3360 store_service (proto,
3370 * Reads the configuration and populates #udp_services and #tcp_services
3373 * @param section name of section in config
3376 read_service_conf (void *cls,
3377 const char *section)
3381 if ((strlen (section) < 8) ||
3382 (0 != strcmp (".gnunet.", section + (strlen (section) - 8))))
3385 GNUNET_CONFIGURATION_get_value_string (cfg,
3390 add_services (IPPROTO_UDP,
3396 GNUNET_CONFIGURATION_get_value_string (cfg,
3401 add_services (IPPROTO_TCP,
3410 * We are running a DNS exit service, advertise it in the
3411 * DHT. This task is run periodically to do the DHT PUT.
3413 * @param cls closure
3416 do_dht_put (void *cls);
3420 * Function called when the DHT PUT operation is complete.
3421 * Schedules the next PUT.
3423 * @param cls closure, NULL
3426 dht_put_cont (void *cls)
3433 * We are running a DNS exit service, advertise it in the
3434 * DHT. This task is run periodically to do the DHT PUT.
3436 * @param cls closure
3439 do_dht_put (void *cls)
3441 struct GNUNET_TIME_Absolute expiration;
3443 dht_task = GNUNET_SCHEDULER_add_delayed (DHT_PUT_FREQUENCY,
3446 expiration = GNUNET_TIME_absolute_ntoh (dns_advertisement.expiration_time);
3447 if (GNUNET_TIME_absolute_get_remaining (expiration).rel_value_us <
3448 GNUNET_TIME_UNIT_HOURS.rel_value_us)
3450 /* refresh advertisement */
3451 expiration = GNUNET_TIME_relative_to_absolute (DNS_ADVERTISEMENT_TIMEOUT);
3452 dns_advertisement.expiration_time = GNUNET_TIME_absolute_hton (expiration);
3453 GNUNET_assert (GNUNET_OK ==
3454 GNUNET_CRYPTO_eddsa_sign (peer_key,
3455 &dns_advertisement.purpose,
3456 &dns_advertisement.signature));
3458 if (NULL != dht_put)
3459 GNUNET_DHT_put_cancel (dht_put);
3460 dht_put = GNUNET_DHT_put (dht,
3462 1 /* replication */,
3464 GNUNET_BLOCK_TYPE_DNS,
3465 sizeof (struct GNUNET_DNS_Advertisement),
3474 * Figure out which IP versions we should support (and which
3475 * are supported by the OS) according to our configuration.
3480 ipv4_exit = GNUNET_CONFIGURATION_get_value_yesno (cfg,
3483 ipv6_exit = GNUNET_CONFIGURATION_get_value_yesno (cfg,
3486 ipv4_enabled = GNUNET_CONFIGURATION_get_value_yesno (cfg,
3489 ipv6_enabled = GNUNET_CONFIGURATION_get_value_yesno (cfg,
3492 if ( (ipv4_exit || ipv4_enabled) &&
3493 GNUNET_OK != GNUNET_NETWORK_test_pf (PF_INET))
3495 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
3496 _("This system does not support IPv4, will disable IPv4 functions despite them being enabled in the configuration\n"));
3497 ipv4_exit = GNUNET_NO;
3498 ipv4_enabled = GNUNET_NO;
3500 if ( (ipv6_exit || ipv6_enabled) &&
3501 GNUNET_OK != GNUNET_NETWORK_test_pf (PF_INET6))
3503 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
3504 _("This system does not support IPv6, will disable IPv6 functions despite them being enabled in the configuration\n"));
3505 ipv6_exit = GNUNET_NO;
3506 ipv6_enabled = GNUNET_NO;
3508 if (ipv4_exit && (! ipv4_enabled))
3510 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
3511 _("Cannot enable IPv4 exit but disable IPv4 on TUN interface, will use ENABLE_IPv4=YES\n"));
3512 ipv4_enabled = GNUNET_YES;
3514 if (ipv6_exit && (! ipv6_enabled))
3516 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
3517 _("Cannot enable IPv6 exit but disable IPv6 on TUN interface, will use ENABLE_IPv6=YES\n"));
3518 ipv6_enabled = GNUNET_YES;
3524 * Helper function to open the CADET port for DNS exits and to
3525 * advertise the DNS exit (if applicable).
3528 advertise_dns_exit ()
3530 struct GNUNET_MQ_MessageHandler handlers[] = {
3531 GNUNET_MQ_hd_var_size (dns_request,
3532 GNUNET_MESSAGE_TYPE_VPN_DNS_TO_INTERNET,
3533 struct DnsResponseMessage,
3535 GNUNET_MQ_handler_end ()
3538 struct GNUNET_HashCode port;
3541 GNUNET_CONFIGURATION_get_value_yesno (cfg,
3545 GNUNET_assert (NULL != (dnsstub = GNUNET_DNSSTUB_start (128)));
3547 /* TODO: support using multiple DNS resolvers */
3549 GNUNET_CONFIGURATION_get_value_string (cfg,
3554 GNUNET_DNSSTUB_add_dns_ip (dnsstub,
3557 GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
3560 _("need a valid IPv4 or IPv6 address\n"));
3561 GNUNET_free_non_null (dns_exit);
3565 GNUNET_CRYPTO_hash (GNUNET_APPLICATION_PORT_INTERNET_RESOLVER,
3566 strlen (GNUNET_APPLICATION_PORT_INTERNET_RESOLVER),
3568 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3569 "Opening CADET port %s for DNS exit service\n",
3570 GNUNET_h2s (&port));
3571 dns_port = GNUNET_CADET_open_port (cadet_handle,
3578 /* advertise exit */
3579 dht = GNUNET_DHT_connect (cfg,
3581 peer_key = GNUNET_CRYPTO_eddsa_key_create_from_configuration (cfg);
3582 GNUNET_CRYPTO_eddsa_key_get_public (peer_key,
3583 &dns_advertisement.peer.public_key);
3584 dns_advertisement.purpose.size = htonl (sizeof (struct GNUNET_DNS_Advertisement) -
3585 sizeof (struct GNUNET_CRYPTO_EddsaSignature));
3586 dns_advertisement.purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_DNS_RECORD);
3587 GNUNET_CRYPTO_hash ("dns",
3590 dht_task = GNUNET_SCHEDULER_add_now (&do_dht_put,
3592 GNUNET_free (dns_exit);
3597 * Initialize #exit_argv.
3599 * @return #GNUNET_OK on success, #GNUNET_SYSERR if we should shutdown
3602 setup_exit_helper_args ()
3611 exit_argv[0] = GNUNET_strdup ("exit-gnunet");
3612 if (GNUNET_SYSERR ==
3613 GNUNET_CONFIGURATION_get_value_string (cfg,
3618 GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
3621 return GNUNET_SYSERR;
3623 exit_argv[1] = tun_ifname;
3626 if (GNUNET_SYSERR ==
3627 GNUNET_CONFIGURATION_get_value_string (cfg,
3632 GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
3635 return GNUNET_SYSERR;
3637 exit_argv[2] = exit_ifname;
3641 exit_argv[2] = GNUNET_strdup ("-");
3644 if (GNUNET_YES == ipv6_enabled)
3647 if ( (GNUNET_SYSERR ==
3648 GNUNET_CONFIGURATION_get_value_string (cfg,
3652 (1 != inet_pton (AF_INET6,
3656 GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
3659 GNUNET_free_non_null (ipv6addr);
3660 return GNUNET_SYSERR;
3662 exit_argv[3] = ipv6addr;
3663 if (GNUNET_SYSERR ==
3664 GNUNET_CONFIGURATION_get_value_string (cfg,
3669 GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
3672 return GNUNET_SYSERR;
3674 exit_argv[4] = ipv6prefix_s;
3676 GNUNET_CONFIGURATION_get_value_number (cfg,
3680 (ipv6prefix >= 127) )
3682 GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
3685 _("Must be a number"));
3686 return GNUNET_SYSERR;
3691 /* IPv6 explicitly disabled */
3692 exit_argv[3] = GNUNET_strdup ("-");
3693 exit_argv[4] = GNUNET_strdup ("-");
3695 if (GNUNET_YES == ipv4_enabled)
3698 if ( (GNUNET_SYSERR ==
3699 GNUNET_CONFIGURATION_get_value_string (cfg,
3703 (1 != inet_pton (AF_INET,
3707 GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
3710 GNUNET_free_non_null (ipv4addr);
3711 return GNUNET_SYSERR;
3713 exit_argv[5] = ipv4addr;
3715 if ( (GNUNET_SYSERR ==
3716 GNUNET_CONFIGURATION_get_value_string (cfg,
3720 (1 != inet_pton (AF_INET,
3724 GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
3727 GNUNET_free_non_null (ipv4mask);
3728 return GNUNET_SYSERR;
3730 exit_argv[6] = ipv4mask;
3734 /* IPv4 explicitly disabled */
3735 exit_argv[5] = GNUNET_strdup ("-");
3736 exit_argv[6] = GNUNET_strdup ("-");
3738 exit_argv[7] = NULL;
3744 * @brief Main function that will be run by the scheduler.
3746 * @param cls closure
3747 * @param args remaining command-line arguments
3748 * @param cfgfile name of the configuration file used (for saving, can be NULL!)
3749 * @param cfg_ configuration
3754 const char *cfgfile,
3755 const struct GNUNET_CONFIGURATION_Handle *cfg_)
3757 struct GNUNET_MQ_MessageHandler handlers[] = {
3758 GNUNET_MQ_hd_var_size (icmp_remote,
3759 GNUNET_MESSAGE_TYPE_VPN_ICMP_TO_INTERNET,
3760 struct GNUNET_EXIT_IcmpInternetMessage,
3762 GNUNET_MQ_hd_var_size (udp_remote,
3763 GNUNET_MESSAGE_TYPE_VPN_UDP_TO_INTERNET,
3764 struct GNUNET_EXIT_UdpInternetMessage,
3766 GNUNET_MQ_hd_var_size (tcp_remote,
3767 GNUNET_MESSAGE_TYPE_VPN_TCP_TO_INTERNET_START,
3768 struct GNUNET_EXIT_TcpInternetStartMessage,
3770 GNUNET_MQ_hd_var_size (tcp_data,
3771 GNUNET_MESSAGE_TYPE_VPN_TCP_DATA_TO_EXIT,
3772 struct GNUNET_EXIT_TcpDataMessage,
3774 GNUNET_MQ_handler_end ()
3776 struct GNUNET_HashCode port;
3780 char *prefixed_regex;
3784 GNUNET_CONFIGURATION_get_value_number (cfg,
3788 max_connections = 1024;
3789 parse_ip_options ();
3790 if ( (ipv4_exit) || (ipv6_exit) )
3792 binary = GNUNET_OS_get_libexec_binary_path ("gnunet-helper-exit");
3794 GNUNET_OS_check_helper_binary (binary,
3796 "gnunet-vpn - - - 169.1.3.7 255.255.255.0")) //no nat, ipv4 only
3798 GNUNET_free (binary);
3799 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
3800 _("`%s' must be installed SUID, EXIT will not work\n"),
3801 "gnunet-helper-exit");
3802 GNUNET_SCHEDULER_add_shutdown (&dummy_task,
3807 GNUNET_free (binary);
3809 if (! (ipv4_enabled || ipv6_enabled))
3811 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
3812 _("No useful service enabled. Exiting.\n"));
3813 GNUNET_SCHEDULER_shutdown ();
3817 GNUNET_SCHEDULER_add_shutdown (&cleanup,
3819 stats = GNUNET_STATISTICS_create ("exit",
3821 cadet_handle = GNUNET_CADET_connect (cfg);
3822 if (NULL == cadet_handle)
3824 GNUNET_SCHEDULER_shutdown ();
3827 advertise_dns_exit ();
3829 setup_exit_helper_args ())
3831 GNUNET_SCHEDULER_shutdown ();
3835 services = GNUNET_CONTAINER_multihashmap_create (65536,
3837 connections_map = GNUNET_CONTAINER_multihashmap_create (65536,
3839 connections_heap = GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN);
3840 GNUNET_CONFIGURATION_iterate_sections (cfg,
3844 /* Cadet handle acquired, now open ports and announce regular
3845 expressions matching our exit */
3846 if ( (GNUNET_YES == ipv4_enabled) &&
3847 (GNUNET_YES == ipv4_exit) )
3849 GNUNET_CRYPTO_hash (GNUNET_APPLICATION_PORT_IPV4_GATEWAY,
3850 strlen (GNUNET_APPLICATION_PORT_IPV4_GATEWAY),
3852 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3853 "Opening CADET port %s for IPv4 gateway service\n",
3854 GNUNET_h2s (&port));
3855 cadet_port4 = GNUNET_CADET_open_port (cadet_handle,
3864 GNUNET_CONFIGURATION_get_value_string (cfg,
3866 "EXIT_RANGE_IPV4_POLICY",
3870 regex = GNUNET_TUN_ipv4policy2regex (policy);
3871 GNUNET_free_non_null (policy);
3874 (void) GNUNET_asprintf (&prefixed_regex,
3876 GNUNET_APPLICATION_TYPE_EXIT_REGEX_PREFIX,
3878 regex4 = GNUNET_REGEX_announce (cfg,
3880 REGEX_REFRESH_FREQUENCY,
3881 REGEX_MAX_PATH_LEN_IPV4);
3882 GNUNET_free (regex);
3883 GNUNET_free (prefixed_regex);
3887 if ( (GNUNET_YES == ipv6_enabled) && (GNUNET_YES == ipv6_exit) )
3889 GNUNET_CRYPTO_hash (GNUNET_APPLICATION_PORT_IPV6_GATEWAY,
3890 strlen (GNUNET_APPLICATION_PORT_IPV6_GATEWAY),
3892 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3893 "Opening CADET port %s for IPv6 gateway service\n",
3894 GNUNET_h2s (&port));
3895 cadet_port6 = GNUNET_CADET_open_port (cadet_handle,
3904 GNUNET_CONFIGURATION_get_value_string (cfg,
3906 "EXIT_RANGE_IPV6_POLICY",
3910 regex = GNUNET_TUN_ipv6policy2regex (policy);
3911 GNUNET_free_non_null (policy);
3914 (void) GNUNET_asprintf (&prefixed_regex,
3916 GNUNET_APPLICATION_TYPE_EXIT_REGEX_PREFIX,
3918 regex6 = GNUNET_REGEX_announce (cfg,
3920 REGEX_REFRESH_FREQUENCY,
3921 REGEX_MAX_PATH_LEN_IPV6);
3922 GNUNET_free (regex);
3923 GNUNET_free (prefixed_regex);
3926 helper_handle = GNUNET_HELPER_start (GNUNET_NO,
3927 "gnunet-helper-exit",
3938 * @param argc number of arguments from the command line
3939 * @param argv command line arguments
3940 * @return 0 ok, 1 on error
3946 static const struct GNUNET_GETOPT_CommandLineOption options[] = {
3947 GNUNET_GETOPT_OPTION_END
3951 GNUNET_STRINGS_get_utf8_args (argc,
3957 return (GNUNET_OK ==
3958 GNUNET_PROGRAM_run (argc,
3960 "gnunet-daemon-exit",
3961 gettext_noop ("Daemon to run to provide an IP exit node for the VPN"),
3964 NULL)) ? global_ret : 1;
3968 /* end of gnunet-daemon-exit.c */