2 This file is part of GNUnet.
3 Copyright (C) 2010-2013 Christian Grothoff
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301, USA.
22 * @file 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.
95 * AF_INET or AF_INET6.
100 * Remote address information.
105 * Address, if af is AF_INET.
110 * Address, if af is AF_INET6.
112 struct in6_addr ipv6;
116 * IPPROTO_TCP or IPPROTO_UDP;
121 * Remote port, in host byte order!
128 * This struct is saved into the services-hashmap to represent
129 * a service this peer is specifically offering an exit for
130 * (for a specific domain name).
136 * Remote address to use for the service.
138 struct SocketAddress address;
141 * DNS name of the service.
146 * Port I am listening on within GNUnet for this service, in host
147 * byte order. (as we may redirect ports).
154 * Information we use to track a connection (the classical 6-tuple of
155 * IP-version, protocol, source-IP, destination-IP, source-port and
158 struct RedirectInformation
162 * Address information for the other party (equivalent of the
163 * arguments one would give to "connect").
165 struct SocketAddress remote_address;
168 * Address information we used locally (AF and proto must match
169 * "remote_address"). Equivalent of the arguments one would give to
172 struct SocketAddress local_address;
175 Note 1: additional information might be added here in the
176 future to support protocols that require special handling,
179 Note 2: we might also sometimes not match on all components
180 of the tuple, to support protocols where things do not always
187 * Queue of messages to a channel.
189 struct ChannelMessageQueue
192 * This is a doubly-linked list.
194 struct ChannelMessageQueue *next;
197 * This is a doubly-linked list.
199 struct ChannelMessageQueue *prev;
202 * Payload to send via the channel.
207 * Number of bytes in 'payload'.
214 * This struct is saved into connections_map to allow finding the
215 * right channel given an IP packet from TUN. It is also associated
216 * with the channel's closure so we can find it again for the next
217 * message from the channel.
222 * Cadet channel that is used for this connection.
224 struct GNUNET_CADET_Channel *channel;
227 * Who is the other end of this channel.
228 * FIXME is this needed? Only used for debugging messages
230 struct GNUNET_PeerIdentity peer;
233 * Active channel transmission request (or NULL).
235 struct GNUNET_CADET_TransmitHandle *th;
238 * #GNUNET_NO if this is a channel for TCP/UDP,
239 * #GNUNET_YES if this is a channel for DNS,
240 * #GNUNET_SYSERR if the channel is not yet initialized.
250 * Heap node for this state in the connections_heap.
252 struct GNUNET_CONTAINER_HeapNode *heap_node;
255 * Key this state has in the connections_map.
257 struct GNUNET_HashCode state_key;
260 * Associated service record, or NULL for no service.
262 struct LocalService *serv;
265 * Head of DLL of messages for this channel.
267 struct ChannelMessageQueue *head;
270 * Tail of DLL of messages for this channel.
272 struct ChannelMessageQueue *tail;
275 * Primary redirection information for this connection.
277 struct RedirectInformation ri;
284 * DNS reply ready for transmission.
289 * Socket we are using to transmit this request (must match if we receive
292 struct GNUNET_DNSSTUB_RequestSocket *rs;
295 * Number of bytes in 'reply'.
300 * Original DNS request ID as used by the client.
302 uint16_t original_id;
305 * DNS request ID that we used for forwarding.
317 * Return value from 'main'.
319 static int global_ret;
322 * Handle to our regex announcement for IPv4.
324 static struct GNUNET_REGEX_Announcement *regex4;
327 * Handle to our regex announcement for IPv4.
329 static struct GNUNET_REGEX_Announcement *regex6;
332 * The handle to the configuration used throughout the process
334 static const struct GNUNET_CONFIGURATION_Handle *cfg;
337 * The handle to the helper
339 static struct GNUNET_HELPER_Handle *helper_handle;
342 * Arguments to the exit helper.
344 static char *exit_argv[8];
347 * IPv6 address of our TUN interface.
349 static struct in6_addr exit_ipv6addr;
352 * IPv6 prefix (0..127) from configuration file.
354 static unsigned long long ipv6prefix;
357 * IPv4 address of our TUN interface.
359 static struct in_addr exit_ipv4addr;
362 * IPv4 netmask of our TUN interface.
364 static struct in_addr exit_ipv4mask;
369 static struct GNUNET_STATISTICS_Handle *stats;
372 * The handle to cadet
374 static struct GNUNET_CADET_Handle *cadet_handle;
377 * This hashmaps contains the mapping from peer, service-descriptor,
378 * source-port and destination-port to a struct ChannelState
380 static struct GNUNET_CONTAINER_MultiHashMap *connections_map;
383 * Heap so we can quickly find "old" connections.
385 static struct GNUNET_CONTAINER_Heap *connections_heap;
388 * If there are at least this many connections, old ones will be removed
390 static unsigned long long max_connections;
393 * This hashmaps saves interesting things about the configured UDP services
395 static struct GNUNET_CONTAINER_MultiHashMap *udp_services;
398 * This hashmaps saves interesting things about the configured TCP services
400 static struct GNUNET_CONTAINER_MultiHashMap *tcp_services;
403 * Array of all open DNS requests from channels.
405 static struct ChannelState *channels[UINT16_MAX + 1];
408 * Handle to the DNS Stub resolver.
410 static struct GNUNET_DNSSTUB_Context *dnsstub;
413 * Handle for ongoing DHT PUT operations to advertise exit service.
415 static struct GNUNET_DHT_PutHandle *dht_put;
420 static struct GNUNET_DHT_Handle *dht;
423 * Task for doing DHT PUTs to advertise exit service.
425 static struct GNUNET_SCHEDULER_Task * dht_task;
428 * Advertisement message we put into the DHT to advertise us
431 static struct GNUNET_DNS_Advertisement dns_advertisement;
434 * Key we store the DNS advertismenet under.
436 static struct GNUNET_HashCode dht_put_key;
439 * Private key for this peer.
441 static struct GNUNET_CRYPTO_EddsaPrivateKey *peer_key;
444 * Are we an IPv4-exit?
446 static int ipv4_exit;
449 * Are we an IPv6-exit?
451 static int ipv6_exit;
454 * Do we support IPv4 at all on the TUN interface?
456 static int ipv4_enabled;
459 * Do we support IPv6 at all on the TUN interface?
461 static int ipv6_enabled;
465 * We got a reply from DNS for a request of a CADET channel. Send it
466 * via the channel (after changing the request ID back).
468 * @param cls the 'struct ChannelState'
469 * @param size number of bytes available in buf
470 * @param buf where to copy the reply
471 * @return number of bytes written to buf
474 transmit_reply_to_cadet (void *cls,
478 struct ChannelState *ts = cls;
482 struct GNUNET_MessageHeader hdr;
483 struct GNUNET_TUN_DnsHeader dns;
485 GNUNET_assert (GNUNET_YES == ts->is_dns);
487 GNUNET_assert (ts->specifics.dns.reply != NULL);
490 ret = sizeof (struct GNUNET_MessageHeader) + ts->specifics.dns.reply_length;
491 GNUNET_assert (ret <= size);
492 hdr.size = htons (ret);
493 hdr.type = htons (GNUNET_MESSAGE_TYPE_VPN_DNS_FROM_INTERNET);
494 memcpy (&dns, ts->specifics.dns.reply, sizeof (dns));
495 dns.id = ts->specifics.dns.original_id;
497 memcpy (&cbuf[off], &hdr, sizeof (hdr));
499 memcpy (&cbuf[off], &dns, sizeof (dns));
501 memcpy (&cbuf[off], &ts->specifics.dns.reply[sizeof (dns)], ts->specifics.dns.reply_length - sizeof (dns));
502 off += ts->specifics.dns.reply_length - sizeof (dns);
503 GNUNET_free (ts->specifics.dns.reply);
504 ts->specifics.dns.reply = NULL;
505 ts->specifics.dns.reply_length = 0;
506 GNUNET_assert (ret == off);
512 * Callback called from DNSSTUB resolver when a resolution
516 * @param rs the socket that received the response
517 * @param dns the response itself
518 * @param r number of bytes in dns
521 process_dns_result (void *cls,
522 struct GNUNET_DNSSTUB_RequestSocket *rs,
523 const struct GNUNET_TUN_DnsHeader *dns,
526 struct ChannelState *ts;
528 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
529 "Processing DNS result from stub resolver\n");
530 GNUNET_assert (NULL == cls);
531 /* Handle case that this is a reply to a request from a CADET DNS channel */
532 ts = channels[dns->id];
534 (ts->specifics.dns.rs != rs) )
536 LOG (GNUNET_ERROR_TYPE_DEBUG,
537 "Got a response from the stub resolver for DNS request received via CADET!\n");
538 channels[dns->id] = NULL;
539 GNUNET_free_non_null (ts->specifics.dns.reply);
540 ts->specifics.dns.reply = GNUNET_malloc (r);
541 ts->specifics.dns.reply_length = r;
542 memcpy (ts->specifics.dns.reply, dns, r);
544 GNUNET_CADET_notify_transmit_ready_cancel (ts->th);
545 ts->th = GNUNET_CADET_notify_transmit_ready (ts->channel,
547 GNUNET_TIME_UNIT_FOREVER_REL,
548 sizeof (struct GNUNET_MessageHeader) + r,
549 &transmit_reply_to_cadet,
555 * Process a request via cadet to perform a DNS query.
557 * @param cls closure, NULL
558 * @param channel connection to the other end
559 * @param channel_ctx pointer to our `struct ChannelState *`
560 * @param message the actual message
562 * @return #GNUNET_OK to keep the connection open,
563 * #GNUNET_SYSERR to close it (signal serious error)
566 receive_dns_request (void *cls GNUNET_UNUSED,
567 struct GNUNET_CADET_Channel *channel,
569 const struct GNUNET_MessageHeader *message)
571 struct ChannelState *ts = *channel_ctx;
572 const struct GNUNET_TUN_DnsHeader *dns;
573 size_t mlen = ntohs (message->size);
574 size_t dlen = mlen - sizeof (struct GNUNET_MessageHeader);
575 char buf[dlen] GNUNET_ALIGN;
576 struct GNUNET_TUN_DnsHeader *dout;
581 return GNUNET_SYSERR;
583 if (GNUNET_NO == ts->is_dns)
586 return GNUNET_SYSERR;
588 if (GNUNET_SYSERR == ts->is_dns)
590 /* channel is DNS from now on */
591 ts->is_dns = GNUNET_YES;
593 if (dlen < sizeof (struct GNUNET_TUN_DnsHeader))
596 return GNUNET_SYSERR;
598 dns = (const struct GNUNET_TUN_DnsHeader *) &message[1];
599 ts->specifics.dns.original_id = dns->id;
600 if (channels[ts->specifics.dns.my_id] == ts)
601 channels[ts->specifics.dns.my_id] = NULL;
602 ts->specifics.dns.my_id = (uint16_t) GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
604 channels[ts->specifics.dns.my_id] = ts;
605 memcpy (buf, dns, dlen);
606 dout = (struct GNUNET_TUN_DnsHeader *) buf;
607 dout->id = ts->specifics.dns.my_id;
608 ts->specifics.dns.rs = GNUNET_DNSSTUB_resolve2 (dnsstub,
612 if (NULL == ts->specifics.dns.rs)
613 return GNUNET_SYSERR;
614 GNUNET_CADET_receive_done (channel);
620 * Given IP information about a connection, calculate the respective
621 * hash we would use for the 'connections_map'.
623 * @param hash resulting hash
624 * @param ri information about the connection
627 hash_redirect_info (struct GNUNET_HashCode *hash,
628 const struct RedirectInformation *ri)
632 memset (hash, 0, sizeof (struct GNUNET_HashCode));
633 /* the GNUnet hashmap only uses the first sizeof(unsigned int) of the hash,
634 so we put the IP address in there (and hope for few collisions) */
636 switch (ri->remote_address.af)
639 memcpy (off, &ri->remote_address.address.ipv4, sizeof (struct in_addr));
640 off += sizeof (struct in_addr);
643 memcpy (off, &ri->remote_address.address.ipv6, sizeof (struct in6_addr));
644 off += sizeof (struct in_addr);
649 memcpy (off, &ri->remote_address.port, sizeof (uint16_t));
650 off += sizeof (uint16_t);
651 switch (ri->local_address.af)
654 memcpy (off, &ri->local_address.address.ipv4, sizeof (struct in_addr));
655 off += sizeof (struct in_addr);
658 memcpy (off, &ri->local_address.address.ipv6, sizeof (struct in6_addr));
659 off += sizeof (struct in_addr);
664 memcpy (off, &ri->local_address.port, sizeof (uint16_t));
665 off += sizeof (uint16_t);
666 memcpy (off, &ri->remote_address.proto, sizeof (uint8_t));
667 /* off += sizeof (uint8_t); */
672 * Get our connection tracking state. Warns if it does not exists,
673 * refreshes the timestamp if it does exist.
675 * @param af address family
676 * @param protocol IPPROTO_UDP or IPPROTO_TCP
677 * @param destination_ip target IP
678 * @param destination_port target port
679 * @param local_ip local IP
680 * @param local_port local port
681 * @param state_key set to hash's state if non-NULL
682 * @return NULL if we have no tracking information for this tuple
684 static struct ChannelState *
685 get_redirect_state (int af,
687 const void *destination_ip,
688 uint16_t destination_port,
689 const void *local_ip,
691 struct GNUNET_HashCode *state_key)
693 struct RedirectInformation ri;
694 struct GNUNET_HashCode key;
695 struct ChannelState *state;
697 if ( ( (af == AF_INET) && (protocol == IPPROTO_ICMP) ) ||
698 ( (af == AF_INET6) && (protocol == IPPROTO_ICMPV6) ) )
701 destination_port = 0;
704 ri.remote_address.af = af;
706 ri.remote_address.address.ipv4 = *((struct in_addr*) destination_ip);
708 ri.remote_address.address.ipv6 = * ((struct in6_addr*) destination_ip);
709 ri.remote_address.port = destination_port;
710 ri.remote_address.proto = protocol;
711 ri.local_address.af = af;
713 ri.local_address.address.ipv4 = *((struct in_addr*) local_ip);
715 ri.local_address.address.ipv6 = * ((struct in6_addr*) local_ip);
716 ri.local_address.port = local_port;
717 ri.local_address.proto = protocol;
718 hash_redirect_info (&key, &ri);
719 if (NULL != state_key)
721 state = GNUNET_CONTAINER_multihashmap_get (connections_map, &key);
724 /* Mark this connection as freshly used */
725 if (NULL == state_key)
726 GNUNET_CONTAINER_heap_update_cost (connections_heap,
727 state->specifics.tcp_udp.heap_node,
728 GNUNET_TIME_absolute_get ().abs_value_us);
734 * Given a service descriptor and a destination port, find the
735 * respective service entry.
737 * @param service_map map of services (TCP or UDP)
738 * @param desc service descriptor
739 * @param destination_port destination port
740 * @return NULL if we are not aware of such a service
742 static struct LocalService *
743 find_service (struct GNUNET_CONTAINER_MultiHashMap *service_map,
744 const struct GNUNET_HashCode *desc,
745 uint16_t destination_port)
747 char key[sizeof (struct GNUNET_HashCode) + sizeof (uint16_t)];
749 memcpy (&key[0], &destination_port, sizeof (uint16_t));
750 memcpy (&key[sizeof(uint16_t)], desc, sizeof (struct GNUNET_HashCode));
751 return GNUNET_CONTAINER_multihashmap_get (service_map,
752 (struct GNUNET_HashCode *) key);
757 * Free memory associated with a service record.
760 * @param key service descriptor
761 * @param value service record to free
765 free_service_record (void *cls,
766 const struct GNUNET_HashCode *key,
769 struct LocalService *service = value;
771 GNUNET_free_non_null (service->name);
772 GNUNET_free (service);
778 * Given a service descriptor and a destination port, find the
779 * respective service entry.
781 * @param service_map map of services (TCP or UDP)
782 * @param name name of the service
783 * @param destination_port destination port
784 * @param service service information record to store (service->name will be set).
787 store_service (struct GNUNET_CONTAINER_MultiHashMap *service_map,
789 uint16_t destination_port,
790 struct LocalService *service)
792 char key[sizeof (struct GNUNET_HashCode) + sizeof (uint16_t)];
793 struct GNUNET_HashCode desc;
795 GNUNET_TUN_service_name_to_hash (name, &desc);
796 service->name = GNUNET_strdup (name);
797 memcpy (&key[0], &destination_port, sizeof (uint16_t));
798 memcpy (&key[sizeof(uint16_t)], &desc, sizeof (struct GNUNET_HashCode));
800 GNUNET_CONTAINER_multihashmap_put (service_map,
801 (struct GNUNET_HashCode *) key,
803 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY))
805 free_service_record (NULL, (struct GNUNET_HashCode *) key, service);
806 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
807 _("Got duplicate service records for `%s:%u'\n"),
809 (unsigned int) destination_port);
815 * CADET is ready to receive a message for the channel. Transmit it.
817 * @param cls the 'struct ChannelState'.
818 * @param size number of bytes available in buf
819 * @param buf where to copy the message
820 * @return number of bytes copied to buf
823 send_to_peer_notify_callback (void *cls, size_t size, void *buf)
825 struct ChannelState *s = cls;
826 struct GNUNET_CADET_Channel *channel = s->channel;
827 struct ChannelMessageQueue *tnq;
830 tnq = s->specifics.tcp_udp.head;
835 s->th = GNUNET_CADET_notify_transmit_ready (channel,
836 GNUNET_NO /* corking */,
837 GNUNET_TIME_UNIT_FOREVER_REL,
839 &send_to_peer_notify_callback,
843 GNUNET_assert (size >= tnq->len);
844 memcpy (buf, tnq->payload, tnq->len);
846 GNUNET_CONTAINER_DLL_remove (s->specifics.tcp_udp.head,
847 s->specifics.tcp_udp.tail,
850 if (NULL != (tnq = s->specifics.tcp_udp.head))
851 s->th = GNUNET_CADET_notify_transmit_ready (channel,
852 GNUNET_NO /* corking */,
853 GNUNET_TIME_UNIT_FOREVER_REL,
855 &send_to_peer_notify_callback,
857 GNUNET_STATISTICS_update (stats,
858 gettext_noop ("# Bytes transmitted via cadet channels"),
865 * Send the given packet via the cadet channel.
867 * @param s channel destination
868 * @param tnq message to queue
871 send_packet_to_cadet_channel (struct ChannelState *s,
872 struct ChannelMessageQueue *tnq)
874 struct GNUNET_CADET_Channel *cadet_channel;
876 cadet_channel = s->channel;
877 GNUNET_assert (NULL != s);
878 GNUNET_CONTAINER_DLL_insert_tail (s->specifics.tcp_udp.head, s->specifics.tcp_udp.tail, tnq);
880 s->th = GNUNET_CADET_notify_transmit_ready (cadet_channel,
881 GNUNET_NO /* cork */,
882 GNUNET_TIME_UNIT_FOREVER_REL,
884 &send_to_peer_notify_callback,
890 * @brief Handles an ICMP packet received from the helper.
892 * @param icmp A pointer to the Packet
893 * @param pktlen number of bytes in 'icmp'
894 * @param af address family (AFINET or AF_INET6)
895 * @param destination_ip destination IP-address of the IP packet (should
896 * be our local address)
897 * @param source_ip original source IP-address of the IP packet (should
898 * be the original destination address)
901 icmp_from_helper (const struct GNUNET_TUN_IcmpHeader *icmp,
904 const void *destination_ip,
905 const void *source_ip)
907 struct ChannelState *state;
908 struct ChannelMessageQueue *tnq;
909 struct GNUNET_EXIT_IcmpToVPNMessage *i2v;
910 const struct GNUNET_TUN_IPv4Header *ipv4;
911 const struct GNUNET_TUN_IPv6Header *ipv6;
912 const struct GNUNET_TUN_UdpHeader *udp;
914 uint16_t source_port;
915 uint16_t destination_port;
919 char sbuf[INET6_ADDRSTRLEN];
920 char dbuf[INET6_ADDRSTRLEN];
921 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
922 "Received ICMP packet going from %s to %s\n",
925 sbuf, sizeof (sbuf)),
928 dbuf, sizeof (dbuf)));
930 if (pktlen < sizeof (struct GNUNET_TUN_IcmpHeader))
937 /* Find out if this is an ICMP packet in response to an existing
938 TCP/UDP packet and if so, figure out ports / protocol of the
939 existing session from the IP data in the ICMP payload */
941 destination_port = 0;
945 protocol = IPPROTO_ICMP;
948 case GNUNET_TUN_ICMPTYPE_ECHO_REPLY:
949 case GNUNET_TUN_ICMPTYPE_ECHO_REQUEST:
951 case GNUNET_TUN_ICMPTYPE_DESTINATION_UNREACHABLE:
952 case GNUNET_TUN_ICMPTYPE_SOURCE_QUENCH:
953 case GNUNET_TUN_ICMPTYPE_TIME_EXCEEDED:
955 sizeof (struct GNUNET_TUN_IcmpHeader) +
956 sizeof (struct GNUNET_TUN_IPv4Header) + 8)
962 ipv4 = (const struct GNUNET_TUN_IPv4Header *) &icmp[1];
963 protocol = ipv4->protocol;
964 /* could be TCP or UDP, but both have the ports in the right
965 place, so that doesn't matter here */
966 udp = (const struct GNUNET_TUN_UdpHeader *) &ipv4[1];
967 /* swap ports, as they are from the original message */
968 destination_port = ntohs (udp->source_port);
969 source_port = ntohs (udp->destination_port);
970 /* throw away ICMP payload, won't be useful for the other side anyway */
971 pktlen = sizeof (struct GNUNET_TUN_IcmpHeader);
974 GNUNET_STATISTICS_update (stats,
975 gettext_noop ("# ICMPv4 packets dropped (type not allowed)"),
981 protocol = IPPROTO_ICMPV6;
984 case GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE:
985 case GNUNET_TUN_ICMPTYPE6_PACKET_TOO_BIG:
986 case GNUNET_TUN_ICMPTYPE6_TIME_EXCEEDED:
987 case GNUNET_TUN_ICMPTYPE6_PARAMETER_PROBLEM:
989 sizeof (struct GNUNET_TUN_IcmpHeader) +
990 sizeof (struct GNUNET_TUN_IPv6Header) + 8)
996 ipv6 = (const struct GNUNET_TUN_IPv6Header *) &icmp[1];
997 protocol = ipv6->next_header;
998 /* could be TCP or UDP, but both have the ports in the right
999 place, so that doesn't matter here */
1000 udp = (const struct GNUNET_TUN_UdpHeader *) &ipv6[1];
1001 /* swap ports, as they are from the original message */
1002 destination_port = ntohs (udp->source_port);
1003 source_port = ntohs (udp->destination_port);
1004 /* throw away ICMP payload, won't be useful for the other side anyway */
1005 pktlen = sizeof (struct GNUNET_TUN_IcmpHeader);
1007 case GNUNET_TUN_ICMPTYPE6_ECHO_REQUEST:
1008 case GNUNET_TUN_ICMPTYPE6_ECHO_REPLY:
1011 GNUNET_STATISTICS_update (stats,
1012 gettext_noop ("# ICMPv6 packets dropped (type not allowed)"),
1023 state = get_redirect_state (af, IPPROTO_ICMP,
1028 case IPPROTO_ICMPV6:
1029 state = get_redirect_state (af, IPPROTO_ICMPV6,
1035 state = get_redirect_state (af, IPPROTO_UDP,
1043 state = get_redirect_state (af, IPPROTO_TCP,
1051 GNUNET_STATISTICS_update (stats,
1052 gettext_noop ("# ICMP packets dropped (not allowed)"),
1058 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1059 _("ICMP Packet dropped, have no matching connection information\n"));
1062 mlen = sizeof (struct GNUNET_EXIT_IcmpToVPNMessage) + pktlen - sizeof (struct GNUNET_TUN_IcmpHeader);
1063 tnq = GNUNET_malloc (sizeof (struct ChannelMessageQueue) + mlen);
1064 tnq->payload = &tnq[1];
1066 i2v = (struct GNUNET_EXIT_IcmpToVPNMessage *) &tnq[1];
1067 i2v->header.size = htons ((uint16_t) mlen);
1068 i2v->header.type = htons (GNUNET_MESSAGE_TYPE_VPN_ICMP_TO_VPN);
1069 i2v->af = htonl (af);
1070 memcpy (&i2v->icmp_header,
1073 send_packet_to_cadet_channel (state, tnq);
1078 * @brief Handles an UDP packet received from the helper.
1080 * @param udp A pointer to the Packet
1081 * @param pktlen number of bytes in 'udp'
1082 * @param af address family (AFINET or AF_INET6)
1083 * @param destination_ip destination IP-address of the IP packet (should
1084 * be our local address)
1085 * @param source_ip original source IP-address of the IP packet (should
1086 * be the original destination address)
1089 udp_from_helper (const struct GNUNET_TUN_UdpHeader *udp,
1092 const void *destination_ip,
1093 const void *source_ip)
1095 struct ChannelState *state;
1096 struct ChannelMessageQueue *tnq;
1097 struct GNUNET_EXIT_UdpReplyMessage *urm;
1101 char sbuf[INET6_ADDRSTRLEN];
1102 char dbuf[INET6_ADDRSTRLEN];
1103 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1104 "Received UDP packet going from %s:%u to %s:%u\n",
1107 sbuf, sizeof (sbuf)),
1108 (unsigned int) ntohs (udp->source_port),
1111 dbuf, sizeof (dbuf)),
1112 (unsigned int) ntohs (udp->destination_port));
1114 if (pktlen < sizeof (struct GNUNET_TUN_UdpHeader))
1120 if (pktlen != ntohs (udp->len))
1126 state = get_redirect_state (af, IPPROTO_UDP,
1128 ntohs (udp->source_port),
1130 ntohs (udp->destination_port),
1134 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1135 _("UDP Packet dropped, have no matching connection information\n"));
1138 mlen = sizeof (struct GNUNET_EXIT_UdpReplyMessage) + pktlen - sizeof (struct GNUNET_TUN_UdpHeader);
1139 tnq = GNUNET_malloc (sizeof (struct ChannelMessageQueue) + mlen);
1140 tnq->payload = &tnq[1];
1142 urm = (struct GNUNET_EXIT_UdpReplyMessage *) &tnq[1];
1143 urm->header.size = htons ((uint16_t) mlen);
1144 urm->header.type = htons (GNUNET_MESSAGE_TYPE_VPN_UDP_REPLY);
1145 urm->source_port = htons (0);
1146 urm->destination_port = htons (0);
1149 pktlen - sizeof (struct GNUNET_TUN_UdpHeader));
1150 send_packet_to_cadet_channel (state, tnq);
1155 * @brief Handles a TCP packet received from the helper.
1157 * @param tcp A pointer to the Packet
1158 * @param pktlen the length of the packet, including its TCP header
1159 * @param af address family (AFINET or AF_INET6)
1160 * @param destination_ip destination IP-address of the IP packet (should
1161 * be our local address)
1162 * @param source_ip original source IP-address of the IP packet (should
1163 * be the original destination address)
1166 tcp_from_helper (const struct GNUNET_TUN_TcpHeader *tcp,
1169 const void *destination_ip,
1170 const void *source_ip)
1172 struct ChannelState *state;
1173 char buf[pktlen] GNUNET_ALIGN;
1174 struct GNUNET_TUN_TcpHeader *mtcp;
1175 struct GNUNET_EXIT_TcpDataMessage *tdm;
1176 struct ChannelMessageQueue *tnq;
1180 char sbuf[INET6_ADDRSTRLEN];
1181 char dbuf[INET6_ADDRSTRLEN];
1182 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1183 "Received TCP packet with %u bytes going from %s:%u to %s:%u\n",
1184 pktlen - sizeof (struct GNUNET_TUN_TcpHeader),
1187 sbuf, sizeof (sbuf)),
1188 (unsigned int) ntohs (tcp->source_port),
1191 dbuf, sizeof (dbuf)),
1192 (unsigned int) ntohs (tcp->destination_port));
1194 if (pktlen < sizeof (struct GNUNET_TUN_TcpHeader))
1200 state = get_redirect_state (af, IPPROTO_TCP,
1202 ntohs (tcp->source_port),
1204 ntohs (tcp->destination_port),
1208 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1209 _("TCP Packet dropped, have no matching connection information\n"));
1213 /* mug port numbers and crc to avoid information leakage;
1214 sender will need to lookup the correct values anyway */
1215 memcpy (buf, tcp, pktlen);
1216 mtcp = (struct GNUNET_TUN_TcpHeader *) buf;
1217 mtcp->source_port = 0;
1218 mtcp->destination_port = 0;
1221 mlen = sizeof (struct GNUNET_EXIT_TcpDataMessage) + (pktlen - sizeof (struct GNUNET_TUN_TcpHeader));
1222 if (mlen >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1228 tnq = GNUNET_malloc (sizeof (struct ChannelMessageQueue) + mlen);
1229 tnq->payload = &tnq[1];
1231 tdm = (struct GNUNET_EXIT_TcpDataMessage *) &tnq[1];
1232 tdm->header.size = htons ((uint16_t) mlen);
1233 tdm->header.type = htons (GNUNET_MESSAGE_TYPE_VPN_TCP_DATA_TO_VPN);
1234 tdm->reserved = htonl (0);
1235 memcpy (&tdm->tcp_header,
1238 send_packet_to_cadet_channel (state, tnq);
1243 * Receive packets from the helper-process
1246 * @param client unsued
1247 * @param message message received from helper
1250 message_token (void *cls GNUNET_UNUSED,
1251 void *client GNUNET_UNUSED,
1252 const struct GNUNET_MessageHeader *message)
1254 const struct GNUNET_TUN_Layer2PacketHeader *pkt_tun;
1257 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1258 "Got %u-byte message of type %u from gnunet-helper-exit\n",
1259 ntohs (message->size),
1260 ntohs (message->type));
1261 GNUNET_STATISTICS_update (stats,
1262 gettext_noop ("# Packets received from TUN"),
1264 if (ntohs (message->type) != GNUNET_MESSAGE_TYPE_VPN_HELPER)
1269 size = ntohs (message->size);
1270 if (size < sizeof (struct GNUNET_TUN_Layer2PacketHeader) + sizeof (struct GNUNET_MessageHeader))
1275 GNUNET_STATISTICS_update (stats,
1276 gettext_noop ("# Bytes received from TUN"),
1278 pkt_tun = (const struct GNUNET_TUN_Layer2PacketHeader *) &message[1];
1279 size -= sizeof (struct GNUNET_TUN_Layer2PacketHeader) + sizeof (struct GNUNET_MessageHeader);
1280 switch (ntohs (pkt_tun->proto))
1284 const struct GNUNET_TUN_IPv4Header *pkt4;
1286 if (size < sizeof (struct GNUNET_TUN_IPv4Header))
1288 /* Kernel to blame? */
1292 pkt4 = (const struct GNUNET_TUN_IPv4Header *) &pkt_tun[1];
1293 if (size != ntohs (pkt4->total_length))
1295 /* Kernel to blame? */
1299 if (pkt4->header_length * 4 != sizeof (struct GNUNET_TUN_IPv4Header))
1301 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1302 _("IPv4 packet options received. Ignored.\n"));
1306 size -= sizeof (struct GNUNET_TUN_IPv4Header);
1307 switch (pkt4->protocol)
1310 udp_from_helper ((const struct GNUNET_TUN_UdpHeader *) &pkt4[1], size,
1312 &pkt4->destination_address,
1313 &pkt4->source_address);
1316 tcp_from_helper ((const struct GNUNET_TUN_TcpHeader *) &pkt4[1], size,
1318 &pkt4->destination_address,
1319 &pkt4->source_address);
1322 icmp_from_helper ((const struct GNUNET_TUN_IcmpHeader *) &pkt4[1], size,
1324 &pkt4->destination_address,
1325 &pkt4->source_address);
1328 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1329 _("IPv4 packet with unsupported next header %u received. Ignored.\n"),
1330 (int) pkt4->protocol);
1337 const struct GNUNET_TUN_IPv6Header *pkt6;
1339 if (size < sizeof (struct GNUNET_TUN_IPv6Header))
1341 /* Kernel to blame? */
1345 pkt6 = (struct GNUNET_TUN_IPv6Header *) &pkt_tun[1];
1346 if (size != ntohs (pkt6->payload_length) + sizeof (struct GNUNET_TUN_IPv6Header))
1348 /* Kernel to blame? */
1352 size -= sizeof (struct GNUNET_TUN_IPv6Header);
1353 switch (pkt6->next_header)
1356 udp_from_helper ((const struct GNUNET_TUN_UdpHeader *) &pkt6[1], size,
1358 &pkt6->destination_address,
1359 &pkt6->source_address);
1362 tcp_from_helper ((const struct GNUNET_TUN_TcpHeader *) &pkt6[1], size,
1364 &pkt6->destination_address,
1365 &pkt6->source_address);
1367 case IPPROTO_ICMPV6:
1368 icmp_from_helper ((const struct GNUNET_TUN_IcmpHeader *) &pkt6[1], size,
1370 &pkt6->destination_address,
1371 &pkt6->source_address);
1374 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1375 _("IPv6 packet with unsupported next header %d received. Ignored.\n"),
1382 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1383 _("Packet from unknown protocol %u received. Ignored.\n"),
1384 ntohs (pkt_tun->proto));
1392 * We need to create a (unique) fresh local address (IP+port).
1395 * @param af desired address family
1396 * @param proto desired protocol (IPPROTO_UDP or IPPROTO_TCP)
1397 * @param local_address address to initialize
1400 setup_fresh_address (int af,
1402 struct SocketAddress *local_address)
1404 local_address->af = af;
1405 local_address->proto = (uint8_t) proto;
1406 /* default "local" port range is often 32768--61000,
1407 so we pick a random value in that range */
1408 if ( ( (af == AF_INET) && (proto == IPPROTO_ICMP) ) ||
1409 ( (af == AF_INET6) && (proto == IPPROTO_ICMPV6) ) )
1410 local_address->port = 0;
1413 = (uint16_t) 32768 + GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
1419 struct in_addr addr;
1420 struct in_addr mask;
1423 addr = exit_ipv4addr;
1424 mask = exit_ipv4mask;
1425 if (0 == ~mask.s_addr)
1427 /* only one valid IP anyway */
1428 local_address->address.ipv4 = addr;
1431 /* Given 192.168.0.1/255.255.0.0, we want a mask
1432 of '192.168.255.255', thus: */
1433 mask.s_addr = addr.s_addr | ~mask.s_addr;
1434 /* Pick random IPv4 address within the subnet, except 'addr' or 'mask' itself */
1437 rnd.s_addr = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
1439 local_address->address.ipv4.s_addr = (addr.s_addr | rnd.s_addr) & mask.s_addr;
1441 while ( (local_address->address.ipv4.s_addr == addr.s_addr) ||
1442 (local_address->address.ipv4.s_addr == mask.s_addr) );
1447 struct in6_addr addr;
1448 struct in6_addr mask;
1449 struct in6_addr rnd;
1452 addr = exit_ipv6addr;
1453 GNUNET_assert (ipv6prefix < 128);
1454 if (ipv6prefix == 127)
1456 /* only one valid IP anyway */
1457 local_address->address.ipv6 = addr;
1460 /* Given ABCD::/96, we want a mask of 'ABCD::FFFF:FFFF,
1463 for (i=127;i>=ipv6prefix;i--)
1464 mask.s6_addr[i / 8] |= (1 << (i % 8));
1466 /* Pick random IPv6 address within the subnet, except 'addr' or 'mask' itself */
1471 rnd.s6_addr[i] = (unsigned char) GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
1473 local_address->address.ipv6.s6_addr[i]
1474 = (addr.s6_addr[i] | rnd.s6_addr[i]) & mask.s6_addr[i];
1477 while ( (0 == memcmp (&local_address->address.ipv6,
1479 sizeof (struct in6_addr))) ||
1480 (0 == memcmp (&local_address->address.ipv6,
1482 sizeof (struct in6_addr))) );
1492 * We are starting a fresh connection (TCP or UDP) and need
1493 * to pick a source port and IP address (within the correct
1494 * range and address family) to associate replies with the
1495 * connection / correct cadet channel. This function generates
1496 * a "fresh" source IP and source port number for a connection
1497 * After picking a good source address, this function sets up
1498 * the state in the 'connections_map' and 'connections_heap'
1499 * to allow finding the state when needed later. The function
1500 * also makes sure that we remain within memory limits by
1501 * cleaning up 'old' states.
1503 * @param state skeleton state to setup a record for; should
1504 * 'state->specifics.tcp_udp.ri.remote_address' filled in so that
1505 * this code can determine which AF/protocol is
1506 * going to be used (the 'channel' should also
1507 * already be set); after calling this function,
1508 * heap_node and the local_address will be
1509 * also initialized (heap_node != NULL can be
1510 * used to test if a state has been fully setup).
1513 setup_state_record (struct ChannelState *state)
1515 struct GNUNET_HashCode key;
1516 struct ChannelState *s;
1518 /* generate fresh, unique address */
1521 if (NULL == state->specifics.tcp_udp.serv)
1522 setup_fresh_address (state->specifics.tcp_udp.ri.remote_address.af,
1523 state->specifics.tcp_udp.ri.remote_address.proto,
1524 &state->specifics.tcp_udp.ri.local_address);
1526 setup_fresh_address (state->specifics.tcp_udp.serv->address.af,
1527 state->specifics.tcp_udp.serv->address.proto,
1528 &state->specifics.tcp_udp.ri.local_address);
1529 } while (NULL != get_redirect_state (state->specifics.tcp_udp.ri.remote_address.af,
1530 state->specifics.tcp_udp.ri.remote_address.proto,
1531 &state->specifics.tcp_udp.ri.remote_address.address,
1532 state->specifics.tcp_udp.ri.remote_address.port,
1533 &state->specifics.tcp_udp.ri.local_address.address,
1534 state->specifics.tcp_udp.ri.local_address.port,
1537 char buf[INET6_ADDRSTRLEN];
1538 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1539 "Picked local address %s:%u for new connection\n",
1540 inet_ntop (state->specifics.tcp_udp.ri.local_address.af,
1541 &state->specifics.tcp_udp.ri.local_address.address,
1543 (unsigned int) state->specifics.tcp_udp.ri.local_address.port);
1545 state->specifics.tcp_udp.state_key = key;
1546 GNUNET_assert (GNUNET_OK ==
1547 GNUNET_CONTAINER_multihashmap_put (connections_map,
1549 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
1550 state->specifics.tcp_udp.heap_node = GNUNET_CONTAINER_heap_insert (connections_heap,
1552 GNUNET_TIME_absolute_get ().abs_value_us);
1553 while (GNUNET_CONTAINER_heap_get_size (connections_heap) > max_connections)
1555 s = GNUNET_CONTAINER_heap_remove_root (connections_heap);
1556 GNUNET_assert (state != s);
1557 s->specifics.tcp_udp.heap_node = NULL;
1558 GNUNET_CADET_channel_destroy (s->channel);
1559 GNUNET_assert (GNUNET_OK ==
1560 GNUNET_CONTAINER_multihashmap_remove (connections_map,
1561 &s->specifics.tcp_udp.state_key,
1569 * Prepare an IPv4 packet for transmission via the TUN interface.
1570 * Initializes the IP header and calculates checksums (IP+UDP/TCP).
1571 * For UDP, the UDP header will be fully created, whereas for TCP
1572 * only the ports and checksum will be filled in. So for TCP,
1573 * a skeleton TCP header must be part of the provided payload.
1575 * @param payload payload of the packet (starting with UDP payload or
1576 * TCP header, depending on protocol)
1577 * @param payload_length number of bytes in 'payload'
1578 * @param protocol IPPROTO_UDP or IPPROTO_TCP
1579 * @param tcp_header skeleton of the TCP header, NULL for UDP
1580 * @param src_address source address to use (IP and port)
1581 * @param dst_address destination address to use (IP and port)
1582 * @param pkt4 where to write the assembled packet; must
1583 * contain enough space for the IP header, UDP/TCP header
1587 prepare_ipv4_packet (const void *payload, size_t payload_length,
1589 const struct GNUNET_TUN_TcpHeader *tcp_header,
1590 const struct SocketAddress *src_address,
1591 const struct SocketAddress *dst_address,
1592 struct GNUNET_TUN_IPv4Header *pkt4)
1596 len = payload_length;
1600 len += sizeof (struct GNUNET_TUN_UdpHeader);
1603 len += sizeof (struct GNUNET_TUN_TcpHeader);
1604 GNUNET_assert (NULL != tcp_header);
1610 if (len + sizeof (struct GNUNET_TUN_IPv4Header) > UINT16_MAX)
1616 GNUNET_TUN_initialize_ipv4_header (pkt4,
1619 &src_address->address.ipv4,
1620 &dst_address->address.ipv4);
1625 struct GNUNET_TUN_UdpHeader *pkt4_udp = (struct GNUNET_TUN_UdpHeader *) &pkt4[1];
1627 pkt4_udp->source_port = htons (src_address->port);
1628 pkt4_udp->destination_port = htons (dst_address->port);
1629 pkt4_udp->len = htons ((uint16_t) payload_length);
1630 GNUNET_TUN_calculate_udp4_checksum (pkt4,
1632 payload, payload_length);
1633 memcpy (&pkt4_udp[1], payload, payload_length);
1638 struct GNUNET_TUN_TcpHeader *pkt4_tcp = (struct GNUNET_TUN_TcpHeader *) &pkt4[1];
1640 *pkt4_tcp = *tcp_header;
1641 pkt4_tcp->source_port = htons (src_address->port);
1642 pkt4_tcp->destination_port = htons (dst_address->port);
1643 GNUNET_TUN_calculate_tcp4_checksum (pkt4,
1647 memcpy (&pkt4_tcp[1], payload, payload_length);
1657 * Prepare an IPv6 packet for transmission via the TUN interface.
1658 * Initializes the IP header and calculates checksums (IP+UDP/TCP).
1659 * For UDP, the UDP header will be fully created, whereas for TCP
1660 * only the ports and checksum will be filled in. So for TCP,
1661 * a skeleton TCP header must be part of the provided payload.
1663 * @param payload payload of the packet (starting with UDP payload or
1664 * TCP header, depending on protocol)
1665 * @param payload_length number of bytes in 'payload'
1666 * @param protocol IPPROTO_UDP or IPPROTO_TCP
1667 * @param tcp_header skeleton TCP header data to send, NULL for UDP
1668 * @param src_address source address to use (IP and port)
1669 * @param dst_address destination address to use (IP and port)
1670 * @param pkt6 where to write the assembled packet; must
1671 * contain enough space for the IP header, UDP/TCP header
1675 prepare_ipv6_packet (const void *payload, size_t payload_length,
1677 const struct GNUNET_TUN_TcpHeader *tcp_header,
1678 const struct SocketAddress *src_address,
1679 const struct SocketAddress *dst_address,
1680 struct GNUNET_TUN_IPv6Header *pkt6)
1684 len = payload_length;
1688 len += sizeof (struct GNUNET_TUN_UdpHeader);
1691 len += sizeof (struct GNUNET_TUN_TcpHeader);
1697 if (len > UINT16_MAX)
1703 GNUNET_TUN_initialize_ipv6_header (pkt6,
1706 &src_address->address.ipv6,
1707 &dst_address->address.ipv6);
1713 struct GNUNET_TUN_UdpHeader *pkt6_udp = (struct GNUNET_TUN_UdpHeader *) &pkt6[1];
1715 pkt6_udp->source_port = htons (src_address->port);
1716 pkt6_udp->destination_port = htons (dst_address->port);
1717 pkt6_udp->len = htons ((uint16_t) payload_length);
1718 GNUNET_TUN_calculate_udp6_checksum (pkt6,
1722 memcpy (&pkt6_udp[1], payload, payload_length);
1727 struct GNUNET_TUN_TcpHeader *pkt6_tcp = (struct GNUNET_TUN_TcpHeader *) &pkt6[1];
1729 /* memcpy first here as some TCP header fields are initialized this way! */
1730 *pkt6_tcp = *tcp_header;
1731 pkt6_tcp->source_port = htons (src_address->port);
1732 pkt6_tcp->destination_port = htons (dst_address->port);
1733 GNUNET_TUN_calculate_tcp6_checksum (pkt6,
1737 memcpy (&pkt6_tcp[1], payload, payload_length);
1748 * Send a TCP packet via the TUN interface.
1750 * @param destination_address IP and port to use for the TCP packet's destination
1751 * @param source_address IP and port to use for the TCP packet's source
1752 * @param tcp_header header template to use
1753 * @param payload payload of the TCP packet
1754 * @param payload_length number of bytes in @a payload
1757 send_tcp_packet_via_tun (const struct SocketAddress *destination_address,
1758 const struct SocketAddress *source_address,
1759 const struct GNUNET_TUN_TcpHeader *tcp_header,
1760 const void *payload, size_t payload_length)
1764 GNUNET_STATISTICS_update (stats,
1765 gettext_noop ("# TCP packets sent via TUN"),
1767 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1768 "Sending packet with %u bytes TCP payload via TUN\n",
1769 (unsigned int) payload_length);
1770 len = sizeof (struct GNUNET_MessageHeader) + sizeof (struct GNUNET_TUN_Layer2PacketHeader);
1771 switch (source_address->af)
1774 len += sizeof (struct GNUNET_TUN_IPv4Header);
1777 len += sizeof (struct GNUNET_TUN_IPv6Header);
1783 len += sizeof (struct GNUNET_TUN_TcpHeader);
1784 len += payload_length;
1785 if (len >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1791 char buf[len] GNUNET_ALIGN;
1792 struct GNUNET_MessageHeader *hdr;
1793 struct GNUNET_TUN_Layer2PacketHeader *tun;
1795 hdr = (struct GNUNET_MessageHeader *) buf;
1796 hdr->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
1797 hdr->size = htons (len);
1798 tun = (struct GNUNET_TUN_Layer2PacketHeader*) &hdr[1];
1799 tun->flags = htons (0);
1800 switch (source_address->af)
1804 struct GNUNET_TUN_IPv4Header * ipv4 = (struct GNUNET_TUN_IPv4Header*) &tun[1];
1806 tun->proto = htons (ETH_P_IPV4);
1807 prepare_ipv4_packet (payload, payload_length,
1811 destination_address,
1817 struct GNUNET_TUN_IPv6Header * ipv6 = (struct GNUNET_TUN_IPv6Header*) &tun[1];
1819 tun->proto = htons (ETH_P_IPV6);
1820 prepare_ipv6_packet (payload, payload_length,
1824 destination_address,
1832 if (NULL != helper_handle)
1833 (void) GNUNET_HELPER_send (helper_handle,
1834 (const struct GNUNET_MessageHeader*) buf,
1842 * Process a request via cadet to send a request to a TCP service
1843 * offered by this system.
1845 * @param cls closure, NULL
1846 * @param channel connection to the other end
1847 * @param channel_ctx pointer to our `struct ChannelState *`
1848 * @param message the actual message
1849 * @return #GNUNET_OK to keep the connection open,
1850 * #GNUNET_SYSERR to close it (signal serious error)
1853 receive_tcp_service (void *cls,
1854 struct GNUNET_CADET_Channel *channel,
1856 const struct GNUNET_MessageHeader *message)
1858 struct ChannelState *state = *channel_ctx;
1859 const struct GNUNET_EXIT_TcpServiceStartMessage *start;
1860 uint16_t pkt_len = ntohs (message->size);
1864 GNUNET_break_op (0);
1865 return GNUNET_SYSERR;
1867 if (GNUNET_YES == state->is_dns)
1869 GNUNET_break_op (0);
1870 return GNUNET_SYSERR;
1872 if (GNUNET_SYSERR == state->is_dns)
1874 /* channel is UDP/TCP from now on */
1875 state->is_dns = GNUNET_NO;
1877 GNUNET_STATISTICS_update (stats,
1878 gettext_noop ("# TCP service creation requests received via cadet"),
1880 GNUNET_STATISTICS_update (stats,
1881 gettext_noop ("# Bytes received from CADET"),
1882 pkt_len, GNUNET_NO);
1883 /* check that we got at least a valid header */
1884 if (pkt_len < sizeof (struct GNUNET_EXIT_TcpServiceStartMessage))
1886 GNUNET_break_op (0);
1887 return GNUNET_SYSERR;
1889 start = (const struct GNUNET_EXIT_TcpServiceStartMessage*) message;
1890 pkt_len -= sizeof (struct GNUNET_EXIT_TcpServiceStartMessage);
1891 if ( (NULL != state->specifics.tcp_udp.serv) ||
1892 (NULL != state->specifics.tcp_udp.heap_node) )
1894 GNUNET_break_op (0);
1895 return GNUNET_SYSERR;
1897 if (start->tcp_header.off * 4 < sizeof (struct GNUNET_TUN_TcpHeader))
1899 GNUNET_break_op (0);
1900 return GNUNET_SYSERR;
1902 GNUNET_break_op (ntohl (start->reserved) == 0);
1903 /* setup fresh connection */
1904 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1905 "Received data from %s for forwarding to TCP service %s on port %u\n",
1906 GNUNET_i2s (&state->peer),
1907 GNUNET_h2s (&start->service_descriptor),
1908 (unsigned int) ntohs (start->tcp_header.destination_port));
1909 if (NULL == (state->specifics.tcp_udp.serv =
1910 find_service (tcp_services,
1911 &start->service_descriptor,
1912 ntohs (start->tcp_header.destination_port))))
1914 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1915 _("No service %s found for %s on port %d!\n"),
1916 GNUNET_h2s (&start->service_descriptor),
1918 ntohs (start->tcp_header.destination_port));
1919 GNUNET_STATISTICS_update (stats,
1920 gettext_noop ("# TCP requests dropped (no such service)"),
1922 return GNUNET_SYSERR;
1924 state->specifics.tcp_udp.ri.remote_address = state->specifics.tcp_udp.serv->address;
1925 setup_state_record (state);
1926 send_tcp_packet_via_tun (&state->specifics.tcp_udp.ri.remote_address,
1927 &state->specifics.tcp_udp.ri.local_address,
1929 &start[1], pkt_len);
1930 GNUNET_CADET_receive_done (channel);
1936 * Process a request to forward TCP data to the Internet via this peer.
1938 * @param cls closure, NULL
1939 * @param channel connection to the other end
1940 * @param channel_ctx pointer to our `struct ChannelState *`
1941 * @param message the actual message
1942 * @return #GNUNET_OK to keep the connection open,
1943 * #GNUNET_SYSERR to close it (signal serious error)
1946 receive_tcp_remote (void *cls GNUNET_UNUSED,
1947 struct GNUNET_CADET_Channel *channel,
1948 void **channel_ctx GNUNET_UNUSED,
1949 const struct GNUNET_MessageHeader *message)
1951 struct ChannelState *state = *channel_ctx;
1952 const struct GNUNET_EXIT_TcpInternetStartMessage *start;
1953 uint16_t pkt_len = ntohs (message->size);
1954 const struct in_addr *v4;
1955 const struct in6_addr *v6;
1956 const void *payload;
1961 GNUNET_break_op (0);
1962 return GNUNET_SYSERR;
1964 if (GNUNET_YES == state->is_dns)
1966 GNUNET_break_op (0);
1967 return GNUNET_SYSERR;
1969 if (GNUNET_SYSERR == state->is_dns)
1971 /* channel is UDP/TCP from now on */
1972 state->is_dns = GNUNET_NO;
1974 GNUNET_STATISTICS_update (stats,
1975 gettext_noop ("# Bytes received from CADET"),
1976 pkt_len, GNUNET_NO);
1977 GNUNET_STATISTICS_update (stats,
1978 gettext_noop ("# TCP IP-exit creation requests received via cadet"),
1980 if (pkt_len < sizeof (struct GNUNET_EXIT_TcpInternetStartMessage))
1982 GNUNET_break_op (0);
1983 return GNUNET_SYSERR;
1985 start = (const struct GNUNET_EXIT_TcpInternetStartMessage*) message;
1986 pkt_len -= sizeof (struct GNUNET_EXIT_TcpInternetStartMessage);
1987 if ( (NULL != state->specifics.tcp_udp.serv) ||
1988 (NULL != state->specifics.tcp_udp.heap_node) )
1990 GNUNET_break_op (0);
1991 return GNUNET_SYSERR;
1993 if (start->tcp_header.off * 4 < sizeof (struct GNUNET_TUN_TcpHeader))
1995 GNUNET_break_op (0);
1996 return GNUNET_SYSERR;
1998 af = (int) ntohl (start->af);
1999 state->specifics.tcp_udp.ri.remote_address.af = af;
2003 if (pkt_len < sizeof (struct in_addr))
2005 GNUNET_break_op (0);
2006 return GNUNET_SYSERR;
2010 GNUNET_break_op (0);
2011 return GNUNET_SYSERR;
2013 v4 = (const struct in_addr*) &start[1];
2015 pkt_len -= sizeof (struct in_addr);
2016 state->specifics.tcp_udp.ri.remote_address.address.ipv4 = *v4;
2019 if (pkt_len < sizeof (struct in6_addr))
2021 GNUNET_break_op (0);
2022 return GNUNET_SYSERR;
2026 GNUNET_break_op (0);
2027 return GNUNET_SYSERR;
2029 v6 = (const struct in6_addr*) &start[1];
2031 pkt_len -= sizeof (struct in6_addr);
2032 state->specifics.tcp_udp.ri.remote_address.address.ipv6 = *v6;
2035 GNUNET_break_op (0);
2036 return GNUNET_SYSERR;
2039 char buf[INET6_ADDRSTRLEN];
2040 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2041 "Received payload from %s for existing TCP stream to %s:%u\n",
2042 GNUNET_i2s (&state->peer),
2044 &state->specifics.tcp_udp.ri.remote_address.address,
2046 (unsigned int) ntohs (start->tcp_header.destination_port));
2048 state->specifics.tcp_udp.ri.remote_address.proto = IPPROTO_TCP;
2049 state->specifics.tcp_udp.ri.remote_address.port = ntohs (start->tcp_header.destination_port);
2050 setup_state_record (state);
2051 send_tcp_packet_via_tun (&state->specifics.tcp_udp.ri.remote_address,
2052 &state->specifics.tcp_udp.ri.local_address,
2055 GNUNET_CADET_receive_done (channel);
2061 * Process a request to forward TCP data on an established
2062 * connection via this peer.
2064 * @param cls closure, NULL
2065 * @param channel connection to the other end
2066 * @param channel_ctx pointer to our `struct ChannelState *`
2067 * @param message the actual message
2068 * @return #GNUNET_OK to keep the connection open,
2069 * #GNUNET_SYSERR to close it (signal serious error)
2072 receive_tcp_data (void *cls GNUNET_UNUSED,
2073 struct GNUNET_CADET_Channel *channel,
2074 void **channel_ctx GNUNET_UNUSED,
2075 const struct GNUNET_MessageHeader *message)
2077 struct ChannelState *state = *channel_ctx;
2078 const struct GNUNET_EXIT_TcpDataMessage *data;
2079 uint16_t pkt_len = ntohs (message->size);
2081 GNUNET_STATISTICS_update (stats,
2082 gettext_noop ("# Bytes received from CADET"),
2083 pkt_len, GNUNET_NO);
2084 GNUNET_STATISTICS_update (stats,
2085 gettext_noop ("# TCP data requests received via cadet"),
2087 if (pkt_len < sizeof (struct GNUNET_EXIT_TcpDataMessage))
2089 GNUNET_break_op (0);
2090 return GNUNET_SYSERR;
2092 data = (const struct GNUNET_EXIT_TcpDataMessage*) message;
2093 pkt_len -= sizeof (struct GNUNET_EXIT_TcpDataMessage);
2094 if ( (NULL == state) ||
2095 (NULL == state->specifics.tcp_udp.heap_node) )
2097 /* connection should have been up! */
2098 GNUNET_STATISTICS_update (stats,
2099 gettext_noop ("# TCP DATA requests dropped (no session)"),
2101 GNUNET_break_op (0);
2102 return GNUNET_SYSERR;
2104 if (data->tcp_header.off * 4 < sizeof (struct GNUNET_TUN_TcpHeader))
2106 GNUNET_break_op (0);
2107 return GNUNET_SYSERR;
2109 if (GNUNET_YES == state->is_dns)
2111 GNUNET_break_op (0);
2112 return GNUNET_SYSERR;
2114 if (GNUNET_SYSERR == state->is_dns)
2116 /* channel is UDP/TCP from now on */
2117 state->is_dns = GNUNET_NO;
2120 GNUNET_break_op (ntohl (data->reserved) == 0);
2122 char buf[INET6_ADDRSTRLEN];
2123 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2124 "Received additional %u bytes of data from %s for TCP stream to %s:%u\n",
2126 GNUNET_i2s (&state->peer),
2127 inet_ntop (state->specifics.tcp_udp.ri.remote_address.af,
2128 &state->specifics.tcp_udp.ri.remote_address.address,
2130 (unsigned int) state->specifics.tcp_udp.ri.remote_address.port);
2133 send_tcp_packet_via_tun (&state->specifics.tcp_udp.ri.remote_address,
2134 &state->specifics.tcp_udp.ri.local_address,
2137 GNUNET_CADET_receive_done (channel);
2143 * Send an ICMP packet via the TUN interface.
2145 * @param destination_address IP to use for the ICMP packet's destination
2146 * @param source_address IP to use for the ICMP packet's source
2147 * @param icmp_header ICMP header to send
2148 * @param payload payload of the ICMP packet (does NOT include ICMP header)
2149 * @param payload_length number of bytes of data in @a payload
2152 send_icmp_packet_via_tun (const struct SocketAddress *destination_address,
2153 const struct SocketAddress *source_address,
2154 const struct GNUNET_TUN_IcmpHeader *icmp_header,
2155 const void *payload, size_t payload_length)
2158 struct GNUNET_TUN_IcmpHeader *icmp;
2160 GNUNET_STATISTICS_update (stats,
2161 gettext_noop ("# ICMP packets sent via TUN"),
2163 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2164 "Sending packet with %u bytes ICMP payload via TUN\n",
2165 (unsigned int) payload_length);
2166 len = sizeof (struct GNUNET_MessageHeader) + sizeof (struct GNUNET_TUN_Layer2PacketHeader);
2167 switch (destination_address->af)
2170 len += sizeof (struct GNUNET_TUN_IPv4Header);
2173 len += sizeof (struct GNUNET_TUN_IPv6Header);
2179 len += sizeof (struct GNUNET_TUN_IcmpHeader);
2180 len += payload_length;
2181 if (len >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
2187 char buf[len] GNUNET_ALIGN;
2188 struct GNUNET_MessageHeader *hdr;
2189 struct GNUNET_TUN_Layer2PacketHeader *tun;
2191 hdr= (struct GNUNET_MessageHeader *) buf;
2192 hdr->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
2193 hdr->size = htons (len);
2194 tun = (struct GNUNET_TUN_Layer2PacketHeader*) &hdr[1];
2195 tun->flags = htons (0);
2196 switch (source_address->af)
2200 struct GNUNET_TUN_IPv4Header * ipv4 = (struct GNUNET_TUN_IPv4Header*) &tun[1];
2202 tun->proto = htons (ETH_P_IPV4);
2203 GNUNET_TUN_initialize_ipv4_header (ipv4,
2205 sizeof (struct GNUNET_TUN_IcmpHeader) + payload_length,
2206 &source_address->address.ipv4,
2207 &destination_address->address.ipv4);
2208 icmp = (struct GNUNET_TUN_IcmpHeader*) &ipv4[1];
2213 struct GNUNET_TUN_IPv6Header * ipv6 = (struct GNUNET_TUN_IPv6Header*) &tun[1];
2215 tun->proto = htons (ETH_P_IPV6);
2216 GNUNET_TUN_initialize_ipv6_header (ipv6,
2218 sizeof (struct GNUNET_TUN_IcmpHeader) + payload_length,
2219 &source_address->address.ipv6,
2220 &destination_address->address.ipv6);
2221 icmp = (struct GNUNET_TUN_IcmpHeader*) &ipv6[1];
2228 *icmp = *icmp_header;
2232 GNUNET_TUN_calculate_icmp_checksum (icmp,
2235 if (NULL != helper_handle)
2236 (void) GNUNET_HELPER_send (helper_handle,
2237 (const struct GNUNET_MessageHeader*) buf,
2245 * Synthesize a plausible ICMP payload for an ICMPv4 error
2246 * response on the given channel.
2248 * @param state channel information
2249 * @param ipp IPv6 header to fill in (ICMP payload)
2250 * @param udp "UDP" header to fill in (ICMP payload); might actually
2251 * also be the first 8 bytes of the TCP header
2254 make_up_icmpv4_payload (struct ChannelState *state,
2255 struct GNUNET_TUN_IPv4Header *ipp,
2256 struct GNUNET_TUN_UdpHeader *udp)
2258 GNUNET_TUN_initialize_ipv4_header (ipp,
2259 state->specifics.tcp_udp.ri.remote_address.proto,
2260 sizeof (struct GNUNET_TUN_TcpHeader),
2261 &state->specifics.tcp_udp.ri.remote_address.address.ipv4,
2262 &state->specifics.tcp_udp.ri.local_address.address.ipv4);
2263 udp->source_port = htons (state->specifics.tcp_udp.ri.remote_address.port);
2264 udp->destination_port = htons (state->specifics.tcp_udp.ri.local_address.port);
2265 udp->len = htons (0);
2266 udp->crc = htons (0);
2271 * Synthesize a plausible ICMP payload for an ICMPv6 error
2272 * response on the given channel.
2274 * @param state channel information
2275 * @param ipp IPv6 header to fill in (ICMP payload)
2276 * @param udp "UDP" header to fill in (ICMP payload); might actually
2277 * also be the first 8 bytes of the TCP header
2280 make_up_icmpv6_payload (struct ChannelState *state,
2281 struct GNUNET_TUN_IPv6Header *ipp,
2282 struct GNUNET_TUN_UdpHeader *udp)
2284 GNUNET_TUN_initialize_ipv6_header (ipp,
2285 state->specifics.tcp_udp.ri.remote_address.proto,
2286 sizeof (struct GNUNET_TUN_TcpHeader),
2287 &state->specifics.tcp_udp.ri.remote_address.address.ipv6,
2288 &state->specifics.tcp_udp.ri.local_address.address.ipv6);
2289 udp->source_port = htons (state->specifics.tcp_udp.ri.remote_address.port);
2290 udp->destination_port = htons (state->specifics.tcp_udp.ri.local_address.port);
2291 udp->len = htons (0);
2292 udp->crc = htons (0);
2297 * Process a request to forward ICMP data to the Internet via this peer.
2299 * @param cls closure, NULL
2300 * @param channel connection to the other end
2301 * @param channel_ctx pointer to our 'struct ChannelState *'
2302 * @param message the actual message
2303 * @return #GNUNET_OK to keep the connection open,
2304 * #GNUNET_SYSERR to close it (signal serious error)
2307 receive_icmp_remote (void *cls,
2308 struct GNUNET_CADET_Channel *channel,
2310 const struct GNUNET_MessageHeader *message)
2312 struct ChannelState *state = *channel_ctx;
2313 const struct GNUNET_EXIT_IcmpInternetMessage *msg;
2314 uint16_t pkt_len = ntohs (message->size);
2315 const struct in_addr *v4;
2316 const struct in6_addr *v6;
2317 const void *payload;
2318 char buf[sizeof (struct GNUNET_TUN_IPv6Header) + 8] GNUNET_ALIGN;
2321 if (GNUNET_YES == state->is_dns)
2323 GNUNET_break_op (0);
2324 return GNUNET_SYSERR;
2326 if (GNUNET_SYSERR == state->is_dns)
2328 /* channel is UDP/TCP from now on */
2329 state->is_dns = GNUNET_NO;
2331 GNUNET_STATISTICS_update (stats,
2332 gettext_noop ("# Bytes received from CADET"),
2333 pkt_len, GNUNET_NO);
2334 GNUNET_STATISTICS_update (stats,
2335 gettext_noop ("# ICMP IP-exit requests received via cadet"),
2337 if (pkt_len < sizeof (struct GNUNET_EXIT_IcmpInternetMessage))
2339 GNUNET_break_op (0);
2340 return GNUNET_SYSERR;
2342 msg = (const struct GNUNET_EXIT_IcmpInternetMessage*) message;
2343 pkt_len -= sizeof (struct GNUNET_EXIT_IcmpInternetMessage);
2345 af = (int) ntohl (msg->af);
2346 if ( (NULL != state->specifics.tcp_udp.heap_node) &&
2347 (af != state->specifics.tcp_udp.ri.remote_address.af) )
2349 /* other peer switched AF on this channel; not allowed */
2350 GNUNET_break_op (0);
2351 return GNUNET_SYSERR;
2357 if (pkt_len < sizeof (struct in_addr))
2359 GNUNET_break_op (0);
2360 return GNUNET_SYSERR;
2364 GNUNET_break_op (0);
2365 return GNUNET_SYSERR;
2367 v4 = (const struct in_addr*) &msg[1];
2369 pkt_len -= sizeof (struct in_addr);
2370 state->specifics.tcp_udp.ri.remote_address.address.ipv4 = *v4;
2371 if (NULL == state->specifics.tcp_udp.heap_node)
2373 state->specifics.tcp_udp.ri.remote_address.af = af;
2374 state->specifics.tcp_udp.ri.remote_address.proto = IPPROTO_ICMP;
2375 setup_state_record (state);
2377 /* check that ICMP type is something we want to support
2378 and possibly make up payload! */
2379 switch (msg->icmp_header.type)
2381 case GNUNET_TUN_ICMPTYPE_ECHO_REPLY:
2382 case GNUNET_TUN_ICMPTYPE_ECHO_REQUEST:
2384 case GNUNET_TUN_ICMPTYPE_DESTINATION_UNREACHABLE:
2385 case GNUNET_TUN_ICMPTYPE_SOURCE_QUENCH:
2386 case GNUNET_TUN_ICMPTYPE_TIME_EXCEEDED:
2389 GNUNET_break_op (0);
2390 return GNUNET_SYSERR;
2392 /* make up payload */
2394 struct GNUNET_TUN_IPv4Header *ipp = (struct GNUNET_TUN_IPv4Header *) buf;
2395 struct GNUNET_TUN_UdpHeader *udp = (struct GNUNET_TUN_UdpHeader *) &ipp[1];
2397 GNUNET_assert (8 == sizeof (struct GNUNET_TUN_UdpHeader));
2398 pkt_len = sizeof (struct GNUNET_TUN_IPv4Header) + 8;
2399 make_up_icmpv4_payload (state,
2406 GNUNET_break_op (0);
2407 GNUNET_STATISTICS_update (stats,
2408 gettext_noop ("# ICMPv4 packets dropped (type not allowed)"),
2410 return GNUNET_SYSERR;
2415 if (pkt_len < sizeof (struct in6_addr))
2417 GNUNET_break_op (0);
2418 return GNUNET_SYSERR;
2422 GNUNET_break_op (0);
2423 return GNUNET_SYSERR;
2425 v6 = (const struct in6_addr*) &msg[1];
2427 pkt_len -= sizeof (struct in6_addr);
2428 state->specifics.tcp_udp.ri.remote_address.address.ipv6 = *v6;
2429 if (NULL == state->specifics.tcp_udp.heap_node)
2431 state->specifics.tcp_udp.ri.remote_address.af = af;
2432 state->specifics.tcp_udp.ri.remote_address.proto = IPPROTO_ICMPV6;
2433 setup_state_record (state);
2435 /* check that ICMP type is something we want to support
2436 and possibly make up payload! */
2437 switch (msg->icmp_header.type)
2439 case GNUNET_TUN_ICMPTYPE6_ECHO_REPLY:
2440 case GNUNET_TUN_ICMPTYPE6_ECHO_REQUEST:
2442 case GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE:
2443 case GNUNET_TUN_ICMPTYPE6_PACKET_TOO_BIG:
2444 case GNUNET_TUN_ICMPTYPE6_TIME_EXCEEDED:
2445 case GNUNET_TUN_ICMPTYPE6_PARAMETER_PROBLEM:
2448 GNUNET_break_op (0);
2449 return GNUNET_SYSERR;
2451 /* make up payload */
2453 struct GNUNET_TUN_IPv6Header *ipp = (struct GNUNET_TUN_IPv6Header *) buf;
2454 struct GNUNET_TUN_UdpHeader *udp = (struct GNUNET_TUN_UdpHeader *) &ipp[1];
2456 GNUNET_assert (8 == sizeof (struct GNUNET_TUN_UdpHeader));
2457 pkt_len = sizeof (struct GNUNET_TUN_IPv6Header) + 8;
2458 make_up_icmpv6_payload (state,
2465 GNUNET_break_op (0);
2466 GNUNET_STATISTICS_update (stats,
2467 gettext_noop ("# ICMPv6 packets dropped (type not allowed)"),
2469 return GNUNET_SYSERR;
2475 GNUNET_break_op (0);
2476 return GNUNET_SYSERR;
2480 char buf[INET6_ADDRSTRLEN];
2481 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2482 "Received ICMP data from %s for forwarding to %s\n",
2483 GNUNET_i2s (&state->peer),
2485 &state->specifics.tcp_udp.ri.remote_address.address,
2486 buf, sizeof (buf)));
2488 send_icmp_packet_via_tun (&state->specifics.tcp_udp.ri.remote_address,
2489 &state->specifics.tcp_udp.ri.local_address,
2492 GNUNET_CADET_receive_done (channel);
2498 * Setup ICMP payload for ICMP error messages. Called
2499 * for both IPv4 and IPv6 addresses.
2501 * @param state context for creating the IP Packet
2502 * @param buf where to create the payload, has at least
2503 * sizeof (struct GNUNET_TUN_IPv6Header) + 8 bytes
2504 * @return number of bytes of payload we created in buf
2507 make_up_icmp_service_payload (struct ChannelState *state,
2510 switch (state->specifics.tcp_udp.serv->address.af)
2514 struct GNUNET_TUN_IPv4Header *ipv4;
2515 struct GNUNET_TUN_UdpHeader *udp;
2517 ipv4 = (struct GNUNET_TUN_IPv4Header *)buf;
2518 udp = (struct GNUNET_TUN_UdpHeader *) &ipv4[1];
2519 make_up_icmpv4_payload (state,
2522 GNUNET_assert (8 == sizeof (struct GNUNET_TUN_UdpHeader));
2523 return sizeof (struct GNUNET_TUN_IPv4Header) + 8;
2528 struct GNUNET_TUN_IPv6Header *ipv6;
2529 struct GNUNET_TUN_UdpHeader *udp;
2531 ipv6 = (struct GNUNET_TUN_IPv6Header *)buf;
2532 udp = (struct GNUNET_TUN_UdpHeader *) &ipv6[1];
2533 make_up_icmpv6_payload (state,
2536 GNUNET_assert (8 == sizeof (struct GNUNET_TUN_UdpHeader));
2537 return sizeof (struct GNUNET_TUN_IPv6Header) + 8;
2548 * Process a request via cadet to send ICMP data to a service
2549 * offered by this system.
2551 * @param cls closure, NULL
2552 * @param channel connection to the other end
2553 * @param channel_ctx pointer to our 'struct ChannelState *'
2554 * @param message the actual message
2555 * @return #GNUNET_OK to keep the connection open,
2556 * #GNUNET_SYSERR to close it (signal serious error)
2559 receive_icmp_service (void *cls,
2560 struct GNUNET_CADET_Channel *channel,
2562 const struct GNUNET_MessageHeader *message)
2564 struct ChannelState *state = *channel_ctx;
2565 const struct GNUNET_EXIT_IcmpServiceMessage *msg;
2566 uint16_t pkt_len = ntohs (message->size);
2567 struct GNUNET_TUN_IcmpHeader icmp;
2568 char buf[sizeof (struct GNUNET_TUN_IPv6Header) + 8] GNUNET_ALIGN;
2569 const void *payload;
2571 if (GNUNET_YES == state->is_dns)
2573 GNUNET_break_op (0);
2574 return GNUNET_SYSERR;
2576 if (GNUNET_SYSERR == state->is_dns)
2578 /* channel is UDP/TCP from now on */
2579 state->is_dns = GNUNET_NO;
2581 GNUNET_STATISTICS_update (stats,
2582 gettext_noop ("# Bytes received from CADET"),
2583 pkt_len, GNUNET_NO);
2584 GNUNET_STATISTICS_update (stats,
2585 gettext_noop ("# ICMP service requests received via cadet"),
2587 /* check that we got at least a valid header */
2588 if (pkt_len < sizeof (struct GNUNET_EXIT_IcmpServiceMessage))
2590 GNUNET_break_op (0);
2591 return GNUNET_SYSERR;
2593 msg = (const struct GNUNET_EXIT_IcmpServiceMessage*) message;
2594 pkt_len -= sizeof (struct GNUNET_EXIT_IcmpServiceMessage);
2595 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2596 "Received data from %s for forwarding to ICMP service %s\n",
2597 GNUNET_i2s (&state->peer),
2598 GNUNET_h2s (&msg->service_descriptor));
2599 if (NULL == state->specifics.tcp_udp.serv)
2601 /* first packet to service must not be ICMP (cannot determine service!) */
2602 GNUNET_break_op (0);
2603 return GNUNET_SYSERR;
2605 icmp = msg->icmp_header;
2607 state->specifics.tcp_udp.ri.remote_address = state->specifics.tcp_udp.serv->address;
2608 setup_state_record (state);
2610 /* check that ICMP type is something we want to support,
2611 perform ICMP PT if needed ans possibly make up payload */
2615 switch (msg->icmp_header.type)
2617 case GNUNET_TUN_ICMPTYPE_ECHO_REPLY:
2618 if (state->specifics.tcp_udp.serv->address.af == AF_INET6)
2619 icmp.type = GNUNET_TUN_ICMPTYPE6_ECHO_REPLY;
2621 case GNUNET_TUN_ICMPTYPE_ECHO_REQUEST:
2622 if (state->specifics.tcp_udp.serv->address.af == AF_INET6)
2623 icmp.type = GNUNET_TUN_ICMPTYPE6_ECHO_REQUEST;
2625 case GNUNET_TUN_ICMPTYPE_DESTINATION_UNREACHABLE:
2626 if (state->specifics.tcp_udp.serv->address.af == AF_INET6)
2627 icmp.type = GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE;
2630 GNUNET_break_op (0);
2631 return GNUNET_SYSERR;
2634 pkt_len = make_up_icmp_service_payload (state, buf);
2636 case GNUNET_TUN_ICMPTYPE_TIME_EXCEEDED:
2637 if (state->specifics.tcp_udp.serv->address.af == AF_INET6)
2638 icmp.type = GNUNET_TUN_ICMPTYPE6_TIME_EXCEEDED;
2641 GNUNET_break_op (0);
2642 return GNUNET_SYSERR;
2645 pkt_len = make_up_icmp_service_payload (state, buf);
2647 case GNUNET_TUN_ICMPTYPE_SOURCE_QUENCH:
2648 if (state->specifics.tcp_udp.serv->address.af == AF_INET6)
2650 GNUNET_STATISTICS_update (stats,
2651 gettext_noop ("# ICMPv4 packets dropped (impossible PT to v6)"),
2657 GNUNET_break_op (0);
2658 return GNUNET_SYSERR;
2661 pkt_len = make_up_icmp_service_payload (state, buf);
2664 GNUNET_break_op (0);
2665 GNUNET_STATISTICS_update (stats,
2666 gettext_noop ("# ICMPv4 packets dropped (type not allowed)"),
2668 return GNUNET_SYSERR;
2670 /* end of AF_INET */
2673 switch (msg->icmp_header.type)
2675 case GNUNET_TUN_ICMPTYPE6_ECHO_REPLY:
2676 if (state->specifics.tcp_udp.serv->address.af == AF_INET)
2677 icmp.type = GNUNET_TUN_ICMPTYPE_ECHO_REPLY;
2679 case GNUNET_TUN_ICMPTYPE6_ECHO_REQUEST:
2680 if (state->specifics.tcp_udp.serv->address.af == AF_INET)
2681 icmp.type = GNUNET_TUN_ICMPTYPE_ECHO_REQUEST;
2683 case GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE:
2684 if (state->specifics.tcp_udp.serv->address.af == AF_INET)
2685 icmp.type = GNUNET_TUN_ICMPTYPE_DESTINATION_UNREACHABLE;
2688 GNUNET_break_op (0);
2689 return GNUNET_SYSERR;
2692 pkt_len = make_up_icmp_service_payload (state, buf);
2694 case GNUNET_TUN_ICMPTYPE6_TIME_EXCEEDED:
2695 if (state->specifics.tcp_udp.serv->address.af == AF_INET)
2696 icmp.type = GNUNET_TUN_ICMPTYPE_TIME_EXCEEDED;
2699 GNUNET_break_op (0);
2700 return GNUNET_SYSERR;
2703 pkt_len = make_up_icmp_service_payload (state, buf);
2705 case GNUNET_TUN_ICMPTYPE6_PACKET_TOO_BIG:
2706 case GNUNET_TUN_ICMPTYPE6_PARAMETER_PROBLEM:
2707 if (state->specifics.tcp_udp.serv->address.af == AF_INET)
2709 GNUNET_STATISTICS_update (stats,
2710 gettext_noop ("# ICMPv6 packets dropped (impossible PT to v4)"),
2716 GNUNET_break_op (0);
2717 return GNUNET_SYSERR;
2720 pkt_len = make_up_icmp_service_payload (state, buf);
2723 GNUNET_break_op (0);
2724 GNUNET_STATISTICS_update (stats,
2725 gettext_noop ("# ICMPv6 packets dropped (type not allowed)"),
2727 return GNUNET_SYSERR;
2729 /* end of AF_INET6 */
2732 GNUNET_break_op (0);
2733 return GNUNET_SYSERR;
2736 send_icmp_packet_via_tun (&state->specifics.tcp_udp.ri.remote_address,
2737 &state->specifics.tcp_udp.ri.local_address,
2740 GNUNET_CADET_receive_done (channel);
2746 * Send a UDP packet via the TUN interface.
2748 * @param destination_address IP and port to use for the UDP packet's destination
2749 * @param source_address IP and port to use for the UDP packet's source
2750 * @param payload payload of the UDP packet (does NOT include UDP header)
2751 * @param payload_length number of bytes of data in @a payload
2754 send_udp_packet_via_tun (const struct SocketAddress *destination_address,
2755 const struct SocketAddress *source_address,
2756 const void *payload, size_t payload_length)
2760 GNUNET_STATISTICS_update (stats,
2761 gettext_noop ("# UDP packets sent via TUN"),
2763 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2764 "Sending packet with %u bytes UDP payload via TUN\n",
2765 (unsigned int) payload_length);
2766 len = sizeof (struct GNUNET_MessageHeader) + sizeof (struct GNUNET_TUN_Layer2PacketHeader);
2767 switch (source_address->af)
2770 len += sizeof (struct GNUNET_TUN_IPv4Header);
2773 len += sizeof (struct GNUNET_TUN_IPv6Header);
2779 len += sizeof (struct GNUNET_TUN_UdpHeader);
2780 len += payload_length;
2781 if (len >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
2787 char buf[len] GNUNET_ALIGN;
2788 struct GNUNET_MessageHeader *hdr;
2789 struct GNUNET_TUN_Layer2PacketHeader *tun;
2791 hdr= (struct GNUNET_MessageHeader *) buf;
2792 hdr->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
2793 hdr->size = htons (len);
2794 tun = (struct GNUNET_TUN_Layer2PacketHeader*) &hdr[1];
2795 tun->flags = htons (0);
2796 switch (source_address->af)
2800 struct GNUNET_TUN_IPv4Header * ipv4 = (struct GNUNET_TUN_IPv4Header*) &tun[1];
2802 tun->proto = htons (ETH_P_IPV4);
2803 prepare_ipv4_packet (payload, payload_length,
2807 destination_address,
2813 struct GNUNET_TUN_IPv6Header * ipv6 = (struct GNUNET_TUN_IPv6Header*) &tun[1];
2815 tun->proto = htons (ETH_P_IPV6);
2816 prepare_ipv6_packet (payload, payload_length,
2820 destination_address,
2828 if (NULL != helper_handle)
2829 (void) GNUNET_HELPER_send (helper_handle,
2830 (const struct GNUNET_MessageHeader*) buf,
2838 * Process a request to forward UDP data to the Internet via this peer.
2840 * @param cls closure, NULL
2841 * @param channel connection to the other end
2842 * @param channel_ctx pointer to our 'struct ChannelState *'
2843 * @param message the actual message
2844 * @return #GNUNET_OK to keep the connection open,
2845 * #GNUNET_SYSERR to close it (signal serious error)
2848 receive_udp_remote (void *cls,
2849 struct GNUNET_CADET_Channel *channel,
2851 const struct GNUNET_MessageHeader *message)
2853 struct ChannelState *state = *channel_ctx;
2854 const struct GNUNET_EXIT_UdpInternetMessage *msg;
2855 uint16_t pkt_len = ntohs (message->size);
2856 const struct in_addr *v4;
2857 const struct in6_addr *v6;
2858 const void *payload;
2861 if (GNUNET_YES == state->is_dns)
2863 GNUNET_break_op (0);
2864 return GNUNET_SYSERR;
2866 if (GNUNET_SYSERR == state->is_dns)
2868 /* channel is UDP/TCP from now on */
2869 state->is_dns = GNUNET_NO;
2871 GNUNET_STATISTICS_update (stats,
2872 gettext_noop ("# Bytes received from CADET"),
2873 pkt_len, GNUNET_NO);
2874 GNUNET_STATISTICS_update (stats,
2875 gettext_noop ("# UDP IP-exit requests received via cadet"),
2877 if (pkt_len < sizeof (struct GNUNET_EXIT_UdpInternetMessage))
2879 GNUNET_break_op (0);
2880 return GNUNET_SYSERR;
2882 msg = (const struct GNUNET_EXIT_UdpInternetMessage*) message;
2883 pkt_len -= sizeof (struct GNUNET_EXIT_UdpInternetMessage);
2884 af = (int) ntohl (msg->af);
2885 state->specifics.tcp_udp.ri.remote_address.af = af;
2889 if (pkt_len < sizeof (struct in_addr))
2891 GNUNET_break_op (0);
2892 return GNUNET_SYSERR;
2896 GNUNET_break_op (0);
2897 return GNUNET_SYSERR;
2899 v4 = (const struct in_addr*) &msg[1];
2901 pkt_len -= sizeof (struct in_addr);
2902 state->specifics.tcp_udp.ri.remote_address.address.ipv4 = *v4;
2905 if (pkt_len < sizeof (struct in6_addr))
2907 GNUNET_break_op (0);
2908 return GNUNET_SYSERR;
2912 GNUNET_break_op (0);
2913 return GNUNET_SYSERR;
2915 v6 = (const struct in6_addr*) &msg[1];
2917 pkt_len -= sizeof (struct in6_addr);
2918 state->specifics.tcp_udp.ri.remote_address.address.ipv6 = *v6;
2921 GNUNET_break_op (0);
2922 return GNUNET_SYSERR;
2925 char buf[INET6_ADDRSTRLEN];
2926 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2927 "Received data from %s for forwarding to UDP %s:%u\n",
2928 GNUNET_i2s (&state->peer),
2930 &state->specifics.tcp_udp.ri.remote_address.address,
2932 (unsigned int) ntohs (msg->destination_port));
2934 state->specifics.tcp_udp.ri.remote_address.proto = IPPROTO_UDP;
2935 state->specifics.tcp_udp.ri.remote_address.port = msg->destination_port;
2936 if (NULL == state->specifics.tcp_udp.heap_node)
2937 setup_state_record (state);
2938 if (0 != ntohs (msg->source_port))
2939 state->specifics.tcp_udp.ri.local_address.port = msg->source_port;
2940 send_udp_packet_via_tun (&state->specifics.tcp_udp.ri.remote_address,
2941 &state->specifics.tcp_udp.ri.local_address,
2943 GNUNET_CADET_receive_done (channel);
2949 * Process a request via cadet to send a request to a UDP service
2950 * offered by this system.
2952 * @param cls closure, NULL
2953 * @param channel connection to the other end
2954 * @param channel_ctx pointer to our 'struct ChannelState *'
2955 * @param message the actual message
2956 * @return #GNUNET_OK to keep the connection open,
2957 * #GNUNET_SYSERR to close it (signal serious error)
2960 receive_udp_service (void *cls,
2961 struct GNUNET_CADET_Channel *channel,
2963 const struct GNUNET_MessageHeader *message)
2965 struct ChannelState *state = *channel_ctx;
2966 const struct GNUNET_EXIT_UdpServiceMessage *msg;
2967 uint16_t pkt_len = ntohs (message->size);
2969 if (GNUNET_YES == state->is_dns)
2971 GNUNET_break_op (0);
2972 return GNUNET_SYSERR;
2974 if (GNUNET_SYSERR == state->is_dns)
2976 /* channel is UDP/TCP from now on */
2977 state->is_dns = GNUNET_NO;
2979 GNUNET_STATISTICS_update (stats,
2980 gettext_noop ("# Bytes received from CADET"),
2981 pkt_len, GNUNET_NO);
2982 GNUNET_STATISTICS_update (stats,
2983 gettext_noop ("# UDP service requests received via cadet"),
2985 /* check that we got at least a valid header */
2986 if (pkt_len < sizeof (struct GNUNET_EXIT_UdpServiceMessage))
2988 GNUNET_break_op (0);
2989 return GNUNET_SYSERR;
2991 msg = (const struct GNUNET_EXIT_UdpServiceMessage*) message;
2992 pkt_len -= sizeof (struct GNUNET_EXIT_UdpServiceMessage);
2993 LOG (GNUNET_ERROR_TYPE_DEBUG,
2994 "Received data from %s for forwarding to UDP service %s on port %u\n",
2995 GNUNET_i2s (&state->peer),
2996 GNUNET_h2s (&msg->service_descriptor),
2997 (unsigned int) ntohs (msg->destination_port));
2998 if (NULL == (state->specifics.tcp_udp.serv =
2999 find_service (udp_services,
3000 &msg->service_descriptor,
3001 ntohs (msg->destination_port))))
3003 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
3004 _("No service %s found for %s on port %d!\n"),
3005 GNUNET_h2s (&msg->service_descriptor),
3007 ntohs (msg->destination_port));
3008 GNUNET_STATISTICS_update (stats,
3009 gettext_noop ("# UDP requests dropped (no such service)"),
3011 return GNUNET_SYSERR;
3013 state->specifics.tcp_udp.ri.remote_address = state->specifics.tcp_udp.serv->address;
3014 setup_state_record (state);
3015 if (0 != ntohs (msg->source_port))
3016 state->specifics.tcp_udp.ri.local_address.port = msg->source_port;
3017 send_udp_packet_via_tun (&state->specifics.tcp_udp.ri.remote_address,
3018 &state->specifics.tcp_udp.ri.local_address,
3020 GNUNET_CADET_receive_done (channel);
3026 * Callback from CADET for new channels.
3028 * @param cls closure
3029 * @param channel new handle to the channel
3030 * @param initiator peer that started the channel
3031 * @param port destination port
3032 * @param options channel options flags
3033 * @return initial channel context for the channel
3036 new_channel (void *cls,
3037 struct GNUNET_CADET_Channel *channel,
3038 const struct GNUNET_PeerIdentity *initiator,
3040 enum GNUNET_CADET_ChannelOption options)
3042 struct ChannelState *s = GNUNET_new (struct ChannelState);
3044 s->is_dns = GNUNET_SYSERR;
3045 s->peer = *initiator;
3046 GNUNET_STATISTICS_update (stats,
3047 gettext_noop ("# Inbound CADET channels created"),
3049 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3050 "Received inbound channel from `%s'\n",
3051 GNUNET_i2s (initiator));
3052 s->channel = channel;
3058 * Function called by cadet whenever an inbound channel is destroyed.
3059 * Should clean up any associated state.
3061 * @param cls closure (set from #GNUNET_CADET_connect)
3062 * @param channel connection to the other end (henceforth invalid)
3063 * @param channel_ctx place where local state associated
3064 * with the channel is stored
3067 clean_channel (void *cls,
3068 const struct GNUNET_CADET_Channel *channel,
3071 struct ChannelState *s = channel_ctx;
3072 struct ChannelMessageQueue *tnq;
3074 LOG (GNUNET_ERROR_TYPE_DEBUG,
3075 "Channel destroyed\n");
3076 if (GNUNET_SYSERR == s->is_dns)
3081 if (GNUNET_YES == s->is_dns)
3083 if (channels[s->specifics.dns.my_id] == s)
3084 channels[s->specifics.dns.my_id] = NULL;
3085 GNUNET_free_non_null (s->specifics.dns.reply);
3089 while (NULL != (tnq = s->specifics.tcp_udp.head))
3091 GNUNET_CONTAINER_DLL_remove (s->specifics.tcp_udp.head,
3092 s->specifics.tcp_udp.tail,
3096 if (NULL != s->specifics.tcp_udp.heap_node)
3098 GNUNET_assert (GNUNET_YES ==
3099 GNUNET_CONTAINER_multihashmap_remove (connections_map,
3100 &s->specifics.tcp_udp.state_key,
3102 GNUNET_CONTAINER_heap_remove_node (s->specifics.tcp_udp.heap_node);
3103 s->specifics.tcp_udp.heap_node = NULL;
3108 GNUNET_CADET_notify_transmit_ready_cancel (s->th);
3116 * Function that frees everything from a hashmap
3120 * @param value value to free
3123 free_iterate (void *cls,
3124 const struct GNUNET_HashCode * hash,
3127 GNUNET_free (value);
3133 * Function scheduled as very last function if the service
3134 * disabled itself because the helper is not installed
3135 * properly. Does nothing, except for keeping the
3136 * service process alive by virtue of being scheduled.
3139 * @param tc scheduler context
3142 dummy_task (void *cls,
3143 const struct GNUNET_SCHEDULER_TaskContext *tc)
3145 /* just terminate */
3150 * Function scheduled as very last function, cleans up after us
3153 * @param tc scheduler context
3157 const struct GNUNET_SCHEDULER_TaskContext *tc)
3161 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3162 "Exit service is shutting down now\n");
3164 if (NULL != helper_handle)
3166 GNUNET_HELPER_stop (helper_handle, GNUNET_NO);
3167 helper_handle = NULL;
3171 GNUNET_REGEX_announce_cancel (regex4);
3176 GNUNET_REGEX_announce_cancel (regex6);
3179 if (NULL != cadet_handle)
3181 GNUNET_CADET_disconnect (cadet_handle);
3182 cadet_handle = NULL;
3184 if (NULL != connections_map)
3186 GNUNET_CONTAINER_multihashmap_iterate (connections_map, &free_iterate, NULL);
3187 GNUNET_CONTAINER_multihashmap_destroy (connections_map);
3188 connections_map = NULL;
3190 if (NULL != connections_heap)
3192 GNUNET_CONTAINER_heap_destroy (connections_heap);
3193 connections_heap = NULL;
3195 if (NULL != tcp_services)
3197 GNUNET_CONTAINER_multihashmap_iterate (tcp_services, &free_service_record, NULL);
3198 GNUNET_CONTAINER_multihashmap_destroy (tcp_services);
3199 tcp_services = NULL;
3201 if (NULL != udp_services)
3203 GNUNET_CONTAINER_multihashmap_iterate (udp_services, &free_service_record, NULL);
3204 GNUNET_CONTAINER_multihashmap_destroy (udp_services);
3205 udp_services = NULL;
3207 if (NULL != dnsstub)
3209 GNUNET_DNSSTUB_stop (dnsstub);
3212 if (NULL != peer_key)
3214 GNUNET_free (peer_key);
3217 if (NULL != dht_task)
3219 GNUNET_SCHEDULER_cancel (dht_task);
3222 if (NULL != dht_put)
3224 GNUNET_DHT_put_cancel (dht_put);
3229 GNUNET_DHT_disconnect (dht);
3234 GNUNET_STATISTICS_destroy (stats, GNUNET_NO);
3238 GNUNET_free_non_null (exit_argv[i]);
3243 * Add services to the service map.
3245 * @param proto IPPROTO_TCP or IPPROTO_UDP
3246 * @param cpy copy of the service descriptor (can be mutilated)
3247 * @param name DNS name of the service
3250 add_services (int proto,
3257 struct LocalService *serv;
3261 slen = strlen (name);
3262 GNUNET_assert (slen >= 8);
3263 n = GNUNET_strndup (name, slen - 8 /* remove .gnunet. */);
3265 for (redirect = strtok (cpy, " "); redirect != NULL;
3266 redirect = strtok (NULL, " "))
3268 if (NULL == (hostname = strstr (redirect, ":")))
3270 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
3271 _("Option `%s' for domain `%s' is not formatted correctly!\n"),
3278 if (NULL == (hostport = strstr (hostname, ":")))
3280 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
3281 _("Option `%s' for domain `%s' is not formatted correctly!\n"),
3289 int local_port = atoi (redirect);
3290 int remote_port = atoi (hostport);
3292 if (!((local_port > 0) && (local_port < 65536)))
3294 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
3295 _("`%s' is not a valid port number (for domain `%s')!"),
3300 if (!((remote_port > 0) && (remote_port < 65536)))
3302 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
3303 _("`%s' is not a valid port number (for domain `%s')!"),
3309 serv = GNUNET_new (struct LocalService);
3310 serv->address.proto = proto;
3311 serv->my_port = (uint16_t) local_port;
3312 serv->address.port = remote_port;
3313 if (0 == strcmp ("localhost4", hostname))
3315 const char *ip4addr = exit_argv[5];
3317 serv->address.af = AF_INET;
3318 GNUNET_assert (1 == inet_pton (AF_INET, ip4addr, &serv->address.address.ipv4));
3320 else if (0 == strcmp ("localhost6", hostname))
3322 const char *ip6addr = exit_argv[3];
3324 serv->address.af = AF_INET6;
3325 GNUNET_assert (1 == inet_pton (AF_INET6, ip6addr, &serv->address.address.ipv6));
3329 struct addrinfo *res;
3332 ret = getaddrinfo (hostname, NULL, NULL, &res);
3333 if ( (ret != 0) || (res == NULL) )
3335 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
3336 _("No addresses found for hostname `%s' of service `%s'!\n"),
3343 serv->address.af = res->ai_family;
3344 switch (res->ai_family)
3349 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
3350 _("Service `%s' configured for IPv4, but IPv4 is disabled!\n"),
3356 serv->address.address.ipv4 = ((struct sockaddr_in *) res->ai_addr)->sin_addr;
3361 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
3362 _("Service `%s' configured for IPv4, but IPv4 is disabled!\n"),
3368 serv->address.address.ipv6 = ((struct sockaddr_in6 *) res->ai_addr)->sin6_addr;
3372 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
3373 _("No IP addresses found for hostname `%s' of service `%s'!\n"),
3381 store_service ((IPPROTO_UDP == proto) ? udp_services : tcp_services,
3391 * Reads the configuration servicecfg and populates udp_services
3394 * @param section name of section in config, equal to hostname
3397 read_service_conf (void *cls,
3398 const char *section)
3402 if ((strlen (section) < 8) ||
3403 (0 != strcmp (".gnunet.", section + (strlen (section) - 8))))
3406 GNUNET_CONFIGURATION_get_value_string (cfg,
3411 add_services (IPPROTO_UDP, cpy, section);
3415 GNUNET_CONFIGURATION_get_value_string (cfg,
3420 add_services (IPPROTO_TCP, cpy, section);
3427 * We are running a DNS exit service, advertise it in the
3428 * DHT. This task is run periodically to do the DHT PUT.
3430 * @param cls closure
3431 * @param tc scheduler context
3434 do_dht_put (void *cls,
3435 const struct GNUNET_SCHEDULER_TaskContext *tc);
3439 * Function called when the DHT PUT operation is complete.
3440 * Schedules the next PUT.
3442 * @param cls closure, NULL
3443 * @param success #GNUNET_OK if the operation worked (unused)
3446 dht_put_cont (void *cls,
3450 dht_task = GNUNET_SCHEDULER_add_delayed (DHT_PUT_FREQUENCY,
3457 * We are running a DNS exit service, advertise it in the
3458 * DHT. This task is run periodically to do the DHT PUT.
3460 * @param cls closure
3461 * @param tc scheduler context
3464 do_dht_put (void *cls,
3465 const struct GNUNET_SCHEDULER_TaskContext *tc)
3467 struct GNUNET_TIME_Absolute expiration;
3470 expiration = GNUNET_TIME_absolute_ntoh (dns_advertisement.expiration_time);
3471 if (GNUNET_TIME_absolute_get_remaining (expiration).rel_value_us <
3472 GNUNET_TIME_UNIT_HOURS.rel_value_us)
3474 /* refresh advertisement */
3475 expiration = GNUNET_TIME_relative_to_absolute (DNS_ADVERTISEMENT_TIMEOUT);
3476 dns_advertisement.expiration_time = GNUNET_TIME_absolute_hton (expiration);
3477 GNUNET_assert (GNUNET_OK ==
3478 GNUNET_CRYPTO_eddsa_sign (peer_key,
3479 &dns_advertisement.purpose,
3480 &dns_advertisement.signature));
3482 dht_put = GNUNET_DHT_put (dht,
3484 1 /* replication */,
3486 GNUNET_BLOCK_TYPE_DNS,
3487 sizeof (struct GNUNET_DNS_Advertisement),
3490 GNUNET_TIME_UNIT_FOREVER_REL,
3491 &dht_put_cont, NULL);
3496 * @brief Main function that will be run by the scheduler.
3498 * @param cls closure
3499 * @param args remaining command-line arguments
3500 * @param cfgfile name of the configuration file used (for saving, can be NULL!)
3501 * @param cfg_ configuration
3506 const char *cfgfile,
3507 const struct GNUNET_CONFIGURATION_Handle *cfg_)
3509 static struct GNUNET_CADET_MessageHandler handlers[] = {
3510 {&receive_icmp_service, GNUNET_MESSAGE_TYPE_VPN_ICMP_TO_SERVICE, 0},
3511 {&receive_icmp_remote, GNUNET_MESSAGE_TYPE_VPN_ICMP_TO_INTERNET, 0},
3512 {&receive_udp_service, GNUNET_MESSAGE_TYPE_VPN_UDP_TO_SERVICE, 0},
3513 {&receive_udp_remote, GNUNET_MESSAGE_TYPE_VPN_UDP_TO_INTERNET, 0},
3514 {&receive_tcp_service, GNUNET_MESSAGE_TYPE_VPN_TCP_TO_SERVICE_START, 0},
3515 {&receive_tcp_remote, GNUNET_MESSAGE_TYPE_VPN_TCP_TO_INTERNET_START, 0},
3516 {&receive_tcp_data, GNUNET_MESSAGE_TYPE_VPN_TCP_DATA_TO_EXIT, 0},
3517 {&receive_dns_request, GNUNET_MESSAGE_TYPE_VPN_DNS_TO_INTERNET, 0},
3521 static uint32_t apptypes[] = {
3522 GNUNET_APPLICATION_TYPE_END,
3523 GNUNET_APPLICATION_TYPE_END,
3524 GNUNET_APPLICATION_TYPE_END,
3525 GNUNET_APPLICATION_TYPE_END
3527 unsigned int app_idx;
3537 char *prefixed_regex;
3538 struct in_addr dns_exit4;
3539 struct in6_addr dns_exit6;
3543 ipv4_exit = GNUNET_CONFIGURATION_get_value_yesno (cfg, "exit", "EXIT_IPV4");
3544 ipv6_exit = GNUNET_CONFIGURATION_get_value_yesno (cfg, "exit", "EXIT_IPV6");
3545 ipv4_enabled = GNUNET_CONFIGURATION_get_value_yesno (cfg, "exit", "ENABLE_IPV4");
3546 ipv6_enabled = GNUNET_CONFIGURATION_get_value_yesno (cfg, "exit", "ENABLE_IPV6");
3547 if ( (ipv4_exit) || (ipv6_exit) )
3549 binary = GNUNET_OS_get_libexec_binary_path ("gnunet-helper-exit");
3551 GNUNET_OS_check_helper_binary (binary, GNUNET_YES, "-d gnunet-vpn - - - 169.1.3.3.7 255.255.255.0")) //no nat, ipv4 only
3553 GNUNET_free (binary);
3554 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
3555 _("`%s' must be installed SUID, EXIT will not work\n"),
3556 "gnunet-helper-exit");
3557 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL,
3563 GNUNET_free (binary);
3565 stats = GNUNET_STATISTICS_create ("exit", cfg);
3567 if ( (ipv4_exit || ipv4_enabled) &&
3568 GNUNET_OK != GNUNET_NETWORK_test_pf (PF_INET))
3570 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
3571 _("This system does not support IPv4, will disable IPv4 functions despite them being enabled in the configuration\n"));
3572 ipv4_exit = GNUNET_NO;
3573 ipv4_enabled = GNUNET_NO;
3575 if ( (ipv6_exit || ipv6_enabled) &&
3576 GNUNET_OK != GNUNET_NETWORK_test_pf (PF_INET6))
3578 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
3579 _("This system does not support IPv6, will disable IPv6 functions despite them being enabled in the configuration\n"));
3580 ipv6_exit = GNUNET_NO;
3581 ipv6_enabled = GNUNET_NO;
3583 if (ipv4_exit && (! ipv4_enabled))
3585 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
3586 _("Cannot enable IPv4 exit but disable IPv4 on TUN interface, will use ENABLE_IPv4=YES\n"));
3587 ipv4_enabled = GNUNET_YES;
3589 if (ipv6_exit && (! ipv6_enabled))
3591 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
3592 _("Cannot enable IPv6 exit but disable IPv6 on TUN interface, will use ENABLE_IPv6=YES\n"));
3593 ipv6_enabled = GNUNET_YES;
3595 if (! (ipv4_enabled || ipv6_enabled))
3597 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
3598 _("No useful service enabled. Exiting.\n"));
3599 GNUNET_SCHEDULER_shutdown ();
3605 GNUNET_CONFIGURATION_get_value_yesno (cfg_, "exit", "EXIT_DNS")) &&
3607 GNUNET_CONFIGURATION_get_value_string (cfg, "exit",
3610 ( (1 != inet_pton (AF_INET, dns_exit, &dns_exit4)) &&
3611 (1 != inet_pton (AF_INET6, dns_exit, &dns_exit6)) ) ) )
3613 GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
3614 "dns", "DNS_RESOLVER",
3615 _("need a valid IPv4 or IPv6 address\n"));
3616 GNUNET_free_non_null (dns_exit);
3620 if (GNUNET_YES == ipv4_exit)
3622 apptypes[app_idx] = GNUNET_APPLICATION_TYPE_IPV4_GATEWAY;
3625 if (GNUNET_YES == ipv6_exit)
3627 apptypes[app_idx] = GNUNET_APPLICATION_TYPE_IPV6_GATEWAY;
3630 if (NULL != dns_exit)
3632 dht = GNUNET_DHT_connect (cfg, 1);
3633 peer_key = GNUNET_CRYPTO_eddsa_key_create_from_configuration (cfg);
3634 GNUNET_CRYPTO_eddsa_key_get_public (peer_key,
3635 &dns_advertisement.peer.public_key);
3636 dns_advertisement.purpose.size = htonl (sizeof (struct GNUNET_DNS_Advertisement) -
3637 sizeof (struct GNUNET_CRYPTO_EddsaSignature));
3638 dns_advertisement.purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_DNS_RECORD);
3639 GNUNET_CRYPTO_hash ("dns",
3642 dht_task = GNUNET_SCHEDULER_add_now (&do_dht_put,
3644 apptypes[app_idx] = GNUNET_APPLICATION_TYPE_INTERNET_RESOLVER;
3647 GNUNET_free_non_null (dns_exit);
3648 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL,
3653 GNUNET_CONFIGURATION_get_value_number (cfg, "exit", "MAX_CONNECTIONS",
3655 max_connections = 1024;
3656 exit_argv[0] = GNUNET_strdup ("exit-gnunet");
3657 if (GNUNET_SYSERR ==
3658 GNUNET_CONFIGURATION_get_value_string (cfg, "exit", "TUN_IFNAME", &tun_ifname))
3660 GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, "EXIT", "TUN_IFNAME");
3661 GNUNET_SCHEDULER_shutdown ();
3664 exit_argv[1] = tun_ifname;
3667 if (GNUNET_SYSERR ==
3668 GNUNET_CONFIGURATION_get_value_string (cfg, "exit", "EXIT_IFNAME", &exit_ifname))
3670 GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, "EXIT", "EXIT_IFNAME");
3671 GNUNET_SCHEDULER_shutdown ();
3674 exit_argv[2] = exit_ifname;
3678 exit_argv[2] = GNUNET_strdup ("-");
3682 if (GNUNET_YES == ipv6_enabled)
3684 if ( (GNUNET_SYSERR ==
3685 GNUNET_CONFIGURATION_get_value_string (cfg, "exit", "IPV6ADDR",
3687 (1 != inet_pton (AF_INET6, ipv6addr, &exit_ipv6addr))) )
3689 GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, "EXIT", "IPV6ADDR");
3690 GNUNET_SCHEDULER_shutdown ();
3693 exit_argv[3] = ipv6addr;
3694 if (GNUNET_SYSERR ==
3695 GNUNET_CONFIGURATION_get_value_string (cfg, "exit", "IPV6PREFIX",
3698 GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, "EXIT", "IPV6PREFIX");
3699 GNUNET_SCHEDULER_shutdown ();
3702 exit_argv[4] = ipv6prefix_s;
3704 GNUNET_CONFIGURATION_get_value_number (cfg, "exit",
3707 (ipv6prefix >= 127) )
3709 GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, "EXIT", "IPV6PREFIX",
3710 _("Must be a number"));
3711 GNUNET_SCHEDULER_shutdown ();
3717 /* IPv6 explicitly disabled */
3718 exit_argv[3] = GNUNET_strdup ("-");
3719 exit_argv[4] = GNUNET_strdup ("-");
3721 if (GNUNET_YES == ipv4_enabled)
3723 if ( (GNUNET_SYSERR ==
3724 GNUNET_CONFIGURATION_get_value_string (cfg, "exit", "IPV4ADDR",
3726 (1 != inet_pton (AF_INET, ipv4addr, &exit_ipv4addr))) )
3728 GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, "EXIT", "IPV4ADDR");
3729 GNUNET_SCHEDULER_shutdown ();
3732 exit_argv[5] = ipv4addr;
3734 if ( (GNUNET_SYSERR ==
3735 GNUNET_CONFIGURATION_get_value_string (cfg, "exit", "IPV4MASK",
3737 (1 != inet_pton (AF_INET, ipv4mask, &exit_ipv4mask))) )
3739 GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, "EXIT", "IPV4MASK");
3740 GNUNET_SCHEDULER_shutdown ();
3741 GNUNET_free_non_null (ipv4mask);
3744 exit_argv[6] = ipv4mask;
3748 /* IPv4 explicitly disabled */
3749 exit_argv[5] = GNUNET_strdup ("-");
3750 exit_argv[6] = GNUNET_strdup ("-");
3752 exit_argv[7] = NULL;
3754 udp_services = GNUNET_CONTAINER_multihashmap_create (65536, GNUNET_NO);
3755 tcp_services = GNUNET_CONTAINER_multihashmap_create (65536, GNUNET_NO);
3756 GNUNET_CONFIGURATION_iterate_sections (cfg, &read_service_conf, NULL);
3758 connections_map = GNUNET_CONTAINER_multihashmap_create (65536, GNUNET_NO);
3759 connections_heap = GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN);
3762 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
3763 _("No useful service enabled. Exiting.\n"));
3764 GNUNET_SCHEDULER_shutdown ();
3768 = GNUNET_CADET_connect (cfg, NULL,
3770 &clean_channel, handlers,
3772 if (NULL == cadet_handle)
3774 GNUNET_SCHEDULER_shutdown ();
3778 /* Cadet handle acquired, now announce regular expressions matching our exit */
3779 if ( (GNUNET_YES == ipv4_enabled) && (GNUNET_YES == ipv4_exit) )
3783 GNUNET_CONFIGURATION_get_value_string (cfg,
3785 "EXIT_RANGE_IPV4_POLICY",
3789 regex = GNUNET_TUN_ipv4policy2regex (policy);
3790 GNUNET_free_non_null (policy);
3793 (void) GNUNET_asprintf (&prefixed_regex,
3795 GNUNET_APPLICATION_TYPE_EXIT_REGEX_PREFIX,
3797 regex4 = GNUNET_REGEX_announce (cfg,
3799 REGEX_REFRESH_FREQUENCY,
3800 REGEX_MAX_PATH_LEN_IPV4);
3801 GNUNET_free (regex);
3802 GNUNET_free (prefixed_regex);
3806 if (GNUNET_YES == ipv6_enabled && GNUNET_YES == ipv6_exit)
3810 GNUNET_CONFIGURATION_get_value_string (cfg,
3812 "EXIT_RANGE_IPV6_POLICY",
3816 regex = GNUNET_TUN_ipv6policy2regex (policy);
3817 GNUNET_free_non_null (policy);
3820 (void) GNUNET_asprintf (&prefixed_regex,
3822 GNUNET_APPLICATION_TYPE_EXIT_REGEX_PREFIX,
3824 regex6 = GNUNET_REGEX_announce (cfg,
3826 REGEX_REFRESH_FREQUENCY,
3827 REGEX_MAX_PATH_LEN_IPV6);
3828 GNUNET_free (regex);
3829 GNUNET_free (prefixed_regex);
3832 if ((ipv4_exit) || (ipv6_exit))
3833 helper_handle = GNUNET_HELPER_start (GNUNET_NO,
3834 "gnunet-helper-exit",
3844 * @param argc number of arguments from the command line
3845 * @param argv command line arguments
3846 * @return 0 ok, 1 on error
3849 main (int argc, char *const *argv)
3851 static const struct GNUNET_GETOPT_CommandLineOption options[] = {
3852 GNUNET_GETOPT_OPTION_END
3855 if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv))
3858 return (GNUNET_OK ==
3859 GNUNET_PROGRAM_run (argc, argv, "gnunet-daemon-exit",
3861 ("Daemon to run to provide an IP exit node for the VPN"),
3862 options, &run, NULL)) ? global_ret : 1;
3866 /* end of gnunet-daemon-exit.c */