2 This file is part of GNUnet.
3 (C) 2010, 2012 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., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
22 * @file exit/gnunet-daemon-exit.c
23 * @brief tool to allow IP traffic exit from the GNUnet mesh 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_mesh_service.h"
42 #include "gnunet_dnsparser_lib.h"
43 #include "gnunet_dnsstub_lib.h"
44 #include "gnunet_statistics_service.h"
45 #include "gnunet_constants.h"
46 #include "gnunet_tun_lib.h"
47 #include "gnunet_regex_lib.h"
51 * Maximum path compression length for mesh regex announcing for IPv4 address
54 #define REGEX_MAX_PATH_LEN_IPV4 4
57 * Maximum path compression length for mesh regex announcing for IPv6 address
60 #define REGEX_MAX_PATH_LEN_IPV6 8
64 * Generic logging shorthand
66 #define LOG(kind, ...) \
67 GNUNET_log_from (kind, "exit", __VA_ARGS__);
72 * Information about an address.
77 * AF_INET or AF_INET6.
82 * Remote address information.
87 * Address, if af is AF_INET.
92 * Address, if af is AF_INET6.
98 * IPPROTO_TCP or IPPROTO_UDP;
103 * Remote port, in host byte order!
110 * This struct is saved into the services-hashmap to represent
111 * a service this peer is specifically offering an exit for
112 * (for a specific domain name).
118 * Remote address to use for the service.
120 struct SocketAddress address;
123 * DNS name of the service.
128 * Port I am listening on within GNUnet for this service, in host
129 * byte order. (as we may redirect ports).
136 * Information we use to track a connection (the classical 6-tuple of
137 * IP-version, protocol, source-IP, destination-IP, source-port and
140 struct RedirectInformation
144 * Address information for the other party (equivalent of the
145 * arguments one would give to "connect").
147 struct SocketAddress remote_address;
150 * Address information we used locally (AF and proto must match
151 * "remote_address"). Equivalent of the arguments one would give to
154 struct SocketAddress local_address;
157 Note 1: additional information might be added here in the
158 future to support protocols that require special handling,
161 Note 2: we might also sometimes not match on all components
162 of the tuple, to support protocols where things do not always
169 * Queue of messages to a tunnel.
171 struct TunnelMessageQueue
174 * This is a doubly-linked list.
176 struct TunnelMessageQueue *next;
179 * This is a doubly-linked list.
181 struct TunnelMessageQueue *prev;
184 * Payload to send via the tunnel.
189 * Number of bytes in 'payload'.
196 * This struct is saved into connections_map to allow finding the
197 * right tunnel given an IP packet from TUN. It is also associated
198 * with the tunnel's closure so we can find it again for the next
199 * message from the tunnel.
204 * Mesh tunnel that is used for this connection.
206 struct GNUNET_MESH_Tunnel *tunnel;
209 * Active tunnel transmission request (or NULL).
211 struct GNUNET_MESH_TransmitHandle *th;
214 * GNUNET_NO if this is a tunnel for TCP/UDP,
215 * GNUNET_YES if this is a tunnel for DNS,
216 * GNUNET_SYSERR if the tunnel is not yet initialized.
226 * Heap node for this state in the connections_heap.
228 struct GNUNET_CONTAINER_HeapNode *heap_node;
231 * Key this state has in the connections_map.
233 struct GNUNET_HashCode state_key;
236 * Associated service record, or NULL for no service.
238 struct LocalService *serv;
241 * Head of DLL of messages for this tunnel.
243 struct TunnelMessageQueue *head;
246 * Tail of DLL of messages for this tunnel.
248 struct TunnelMessageQueue *tail;
251 * Primary redirection information for this connection.
253 struct RedirectInformation ri;
260 * DNS reply ready for transmission.
265 * Socket we are using to transmit this request (must match if we receive
268 struct GNUNET_DNSSTUB_RequestSocket *rs;
271 * Number of bytes in 'reply'.
276 * Original DNS request ID as used by the client.
278 uint16_t original_id;
281 * DNS request ID that we used for forwarding.
293 * Return value from 'main'.
295 static int global_ret;
298 * The handle to the configuration used throughout the process
300 static const struct GNUNET_CONFIGURATION_Handle *cfg;
303 * The handle to the helper
305 static struct GNUNET_HELPER_Handle *helper_handle;
308 * Arguments to the exit helper.
310 static char *exit_argv[8];
313 * IPv6 address of our TUN interface.
315 static struct in6_addr exit_ipv6addr;
318 * IPv6 prefix (0..127) from configuration file.
320 static unsigned long long ipv6prefix;
323 * IPv4 address of our TUN interface.
325 static struct in_addr exit_ipv4addr;
328 * IPv4 netmask of our TUN interface.
330 static struct in_addr exit_ipv4mask;
335 static struct GNUNET_STATISTICS_Handle *stats;
340 static struct GNUNET_MESH_Handle *mesh_handle;
343 * This hashmaps contains the mapping from peer, service-descriptor,
344 * source-port and destination-port to a struct TunnelState
346 static struct GNUNET_CONTAINER_MultiHashMap *connections_map;
349 * Heap so we can quickly find "old" connections.
351 static struct GNUNET_CONTAINER_Heap *connections_heap;
354 * If there are at least this many connections, old ones will be removed
356 static unsigned long long max_connections;
359 * This hashmaps saves interesting things about the configured UDP services
361 static struct GNUNET_CONTAINER_MultiHashMap *udp_services;
364 * This hashmaps saves interesting things about the configured TCP services
366 static struct GNUNET_CONTAINER_MultiHashMap *tcp_services;
369 * Array of all open DNS requests from tunnels.
371 static struct TunnelState *tunnels[UINT16_MAX + 1];
374 * Handle to the DNS Stub resolver.
376 static struct GNUNET_DNSSTUB_Context *dnsstub;
379 * Are we an IPv4-exit?
381 static int ipv4_exit;
384 * Are we an IPv6-exit?
386 static int ipv6_exit;
389 * Do we support IPv4 at all on the TUN interface?
391 static int ipv4_enabled;
394 * Do we support IPv6 at all on the TUN interface?
396 static int ipv6_enabled;
400 * We got a reply from DNS for a request of a MESH tunnel. Send it
401 * via the tunnel (after changing the request ID back).
403 * @param cls the 'struct TunnelState'
404 * @param size number of bytes available in buf
405 * @param buf where to copy the reply
406 * @return number of bytes written to buf
409 transmit_reply_to_mesh (void *cls,
413 struct TunnelState *ts = cls;
417 struct GNUNET_MessageHeader hdr;
418 struct GNUNET_TUN_DnsHeader dns;
420 GNUNET_assert (GNUNET_YES == ts->is_dns);
422 GNUNET_assert (ts->specifics.dns.reply != NULL);
425 ret = sizeof (struct GNUNET_MessageHeader) + ts->specifics.dns.reply_length;
426 GNUNET_assert (ret <= size);
427 hdr.size = htons (ret);
428 hdr.type = htons (GNUNET_MESSAGE_TYPE_VPN_DNS_FROM_INTERNET);
429 memcpy (&dns, ts->specifics.dns.reply, sizeof (dns));
430 dns.id = ts->specifics.dns.original_id;
432 memcpy (&cbuf[off], &hdr, sizeof (hdr));
434 memcpy (&cbuf[off], &dns, sizeof (dns));
436 memcpy (&cbuf[off], &ts->specifics.dns.reply[sizeof (dns)], ts->specifics.dns.reply_length - sizeof (dns));
437 off += ts->specifics.dns.reply_length - sizeof (dns);
438 GNUNET_free (ts->specifics.dns.reply);
439 ts->specifics.dns.reply = NULL;
440 ts->specifics.dns.reply_length = 0;
441 GNUNET_assert (ret == off);
447 * Callback called from DNSSTUB resolver when a resolution
451 * @param rs the socket that received the response
452 * @param dns the response itself
453 * @param r number of bytes in dns
456 process_dns_result (void *cls,
457 struct GNUNET_DNSSTUB_RequestSocket *rs,
458 const struct GNUNET_TUN_DnsHeader *dns,
461 struct TunnelState *ts;
463 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
464 "Processing DNS result from stub resolver\n");
465 GNUNET_assert (NULL == cls);
466 /* Handle case that this is a reply to a request from a MESH DNS tunnel */
467 ts = tunnels[dns->id];
469 (ts->specifics.dns.rs != rs) )
471 LOG (GNUNET_ERROR_TYPE_DEBUG,
472 "Got a response from the stub resolver for DNS request received via MESH!\n");
473 tunnels[dns->id] = NULL;
474 GNUNET_free_non_null (ts->specifics.dns.reply);
475 ts->specifics.dns.reply = GNUNET_malloc (r);
476 ts->specifics.dns.reply_length = r;
477 memcpy (ts->specifics.dns.reply, dns, r);
479 GNUNET_MESH_notify_transmit_ready_cancel (ts->th);
480 ts->th = GNUNET_MESH_notify_transmit_ready (ts->tunnel,
482 GNUNET_TIME_UNIT_FOREVER_REL,
484 sizeof (struct GNUNET_MessageHeader) + r,
485 &transmit_reply_to_mesh,
491 * Process a request via mesh to perform a DNS query.
493 * @param cls closure, NULL
494 * @param tunnel connection to the other end
495 * @param tunnel_ctx pointer to our 'struct TunnelState *'
496 * @param sender who sent the message
497 * @param message the actual message
498 * @param atsi performance data for the connection
499 * @return GNUNET_OK to keep the connection open,
500 * GNUNET_SYSERR to close it (signal serious error)
503 receive_dns_request (void *cls GNUNET_UNUSED, struct GNUNET_MESH_Tunnel *tunnel,
505 const struct GNUNET_PeerIdentity *sender GNUNET_UNUSED,
506 const struct GNUNET_MessageHeader *message,
507 const struct GNUNET_ATS_Information *atsi GNUNET_UNUSED)
509 struct TunnelState *ts = *tunnel_ctx;
510 const struct GNUNET_TUN_DnsHeader *dns;
511 size_t mlen = ntohs (message->size);
512 size_t dlen = mlen - sizeof (struct GNUNET_MessageHeader);
513 char buf[dlen] GNUNET_ALIGN;
514 struct GNUNET_TUN_DnsHeader *dout;
517 return GNUNET_SYSERR;
518 if (GNUNET_NO == ts->is_dns)
521 return GNUNET_SYSERR;
523 if (GNUNET_SYSERR == ts->is_dns)
525 /* tunnel is DNS from now on */
526 ts->is_dns = GNUNET_YES;
528 if (dlen < sizeof (struct GNUNET_TUN_DnsHeader))
531 return GNUNET_SYSERR;
533 dns = (const struct GNUNET_TUN_DnsHeader *) &message[1];
534 ts->specifics.dns.original_id = dns->id;
535 if (tunnels[ts->specifics.dns.my_id] == ts)
536 tunnels[ts->specifics.dns.my_id] = NULL;
537 ts->specifics.dns.my_id = (uint16_t) GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
539 tunnels[ts->specifics.dns.my_id] = ts;
540 memcpy (buf, dns, dlen);
541 dout = (struct GNUNET_TUN_DnsHeader *) buf;
542 dout->id = ts->specifics.dns.my_id;
543 ts->specifics.dns.rs = GNUNET_DNSSTUB_resolve2 (dnsstub,
547 if (NULL == ts->specifics.dns.rs)
548 return GNUNET_SYSERR;
554 * Given IP information about a connection, calculate the respective
555 * hash we would use for the 'connections_map'.
557 * @param hash resulting hash
558 * @param ri information about the connection
561 hash_redirect_info (struct GNUNET_HashCode *hash,
562 const struct RedirectInformation *ri)
566 memset (hash, 0, sizeof (struct GNUNET_HashCode));
567 /* the GNUnet hashmap only uses the first sizeof(unsigned int) of the hash,
568 so we put the IP address in there (and hope for few collisions) */
570 switch (ri->remote_address.af)
573 memcpy (off, &ri->remote_address.address.ipv4, sizeof (struct in_addr));
574 off += sizeof (struct in_addr);
577 memcpy (off, &ri->remote_address.address.ipv6, sizeof (struct in6_addr));
578 off += sizeof (struct in_addr);
583 memcpy (off, &ri->remote_address.port, sizeof (uint16_t));
584 off += sizeof (uint16_t);
585 switch (ri->local_address.af)
588 memcpy (off, &ri->local_address.address.ipv4, sizeof (struct in_addr));
589 off += sizeof (struct in_addr);
592 memcpy (off, &ri->local_address.address.ipv6, sizeof (struct in6_addr));
593 off += sizeof (struct in_addr);
598 memcpy (off, &ri->local_address.port, sizeof (uint16_t));
599 off += sizeof (uint16_t);
600 memcpy (off, &ri->remote_address.proto, sizeof (uint8_t));
601 off += sizeof (uint8_t);
606 * Get our connection tracking state. Warns if it does not exists,
607 * refreshes the timestamp if it does exist.
609 * @param af address family
610 * @param protocol IPPROTO_UDP or IPPROTO_TCP
611 * @param destination_ip target IP
612 * @param destination_port target port
613 * @param local_ip local IP
614 * @param local_port local port
615 * @param state_key set to hash's state if non-NULL
616 * @return NULL if we have no tracking information for this tuple
618 static struct TunnelState *
619 get_redirect_state (int af,
621 const void *destination_ip,
622 uint16_t destination_port,
623 const void *local_ip,
625 struct GNUNET_HashCode *state_key)
627 struct RedirectInformation ri;
628 struct GNUNET_HashCode key;
629 struct TunnelState *state;
631 if ( ( (af == AF_INET) && (protocol == IPPROTO_ICMP) ) ||
632 ( (af == AF_INET6) && (protocol == IPPROTO_ICMPV6) ) )
635 destination_port = 0;
638 ri.remote_address.af = af;
640 ri.remote_address.address.ipv4 = *((struct in_addr*) destination_ip);
642 ri.remote_address.address.ipv6 = * ((struct in6_addr*) destination_ip);
643 ri.remote_address.port = destination_port;
644 ri.remote_address.proto = protocol;
645 ri.local_address.af = af;
647 ri.local_address.address.ipv4 = *((struct in_addr*) local_ip);
649 ri.local_address.address.ipv6 = * ((struct in6_addr*) local_ip);
650 ri.local_address.port = local_port;
651 ri.local_address.proto = protocol;
652 hash_redirect_info (&key, &ri);
653 if (NULL != state_key)
655 state = GNUNET_CONTAINER_multihashmap_get (connections_map, &key);
658 /* Mark this connection as freshly used */
659 if (NULL == state_key)
660 GNUNET_CONTAINER_heap_update_cost (connections_heap,
661 state->specifics.tcp_udp.heap_node,
662 GNUNET_TIME_absolute_get ().abs_value);
668 * Given a service descriptor and a destination port, find the
669 * respective service entry.
671 * @param service_map map of services (TCP or UDP)
672 * @param desc service descriptor
673 * @param destination_port destination port
674 * @return NULL if we are not aware of such a service
676 static struct LocalService *
677 find_service (struct GNUNET_CONTAINER_MultiHashMap *service_map,
678 const struct GNUNET_HashCode *desc,
679 uint16_t destination_port)
681 char key[sizeof (struct GNUNET_HashCode) + sizeof (uint16_t)];
683 memcpy (&key[0], &destination_port, sizeof (uint16_t));
684 memcpy (&key[sizeof(uint16_t)], desc, sizeof (struct GNUNET_HashCode));
685 return GNUNET_CONTAINER_multihashmap_get (service_map,
686 (struct GNUNET_HashCode *) key);
691 * Free memory associated with a service record.
694 * @param key service descriptor
695 * @param value service record to free
699 free_service_record (void *cls,
700 const struct GNUNET_HashCode *key,
703 struct LocalService *service = value;
705 GNUNET_free_non_null (service->name);
706 GNUNET_free (service);
712 * Given a service descriptor and a destination port, find the
713 * respective service entry.
715 * @param service_map map of services (TCP or UDP)
716 * @param name name of the service
717 * @param destination_port destination port
718 * @param service service information record to store (service->name will be set).
721 store_service (struct GNUNET_CONTAINER_MultiHashMap *service_map,
723 uint16_t destination_port,
724 struct LocalService *service)
726 char key[sizeof (struct GNUNET_HashCode) + sizeof (uint16_t)];
727 struct GNUNET_HashCode desc;
729 GNUNET_CRYPTO_hash (name, strlen (name) + 1, &desc);
730 service->name = GNUNET_strdup (name);
731 memcpy (&key[0], &destination_port, sizeof (uint16_t));
732 memcpy (&key[sizeof(uint16_t)], &desc, sizeof (struct GNUNET_HashCode));
734 GNUNET_CONTAINER_multihashmap_put (service_map,
735 (struct GNUNET_HashCode *) key,
737 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY))
739 free_service_record (NULL, (struct GNUNET_HashCode *) key, service);
740 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
741 _("Got duplicate service records for `%s:%u'\n"),
743 (unsigned int) destination_port);
749 * MESH is ready to receive a message for the tunnel. Transmit it.
751 * @param cls the 'struct TunnelState'.
752 * @param size number of bytes available in buf
753 * @param buf where to copy the message
754 * @return number of bytes copied to buf
757 send_to_peer_notify_callback (void *cls, size_t size, void *buf)
759 struct TunnelState *s = cls;
760 struct GNUNET_MESH_Tunnel *tunnel = s->tunnel;
761 struct TunnelMessageQueue *tnq;
764 tnq = s->specifics.tcp_udp.head;
769 s->th = GNUNET_MESH_notify_transmit_ready (tunnel,
770 GNUNET_NO /* corking */,
771 GNUNET_TIME_UNIT_FOREVER_REL,
774 &send_to_peer_notify_callback,
778 GNUNET_assert (size >= tnq->len);
779 memcpy (buf, tnq->payload, tnq->len);
781 GNUNET_CONTAINER_DLL_remove (s->specifics.tcp_udp.head,
782 s->specifics.tcp_udp.tail,
785 if (NULL != (tnq = s->specifics.tcp_udp.head))
786 s->th = GNUNET_MESH_notify_transmit_ready (tunnel,
787 GNUNET_NO /* corking */,
788 GNUNET_TIME_UNIT_FOREVER_REL,
791 &send_to_peer_notify_callback,
793 GNUNET_STATISTICS_update (stats,
794 gettext_noop ("# Bytes transmitted via mesh tunnels"),
801 * Send the given packet via the mesh tunnel.
803 * @param mesh_tunnel destination
804 * @param tnq message to queue
807 send_packet_to_mesh_tunnel (struct GNUNET_MESH_Tunnel *mesh_tunnel,
808 struct TunnelMessageQueue *tnq)
810 struct TunnelState *s;
812 s = GNUNET_MESH_tunnel_get_data (mesh_tunnel);
813 GNUNET_assert (NULL != s);
814 GNUNET_CONTAINER_DLL_insert_tail (s->specifics.tcp_udp.head, s->specifics.tcp_udp.tail, tnq);
816 s->th = GNUNET_MESH_notify_transmit_ready (mesh_tunnel,
817 GNUNET_NO /* cork */,
818 GNUNET_TIME_UNIT_FOREVER_REL,
820 &send_to_peer_notify_callback,
826 * @brief Handles an ICMP packet received from the helper.
828 * @param icmp A pointer to the Packet
829 * @param pktlen number of bytes in 'icmp'
830 * @param af address family (AFINET or AF_INET6)
831 * @param destination_ip destination IP-address of the IP packet (should
832 * be our local address)
833 * @param source_ip original source IP-address of the IP packet (should
834 * be the original destination address)
837 icmp_from_helper (const struct GNUNET_TUN_IcmpHeader *icmp,
840 const void *destination_ip,
841 const void *source_ip)
843 struct TunnelState *state;
844 struct TunnelMessageQueue *tnq;
845 struct GNUNET_EXIT_IcmpToVPNMessage *i2v;
846 const struct GNUNET_TUN_IPv4Header *ipv4;
847 const struct GNUNET_TUN_IPv6Header *ipv6;
848 const struct GNUNET_TUN_UdpHeader *udp;
850 uint16_t source_port;
851 uint16_t destination_port;
855 char sbuf[INET6_ADDRSTRLEN];
856 char dbuf[INET6_ADDRSTRLEN];
857 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
858 "Received ICMP packet going from %s to %s\n",
861 sbuf, sizeof (sbuf)),
864 dbuf, sizeof (dbuf)));
866 if (pktlen < sizeof (struct GNUNET_TUN_IcmpHeader))
873 /* Find out if this is an ICMP packet in response to an existing
874 TCP/UDP packet and if so, figure out ports / protocol of the
875 existing session from the IP data in the ICMP payload */
877 destination_port = 0;
881 protocol = IPPROTO_ICMP;
884 case GNUNET_TUN_ICMPTYPE_ECHO_REPLY:
885 case GNUNET_TUN_ICMPTYPE_ECHO_REQUEST:
887 case GNUNET_TUN_ICMPTYPE_DESTINATION_UNREACHABLE:
888 case GNUNET_TUN_ICMPTYPE_SOURCE_QUENCH:
889 case GNUNET_TUN_ICMPTYPE_TIME_EXCEEDED:
891 sizeof (struct GNUNET_TUN_IcmpHeader) +
892 sizeof (struct GNUNET_TUN_IPv4Header) + 8)
898 ipv4 = (const struct GNUNET_TUN_IPv4Header *) &icmp[1];
899 protocol = ipv4->protocol;
900 /* could be TCP or UDP, but both have the ports in the right
901 place, so that doesn't matter here */
902 udp = (const struct GNUNET_TUN_UdpHeader *) &ipv4[1];
903 /* swap ports, as they are from the original message */
904 destination_port = ntohs (udp->source_port);
905 source_port = ntohs (udp->destination_port);
906 /* throw away ICMP payload, won't be useful for the other side anyway */
907 pktlen = sizeof (struct GNUNET_TUN_IcmpHeader);
910 GNUNET_STATISTICS_update (stats,
911 gettext_noop ("# ICMPv4 packets dropped (type not allowed)"),
917 protocol = IPPROTO_ICMPV6;
920 case GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE:
921 case GNUNET_TUN_ICMPTYPE6_PACKET_TOO_BIG:
922 case GNUNET_TUN_ICMPTYPE6_TIME_EXCEEDED:
923 case GNUNET_TUN_ICMPTYPE6_PARAMETER_PROBLEM:
925 sizeof (struct GNUNET_TUN_IcmpHeader) +
926 sizeof (struct GNUNET_TUN_IPv6Header) + 8)
932 ipv6 = (const struct GNUNET_TUN_IPv6Header *) &icmp[1];
933 protocol = ipv6->next_header;
934 /* could be TCP or UDP, but both have the ports in the right
935 place, so that doesn't matter here */
936 udp = (const struct GNUNET_TUN_UdpHeader *) &ipv6[1];
937 /* swap ports, as they are from the original message */
938 destination_port = ntohs (udp->source_port);
939 source_port = ntohs (udp->destination_port);
940 /* throw away ICMP payload, won't be useful for the other side anyway */
941 pktlen = sizeof (struct GNUNET_TUN_IcmpHeader);
943 case GNUNET_TUN_ICMPTYPE6_ECHO_REQUEST:
944 case GNUNET_TUN_ICMPTYPE6_ECHO_REPLY:
947 GNUNET_STATISTICS_update (stats,
948 gettext_noop ("# ICMPv6 packets dropped (type not allowed)"),
959 state = get_redirect_state (af, IPPROTO_ICMP,
965 state = get_redirect_state (af, IPPROTO_ICMPV6,
971 state = get_redirect_state (af, IPPROTO_UDP,
979 state = get_redirect_state (af, IPPROTO_TCP,
987 GNUNET_STATISTICS_update (stats,
988 gettext_noop ("# ICMP packets dropped (not allowed)"),
994 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
995 _("ICMP Packet dropped, have no matching connection information\n"));
998 mlen = sizeof (struct GNUNET_EXIT_IcmpToVPNMessage) + pktlen - sizeof (struct GNUNET_TUN_IcmpHeader);
999 tnq = GNUNET_malloc (sizeof (struct TunnelMessageQueue) + mlen);
1000 tnq->payload = &tnq[1];
1002 i2v = (struct GNUNET_EXIT_IcmpToVPNMessage *) &tnq[1];
1003 i2v->header.size = htons ((uint16_t) mlen);
1004 i2v->header.type = htons (GNUNET_MESSAGE_TYPE_VPN_ICMP_TO_VPN);
1005 i2v->af = htonl (af);
1006 memcpy (&i2v->icmp_header,
1009 send_packet_to_mesh_tunnel (state->tunnel,
1015 * @brief Handles an UDP packet received from the helper.
1017 * @param udp A pointer to the Packet
1018 * @param pktlen number of bytes in 'udp'
1019 * @param af address family (AFINET or AF_INET6)
1020 * @param destination_ip destination IP-address of the IP packet (should
1021 * be our local address)
1022 * @param source_ip original source IP-address of the IP packet (should
1023 * be the original destination address)
1026 udp_from_helper (const struct GNUNET_TUN_UdpHeader *udp,
1029 const void *destination_ip,
1030 const void *source_ip)
1032 struct TunnelState *state;
1033 struct TunnelMessageQueue *tnq;
1034 struct GNUNET_EXIT_UdpReplyMessage *urm;
1038 char sbuf[INET6_ADDRSTRLEN];
1039 char dbuf[INET6_ADDRSTRLEN];
1040 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1041 "Received UDP packet going from %s:%u to %s:%u\n",
1044 sbuf, sizeof (sbuf)),
1045 (unsigned int) ntohs (udp->source_port),
1048 dbuf, sizeof (dbuf)),
1049 (unsigned int) ntohs (udp->destination_port));
1051 if (pktlen < sizeof (struct GNUNET_TUN_UdpHeader))
1057 if (pktlen != ntohs (udp->len))
1063 state = get_redirect_state (af, IPPROTO_UDP,
1065 ntohs (udp->source_port),
1067 ntohs (udp->destination_port),
1071 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1072 _("UDP Packet dropped, have no matching connection information\n"));
1075 mlen = sizeof (struct GNUNET_EXIT_UdpReplyMessage) + pktlen - sizeof (struct GNUNET_TUN_UdpHeader);
1076 tnq = GNUNET_malloc (sizeof (struct TunnelMessageQueue) + mlen);
1077 tnq->payload = &tnq[1];
1079 urm = (struct GNUNET_EXIT_UdpReplyMessage *) &tnq[1];
1080 urm->header.size = htons ((uint16_t) mlen);
1081 urm->header.type = htons (GNUNET_MESSAGE_TYPE_VPN_UDP_REPLY);
1082 urm->source_port = htons (0);
1083 urm->destination_port = htons (0);
1086 pktlen - sizeof (struct GNUNET_TUN_UdpHeader));
1087 send_packet_to_mesh_tunnel (state->tunnel,
1093 * @brief Handles a TCP packet received from the helper.
1095 * @param tcp A pointer to the Packet
1096 * @param pktlen the length of the packet, including its TCP header
1097 * @param af address family (AFINET or AF_INET6)
1098 * @param destination_ip destination IP-address of the IP packet (should
1099 * be our local address)
1100 * @param source_ip original source IP-address of the IP packet (should
1101 * be the original destination address)
1104 tcp_from_helper (const struct GNUNET_TUN_TcpHeader *tcp,
1107 const void *destination_ip,
1108 const void *source_ip)
1110 struct TunnelState *state;
1111 char buf[pktlen] GNUNET_ALIGN;
1112 struct GNUNET_TUN_TcpHeader *mtcp;
1113 struct GNUNET_EXIT_TcpDataMessage *tdm;
1114 struct TunnelMessageQueue *tnq;
1118 char sbuf[INET6_ADDRSTRLEN];
1119 char dbuf[INET6_ADDRSTRLEN];
1120 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1121 "Received TCP packet with %u bytes going from %s:%u to %s:%u\n",
1122 pktlen - sizeof (struct GNUNET_TUN_TcpHeader),
1125 sbuf, sizeof (sbuf)),
1126 (unsigned int) ntohs (tcp->source_port),
1129 dbuf, sizeof (dbuf)),
1130 (unsigned int) ntohs (tcp->destination_port));
1132 if (pktlen < sizeof (struct GNUNET_TUN_TcpHeader))
1138 state = get_redirect_state (af, IPPROTO_TCP,
1140 ntohs (tcp->source_port),
1142 ntohs (tcp->destination_port),
1146 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1147 _("TCP Packet dropped, have no matching connection information\n"));
1151 /* mug port numbers and crc to avoid information leakage;
1152 sender will need to lookup the correct values anyway */
1153 memcpy (buf, tcp, pktlen);
1154 mtcp = (struct GNUNET_TUN_TcpHeader *) buf;
1155 mtcp->source_port = 0;
1156 mtcp->destination_port = 0;
1159 mlen = sizeof (struct GNUNET_EXIT_TcpDataMessage) + (pktlen - sizeof (struct GNUNET_TUN_TcpHeader));
1160 if (mlen >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1166 tnq = GNUNET_malloc (sizeof (struct TunnelMessageQueue) + mlen);
1167 tnq->payload = &tnq[1];
1169 tdm = (struct GNUNET_EXIT_TcpDataMessage *) &tnq[1];
1170 tdm->header.size = htons ((uint16_t) mlen);
1171 tdm->header.type = htons (GNUNET_MESSAGE_TYPE_VPN_TCP_DATA_TO_VPN);
1172 tdm->reserved = htonl (0);
1173 memcpy (&tdm->tcp_header,
1176 send_packet_to_mesh_tunnel (state->tunnel,
1182 * Receive packets from the helper-process
1185 * @param client unsued
1186 * @param message message received from helper
1189 message_token (void *cls GNUNET_UNUSED, void *client GNUNET_UNUSED,
1190 const struct GNUNET_MessageHeader *message)
1192 const struct GNUNET_TUN_Layer2PacketHeader *pkt_tun;
1195 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1196 "Got %u-byte message of type %u from gnunet-helper-exit\n",
1197 ntohs (message->size),
1198 ntohs (message->type));
1199 GNUNET_STATISTICS_update (stats,
1200 gettext_noop ("# Packets received from TUN"),
1202 if (ntohs (message->type) != GNUNET_MESSAGE_TYPE_VPN_HELPER)
1207 size = ntohs (message->size);
1208 if (size < sizeof (struct GNUNET_TUN_Layer2PacketHeader) + sizeof (struct GNUNET_MessageHeader))
1213 GNUNET_STATISTICS_update (stats,
1214 gettext_noop ("# Bytes received from TUN"),
1216 pkt_tun = (const struct GNUNET_TUN_Layer2PacketHeader *) &message[1];
1217 size -= sizeof (struct GNUNET_TUN_Layer2PacketHeader) + sizeof (struct GNUNET_MessageHeader);
1218 switch (ntohs (pkt_tun->proto))
1222 const struct GNUNET_TUN_IPv4Header *pkt4;
1224 if (size < sizeof (struct GNUNET_TUN_IPv4Header))
1226 /* Kernel to blame? */
1230 pkt4 = (const struct GNUNET_TUN_IPv4Header *) &pkt_tun[1];
1231 if (size != ntohs (pkt4->total_length))
1233 /* Kernel to blame? */
1237 if (pkt4->header_length * 4 != sizeof (struct GNUNET_TUN_IPv4Header))
1239 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1240 _("IPv4 packet options received. Ignored.\n"));
1244 size -= sizeof (struct GNUNET_TUN_IPv4Header);
1245 switch (pkt4->protocol)
1248 udp_from_helper ((const struct GNUNET_TUN_UdpHeader *) &pkt4[1], size,
1250 &pkt4->destination_address,
1251 &pkt4->source_address);
1254 tcp_from_helper ((const struct GNUNET_TUN_TcpHeader *) &pkt4[1], size,
1256 &pkt4->destination_address,
1257 &pkt4->source_address);
1260 icmp_from_helper ((const struct GNUNET_TUN_IcmpHeader *) &pkt4[1], size,
1262 &pkt4->destination_address,
1263 &pkt4->source_address);
1266 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1267 _("IPv4 packet with unsupported next header %u received. Ignored.\n"),
1268 (int) pkt4->protocol);
1275 const struct GNUNET_TUN_IPv6Header *pkt6;
1277 if (size < sizeof (struct GNUNET_TUN_IPv6Header))
1279 /* Kernel to blame? */
1283 pkt6 = (struct GNUNET_TUN_IPv6Header *) &pkt_tun[1];
1284 if (size != ntohs (pkt6->payload_length) + sizeof (struct GNUNET_TUN_IPv6Header))
1286 /* Kernel to blame? */
1290 size -= sizeof (struct GNUNET_TUN_IPv6Header);
1291 switch (pkt6->next_header)
1294 udp_from_helper ((const struct GNUNET_TUN_UdpHeader *) &pkt6[1], size,
1296 &pkt6->destination_address,
1297 &pkt6->source_address);
1300 tcp_from_helper ((const struct GNUNET_TUN_TcpHeader *) &pkt6[1], size,
1302 &pkt6->destination_address,
1303 &pkt6->source_address);
1305 case IPPROTO_ICMPV6:
1306 icmp_from_helper ((const struct GNUNET_TUN_IcmpHeader *) &pkt6[1], size,
1308 &pkt6->destination_address,
1309 &pkt6->source_address);
1312 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1313 _("IPv6 packet with unsupported next header %d received. Ignored.\n"),
1320 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1321 _("Packet from unknown protocol %u received. Ignored.\n"),
1322 ntohs (pkt_tun->proto));
1330 * We need to create a (unique) fresh local address (IP+port).
1333 * @param af desired address family
1334 * @param proto desired protocol (IPPROTO_UDP or IPPROTO_TCP)
1335 * @param local_address address to initialize
1338 setup_fresh_address (int af,
1340 struct SocketAddress *local_address)
1342 local_address->af = af;
1343 local_address->proto = (uint8_t) proto;
1344 /* default "local" port range is often 32768--61000,
1345 so we pick a random value in that range */
1346 if ( ( (af == AF_INET) && (proto == IPPROTO_ICMP) ) ||
1347 ( (af == AF_INET6) && (proto == IPPROTO_ICMPV6) ) )
1348 local_address->port = 0;
1351 = (uint16_t) 32768 + GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
1357 struct in_addr addr;
1358 struct in_addr mask;
1361 addr = exit_ipv4addr;
1362 mask = exit_ipv4mask;
1363 if (0 == ~mask.s_addr)
1365 /* only one valid IP anyway */
1366 local_address->address.ipv4 = addr;
1369 /* Given 192.168.0.1/255.255.0.0, we want a mask
1370 of '192.168.255.255', thus: */
1371 mask.s_addr = addr.s_addr | ~mask.s_addr;
1372 /* Pick random IPv4 address within the subnet, except 'addr' or 'mask' itself */
1375 rnd.s_addr = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
1377 local_address->address.ipv4.s_addr = (addr.s_addr | rnd.s_addr) & mask.s_addr;
1379 while ( (local_address->address.ipv4.s_addr == addr.s_addr) ||
1380 (local_address->address.ipv4.s_addr == mask.s_addr) );
1385 struct in6_addr addr;
1386 struct in6_addr mask;
1387 struct in6_addr rnd;
1390 addr = exit_ipv6addr;
1391 GNUNET_assert (ipv6prefix < 128);
1392 if (ipv6prefix == 127)
1394 /* only one valid IP anyway */
1395 local_address->address.ipv6 = addr;
1398 /* Given ABCD::/96, we want a mask of 'ABCD::FFFF:FFFF,
1401 for (i=127;i>=ipv6prefix;i--)
1402 mask.s6_addr[i / 8] |= (1 << (i % 8));
1404 /* Pick random IPv6 address within the subnet, except 'addr' or 'mask' itself */
1409 rnd.s6_addr[i] = (unsigned char) GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
1411 local_address->address.ipv6.s6_addr[i]
1412 = (addr.s6_addr[i] | rnd.s6_addr[i]) & mask.s6_addr[i];
1415 while ( (0 == memcmp (&local_address->address.ipv6,
1417 sizeof (struct in6_addr))) ||
1418 (0 == memcmp (&local_address->address.ipv6,
1420 sizeof (struct in6_addr))) );
1430 * We are starting a fresh connection (TCP or UDP) and need
1431 * to pick a source port and IP address (within the correct
1432 * range and address family) to associate replies with the
1433 * connection / correct mesh tunnel. This function generates
1434 * a "fresh" source IP and source port number for a connection
1435 * After picking a good source address, this function sets up
1436 * the state in the 'connections_map' and 'connections_heap'
1437 * to allow finding the state when needed later. The function
1438 * also makes sure that we remain within memory limits by
1439 * cleaning up 'old' states.
1441 * @param state skeleton state to setup a record for; should
1442 * 'state->specifics.tcp_udp.ri.remote_address' filled in so that
1443 * this code can determine which AF/protocol is
1444 * going to be used (the 'tunnel' should also
1445 * already be set); after calling this function,
1446 * heap_node and the local_address will be
1447 * also initialized (heap_node != NULL can be
1448 * used to test if a state has been fully setup).
1451 setup_state_record (struct TunnelState *state)
1453 struct GNUNET_HashCode key;
1454 struct TunnelState *s;
1456 /* generate fresh, unique address */
1459 if (NULL == state->specifics.tcp_udp.serv)
1460 setup_fresh_address (state->specifics.tcp_udp.ri.remote_address.af,
1461 state->specifics.tcp_udp.ri.remote_address.proto,
1462 &state->specifics.tcp_udp.ri.local_address);
1464 setup_fresh_address (state->specifics.tcp_udp.serv->address.af,
1465 state->specifics.tcp_udp.serv->address.proto,
1466 &state->specifics.tcp_udp.ri.local_address);
1467 } while (NULL != get_redirect_state (state->specifics.tcp_udp.ri.remote_address.af,
1468 state->specifics.tcp_udp.ri.remote_address.proto,
1469 &state->specifics.tcp_udp.ri.remote_address.address,
1470 state->specifics.tcp_udp.ri.remote_address.port,
1471 &state->specifics.tcp_udp.ri.local_address.address,
1472 state->specifics.tcp_udp.ri.local_address.port,
1475 char buf[INET6_ADDRSTRLEN];
1476 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1477 "Picked local address %s:%u for new connection\n",
1478 inet_ntop (state->specifics.tcp_udp.ri.local_address.af,
1479 &state->specifics.tcp_udp.ri.local_address.address,
1481 (unsigned int) state->specifics.tcp_udp.ri.local_address.port);
1483 state->specifics.tcp_udp.state_key = key;
1484 GNUNET_assert (GNUNET_OK ==
1485 GNUNET_CONTAINER_multihashmap_put (connections_map,
1487 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
1488 state->specifics.tcp_udp.heap_node = GNUNET_CONTAINER_heap_insert (connections_heap,
1490 GNUNET_TIME_absolute_get ().abs_value);
1491 while (GNUNET_CONTAINER_heap_get_size (connections_heap) > max_connections)
1493 s = GNUNET_CONTAINER_heap_remove_root (connections_heap);
1494 GNUNET_assert (state != s);
1495 s->specifics.tcp_udp.heap_node = NULL;
1496 GNUNET_MESH_tunnel_destroy (s->tunnel);
1497 GNUNET_assert (GNUNET_OK ==
1498 GNUNET_CONTAINER_multihashmap_remove (connections_map,
1499 &s->specifics.tcp_udp.state_key,
1507 * Prepare an IPv4 packet for transmission via the TUN interface.
1508 * Initializes the IP header and calculates checksums (IP+UDP/TCP).
1509 * For UDP, the UDP header will be fully created, whereas for TCP
1510 * only the ports and checksum will be filled in. So for TCP,
1511 * a skeleton TCP header must be part of the provided payload.
1513 * @param payload payload of the packet (starting with UDP payload or
1514 * TCP header, depending on protocol)
1515 * @param payload_length number of bytes in 'payload'
1516 * @param protocol IPPROTO_UDP or IPPROTO_TCP
1517 * @param tcp_header skeleton of the TCP header, NULL for UDP
1518 * @param src_address source address to use (IP and port)
1519 * @param dst_address destination address to use (IP and port)
1520 * @param pkt4 where to write the assembled packet; must
1521 * contain enough space for the IP header, UDP/TCP header
1525 prepare_ipv4_packet (const void *payload, size_t payload_length,
1527 const struct GNUNET_TUN_TcpHeader *tcp_header,
1528 const struct SocketAddress *src_address,
1529 const struct SocketAddress *dst_address,
1530 struct GNUNET_TUN_IPv4Header *pkt4)
1534 len = payload_length;
1538 len += sizeof (struct GNUNET_TUN_UdpHeader);
1541 len += sizeof (struct GNUNET_TUN_TcpHeader);
1542 GNUNET_assert (NULL != tcp_header);
1548 if (len + sizeof (struct GNUNET_TUN_IPv4Header) > UINT16_MAX)
1554 GNUNET_TUN_initialize_ipv4_header (pkt4,
1557 &src_address->address.ipv4,
1558 &dst_address->address.ipv4);
1563 struct GNUNET_TUN_UdpHeader *pkt4_udp = (struct GNUNET_TUN_UdpHeader *) &pkt4[1];
1565 pkt4_udp->source_port = htons (src_address->port);
1566 pkt4_udp->destination_port = htons (dst_address->port);
1567 pkt4_udp->len = htons ((uint16_t) payload_length);
1568 GNUNET_TUN_calculate_udp4_checksum (pkt4,
1570 payload, payload_length);
1571 memcpy (&pkt4_udp[1], payload, payload_length);
1576 struct GNUNET_TUN_TcpHeader *pkt4_tcp = (struct GNUNET_TUN_TcpHeader *) &pkt4[1];
1578 *pkt4_tcp = *tcp_header;
1579 pkt4_tcp->source_port = htons (src_address->port);
1580 pkt4_tcp->destination_port = htons (dst_address->port);
1581 GNUNET_TUN_calculate_tcp4_checksum (pkt4,
1585 memcpy (&pkt4_tcp[1], payload, payload_length);
1595 * Prepare an IPv6 packet for transmission via the TUN interface.
1596 * Initializes the IP header and calculates checksums (IP+UDP/TCP).
1597 * For UDP, the UDP header will be fully created, whereas for TCP
1598 * only the ports and checksum will be filled in. So for TCP,
1599 * a skeleton TCP header must be part of the provided payload.
1601 * @param payload payload of the packet (starting with UDP payload or
1602 * TCP header, depending on protocol)
1603 * @param payload_length number of bytes in 'payload'
1604 * @param protocol IPPROTO_UDP or IPPROTO_TCP
1605 * @param tcp_header skeleton TCP header data to send, NULL for UDP
1606 * @param src_address source address to use (IP and port)
1607 * @param dst_address destination address to use (IP and port)
1608 * @param pkt6 where to write the assembled packet; must
1609 * contain enough space for the IP header, UDP/TCP header
1613 prepare_ipv6_packet (const void *payload, size_t payload_length,
1615 const struct GNUNET_TUN_TcpHeader *tcp_header,
1616 const struct SocketAddress *src_address,
1617 const struct SocketAddress *dst_address,
1618 struct GNUNET_TUN_IPv6Header *pkt6)
1622 len = payload_length;
1626 len += sizeof (struct GNUNET_TUN_UdpHeader);
1629 len += sizeof (struct GNUNET_TUN_TcpHeader);
1635 if (len > UINT16_MAX)
1641 GNUNET_TUN_initialize_ipv6_header (pkt6,
1644 &src_address->address.ipv6,
1645 &dst_address->address.ipv6);
1651 struct GNUNET_TUN_UdpHeader *pkt6_udp = (struct GNUNET_TUN_UdpHeader *) &pkt6[1];
1653 pkt6_udp->source_port = htons (src_address->port);
1654 pkt6_udp->destination_port = htons (dst_address->port);
1655 pkt6_udp->len = htons ((uint16_t) payload_length);
1656 GNUNET_TUN_calculate_udp6_checksum (pkt6,
1660 memcpy (&pkt6_udp[1], payload, payload_length);
1665 struct GNUNET_TUN_TcpHeader *pkt6_tcp = (struct GNUNET_TUN_TcpHeader *) &pkt6[1];
1667 /* memcpy first here as some TCP header fields are initialized this way! */
1668 *pkt6_tcp = *tcp_header;
1669 pkt6_tcp->source_port = htons (src_address->port);
1670 pkt6_tcp->destination_port = htons (dst_address->port);
1671 GNUNET_TUN_calculate_tcp6_checksum (pkt6,
1675 memcpy (&pkt6_tcp[1], payload, payload_length);
1686 * Send a TCP packet via the TUN interface.
1688 * @param destination_address IP and port to use for the TCP packet's destination
1689 * @param source_address IP and port to use for the TCP packet's source
1690 * @param tcp_header header template to use
1691 * @param payload payload of the TCP packet
1692 * @param payload_length number of bytes in 'payload'
1695 send_tcp_packet_via_tun (const struct SocketAddress *destination_address,
1696 const struct SocketAddress *source_address,
1697 const struct GNUNET_TUN_TcpHeader *tcp_header,
1698 const void *payload, size_t payload_length)
1702 GNUNET_STATISTICS_update (stats,
1703 gettext_noop ("# TCP packets sent via TUN"),
1705 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1706 "Sending packet with %u bytes TCP payload via TUN\n",
1707 (unsigned int) payload_length);
1708 len = sizeof (struct GNUNET_MessageHeader) + sizeof (struct GNUNET_TUN_Layer2PacketHeader);
1709 switch (source_address->af)
1712 len += sizeof (struct GNUNET_TUN_IPv4Header);
1715 len += sizeof (struct GNUNET_TUN_IPv6Header);
1721 len += sizeof (struct GNUNET_TUN_TcpHeader);
1722 len += payload_length;
1723 if (len >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1729 char buf[len] GNUNET_ALIGN;
1730 struct GNUNET_MessageHeader *hdr;
1731 struct GNUNET_TUN_Layer2PacketHeader *tun;
1733 hdr = (struct GNUNET_MessageHeader *) buf;
1734 hdr->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
1735 hdr->size = htons (len);
1736 tun = (struct GNUNET_TUN_Layer2PacketHeader*) &hdr[1];
1737 tun->flags = htons (0);
1738 switch (source_address->af)
1742 struct GNUNET_TUN_IPv4Header * ipv4 = (struct GNUNET_TUN_IPv4Header*) &tun[1];
1744 tun->proto = htons (ETH_P_IPV4);
1745 prepare_ipv4_packet (payload, payload_length,
1749 destination_address,
1755 struct GNUNET_TUN_IPv6Header * ipv6 = (struct GNUNET_TUN_IPv6Header*) &tun[1];
1757 tun->proto = htons (ETH_P_IPV6);
1758 prepare_ipv6_packet (payload, payload_length,
1762 destination_address,
1770 if (NULL != helper_handle)
1771 (void) GNUNET_HELPER_send (helper_handle,
1772 (const struct GNUNET_MessageHeader*) buf,
1780 * Process a request via mesh to send a request to a TCP service
1781 * offered by this system.
1783 * @param cls closure, NULL
1784 * @param tunnel connection to the other end
1785 * @param tunnel_ctx pointer to our 'struct TunnelState *'
1786 * @param sender who sent the message
1787 * @param message the actual message
1788 * @param atsi performance data for the connection
1789 * @return GNUNET_OK to keep the connection open,
1790 * GNUNET_SYSERR to close it (signal serious error)
1793 receive_tcp_service (void *cls GNUNET_UNUSED, struct GNUNET_MESH_Tunnel *tunnel,
1794 void **tunnel_ctx GNUNET_UNUSED,
1795 const struct GNUNET_PeerIdentity *sender GNUNET_UNUSED,
1796 const struct GNUNET_MessageHeader *message,
1797 const struct GNUNET_ATS_Information *atsi GNUNET_UNUSED)
1799 struct TunnelState *state = *tunnel_ctx;
1800 const struct GNUNET_EXIT_TcpServiceStartMessage *start;
1801 uint16_t pkt_len = ntohs (message->size);
1803 if (GNUNET_YES == state->is_dns)
1805 GNUNET_break_op (0);
1806 return GNUNET_SYSERR;
1808 if (GNUNET_SYSERR == state->is_dns)
1810 /* tunnel is UDP/TCP from now on */
1811 state->is_dns = GNUNET_NO;
1813 GNUNET_STATISTICS_update (stats,
1814 gettext_noop ("# TCP service creation requests received via mesh"),
1816 GNUNET_STATISTICS_update (stats,
1817 gettext_noop ("# Bytes received from MESH"),
1818 pkt_len, GNUNET_NO);
1819 /* check that we got at least a valid header */
1820 if (pkt_len < sizeof (struct GNUNET_EXIT_TcpServiceStartMessage))
1822 GNUNET_break_op (0);
1823 return GNUNET_SYSERR;
1825 start = (const struct GNUNET_EXIT_TcpServiceStartMessage*) message;
1826 pkt_len -= sizeof (struct GNUNET_EXIT_TcpServiceStartMessage);
1827 if ( (NULL == state) ||
1828 (NULL != state->specifics.tcp_udp.serv) ||
1829 (NULL != state->specifics.tcp_udp.heap_node) )
1831 GNUNET_break_op (0);
1832 return GNUNET_SYSERR;
1834 if (start->tcp_header.off * 4 < sizeof (struct GNUNET_TUN_TcpHeader))
1836 GNUNET_break_op (0);
1837 return GNUNET_SYSERR;
1839 GNUNET_break_op (ntohl (start->reserved) == 0);
1840 /* setup fresh connection */
1841 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1842 "Received data from %s for forwarding to TCP service %s on port %u\n",
1843 GNUNET_i2s (sender),
1844 GNUNET_h2s (&start->service_descriptor),
1845 (unsigned int) ntohs (start->tcp_header.destination_port));
1846 if (NULL == (state->specifics.tcp_udp.serv = find_service (tcp_services, &start->service_descriptor,
1847 ntohs (start->tcp_header.destination_port))))
1849 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1850 _("No service found for %s on port %d!\n"),
1852 ntohs (start->tcp_header.destination_port));
1853 GNUNET_STATISTICS_update (stats,
1854 gettext_noop ("# TCP requests dropped (no such service)"),
1856 return GNUNET_SYSERR;
1858 state->specifics.tcp_udp.ri.remote_address = state->specifics.tcp_udp.serv->address;
1859 setup_state_record (state);
1860 send_tcp_packet_via_tun (&state->specifics.tcp_udp.ri.remote_address,
1861 &state->specifics.tcp_udp.ri.local_address,
1863 &start[1], pkt_len);
1869 * Process a request to forward TCP data to the Internet via this peer.
1871 * @param cls closure, NULL
1872 * @param tunnel connection to the other end
1873 * @param tunnel_ctx pointer to our 'struct TunnelState *'
1874 * @param sender who sent the message
1875 * @param message the actual message
1876 * @param atsi performance data for the connection
1877 * @return GNUNET_OK to keep the connection open,
1878 * GNUNET_SYSERR to close it (signal serious error)
1881 receive_tcp_remote (void *cls GNUNET_UNUSED, struct GNUNET_MESH_Tunnel *tunnel,
1882 void **tunnel_ctx GNUNET_UNUSED,
1883 const struct GNUNET_PeerIdentity *sender GNUNET_UNUSED,
1884 const struct GNUNET_MessageHeader *message,
1885 const struct GNUNET_ATS_Information *atsi GNUNET_UNUSED)
1887 struct TunnelState *state = *tunnel_ctx;
1888 const struct GNUNET_EXIT_TcpInternetStartMessage *start;
1889 uint16_t pkt_len = ntohs (message->size);
1890 const struct in_addr *v4;
1891 const struct in6_addr *v6;
1892 const void *payload;
1895 if (GNUNET_YES == state->is_dns)
1897 GNUNET_break_op (0);
1898 return GNUNET_SYSERR;
1900 if (GNUNET_SYSERR == state->is_dns)
1902 /* tunnel is UDP/TCP from now on */
1903 state->is_dns = GNUNET_NO;
1905 GNUNET_STATISTICS_update (stats,
1906 gettext_noop ("# Bytes received from MESH"),
1907 pkt_len, GNUNET_NO);
1908 GNUNET_STATISTICS_update (stats,
1909 gettext_noop ("# TCP IP-exit creation requests received via mesh"),
1911 if (pkt_len < sizeof (struct GNUNET_EXIT_TcpInternetStartMessage))
1913 GNUNET_break_op (0);
1914 return GNUNET_SYSERR;
1916 start = (const struct GNUNET_EXIT_TcpInternetStartMessage*) message;
1917 pkt_len -= sizeof (struct GNUNET_EXIT_TcpInternetStartMessage);
1918 if ( (NULL == state) ||
1919 (NULL != state->specifics.tcp_udp.serv) ||
1920 (NULL != state->specifics.tcp_udp.heap_node) )
1922 GNUNET_break_op (0);
1923 return GNUNET_SYSERR;
1925 if (start->tcp_header.off * 4 < sizeof (struct GNUNET_TUN_TcpHeader))
1927 GNUNET_break_op (0);
1928 return GNUNET_SYSERR;
1930 af = (int) ntohl (start->af);
1931 state->specifics.tcp_udp.ri.remote_address.af = af;
1935 if (pkt_len < sizeof (struct in_addr))
1937 GNUNET_break_op (0);
1938 return GNUNET_SYSERR;
1942 GNUNET_break_op (0);
1943 return GNUNET_SYSERR;
1945 v4 = (const struct in_addr*) &start[1];
1947 pkt_len -= sizeof (struct in_addr);
1948 state->specifics.tcp_udp.ri.remote_address.address.ipv4 = *v4;
1951 if (pkt_len < sizeof (struct in6_addr))
1953 GNUNET_break_op (0);
1954 return GNUNET_SYSERR;
1958 GNUNET_break_op (0);
1959 return GNUNET_SYSERR;
1961 v6 = (const struct in6_addr*) &start[1];
1963 pkt_len -= sizeof (struct in6_addr);
1964 state->specifics.tcp_udp.ri.remote_address.address.ipv6 = *v6;
1967 GNUNET_break_op (0);
1968 return GNUNET_SYSERR;
1971 char buf[INET6_ADDRSTRLEN];
1972 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1973 "Received data from %s for starting TCP stream to %s:%u\n",
1974 GNUNET_i2s (sender),
1976 &state->specifics.tcp_udp.ri.remote_address.address,
1978 (unsigned int) ntohs (start->tcp_header.destination_port));
1980 state->specifics.tcp_udp.ri.remote_address.proto = IPPROTO_TCP;
1981 state->specifics.tcp_udp.ri.remote_address.port = ntohs (start->tcp_header.destination_port);
1982 setup_state_record (state);
1983 send_tcp_packet_via_tun (&state->specifics.tcp_udp.ri.remote_address,
1984 &state->specifics.tcp_udp.ri.local_address,
1992 * Process a request to forward TCP data on an established
1993 * connection via this peer.
1995 * @param cls closure, NULL
1996 * @param tunnel connection to the other end
1997 * @param tunnel_ctx pointer to our 'struct TunnelState *'
1998 * @param sender who sent the message
1999 * @param message the actual message
2000 * @param atsi performance data for the connection
2001 * @return GNUNET_OK to keep the connection open,
2002 * GNUNET_SYSERR to close it (signal serious error)
2005 receive_tcp_data (void *cls GNUNET_UNUSED, struct GNUNET_MESH_Tunnel *tunnel,
2006 void **tunnel_ctx GNUNET_UNUSED,
2007 const struct GNUNET_PeerIdentity *sender GNUNET_UNUSED,
2008 const struct GNUNET_MessageHeader *message,
2009 const struct GNUNET_ATS_Information *atsi GNUNET_UNUSED)
2011 struct TunnelState *state = *tunnel_ctx;
2012 const struct GNUNET_EXIT_TcpDataMessage *data;
2013 uint16_t pkt_len = ntohs (message->size);
2015 if (GNUNET_YES == state->is_dns)
2017 GNUNET_break_op (0);
2018 return GNUNET_SYSERR;
2020 if (GNUNET_SYSERR == state->is_dns)
2022 /* tunnel is UDP/TCP from now on */
2023 state->is_dns = GNUNET_NO;
2025 GNUNET_STATISTICS_update (stats,
2026 gettext_noop ("# Bytes received from MESH"),
2027 pkt_len, GNUNET_NO);
2028 GNUNET_STATISTICS_update (stats,
2029 gettext_noop ("# TCP data requests received via mesh"),
2031 if (pkt_len < sizeof (struct GNUNET_EXIT_TcpDataMessage))
2033 GNUNET_break_op (0);
2034 return GNUNET_SYSERR;
2036 data = (const struct GNUNET_EXIT_TcpDataMessage*) message;
2037 pkt_len -= sizeof (struct GNUNET_EXIT_TcpDataMessage);
2038 if ( (NULL == state) ||
2039 (NULL == state->specifics.tcp_udp.heap_node) )
2041 /* connection should have been up! */
2042 GNUNET_STATISTICS_update (stats,
2043 gettext_noop ("# TCP DATA requests dropped (no session)"),
2045 return GNUNET_SYSERR;
2047 if (data->tcp_header.off * 4 < sizeof (struct GNUNET_TUN_TcpHeader))
2049 GNUNET_break_op (0);
2050 return GNUNET_SYSERR;
2053 GNUNET_break_op (ntohl (data->reserved) == 0);
2055 char buf[INET6_ADDRSTRLEN];
2056 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2057 "Received additional %u bytes of data from %s for TCP stream to %s:%u\n",
2059 GNUNET_i2s (sender),
2060 inet_ntop (state->specifics.tcp_udp.ri.remote_address.af,
2061 &state->specifics.tcp_udp.ri.remote_address.address,
2063 (unsigned int) state->specifics.tcp_udp.ri.remote_address.port);
2066 send_tcp_packet_via_tun (&state->specifics.tcp_udp.ri.remote_address,
2067 &state->specifics.tcp_udp.ri.local_address,
2075 * Send an ICMP packet via the TUN interface.
2077 * @param destination_address IP to use for the ICMP packet's destination
2078 * @param source_address IP to use for the ICMP packet's source
2079 * @param icmp_header ICMP header to send
2080 * @param payload payload of the ICMP packet (does NOT include ICMP header)
2081 * @param payload_length number of bytes of data in payload
2084 send_icmp_packet_via_tun (const struct SocketAddress *destination_address,
2085 const struct SocketAddress *source_address,
2086 const struct GNUNET_TUN_IcmpHeader *icmp_header,
2087 const void *payload, size_t payload_length)
2090 struct GNUNET_TUN_IcmpHeader *icmp;
2092 GNUNET_STATISTICS_update (stats,
2093 gettext_noop ("# ICMP packets sent via TUN"),
2095 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2096 "Sending packet with %u bytes ICMP payload via TUN\n",
2097 (unsigned int) payload_length);
2098 len = sizeof (struct GNUNET_MessageHeader) + sizeof (struct GNUNET_TUN_Layer2PacketHeader);
2099 switch (destination_address->af)
2102 len += sizeof (struct GNUNET_TUN_IPv4Header);
2105 len += sizeof (struct GNUNET_TUN_IPv6Header);
2111 len += sizeof (struct GNUNET_TUN_IcmpHeader);
2112 len += payload_length;
2113 if (len >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
2119 char buf[len] GNUNET_ALIGN;
2120 struct GNUNET_MessageHeader *hdr;
2121 struct GNUNET_TUN_Layer2PacketHeader *tun;
2123 hdr= (struct GNUNET_MessageHeader *) buf;
2124 hdr->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
2125 hdr->size = htons (len);
2126 tun = (struct GNUNET_TUN_Layer2PacketHeader*) &hdr[1];
2127 tun->flags = htons (0);
2128 switch (source_address->af)
2132 struct GNUNET_TUN_IPv4Header * ipv4 = (struct GNUNET_TUN_IPv4Header*) &tun[1];
2134 tun->proto = htons (ETH_P_IPV4);
2135 GNUNET_TUN_initialize_ipv4_header (ipv4,
2137 sizeof (struct GNUNET_TUN_IcmpHeader) + payload_length,
2138 &source_address->address.ipv4,
2139 &destination_address->address.ipv4);
2140 icmp = (struct GNUNET_TUN_IcmpHeader*) &ipv4[1];
2145 struct GNUNET_TUN_IPv6Header * ipv6 = (struct GNUNET_TUN_IPv6Header*) &tun[1];
2147 tun->proto = htons (ETH_P_IPV6);
2148 GNUNET_TUN_initialize_ipv6_header (ipv6,
2150 sizeof (struct GNUNET_TUN_IcmpHeader) + payload_length,
2151 &source_address->address.ipv6,
2152 &destination_address->address.ipv6);
2153 icmp = (struct GNUNET_TUN_IcmpHeader*) &ipv6[1];
2160 *icmp = *icmp_header;
2164 GNUNET_TUN_calculate_icmp_checksum (icmp,
2167 if (NULL != helper_handle)
2168 (void) GNUNET_HELPER_send (helper_handle,
2169 (const struct GNUNET_MessageHeader*) buf,
2177 * Synthesize a plausible ICMP payload for an ICMPv4 error
2178 * response on the given tunnel.
2180 * @param state tunnel information
2181 * @param ipp IPv6 header to fill in (ICMP payload)
2182 * @param udp "UDP" header to fill in (ICMP payload); might actually
2183 * also be the first 8 bytes of the TCP header
2186 make_up_icmpv4_payload (struct TunnelState *state,
2187 struct GNUNET_TUN_IPv4Header *ipp,
2188 struct GNUNET_TUN_UdpHeader *udp)
2190 GNUNET_TUN_initialize_ipv4_header (ipp,
2191 state->specifics.tcp_udp.ri.remote_address.proto,
2192 sizeof (struct GNUNET_TUN_TcpHeader),
2193 &state->specifics.tcp_udp.ri.remote_address.address.ipv4,
2194 &state->specifics.tcp_udp.ri.local_address.address.ipv4);
2195 udp->source_port = htons (state->specifics.tcp_udp.ri.remote_address.port);
2196 udp->destination_port = htons (state->specifics.tcp_udp.ri.local_address.port);
2197 udp->len = htons (0);
2198 udp->crc = htons (0);
2203 * Synthesize a plausible ICMP payload for an ICMPv6 error
2204 * response on the given tunnel.
2206 * @param state tunnel information
2207 * @param ipp IPv6 header to fill in (ICMP payload)
2208 * @param udp "UDP" header to fill in (ICMP payload); might actually
2209 * also be the first 8 bytes of the TCP header
2212 make_up_icmpv6_payload (struct TunnelState *state,
2213 struct GNUNET_TUN_IPv6Header *ipp,
2214 struct GNUNET_TUN_UdpHeader *udp)
2216 GNUNET_TUN_initialize_ipv6_header (ipp,
2217 state->specifics.tcp_udp.ri.remote_address.proto,
2218 sizeof (struct GNUNET_TUN_TcpHeader),
2219 &state->specifics.tcp_udp.ri.remote_address.address.ipv6,
2220 &state->specifics.tcp_udp.ri.local_address.address.ipv6);
2221 udp->source_port = htons (state->specifics.tcp_udp.ri.remote_address.port);
2222 udp->destination_port = htons (state->specifics.tcp_udp.ri.local_address.port);
2223 udp->len = htons (0);
2224 udp->crc = htons (0);
2229 * Process a request to forward ICMP data to the Internet via this peer.
2231 * @param cls closure, NULL
2232 * @param tunnel connection to the other end
2233 * @param tunnel_ctx pointer to our 'struct TunnelState *'
2234 * @param sender who sent the message
2235 * @param message the actual message
2236 * @param atsi performance data for the connection
2237 * @return GNUNET_OK to keep the connection open,
2238 * GNUNET_SYSERR to close it (signal serious error)
2241 receive_icmp_remote (void *cls GNUNET_UNUSED, struct GNUNET_MESH_Tunnel *tunnel,
2242 void **tunnel_ctx GNUNET_UNUSED,
2243 const struct GNUNET_PeerIdentity *sender GNUNET_UNUSED,
2244 const struct GNUNET_MessageHeader *message,
2245 const struct GNUNET_ATS_Information *atsi GNUNET_UNUSED)
2247 struct TunnelState *state = *tunnel_ctx;
2248 const struct GNUNET_EXIT_IcmpInternetMessage *msg;
2249 uint16_t pkt_len = ntohs (message->size);
2250 const struct in_addr *v4;
2251 const struct in6_addr *v6;
2252 const void *payload;
2253 char buf[sizeof (struct GNUNET_TUN_IPv6Header) + 8] GNUNET_ALIGN;
2256 if (GNUNET_YES == state->is_dns)
2258 GNUNET_break_op (0);
2259 return GNUNET_SYSERR;
2261 if (GNUNET_SYSERR == state->is_dns)
2263 /* tunnel is UDP/TCP from now on */
2264 state->is_dns = GNUNET_NO;
2266 GNUNET_STATISTICS_update (stats,
2267 gettext_noop ("# Bytes received from MESH"),
2268 pkt_len, GNUNET_NO);
2269 GNUNET_STATISTICS_update (stats,
2270 gettext_noop ("# ICMP IP-exit requests received via mesh"),
2272 if (pkt_len < sizeof (struct GNUNET_EXIT_IcmpInternetMessage))
2274 GNUNET_break_op (0);
2275 return GNUNET_SYSERR;
2277 msg = (const struct GNUNET_EXIT_IcmpInternetMessage*) message;
2278 pkt_len -= sizeof (struct GNUNET_EXIT_IcmpInternetMessage);
2280 af = (int) ntohl (msg->af);
2281 if ( (NULL != state->specifics.tcp_udp.heap_node) &&
2282 (af != state->specifics.tcp_udp.ri.remote_address.af) )
2284 /* other peer switched AF on this tunnel; not allowed */
2285 GNUNET_break_op (0);
2286 return GNUNET_SYSERR;
2292 if (pkt_len < sizeof (struct in_addr))
2294 GNUNET_break_op (0);
2295 return GNUNET_SYSERR;
2299 GNUNET_break_op (0);
2300 return GNUNET_SYSERR;
2302 v4 = (const struct in_addr*) &msg[1];
2304 pkt_len -= sizeof (struct in_addr);
2305 state->specifics.tcp_udp.ri.remote_address.address.ipv4 = *v4;
2306 if (NULL == state->specifics.tcp_udp.heap_node)
2308 state->specifics.tcp_udp.ri.remote_address.af = af;
2309 state->specifics.tcp_udp.ri.remote_address.proto = IPPROTO_ICMP;
2310 setup_state_record (state);
2312 /* check that ICMP type is something we want to support
2313 and possibly make up payload! */
2314 switch (msg->icmp_header.type)
2316 case GNUNET_TUN_ICMPTYPE_ECHO_REPLY:
2317 case GNUNET_TUN_ICMPTYPE_ECHO_REQUEST:
2319 case GNUNET_TUN_ICMPTYPE_DESTINATION_UNREACHABLE:
2320 case GNUNET_TUN_ICMPTYPE_SOURCE_QUENCH:
2321 case GNUNET_TUN_ICMPTYPE_TIME_EXCEEDED:
2324 GNUNET_break_op (0);
2325 return GNUNET_SYSERR;
2327 /* make up payload */
2329 struct GNUNET_TUN_IPv4Header *ipp = (struct GNUNET_TUN_IPv4Header *) buf;
2330 struct GNUNET_TUN_UdpHeader *udp = (struct GNUNET_TUN_UdpHeader *) &ipp[1];
2332 GNUNET_assert (8 == sizeof (struct GNUNET_TUN_UdpHeader));
2333 pkt_len = sizeof (struct GNUNET_TUN_IPv4Header) + 8;
2334 make_up_icmpv4_payload (state,
2341 GNUNET_break_op (0);
2342 GNUNET_STATISTICS_update (stats,
2343 gettext_noop ("# ICMPv4 packets dropped (type not allowed)"),
2345 return GNUNET_SYSERR;
2350 if (pkt_len < sizeof (struct in6_addr))
2352 GNUNET_break_op (0);
2353 return GNUNET_SYSERR;
2357 GNUNET_break_op (0);
2358 return GNUNET_SYSERR;
2360 v6 = (const struct in6_addr*) &msg[1];
2362 pkt_len -= sizeof (struct in6_addr);
2363 state->specifics.tcp_udp.ri.remote_address.address.ipv6 = *v6;
2364 if (NULL == state->specifics.tcp_udp.heap_node)
2366 state->specifics.tcp_udp.ri.remote_address.af = af;
2367 state->specifics.tcp_udp.ri.remote_address.proto = IPPROTO_ICMPV6;
2368 setup_state_record (state);
2370 /* check that ICMP type is something we want to support
2371 and possibly make up payload! */
2372 switch (msg->icmp_header.type)
2374 case GNUNET_TUN_ICMPTYPE6_ECHO_REPLY:
2375 case GNUNET_TUN_ICMPTYPE6_ECHO_REQUEST:
2377 case GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE:
2378 case GNUNET_TUN_ICMPTYPE6_PACKET_TOO_BIG:
2379 case GNUNET_TUN_ICMPTYPE6_TIME_EXCEEDED:
2380 case GNUNET_TUN_ICMPTYPE6_PARAMETER_PROBLEM:
2383 GNUNET_break_op (0);
2384 return GNUNET_SYSERR;
2386 /* make up payload */
2388 struct GNUNET_TUN_IPv6Header *ipp = (struct GNUNET_TUN_IPv6Header *) buf;
2389 struct GNUNET_TUN_UdpHeader *udp = (struct GNUNET_TUN_UdpHeader *) &ipp[1];
2391 GNUNET_assert (8 == sizeof (struct GNUNET_TUN_UdpHeader));
2392 pkt_len = sizeof (struct GNUNET_TUN_IPv6Header) + 8;
2393 make_up_icmpv6_payload (state,
2400 GNUNET_break_op (0);
2401 GNUNET_STATISTICS_update (stats,
2402 gettext_noop ("# ICMPv6 packets dropped (type not allowed)"),
2404 return GNUNET_SYSERR;
2410 GNUNET_break_op (0);
2411 return GNUNET_SYSERR;
2415 char buf[INET6_ADDRSTRLEN];
2416 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2417 "Received ICMP data from %s for forwarding to %s\n",
2418 GNUNET_i2s (sender),
2420 &state->specifics.tcp_udp.ri.remote_address.address,
2421 buf, sizeof (buf)));
2423 send_icmp_packet_via_tun (&state->specifics.tcp_udp.ri.remote_address,
2424 &state->specifics.tcp_udp.ri.local_address,
2432 * Setup ICMP payload for ICMP error messages. Called
2433 * for both IPv4 and IPv6 addresses.
2435 * @param state context for creating the IP Packet
2436 * @param buf where to create the payload, has at least
2437 * sizeof (struct GNUNET_TUN_IPv6Header) + 8 bytes
2438 * @return number of bytes of payload we created in buf
2441 make_up_icmp_service_payload (struct TunnelState *state,
2444 switch (state->specifics.tcp_udp.serv->address.af)
2448 struct GNUNET_TUN_IPv4Header *ipv4;
2449 struct GNUNET_TUN_UdpHeader *udp;
2451 ipv4 = (struct GNUNET_TUN_IPv4Header *)buf;
2452 udp = (struct GNUNET_TUN_UdpHeader *) &ipv4[1];
2453 make_up_icmpv4_payload (state,
2456 GNUNET_assert (8 == sizeof (struct GNUNET_TUN_UdpHeader));
2457 return sizeof (struct GNUNET_TUN_IPv4Header) + 8;
2462 struct GNUNET_TUN_IPv6Header *ipv6;
2463 struct GNUNET_TUN_UdpHeader *udp;
2465 ipv6 = (struct GNUNET_TUN_IPv6Header *)buf;
2466 udp = (struct GNUNET_TUN_UdpHeader *) &ipv6[1];
2467 make_up_icmpv6_payload (state,
2470 GNUNET_assert (8 == sizeof (struct GNUNET_TUN_UdpHeader));
2471 return sizeof (struct GNUNET_TUN_IPv6Header) + 8;
2482 * Process a request via mesh to send ICMP data to a service
2483 * offered by this system.
2485 * @param cls closure, NULL
2486 * @param tunnel connection to the other end
2487 * @param tunnel_ctx pointer to our 'struct TunnelState *'
2488 * @param sender who sent the message
2489 * @param message the actual message
2490 * @param atsi performance data for the connection
2491 * @return GNUNET_OK to keep the connection open,
2492 * GNUNET_SYSERR to close it (signal serious error)
2495 receive_icmp_service (void *cls GNUNET_UNUSED, struct GNUNET_MESH_Tunnel *tunnel,
2497 const struct GNUNET_PeerIdentity *sender GNUNET_UNUSED,
2498 const struct GNUNET_MessageHeader *message,
2499 const struct GNUNET_ATS_Information *atsi GNUNET_UNUSED)
2501 struct TunnelState *state = *tunnel_ctx;
2502 const struct GNUNET_EXIT_IcmpServiceMessage *msg;
2503 uint16_t pkt_len = ntohs (message->size);
2504 struct GNUNET_TUN_IcmpHeader icmp;
2505 char buf[sizeof (struct GNUNET_TUN_IPv6Header) + 8] GNUNET_ALIGN;
2506 const void *payload;
2508 if (GNUNET_YES == state->is_dns)
2510 GNUNET_break_op (0);
2511 return GNUNET_SYSERR;
2513 if (GNUNET_SYSERR == state->is_dns)
2515 /* tunnel is UDP/TCP from now on */
2516 state->is_dns = GNUNET_NO;
2518 GNUNET_STATISTICS_update (stats,
2519 gettext_noop ("# Bytes received from MESH"),
2520 pkt_len, GNUNET_NO);
2521 GNUNET_STATISTICS_update (stats,
2522 gettext_noop ("# ICMP service requests received via mesh"),
2524 /* check that we got at least a valid header */
2525 if (pkt_len < sizeof (struct GNUNET_EXIT_IcmpServiceMessage))
2527 GNUNET_break_op (0);
2528 return GNUNET_SYSERR;
2530 msg = (const struct GNUNET_EXIT_IcmpServiceMessage*) message;
2531 pkt_len -= sizeof (struct GNUNET_EXIT_IcmpServiceMessage);
2532 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2533 "Received data from %s for forwarding to ICMP service %s\n",
2534 GNUNET_i2s (sender),
2535 GNUNET_h2s (&msg->service_descriptor));
2536 if (NULL == state->specifics.tcp_udp.serv)
2538 /* first packet to service must not be ICMP (cannot determine service!) */
2539 GNUNET_break_op (0);
2540 return GNUNET_SYSERR;
2542 icmp = msg->icmp_header;
2544 state->specifics.tcp_udp.ri.remote_address = state->specifics.tcp_udp.serv->address;
2545 setup_state_record (state);
2547 /* check that ICMP type is something we want to support,
2548 perform ICMP PT if needed ans possibly make up payload */
2552 switch (msg->icmp_header.type)
2554 case GNUNET_TUN_ICMPTYPE_ECHO_REPLY:
2555 if (state->specifics.tcp_udp.serv->address.af == AF_INET6)
2556 icmp.type = GNUNET_TUN_ICMPTYPE6_ECHO_REPLY;
2558 case GNUNET_TUN_ICMPTYPE_ECHO_REQUEST:
2559 if (state->specifics.tcp_udp.serv->address.af == AF_INET6)
2560 icmp.type = GNUNET_TUN_ICMPTYPE6_ECHO_REQUEST;
2562 case GNUNET_TUN_ICMPTYPE_DESTINATION_UNREACHABLE:
2563 if (state->specifics.tcp_udp.serv->address.af == AF_INET6)
2564 icmp.type = GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE;
2567 GNUNET_break_op (0);
2568 return GNUNET_SYSERR;
2571 pkt_len = make_up_icmp_service_payload (state, buf);
2573 case GNUNET_TUN_ICMPTYPE_TIME_EXCEEDED:
2574 if (state->specifics.tcp_udp.serv->address.af == AF_INET6)
2575 icmp.type = GNUNET_TUN_ICMPTYPE6_TIME_EXCEEDED;
2578 GNUNET_break_op (0);
2579 return GNUNET_SYSERR;
2582 pkt_len = make_up_icmp_service_payload (state, buf);
2584 case GNUNET_TUN_ICMPTYPE_SOURCE_QUENCH:
2585 if (state->specifics.tcp_udp.serv->address.af == AF_INET6)
2587 GNUNET_STATISTICS_update (stats,
2588 gettext_noop ("# ICMPv4 packets dropped (impossible PT to v6)"),
2594 GNUNET_break_op (0);
2595 return GNUNET_SYSERR;
2598 pkt_len = make_up_icmp_service_payload (state, buf);
2601 GNUNET_break_op (0);
2602 GNUNET_STATISTICS_update (stats,
2603 gettext_noop ("# ICMPv4 packets dropped (type not allowed)"),
2605 return GNUNET_SYSERR;
2607 /* end of AF_INET */
2610 switch (msg->icmp_header.type)
2612 case GNUNET_TUN_ICMPTYPE6_ECHO_REPLY:
2613 if (state->specifics.tcp_udp.serv->address.af == AF_INET)
2614 icmp.type = GNUNET_TUN_ICMPTYPE_ECHO_REPLY;
2616 case GNUNET_TUN_ICMPTYPE6_ECHO_REQUEST:
2617 if (state->specifics.tcp_udp.serv->address.af == AF_INET)
2618 icmp.type = GNUNET_TUN_ICMPTYPE_ECHO_REQUEST;
2620 case GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE:
2621 if (state->specifics.tcp_udp.serv->address.af == AF_INET)
2622 icmp.type = GNUNET_TUN_ICMPTYPE_DESTINATION_UNREACHABLE;
2625 GNUNET_break_op (0);
2626 return GNUNET_SYSERR;
2629 pkt_len = make_up_icmp_service_payload (state, buf);
2631 case GNUNET_TUN_ICMPTYPE6_TIME_EXCEEDED:
2632 if (state->specifics.tcp_udp.serv->address.af == AF_INET)
2633 icmp.type = GNUNET_TUN_ICMPTYPE_TIME_EXCEEDED;
2636 GNUNET_break_op (0);
2637 return GNUNET_SYSERR;
2640 pkt_len = make_up_icmp_service_payload (state, buf);
2642 case GNUNET_TUN_ICMPTYPE6_PACKET_TOO_BIG:
2643 case GNUNET_TUN_ICMPTYPE6_PARAMETER_PROBLEM:
2644 if (state->specifics.tcp_udp.serv->address.af == AF_INET)
2646 GNUNET_STATISTICS_update (stats,
2647 gettext_noop ("# ICMPv6 packets dropped (impossible PT to v4)"),
2653 GNUNET_break_op (0);
2654 return GNUNET_SYSERR;
2657 pkt_len = make_up_icmp_service_payload (state, buf);
2660 GNUNET_break_op (0);
2661 GNUNET_STATISTICS_update (stats,
2662 gettext_noop ("# ICMPv6 packets dropped (type not allowed)"),
2664 return GNUNET_SYSERR;
2666 /* end of AF_INET6 */
2669 GNUNET_break_op (0);
2670 return GNUNET_SYSERR;
2673 send_icmp_packet_via_tun (&state->specifics.tcp_udp.ri.remote_address,
2674 &state->specifics.tcp_udp.ri.local_address,
2682 * Send a UDP packet via the TUN interface.
2684 * @param destination_address IP and port to use for the UDP packet's destination
2685 * @param source_address IP and port to use for the UDP packet's source
2686 * @param payload payload of the UDP packet (does NOT include UDP header)
2687 * @param payload_length number of bytes of data in payload
2690 send_udp_packet_via_tun (const struct SocketAddress *destination_address,
2691 const struct SocketAddress *source_address,
2692 const void *payload, size_t payload_length)
2696 GNUNET_STATISTICS_update (stats,
2697 gettext_noop ("# UDP packets sent via TUN"),
2699 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2700 "Sending packet with %u bytes UDP payload via TUN\n",
2701 (unsigned int) payload_length);
2702 len = sizeof (struct GNUNET_MessageHeader) + sizeof (struct GNUNET_TUN_Layer2PacketHeader);
2703 switch (source_address->af)
2706 len += sizeof (struct GNUNET_TUN_IPv4Header);
2709 len += sizeof (struct GNUNET_TUN_IPv6Header);
2715 len += sizeof (struct GNUNET_TUN_UdpHeader);
2716 len += payload_length;
2717 if (len >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
2723 char buf[len] GNUNET_ALIGN;
2724 struct GNUNET_MessageHeader *hdr;
2725 struct GNUNET_TUN_Layer2PacketHeader *tun;
2727 hdr= (struct GNUNET_MessageHeader *) buf;
2728 hdr->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
2729 hdr->size = htons (len);
2730 tun = (struct GNUNET_TUN_Layer2PacketHeader*) &hdr[1];
2731 tun->flags = htons (0);
2732 switch (source_address->af)
2736 struct GNUNET_TUN_IPv4Header * ipv4 = (struct GNUNET_TUN_IPv4Header*) &tun[1];
2738 tun->proto = htons (ETH_P_IPV4);
2739 prepare_ipv4_packet (payload, payload_length,
2743 destination_address,
2749 struct GNUNET_TUN_IPv6Header * ipv6 = (struct GNUNET_TUN_IPv6Header*) &tun[1];
2751 tun->proto = htons (ETH_P_IPV6);
2752 prepare_ipv6_packet (payload, payload_length,
2756 destination_address,
2764 if (NULL != helper_handle)
2765 (void) GNUNET_HELPER_send (helper_handle,
2766 (const struct GNUNET_MessageHeader*) buf,
2774 * Process a request to forward UDP data to the Internet via this peer.
2776 * @param cls closure, NULL
2777 * @param tunnel connection to the other end
2778 * @param tunnel_ctx pointer to our 'struct TunnelState *'
2779 * @param sender who sent the message
2780 * @param message the actual message
2781 * @param atsi performance data for the connection
2782 * @return GNUNET_OK to keep the connection open,
2783 * GNUNET_SYSERR to close it (signal serious error)
2786 receive_udp_remote (void *cls GNUNET_UNUSED, struct GNUNET_MESH_Tunnel *tunnel,
2787 void **tunnel_ctx GNUNET_UNUSED,
2788 const struct GNUNET_PeerIdentity *sender GNUNET_UNUSED,
2789 const struct GNUNET_MessageHeader *message,
2790 const struct GNUNET_ATS_Information *atsi GNUNET_UNUSED)
2792 struct TunnelState *state = *tunnel_ctx;
2793 const struct GNUNET_EXIT_UdpInternetMessage *msg;
2794 uint16_t pkt_len = ntohs (message->size);
2795 const struct in_addr *v4;
2796 const struct in6_addr *v6;
2797 const void *payload;
2800 if (GNUNET_YES == state->is_dns)
2802 GNUNET_break_op (0);
2803 return GNUNET_SYSERR;
2805 if (GNUNET_SYSERR == state->is_dns)
2807 /* tunnel is UDP/TCP from now on */
2808 state->is_dns = GNUNET_NO;
2810 GNUNET_STATISTICS_update (stats,
2811 gettext_noop ("# Bytes received from MESH"),
2812 pkt_len, GNUNET_NO);
2813 GNUNET_STATISTICS_update (stats,
2814 gettext_noop ("# UDP IP-exit requests received via mesh"),
2816 if (pkt_len < sizeof (struct GNUNET_EXIT_UdpInternetMessage))
2818 GNUNET_break_op (0);
2819 return GNUNET_SYSERR;
2821 msg = (const struct GNUNET_EXIT_UdpInternetMessage*) message;
2822 pkt_len -= sizeof (struct GNUNET_EXIT_UdpInternetMessage);
2823 af = (int) ntohl (msg->af);
2824 state->specifics.tcp_udp.ri.remote_address.af = af;
2828 if (pkt_len < sizeof (struct in_addr))
2830 GNUNET_break_op (0);
2831 return GNUNET_SYSERR;
2835 GNUNET_break_op (0);
2836 return GNUNET_SYSERR;
2838 v4 = (const struct in_addr*) &msg[1];
2840 pkt_len -= sizeof (struct in_addr);
2841 state->specifics.tcp_udp.ri.remote_address.address.ipv4 = *v4;
2844 if (pkt_len < sizeof (struct in6_addr))
2846 GNUNET_break_op (0);
2847 return GNUNET_SYSERR;
2851 GNUNET_break_op (0);
2852 return GNUNET_SYSERR;
2854 v6 = (const struct in6_addr*) &msg[1];
2856 pkt_len -= sizeof (struct in6_addr);
2857 state->specifics.tcp_udp.ri.remote_address.address.ipv6 = *v6;
2860 GNUNET_break_op (0);
2861 return GNUNET_SYSERR;
2864 char buf[INET6_ADDRSTRLEN];
2865 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2866 "Received data from %s for forwarding to UDP %s:%u\n",
2867 GNUNET_i2s (sender),
2869 &state->specifics.tcp_udp.ri.remote_address.address,
2871 (unsigned int) ntohs (msg->destination_port));
2873 state->specifics.tcp_udp.ri.remote_address.proto = IPPROTO_UDP;
2874 state->specifics.tcp_udp.ri.remote_address.port = msg->destination_port;
2875 if (NULL == state->specifics.tcp_udp.heap_node)
2876 setup_state_record (state);
2877 if (0 != ntohs (msg->source_port))
2878 state->specifics.tcp_udp.ri.local_address.port = msg->source_port;
2879 send_udp_packet_via_tun (&state->specifics.tcp_udp.ri.remote_address,
2880 &state->specifics.tcp_udp.ri.local_address,
2887 * Process a request via mesh to send a request to a UDP service
2888 * offered by this system.
2890 * @param cls closure, NULL
2891 * @param tunnel connection to the other end
2892 * @param tunnel_ctx pointer to our 'struct TunnelState *'
2893 * @param sender who sent the message
2894 * @param message the actual message
2895 * @param atsi performance data for the connection
2896 * @return GNUNET_OK to keep the connection open,
2897 * GNUNET_SYSERR to close it (signal serious error)
2900 receive_udp_service (void *cls GNUNET_UNUSED, struct GNUNET_MESH_Tunnel *tunnel,
2902 const struct GNUNET_PeerIdentity *sender GNUNET_UNUSED,
2903 const struct GNUNET_MessageHeader *message,
2904 const struct GNUNET_ATS_Information *atsi GNUNET_UNUSED)
2906 struct TunnelState *state = *tunnel_ctx;
2907 const struct GNUNET_EXIT_UdpServiceMessage *msg;
2908 uint16_t pkt_len = ntohs (message->size);
2910 if (GNUNET_YES == state->is_dns)
2912 GNUNET_break_op (0);
2913 return GNUNET_SYSERR;
2915 if (GNUNET_SYSERR == state->is_dns)
2917 /* tunnel is UDP/TCP from now on */
2918 state->is_dns = GNUNET_NO;
2920 GNUNET_STATISTICS_update (stats,
2921 gettext_noop ("# Bytes received from MESH"),
2922 pkt_len, GNUNET_NO);
2923 GNUNET_STATISTICS_update (stats,
2924 gettext_noop ("# UDP service requests received via mesh"),
2926 /* check that we got at least a valid header */
2927 if (pkt_len < sizeof (struct GNUNET_EXIT_UdpServiceMessage))
2929 GNUNET_break_op (0);
2930 return GNUNET_SYSERR;
2932 msg = (const struct GNUNET_EXIT_UdpServiceMessage*) message;
2933 pkt_len -= sizeof (struct GNUNET_EXIT_UdpServiceMessage);
2934 LOG (GNUNET_ERROR_TYPE_DEBUG,
2935 "Received data from %s for forwarding to UDP service %s on port %u\n",
2936 GNUNET_i2s (sender),
2937 GNUNET_h2s (&msg->service_descriptor),
2938 (unsigned int) ntohs (msg->destination_port));
2939 if (NULL == (state->specifics.tcp_udp.serv = find_service (udp_services, &msg->service_descriptor,
2940 ntohs (msg->destination_port))))
2942 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
2943 _("No service found for %s on port %d!\n"),
2945 ntohs (msg->destination_port));
2946 GNUNET_STATISTICS_update (stats,
2947 gettext_noop ("# UDP requests dropped (no such service)"),
2949 return GNUNET_SYSERR;
2951 state->specifics.tcp_udp.ri.remote_address = state->specifics.tcp_udp.serv->address;
2952 setup_state_record (state);
2953 if (0 != ntohs (msg->source_port))
2954 state->specifics.tcp_udp.ri.local_address.port = msg->source_port;
2955 send_udp_packet_via_tun (&state->specifics.tcp_udp.ri.remote_address,
2956 &state->specifics.tcp_udp.ri.local_address,
2963 * Callback from GNUNET_MESH for new tunnels.
2965 * @param cls closure
2966 * @param tunnel new handle to the tunnel
2967 * @param initiator peer that started the tunnel
2968 * @param atsi performance information for the tunnel
2969 * @return initial tunnel context for the tunnel
2972 new_tunnel (void *cls GNUNET_UNUSED, struct GNUNET_MESH_Tunnel *tunnel,
2973 const struct GNUNET_PeerIdentity *initiator GNUNET_UNUSED,
2974 const struct GNUNET_ATS_Information *atsi GNUNET_UNUSED)
2976 struct TunnelState *s = GNUNET_malloc (sizeof (struct TunnelState));
2978 s->is_dns = GNUNET_SYSERR;
2979 GNUNET_STATISTICS_update (stats,
2980 gettext_noop ("# Inbound MESH tunnels created"),
2982 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2983 "Received inbound tunnel from `%s'\n",
2984 GNUNET_i2s (initiator));
2991 * Function called by mesh whenever an inbound tunnel is destroyed.
2992 * Should clean up any associated state.
2994 * @param cls closure (set from GNUNET_MESH_connect)
2995 * @param tunnel connection to the other end (henceforth invalid)
2996 * @param tunnel_ctx place where local state associated
2997 * with the tunnel is stored
3000 clean_tunnel (void *cls GNUNET_UNUSED, const struct GNUNET_MESH_Tunnel *tunnel,
3003 struct TunnelState *s = tunnel_ctx;
3004 struct TunnelMessageQueue *tnq;
3006 LOG (GNUNET_ERROR_TYPE_DEBUG,
3007 "Tunnel destroyed\n");
3008 if (GNUNET_SYSERR == s->is_dns)
3013 if (GNUNET_YES == s->is_dns)
3015 if (tunnels[s->specifics.dns.my_id] == s)
3016 tunnels[s->specifics.dns.my_id] = NULL;
3017 GNUNET_free_non_null (s->specifics.dns.reply);
3021 while (NULL != (tnq = s->specifics.tcp_udp.head))
3023 GNUNET_CONTAINER_DLL_remove (s->specifics.tcp_udp.head,
3024 s->specifics.tcp_udp.tail,
3028 if (NULL != s->specifics.tcp_udp.heap_node)
3030 GNUNET_assert (GNUNET_YES ==
3031 GNUNET_CONTAINER_multihashmap_remove (connections_map,
3032 &s->specifics.tcp_udp.state_key,
3034 GNUNET_CONTAINER_heap_remove_node (s->specifics.tcp_udp.heap_node);
3035 s->specifics.tcp_udp.heap_node = NULL;
3040 GNUNET_MESH_notify_transmit_ready_cancel (s->th);
3048 * Function that frees everything from a hashmap
3052 * @param value value to free
3055 free_iterate (void *cls GNUNET_UNUSED,
3056 const struct GNUNET_HashCode * hash GNUNET_UNUSED, void *value)
3058 GNUNET_free (value);
3064 * Function scheduled as very last function, cleans up after us
3067 cleanup (void *cls GNUNET_UNUSED,
3068 const struct GNUNET_SCHEDULER_TaskContext *tskctx)
3072 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3073 "Exit service is shutting down now\n");
3075 if (helper_handle != NULL)
3077 GNUNET_HELPER_stop (helper_handle, GNUNET_NO);
3078 helper_handle = NULL;
3080 if (mesh_handle != NULL)
3082 GNUNET_MESH_disconnect (mesh_handle);
3085 if (NULL != connections_map)
3087 GNUNET_CONTAINER_multihashmap_iterate (connections_map, &free_iterate, NULL);
3088 GNUNET_CONTAINER_multihashmap_destroy (connections_map);
3089 connections_map = NULL;
3091 if (NULL != connections_heap)
3093 GNUNET_CONTAINER_heap_destroy (connections_heap);
3094 connections_heap = NULL;
3096 if (NULL != tcp_services)
3098 GNUNET_CONTAINER_multihashmap_iterate (tcp_services, &free_service_record, NULL);
3099 GNUNET_CONTAINER_multihashmap_destroy (tcp_services);
3100 tcp_services = NULL;
3102 if (NULL != udp_services)
3104 GNUNET_CONTAINER_multihashmap_iterate (udp_services, &free_service_record, NULL);
3105 GNUNET_CONTAINER_multihashmap_destroy (udp_services);
3106 udp_services = NULL;
3108 if (NULL != dnsstub)
3110 GNUNET_DNSSTUB_stop (dnsstub);
3115 GNUNET_STATISTICS_destroy (stats, GNUNET_NO);
3119 GNUNET_free_non_null (exit_argv[i]);
3124 * Add services to the service map.
3126 * @param proto IPPROTO_TCP or IPPROTO_UDP
3127 * @param cpy copy of the service descriptor (can be mutilated)
3128 * @param name DNS name of the service
3131 add_services (int proto,
3138 struct LocalService *serv;
3140 for (redirect = strtok (cpy, " "); redirect != NULL;
3141 redirect = strtok (NULL, " "))
3143 if (NULL == (hostname = strstr (redirect, ":")))
3145 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
3146 "option `%s' for domain `%s' is not formatted correctly!\n",
3153 if (NULL == (hostport = strstr (hostname, ":")))
3155 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
3156 "option `%s' for domain `%s' is not formatted correctly!\n",
3164 int local_port = atoi (redirect);
3165 int remote_port = atoi (hostport);
3167 if (!((local_port > 0) && (local_port < 65536)))
3169 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
3170 "`%s' is not a valid port number (for domain `%s')!", redirect,
3174 if (!((remote_port > 0) && (remote_port < 65536)))
3176 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
3177 "`%s' is not a valid port number (for domain `%s')!", hostport,
3182 serv = GNUNET_malloc (sizeof (struct LocalService));
3183 serv->address.proto = proto;
3184 serv->my_port = (uint16_t) local_port;
3185 serv->address.port = remote_port;
3186 if (0 == strcmp ("localhost4", hostname))
3188 const char *ip4addr = exit_argv[5];
3190 serv->address.af = AF_INET;
3191 GNUNET_assert (1 == inet_pton (AF_INET, ip4addr, &serv->address.address.ipv4));
3193 else if (0 == strcmp ("localhost6", hostname))
3195 const char *ip6addr = exit_argv[3];
3197 serv->address.af = AF_INET6;
3198 GNUNET_assert (1 == inet_pton (AF_INET6, ip6addr, &serv->address.address.ipv6));
3202 struct addrinfo *res;
3205 ret = getaddrinfo (hostname, NULL, NULL, &res);
3206 if ( (ret != 0) || (res == NULL) )
3208 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
3209 _("No addresses found for hostname `%s' of service `%s'!\n"),
3216 serv->address.af = res->ai_family;
3217 switch (res->ai_family)
3222 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
3223 _("Service `%s' configured for IPv4, but IPv4 is disabled!\n"),
3229 serv->address.address.ipv4 = ((struct sockaddr_in *) res->ai_addr)->sin_addr;
3234 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
3235 _("Service `%s' configured for IPv4, but IPv4 is disabled!\n"),
3241 serv->address.address.ipv6 = ((struct sockaddr_in6 *) res->ai_addr)->sin6_addr;
3245 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
3246 _("No IP addresses found for hostname `%s' of service `%s'!\n"),
3254 store_service ((IPPROTO_UDP == proto) ? udp_services : tcp_services,
3263 * Reads the configuration servicecfg and populates udp_services
3266 * @param section name of section in config, equal to hostname
3269 read_service_conf (void *cls GNUNET_UNUSED, const char *section)
3273 if ((strlen (section) < 8) ||
3274 (0 != strcmp (".gnunet.", section + (strlen (section) - 8))))
3277 GNUNET_CONFIGURATION_get_value_string (cfg, section, "UDP_REDIRECTS",
3280 add_services (IPPROTO_UDP, cpy, section);
3284 GNUNET_CONFIGURATION_get_value_string (cfg, section, "TCP_REDIRECTS",
3287 add_services (IPPROTO_TCP, cpy, section);
3294 * @brief Main function that will be run by the scheduler.
3296 * @param cls closure
3297 * @param args remaining command-line arguments
3298 * @param cfgfile name of the configuration file used (for saving, can be NULL!)
3299 * @param cfg_ configuration
3302 run (void *cls, char *const *args GNUNET_UNUSED,
3303 const char *cfgfile GNUNET_UNUSED,
3304 const struct GNUNET_CONFIGURATION_Handle *cfg_)
3306 static struct GNUNET_MESH_MessageHandler handlers[] = {
3307 {&receive_icmp_service, GNUNET_MESSAGE_TYPE_VPN_ICMP_TO_SERVICE, 0},
3308 {&receive_icmp_remote, GNUNET_MESSAGE_TYPE_VPN_ICMP_TO_INTERNET, 0},
3309 {&receive_udp_service, GNUNET_MESSAGE_TYPE_VPN_UDP_TO_SERVICE, 0},
3310 {&receive_udp_remote, GNUNET_MESSAGE_TYPE_VPN_UDP_TO_INTERNET, 0},
3311 {&receive_tcp_service, GNUNET_MESSAGE_TYPE_VPN_TCP_TO_SERVICE_START, 0},
3312 {&receive_tcp_remote, GNUNET_MESSAGE_TYPE_VPN_TCP_TO_INTERNET_START, 0},
3313 {&receive_tcp_data, GNUNET_MESSAGE_TYPE_VPN_TCP_DATA_TO_EXIT, 0},
3314 {&receive_dns_request, GNUNET_MESSAGE_TYPE_VPN_DNS_TO_INTERNET, 0},
3318 static GNUNET_MESH_ApplicationType apptypes[] = {
3319 GNUNET_APPLICATION_TYPE_END,
3320 GNUNET_APPLICATION_TYPE_END,
3321 GNUNET_APPLICATION_TYPE_END,
3322 GNUNET_APPLICATION_TYPE_END
3324 unsigned int app_idx;
3333 char *prefixed_regex;
3334 struct in_addr dns_exit4;
3335 struct in6_addr dns_exit6;
3339 ipv4_exit = GNUNET_CONFIGURATION_get_value_yesno (cfg, "exit", "EXIT_IPV4");
3340 ipv6_exit = GNUNET_CONFIGURATION_get_value_yesno (cfg, "exit", "EXIT_IPV6");
3341 ipv4_enabled = GNUNET_CONFIGURATION_get_value_yesno (cfg, "exit", "ENABLE_IPV4");
3342 ipv6_enabled = GNUNET_CONFIGURATION_get_value_yesno (cfg, "exit", "ENABLE_IPV6");
3343 if ( (ipv4_exit) || (ipv6_exit) )
3345 binary = GNUNET_OS_get_libexec_binary_path ("gnunet-helper-exit");
3347 GNUNET_OS_check_helper_binary (binary, GNUNET_YES, "-d gnunet-vpn - - - 169.1.3.3.7 255.255.255.0")) //no nat, ipv4 only
3349 GNUNET_free (binary);
3350 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
3351 _("`%s' must be installed SUID, refusing to run\n"),
3352 "gnunet-helper-exit");
3356 GNUNET_free (binary);
3358 stats = GNUNET_STATISTICS_create ("exit", cfg);
3360 if ( (ipv4_exit || ipv4_enabled) &&
3361 GNUNET_OK != GNUNET_NETWORK_test_pf (PF_INET))
3363 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
3364 _("This system does not support IPv4, will disable IPv4 functions despite them being enabled in the configuration\n"));
3365 ipv4_exit = GNUNET_NO;
3366 ipv4_enabled = GNUNET_NO;
3368 if ( (ipv6_exit || ipv6_enabled) &&
3369 GNUNET_OK != GNUNET_NETWORK_test_pf (PF_INET6))
3371 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
3372 _("This system does not support IPv6, will disable IPv6 functions despite them being enabled in the configuration\n"));
3373 ipv6_exit = GNUNET_NO;
3374 ipv6_enabled = GNUNET_NO;
3376 if (ipv4_exit && (! ipv4_enabled))
3378 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
3379 _("Cannot enable IPv4 exit but disable IPv4 on TUN interface, will use ENABLE_IPv4=YES\n"));
3380 ipv4_enabled = GNUNET_YES;
3382 if (ipv6_exit && (! ipv6_enabled))
3384 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
3385 _("Cannot enable IPv6 exit but disable IPv6 on TUN interface, will use ENABLE_IPv6=YES\n"));
3386 ipv6_enabled = GNUNET_YES;
3388 if (! (ipv4_enabled || ipv6_enabled))
3390 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
3391 _("No useful service enabled. Exiting.\n"));
3392 GNUNET_SCHEDULER_shutdown ();
3398 GNUNET_CONFIGURATION_get_value_yesno (cfg_, "exit", "ENABLE_DNS")) &&
3400 GNUNET_CONFIGURATION_get_value_string (cfg, "exit",
3403 ( (1 != inet_pton (AF_INET, dns_exit, &dns_exit4)) &&
3404 (1 != inet_pton (AF_INET6, dns_exit, &dns_exit6)) ) ) )
3406 GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, "dns", "DNS_RESOLVER",
3407 _("need a valid IPv4 or IPv6 address\n"));
3408 GNUNET_free_non_null (dns_exit);
3411 if (NULL != dns_exit)
3412 dnsstub = GNUNET_DNSSTUB_start (dns_exit);
3416 if (GNUNET_YES == ipv4_exit)
3418 apptypes[app_idx] = GNUNET_APPLICATION_TYPE_IPV4_GATEWAY;
3421 if (GNUNET_YES == ipv6_exit)
3423 apptypes[app_idx] = GNUNET_APPLICATION_TYPE_IPV6_GATEWAY;
3426 if (NULL != dns_exit)
3428 apptypes[app_idx] = GNUNET_APPLICATION_TYPE_INTERNET_RESOLVER;
3432 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &cleanup, cls);
3435 GNUNET_CONFIGURATION_get_value_number (cfg, "exit", "MAX_CONNECTIONS",
3437 max_connections = 1024;
3438 exit_argv[0] = GNUNET_strdup ("exit-gnunet");
3439 if (GNUNET_SYSERR ==
3440 GNUNET_CONFIGURATION_get_value_string (cfg, "exit", "TUN_IFNAME", &tun_ifname))
3442 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
3443 "No entry 'TUN_IFNAME' in configuration!\n");
3444 GNUNET_SCHEDULER_shutdown ();
3447 exit_argv[1] = tun_ifname;
3450 if (GNUNET_SYSERR ==
3451 GNUNET_CONFIGURATION_get_value_string (cfg, "exit", "EXIT_IFNAME", &exit_ifname))
3453 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
3454 "No entry 'EXIT_IFNAME' in configuration!\n");
3455 GNUNET_SCHEDULER_shutdown ();
3458 exit_argv[2] = exit_ifname;
3462 exit_argv[2] = GNUNET_strdup ("-");
3466 if (GNUNET_YES == ipv6_enabled)
3468 if ( (GNUNET_SYSERR ==
3469 GNUNET_CONFIGURATION_get_value_string (cfg, "exit", "IPV6ADDR",
3471 (1 != inet_pton (AF_INET6, ipv6addr, &exit_ipv6addr))) )
3473 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
3474 "No valid entry 'IPV6ADDR' in configuration!\n");
3475 GNUNET_SCHEDULER_shutdown ();
3478 exit_argv[3] = ipv6addr;
3479 if (GNUNET_SYSERR ==
3480 GNUNET_CONFIGURATION_get_value_string (cfg, "exit", "IPV6PREFIX",
3483 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
3484 "No entry 'IPV6PREFIX' in configuration!\n");
3485 GNUNET_SCHEDULER_shutdown ();
3488 exit_argv[4] = ipv6prefix_s;
3490 GNUNET_CONFIGURATION_get_value_number (cfg, "exit",
3493 (ipv6prefix >= 127) )
3495 GNUNET_SCHEDULER_shutdown ();
3501 /* IPv6 explicitly disabled */
3502 exit_argv[3] = GNUNET_strdup ("-");
3503 exit_argv[4] = GNUNET_strdup ("-");
3505 if (GNUNET_YES == ipv4_enabled)
3507 if ( (GNUNET_SYSERR ==
3508 GNUNET_CONFIGURATION_get_value_string (cfg, "exit", "IPV4ADDR",
3510 (1 != inet_pton (AF_INET, ipv4addr, &exit_ipv4addr))) )
3512 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
3513 "No valid entry for 'IPV4ADDR' in configuration!\n");
3514 GNUNET_SCHEDULER_shutdown ();
3517 exit_argv[5] = ipv4addr;
3518 if ( (GNUNET_SYSERR ==
3519 GNUNET_CONFIGURATION_get_value_string (cfg, "exit", "IPV4MASK",
3521 (1 != inet_pton (AF_INET, ipv4mask, &exit_ipv4mask))) )
3523 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
3524 "No valid entry 'IPV4MASK' in configuration!\n");
3525 GNUNET_SCHEDULER_shutdown ();
3528 exit_argv[6] = ipv4mask;
3532 /* IPv4 explicitly disabled */
3533 exit_argv[5] = GNUNET_strdup ("-");
3534 exit_argv[6] = GNUNET_strdup ("-");
3536 exit_argv[7] = NULL;
3538 udp_services = GNUNET_CONTAINER_multihashmap_create (65536, GNUNET_NO);
3539 tcp_services = GNUNET_CONTAINER_multihashmap_create (65536, GNUNET_NO);
3540 GNUNET_CONFIGURATION_iterate_sections (cfg, &read_service_conf, NULL);
3542 connections_map = GNUNET_CONTAINER_multihashmap_create (65536, GNUNET_NO);
3543 connections_heap = GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN);
3545 = GNUNET_MESH_connect (cfg, NULL,
3547 &clean_tunnel, handlers,
3549 if (NULL == mesh_handle)
3551 GNUNET_SCHEDULER_shutdown ();
3555 /* Mesh handle acquired, now announce regular expressions matching our exit */
3556 if ( (GNUNET_YES == ipv4_enabled) && (GNUNET_YES == ipv4_exit) )
3559 GNUNET_CONFIGURATION_get_value_string (cfg,
3561 "EXIT_RANGE_IPV4_REGEX",
3563 regex = GNUNET_strdup ("(0|1)*");
3564 (void) GNUNET_asprintf (&prefixed_regex, "%s%s%s",
3565 GNUNET_APPLICATION_TYPE_EXIT_REGEX_PREFIX,
3567 GNUNET_MESH_announce_regex (mesh_handle,
3569 REGEX_MAX_PATH_LEN_IPV4);
3570 GNUNET_free (regex);
3571 GNUNET_free (prefixed_regex);
3574 if (GNUNET_YES == ipv6_enabled && GNUNET_YES == ipv6_exit)
3577 GNUNET_CONFIGURATION_get_value_string (cfg,
3579 "EXIT_RANGE_IPV6_REGEX",
3581 regex = GNUNET_strdup ("(0|1)*");
3582 (void) GNUNET_asprintf (&prefixed_regex, "%s%s%s",
3583 GNUNET_APPLICATION_TYPE_EXIT_REGEX_PREFIX,
3585 GNUNET_MESH_announce_regex (mesh_handle,
3587 REGEX_MAX_PATH_LEN_IPV6);
3588 GNUNET_free (regex);
3589 GNUNET_free (prefixed_regex);
3591 if ((ipv4_exit) || (ipv6_exit))
3592 helper_handle = GNUNET_HELPER_start (GNUNET_NO,
3593 "gnunet-helper-exit",
3603 * @param argc number of arguments from the command line
3604 * @param argv command line arguments
3605 * @return 0 ok, 1 on error
3608 main (int argc, char *const *argv)
3610 static const struct GNUNET_GETOPT_CommandLineOption options[] = {
3611 GNUNET_GETOPT_OPTION_END
3614 if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv))
3617 return (GNUNET_OK ==
3618 GNUNET_PROGRAM_run (argc, argv, "gnunet-daemon-exit",
3620 ("Daemon to run to provide an IP exit node for the VPN"),
3621 options, &run, NULL)) ? global_ret : 1;
3625 /* end of gnunet-daemon-exit.c */