diff options
author | Christian Grothoff <christian@grothoff.org> | 2017-01-07 16:47:07 +0100 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2017-01-07 16:47:07 +0100 |
commit | ddadc570d8fd3ce7a4f658adf9a2c9b9d9c0dcba (patch) | |
tree | 076f4d7b4732099d33662de3bdff51c965cae8df /src/nat | |
parent | 659e270f9e023112ca864065a22db5e484ba5ef6 (diff) |
remove legacy NAT library logic, or preserve if it might still be useful
Diffstat (limited to 'src/nat')
-rw-r--r-- | src/nat/Makefile.am | 70 | ||||
-rw-r--r-- | src/nat/gnunet-service-nat.c | 9 | ||||
-rw-r--r-- | src/nat/nat.c | 2054 | ||||
-rw-r--r-- | src/nat/nat_auto.c | 1081 | ||||
-rw-r--r-- | src/nat/nat_mini.c | 712 | ||||
-rw-r--r-- | src/nat/nat_stun.c | 439 | ||||
-rw-r--r-- | src/nat/nat_test.c | 645 |
7 files changed, 30 insertions, 4980 deletions
diff --git a/src/nat/Makefile.am b/src/nat/Makefile.am index 456ddfb62c..3dc001dd79 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 b3e81127b8..7fa329b54e 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 08dd5dd1ec..0000000000 --- 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;i<h->num_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;i<h->num_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_s |