summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/exit/Makefile.am4
-rw-r--r--src/exit/gnunet-daemon-exit.c60
-rw-r--r--src/vpn/Makefile.am2
-rw-r--r--src/vpn/gnunet-service-vpn.c219
4 files changed, 248 insertions, 37 deletions
diff --git a/src/exit/Makefile.am b/src/exit/Makefile.am
index d350d86e2..93a26801f 100644
--- a/src/exit/Makefile.am
+++ b/src/exit/Makefile.am
@@ -34,7 +34,7 @@ libexec_PROGRAMS = \
34if MINGW 34if MINGW
35 gnunet_helper_exit_LDFLAGS = \ 35 gnunet_helper_exit_LDFLAGS = \
36 -no-undefined -Wl,--export-all-symbols 36 -no-undefined -Wl,--export-all-symbols
37 37
38 gnunet_helper_exit_LDADD = \ 38 gnunet_helper_exit_LDADD = \
39 -lsetupapi -lnewdev -lshell32 -liconv -lstdc++ \ 39 -lsetupapi -lnewdev -lshell32 -liconv -lstdc++ \
40 -lcomdlg32 -lgdi32 -liphlpapi 40 -lcomdlg32 -lgdi32 -liphlpapi
@@ -54,5 +54,5 @@ gnunet_daemon_exit_LDADD = \
54 $(top_builddir)/src/tun/libgnunettun.la \ 54 $(top_builddir)/src/tun/libgnunettun.la \
55 $(top_builddir)/src/util/libgnunetutil.la \ 55 $(top_builddir)/src/util/libgnunetutil.la \
56 $(top_builddir)/src/mesh/libgnunetmesh.la \ 56 $(top_builddir)/src/mesh/libgnunetmesh.la \
57 $(top_builddir)/src/regex/libgnunetregex.la \ 57 $(top_builddir)/src/regex/libgnunetregexnew.la \
58 $(GN_LIBINTL) 58 $(GN_LIBINTL)
diff --git a/src/exit/gnunet-daemon-exit.c b/src/exit/gnunet-daemon-exit.c
index fbf173086..d7da94756 100644
--- a/src/exit/gnunet-daemon-exit.c
+++ b/src/exit/gnunet-daemon-exit.c
@@ -44,7 +44,7 @@
44#include "gnunet_statistics_service.h" 44#include "gnunet_statistics_service.h"
45#include "gnunet_constants.h" 45#include "gnunet_constants.h"
46#include "gnunet_tun_lib.h" 46#include "gnunet_tun_lib.h"
47#include "gnunet_regex_lib.h" 47#include "gnunet_regex_service.h"
48#include "exit.h" 48#include "exit.h"
49 49
50/** 50/**
@@ -59,6 +59,10 @@
59 */ 59 */
60#define REGEX_MAX_PATH_LEN_IPV6 8 60#define REGEX_MAX_PATH_LEN_IPV6 8
61 61
62/**
63 * How frequently do we re-announce the regex for the exit?
64 */
65#define REGEX_REFRESH_FREQUENCY GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 30)
62 66
63/** 67/**
64 * Generic logging shorthand 68 * Generic logging shorthand
@@ -67,7 +71,6 @@
67 GNUNET_log_from (kind, "exit", __VA_ARGS__); 71 GNUNET_log_from (kind, "exit", __VA_ARGS__);
68 72
69 73
70
71/** 74/**
72 * Information about an address. 75 * Information about an address.
73 */ 76 */
@@ -295,6 +298,16 @@ struct TunnelState
295static int global_ret; 298static int global_ret;
296 299
297/** 300/**
301 * Handle to our regex announcement for IPv4.
302 */
303static struct GNUNET_REGEX_Announcement *regex4;
304
305/**
306 * Handle to our regex announcement for IPv4.
307 */
308static struct GNUNET_REGEX_Announcement *regex6;
309
310/**
298 * The handle to the configuration used throughout the process 311 * The handle to the configuration used throughout the process
299 */ 312 */
300static const struct GNUNET_CONFIGURATION_Handle *cfg; 313static const struct GNUNET_CONFIGURATION_Handle *cfg;
@@ -376,6 +389,11 @@ static struct TunnelState *tunnels[UINT16_MAX + 1];
376static struct GNUNET_DNSSTUB_Context *dnsstub; 389static struct GNUNET_DNSSTUB_Context *dnsstub;
377 390
378/** 391/**
392 * Identity of this peer.
393 */
394static struct GNUNET_PeerIdentity my_identity;
395
396/**
379 * Are we an IPv4-exit? 397 * Are we an IPv4-exit?
380 */ 398 */
381static int ipv4_exit; 399static int ipv4_exit;
@@ -3072,12 +3090,22 @@ cleanup (void *cls GNUNET_UNUSED,
3072 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 3090 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3073 "Exit service is shutting down now\n"); 3091 "Exit service is shutting down now\n");
3074 3092
3075 if (helper_handle != NULL) 3093 if (NULL != helper_handle)
3076 { 3094 {
3077 GNUNET_HELPER_stop (helper_handle, GNUNET_NO); 3095 GNUNET_HELPER_stop (helper_handle, GNUNET_NO);
3078 helper_handle = NULL; 3096 helper_handle = NULL;
3079 } 3097 }
3080 if (mesh_handle != NULL) 3098 if (NULL != regex4)
3099 {
3100 GNUNET_REGEX_announce_cancel (regex4);
3101 regex4 = NULL;
3102 }
3103 if (NULL != regex6)
3104 {
3105 GNUNET_REGEX_announce_cancel (regex6);
3106 regex6 = NULL;
3107 }
3108 if (NULL != mesh_handle)
3081 { 3109 {
3082 GNUNET_MESH_disconnect (mesh_handle); 3110 GNUNET_MESH_disconnect (mesh_handle);
3083 mesh_handle = NULL; 3111 mesh_handle = NULL;
@@ -3541,6 +3569,14 @@ run (void *cls, char *const *args GNUNET_UNUSED,
3541 3569
3542 connections_map = GNUNET_CONTAINER_multihashmap_create (65536, GNUNET_NO); 3570 connections_map = GNUNET_CONTAINER_multihashmap_create (65536, GNUNET_NO);
3543 connections_heap = GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN); 3571 connections_heap = GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN);
3572 if (GNUNET_OK !=
3573 GNUNET_CRYPTO_get_host_identity (cfg,
3574 &my_identity))
3575 {
3576 GNUNET_break (0);
3577 GNUNET_SCHEDULER_shutdown ();
3578 return;
3579 }
3544 mesh_handle 3580 mesh_handle
3545 = GNUNET_MESH_connect (cfg, NULL, 3581 = GNUNET_MESH_connect (cfg, NULL,
3546 &new_tunnel, 3582 &new_tunnel,
@@ -3564,9 +3600,11 @@ run (void *cls, char *const *args GNUNET_UNUSED,
3564 (void) GNUNET_asprintf (&prefixed_regex, "%s%s%s", 3600 (void) GNUNET_asprintf (&prefixed_regex, "%s%s%s",
3565 GNUNET_APPLICATION_TYPE_EXIT_REGEX_PREFIX, 3601 GNUNET_APPLICATION_TYPE_EXIT_REGEX_PREFIX,
3566 "4", regex); 3602 "4", regex);
3567 GNUNET_MESH_announce_regex (mesh_handle, 3603 regex4 = GNUNET_REGEX_announce (cfg,
3568 prefixed_regex, 3604 &my_identity,
3569 REGEX_MAX_PATH_LEN_IPV4); 3605 prefixed_regex,
3606 REGEX_REFRESH_FREQUENCY,
3607 REGEX_MAX_PATH_LEN_IPV4);
3570 GNUNET_free (regex); 3608 GNUNET_free (regex);
3571 GNUNET_free (prefixed_regex); 3609 GNUNET_free (prefixed_regex);
3572 } 3610 }
@@ -3582,9 +3620,11 @@ run (void *cls, char *const *args GNUNET_UNUSED,
3582 (void) GNUNET_asprintf (&prefixed_regex, "%s%s%s", 3620 (void) GNUNET_asprintf (&prefixed_regex, "%s%s%s",
3583 GNUNET_APPLICATION_TYPE_EXIT_REGEX_PREFIX, 3621 GNUNET_APPLICATION_TYPE_EXIT_REGEX_PREFIX,
3584 "6", regex); 3622 "6", regex);
3585 GNUNET_MESH_announce_regex (mesh_handle, 3623 regex6 = GNUNET_REGEX_announce (cfg,
3586 prefixed_regex, 3624 &my_identity,
3587 REGEX_MAX_PATH_LEN_IPV6); 3625 prefixed_regex,
3626 REGEX_REFRESH_FREQUENCY,
3627 REGEX_MAX_PATH_LEN_IPV6);
3588 GNUNET_free (regex); 3628 GNUNET_free (regex);
3589 GNUNET_free (prefixed_regex); 3629 GNUNET_free (prefixed_regex);
3590 } 3630 }
diff --git a/src/vpn/Makefile.am b/src/vpn/Makefile.am
index 8b67a3373..d4c985116 100644
--- a/src/vpn/Makefile.am
+++ b/src/vpn/Makefile.am
@@ -59,7 +59,7 @@ gnunet_service_vpn_LDADD = \
59 $(top_builddir)/src/tun/libgnunettun.la \ 59 $(top_builddir)/src/tun/libgnunettun.la \
60 $(top_builddir)/src/util/libgnunetutil.la \ 60 $(top_builddir)/src/util/libgnunetutil.la \
61 $(top_builddir)/src/mesh/libgnunetmesh.la \ 61 $(top_builddir)/src/mesh/libgnunetmesh.la \
62 $(top_builddir)/src/regex/libgnunetregex.la \ 62 $(top_builddir)/src/regex/libgnunetregexnew.la \
63 $(GN_LIBINTL) 63 $(GN_LIBINTL)
64gnunet_service_vpn_CFLAGS = \ 64gnunet_service_vpn_CFLAGS = \
65 -I$(top_srcdir)/src/exit $(CFLAGS) 65 -I$(top_srcdir)/src/exit $(CFLAGS)
diff --git a/src/vpn/gnunet-service-vpn.c b/src/vpn/gnunet-service-vpn.c
index a56aff52a..a223e746e 100644
--- a/src/vpn/gnunet-service-vpn.c
+++ b/src/vpn/gnunet-service-vpn.c
@@ -25,6 +25,10 @@
25 * IP traffic received on those IPs via the GNUnet mesh 25 * IP traffic received on those IPs via the GNUnet mesh
26 * @author Philipp Toelke 26 * @author Philipp Toelke
27 * @author Christian Grothoff 27 * @author Christian Grothoff
28 *
29 * TODO:
30 * - keep multiple peers/mesh tunnels ready as alternative exits /
31 * recover from tunnel-to-exit failure gracefully
28 */ 32 */
29#include "platform.h" 33#include "platform.h"
30#include "gnunet_util_lib.h" 34#include "gnunet_util_lib.h"
@@ -35,7 +39,7 @@
35#include "gnunet_statistics_service.h" 39#include "gnunet_statistics_service.h"
36#include "gnunet_constants.h" 40#include "gnunet_constants.h"
37#include "gnunet_tun_lib.h" 41#include "gnunet_tun_lib.h"
38#include "gnunet_regex_lib.h" 42#include "gnunet_regex_service.h"
39#include "vpn.h" 43#include "vpn.h"
40#include "exit.h" 44#include "exit.h"
41 45
@@ -45,6 +49,16 @@
45 */ 49 */
46#define MAX_MESSAGE_QUEUE_SIZE 4 50#define MAX_MESSAGE_QUEUE_SIZE 4
47 51
52/**
53 * Maximum regex string length for use with GNUNET_REGEX_ipv4toregex
54 */
55#define GNUNET_REGEX_IPV4_REGEXLEN 32 + 6
56
57/**
58 * Maximum regex string length for use with GNUNET_REGEX_ipv6toregex
59 */
60#define GNUNET_REGEX_IPV6_REGEXLEN 128 + 6
61
48 62
49/** 63/**
50 * State we keep for each of our tunnels. 64 * State we keep for each of our tunnels.
@@ -172,6 +186,11 @@ struct TunnelState
172 struct GNUNET_MESH_Tunnel *tunnel; 186 struct GNUNET_MESH_Tunnel *tunnel;
173 187
174 /** 188 /**
189 * Active query with REGEX to locate exit.
190 */
191 struct GNUNET_REGEX_Search *search;
192
193 /**
175 * Active transmission handle, NULL for none. 194 * Active transmission handle, NULL for none.
176 */ 195 */
177 struct GNUNET_MESH_TransmitHandle *th; 196 struct GNUNET_MESH_TransmitHandle *th;
@@ -536,6 +555,11 @@ free_tunnel_state (struct TunnelState *ts)
536 ts->tunnel = NULL; 555 ts->tunnel = NULL;
537 GNUNET_MESH_tunnel_destroy (tunnel); 556 GNUNET_MESH_tunnel_destroy (tunnel);
538 } 557 }
558 if (NULL != ts->search)
559 {
560 GNUNET_REGEX_search_cancel (ts->search);
561 ts->search = NULL;
562 }
539 if (GNUNET_SCHEDULER_NO_TASK != ts->destroy_task) 563 if (GNUNET_SCHEDULER_NO_TASK != ts->destroy_task)
540 { 564 {
541 GNUNET_SCHEDULER_cancel (ts->destroy_task); 565 GNUNET_SCHEDULER_cancel (ts->destroy_task);
@@ -751,6 +775,150 @@ send_to_tunnel (struct TunnelMessageQueueEntry *tnq,
751 775
752 776
753/** 777/**
778 * Create a string with binary IP notation for the given 'addr' in 'str'.
779 *
780 * @param af address family of the given 'addr'.
781 * @param addr address that should be converted to a string.
782 * struct in_addr * for IPv4 and struct in6_addr * for IPv6.
783 * @param str string that will contain binary notation of 'addr'. Expected
784 * to be at least 33 bytes long for IPv4 and 129 bytes long for IPv6.
785 */
786static void
787iptobinstr (const int af, const void *addr, char *str)
788{
789 int i;
790
791 switch (af)
792 {
793 case AF_INET:
794 {
795 uint32_t b = htonl (((struct in_addr *) addr)->s_addr);
796
797 str[32] = '\0';
798 str += 31;
799 for (i = 31; i >= 0; i--)
800 {
801 *str = (b & 1) + '0';
802 str--;
803 b >>= 1;
804 }
805 break;
806 }
807 case AF_INET6:
808 {
809 struct in6_addr b = *(const struct in6_addr *) addr;
810
811 str[128] = '\0';
812 str += 127;
813 for (i = 127; i >= 0; i--)
814 {
815 *str = (b.s6_addr[i / 8] & 1) + '0';
816 str--;
817 b.s6_addr[i / 8] >>= 1;
818 }
819 break;
820 }
821 }
822}
823
824
825/**
826 * Get the ipv4 network prefix from the given 'netmask'.
827 *
828 * @param netmask netmask for which to get the prefix len.
829 *
830 * @return length of ipv4 prefix for 'netmask'.
831 */
832static unsigned int
833ipv4netmasktoprefixlen (const char *netmask)
834{
835 struct in_addr a;
836 unsigned int len;
837 uint32_t t;
838
839 if (1 != inet_pton (AF_INET, netmask, &a))
840 return 0;
841 len = 32;
842 for (t = htonl (~a.s_addr); 0 != t; t >>= 1)
843 len--;
844 return len;
845}
846
847
848/**
849 * Create a regex in 'rxstr' from the given 'ip' and 'netmask'.
850 *
851 * @param ip IPv4 representation.
852 * @param netmask netmask for the ip.
853 * @param rxstr generated regex, must be at least GNUNET_REGEX_IPV4_REGEXLEN
854 * bytes long.
855 */
856static void
857ipv4toregex (const struct in_addr *ip, const char *netmask,
858 char *rxstr)
859{
860 unsigned int pfxlen;
861
862 pfxlen = ipv4netmasktoprefixlen (netmask);
863 iptobinstr (AF_INET, ip, rxstr);
864 rxstr[pfxlen] = '\0';
865 if (pfxlen < 32)
866 strcat (rxstr, "(0|1)+");
867}
868
869
870/**
871 * Create a regex in 'rxstr' from the given 'ipv6' and 'prefixlen'.
872 *
873 * @param ipv6 IPv6 representation.
874 * @param prefixlen length of the ipv6 prefix.
875 * @param rxstr generated regex, must be at least GNUNET_REGEX_IPV6_REGEXLEN
876 * bytes long.
877 */
878static void
879ipv6toregex (const struct in6_addr *ipv6, unsigned int prefixlen,
880 char *rxstr)
881{
882 iptobinstr (AF_INET6, ipv6, rxstr);
883 rxstr[prefixlen] = '\0';
884 if (prefixlen < 128)
885 strcat (rxstr, "(0|1)+");
886}
887
888
889/**
890 * Regex has found a potential exit peer for us; consider using it.
891 *
892 * @param cls the 'struct TunnelState'
893 * @param id Peer providing a regex that matches the string.
894 * @param get_path Path of the get request.
895 * @param get_path_length Lenght of get_path.
896 * @param put_path Path of the put request.
897 * @param put_path_length Length of the put_path.
898 */
899static void
900handle_regex_result (void *cls,
901 const struct GNUNET_PeerIdentity *id,
902 const struct GNUNET_PeerIdentity *get_path,
903 unsigned int get_path_length,
904 const struct GNUNET_PeerIdentity *put_path,
905 unsigned int put_path_length)
906{
907 struct TunnelState *ts = cls;
908
909 GNUNET_REGEX_search_cancel (ts->search);
910 ts->search = NULL;
911 ts->tunnel = GNUNET_MESH_tunnel_create (mesh_handle,
912 ts,
913 &tunnel_peer_connect_handler,
914 &tunnel_peer_disconnect_handler,
915 ts);
916 GNUNET_MESH_peer_request_connect_add (ts->tunnel,
917 id);
918}
919
920
921/**
754 * Initialize the given destination entry's mesh tunnel. 922 * Initialize the given destination entry's mesh tunnel.
755 * 923 *
756 * @param de destination entry for which we need to setup a tunnel 924 * @param de destination entry for which we need to setup a tunnel
@@ -783,22 +951,22 @@ create_tunnel_to_destination (struct DestinationEntry *de,
783 ts->destination.heap_node = NULL; /* copy is NOT in destination heap */ 951 ts->destination.heap_node = NULL; /* copy is NOT in destination heap */
784 de->ts = ts; 952 de->ts = ts;
785 ts->destination_container = de; /* we are referenced from de */ 953 ts->destination_container = de; /* we are referenced from de */
786 ts->tunnel = GNUNET_MESH_tunnel_create (mesh_handle,
787 ts,
788 &tunnel_peer_connect_handler,
789 &tunnel_peer_disconnect_handler,
790 ts);
791 if (NULL == ts->tunnel)
792 {
793 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
794 _("Failed to setup mesh tunnel!\n"));
795 if (NULL != client)
796 GNUNET_SERVER_client_drop (client);
797 GNUNET_free (ts);
798 return NULL;
799 }
800 if (de->is_service) 954 if (de->is_service)
801 { 955 {
956 ts->tunnel = GNUNET_MESH_tunnel_create (mesh_handle,
957 ts,
958 &tunnel_peer_connect_handler,
959 &tunnel_peer_disconnect_handler,
960 ts);
961 if (NULL == ts->tunnel)
962 {
963 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
964 _("Failed to setup mesh tunnel!\n"));
965 if (NULL != client)
966 GNUNET_SERVER_client_drop (client);
967 GNUNET_free (ts);
968 return NULL;
969 }
802 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 970 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
803 "Creating tunnel to peer %s offering service %s\n", 971 "Creating tunnel to peer %s offering service %s\n",
804 GNUNET_i2s (&de->details.service_destination.target), 972 GNUNET_i2s (&de->details.service_destination.target),
@@ -815,8 +983,9 @@ create_tunnel_to_destination (struct DestinationEntry *de,
815 case AF_INET: 983 case AF_INET:
816 { 984 {
817 char address[GNUNET_REGEX_IPV4_REGEXLEN]; 985 char address[GNUNET_REGEX_IPV4_REGEXLEN];
818 GNUNET_REGEX_ipv4toregex (&de->details.exit_destination.ip.v4, 986
819 "255.255.255.255", address); 987 ipv4toregex (&de->details.exit_destination.ip.v4,
988 "255.255.255.255", address);
820 GNUNET_asprintf (&policy, "%s%s%s", 989 GNUNET_asprintf (&policy, "%s%s%s",
821 GNUNET_APPLICATION_TYPE_EXIT_REGEX_PREFIX, 990 GNUNET_APPLICATION_TYPE_EXIT_REGEX_PREFIX,
822 "4", 991 "4",
@@ -826,8 +995,9 @@ create_tunnel_to_destination (struct DestinationEntry *de,
826 case AF_INET6: 995 case AF_INET6:
827 { 996 {
828 char address[GNUNET_REGEX_IPV6_REGEXLEN]; 997 char address[GNUNET_REGEX_IPV6_REGEXLEN];
829 GNUNET_REGEX_ipv6toregex (&de->details.exit_destination.ip.v6, 998
830 128, address); 999 ipv6toregex (&de->details.exit_destination.ip.v6,
1000 128, address);
831 GNUNET_asprintf (&policy, "%s%s%s", 1001 GNUNET_asprintf (&policy, "%s%s%s",
832 GNUNET_APPLICATION_TYPE_EXIT_REGEX_PREFIX, 1002 GNUNET_APPLICATION_TYPE_EXIT_REGEX_PREFIX,
833 "6", 1003 "6",
@@ -839,12 +1009,13 @@ create_tunnel_to_destination (struct DestinationEntry *de,
839 break; 1009 break;
840 } 1010 }
841 1011
842 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Requesting connect by string: %s\n", policy);
843
844 GNUNET_MESH_peer_request_connect_by_string (ts->tunnel, policy);
845 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1012 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
846 "Creating tunnel to exit peer for policy `%s'\n", 1013 "Requesting connect by string: %s\n",
847 policy); 1014 policy);
1015 ts->search = GNUNET_REGEX_search (cfg,
1016 policy,
1017 &handle_regex_result,
1018 ts);
848 GNUNET_free (policy); 1019 GNUNET_free (policy);
849 } 1020 }
850 return ts; 1021 return ts;