From ddadc570d8fd3ce7a4f658adf9a2c9b9d9c0dcba Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Sat, 7 Jan 2017 16:47:07 +0100 Subject: [PATCH] remove legacy NAT library logic, or preserve if it might still be useful --- ChangeLog | 3 + .../gnunet-nat-auto_legacy.c} | 0 src/nat-auto/gnunet-service-nat-auto.c | 3 +- .../gnunet-service-nat-auto_legacy.c} | 0 src/nat/Makefile.am | 70 +- src/nat/gnunet-service-nat.c | 9 +- src/nat/nat.c | 2054 ----------------- src/nat/nat_mini.c | 712 ------ src/nat/nat_stun.c | 439 ---- src/peerinfo-tool/Makefile.am | 1 - src/transport/Makefile.am | 7 +- 11 files changed, 36 insertions(+), 3262 deletions(-) rename src/{nat/nat_test.c => nat-auto/gnunet-nat-auto_legacy.c} (100%) rename src/{nat/nat_auto.c => nat-auto/gnunet-service-nat-auto_legacy.c} (100%) delete mode 100644 src/nat/nat.c delete mode 100644 src/nat/nat_mini.c delete mode 100644 src/nat/nat_stun.c diff --git a/ChangeLog b/ChangeLog index e69de29bb..a44065ec2 100644 --- a/ChangeLog +++ b/ChangeLog @@ -0,0 +1,3 @@ +Sat Jan 7 16:41:34 CET 2017 + Converting NAT library to new NAT service (and + splitting of nat-auto service for auto-configuration). -CG diff --git a/src/nat/nat_test.c b/src/nat-auto/gnunet-nat-auto_legacy.c similarity index 100% rename from src/nat/nat_test.c rename to src/nat-auto/gnunet-nat-auto_legacy.c diff --git a/src/nat-auto/gnunet-service-nat-auto.c b/src/nat-auto/gnunet-service-nat-auto.c index f4e1b09e4..fafc4d382 100644 --- a/src/nat-auto/gnunet-service-nat-auto.c +++ b/src/nat-auto/gnunet-service-nat-auto.c @@ -27,6 +27,7 @@ * - merge client handle and autoconfig context * - implement "more" autoconfig: * + re-work gnunet-nat-server & integrate! + * + integrate "legacy" code * + test manually punched NAT (how?) */ #include "platform.h" @@ -450,7 +451,7 @@ client_disconnect_cb (void *cls, * Define "main" method using service macro. */ GNUNET_SERVICE_MAIN -("nat", +("nat-auto", GNUNET_SERVICE_OPTION_NONE, &run, &client_connect_cb, diff --git a/src/nat/nat_auto.c b/src/nat-auto/gnunet-service-nat-auto_legacy.c similarity index 100% rename from src/nat/nat_auto.c rename to src/nat-auto/gnunet-service-nat-auto_legacy.c diff --git a/src/nat/Makefile.am b/src/nat/Makefile.am index 456ddfb62..3dc001dd7 100644 --- a/src/nat/Makefile.am +++ b/src/nat/Makefile.am @@ -60,22 +60,8 @@ if USE_COVERAGE endif lib_LTLIBRARIES = \ - libgnunetnat.la \ libgnunetnatnew.la -libgnunetnat_la_SOURCES = \ - nat.c nat.h \ - nat_auto.c \ - nat_test.c \ - nat_mini.c \ - nat_stun.c -libgnunetnat_la_LIBADD = \ - $(top_builddir)/src/util/libgnunetutil.la \ - $(GN_LIBINTL) @EXT_LIBS@ -libgnunetnat_la_LDFLAGS = \ - $(GN_LIB_LDFLAGS) $(WINFLAGS) \ - -version-info 1:1:1 - libgnunetnatnew_la_SOURCES = \ nat_api.c \ nat_api_stun.c nat_stun.h \ @@ -100,40 +86,40 @@ gnunet_service_nat_LDADD = \ -lgcrypt \ $(GN_LIBINTL) -check_PROGRAMS = \ - test_nat \ - test_nat_mini \ - test_nat_test \ - test_stun +#check_PROGRAMS = \ +# test_nat \ +# test_nat_mini \ +# test_nat_test \ +# test_stun if ENABLE_TEST_RUN AM_TESTS_ENVIRONMENT=export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH; TESTS = $(check_PROGRAMS) endif -test_nat_SOURCES = \ - test_nat.c -test_nat_LDADD = \ - libgnunetnat.la \ - $(top_builddir)/src/util/libgnunetutil.la - -test_nat_mini_SOURCES = \ - test_nat_mini.c -test_nat_mini_LDADD = \ - libgnunetnat.la \ - $(top_builddir)/src/util/libgnunetutil.la - -test_nat_test_SOURCES = \ - test_nat_test.c -test_nat_test_LDADD = \ - libgnunetnat.la \ - $(top_builddir)/src/util/libgnunetutil.la - -test_stun_SOURCES = \ - test_stun.c -test_stun_LDADD = \ - libgnunetnat.la \ - $(top_builddir)/src/util/libgnunetutil.la +#test_nat_SOURCES = \ +# test_nat.c +#test_nat_LDADD = \ +# libgnunetnat.la \ +# $(top_builddir)/src/util/libgnunetutil.la + +#test_nat_mini_SOURCES = \ +# test_nat_mini.c +#test_nat_mini_LDADD = \ +# libgnunetnat.la \ +# $(top_builddir)/src/util/libgnunetutil.la + +#test_nat_test_SOURCES = \ +# test_nat_test.c +#test_nat_test_LDADD = \ +# libgnunetnat.la \ +# $(top_builddir)/src/util/libgnunetutil.la + +#test_stun_SOURCES = \ +# test_stun.c +#test_stun_LDADD = \ +# libgnunetnat.la \ +# $(top_builddir)/src/util/libgnunetutil.la EXTRA_DIST = \ test_nat_data.conf \ diff --git a/src/nat/gnunet-service-nat.c b/src/nat/gnunet-service-nat.c index b3e81127b..7fa329b54 100644 --- a/src/nat/gnunet-service-nat.c +++ b/src/nat/gnunet-service-nat.c @@ -28,13 +28,8 @@ * knowledge about the local network topology. * * TODO: - * - adapt existing transports to use new NAT logic - * - abandon legacy NAT code - * - * - implement "more" autoconfig: - * + consider moving autoconfig-logic into separate service! - * + re-work gnunet-nat-server & integrate! - * + test manually punched NAT (how?) + * - migrate test cases to new NAT service + * - add new traceroute-based logic for external IP detection * * - implement & test STUN processing to classify NAT; * basically, open port & try different methods. diff --git a/src/nat/nat.c b/src/nat/nat.c deleted file mode 100644 index 08dd5dd1e..000000000 --- a/src/nat/nat.c +++ /dev/null @@ -1,2054 +0,0 @@ -/* - This file is part of GNUnet. - Copyright (C) 2009, 2010, 2011 GNUnet e.V. - - GNUnet is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published - by the Free Software Foundation; either version 3, or (at your - option) any later version. - - GNUnet is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with GNUnet; see the file COPYING. If not, write to the - Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - Boston, MA 02110-1301, USA. -*/ - -/** - * @file nat/nat.c - * @brief Library handling UPnP and NAT-PMP port forwarding and - * external IP address retrieval - * @author Milan Bouchet-Valat - * @author Christian Grothoff - */ -#include "platform.h" -#include "gnunet_util_lib.h" -#include "gnunet_resolver_service.h" -#include "gnunet_nat_lib.h" -#include "nat.h" - -#define LOG(kind,...) GNUNET_log_from (kind, "nat", __VA_ARGS__) - -/** - * How often do we scan for changes in our IP address from our local - * interfaces? - */ -#define IFC_SCAN_FREQUENCY GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 15) - -/** - * How often do we scan for changes in how our hostname resolves? - */ -#define HOSTNAME_DNS_FREQUENCY GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 20) - - -/** - * How often do we scan for changes in how our external (dyndns) hostname resolves? - */ -#define DYNDNS_FREQUENCY GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 7) - -/** - * How long until we give up trying to resolve our own hostname? - */ -#define HOSTNAME_RESOLVE_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 1) - - -/** - * How often do we check a STUN server ? - */ -#define STUN_FREQUENCY GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 2) - - -/** - * Where did the given local address originate from? - * To be used for debugging as well as in the future - * to remove all addresses from a certain source when - * we reevaluate the source. - */ -enum LocalAddressSource -{ - /** - * Address was obtained by DNS resolution of the external hostname - * given in the configuration (i.e. hole-punched DynDNS setup). - */ - LAL_EXTERNAL_IP, - - /** - * Address was obtained by an external STUN server - */ - LAL_EXTERNAL_STUN_IP, - - /** - * Address was obtained by DNS resolution of the external hostname - * given in the configuration (i.e. hole-punched DynDNS setup) - * during the previous iteration (see #3213). - */ - LAL_EXTERNAL_IP_OLD, - - /** - * Address was obtained by looking up our own hostname in DNS. - */ - LAL_HOSTNAME_DNS, - - /** - * Address was obtained by scanning our hosts's network interfaces - * and taking their address (no DNS involved). - */ - LAL_INTERFACE_ADDRESS, - - /** - * Addresses we were explicitly bound to. - */ - LAL_BINDTO_ADDRESS, - - /** - * Addresses from UPnP or PMP - */ - LAL_UPNP, - - /** - * End of the list. - */ - LAL_END -}; - - -/** - * List of local addresses that we currently deem valid. Actual - * struct is followed by the 'struct sockaddr'. Note that the code - * intentionally makes no attempt to ensure that a particular address - * is only listed once (especially since it may come from different - * sources, and the source is an "internal" construct). - */ -struct LocalAddressList -{ - /** - * This is a linked list. - */ - struct LocalAddressList *next; - - /** - * Previous entry. - */ - struct LocalAddressList *prev; - - /** - * Number of bytes of address that follow. - */ - socklen_t addrlen; - - /** - * Origin of the local address. - */ - enum LocalAddressSource source; -}; - - -/** - * Handle for miniupnp-based NAT traversal actions. - */ -struct MiniList -{ - - /** - * Doubly-linked list. - */ - struct MiniList *next; - - /** - * Doubly-linked list. - */ - struct MiniList *prev; - - /** - * Handle to mini-action. - */ - struct GNUNET_NAT_MiniHandle *mini; - - /** - * Local port number that was mapped. - */ - uint16_t port; - -}; - - -/** - * List of STUN servers - */ -struct StunServerList -{ - - /** - * Doubly-linked list. - */ - struct StunServerList *next; - - /** - * Doubly-linked list. - */ - struct StunServerList *prev; - - /** - * Address - */ - char * address; - - /** - * Server Port - */ - uint16_t port; - -}; - - -/** - * Handle for active NAT registrations. - */ -struct GNUNET_NAT_Handle -{ - - /** - * Configuration to use. - */ - const struct GNUNET_CONFIGURATION_Handle *cfg; - - /** - * Function to call when we learn about a new address. - */ - GNUNET_NAT_AddressCallback address_callback; - - /** - * Function to call when we notice another peer asking for - * connection reversal. - */ - GNUNET_NAT_ReversalCallback reversal_callback; - - /** - * Closure for callbacks (@e address_callback and @e reversal_callback) - */ - void *callback_cls; - - /** - * Handle for (DYN)DNS lookup of our external IP. - */ - struct GNUNET_RESOLVER_RequestHandle *ext_dns; - - /** - * Handle for request of hostname resolution, non-NULL if pending. - */ - struct GNUNET_RESOLVER_RequestHandle *hostname_dns; - - /** - * stdout pipe handle for the gnunet-helper-nat-server process - */ - struct GNUNET_DISK_PipeHandle *server_stdout; - - /** - * stdout file handle (for reading) for the gnunet-helper-nat-server process - */ - const struct GNUNET_DISK_FileHandle *server_stdout_handle; - - /** - * Linked list of currently valid addresses (head). - */ - struct LocalAddressList *lal_head; - - /** - * Linked list of currently valid addresses (tail). - */ - struct LocalAddressList *lal_tail; - - /** - * How long do we wait for restarting a crashed gnunet-helper-nat-server? - */ - struct GNUNET_TIME_Relative server_retry_delay; - - /** - * ID of select gnunet-helper-nat-server stdout read task - */ - struct GNUNET_SCHEDULER_Task *server_read_task; - - /** - * ID of interface IP-scan task - */ - struct GNUNET_SCHEDULER_Task *ifc_task; - - /** - * ID of hostname DNS lookup task - */ - struct GNUNET_SCHEDULER_Task *hostname_task; - - /** - * ID of DynDNS lookup task - */ - struct GNUNET_SCHEDULER_Task *dns_task; - - /** - * Active STUN request, if any. - */ - struct GNUNET_NAT_STUN_Handle *stun_request; - - /** - * How often do we scan for changes in our IP address from our local - * interfaces? - */ - struct GNUNET_TIME_Relative ifc_scan_frequency; - - /** - * How often do we scan for changes in how our hostname resolves? - */ - struct GNUNET_TIME_Relative hostname_dns_frequency; - - /** - * How often do we scan for changes in how our external (dyndns) hostname resolves? - */ - struct GNUNET_TIME_Relative dyndns_frequency; - - /** - * The process id of the server process (if behind NAT) - */ - struct GNUNET_OS_Process *server_proc; - - /** - * LAN address as passed by the caller (array). - */ - struct sockaddr **local_addrs; - - /** - * Length of the @e local_addrs. - */ - socklen_t *local_addrlens; - - /** - * List of handles for UPnP-traversal, one per local port (if - * not IPv6-only). - */ - struct MiniList *mini_head; - - /** - * List of handles for UPnP-traversal, one per local port (if - * not IPv6-only). - */ - struct MiniList *mini_tail; - - /** - * Number of entries in 'local_addrs' array. - */ - unsigned int num_local_addrs; - - /** - * Our external address (according to config, UPnP may disagree...), - * in dotted decimal notation, IPv4-only. Or NULL if not known. - */ - char *external_address; - - /** - * Presumably our internal address (according to config) - */ - char *internal_address; - - /** - * Is this transport configured to be behind a NAT? - */ - int behind_nat; - - /** - * Has the NAT been punched? (according to config) - */ - int nat_punched; - - /** - * Is this transport configured to allow connections to NAT'd peers? - */ - int enable_nat_client; - - /** - * Should we run the gnunet-helper-nat-server? - */ - int enable_nat_server; - - /** - * Are we allowed to try UPnP/PMP for NAT traversal? - */ - int enable_upnp; - - /** - * Should we use local addresses (loopback)? (according to config) - */ - int use_localaddresses; - - /** - * Should we return local addresses to clients - */ - int return_localaddress; - - /** - * Should we do a DNS lookup of our hostname to find out our own IP? - */ - int use_hostname; - - /** - * Is using IPv6 disabled? - */ - int disable_ipv6; - - /** - * Is this TCP or UDP? - */ - int is_tcp; - - /** - * Port we advertise to the outside. - */ - uint16_t adv_port; - - /** - * Should we use STUN ? - */ - int use_stun; - - /** - * How often should we check STUN ? - */ - struct GNUNET_TIME_Relative stun_frequency; - - /** - * STUN socket - */ - struct GNUNET_NETWORK_Handle* socket; - - /* - * Am I waiting for a STUN response ? - */ - int waiting_stun; - - /** - * STUN request task - */ - struct GNUNET_SCHEDULER_Task *stun_task; - - /** - * Head of List of STUN servers - */ - struct StunServerList *stun_servers_head; - - /** - * Tail of List of STUN servers - */ - struct StunServerList *stun_servers_tail; - - /** - * Actual STUN Server - */ - struct StunServerList *actual_stun_server; - -}; - - -/** - * Try to start the gnunet-helper-nat-server (if it is not - * already running). - * - * @param h handle to NAT - */ -static void -start_gnunet_nat_server (struct GNUNET_NAT_Handle *h); - - -/** - * Remove all addresses from the list of 'local' addresses - * that originated from the given source. - * - * @param h handle to NAT - * @param src source that identifies addresses to remove - */ -static void -remove_from_address_list_by_source (struct GNUNET_NAT_Handle *h, - enum LocalAddressSource src) -{ - struct LocalAddressList *pos; - struct LocalAddressList *next; - - next = h->lal_head; - while (NULL != (pos = next)) - { - next = pos->next; - if (pos->source != src) - continue; - GNUNET_CONTAINER_DLL_remove (h->lal_head, - h->lal_tail, - pos); - if (NULL != h->address_callback) - h->address_callback (h->callback_cls, - GNUNET_NO, - (const struct sockaddr *) &pos[1], - pos->addrlen); - GNUNET_free (pos); - } -} - - -/** - * Add the given address to the list of 'local' addresses, thereby - * making it a 'legal' address for this peer to have. - * - * @param h handle to NAT - * @param src where did the local address originate from? - * @param arg the address, some `struct sockaddr` - * @param arg_size number of bytes in @a arg - */ -static void -add_to_address_list_as_is (struct GNUNET_NAT_Handle *h, - enum LocalAddressSource src, - const struct sockaddr *arg, - socklen_t arg_size) -{ - struct LocalAddressList *lal; - - lal = GNUNET_malloc (sizeof (struct LocalAddressList) + arg_size); - GNUNET_memcpy (&lal[1], arg, arg_size); - lal->addrlen = arg_size; - lal->source = src; - GNUNET_CONTAINER_DLL_insert (h->lal_head, - h->lal_tail, - lal); - LOG (GNUNET_ERROR_TYPE_DEBUG, - "Adding address `%s' from source %d\n", - GNUNET_a2s (arg, arg_size), - src); - if (NULL != h->address_callback) - h->address_callback (h->callback_cls, - GNUNET_YES, - arg, - arg_size); -} - - -/** - * Add the given address to the list of 'local' addresses, thereby - * making it a 'legal' address for this peer to have. Set the - * port number in the process to the advertised port and possibly - * also to zero (if we have the gnunet-helper-nat-server). - * - * @param h handle to NAT - * @param src where did the local address originate from? - * @param arg the address, some `struct sockaddr` - * @param arg_size number of bytes in @a arg - */ -static void -add_to_address_list (struct GNUNET_NAT_Handle *h, - enum LocalAddressSource src, - const struct sockaddr *arg, - socklen_t arg_size) -{ - struct sockaddr_in s4; - const struct sockaddr_in *in4; - struct sockaddr_in6 s6; - const struct sockaddr_in6 *in6; - - if (arg_size == sizeof (struct sockaddr_in)) - { - in4 = (const struct sockaddr_in *) arg; - s4 = *in4; - s4.sin_port = htons (h->adv_port); - add_to_address_list_as_is (h, src, (const struct sockaddr *) &s4, - sizeof (struct sockaddr_in)); - if (GNUNET_YES == h->enable_nat_server) - { - /* also add with PORT = 0 to indicate NAT server is enabled */ - s4.sin_port = htons (0); - add_to_address_list_as_is (h, src, (const struct sockaddr *) &s4, - sizeof (struct sockaddr_in)); - } - } - else if (arg_size == sizeof (struct sockaddr_in6)) - { - if (GNUNET_YES != h->disable_ipv6) - { - in6 = (const struct sockaddr_in6 *) arg; - s6 = *in6; - s6.sin6_port = htons (h->adv_port); - add_to_address_list_as_is (h, src, (const struct sockaddr *) &s6, - sizeof (struct sockaddr_in6)); - } - } - else - { - GNUNET_assert (0); - } -} - - -/** - * Add the given IP address to the list of 'local' addresses, thereby - * making it a 'legal' address for this peer to have. - * - * @param h handle to NAT - * @param src where did the local address originate from? - * @param addr the address, some `struct in_addr` or `struct in6_addr` - * @param addrlen number of bytes in addr - */ -static void -add_ip_to_address_list (struct GNUNET_NAT_Handle *h, - enum LocalAddressSource src, - const void *addr, - socklen_t addrlen) -{ - struct sockaddr_in s4; - const struct in_addr *in4; - struct sockaddr_in6 s6; - const struct in6_addr *in6; - - if (addrlen == sizeof (struct in_addr)) - { - in4 = (const struct in_addr *) addr; - memset (&s4, 0, sizeof (s4)); - s4.sin_family = AF_INET; - s4.sin_port = 0; -#if HAVE_SOCKADDR_IN_SIN_LEN - s4.sin_len = (u_char) sizeof (struct sockaddr_in); -#endif - s4.sin_addr = *in4; - add_to_address_list (h, src, (const struct sockaddr *) &s4, - sizeof (struct sockaddr_in)); - if (GNUNET_YES == h->enable_nat_server) - { - /* also add with PORT = 0 to indicate NAT server is enabled */ - s4.sin_port = htons (0); - add_to_address_list (h, src, (const struct sockaddr *) &s4, - sizeof (struct sockaddr_in)); - - } - } - else if (addrlen == sizeof (struct in6_addr)) - { - if (GNUNET_YES != h->disable_ipv6) - { - in6 = (const struct in6_addr *) addr; - memset (&s6, 0, sizeof (s6)); - s6.sin6_family = AF_INET6; - s6.sin6_port = htons (h->adv_port); -#if HAVE_SOCKADDR_IN_SIN_LEN - s6.sin6_len = (u_char) sizeof (struct sockaddr_in6); -#endif - s6.sin6_addr = *in6; - add_to_address_list (h, src, (const struct sockaddr *) &s6, - sizeof (struct sockaddr_in6)); - } - } - else - { - GNUNET_assert (0); - } -} - - -/** - * Task to do DNS lookup on our external hostname to - * get DynDNS-IP addresses. - * - * @param cls the NAT handle - */ -static void -resolve_dns (void *cls); - - -/** - * Our (external) hostname was resolved and the configuration says that - * the NAT was hole-punched. - * - * @param cls the `struct GNUNET_NAT_Handle` - * @param addr NULL on error, otherwise result of DNS lookup - * @param addrlen number of bytes in @a addr - */ -static void -process_external_ip (void *cls, - const struct sockaddr *addr, - socklen_t addrlen) -{ - struct GNUNET_NAT_Handle *h = cls; - struct in_addr dummy; - - if (NULL == addr) - { - h->ext_dns = NULL; - /* Current iteration is over, remove 'old' IPs now */ - LOG (GNUNET_ERROR_TYPE_DEBUG, - "Purging old IPs for external address\n"); - remove_from_address_list_by_source (h, - LAL_EXTERNAL_IP_OLD); - if (1 == inet_pton (AF_INET, - h->external_address, - &dummy)) - { - LOG (GNUNET_ERROR_TYPE_DEBUG, - "Got numeric IP for external address, not repeating lookup\n"); - return; /* repated lookup pointless: was numeric! */ - } - h->dns_task = - GNUNET_SCHEDULER_add_delayed (h->dyndns_frequency, - &resolve_dns, h); - return; - } - LOG (GNUNET_ERROR_TYPE_DEBUG, - "Got IP `%s' for external address `%s'\n", - GNUNET_a2s (addr, - addrlen), - h->external_address); - add_to_address_list (h, - LAL_EXTERNAL_IP, - addr, - addrlen); -} - - -/** - * Task to do a lookup on our hostname for IP addresses. - * - * @param cls the NAT handle - */ -static void -resolve_hostname (void *cls); - - -/** - * Function called by the resolver for each address obtained from DNS - * for our own hostname. Add the addresses to the list of our IP - * addresses. - * - * @param cls closure - * @param addr one of the addresses of the host, NULL for the last address - * @param addrlen length of the @a addr - */ -static void -process_hostname_ip (void *cls, - const struct sockaddr *addr, - socklen_t addrlen) -{ - struct GNUNET_NAT_Handle *h = cls; - - if (NULL == addr) - { - h->hostname_dns = NULL; - h->hostname_task = - GNUNET_SCHEDULER_add_delayed (h->hostname_dns_frequency, - &resolve_hostname, - h); - return; - } - add_to_address_list (h, - LAL_HOSTNAME_DNS, - addr, - addrlen); -} - - -/** - * Length of the interface names returned from os_network.c. - * (in that file, hardcoded at 11). - */ -#define IF_NAME_LEN 11 - - -/** - * Add the IP of our network interface to the list of - * our IP addresses. - * - * @param cls the `struct GNUNET_NAT_Handle` - * @param name name of the interface - * @param isDefault do we think this may be our default interface - * @param addr address of the interface - * @param broadcast_addr the broadcast address (can be NULL for unknown or unassigned) - * @param netmask the network mask (can be NULL for unknown or unassigned)) - * @param addrlen number of bytes in @a addr and @a broadcast_addr - * @return #GNUNET_OK to continue iterating - */ -static int -process_interfaces (void *cls, - const char *name, - int isDefault, - const struct sockaddr *addr, - const struct sockaddr *broadcast_addr, - const struct sockaddr *netmask, - socklen_t addrlen) -{ - const static struct in6_addr any6 = IN6ADDR_ANY_INIT; - struct GNUNET_NAT_Handle *h = cls; - const struct sockaddr_in *s4; - const struct sockaddr_in6 *s6; - const void *ip; - char buf[INET6_ADDRSTRLEN]; - unsigned int i; - int have_any; - char *tun_if; - - /* skip virtual interfaces created by GNUnet-vpn */ - if (GNUNET_OK == - GNUNET_CONFIGURATION_get_value_string (h->cfg, - "vpn", - "IFNAME", - &tun_if)) - { - if (0 == strncasecmp (name, - tun_if, - IF_NAME_LEN)) - { - GNUNET_free (tun_if); - return GNUNET_OK; - } - GNUNET_free (tun_if); - } - /* skip virtual interfaces created by GNUnet-dns */ - if (GNUNET_OK == - GNUNET_CONFIGURATION_get_value_string (h->cfg, - "dns", - "IFNAME", - &tun_if)) - { - if (0 == strncasecmp (name, - tun_if, - IF_NAME_LEN)) - { - GNUNET_free (tun_if); - return GNUNET_OK; - } - GNUNET_free (tun_if); - } - /* skip virtual interfaces created by GNUnet-exit */ - if (GNUNET_OK == - GNUNET_CONFIGURATION_get_value_string (h->cfg, - "exit", - "TUN_IFNAME", - &tun_if)) - { - if (0 == strncasecmp (name, - tun_if, - IF_NAME_LEN)) - { - GNUNET_free (tun_if); - return GNUNET_OK; - } - GNUNET_free (tun_if); - } - - switch (addr->sa_family) - { - case AF_INET: - /* check if we're bound to the "ANY" IP address */ - have_any = GNUNET_NO; - for (i=0;inum_local_addrs;i++) - { - if (h->local_addrs[i]->sa_family != AF_INET) - continue; -#ifndef INADDR_ANY -#define INADDR_ANY 0 -#endif - if (INADDR_ANY == ((struct sockaddr_in*) h->local_addrs[i])->sin_addr.s_addr) - { - have_any = GNUNET_YES; - break; - } - } - if (GNUNET_NO == have_any) - return GNUNET_OK; /* not bound to IP 0.0.0.0 but to specific IP addresses, - do not use those from interfaces */ - s4 = (struct sockaddr_in *) addr; - ip = &s4->sin_addr; - - /* Check if address is in 127.0.0.0/8 */ - uint32_t address = ntohl ((uint32_t) (s4->sin_addr.s_addr)); - uint32_t value = (address & 0xFF000000) ^ 0x7F000000; - - if ((h->return_localaddress == GNUNET_NO) && (value == 0)) - { - return GNUNET_OK; - } - if ((GNUNET_YES == h->use_localaddresses) || (value != 0)) - { - add_ip_to_address_list (h, LAL_INTERFACE_ADDRESS, &s4->sin_addr, - sizeof (struct in_addr)); - } - break; - case AF_INET6: - /* check if we're bound to the "ANY" IP address */ - have_any = GNUNET_NO; - for (i=0;inum_local_addrs;i++) - { - if (h->local_addrs[i]->sa_family != AF_INET6) - continue; - if (0 == memcmp (&any6, - &((struct sockaddr_in6*) h->local_addrs[i])->sin6_addr, - sizeof (struct in6_addr))) - { - have_any = GNUNET_YES; - break; - } - } - if (GNUNET_NO == have_any) - return GNUNET_OK; /* not bound to "ANY" IP (::0) but to specific IP addresses, - do not use those from interfaces */ - - s6 = (struct sockaddr_in6 *) addr; - if (IN6_IS_ADDR_LINKLOCAL (&((struct sockaddr_in6 *) addr)->sin6_addr)) - { - /* skip link local addresses */ - return GNUNET_OK; - } - if ((h->return_localaddress == GNUNET_NO) && - (IN6_IS_ADDR_LOOPBACK (&((struct sockaddr_in6 *) addr)->sin6_addr))) - { - return GNUNET_OK; - } - ip = &s6->sin6_addr; - if (GNUNET_YES == h->use_localaddresses) - { - add_ip_to_address_list (h, LAL_INTERFACE_ADDRESS, &s6->sin6_addr, - sizeof (struct in6_addr)); - } - break; - default: - GNUNET_break (0); - return GNUNET_OK; - } - if ( (h->internal_address == NULL) && - (h->server_proc == NULL) && - (h->server_read_task == NULL) && - (GNUNET_YES == isDefault) && - ( (addr->sa_family == AF_INET) || - (addr->sa_family == AF_INET6) ) ) - { - /* no internal address configured, but we found a "default" - * interface, try using that as our 'internal' address */ - h->internal_address = - GNUNET_strdup (inet_ntop (addr->sa_family, ip, buf, sizeof (buf))); - start_gnunet_nat_server (h); - } - return GNUNET_OK; -} - - -/** - * Task that restarts the gnunet-helper-nat-server process after a crash - * after a certain delay. - * - * @param cls the `struct GNUNET_NAT_Handle` - */ -static void -restart_nat_server (void *cls) -{ - struct GNUNET_NAT_Handle *h = cls; - - h->server_read_task = NULL; - start_gnunet_nat_server (h); -} - - -/** - * We have been notified that gnunet-helper-nat-server has written - * something to stdout. Handle the output, then reschedule this - * function to be called again once more is available. - * - * @param cls the NAT handle - */ -static void -nat_server_read (void *cls) -{ - struct GNUNET_NAT_Handle *h = cls; - char mybuf[40]; - ssize_t bytes; - size_t i; - int port; - const char *port_start; - struct sockaddr_in sin_addr; - - h->server_read_task = NULL; - memset (mybuf, 0, sizeof (mybuf)); - bytes = - GNUNET_DISK_file_read (h->server_stdout_handle, mybuf, sizeof (mybuf)); - if (bytes < 1) - { - LOG (GNUNET_ERROR_TYPE_DEBUG, - "Finished reading from server stdout with code: %d\n", - bytes); - if (0 != GNUNET_OS_process_kill (h->server_proc, GNUNET_TERM_SIG)) - GNUNET_log_from_strerror (GNUNET_ERROR_TYPE_WARNING, "nat", "kill"); - GNUNET_OS_process_wait (h->server_proc); - GNUNET_OS_process_destroy (h->server_proc); - h->server_proc = NULL; - GNUNET_DISK_pipe_close (h->server_stdout); - h->server_stdout = NULL; - h->server_stdout_handle = NULL; - /* now try to restart it */ - h->server_retry_delay = GNUNET_TIME_STD_BACKOFF (h->server_retry_delay); - h->server_read_task = - GNUNET_SCHEDULER_add_delayed (h->server_retry_delay, - &restart_nat_server, h); - return; - } - - port_start = NULL; - for (i = 0; i < sizeof (mybuf); i++) - { - if (mybuf[i] == '\n') - { - mybuf[i] = '\0'; - break; - } - if ((mybuf[i] == ':') && (i + 1 < sizeof (mybuf))) - { - mybuf[i] = '\0'; - port_start = &mybuf[i + 1]; - } - } - - /* construct socket address of sender */ - memset (&sin_addr, 0, sizeof (sin_addr)); - sin_addr.sin_family = AF_INET; -#if HAVE_SOCKADDR_IN_SIN_LEN - sin_addr.sin_len = sizeof (sin_addr); -#endif - if ((NULL == port_start) || (1 != SSCANF (port_start, "%d", &port)) || - (-1 == inet_pton (AF_INET, mybuf, &sin_addr.sin_addr))) - { - /* should we restart gnunet-helper-nat-server? */ - LOG (GNUNET_ERROR_TYPE_WARNING, "nat", - _("gnunet-helper-nat-server generated malformed address `%s'\n"), - mybuf); - h->server_read_task = - GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL, - h->server_stdout_handle, - &nat_server_read, h); - return; - } - sin_addr.sin_port = htons ((uint16_t) port); - LOG (GNUNET_ERROR_TYPE_DEBUG, "gnunet-helper-nat-server read: %s:%d\n", mybuf, - port); - h->reversal_callback (h->callback_cls, (const struct sockaddr *) &sin_addr, - sizeof (sin_addr)); - h->server_read_task = - GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL, - h->server_stdout_handle, - &nat_server_read, - h); -} - - -/** - * Try to start the gnunet-helper-nat-server (if it is not - * already running). - * - * @param h handle to NAT - */ -static void -start_gnunet_nat_server (struct GNUNET_NAT_Handle *h) -{ - char *binary; - - if ((h->behind_nat == GNUNET_YES) && (h->enable_nat_server == GNUNET_YES) && - (h->internal_address != NULL) && - (NULL != - (h->server_stdout = - GNUNET_DISK_pipe (GNUNET_YES, GNUNET_YES, GNUNET_NO, GNUNET_YES)))) - { - LOG (GNUNET_ERROR_TYPE_DEBUG, - "Starting `%s' at `%s'\n", - "gnunet-helper-nat-server", h->internal_address); - /* Start the server process */ - binary = GNUNET_OS_get_libexec_binary_path ("gnunet-helper-nat-server"); - h->server_proc = - GNUNET_OS_start_process (GNUNET_NO, 0, NULL, h->server_stdout, NULL, - binary, - "gnunet-helper-nat-server", - h->internal_address, NULL); - GNUNET_free (binary); - if (h->server_proc == NULL) - { - LOG (GNUNET_ERROR_TYPE_WARNING, "nat", _("Failed to start %s\n"), - "gnunet-helper-nat-server"); - GNUNET_DISK_pipe_close (h->server_stdout); - h->server_stdout = NULL; - } - else - { - /* Close the write end of the read pipe */ - GNUNET_DISK_pipe_close_end (h->server_stdout, GNUNET_DISK_PIPE_END_WRITE); - h->server_stdout_handle = - GNUNET_DISK_pipe_handle (h->server_stdout, GNUNET_DISK_PIPE_END_READ); - h->server_read_task = - GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL, - h->server_stdout_handle, - &nat_server_read, h); - } - } -} - - -/** - * Task to scan the local network interfaces for IP addresses. - * - * @param cls the NAT handle - */ -static void -list_interfaces (void *cls) -{ - struct GNUNET_NAT_Handle *h = cls; - - h->ifc_task = NULL; - remove_from_address_list_by_source (h, LAL_INTERFACE_ADDRESS); - GNUNET_OS_network_interfaces_list (&process_interfaces, h); - h->ifc_task = - GNUNET_SCHEDULER_add_delayed (h->ifc_scan_frequency, - &list_interfaces, h); -} - - -/** - * Callback with the result from the STUN request. - * - * @param cls the NAT handle - * @param result the status - */ -static void -stun_request_callback (void *cls, - enum GNUNET_NAT_StatusCode result) -{ - struct GNUNET_NAT_Handle *h = cls; - - h->stun_request = NULL; - switch (result) - { - case GNUNET_NAT_ERROR_INTERNAL_NETWORK_ERROR: - LOG (GNUNET_ERROR_TYPE_WARNING, - "Failed to transmit STUN request\n"); - break; - case GNUNET_NAT_ERROR_NOT_ONLINE: - LOG (GNUNET_ERROR_TYPE_WARNING, - "Failed to resolve STUN server (are we online?)\n"); - break; - case GNUNET_NAT_ERROR_SUCCESS: - /* all good, STUN request active */ - h->waiting_stun = GNUNET_YES; - break; - default: - /* unexpected error code for STUN */ - GNUNET_break (0); - } -} - - -/** - * CHECK if is a valid STUN packet sending to GNUNET_NAT_stun_handle_packet(). - * It also check if it can handle the packet based on the NAT handler. - * You don't need to call anything else to check if the packet is valid, - * - * @param cls the NAT handle - * @param data packet - * @param len packet length - * @return #GNUNET_NO if it can't decode, #GNUNET_YES if is a packet - */ -int -GNUNET_NAT_is_valid_stun_packet (void *cls, - const void *data, - size_t len) -{ - struct GNUNET_NAT_Handle *h = cls; - struct sockaddr_in answer; - - /* We are not expecting a STUN message */ - if (GNUNET_YES != h->waiting_stun) - return GNUNET_NO; - - /* We dont have STUN installed */ - if (! h->use_stun) - return GNUNET_NO; - - /* Empty the answer structure */ - memset (&answer, - 0, - sizeof(struct sockaddr_in)); - - /* Lets handle the packet*/ - if (GNUNET_NO == - GNUNET_NAT_stun_handle_packet (data, - len, - &answer)) - return GNUNET_NO; - - LOG (GNUNET_ERROR_TYPE_INFO, - "STUN server returned %s:%d\n", - inet_ntoa (answer.sin_addr), - ntohs (answer.sin_port)); - /* Remove old IPs from previous STUN calls */ - remove_from_address_list_by_source (h, - LAL_EXTERNAL_STUN_IP); - /* Add new IP from STUN packet */ - add_to_address_list (h, - LAL_EXTERNAL_STUN_IP, - (const struct sockaddr *) &answer, - sizeof (struct sockaddr_in)); - h->waiting_stun = GNUNET_NO; - return GNUNET_YES; -} - - -/** - * Task to do a STUN request - * - * @param cls the NAT handle - */ -static void -process_stun (void *cls) -{ - struct GNUNET_NAT_Handle *h = cls; - struct StunServerList *elem = h->actual_stun_server; - - h->stun_task = NULL; - /* Make the request */ - LOG (GNUNET_ERROR_TYPE_INFO, - "I will request the stun server %s:%i\n", - elem->address, - elem->port); - if (NULL != h->stun_request) - { - GNUNET_NAT_stun_make_request_cancel (h->stun_request); - h->stun_request = NULL; - } - h->waiting_stun = GNUNET_NO; - h->stun_request - = GNUNET_NAT_stun_make_request (elem->address, - elem->port, - h->socket, - &stun_request_callback, - h); - if (NULL == h->stun_request) - { - LOG (GNUNET_ERROR_TYPE_ERROR, - "STUN request to %s:%i failed\n", - elem->address, - elem->port); - } - h->stun_task = - GNUNET_SCHEDULER_add_delayed (h->stun_frequency, - &process_stun, - h); - - /* Set actual Server*/ - if (NULL != elem->next) - { - h->actual_stun_server = elem->next; - } - else - { - h->actual_stun_server = h->stun_servers_head; - } -} - - -/** - * Task to do a lookup on our hostname for IP addresses. - * - * @param cls the NAT handle - */ -static void -resolve_hostname (void *cls) -{ - struct GNUNET_NAT_Handle *h = cls; - - h->hostname_task = NULL; - remove_from_address_list_by_source (h, LAL_HOSTNAME_DNS); - GNUNET_assert (NULL == h->hostname_dns); - h->hostname_dns = - GNUNET_RESOLVER_hostname_resolve (AF_UNSPEC, - HOSTNAME_RESOLVE_TIMEOUT, - &process_hostname_ip, - h); -} - - -/** - * Task to do DNS lookup on our external hostname to - * get DynDNS-IP addresses. - * - * @param cls the NAT handle - */ -static void -resolve_dns (void *cls) -{ - struct GNUNET_NAT_Handle *h = cls; - struct LocalAddressList *pos; - - h->dns_task = NULL; - for (pos = h->lal_head; NULL != pos; pos = pos->next) - if (pos->source == LAL_EXTERNAL_IP) - pos->source = LAL_EXTERNAL_IP_OLD; - LOG (GNUNET_ERROR_TYPE_DEBUG, - "Resolving external address `%s'\n", - h->external_address); - GNUNET_assert (NULL == h->ext_dns); - h->ext_dns = - GNUNET_RESOLVER_ip_get (h->external_address, - AF_INET, - GNUNET_TIME_UNIT_MINUTES, - &process_external_ip, - h); -} - - -/** - * Add or remove UPnP-mapped addresses. - * - * @param cls the `struct GNUNET_NAT_Handle` - * @param add_remove #GNUNET_YES to mean the new public IP address, #GNUNET_NO to mean - * the previous (now invalid) one - * @param addr either the previous or the new public IP address - * @param addrlen actual lenght of @a addr - * @param ret GNUNET_NAT_ERROR_SUCCESS on success, otherwise an error code - */ -static void -upnp_add (void *cls, - int add_remove, - const struct sockaddr *addr, - socklen_t addrlen, - enum GNUNET_NAT_StatusCode ret) -{ - struct GNUNET_NAT_Handle *h = cls; - struct LocalAddressList *pos; - struct LocalAddressList *next; - - - if (GNUNET_NAT_ERROR_SUCCESS != ret) - { - /* Error while running upnp client */ - LOG (GNUNET_ERROR_TYPE_ERROR, - _("Error while running upnp client:\n")); - //FIXME: convert error code to string - return; - } - - if (GNUNET_YES == add_remove) - { - add_to_address_list (h, - LAL_UPNP, - addr, - addrlen); - return; - } - else if (GNUNET_NO == add_remove) - { - /* remove address */ - next = h->lal_head; - while (NULL != (pos = next)) - { - next = pos->next; - if ((pos->source != LAL_UPNP) || (pos->addrlen != addrlen) || - (0 != memcmp (&pos[1], addr, addrlen))) - continue; - GNUNET_CONTAINER_DLL_remove (h->lal_head, - h->lal_tail, - pos); - if (NULL != h->address_callback) - h->address_callback (h->callback_cls, - GNUNET_NO, - (const struct sockaddr *) &pos[1], - pos->addrlen); - GNUNET_free (pos); - return; /* only remove once */ - } - /* asked to remove address that does not exist */ - LOG (GNUNET_ERROR_TYPE_ERROR, - "Asked to remove unkown address `%s'\n", - GNUNET_a2s(addr, addrlen)); - GNUNET_break (0); - } - else - { - - GNUNET_break (0); - } -} - - -/** - * Try to add a port mapping using UPnP. - * - * @param h overall NAT handle - * @param port port to map with UPnP - */ -static void -add_minis (struct GNUNET_NAT_Handle *h, - uint16_t port) -{ - struct MiniList *ml; - - ml = h->mini_head; - while (NULL != ml) - { - if (port == ml->port) - return; /* already got this port */ - ml = ml->next; - } - - ml = GNUNET_new (struct MiniList); - ml->port = port; - ml->mini = GNUNET_NAT_mini_map_start (port, h->is_tcp, &upnp_add, h); - - if (NULL == ml->mini) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - _("Failed to run upnp client for port %u\n"), ml->port); - GNUNET_free (ml); - return; - } - - GNUNET_CONTAINER_DLL_insert (h->mini_head, - h->mini_tail, - ml); -} - - -/** - * Task to add addresses from original bind to set of valid addrs. - * - * @param h the NAT handle - */ -static void -add_from_bind (struct GNUNET_NAT_Handle *h) -{ - static struct in6_addr any = IN6ADDR_ANY_INIT; - - unsigned int i; - struct sockaddr *sa; - const struct sockaddr_in *v4; - - for (i = 0; i < h->num_local_addrs; i++) - { - sa = h->local_addrs[i]; - switch (sa->sa_family) - { - case AF_INET: - if (sizeof (struct sockaddr_in) != h->local_addrlens[i]) - { - GNUNET_break (0); - break; - } - v4 = (const struct sockaddr_in *) sa; - if (0 != v4->sin_addr.s_addr) - add_to_address_list (h, - LAL_BINDTO_ADDRESS, sa, - sizeof (struct sockaddr_in)); - if (h->enable_upnp) - { - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "Running upnp client for address `%s'\n", - GNUNET_a2s (sa,sizeof (struct sockaddr_in))); - add_minis (h, ntohs (v4->sin_port)); - } - break; - case AF_INET6: - if (sizeof (struct sockaddr_in6) != h->local_addrlens[i]) - { - GNUNET_break (0); - break; - } - if (0 != - memcmp (&((const struct sockaddr_in6 *) sa)->sin6_addr, - &any, - sizeof (struct in6_addr))) - add_to_address_list (h, - LAL_BINDTO_ADDRESS, - sa, - sizeof (struct sockaddr_in6)); - break; - default: - break; - } - } -} - - -/** - * Attempt to enable port redirection and detect public IP address contacting - * UPnP or NAT-PMP routers on the local network. Use addr to specify to which - * of the local host's addresses should the external port be mapped. The port - * is taken from the corresponding sockaddr_in[6] field. - * - * @param cfg configuration to use - * @param is_tcp #GNUNET_YES for TCP, #GNUNET_NO for UDP - * @param adv_port advertised port (port we are either bound to or that our OS - * locally performs redirection from to our bound port). - * @param num_addrs number of addresses in @a addrs - * @param addrs the local addresses packets should be redirected to - * @param addrlens actual lengths of the addresses - * @param address_callback function to call everytime the public IP address changes - * @param reversal_callback function to call if someone wants connection reversal from us - * @param callback_cls closure for callbacks - * @param sock used socket - * @return NULL on error, otherwise handle that can be used to unregister - */ -struct GNUNET_NAT_Handle * -GNUNET_NAT_register (const struct GNUNET_CONFIGURATION_Handle *cfg, - int is_tcp, - uint16_t adv_port, - unsigned int num_addrs, - const struct sockaddr **addrs, - const socklen_t *addrlens, - GNUNET_NAT_AddressCallback address_callback, - GNUNET_NAT_ReversalCallback reversal_callback, - void *callback_cls, - struct GNUNET_NETWORK_Handle *sock) -{ - struct GNUNET_NAT_Handle *h; - struct in_addr in_addr; - unsigned int i; - char *binary; - - LOG (GNUNET_ERROR_TYPE_DEBUG, - "Registered with NAT service at port %u with %u IP bound local addresses\n", - (unsigned int) adv_port, num_addrs); - h = GNUNET_new (struct GNUNET_NAT_Handle); - h->server_retry_delay = GNUNET_TIME_UNIT_SECONDS; - h->cfg = cfg; - h->is_tcp = is_tcp; - h->address_callback = address_callback; - h->reversal_callback = reversal_callback; - h->callback_cls = callback_cls; - h->num_local_addrs = num_addrs; - h->adv_port = adv_port; - if (0 != num_addrs) - { - h->local_addrs = GNUNET_malloc (num_addrs * sizeof (struct sockaddr *)); - h->local_addrlens = GNUNET_malloc (num_addrs * sizeof (socklen_t)); - for (i = 0; i < num_addrs; i++) - { - GNUNET_assert (addrlens[i] > 0); - GNUNET_assert (addrs[i] != NULL); - h->local_addrlens[i] = addrlens[i]; - h->local_addrs[i] = GNUNET_malloc (addrlens[i]); - GNUNET_memcpy (h->local_addrs[i], addrs[i], addrlens[i]); - } - } - if (GNUNET_OK == - GNUNET_CONFIGURATION_have_value (cfg, "nat", "INTERNAL_ADDRESS")) - { - (void) GNUNET_CONFIGURATION_get_value_string (cfg, "nat", - "INTERNAL_ADDRESS", - &h->internal_address); - } - if ((h->internal_address != NULL) && - (inet_pton (AF_INET, h->internal_address, &in_addr) != 1)) - { - GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_WARNING, - "nat", "INTERNAL_ADDRESS", - _("malformed")); - GNUNET_free (h->internal_address); - h->internal_address = NULL; - } - - if (GNUNET_OK == - GNUNET_CONFIGURATION_have_value (cfg, "nat", "EXTERNAL_ADDRESS")) - { - (void) GNUNET_CONFIGURATION_get_value_string (cfg, "nat", - "EXTERNAL_ADDRESS", - &h->external_address); - } - h->behind_nat = - GNUNET_CONFIGURATION_get_value_yesno (cfg, "nat", "BEHIND_NAT"); - h->nat_punched = - GNUNET_CONFIGURATION_get_value_yesno (cfg, "nat", "PUNCHED_NAT"); - h->enable_nat_client = - GNUNET_CONFIGURATION_get_value_yesno (cfg, "nat", "ENABLE_ICMP_CLIENT"); - h->enable_nat_server = - GNUNET_CONFIGURATION_get_value_yesno (cfg, "nat", "ENABLE_ICMP_SERVER"); - h->enable_upnp = - GNUNET_CONFIGURATION_get_value_yesno (cfg, "nat", "ENABLE_UPNP"); - h->use_localaddresses = - GNUNET_CONFIGURATION_get_value_yesno (cfg, "nat", "USE_LOCALADDR"); - h->return_localaddress = - GNUNET_CONFIGURATION_get_value_yesno (cfg, "nat", - "RETURN_LOCAL_ADDRESSES"); - - h->use_hostname = - GNUNET_CONFIGURATION_get_value_yesno (cfg, "nat", "USE_HOSTNAME"); - h->disable_ipv6 = - GNUNET_CONFIGURATION_get_value_yesno (cfg, "nat", "DISABLEV6"); - if (GNUNET_OK != - GNUNET_CONFIGURATION_get_value_time (cfg, "nat", "DYNDNS_FREQUENCY", - &h->dyndns_frequency)) - h->dyndns_frequency = DYNDNS_FREQUENCY; - if (GNUNET_OK != - GNUNET_CONFIGURATION_get_value_time (cfg, "nat", "IFC_SCAN_FREQUENCY", - &h->ifc_scan_frequency)) - h->ifc_scan_frequency = IFC_SCAN_FREQUENCY; - if (GNUNET_OK != - GNUNET_CONFIGURATION_get_value_time (cfg, "nat", "HOSTNAME_DNS_FREQUENCY", - &h->hostname_dns_frequency)) - h->hostname_dns_frequency = HOSTNAME_DNS_FREQUENCY; - - if (NULL == reversal_callback) - h->enable_nat_server = GNUNET_NO; - - /* Check for UPnP client, disable immediately if not available */ - if ( (GNUNET_YES == h->enable_upnp) && - (GNUNET_SYSERR == - GNUNET_OS_check_helper_binary ("upnpc", GNUNET_NO, NULL)) ) - { - LOG (GNUNET_ERROR_TYPE_ERROR, - _("UPnP enabled in configuration, but UPnP client `upnpc` command not found, disabling UPnP \n")); - h->enable_upnp = GNUNET_NO; - } - - /* STUN */ - h->use_stun = - GNUNET_CONFIGURATION_get_value_yesno (cfg, - "nat", - "USE_STUN"); - - if (GNUNET_OK != - GNUNET_CONFIGURATION_get_value_time (cfg, - "nat", - "STUN_FREQUENCY", - &h->stun_frequency)) - h->stun_frequency = STUN_FREQUENCY; - - - /* Check if NAT was hole-punched */ - if ((NULL != h->address_callback) && - (NULL != h->external_address) && - (GNUNET_YES == h->nat_punched)) - { - h->dns_task = GNUNET_SCHEDULER_add_now (&resolve_dns, h); - h->enable_nat_server = GNUNET_NO; - h->enable_upnp = GNUNET_NO; - h->use_stun = GNUNET_NO; - } - else - { - LOG (GNUNET_ERROR_TYPE_DEBUG, - "No external IP address given to add to our list of addresses\n"); - } - - /* ENABLE STUN ONLY ON UDP */ - if( (! is_tcp) && - (NULL != sock) && - h->use_stun) - { - char *stun_servers; - size_t urls; - ssize_t pos; - size_t pos_port; - - h->socket = sock; - stun_servers = NULL; - /* Lets process the servers*/ - (void) GNUNET_CONFIGURATION_get_value_string (cfg, - "nat", - "STUN_SERVERS", - &stun_servers); - urls = 0; - if ( (NULL != stun_servers) && - (strlen (stun_servers) > 0) ) - { - pos_port = 0; - for (pos = strlen (stun_servers) - 1; - pos >= 0; - pos--) - { - if (stun_servers[pos] == ':') - { - pos_port = pos + 1; - stun_servers[pos] = '\0'; - continue; - } - if ((stun_servers[pos] == ' ') || (0 == pos)) - { - struct StunServerList *ml; - - /* Check if we do have a port */ - if ((0 == pos_port) || (pos_port <= pos)) - { - LOG (GNUNET_ERROR_TYPE_WARNING, - "STUN server format mistake\n"); - break; - } - urls++; - ml = GNUNET_new (struct StunServerList); - ml->port = atoi (&stun_servers[pos_port]); - - /* Remove trailing space */ - if (stun_servers[pos] == ' ') - ml->address = GNUNET_strdup (&stun_servers[pos + 1]); - else - ml->address = GNUNET_strdup (&stun_servers[pos]); - LOG (GNUNET_ERROR_TYPE_DEBUG, - "Found STUN server %s:%i\n", - ml->address, - ml->port); - GNUNET_CONTAINER_DLL_insert (h->stun_servers_head, - h->stun_servers_tail, - ml); - stun_servers[pos] = '\0'; - } - } - } - if (0 == urls) - { - GNUNET_log_config_missing (GNUNET_ERROR_TYPE_WARNING, - "nat", - "STUN_SERVERS"); - } - else - { - /* Set the actual STUN server*/ - h->actual_stun_server = h->stun_servers_head; - } - h->stun_task = GNUNET_SCHEDULER_add_now (&process_stun, - h); - GNUNET_free_non_null (stun_servers); - } - - - /* Test for SUID binaries */ - binary = GNUNET_OS_get_libexec_binary_path ("gnunet-helper-nat-server"); - if ( (GNUNET_YES == h->behind_nat) && - (GNUNET_YES == h->enable_nat_server) && - (GNUNET_YES != - GNUNET_OS_check_helper_binary (binary, - GNUNET_YES, - "-d 127.0.0.1" ))) - { - // use localhost as source for that one udp-port, ok for testing - h->enable_nat_server = GNUNET_NO; - LOG (GNUNET_ERROR_TYPE_WARNING, - _("Configuration requires `%s', but binary is not installed properly (SUID bit not set). Option disabled.\n"), - "gnunet-helper-nat-server"); - } - GNUNET_free (binary); - binary = GNUNET_OS_get_libexec_binary_path ("gnunet-helper-nat-client"); - if ((GNUNET_YES == h->enable_nat_client) && - (GNUNET_YES != - GNUNET_OS_check_helper_binary (binary, - GNUNET_YES, - "-d 127.0.0.1 127.0.0.2 42"))) /* none of these parameters are actually used in privilege testing mode */ - { - h->enable_nat_client = GNUNET_NO; - LOG (GNUNET_ERROR_TYPE_WARNING, - _("Configuration requires `%s', but binary is not installed properly (SUID bit not set). Option disabled.\n"), - "gnunet-helper-nat-client"); - } - GNUNET_free (binary); - start_gnunet_nat_server (h); - - /* FIXME: add support for UPnP, etc */ - - if (NULL != h->address_callback) - { - h->ifc_task = GNUNET_SCHEDULER_add_now (&list_interfaces, - h); - if (GNUNET_YES == h->use_hostname) - h->hostname_task = GNUNET_SCHEDULER_add_now (&resolve_hostname, - h); - } - add_from_bind (h); - - return h; -} - - -/** - * Stop port redirection and public IP address detection for the given handle. - * This frees the handle, after having sent the needed commands to close open ports. - * - * @param h the handle to stop - */ -void -GNUNET_NAT_unregister (struct GNUNET_NAT_Handle *h) -{ - unsigned int i; - struct LocalAddressList *lal; - struct MiniList *ml; - struct StunServerList *ssl; - - LOG (GNUNET_ERROR_TYPE_DEBUG, - "NAT unregister called\n"); - while (NULL != (ssl = h->stun_servers_head)) - { - GNUNET_CONTAINER_DLL_remove (h->stun_servers_head, - h->stun_servers_tail, - ssl); - GNUNET_free (ssl->address); - GNUNET_free (ssl); - } - while (NULL != (lal = h->lal_head)) - { - GNUNET_CONTAINER_DLL_remove (h->lal_head, - h->lal_tail, - lal); - if (NULL != h->address_callback) - h->address_callback (h->callback_cls, - GNUNET_NO, - (const struct sockaddr *) &lal[1], - lal->addrlen); - GNUNET_free (lal); - } - while (NULL != (ml = h->mini_head)) - { - GNUNET_CONTAINER_DLL_remove (h->mini_head, - h->mini_tail, - ml); - if (NULL != ml->mini) - GNUNET_NAT_mini_map_stop (ml->mini); - GNUNET_free (ml); - } - if (NULL != h->ext_dns) - { - GNUNET_RESOLVER_request_cancel (h->ext_dns); - h->ext_dns = NULL; - } - if (NULL != h->hostname_dns) - { - GNUNET_RESOLVER_request_cancel (h->hostname_dns); - h->hostname_dns = NULL; - } - if (NULL != h->server_read_task) - { - GNUNET_SCHEDULER_cancel (h->server_read_task); - h->server_read_task = NULL; - } - if (NULL != h->ifc_task) - { - GNUNET_SCHEDULER_cancel (h->ifc_task); - h->ifc_task = NULL; - } - if (NULL != h->hostname_task) - { - GNUNET_SCHEDULER_cancel (h->hostname_task); - h->hostname_task = NULL; - } - if (NULL != h->dns_task) - { - GNUNET_SCHEDULER_cancel (h->dns_task); - h->dns_task = NULL; - } - if (NULL != h->stun_task) - { - GNUNET_SCHEDULER_cancel (h->stun_task); - h->stun_task = NULL; - } - if (NULL != h->stun_request) - { - GNUNET_NAT_stun_make_request_cancel (h->stun_request); - h->stun_request = NULL; - } - if (NULL != h->server_proc) - { - if (0 != GNUNET_OS_process_kill (h->server_proc, - GNUNET_TERM_SIG)) - GNUNET_log_from_strerror (GNUNET_ERROR_TYPE_WARNING, - "nat", - "kill"); - GNUNET_OS_process_wait (h->server_proc); - GNUNET_OS_process_destroy (h->server_proc); - h->server_proc = NULL; - GNUNET_DISK_pipe_close (h->server_stdout); - h->server_stdout = NULL; - h->server_stdout_handle = NULL; - } - if (NULL != h->server_stdout) - { - GNUNET_DISK_pipe_close (h->server_stdout); - h->server_stdout = NULL; - h->server_stdout_handle = NULL; - } - for (i = 0; i < h->num_local_addrs; i++) - GNUNET_free (h->local_addrs[i]); - GNUNET_free_non_null (h->local_addrs); - GNUNET_free_non_null (h->local_addrlens); - GNUNET_free_non_null (h->external_address); - GNUNET_free_non_null (h->internal_address); - GNUNET_free (h); -} - - -/** - * We learned about a peer (possibly behind NAT) so run the - * gnunet-helper-nat-client to send dummy ICMP responses to cause - * that peer to connect to us (connection reversal). - * - * @param h handle (used for configuration) - * @param sa the address of the peer (IPv4-only) - * @return #GNUNET_SYSERR on error, #GNUNET_NO if nat client is disabled, - * #GNUNET_OK otherwise - */ -int -GNUNET_NAT_run_client (struct GNUNET_NAT_Handle *h, - const struct sockaddr_in *sa) - - -{ - char inet4[INET_ADDRSTRLEN]; - char port_as_string[6]; - struct GNUNET_OS_Process *proc; - char *binary; - - if (GNUNET_YES != h->enable_nat_client) - return GNUNET_NO; /* not permitted / possible */ - - if (h->internal_address == NULL) - { - LOG (GNUNET_ERROR_TYPE_WARNING, "nat", - _("Internal IP address not known, cannot use ICMP NAT traversal method\n")); - return GNUNET_SYSERR; - } - GNUNET_assert (sa->sin_family == AF_INET); - if (NULL == inet_ntop (AF_INET, &sa->sin_addr, inet4, INET_ADDRSTRLEN)) - { - GNUNET_log_from_strerror (GNUNET_ERROR_TYPE_WARNING, - "nat", - "inet_ntop"); - return GNUNET_SYSERR; - } - GNUNET_snprintf (port_as_string, - sizeof (port_as_string), - "%d", - h->adv_port); - LOG (GNUNET_ERROR_TYPE_DEBUG, - _("Running gnunet-helper-nat-client %s %s %u\n"), - h->internal_address, - inet4, - (unsigned int) h->adv_port); - binary = GNUNET_OS_get_libexec_binary_path ("gnunet-helper-nat-client"); - proc = - GNUNET_OS_start_process (GNUNET_NO, 0, NULL, NULL, NULL, - binary, - "gnunet-helper-nat-client", - h->internal_address, - inet4, port_as_string, NULL); - GNUNET_free (binary); - if (NULL == proc) - return GNUNET_SYSERR; - /* we know that the gnunet-helper-nat-client will terminate virtually - * instantly */ - GNUNET_OS_process_wait (proc); - GNUNET_OS_process_destroy (proc); - return GNUNET_OK; -} - - -/** - * Test if the given address is (currently) a plausible IP address for this peer. - * - * @param h the handle returned by register - * @param addr IP address to test (IPv4 or IPv6) - * @param addrlen number of bytes in @a addr - * @return #GNUNET_YES if the address is plausible, - * #GNUNET_NO if the address is not plausible, - * #GNUNET_SYSERR if the address is malformed - */ -int -GNUNET_NAT_test_address (struct GNUNET_NAT_Handle *h, - const void *addr, - socklen_t addrlen) -{ - struct LocalAddressList *pos; - const struct sockaddr_in *in4; - const struct sockaddr_in6 *in6; - char pbuf[INET6_ADDRSTRLEN+1]; - - if ((addrlen != sizeof (struct in_addr)) && - (addrlen != sizeof (struct in6_addr))) - { - GNUNET_break (0); - return GNUNET_SYSERR; - } - for (pos = h->lal_head; NULL != pos; pos = pos->next) - { - if (pos->addrlen == sizeof (struct sockaddr_in)) - { - in4 = (struct sockaddr_in *) &pos[1]; - if ((addrlen == sizeof (struct in_addr)) && - (0 == memcmp (&in4->sin_addr, addr, sizeof (struct in_addr)))) - return GNUNET_YES; - } - else if (pos->addrlen == sizeof (struct sockaddr_in6)) - { - in6 = (struct sockaddr_in6 *) &pos[1]; - if ((addrlen == sizeof (struct in6_addr)) && - (0 == memcmp (&in6->sin6_addr, addr, sizeof (struct in6_addr)))) - return GNUNET_YES; - } - else - { - GNUNET_assert (0); - } - } - LOG (GNUNET_ERROR_TYPE_WARNING, - "Asked to validate one of my addresses (%s) and validation failed!\n", - inet_ntop ((addrlen == sizeof(struct in_addr)) - ? AF_INET - : AF_INET6, - addr, - pbuf, sizeof (pbuf))); - return GNUNET_NO; -} - -/** - * Converts enum GNUNET_NAT_StatusCode to a string - * - * @param err error code to resolve to a string - * @return pointer to a static string containing the error code - */ -const char * -GNUNET_NAT_status2string (enum GNUNET_NAT_StatusCode err) -{ - switch (err) - { - case GNUNET_NAT_ERROR_SUCCESS: - return _ ("Operation Successful"); - case GNUNET_NAT_ERROR_IPC_FAILURE: - return _ ("Internal Failure (IPC, ...)"); - case GNUNET_NAT_ERROR_INTERNAL_NETWORK_ERROR: - return _ ("Failure in network subsystem, check permissions."); - case GNUNET_NAT_ERROR_TIMEOUT: - return _ ("Encountered timeout while performing operation"); - case GNUNET_NAT_ERROR_NOT_ONLINE: - return _ ("detected that we are offline"); - case GNUNET_NAT_ERROR_UPNPC_NOT_FOUND: - return _ ("`upnpc` command not found"); - case GNUNET_NAT_ERROR_UPNPC_FAILED: - return _ ("Failed to run `upnpc` command"); - case GNUNET_NAT_ERROR_UPNPC_TIMEOUT: - return _ ("`upnpc' command took too long, process killed"); - case GNUNET_NAT_ERROR_UPNPC_PORTMAP_FAILED: - return _ ("`upnpc' command failed to establish port mapping"); - case GNUNET_NAT_ERROR_EXTERNAL_IP_UTILITY_NOT_FOUND: - return _ ("`external-ip' command not found"); - case GNUNET_NAT_ERROR_EXTERNAL_IP_UTILITY_FAILED: - return _ ("Failed to run `external-ip` command"); - case GNUNET_NAT_ERROR_EXTERNAL_IP_UTILITY_OUTPUT_INVALID: - return _ ("`external-ip' command output invalid"); - case GNUNET_NAT_ERROR_EXTERNAL_IP_ADDRESS_INVALID: - return _ ("no valid address was returned by `external-ip'"); - case GNUNET_NAT_ERROR_NO_VALID_IF_IP_COMBO: - return _ ("Could not determine interface with internal/local network address"); - case GNUNET_NAT_ERROR_HELPER_NAT_SERVER_NOT_FOUND: - return _ ("No functioning gnunet-helper-nat-server installation found"); - case GNUNET_NAT_ERROR_NAT_TEST_START_FAILED: - return _ ("NAT test could not be initialized"); - case GNUNET_NAT_ERROR_NAT_TEST_TIMEOUT: - return _ ("NAT test timeout reached"); - case GNUNET_NAT_ERROR_NAT_REGISTER_FAILED: - return _ ("could not register NAT"); - case GNUNET_NAT_ERROR_HELPER_NAT_CLIENT_NOT_FOUND: - return _ ("No working gnunet-helper-nat-client installation found"); -/* case: - return _ ("");*/ - default: - return "unknown status code"; - } -} - -/* end of nat.c */ diff --git a/src/nat/nat_mini.c b/src/nat/nat_mini.c deleted file mode 100644 index 915bcbdb6..000000000 --- a/src/nat/nat_mini.c +++ /dev/null @@ -1,712 +0,0 @@ -/* - This file is part of GNUnet. - Copyright (C) 2011-2014 GNUnet e.V. - - GNUnet is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published - by the Free Software Foundation; either version 3, or (at your - option) any later version. - - GNUnet is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with GNUnet; see the file COPYING. If not, write to the - Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - Boston, MA 02110-1301, USA. -*/ - -/** - * @file nat/nat_mini.c - * @brief functions for interaction with miniupnp; tested with miniupnpc 1.5 - * @author Christian Grothoff - */ -#include "platform.h" -#include "gnunet_util_lib.h" -#include "gnunet_nat_lib.h" -#include "nat.h" - -#define LOG(kind,...) GNUNET_log_from (kind, "nat", __VA_ARGS__) - -/** - * How long do we give upnpc to create a mapping? - */ -#define MAP_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 15) - -/** - * How long do we give upnpc to remove a mapping? - */ -#define UNMAP_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 1) - -/** - * How often do we check for changes in the mapping? - */ -#define MAP_REFRESH_FREQ GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 5) - - - -/** - * Opaque handle to cancel "GNUNET_NAT_mini_get_external_ipv4" operation. - */ -struct GNUNET_NAT_ExternalHandle -{ - - /** - * Function to call with the result. - */ - GNUNET_NAT_IPCallback cb; - - /** - * Closure for @e cb. - */ - void *cb_cls; - - /** - * Read task. - */ - struct GNUNET_SCHEDULER_Task * task; - - /** - * Handle to 'external-ip' process. - */ - struct GNUNET_OS_Process *eip; - - /** - * Handle to stdout pipe of 'external-ip'. - */ - struct GNUNET_DISK_PipeHandle *opipe; - - /** - * Read handle of @e opipe. - */ - const struct GNUNET_DISK_FileHandle *r; - - /** - * When should this operation time out? - */ - struct GNUNET_TIME_Absolute timeout; - - /** - * Number of bytes in 'buf' that are valid. - */ - size_t off; - - /** - * Destination of our read operation (output of 'external-ip'). - */ - char buf[17]; - - /** - * Error code for better debugging and user feedback - */ - enum GNUNET_NAT_StatusCode ret; -}; - - -/** - * Read the output of 'external-ip' into buf. When complete, parse the - * address and call our callback. - * - * @param cls the `struct GNUNET_NAT_ExternalHandle` - */ -static void -read_external_ipv4 (void *cls) -{ - struct GNUNET_NAT_ExternalHandle *eh = cls; - ssize_t ret; - struct in_addr addr; - const struct GNUNET_SCHEDULER_TaskContext *tc; - - eh->task = NULL; - tc = GNUNET_SCHEDULER_get_task_context (); - if (GNUNET_YES == - GNUNET_NETWORK_fdset_handle_isset (tc->read_ready, eh->r)) - { - ret = - GNUNET_DISK_file_read (eh->r, &eh->buf[eh->off], - sizeof (eh->buf) - eh->off); - } - else - { - eh->ret = GNUNET_NAT_ERROR_IPC_FAILURE; - ret = -1; /* error reading, timeout, etc. */ - } - if (ret > 0) - { - /* try to read more */ - eh->off += ret; - eh->task = - GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_absolute_get_remaining - (eh->timeout), eh->r, - &read_external_ipv4, eh); - return; - } - eh->ret = GNUNET_NAT_ERROR_EXTERNAL_IP_UTILITY_OUTPUT_INVALID; - if ((eh->off > 7) && (eh->buf[eh->off - 1] == '\n')) - { - eh->buf[eh->off - 1] = '\0'; - if (1 == inet_pton (AF_INET, eh->buf, &addr)) - { - if (0 != addr.s_addr) - eh->ret = GNUNET_NAT_ERROR_EXTERNAL_IP_ADDRESS_INVALID; /* got 0.0.0.0 */ - else - eh->ret = GNUNET_NAT_ERROR_SUCCESS; - } - } - eh->cb (eh->cb_cls, - (GNUNET_NAT_ERROR_SUCCESS == eh->ret) ? &addr : NULL, - eh->ret); - GNUNET_NAT_mini_get_external_ipv4_cancel (eh); -} - - -/** - * (Asynchronously) signal error invoking "external-ip" to client. - * - * @param cls the `struct GNUNET_NAT_ExternalHandle` (freed) - */ -static void -signal_external_ip_error (void *cls) -{ - struct GNUNET_NAT_ExternalHandle *eh = cls; - - eh->task = NULL; - eh->cb (eh->cb_cls, - NULL, - eh->ret); - GNUNET_free (eh); -} - - -/** - * Try to get the external IPv4 address of this peer. - * - * @param timeout when to fail - * @param cb function to call with result - * @param cb_cls closure for @a cb - * @return handle for cancellation (can only be used until @a cb is called), never NULL - */ -struct GNUNET_NAT_ExternalHandle * -GNUNET_NAT_mini_get_external_ipv4 (struct GNUNET_TIME_Relative timeout, - GNUNET_NAT_IPCallback cb, void *cb_cls) -{ - struct GNUNET_NAT_ExternalHandle *eh; - - eh = GNUNET_new (struct GNUNET_NAT_ExternalHandle); - eh->cb = cb; - eh->cb_cls = cb_cls; - eh->ret = GNUNET_NAT_ERROR_SUCCESS; - if (GNUNET_SYSERR == - GNUNET_OS_check_helper_binary ("external-ip", GNUNET_NO, NULL)) - { - LOG (GNUNET_ERROR_TYPE_INFO, - _("`external-ip' command not found\n")); - eh->ret = GNUNET_NAT_ERROR_EXTERNAL_IP_UTILITY_NOT_FOUND; - eh->task = GNUNET_SCHEDULER_add_now (&signal_external_ip_error, - eh); - return eh; - } - LOG (GNUNET_ERROR_TYPE_DEBUG, - "Running `external-ip' to determine our external IP\n"); - eh->opipe = GNUNET_DISK_pipe (GNUNET_YES, GNUNET_YES, GNUNET_NO, GNUNET_YES); - if (NULL == eh->opipe) - { - eh->ret = GNUNET_NAT_ERROR_IPC_FAILURE; - eh->task = GNUNET_SCHEDULER_add_now (&signal_external_ip_error, - eh); - return eh; - } - eh->eip = - GNUNET_OS_start_process (GNUNET_NO, 0, NULL, eh->opipe, NULL, - "external-ip", "external-ip", - NULL); - if (NULL == eh->eip) - { - GNUNET_DISK_pipe_close (eh->opipe); - eh->ret = GNUNET_NAT_ERROR_EXTERNAL_IP_UTILITY_FAILED; - eh->task = GNUNET_SCHEDULER_add_now (&signal_external_ip_error, - eh); - return eh; - } - GNUNET_DISK_pipe_close_end (eh->opipe, GNUNET_DISK_PIPE_END_WRITE); - eh->timeout = GNUNET_TIME_relative_to_absolute (timeout); - eh->r = GNUNET_DISK_pipe_handle (eh->opipe, GNUNET_DISK_PIPE_END_READ); - eh->task = - GNUNET_SCHEDULER_add_read_file (timeout, - eh->r, - &read_external_ipv4, eh); - return eh; -} - - -/** - * Cancel operation. - * - * @param eh operation to cancel - */ -void -GNUNET_NAT_mini_get_external_ipv4_cancel (struct GNUNET_NAT_ExternalHandle *eh) -{ - if (NULL != eh->eip) - { - (void) GNUNET_OS_process_kill (eh->eip, SIGKILL); - GNUNET_OS_process_destroy (eh->eip); - } - if (NULL != eh->opipe) - GNUNET_DISK_pipe_close (eh->opipe); - if (NULL != eh->task) - GNUNET_SCHEDULER_cancel (eh->task); - GNUNET_free (eh); -} - - -/** - * Handle to a mapping created with upnpc. - */ -struct GNUNET_NAT_MiniHandle -{ - - /** - * Function to call on mapping changes. - */ - GNUNET_NAT_MiniAddressCallback ac; - - /** - * Closure for @e ac. - */ - void *ac_cls; - - /** - * Command used to install the map. - */ - struct GNUNET_OS_CommandHandle *map_cmd; - - /** - * Command used to refresh our map information. - */ - struct GNUNET_OS_CommandHandle *refresh_cmd; - - /** - * Command used to remove the mapping. - */ - struct GNUNET_OS_CommandHandle *unmap_cmd; - - /** - * Our current external mapping (if we have one). - */ - struct sockaddr_in current_addr; - - /** - * We check the mapping periodically to see if it - * still works. This task triggers the check. - */ - struct GNUNET_SCHEDULER_Task * refresh_task; - - /** - * Are we mapping TCP or UDP? - */ - int is_tcp; - - /** - * Did we succeed with creating a mapping? - */ - int did_map; - - /** - * Did we find our mapping during refresh scan? - */ - int found; - - /** - * Which port are we mapping? - */ - uint16_t port; - -}; - - -/** - * Run "upnpc -l" to find out if our mapping changed. - * - * @param cls the `struct GNUNET_NAT_MiniHandle` - */ -static void -do_refresh (void *cls); - - -/** - * Process the output from the "upnpc -r" command. - * - * @param cls the `struct GNUNET_NAT_MiniHandle` - * @param line line of output, NULL at the end - */ -static void -process_map_output (void *cls, const char *line); - - -/** - * Run "upnpc -r" to map our internal port. - * - * @param mini our handle - */ -static void -run_upnpc_r (struct GNUNET_NAT_MiniHandle *mini) -{ - char pstr[6]; - - GNUNET_snprintf (pstr, - sizeof (pstr), - "%u", - (unsigned int) mini->port); - mini->map_cmd = - GNUNET_OS_command_run (&process_map_output, mini, MAP_TIMEOUT, - "upnpc", "upnpc", "-r", pstr, - mini->is_tcp ? "tcp" : "udp", NULL); - if (NULL == mini->map_cmd) - { - mini->ac (mini->ac_cls, - GNUNET_SYSERR, - NULL, 0, - GNUNET_NAT_ERROR_UPNPC_FAILED); - return; - } -} - - -/** - * Process the output from "upnpc -l" to see if our - * external mapping changed. If so, do the notifications. - * - * @param cls the `struct GNUNET_NAT_MiniHandle` - * @param line line of output, NULL at the end - */ -static void -process_refresh_output (void *cls, const char *line) -{ - struct GNUNET_NAT_MiniHandle *mini = cls; - char pstr[9]; - const char *s; - unsigned int nport; - struct in_addr exip; - - if (NULL == line) - { - GNUNET_OS_command_stop (mini->refresh_cmd); - mini->refresh_cmd = NULL; - if (GNUNET_NO == mini->found) - { - /* mapping disappeared, try to re-create */ - if (GNUNET_YES == mini->did_map) - { - mini->ac (mini->ac_cls, - GNUNET_NO, - (const struct sockaddr *) &mini->current_addr, - sizeof (mini->current_addr), - GNUNET_NAT_ERROR_SUCCESS); - mini->did_map = GNUNET_NO; - } - run_upnpc_r (mini); - } - return; - } - if (!mini->did_map) - return; /* never mapped, won't find our mapping anyway */ - - /* we're looking for output of the form: - * "ExternalIPAddress = 12.134.41.124" */ - - s = strstr (line, "ExternalIPAddress = "); - if (NULL != s) - { - s += strlen ("ExternalIPAddress = "); - if (1 != inet_pton (AF_INET, s, &exip)) - return; /* skip */ - if (exip.s_addr == mini->current_addr.sin_addr.s_addr) - return; /* no change */ - /* update mapping */ - mini->ac (mini->ac_cls, GNUNET_NO, - (const struct sockaddr *) &mini->current_addr, - sizeof (mini->current_addr), - GNUNET_NAT_ERROR_SUCCESS); - mini->current_addr.sin_addr = exip; - mini->ac (mini->ac_cls, GNUNET_YES, - (const struct sockaddr *) &mini->current_addr, - sizeof (mini->current_addr), - GNUNET_NAT_ERROR_SUCCESS); - return; - } - /* - * we're looking for output of the form: - * - * "0 TCP 3000->192.168.2.150:3000 'libminiupnpc' ''" - * "1 UDP 3001->192.168.2.150:3001 'libminiupnpc' ''" - * - * the pattern we look for is: - * - * "%s TCP PORT->STRING:OURPORT *" or - * "%s UDP PORT->STRING:OURPORT *" - */ - GNUNET_snprintf (pstr, sizeof (pstr), ":%u ", mini->port); - if (NULL == (s = strstr (line, "->"))) - return; /* skip */ - if (NULL == strstr (s, pstr)) - return; /* skip */ - if (1 != - SSCANF (line, - (mini->is_tcp) ? "%*u TCP %u->%*s:%*u %*s" : - "%*u UDP %u->%*s:%*u %*s", &nport)) - return; /* skip */ - mini->found = GNUNET_YES; - if (nport == ntohs (mini->current_addr.sin_port)) - return; /* no change */ - - /* external port changed, update mapping */ - mini->ac (mini->ac_cls, GNUNET_NO, - (const struct sockaddr *) &mini->current_addr, - sizeof (mini->current_addr), - GNUNET_NAT_ERROR_SUCCESS); - mini->current_addr.sin_port = htons ((uint16_t) nport); - mini->ac (mini->ac_cls, GNUNET_YES, - (const struct sockaddr *) &mini->current_addr, - sizeof (mini->current_addr), - GNUNET_NAT_ERROR_SUCCESS); -} - - -/** - * Run "upnpc -l" to find out if our mapping changed. - * - * @param cls the 'struct GNUNET_NAT_MiniHandle' - */ -static void -do_refresh (void *cls) -{ - struct GNUNET_NAT_MiniHandle *mini = cls; - int ac; - - mini->refresh_task = - GNUNET_SCHEDULER_add_delayed (MAP_REFRESH_FREQ, - &do_refresh, mini); - LOG (GNUNET_ERROR_TYPE_DEBUG, - "Running `upnpc' to check if our mapping still exists\n"); - mini->found = GNUNET_NO; - ac = GNUNET_NO; - if (NULL != mini->map_cmd) - { - /* took way too long, abort it! */ - GNUNET_OS_command_stop (mini->map_cmd); - mini->map_cmd = NULL; - ac = GNUNET_YES; - } - if (NULL != mini->refresh_cmd) - { - /* took way too long, abort it! */ - GNUNET_OS_command_stop (mini->refresh_cmd); - mini->refresh_cmd = NULL; - ac = GNUNET_YES; - } - mini->refresh_cmd = - GNUNET_OS_command_run (&process_refresh_output, mini, MAP_TIMEOUT, - "upnpc", "upnpc", "-l", NULL); - if (GNUNET_YES == ac) - mini->ac (mini->ac_cls, - GNUNET_SYSERR, - NULL, 0, - GNUNET_NAT_ERROR_UPNPC_TIMEOUT); -} - - -/** - * Process the output from the 'upnpc -r' command. - * - * @param cls the `struct GNUNET_NAT_MiniHandle` - * @param line line of output, NULL at the end - */ -static void -process_map_output (void *cls, - const char *line) -{ - struct GNUNET_NAT_MiniHandle *mini = cls; - const char *ipaddr; - char *ipa; - const char *pstr; - unsigned int port; - - if (NULL == line) - { - GNUNET_OS_command_stop (mini->map_cmd); - mini->map_cmd = NULL; - if (GNUNET_YES != mini->did_map) - mini->ac (mini->ac_cls, - GNUNET_SYSERR, - NULL, 0, - GNUNET_NAT_ERROR_UPNPC_PORTMAP_FAILED); - if (NULL == mini->refresh_task) - mini->refresh_task = - GNUNET_SCHEDULER_add_delayed (MAP_REFRESH_FREQ, - &do_refresh, - mini); - return; - } - /* - * The upnpc output we're after looks like this: - * - * "external 87.123.42.204:3000 TCP is redirected to internal 192.168.2.150:3000" - */ - if ((NULL == (ipaddr = strstr (line, " "))) || - (NULL == (pstr = strstr (ipaddr, ":"))) || - (1 != SSCANF (pstr + 1, "%u", &port))) - { - return; /* skip line */ - } - ipa = GNUNET_strdup (ipaddr + 1); - strstr (ipa, ":")[0] = '\0'; - if (1 != inet_pton (AF_INET, ipa, &mini->current_addr.sin_addr)) - { - GNUNET_free (ipa); - return; /* skip line */ - } - GNUNET_free (ipa); - - mini->current_addr.sin_port = htons (port); - mini->current_addr.sin_family = AF_INET; -#if HAVE_SOCKADDR_IN_SIN_LEN - mini->current_addr.sin_len = sizeof (struct sockaddr_in); -#endif - mini->did_map = GNUNET_YES; - mini->ac (mini->ac_cls, GNUNET_YES, - (const struct sockaddr *) &mini->current_addr, - sizeof (mini->current_addr), - GNUNET_NAT_ERROR_SUCCESS); -} - - -/** - * Start mapping the given port using (mini)upnpc. This function - * should typically not be used directly (it is used within the - * general-purpose #GNUNET_NAT_register() code). However, it can be - * used if specifically UPnP-based NAT traversal is to be used or - * tested. - * - * @param port port to map - * @param is_tcp #GNUNET_YES to map TCP, #GNUNET_NO for UDP - * @param ac function to call with mapping result - * @param ac_cls closure for @a ac - * @return NULL on error (no 'upnpc' installed) - */ -struct GNUNET_NAT_MiniHandle * -GNUNET_NAT_mini_map_start (uint16_t port, - int is_tcp, - GNUNET_NAT_MiniAddressCallback ac, - void *ac_cls) -{ - struct GNUNET_NAT_MiniHandle *ret; - - if (GNUNET_SYSERR == - GNUNET_OS_check_helper_binary ("upnpc", GNUNET_NO, NULL)) - { - LOG (GNUNET_ERROR_TYPE_INFO, - _("`upnpc' command not found\n")); - ac (ac_cls, - GNUNET_SYSERR, - NULL, 0, - GNUNET_NAT_ERROR_UPNPC_NOT_FOUND); - return NULL; - } - LOG (GNUNET_ERROR_TYPE_DEBUG, - "Running `upnpc' to install mapping\n"); - ret = GNUNET_new (struct GNUNET_NAT_MiniHandle); - ret->ac = ac; - ret->ac_cls = ac_cls; - ret->is_tcp = is_tcp; - ret->port = port; - ret->refresh_task = - GNUNET_SCHEDULER_add_delayed (MAP_REFRESH_FREQ, - &do_refresh, - ret); - run_upnpc_r (ret); - return ret; -} - - -/** - * Process output from our 'unmap' command. - * - * @param cls the `struct GNUNET_NAT_MiniHandle` - * @param line line of output, NULL at the end - */ -static void -process_unmap_output (void *cls, const char *line) -{ - struct GNUNET_NAT_MiniHandle *mini = cls; - - if (NULL == line) - { - LOG (GNUNET_ERROR_TYPE_DEBUG, - "UPnP unmap done\n"); - GNUNET_OS_command_stop (mini->unmap_cmd); - mini->unmap_cmd = NULL; - GNUNET_free (mini); - return; - } - /* we don't really care about the output... */ -} - - -/** - * Remove a mapping created with (mini)upnpc. Calling - * this function will give 'upnpc' 1s to remove tha mapping, - * so while this function is non-blocking, a task will be - * left with the scheduler for up to 1s past this call. - * - * @param mini the handle - */ -void -GNUNET_NAT_mini_map_stop (struct GNUNET_NAT_MiniHandle *mini) -{ - char pstr[6]; - - if (NULL != mini->refresh_task) - { - GNUNET_SCHEDULER_cancel (mini->refresh_task); - mini->refresh_task = NULL; - } - if (NULL != mini->refresh_cmd) - { - GNUNET_OS_command_stop (mini->refresh_cmd); - mini->refresh_cmd = NULL; - } - if (NULL != mini->map_cmd) - { - GNUNET_OS_command_stop (mini->map_cmd); - mini->map_cmd = NULL; - } - if (GNUNET_NO == mini->did_map) - { - GNUNET_free (mini); - return; - } - mini->ac (mini->ac_cls, GNUNET_NO, - (const struct sockaddr *) &mini->current_addr, - sizeof (mini->current_addr), - GNUNET_NAT_ERROR_SUCCESS); - /* Note: oddly enough, deletion uses the external port whereas - * addition uses the internal port; this rarely matters since they - * often are the same, but it might... */ - GNUNET_snprintf (pstr, - sizeof (pstr), - "%u", - (unsigned int) ntohs (mini->current_addr.sin_port)); - LOG (GNUNET_ERROR_TYPE_DEBUG, - "Unmapping port %u with UPnP\n", - ntohs (mini->current_addr.sin_port)); - mini->unmap_cmd = - GNUNET_OS_command_run (&process_unmap_output, mini, UNMAP_TIMEOUT, - "upnpc", "upnpc", "-d", pstr, - mini->is_tcp ? "tcp" : "udp", NULL); -} - - -/* end of nat_mini.c */ diff --git a/src/nat/nat_stun.c b/src/nat/nat_stun.c deleted file mode 100644 index 62916ab84..000000000 --- a/src/nat/nat_stun.c +++ /dev/null @@ -1,439 +0,0 @@ -/* - This file is part of GNUnet. - Copyright (C) 2009, 2015 GNUnet e.V. - - GNUnet is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published - by the Free Software Foundation; either version 3, or (at your - option) any later version. - - GNUnet is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with GNUnet; see the file COPYING. If not, write to the - Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - Boston, MA 02110-1301, USA. -*/ -/** - * This code provides some support for doing STUN transactions. - * We send simplest possible packet ia REQUEST with BIND to a STUN server. - * - * All STUN packets start with a simple header made of a type, - * length (excluding the header) and a 16-byte random transaction id. - * Following the header we may have zero or more attributes, each - * structured as a type, length and a value (whose format depends - * on the type, but often contains addresses). - * Of course all fields are in network format. - * - * This code was based on ministun.c. - * - * @file nat/nat_stun.c - * @brief Functions for STUN functionality - * @author Bruno Souza Cabral - */ - -#include "platform.h" -#include "gnunet_util_lib.h" -#include "gnunet_resolver_service.h" -#include "gnunet_nat_lib.h" - - -#include "nat_stun.h" - -#define LOG(kind,...) GNUNET_log_from (kind, "stun", __VA_ARGS__) - -#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 15) - - -/** - * Handle to a request given to the resolver. Can be used to cancel - * the request prior to the timeout or successful execution. Also - * used to track our internal state for the request. - */ -struct GNUNET_NAT_STUN_Handle -{ - - /** - * Handle to a pending DNS lookup request. - */ - struct GNUNET_RESOLVER_RequestHandle *dns_active; - - /** - * Handle to the listen socket - */ - struct GNUNET_NETWORK_Handle *sock; - - /** - * Stun server address - */ - char *stun_server; - - /** - * Function to call when a error occours - */ - GNUNET_NAT_STUN_ErrorCallback cb; - - /** - * Closure for @e cb. - */ - void *cb_cls; - - /** - * Do we got a DNS resolution successfully? - */ - int dns_success; - - /** - * STUN port - */ - uint16_t stun_port; - -}; - - -/** - * here we store credentials extracted from a message -*/ -struct StunState -{ - uint16_t attr; -}; - - -/** - * Encode a class and method to a compatible STUN format - * - * @param msg_class class to be converted - * @param method method to be converted - * @return message in a STUN compatible format - */ -static int -encode_message (enum StunClasses msg_class, - enum StunMethods method) -{ - return ((msg_class & 1) << 4) | ((msg_class & 2) << 7) | - (method & 0x000f) | ((method & 0x0070) << 1) | ((method & 0x0f800) << 2); -} - - -/** - * Fill the stun_header with a random request_id - * - * @param req, stun header to be filled - */ -static void -generate_request_id (struct stun_header *req) -{ - unsigned int x; - - req->magic = htonl(STUN_MAGIC_COOKIE); - for (x = 0; x < 3; x++) - req->id.id[x] = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_NONCE, - UINT32_MAX); -} - - -/** - * Extract the STUN_MAPPED_ADDRESS from the stun response. - * This is used as a callback for stun_handle_response - * when called from stun_request. - * - * @param st, pointer where we will set the type - * @param attr , received stun attribute - * @param arg , pointer to a sockaddr_in where we will set the reported IP and port - * @param magic , Magic cookie - * - * @return 0 on success, other value otherwise - */ -static int -stun_get_mapped (struct StunState *st, - struct stun_attr *attr, - struct sockaddr_in *arg, - unsigned int magic) -{ - struct stun_addr *returned_addr = (struct stun_addr *)(attr + 1); - struct sockaddr_in *sa = (struct sockaddr_in *)arg; - unsigned short type = ntohs(attr->attr); - - switch (type) - { - case STUN_MAPPED_ADDRESS: - if (st->attr == STUN_XOR_MAPPED_ADDRESS || - st->attr == STUN_MS_XOR_MAPPED_ADDRESS) - return 1; - magic = 0; - break; - case STUN_MS_XOR_MAPPED_ADDRESS: - if (st->attr == STUN_XOR_MAPPED_ADDRESS) - return 1; - break; - case STUN_XOR_MAPPED_ADDRESS: - break; - default: - return 1; - } - if ( (ntohs(attr->len) < 8) && - (returned_addr->family != 1) ) - { - return 1; - } - st->attr = type; - sa->sin_family = AF_INET; - sa->sin_port = returned_addr->port ^ htons(ntohl(magic) >> 16); - sa->sin_addr.s_addr = returned_addr->addr ^ magic; - return 0; -} - - -/** - * Handle an incoming STUN message, Do some basic sanity checks on packet size and content, - * try to extract a bit of information, and possibly reply. - * At the moment this only processes BIND requests, and returns - * the externally visible address of the request. - * If a callback is specified, invoke it with the attribute. - * - * @param data the packet - * @param len the length of the packet in @a data - * @param[out] arg sockaddr_in where we will set our discovered address - * - * @return, #GNUNET_OK on OK, #GNUNET_NO if the packet is invalid (not a stun packet) - */ -int -GNUNET_NAT_stun_handle_packet (const void *data, - size_t len, - struct sockaddr_in *arg) -{ - const struct stun_header *hdr = (const struct stun_header *)data; - struct stun_attr *attr; - struct StunState st; - int ret = GNUNET_OK; - uint32_t advertised_message_size; - uint32_t message_magic_cookie; - - /* On entry, 'len' is the length of the udp payload. After the - * initial checks it becomes the size of unprocessed options, - * while 'data' is advanced accordingly. - */ - if (len < sizeof(struct stun_header)) - { - LOG (GNUNET_ERROR_TYPE_INFO, - "STUN packet too short (only %d, wanting at least %d)\n", - (int) len, - (int) sizeof(struct stun_header)); - GNUNET_break_op (0); - return GNUNET_NO; - } - /* Skip header as it is already in hdr */ - len -= sizeof(struct stun_header); - data += sizeof(struct stun_header); - - /* len as advertised in the message */ - advertised_message_size = ntohs(hdr->msglen); - - message_magic_cookie = ntohl(hdr->magic); - /* Compare if the cookie match */ - if (STUN_MAGIC_COOKIE != message_magic_cookie) - { - LOG (GNUNET_ERROR_TYPE_INFO, - "Invalid magic cookie \n"); - return GNUNET_NO; - } - - LOG (GNUNET_ERROR_TYPE_INFO, - "STUN Packet, msg %s (%04x), length: %d\n", - stun_msg2str(ntohs(hdr->msgtype)), - ntohs(hdr->msgtype), - advertised_message_size); - if (advertised_message_size > len) - { - LOG (GNUNET_ERROR_TYPE_INFO, - "Scrambled STUN packet length (got %d, expecting %d)\n", - advertised_message_size, - (int)len); - return GNUNET_NO; - } - len = advertised_message_size; - memset (&st, 0, sizeof(st)); - - while (len > 0) - { - if (len < sizeof(struct stun_attr)) - { - LOG (GNUNET_ERROR_TYPE_INFO, - "Attribute too short (got %d, expecting %d)\n", - (int)len, - (int) sizeof(struct stun_attr)); - break; - } - attr = (struct stun_attr *)data; - - /* compute total attribute length */ - advertised_message_size = ntohs(attr->len) + sizeof(struct stun_attr); - - /* Check if we still have space in our buffer */ - if (advertised_message_size > len ) - { - LOG (GNUNET_ERROR_TYPE_INFO, - "Inconsistent Attribute (length %d exceeds remaining msg len %d)\n", - advertised_message_size, - (int)len); - break; - } - stun_get_mapped (&st, - attr, - arg, - hdr->magic); - /* Clear attribute id: in case previous entry was a string, - * this will act as the terminator for the string. - */ - attr->attr = 0; - data += advertised_message_size; - len -= advertised_message_size; - ret = GNUNET_OK; - } - return ret; -} - - -/** - * Cancel active STUN request. Frees associated resources - * and ensures that the callback is no longer invoked. - * - * @param rh request to cancel - */ -void -GNUNET_NAT_stun_make_request_cancel (struct GNUNET_NAT_STUN_Handle *rh) -{ - if (NULL != rh->dns_active) - { - GNUNET_RESOLVER_request_cancel (rh->dns_active); - rh->dns_active = NULL; - } - GNUNET_free (rh->stun_server); - GNUNET_free (rh); -} - - -/** - * Try to establish a connection given the specified address. - * - * @param cls our `struct GNUNET_NAT_STUN_Handle *` - * @param addr address to try, NULL for "last call" - * @param addrlen length of @a addr - */ -static void -stun_dns_callback (void *cls, - const struct sockaddr *addr, - socklen_t addrlen) -{ - struct GNUNET_NAT_STUN_Handle *rh = cls; - struct stun_header *req; - uint8_t reqdata[1024]; - int reqlen; - struct sockaddr_in server; - - if (NULL == addr) - { - rh->dns_active = NULL; - if (GNUNET_NO == rh->dns_success) - { - LOG (GNUNET_ERROR_TYPE_INFO, - "Error resolving host %s\n", - rh->stun_server); - rh->cb (rh->cb_cls, - GNUNET_NAT_ERROR_NOT_ONLINE); - } - else if (GNUNET_SYSERR == rh->dns_success) - { - rh->cb (rh->cb_cls, - GNUNET_NAT_ERROR_INTERNAL_NETWORK_ERROR); - } - else - { - rh->cb (rh->cb_cls, - GNUNET_NAT_ERROR_SUCCESS); - } - GNUNET_NAT_stun_make_request_cancel (rh); - return; - } - - rh->dns_success = GNUNET_YES; - memset (&server,0, sizeof(server)); - server.sin_family = AF_INET; - server.sin_addr = ((struct sockaddr_in *)addr)->sin_addr; - server.sin_port = htons(rh->stun_port); -#if HAVE_SOCKADDR_IN_SIN_LEN - server.sin_len = (u_char) sizeof (struct sockaddr_in); -#endif - - /*Craft the simplest possible STUN packet. A request binding*/ - req = (struct stun_header *)reqdata; - generate_request_id (req); - reqlen = 0; - req->msgtype = 0; - req->msglen = 0; - req->msglen = htons (reqlen); - req->msgtype = htons (encode_message (STUN_REQUEST, - STUN_BINDING)); - - /* Send the packet */ - if (-1 == - GNUNET_NETWORK_socket_sendto (rh->sock, - req, - ntohs(req->msglen) + sizeof(*req), - (const struct sockaddr *) &server, - sizeof (server))) - { - GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, - "sendto"); - rh->dns_success = GNUNET_SYSERR; - return; - } -} - - -/** - * Make Generic STUN request. Sends a generic stun request to the - * server specified using the specified socket, possibly waiting for - * a reply and filling the 'reply' field with the externally visible - * address. - * - * @param server the address of the stun server - * @param port port of the stun server - * @param sock the socket used to send the request - * @param cb callback in case of error - * @param cb_cls closure for @a cb - * @return NULL on error - */ -struct GNUNET_NAT_STUN_Handle * -GNUNET_NAT_stun_make_request (const char *server, - uint16_t port, - struct GNUNET_NETWORK_Handle *sock, - GNUNET_NAT_STUN_ErrorCallback cb, - void *cb_cls) -{ - struct GNUNET_NAT_STUN_Handle *rh; - - rh = GNUNET_new (struct GNUNET_NAT_STUN_Handle); - rh->sock = sock; - rh->cb = cb; - rh->cb_cls = cb_cls; - rh->stun_server = GNUNET_strdup (server); - rh->stun_port = port; - rh->dns_success = GNUNET_NO; - rh->dns_active = GNUNET_RESOLVER_ip_get (rh->stun_server, - AF_INET, - TIMEOUT, - &stun_dns_callback, rh); - if (NULL == rh->dns_active) - { - GNUNET_NAT_stun_make_request_cancel (rh); - return NULL; - } - return rh; -} - -/* end of nat_stun.c */ diff --git a/src/peerinfo-tool/Makefile.am b/src/peerinfo-tool/Makefile.am index f22380a9e..c79c3ac68 100644 --- a/src/peerinfo-tool/Makefile.am +++ b/src/peerinfo-tool/Makefile.am @@ -19,7 +19,6 @@ gnunet_peerinfo_SOURCES = \ gnunet_peerinfo_LDADD = \ $(top_builddir)/src/peerinfo/libgnunetpeerinfo.la \ - $(top_builddir)/src/nat/libgnunetnat.la \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ diff --git a/src/transport/Makefile.am b/src/transport/Makefile.am index 8f2df40a1..0b523eecc 100644 --- a/src/transport/Makefile.am +++ b/src/transport/Makefile.am @@ -235,7 +235,6 @@ gnunet_transport_profiler_SOURCES = \ gnunet-transport-profiler.c gnunet_transport_profiler_LDADD = \ libgnunettransport.la \ - $(top_builddir)/src/nat/libgnunetnat.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/ats/libgnunetats.la \ $(top_builddir)/src/util/libgnunetutil.la \ @@ -267,7 +266,6 @@ gnunet_service_transport_LDADD = \ $(top_builddir)/src/ats/libgnunetats.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/peerinfo/libgnunetpeerinfo.la \ - $(top_builddir)/src/nat/libgnunetnat.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(GN_GLPK) \ @@ -371,7 +369,6 @@ libgnunet_plugin_transport_http_client_la_LIBADD = \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/peerinfo/libgnunetpeerinfo.la \ $(LIB_GNURL) \ - $(top_builddir)/src/nat/libgnunetnat.la \ $(top_builddir)/src/util/libgnunetutil.la libgnunet_plugin_transport_http_client_la_LDFLAGS = \ $(GN_PLUGIN_LDFLAGS) @@ -402,7 +399,6 @@ libgnunet_plugin_transport_https_client_la_LIBADD = \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/peerinfo/libgnunetpeerinfo.la \ $(LIB_GNURL) \ - $(top_builddir)/src/nat/libgnunetnat.la \ $(top_builddir)/src/util/libgnunetutil.la libgnunet_plugin_transport_https_client_la_LDFLAGS = \ $(GN_PLUGIN_LDFLAGS) @@ -418,7 +414,7 @@ libgnunet_plugin_transport_https_server_la_LIBADD = \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/peerinfo/libgnunetpeerinfo.la \ - $(top_builddir)/src/nat/libgnunetnat.la \ + $(top_builddir)/src/nat/libgnunetnatnew.la \ $(top_builddir)/src/util/libgnunetutil.la libgnunet_plugin_transport_https_server_la_LDFLAGS = \ $(GN_LIBMHD) \ @@ -1175,7 +1171,6 @@ test_quota_compliance_wlan_asymmetric_LDADD = \ test_quota_compliance_bluetooth_SOURCES = \ test_quota_compliance.c test_quota_compliance_bluetooth_LDADD = \ - $(top_builddir)/src/nat/libgnunetnat.la \ libgnunettransport.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/ats/libgnunetats.la \ -- 2.25.1