From ddadc570d8fd3ce7a4f658adf9a2c9b9d9c0dcba Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Sat, 7 Jan 2017 16:47:07 +0100 Subject: remove legacy NAT library logic, or preserve if it might still be useful --- ChangeLog | 3 + src/nat-auto/gnunet-nat-auto_legacy.c | 645 ++++++++ src/nat-auto/gnunet-service-nat-auto.c | 3 +- src/nat-auto/gnunet-service-nat-auto_legacy.c | 1081 +++++++++++++ src/nat/Makefile.am | 70 +- src/nat/gnunet-service-nat.c | 9 +- src/nat/nat.c | 2054 ------------------------- src/nat/nat_auto.c | 1081 ------------- src/nat/nat_mini.c | 712 --------- src/nat/nat_stun.c | 439 ------ src/nat/nat_test.c | 645 -------- src/peerinfo-tool/Makefile.am | 1 - src/transport/Makefile.am | 7 +- 13 files changed, 1762 insertions(+), 4988 deletions(-) create mode 100644 src/nat-auto/gnunet-nat-auto_legacy.c create mode 100644 src/nat-auto/gnunet-service-nat-auto_legacy.c delete mode 100644 src/nat/nat.c delete mode 100644 src/nat/nat_auto.c delete mode 100644 src/nat/nat_mini.c delete mode 100644 src/nat/nat_stun.c delete mode 100644 src/nat/nat_test.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-auto/gnunet-nat-auto_legacy.c b/src/nat-auto/gnunet-nat-auto_legacy.c new file mode 100644 index 000000000..803ff23e3 --- /dev/null +++ b/src/nat-auto/gnunet-nat-auto_legacy.c @@ -0,0 +1,645 @@ +/* + This file is part of GNUnet. + Copyright (C) 2011, 2016 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_test.c + * @brief functions to test if the NAT configuration is successful at achieving NAT traversal (with the help of a gnunet-nat-server) + * @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__) + +#define NAT_SERVER_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 30) + +/** + * Entry we keep for each incoming connection. + */ +struct NatActivity +{ + /** + * This is a doubly-linked list. + */ + struct NatActivity *next; + + /** + * This is a doubly-linked list. + */ + struct NatActivity *prev; + + /** + * Socket of the incoming connection. + */ + struct GNUNET_NETWORK_Handle *sock; + + /** + * Handle of the master context. + */ + struct GNUNET_NAT_Test *h; + + /** + * Task reading from the incoming connection. + */ + struct GNUNET_SCHEDULER_Task *rtask; +}; + + +/** + * Entry we keep for each connection to the gnunet-nat-service. + */ +struct ClientActivity +{ + /** + * This is a doubly-linked list. + */ + struct ClientActivity *next; + + /** + * This is a doubly-linked list. + */ + struct ClientActivity *prev; + + /** + * Socket of the incoming connection. + */ + struct GNUNET_MQ_Handle *mq; + + /** + * Handle to overall NAT test. + */ + struct GNUNET_NAT_Test *h; + +}; + + +/** + * Handle to a NAT test. + */ +struct GNUNET_NAT_Test +{ + + /** + * Configuration used + */ + const struct GNUNET_CONFIGURATION_Handle *cfg; + + /** + * Function to call with success report + */ + GNUNET_NAT_TestCallback report; + + /** + * Closure for @e report. + */ + void *report_cls; + + /** + * Handle to NAT traversal in use + */ + struct GNUNET_NAT_Handle *nat; + + /** + * Handle to listen socket, or NULL + */ + struct GNUNET_NETWORK_Handle *lsock; + + /** + * Head of list of nat activities. + */ + struct NatActivity *na_head; + + /** + * Tail of list of nat activities. + */ + struct NatActivity *na_tail; + + /** + * Head of list of client activities. + */ + struct ClientActivity *ca_head; + + /** + * Tail of list of client activities. + */ + struct ClientActivity *ca_tail; + + /** + * Identity of task for the listen socket (if any) + */ + struct GNUNET_SCHEDULER_Task *ltask; + + /** + * Task identifier for the timeout (if any) + */ + struct GNUNET_SCHEDULER_Task *ttask; + + /** + * #GNUNET_YES if we're testing TCP + */ + int is_tcp; + + /** + * Data that should be transmitted or source-port. + */ + uint16_t data; + + /** + * Advertised port to the other peer. + */ + uint16_t adv_port; + + /** + * Status code to be reported to the timeout/status call + */ + enum GNUNET_NAT_StatusCode status; +}; + + +/** + * Function called from #GNUNET_NAT_register whenever someone asks us + * to do connection reversal. + * + * @param cls closure, our `struct GNUNET_NAT_Handle` + * @param addr public IP address of the other peer + * @param addrlen actual lenght of the @a addr + */ +static void +reversal_cb (void *cls, + const struct sockaddr *addr, + socklen_t addrlen) +{ + struct GNUNET_NAT_Test *h = cls; + const struct sockaddr_in *sa; + + if (sizeof (struct sockaddr_in) != addrlen) + return; + sa = (const struct sockaddr_in *) addr; + if (h->data != sa->sin_port) + { + LOG (GNUNET_ERROR_TYPE_DEBUG, + "Received connection reversal request for wrong port\n"); + return; /* wrong port */ + } + /* report success */ + h->report (h->report_cls, + GNUNET_NAT_ERROR_SUCCESS); +} + + +/** + * Activity on our incoming socket. Read data from the + * incoming connection. + * + * @param cls the `struct GNUNET_NAT_Test` + */ +static void +do_udp_read (void *cls) +{ + struct GNUNET_NAT_Test *tst = cls; + uint16_t data; + const struct GNUNET_SCHEDULER_TaskContext *tc; + + tc = GNUNET_SCHEDULER_get_task_context (); + tst->ltask = + GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL, + tst->lsock, + &do_udp_read, + tst); + if ((NULL != tc->write_ready) && + (GNUNET_NETWORK_fdset_isset (tc->read_ready, + tst->lsock)) && + (sizeof (data) == + GNUNET_NETWORK_socket_recv (tst->lsock, + &data, + sizeof (data)))) + { + if (data == tst->data) + tst->report (tst->report_cls, + GNUNET_NAT_ERROR_SUCCESS); + else + LOG (GNUNET_ERROR_TYPE_DEBUG, + "Received data mismatches expected value\n"); + } + else + LOG (GNUNET_ERROR_TYPE_DEBUG, + "Failed to receive data from inbound connection\n"); +} + + +/** + * Activity on our incoming socket. Read data from the + * incoming connection. + * + * @param cls the `struct NatActivity` + */ +static void +do_read (void *cls) +{ + struct NatActivity *na = cls; + struct GNUNET_NAT_Test *tst; + uint16_t data; + const struct GNUNET_SCHEDULER_TaskContext *tc; + + tc = GNUNET_SCHEDULER_get_task_context (); + na->rtask = NULL; + tst = na->h; + GNUNET_CONTAINER_DLL_remove (tst->na_head, + tst->na_tail, + na); + if ((NULL != tc->write_ready) && + (GNUNET_NETWORK_fdset_isset (tc->read_ready, + na->sock)) && + (sizeof (data) == + GNUNET_NETWORK_socket_recv (na->sock, + &data, + sizeof (data)))) + { + if (data == tst->data) + tst->report (tst->report_cls, + GNUNET_NAT_ERROR_SUCCESS); + else + LOG (GNUNET_ERROR_TYPE_DEBUG, + "Received data does not match expected value\n"); + } + else + LOG (GNUNET_ERROR_TYPE_DEBUG, + "Failed to receive data from inbound connection\n"); + GNUNET_NETWORK_socket_close (na->sock); + GNUNET_free (na); +} + + +/** + * Activity on our listen socket. Accept the + * incoming connection. + * + * @param cls the `struct GNUNET_NAT_Test` + */ +static void +do_accept (void *cls) +{ + struct GNUNET_NAT_Test *tst = cls; + struct GNUNET_NETWORK_Handle *s; + struct NatActivity *wl; + + tst->ltask = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL, + tst->lsock, + &do_accept, + tst); + s = GNUNET_NETWORK_socket_accept (tst->lsock, + NULL, + NULL); + if (NULL == s) + { + GNUNET_log_strerror (GNUNET_ERROR_TYPE_INFO, + "accept"); + return; /* odd error */ + } + LOG (GNUNET_ERROR_TYPE_DEBUG, + "Got an inbound connection, waiting for data\n"); + wl = GNUNET_new (struct NatActivity); + wl->sock = s; + wl->h = tst; + wl->rtask = + GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL, + wl->sock, + &do_read, + wl); + GNUNET_CONTAINER_DLL_insert (tst->na_head, + tst->na_tail, + wl); +} + + +/** + * We got disconnected from the NAT server. Stop + * waiting for a reply. + * + * @param cls the `struct ClientActivity` + * @param error error code + */ +static void +mq_error_handler (void *cls, + enum GNUNET_MQ_Error error) +{ + struct ClientActivity *ca = cls; + struct GNUNET_NAT_Test *tst = ca->h; + + GNUNET_CONTAINER_DLL_remove (tst->ca_head, + tst->ca_tail, + ca); + GNUNET_MQ_destroy (ca->mq); + GNUNET_free (ca); +} + + +/** + * Address-callback, used to send message to gnunet-nat-server. + * + * @param cls closure + * @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 length of the @a addr + */ +static void +addr_cb (void *cls, + int add_remove, + const struct sockaddr *addr, + socklen_t addrlen) +{ + struct GNUNET_NAT_Test *h = cls; + struct ClientActivity *ca; + struct GNUNET_MQ_Envelope *env; + struct GNUNET_NAT_TestMessage *msg; + const struct sockaddr_in *sa; + + if (GNUNET_YES != add_remove) + return; + if (addrlen != sizeof (struct sockaddr_in)) + { + LOG (GNUNET_ERROR_TYPE_DEBUG, + "NAT test ignores IPv6 address `%s' returned from NAT library\n", + GNUNET_a2s (addr, + addrlen)); + return; /* ignore IPv6 here */ + } + LOG (GNUNET_ERROR_TYPE_INFO, + "Asking gnunet-nat-server to connect to `%s'\n", + GNUNET_a2s (addr, + addrlen)); + + ca = GNUNET_new (struct ClientActivity); + ca->h = h; + ca->mq = GNUNET_CLIENT_connecT (h->cfg, + "gnunet-nat-server", + NULL, + &mq_error_handler, + ca); + if (NULL == ca->mq) + { + GNUNET_free (ca); + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + _("Failed to connect to `gnunet-nat-server'\n")); + return; + } + GNUNET_CONTAINER_DLL_insert (h->ca_head, + h->ca_tail, + ca); + sa = (const struct sockaddr_in *) addr; + env = GNUNET_MQ_msg (msg, + GNUNET_MESSAGE_TYPE_NAT_TEST); + msg->dst_ipv4 = sa->sin_addr.s_addr; + msg->dport = sa->sin_port; + msg->data = h->data; + msg->is_tcp = htonl ((uint32_t) h->is_tcp); + GNUNET_MQ_send (ca->mq, + env); +} + + +/** + * Timeout task for a nat test. + * Calls the report-callback with a timeout return value + * + * Destroys the nat handle after the callback has been processed. + * + * @param cls handle to the timed out NAT test + */ +static void +do_timeout (void *cls) +{ + struct GNUNET_NAT_Test *nh = cls; + + nh->ttask = NULL; + nh->report (nh->report_cls, + (GNUNET_NAT_ERROR_SUCCESS == nh->status) + ? GNUNET_NAT_ERROR_TIMEOUT + : nh->status); +} + + +/** + * Start testing if NAT traversal works using the + * given configuration (IPv4-only). + * + * ALL failures are reported directly to the report callback + * + * @param cfg configuration for the NAT traversal + * @param is_tcp #GNUNET_YES to test TCP, #GNUNET_NO to test UDP + * @param bnd_port port to bind to, 0 for connection reversal + * @param adv_port externally advertised port to use + * @param timeout delay after which the test should be aborted + * @param report function to call with the result of the test + * @param report_cls closure for @a report + * @return handle to cancel NAT test or NULL. The error is always indicated via the report callback + */ +struct GNUNET_NAT_Test * +GNUNET_NAT_test_start (const struct GNUNET_CONFIGURATION_Handle *cfg, + int is_tcp, + uint16_t bnd_port, + uint16_t adv_port, + struct GNUNET_TIME_Relative timeout, + GNUNET_NAT_TestCallback report, + void *report_cls) +{ + struct GNUNET_NAT_Test *nh; + struct sockaddr_in sa; + const struct sockaddr *addrs[] = { + (const struct sockaddr *) &sa + }; + const socklen_t addrlens[] = { + sizeof (sa) + }; + + memset (&sa, 0, sizeof (sa)); + sa.sin_family = AF_INET; + sa.sin_port = htons (bnd_port); +#if HAVE_SOCKADDR_IN_SIN_LEN + sa.sin_len = sizeof (sa); +#endif + + nh = GNUNET_new (struct GNUNET_NAT_Test); + nh->cfg = cfg; + nh->is_tcp = is_tcp; + nh->data = bnd_port; + nh->adv_port = adv_port; + nh->report = report; + nh->report_cls = report_cls; + nh->status = GNUNET_NAT_ERROR_SUCCESS; + if (0 == bnd_port) + { + nh->nat + = GNUNET_NAT_register (cfg, + is_tcp, + 0, + 0, + NULL, + NULL, + &addr_cb, + &reversal_cb, + nh, + NULL); + } + else + { + nh->lsock = + GNUNET_NETWORK_socket_create (AF_INET, + (is_tcp == + GNUNET_YES) ? SOCK_STREAM : SOCK_DGRAM, + 0); + if ((nh->lsock == NULL) || + (GNUNET_OK != + GNUNET_NETWORK_socket_bind (nh->lsock, + (const struct sockaddr *) &sa, + sizeof (sa)))) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + _("Failed to create listen socket bound to `%s' for NAT test: %s\n"), + GNUNET_a2s ((const struct sockaddr *) &sa, + sizeof (sa)), + STRERROR (errno)); + if (NULL != nh->lsock) + { + GNUNET_NETWORK_socket_close (nh->lsock); + nh->lsock = NULL; + } + nh->status = GNUNET_NAT_ERROR_INTERNAL_NETWORK_ERROR; + nh->ttask = GNUNET_SCHEDULER_add_now (&do_timeout, + nh); + return nh; + } + if (GNUNET_YES == is_tcp) + { + GNUNET_break (GNUNET_OK == + GNUNET_NETWORK_socket_listen (nh->lsock, + 5)); + nh->ltask = + GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL, + nh->lsock, + &do_accept, + nh); + } + else + { + nh->ltask = + GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL, + nh->lsock, + &do_udp_read, + nh); + } + LOG (GNUNET_ERROR_TYPE_INFO, + "NAT test listens on port %u (%s)\n", + bnd_port, + (GNUNET_YES == is_tcp) ? "tcp" : "udp"); + nh->nat = GNUNET_NAT_register (cfg, + is_tcp, + adv_port, + 1, + addrs, + addrlens, + &addr_cb, + NULL, + nh, + NULL); + if (NULL == nh->nat) + { + LOG (GNUNET_ERROR_TYPE_INFO, + _("NAT test failed to start NAT library\n")); + if (NULL != nh->ltask) + { + GNUNET_SCHEDULER_cancel (nh->ltask); + nh->ltask = NULL; + } + if (NULL != nh->lsock) + { + GNUNET_NETWORK_socket_close (nh->lsock); + nh->lsock = NULL; + } + nh->status = GNUNET_NAT_ERROR_NAT_REGISTER_FAILED; + nh->ttask = GNUNET_SCHEDULER_add_now (&do_timeout, + nh); + return nh; + } + } + nh->ttask = GNUNET_SCHEDULER_add_delayed (timeout, + &do_timeout, + nh); + return nh; +} + + +/** + * Stop an active NAT test. + * + * @param tst test to stop. + */ +void +GNUNET_NAT_test_stop (struct GNUNET_NAT_Test *tst) +{ + struct NatActivity *pos; + struct ClientActivity *cpos; + + LOG (GNUNET_ERROR_TYPE_DEBUG, + "Stopping NAT test\n"); + while (NULL != (cpos = tst->ca_head)) + { + GNUNET_CONTAINER_DLL_remove (tst->ca_head, + tst->ca_tail, + cpos); + GNUNET_MQ_destroy (cpos->mq); + GNUNET_free (cpos); + } + while (NULL != (pos = tst->na_head)) + { + GNUNET_CONTAINER_DLL_remove (tst->na_head, + tst->na_tail, + pos); + GNUNET_SCHEDULER_cancel (pos->rtask); + GNUNET_NETWORK_socket_close (pos->sock); + GNUNET_free (pos); + } + if (NULL != tst->ttask) + { + GNUNET_SCHEDULER_cancel (tst->ttask); + tst->ttask = NULL; + } + if (NULL != tst->ltask) + { + GNUNET_SCHEDULER_cancel (tst->ltask); + tst->ltask = NULL; + } + if (NULL != tst->lsock) + { + GNUNET_NETWORK_socket_close (tst->lsock); + tst->lsock = NULL; + } + if (NULL != tst->nat) + { + GNUNET_NAT_unregister (tst->nat); + tst->nat = NULL; + } + GNUNET_free (tst); +} + +/* end of nat_test.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-auto/gnunet-service-nat-auto_legacy.c b/src/nat-auto/gnunet-service-nat-auto_legacy.c new file mode 100644 index 000000000..061d0cbe6 --- /dev/null +++ b/src/nat-auto/gnunet-service-nat-auto_legacy.c @@ -0,0 +1,1081 @@ +/* + This file is part of GNUnet. + Copyright (C) 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. +*/ + +/** + * @file nat/nat_auto.c + * @brief functions for auto-configuration of the network + * @author Christian Grothoff + * @author Bruno Cabral + */ +#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 long do we wait for the NAT test to report success? + */ +#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 15) + +#define NAT_SERVER_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 10) + +/** + * Phases of the auto configuration. + */ +enum AutoPhase +{ + /** + * Initial start value. + */ + AUTO_INIT = 0, + + /** + * Test our external IP. + */ + AUTO_EXTERNAL_IP, + + /** + * Test our external IP. + */ + AUTO_STUN, + + /** + * Test our internal IP. + */ + AUTO_LOCAL_IP, + + /** + * Test if NAT was punched. + */ + AUTO_NAT_PUNCHED, + + /** + * Test if UPnP is working. + */ + AUTO_UPNPC, + + /** + * Test if ICMP server works. + */ + AUTO_ICMP_SERVER, + + /** + * Test if ICMP client works. + */ + AUTO_ICMP_CLIENT, + + /** + * Last phase, we're done. + */ + AUTO_DONE + +}; + + +/** + * Handle to auto-configuration in progress. + */ +struct GNUNET_NAT_AutoHandle +{ + + /** + * Handle to the active NAT test. + */ + struct GNUNET_NAT_Test *tst; + + /** + * Function to call when done. + */ + GNUNET_NAT_AutoResultCallback fin_cb; + + /** + * Closure for @e fin_cb. + */ + void *fin_cb_cls; + + /** + * Handle for active 'GNUNET_NAT_mini_get_external_ipv4'-operation. + */ + struct GNUNET_NAT_ExternalHandle *eh; + + /** + * Current configuration (with updates from previous phases) + */ + struct GNUNET_CONFIGURATION_Handle *cfg; + + /** + * Original configuration (used to calculate differences) + */ + struct GNUNET_CONFIGURATION_Handle *initial_cfg; + + /** + * Task identifier for the timeout. + */ + struct GNUNET_SCHEDULER_Task *task; + + /** + * Message queue to the gnunet-nat-server. + */ + struct GNUNET_MQ_Handle *mq; + + /** + * Where are we in the test? + */ + enum AutoPhase phase; + + /** + * Situation of the NAT + */ + enum GNUNET_NAT_Type type; + + /** + * Do we have IPv6? + */ + int have_v6; + + /** + * UPnP already set the external ip address ? + */ + int upnp_set_external_address; + + /** + * Did the external server connected back ? + */ + int connected_back; + + /** + * Address detected by STUN + */ + char *stun_ip; + + unsigned int stun_port; + + /** + * Internal IP is the same as the public one ? + */ + int internal_ip_is_public; + + /** + * Error code for better debugging and user feedback + */ + enum GNUNET_NAT_StatusCode ret; +}; + + +/** + * The listen socket of the service for IPv4 + */ +static struct GNUNET_NETWORK_Handle *lsock4; + +/** + * The listen task ID for IPv4 + */ +static struct GNUNET_SCHEDULER_Task *ltask4; + +/** + * The port the test service is running on (default 7895) + */ +static unsigned long long port = 7895; + +static char *stun_server = "stun.ekiga.net"; + +static unsigned int stun_port = 3478; + + +/** + * Run the next phase of the auto test. + * + * @param ah auto test handle + */ +static void +next_phase (struct GNUNET_NAT_AutoHandle *ah); + + +static void +process_stun_reply(struct sockaddr_in *answer, + struct GNUNET_NAT_AutoHandle *ah) +{ + ah->stun_ip = inet_ntoa(answer->sin_addr); + ah->stun_port = ntohs (answer->sin_port); + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "External IP is: %s , with port %u\n", + ah->stun_ip, + ah->stun_port); + next_phase (ah); +} + + +/** + * Function that terminates the test. + */ +static void +stop_stun () +{ + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "Stopping STUN and quitting...\n"); + /* Clean task */ + if (NULL != ltask4) + { + GNUNET_SCHEDULER_cancel (ltask4); + ltask4 = NULL; + } + /* Clean socket */ + if (NULL != lsock4) + { + GNUNET_NETWORK_socket_close (lsock4); + lsock4 = NULL; + } +} + + +/** + * Activity on our incoming socket. Read data from the + * incoming connection. + * + * @param cls + */ +static void +do_udp_read (void *cls) +{ + struct GNUNET_NAT_AutoHandle *ah = cls; + unsigned char reply_buf[1024]; + ssize_t rlen; + struct sockaddr_in answer; + const struct GNUNET_SCHEDULER_TaskContext *tc; + + tc = GNUNET_SCHEDULER_get_task_context (); + if ((0 != (tc->reason & GNUNET_SCHEDULER_REASON_READ_READY)) && + (GNUNET_NETWORK_fdset_isset (tc->read_ready, + lsock4))) + { + rlen = GNUNET_NETWORK_socket_recv (lsock4, + reply_buf, + sizeof (reply_buf)); + + //Lets handle the packet + memset (&answer, 0, sizeof(struct sockaddr_in)); + if (ah->phase == AUTO_NAT_PUNCHED) + { + //Destroy the connection + GNUNET_NETWORK_socket_close (lsock4); + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "The external server was able to connect back"); + ah->connected_back = GNUNET_YES; + next_phase (ah); + } + else + { + if (GNUNET_OK == + GNUNET_NAT_stun_handle_packet (reply_buf, rlen, &answer)) + { + //Process the answer + process_stun_reply (&answer, ah); + } + else + { + next_phase (ah); + } + } + } + else + { + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "TIMEOUT while waiting for an answer\n"); + if (ah->phase == AUTO_NAT_PUNCHED) + { + stop_stun(); + } + + next_phase (ah); + } +} + + +/** + * Create an IPv4 listen socket bound to our port. + * + * @return NULL on error + */ +static struct GNUNET_NETWORK_Handle * +bind_v4 () +{ + struct GNUNET_NETWORK_Handle *ls; + struct sockaddr_in sa4; + int eno; + + memset (&sa4, 0, sizeof (sa4)); + sa4.sin_family = AF_INET; + sa4.sin_port = htons (port); +#if HAVE_SOCKADDR_IN_SIN_LEN + sa4.sin_len = sizeof (sa4); +#endif + ls = GNUNET_NETWORK_socket_create (AF_INET, + SOCK_DGRAM, + 0); + if (NULL == ls) + return NULL; + if (GNUNET_OK != + GNUNET_NETWORK_socket_bind (ls, (const struct sockaddr *) &sa4, + sizeof (sa4))) + { + eno = errno; + GNUNET_NETWORK_socket_close (ls); + errno = eno; + return NULL; + } + return ls; +} + + +static void +request_callback (void *cls, + enum GNUNET_NAT_StatusCode result) +{ + // struct GNUNET_NAT_AutoHandle *ah = cls; + + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "Request callback: stop and quit\n"); + stop_stun (); + + // next_phase (ah); FIXME this always will be NULL, as called in test_stun() +} + + +/** + * Function called by NAT to report the outcome of the nat-test. + * Clean up and update GUI. + * + * @param cls the auto handle + * @param success currently always #GNUNET_OK + * @param emsg NULL on success, otherwise an error message + */ +static void +result_callback (void *cls, + enum GNUNET_NAT_StatusCode ret) +{ + struct GNUNET_NAT_AutoHandle *ah = cls; + + if (GNUNET_NAT_ERROR_SUCCESS == ret) + GNUNET_NAT_test_stop (ah->tst); + ah->tst = NULL; + ah->ret = ret; + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + GNUNET_NAT_ERROR_SUCCESS == ret + ? _("NAT traversal with ICMP Server succeeded.\n") + : _("NAT traversal with ICMP Server failed.\n")); + GNUNET_CONFIGURATION_set_value_string (ah->cfg, "nat", "ENABLE_ICMP_SERVER", + GNUNET_NAT_ERROR_SUCCESS == ret ? "NO" : "YES"); + next_phase (ah); +} + + +/** + * Main function for the connection reversal test. + * + * @param cls the `struct GNUNET_NAT_AutoHandle` + */ +static void +reversal_test (void *cls) +{ + struct GNUNET_NAT_AutoHandle *ah = cls; + + ah->task = NULL; + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + _("Testing connection reversal with ICMP server.\n")); + GNUNET_RESOLVER_connect (ah->cfg); + ah->tst = GNUNET_NAT_test_start (ah->cfg, GNUNET_YES, 0, 0, TIMEOUT, + &result_callback, ah); +} + + +/** + * Set our external IPv4 address based on the UPnP. + * + * + * @param cls closure with our setup context + * @param addr the address, NULL on errors + * @param emsg NULL on success, otherwise an error message + */ +static void +set_external_ipv4 (void *cls, + const struct in_addr *addr, + enum GNUNET_NAT_StatusCode ret) +{ + struct GNUNET_NAT_AutoHandle *ah = cls; + char buf[INET_ADDRSTRLEN]; + + ah->eh = NULL; + ah->ret = ret; + if (GNUNET_NAT_ERROR_SUCCESS != ret) + { + next_phase (ah); + return; + } + /* enable 'behind nat' */ + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + _("Detected external IP `%s'\n"), + inet_ntop (AF_INET, + addr, + buf, + sizeof (buf))); + GNUNET_CONFIGURATION_set_value_string (ah->cfg, "nat", "BEHIND_NAT", "YES"); + + /* set external IP address */ + if (NULL == inet_ntop (AF_INET, addr, buf, sizeof (buf))) + { + GNUNET_break (0); + /* actually, this should never happen, as the caller already executed just + * this check, but for consistency (eg: future changes in the caller) + * we still need to report this error... + */ + ah->ret = GNUNET_NAT_ERROR_EXTERNAL_IP_ADDRESS_INVALID; + next_phase (ah); + return; + } + GNUNET_CONFIGURATION_set_value_string (ah->cfg, "nat", "EXTERNAL_ADDRESS", + buf); + ah->upnp_set_external_address = GNUNET_YES; + next_phase (ah); +} + + +/** + * Determine our external IPv4 address. + * + * @param ah auto setup context + */ +static void +test_external_ip (struct GNUNET_NAT_AutoHandle *ah) +{ + if (GNUNET_NAT_ERROR_SUCCESS != ah->ret) + next_phase (ah); + + // FIXME: CPS? + /* try to detect external IP */ + ah->eh = GNUNET_NAT_mini_get_external_ipv4 (TIMEOUT, + &set_external_ipv4, ah); +} + + +/** + * Determine our external IPv4 address and port using an external STUN server + * + * @param ah auto setup context + */ +static void +test_stun (struct GNUNET_NAT_AutoHandle *ah) +{ + + GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Running STUN test\n"); + + /* Get port from the configuration */ + if (GNUNET_OK != + GNUNET_CONFIGURATION_get_value_number (ah->cfg, + "transport-udp", + "PORT", + &port)) + { + port = 2086; + } + + //Lets create the socket + lsock4 = bind_v4 (); + if (NULL == lsock4) + { + GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "bind"); + next_phase(ah); + return; + } + else + { + //Lets call our function now when it accepts + ltask4 = GNUNET_SCHEDULER_add_read_net (NAT_SERVER_TIMEOUT, + lsock4, + &do_udp_read, + ah); + } + + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "STUN service listens on port %u\n", + (unsigned int) port); + if (GNUNET_NO == + GNUNET_NAT_stun_make_request (stun_server, + stun_port, + lsock4, + &request_callback, + NULL)) + { + /*An error happened*/ + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "STUN error, stopping\n"); + stop_stun (); + next_phase (ah); + } +} + + +/** + * Process list of local IP addresses. Find and set the + * one of the default interface. + * + * @param cls our `struct GNUNET_NAT_AutoHandle` + * @param name name of the interface (can be NULL for unknown) + * @param isDefault is this presumably the default interface + * @param addr address of this interface (can be NULL for unknown or unassigned) + * @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 length of the @a addr and @a broadcast_addr + * @return #GNUNET_OK to continue iteration, #GNUNET_SYSERR to abort + */ +static int +process_if (void *cls, + const char *name, + int isDefault, + const struct sockaddr *addr, + const struct sockaddr *broadcast_addr, + const struct sockaddr *netmask, + socklen_t addrlen) +{ + struct GNUNET_NAT_AutoHandle *ah = cls; + const struct sockaddr_in *in; + char buf[INET_ADDRSTRLEN]; + + + if ( (sizeof (struct sockaddr_in6) == addrlen) && + (0 != memcmp (&in6addr_loopback, &((const struct sockaddr_in6 *) addr)->sin6_addr, + sizeof (struct in6_addr))) && + (! IN6_IS_ADDR_LINKLOCAL(&((const struct sockaddr_in6 *) addr)->sin6_addr)) ) + { + ah->have_v6 = GNUNET_YES; + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + _("This system has a global IPv6 address, setting IPv6 to supported.\n")); + + return GNUNET_OK; + } + if (addrlen != sizeof (struct sockaddr_in)) + return GNUNET_OK; + in = (const struct sockaddr_in *) addr; + + + /* set internal IP address */ + if (NULL == inet_ntop (AF_INET, &in->sin_addr, buf, sizeof (buf))) + { + GNUNET_break (0); + return GNUNET_OK; + } + GNUNET_CONFIGURATION_set_value_string (ah->cfg, "nat", "INTERNAL_ADDRESS", + buf); + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + _("Detected internal network address `%s'.\n"), + buf); + + + ah->ret = GNUNET_NAT_ERROR_SUCCESS; + + /* Check if our internal IP is the same as the External detect by STUN*/ + if(ah->stun_ip && (strcmp(buf, ah->stun_ip) == 0) ) + { + ah->internal_ip_is_public = GNUNET_YES; + GNUNET_log (GNUNET_ERROR_TYPE_INFO,"A internal IP is the sameas the external"); + /* No need to continue*/ + return GNUNET_SYSERR; + } + + /* no need to continue iteration if we found the default */ + if (!isDefault) + return GNUNET_OK; + else + return GNUNET_SYSERR; +} + + +/** + * Determine our local IP addresses; detect internal IP & IPv6-support + * + * @param ah auto setup context + */ +static void +test_local_ip (struct GNUNET_NAT_AutoHandle *ah) +{ + ah->have_v6 = GNUNET_NO; + ah->ret = GNUNET_NAT_ERROR_NO_VALID_IF_IP_COMBO; // reset to success if any of the IFs in below iterator has a valid IP + GNUNET_OS_network_interfaces_list (&process_if, ah); + + GNUNET_CONFIGURATION_set_value_string (ah->cfg, "nat", "DISABLEV6", + (GNUNET_YES == ah->have_v6) ? "NO" : "YES"); + next_phase (ah); +} + + +/** + * We got disconnected from the NAT server. Stop + * waiting for a reply. + * + * @param cls the `struct GNUNET_NAT_AutoHandle` + * @param error error code + */ +static void +mq_error_handler (void *cls, + enum GNUNET_MQ_Error error) +{ + struct GNUNET_NAT_AutoHandle *ah = cls; + + GNUNET_MQ_destroy (ah->mq); + ah->mq = NULL; + /* wait a bit first? */ + next_phase (ah); +} + + +/** + * Test if NAT has been punched + * + * @param ah auto setup context + */ +static void +test_nat_punched (struct GNUNET_NAT_AutoHandle *ah) +{ + struct GNUNET_NAT_TestMessage *msg; + struct GNUNET_MQ_Envelope *env; + + if (! ah->stun_ip) + { + LOG (GNUNET_ERROR_TYPE_INFO, + "We don't have a STUN IP"); + next_phase (ah); + return; + } + + LOG (GNUNET_ERROR_TYPE_INFO, + "Asking gnunet-nat-server to connect to `%s'\n", + ah->stun_ip); + ah->mq = GNUNET_CLIENT_connecT (ah->cfg, + "gnunet-nat-server", + NULL, + &mq_error_handler, + ah); + if (NULL == ah->mq) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + _("Failed to connect to `gnunet-nat-server'\n")); + next_phase (ah); + return; + } + env = GNUNET_MQ_msg (msg, + GNUNET_MESSAGE_TYPE_NAT_TEST); + msg->dst_ipv4 = inet_addr (ah->stun_ip); + msg->dport = htons (ah->stun_port); + msg->data = port; + msg->is_tcp = htonl ((uint32_t) GNUNET_NO); + GNUNET_MQ_send (ah->mq, + env); + if (NULL != ltask4) + { + GNUNET_SCHEDULER_cancel (ltask4); + ltask4 = GNUNET_SCHEDULER_add_read_net (NAT_SERVER_TIMEOUT, + lsock4, + &do_udp_read, + ah); + } +} + + +/** + * Test if UPnPC works. + * + * @param ah auto setup context + */ +static void +test_upnpc (struct GNUNET_NAT_AutoHandle *ah) +{ + + int have_upnpc; + + if (GNUNET_NAT_ERROR_SUCCESS != ah->ret) + next_phase (ah); + + // test if upnpc is available + have_upnpc = (GNUNET_SYSERR != + GNUNET_OS_check_helper_binary ("upnpc", GNUNET_NO, NULL)); + //FIXME: test if upnpc is actually working, that is, if transports start to work once we use UPnP + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + (have_upnpc) + ? _("upnpc found, enabling its use\n") + : _("upnpc not found\n")); + GNUNET_CONFIGURATION_set_value_string (ah->cfg, "nat", "ENABLE_UPNP", + (GNUNET_YES == have_upnpc) ? "YES" : "NO"); + next_phase (ah); + +} + + +/** + * Test if ICMP server is working + * + * @param ah auto setup context + */ +static void +test_icmp_server (struct GNUNET_NAT_AutoHandle *ah) +{ + + int ext_ip; + int nated; + int binary; + char *tmp; + char *helper; + ext_ip = GNUNET_NO; + nated = GNUNET_NO; + binary = GNUNET_NO; + + tmp = NULL; + helper = GNUNET_OS_get_libexec_binary_path ("gnunet-helper-nat-server"); + if ( (GNUNET_OK == + GNUNET_CONFIGURATION_get_value_string (ah->cfg, + "nat", + "EXTERNAL_ADDRESS", + &tmp)) && + (0 < strlen (tmp)) ) + { + ext_ip = GNUNET_OK; + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + _("test_icmp_server not possible, as we have no public IPv4 address\n")); + } + else + goto err; + + if (GNUNET_YES == + GNUNET_CONFIGURATION_get_value_yesno (ah->cfg, + "nat", + "BEHIND_NAT")) + { + nated = GNUNET_YES; + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + _("test_icmp_server not possible, as we are not behind NAT\n")); + } + else + goto err; + + if (GNUNET_YES == + GNUNET_OS_check_helper_binary (helper, + GNUNET_YES, + "-d 127.0.0.1" )) + { + binary = GNUNET_OK; // use localhost as source for that one udp-port, ok for testing + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + _("No working gnunet-helper-nat-server found\n")); + } +err: + GNUNET_free_non_null (tmp); + GNUNET_free (helper); + + if ( (GNUNET_OK == ext_ip) && + (GNUNET_YES == nated) && + (GNUNET_OK == binary) ) + ah->task = GNUNET_SCHEDULER_add_now (&reversal_test, + ah); + else + next_phase (ah); +} + + +/** + * Test if ICMP client is working + * + * @param ah auto setup context + */ +static void +test_icmp_client (struct GNUNET_NAT_AutoHandle *ah) +{ + char *tmp; + char *helper; + + tmp = NULL; + helper = GNUNET_OS_get_libexec_binary_path ("gnunet-helper-nat-client"); + if ( (GNUNET_OK == + GNUNET_CONFIGURATION_get_value_string (ah->cfg, + "nat", + "INTERNAL_ADDRESS", + &tmp)) && + (0 < strlen (tmp)) ) + { + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + _("test_icmp_client not possible, as we have no internal IPv4 address\n")); + } + else + goto err; + + if (GNUNET_YES != + GNUNET_CONFIGURATION_get_value_yesno (ah->cfg, + "nat", + "BEHIND_NAT")) + { + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + _("test_icmp_server not possible, as we are not behind NAT\n")); + } + else + goto err; + + if (GNUNET_YES == + GNUNET_OS_check_helper_binary (helper, + GNUNET_YES, + "-d 127.0.0.1 127.0.0.2 42")) + { + // none of these parameters are actually used in privilege testing mode + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + _("No working gnunet-helper-nat-server found\n")); + } +err: + GNUNET_free_non_null (tmp); + GNUNET_free (helper); + + next_phase (ah); +} + + +/** + * Run the next phase of the auto test. + */ +static void +next_phase (struct GNUNET_NAT_AutoHandle *ah) +{ + struct GNUNET_CONFIGURATION_Handle *diff; + + ah->phase++; + switch (ah->phase) + { + case AUTO_INIT: + GNUNET_assert (0); + break; + case AUTO_EXTERNAL_IP: + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Will run AUTO_EXTERNAL_IP\n"); + test_external_ip (ah); + break; + case AUTO_STUN: + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Will run AUTO_STUN\n"); + test_stun (ah); + break; + case AUTO_LOCAL_IP: + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Will run AUTO_LOCAL_IP\n"); + test_local_ip (ah); + break; + case AUTO_NAT_PUNCHED: + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Will run AUTO_NAT_PUNCHED\n"); + test_nat_punched (ah); + break; + case AUTO_UPNPC: + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Will run AUTO_UPNPC\n"); + test_upnpc (ah); + break; + case AUTO_ICMP_SERVER: + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Will run AUTO_ICMP_SERVER\n"); + test_icmp_server (ah); + break; + case AUTO_ICMP_CLIENT: + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Will run AUTO_ICMP_CLIENT\n"); + test_icmp_client (ah); + break; + case AUTO_DONE: + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Done with tests\n"); + if (!ah->internal_ip_is_public) + { + GNUNET_CONFIGURATION_set_value_string (ah->cfg, + "nat", + "BEHIND_NAT", + "YES"); + + if (ah->connected_back) + { + GNUNET_CONFIGURATION_set_value_string (ah->cfg, + "nat", + "PUNCHED_NAT", + "YES"); + } + else + { + GNUNET_CONFIGURATION_set_value_string (ah->cfg, + "nat", + "PUNCHED_NAT", + "NO"); + } + + if (ah->stun_ip) + { + GNUNET_CONFIGURATION_set_value_string (ah->cfg, + "nat", + "EXTERNAL_ADDRESS", + ah->stun_ip); + if (ah->connected_back) + { + ah->type = GNUNET_NAT_TYPE_STUN_PUNCHED_NAT; + GNUNET_CONFIGURATION_set_value_string (ah->cfg, + "nat", + "USE_STUN", + "YES"); + } + else + { + ah->type = GNUNET_NAT_TYPE_UNREACHABLE_NAT; + GNUNET_CONFIGURATION_set_value_string (ah->cfg, + "nat", + "USE_STUN", + "NO"); + } + + } + if (0 != ah->stun_port) + { + GNUNET_CONFIGURATION_set_value_number (ah->cfg, + "transport-udp", + "ADVERTISED_PORT", + ah->stun_port); + } + + } + else + { + //The internal IP is the same as public, but we didn't got a incoming connection + if (ah->connected_back) + { + ah->type = GNUNET_NAT_TYPE_NO_NAT; + GNUNET_CONFIGURATION_set_value_string (ah->cfg, + "nat", + "BEHIND_NAT", + "NO"); + } + else + { + GNUNET_CONFIGURATION_set_value_string (ah->cfg, + "nat", + "BEHIND_NAT", + "YES"); + ah->type = GNUNET_NAT_TYPE_UNREACHABLE_NAT; + if (ah->stun_ip) + { + GNUNET_CONFIGURATION_set_value_string (ah->cfg, + "nat", + "EXTERNAL_ADDRESS", + ah->stun_ip); + } + if (0 != ah->stun_port) + { + GNUNET_CONFIGURATION_set_value_number (ah->cfg, + "transport-udp", + "ADVERTISED_PORT", + ah->stun_port); + + } + } + } + + diff = GNUNET_CONFIGURATION_get_diff (ah->initial_cfg, + ah->cfg); + + + ah->fin_cb (ah->fin_cb_cls, + diff, + ah->ret, + ah->type); + GNUNET_CONFIGURATION_destroy (diff); + GNUNET_NAT_autoconfig_cancel (ah); + } +} + + +/** + * Start auto-configuration routine. The resolver service should + * be available when this function is called. + * + * @param cfg initial configuration + * @param cb function to call with autoconfiguration result + * @param cb_cls closure for @a cb + * @return handle to cancel operation + */ +struct GNUNET_NAT_AutoHandle * +GNUNET_NAT_autoconfig_start (const struct GNUNET_CONFIGURATION_Handle *cfg, + GNUNET_NAT_AutoResultCallback cb, + void *cb_cls) +{ + struct GNUNET_NAT_AutoHandle *ah; + + ah = GNUNET_new (struct GNUNET_NAT_AutoHandle); + ah->fin_cb = cb; + ah->fin_cb_cls = cb_cls; + ah->ret = GNUNET_NAT_ERROR_SUCCESS; + ah->cfg = GNUNET_CONFIGURATION_dup (cfg); + ah->initial_cfg = GNUNET_CONFIGURATION_dup (cfg); + + /* never use loopback addresses if user wanted autoconfiguration */ + GNUNET_CONFIGURATION_set_value_string (ah->cfg, + "nat", + "USE_LOCALADDR", + "NO"); + + next_phase (ah); + return ah; +} + + +/** + * Abort autoconfiguration. + * + * @param ah handle for operation to abort + */ +void +GNUNET_NAT_autoconfig_cancel (struct GNUNET_NAT_AutoHandle *ah) +{ + if (NULL != ah->tst) + { + GNUNET_NAT_test_stop (ah->tst); + ah->tst = NULL; + } + if (NULL != ah->eh) + { + GNUNET_NAT_mini_get_external_ipv4_cancel (ah->eh); + ah->eh = NULL; + } + if (NULL != ah->mq) + { + GNUNET_MQ_destroy (ah->mq); + ah->mq = NULL; + } + if (NULL != ah->task) + { + GNUNET_SCHEDULER_cancel (ah->task); + ah->task = NULL; + } + GNUNET_CONFIGURATION_destroy (ah->cfg); + GNUNET_CONFIGURATION_destroy (ah->initial_cfg); + GNUNET_free (ah); +} + + +/* end of nat_auto.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_auto.c b/src/nat/nat_auto.c deleted file mode 100644 index 061d0cbe6..000000000 --- a/src/nat/nat_auto.c +++ /dev/null @@ -1,1081 +0,0 @@ -/* - This file is part of GNUnet. - Copyright (C) 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. -*/ - -/** - * @file nat/nat_auto.c - * @brief functions for auto-configuration of the network - * @author Christian Grothoff - * @author Bruno Cabral - */ -#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 long do we wait for the NAT test to report success? - */ -#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 15) - -#define NAT_SERVER_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 10) - -/** - * Phases of the auto configuration. - */ -enum AutoPhase -{ - /** - * Initial start value. - */ - AUTO_INIT = 0, - - /** - * Test our external IP. - */ - AUTO_EXTERNAL_IP, - - /** - * Test our external IP. - */ - AUTO_STUN, - - /** - * Test our internal IP. - */ - AUTO_LOCAL_IP, - - /** - * Test if NAT was punched. - */ - AUTO_NAT_PUNCHED, - - /** - * Test if UPnP is working. - */ - AUTO_UPNPC, - - /** - * Test if ICMP server works. - */ - AUTO_ICMP_SERVER, - - /** - * Test if ICMP client works. - */ - AUTO_ICMP_CLIENT, - - /** - * Last phase, we're done. - */ - AUTO_DONE - -}; - - -/** - * Handle to auto-configuration in progress. - */ -struct GNUNET_NAT_AutoHandle -{ - - /** - * Handle to the active NAT test. - */ - struct GNUNET_NAT_Test *tst; - - /** - * Function to call when done. - */ - GNUNET_NAT_AutoResultCallback fin_cb; - - /** - * Closure for @e fin_cb. - */ - void *fin_cb_cls; - - /** - * Handle for active 'GNUNET_NAT_mini_get_external_ipv4'-operation. - */ - struct GNUNET_NAT_ExternalHandle *eh; - - /** - * Current configuration (with updates from previous phases) - */ - struct GNUNET_CONFIGURATION_Handle *cfg; - - /** - * Original configuration (used to calculate differences) - */ - struct GNUNET_CONFIGURATION_Handle *initial_cfg; - - /** - * Task identifier for the timeout. - */ - struct GNUNET_SCHEDULER_Task *task; - - /** - * Message queue to the gnunet-nat-server. - */ - struct GNUNET_MQ_Handle *mq; - - /** - * Where are we in the test? - */ - enum AutoPhase phase; - - /** - * Situation of the NAT - */ - enum GNUNET_NAT_Type type; - - /** - * Do we have IPv6? - */ - int have_v6; - - /** - * UPnP already set the external ip address ? - */ - int upnp_set_external_address; - - /** - * Did the external server connected back ? - */ - int connected_back; - - /** - * Address detected by STUN - */ - char *stun_ip; - - unsigned int stun_port; - - /** - * Internal IP is the same as the public one ? - */ - int internal_ip_is_public; - - /** - * Error code for better debugging and user feedback - */ - enum GNUNET_NAT_StatusCode ret; -}; - - -/** - * The listen socket of the service for IPv4 - */ -static struct GNUNET_NETWORK_Handle *lsock4; - -/** - * The listen task ID for IPv4 - */ -static struct GNUNET_SCHEDULER_Task *ltask4; - -/** - * The port the test service is running on (default 7895) - */ -static unsigned long long port = 7895; - -static char *stun_server = "stun.ekiga.net"; - -static unsigned int stun_port = 3478; - - -/** - * Run the next phase of the auto test. - * - * @param ah auto test handle - */ -static void -next_phase (struct GNUNET_NAT_AutoHandle *ah); - - -static void -process_stun_reply(struct sockaddr_in *answer, - struct GNUNET_NAT_AutoHandle *ah) -{ - ah->stun_ip = inet_ntoa(answer->sin_addr); - ah->stun_port = ntohs (answer->sin_port); - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "External IP is: %s , with port %u\n", - ah->stun_ip, - ah->stun_port); - next_phase (ah); -} - - -/** - * Function that terminates the test. - */ -static void -stop_stun () -{ - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "Stopping STUN and quitting...\n"); - /* Clean task */ - if (NULL != ltask4) - { - GNUNET_SCHEDULER_cancel (ltask4); - ltask4 = NULL; - } - /* Clean socket */ - if (NULL != lsock4) - { - GNUNET_NETWORK_socket_close (lsock4); - lsock4 = NULL; - } -} - - -/** - * Activity on our incoming socket. Read data from the - * incoming connection. - * - * @param cls - */ -static void -do_udp_read (void *cls) -{ - struct GNUNET_NAT_AutoHandle *ah = cls; - unsigned char reply_buf[1024]; - ssize_t rlen; - struct sockaddr_in answer; - const struct GNUNET_SCHEDULER_TaskContext *tc; - - tc = GNUNET_SCHEDULER_get_task_context (); - if ((0 != (tc->reason & GNUNET_SCHEDULER_REASON_READ_READY)) && - (GNUNET_NETWORK_fdset_isset (tc->read_ready, - lsock4))) - { - rlen = GNUNET_NETWORK_socket_recv (lsock4, - reply_buf, - sizeof (reply_buf)); - - //Lets handle the packet - memset (&answer, 0, sizeof(struct sockaddr_in)); - if (ah->phase == AUTO_NAT_PUNCHED) - { - //Destroy the connection - GNUNET_NETWORK_socket_close (lsock4); - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "The external server was able to connect back"); - ah->connected_back = GNUNET_YES; - next_phase (ah); - } - else - { - if (GNUNET_OK == - GNUNET_NAT_stun_handle_packet (reply_buf, rlen, &answer)) - { - //Process the answer - process_stun_reply (&answer, ah); - } - else - { - next_phase (ah); - } - } - } - else - { - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "TIMEOUT while waiting for an answer\n"); - if (ah->phase == AUTO_NAT_PUNCHED) - { - stop_stun(); - } - - next_phase (ah); - } -} - - -/** - * Create an IPv4 listen socket bound to our port. - * - * @return NULL on error - */ -static struct GNUNET_NETWORK_Handle * -bind_v4 () -{ - struct GNUNET_NETWORK_Handle *ls; - struct sockaddr_in sa4; - int eno; - - memset (&sa4, 0, sizeof (sa4)); - sa4.sin_family = AF_INET; - sa4.sin_port = htons (port); -#if HAVE_SOCKADDR_IN_SIN_LEN - sa4.sin_len = sizeof (sa4); -#endif - ls = GNUNET_NETWORK_socket_create (AF_INET, - SOCK_DGRAM, - 0); - if (NULL == ls) - return NULL; - if (GNUNET_OK != - GNUNET_NETWORK_socket_bind (ls, (const struct sockaddr *) &sa4, - sizeof (sa4))) - { - eno = errno; - GNUNET_NETWORK_socket_close (ls); - errno = eno; - return NULL; - } - return ls; -} - - -static void -request_callback (void *cls, - enum GNUNET_NAT_StatusCode result) -{ - // struct GNUNET_NAT_AutoHandle *ah = cls; - - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "Request callback: stop and quit\n"); - stop_stun (); - - // next_phase (ah); FIXME this always will be NULL, as called in test_stun() -} - - -/** - * Function called by NAT to report the outcome of the nat-test. - * Clean up and update GUI. - * - * @param cls the auto handle - * @param success currently always #GNUNET_OK - * @param emsg NULL on success, otherwise an error message - */ -static void -result_callback (void *cls, - enum GNUNET_NAT_StatusCode ret) -{ - struct GNUNET_NAT_AutoHandle *ah = cls; - - if (GNUNET_NAT_ERROR_SUCCESS == ret) - GNUNET_NAT_test_stop (ah->tst); - ah->tst = NULL; - ah->ret = ret; - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - GNUNET_NAT_ERROR_SUCCESS == ret - ? _("NAT traversal with ICMP Server succeeded.\n") - : _("NAT traversal with ICMP Server failed.\n")); - GNUNET_CONFIGURATION_set_value_string (ah->cfg, "nat", "ENABLE_ICMP_SERVER", - GNUNET_NAT_ERROR_SUCCESS == ret ? "NO" : "YES"); - next_phase (ah); -} - - -/** - * Main function for the connection reversal test. - * - * @param cls the `struct GNUNET_NAT_AutoHandle` - */ -static void -reversal_test (void *cls) -{ - struct GNUNET_NAT_AutoHandle *ah = cls; - - ah->task = NULL; - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - _("Testing connection reversal with ICMP server.\n")); - GNUNET_RESOLVER_connect (ah->cfg); - ah->tst = GNUNET_NAT_test_start (ah->cfg, GNUNET_YES, 0, 0, TIMEOUT, - &result_callback, ah); -} - - -/** - * Set our external IPv4 address based on the UPnP. - * - * - * @param cls closure with our setup context - * @param addr the address, NULL on errors - * @param emsg NULL on success, otherwise an error message - */ -static void -set_external_ipv4 (void *cls, - const struct in_addr *addr, - enum GNUNET_NAT_StatusCode ret) -{ - struct GNUNET_NAT_AutoHandle *ah = cls; - char buf[INET_ADDRSTRLEN]; - - ah->eh = NULL; - ah->ret = ret; - if (GNUNET_NAT_ERROR_SUCCESS != ret) - { - next_phase (ah); - return; - } - /* enable 'behind nat' */ - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - _("Detected external IP `%s'\n"), - inet_ntop (AF_INET, - addr, - buf, - sizeof (buf))); - GNUNET_CONFIGURATION_set_value_string (ah->cfg, "nat", "BEHIND_NAT", "YES"); - - /* set external IP address */ - if (NULL == inet_ntop (AF_INET, addr, buf, sizeof (buf))) - { - GNUNET_break (0); - /* actually, this should never happen, as the caller already executed just - * this check, but for consistency (eg: future changes in the caller) - * we still need to report this error... - */ - ah->ret = GNUNET_NAT_ERROR_EXTERNAL_IP_ADDRESS_INVALID; - next_phase (ah); - return; - } - GNUNET_CONFIGURATION_set_value_string (ah->cfg, "nat", "EXTERNAL_ADDRESS", - buf); - ah->upnp_set_external_address = GNUNET_YES; - next_phase (ah); -} - - -/** - * Determine our external IPv4 address. - * - * @param ah auto setup context - */ -static void -test_external_ip (struct GNUNET_NAT_AutoHandle *ah) -{ - if (GNUNET_NAT_ERROR_SUCCESS != ah->ret) - next_phase (ah); - - // FIXME: CPS? - /* try to detect external IP */ - ah->eh = GNUNET_NAT_mini_get_external_ipv4 (TIMEOUT, - &set_external_ipv4, ah); -} - - -/** - * Determine our external IPv4 address and port using an external STUN server - * - * @param ah auto setup context - */ -static void -test_stun (struct GNUNET_NAT_AutoHandle *ah) -{ - - GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Running STUN test\n"); - - /* Get port from the configuration */ - if (GNUNET_OK != - GNUNET_CONFIGURATION_get_value_number (ah->cfg, - "transport-udp", - "PORT", - &port)) - { - port = 2086; - } - - //Lets create the socket - lsock4 = bind_v4 (); - if (NULL == lsock4) - { - GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "bind"); - next_phase(ah); - return; - } - else - { - //Lets call our function now when it accepts - ltask4 = GNUNET_SCHEDULER_add_read_net (NAT_SERVER_TIMEOUT, - lsock4, - &do_udp_read, - ah); - } - - - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "STUN service listens on port %u\n", - (unsigned int) port); - if (GNUNET_NO == - GNUNET_NAT_stun_make_request (stun_server, - stun_port, - lsock4, - &request_callback, - NULL)) - { - /*An error happened*/ - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "STUN error, stopping\n"); - stop_stun (); - next_phase (ah); - } -} - - -/** - * Process list of local IP addresses. Find and set the - * one of the default interface. - * - * @param cls our `struct GNUNET_NAT_AutoHandle` - * @param name name of the interface (can be NULL for unknown) - * @param isDefault is this presumably the default interface - * @param addr address of this interface (can be NULL for unknown or unassigned) - * @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 length of the @a addr and @a broadcast_addr - * @return #GNUNET_OK to continue iteration, #GNUNET_SYSERR to abort - */ -static int -process_if (void *cls, - const char *name, - int isDefault, - const struct sockaddr *addr, - const struct sockaddr *broadcast_addr, - const struct sockaddr *netmask, - socklen_t addrlen) -{ - struct GNUNET_NAT_AutoHandle *ah = cls; - const struct sockaddr_in *in; - char buf[INET_ADDRSTRLEN]; - - - if ( (sizeof (struct sockaddr_in6) == addrlen) && - (0 != memcmp (&in6addr_loopback, &((const struct sockaddr_in6 *) addr)->sin6_addr, - sizeof (struct in6_addr))) && - (! IN6_IS_ADDR_LINKLOCAL(&((const struct sockaddr_in6 *) addr)->sin6_addr)) ) - { - ah->have_v6 = GNUNET_YES; - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - _("This system has a global IPv6 address, setting IPv6 to supported.\n")); - - return GNUNET_OK; - } - if (addrlen != sizeof (struct sockaddr_in)) - return GNUNET_OK; - in = (const struct sockaddr_in *) addr; - - - /* set internal IP address */ - if (NULL == inet_ntop (AF_INET, &in->sin_addr, buf, sizeof (buf))) - { - GNUNET_break (0); - return GNUNET_OK; - } - GNUNET_CONFIGURATION_set_value_string (ah->cfg, "nat", "INTERNAL_ADDRESS", - buf); - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - _("Detected internal network address `%s'.\n"), - buf); - - - ah->ret = GNUNET_NAT_ERROR_SUCCESS; - - /* Check if our internal IP is the same as the External detect by STUN*/ - if(ah->stun_ip && (strcmp(buf, ah->stun_ip) == 0) ) - { - ah->internal_ip_is_public = GNUNET_YES; - GNUNET_log (GNUNET_ERROR_TYPE_INFO,"A internal IP is the sameas the external"); - /* No need to continue*/ - return GNUNET_SYSERR; - } - - /* no need to continue iteration if we found the default */ - if (!isDefault) - return GNUNET_OK; - else - return GNUNET_SYSERR; -} - - -/** - * Determine our local IP addresses; detect internal IP & IPv6-support - * - * @param ah auto setup context - */ -static void -test_local_ip (struct GNUNET_NAT_AutoHandle *ah) -{ - ah->have_v6 = GNUNET_NO; - ah->ret = GNUNET_NAT_ERROR_NO_VALID_IF_IP_COMBO; // reset to success if any of the IFs in below iterator has a valid IP - GNUNET_OS_network_interfaces_list (&process_if, ah); - - GNUNET_CONFIGURATION_set_value_string (ah->cfg, "nat", "DISABLEV6", - (GNUNET_YES == ah->have_v6) ? "NO" : "YES"); - next_phase (ah); -} - - -/** - * We got disconnected from the NAT server. Stop - * waiting for a reply. - * - * @param cls the `struct GNUNET_NAT_AutoHandle` - * @param error error code - */ -static void -mq_error_handler (void *cls, - enum GNUNET_MQ_Error error) -{ - struct GNUNET_NAT_AutoHandle *ah = cls; - - GNUNET_MQ_destroy (ah->mq); - ah->mq = NULL; - /* wait a bit first? */ - next_phase (ah); -} - - -/** - * Test if NAT has been punched - * - * @param ah auto setup context - */ -static void -test_nat_punched (struct GNUNET_NAT_AutoHandle *ah) -{ - struct GNUNET_NAT_TestMessage *msg; - struct GNUNET_MQ_Envelope *env; - - if (! ah->stun_ip) - { - LOG (GNUNET_ERROR_TYPE_INFO, - "We don't have a STUN IP"); - next_phase (ah); - return; - } - - LOG (GNUNET_ERROR_TYPE_INFO, - "Asking gnunet-nat-server to connect to `%s'\n", - ah->stun_ip); - ah->mq = GNUNET_CLIENT_connecT (ah->cfg, - "gnunet-nat-server", - NULL, - &mq_error_handler, - ah); - if (NULL == ah->mq) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - _("Failed to connect to `gnunet-nat-server'\n")); - next_phase (ah); - return; - } - env = GNUNET_MQ_msg (msg, - GNUNET_MESSAGE_TYPE_NAT_TEST); - msg->dst_ipv4 = inet_addr (ah->stun_ip); - msg->dport = htons (ah->stun_port); - msg->data = port; - msg->is_tcp = htonl ((uint32_t) GNUNET_NO); - GNUNET_MQ_send (ah->mq, - env); - if (NULL != ltask4) - { - GNUNET_SCHEDULER_cancel (ltask4); - ltask4 = GNUNET_SCHEDULER_add_read_net (NAT_SERVER_TIMEOUT, - lsock4, - &do_udp_read, - ah); - } -} - - -/** - * Test if UPnPC works. - * - * @param ah auto setup context - */ -static void -test_upnpc (struct GNUNET_NAT_AutoHandle *ah) -{ - - int have_upnpc; - - if (GNUNET_NAT_ERROR_SUCCESS != ah->ret) - next_phase (ah); - - // test if upnpc is available - have_upnpc = (GNUNET_SYSERR != - GNUNET_OS_check_helper_binary ("upnpc", GNUNET_NO, NULL)); - //FIXME: test if upnpc is actually working, that is, if transports start to work once we use UPnP - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - (have_upnpc) - ? _("upnpc found, enabling its use\n") - : _("upnpc not found\n")); - GNUNET_CONFIGURATION_set_value_string (ah->cfg, "nat", "ENABLE_UPNP", - (GNUNET_YES == have_upnpc) ? "YES" : "NO"); - next_phase (ah); - -} - - -/** - * Test if ICMP server is working - * - * @param ah auto setup context - */ -static void -test_icmp_server (struct GNUNET_NAT_AutoHandle *ah) -{ - - int ext_ip; - int nated; - int binary; - char *tmp; - char *helper; - ext_ip = GNUNET_NO; - nated = GNUNET_NO; - binary = GNUNET_NO; - - tmp = NULL; - helper = GNUNET_OS_get_libexec_binary_path ("gnunet-helper-nat-server"); - if ( (GNUNET_OK == - GNUNET_CONFIGURATION_get_value_string (ah->cfg, - "nat", - "EXTERNAL_ADDRESS", - &tmp)) && - (0 < strlen (tmp)) ) - { - ext_ip = GNUNET_OK; - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - _("test_icmp_server not possible, as we have no public IPv4 address\n")); - } - else - goto err; - - if (GNUNET_YES == - GNUNET_CONFIGURATION_get_value_yesno (ah->cfg, - "nat", - "BEHIND_NAT")) - { - nated = GNUNET_YES; - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - _("test_icmp_server not possible, as we are not behind NAT\n")); - } - else - goto err; - - if (GNUNET_YES == - GNUNET_OS_check_helper_binary (helper, - GNUNET_YES, - "-d 127.0.0.1" )) - { - binary = GNUNET_OK; // use localhost as source for that one udp-port, ok for testing - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - _("No working gnunet-helper-nat-server found\n")); - } -err: - GNUNET_free_non_null (tmp); - GNUNET_free (helper); - - if ( (GNUNET_OK == ext_ip) && - (GNUNET_YES == nated) && - (GNUNET_OK == binary) ) - ah->task = GNUNET_SCHEDULER_add_now (&reversal_test, - ah); - else - next_phase (ah); -} - - -/** - * Test if ICMP client is working - * - * @param ah auto setup context - */ -static void -test_icmp_client (struct GNUNET_NAT_AutoHandle *ah) -{ - char *tmp; - char *helper; - - tmp = NULL; - helper = GNUNET_OS_get_libexec_binary_path ("gnunet-helper-nat-client"); - if ( (GNUNET_OK == - GNUNET_CONFIGURATION_get_value_string (ah->cfg, - "nat", - "INTERNAL_ADDRESS", - &tmp)) && - (0 < strlen (tmp)) ) - { - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - _("test_icmp_client not possible, as we have no internal IPv4 address\n")); - } - else - goto err; - - if (GNUNET_YES != - GNUNET_CONFIGURATION_get_value_yesno (ah->cfg, - "nat", - "BEHIND_NAT")) - { - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - _("test_icmp_server not possible, as we are not behind NAT\n")); - } - else - goto err; - - if (GNUNET_YES == - GNUNET_OS_check_helper_binary (helper, - GNUNET_YES, - "-d 127.0.0.1 127.0.0.2 42")) - { - // none of these parameters are actually used in privilege testing mode - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - _("No working gnunet-helper-nat-server found\n")); - } -err: - GNUNET_free_non_null (tmp); - GNUNET_free (helper); - - next_phase (ah); -} - - -/** - * Run the next phase of the auto test. - */ -static void -next_phase (struct GNUNET_NAT_AutoHandle *ah) -{ - struct GNUNET_CONFIGURATION_Handle *diff; - - ah->phase++; - switch (ah->phase) - { - case AUTO_INIT: - GNUNET_assert (0); - break; - case AUTO_EXTERNAL_IP: - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Will run AUTO_EXTERNAL_IP\n"); - test_external_ip (ah); - break; - case AUTO_STUN: - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Will run AUTO_STUN\n"); - test_stun (ah); - break; - case AUTO_LOCAL_IP: - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Will run AUTO_LOCAL_IP\n"); - test_local_ip (ah); - break; - case AUTO_NAT_PUNCHED: - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Will run AUTO_NAT_PUNCHED\n"); - test_nat_punched (ah); - break; - case AUTO_UPNPC: - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Will run AUTO_UPNPC\n"); - test_upnpc (ah); - break; - case AUTO_ICMP_SERVER: - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Will run AUTO_ICMP_SERVER\n"); - test_icmp_server (ah); - break; - case AUTO_ICMP_CLIENT: - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Will run AUTO_ICMP_CLIENT\n"); - test_icmp_client (ah); - break; - case AUTO_DONE: - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Done with tests\n"); - if (!ah->internal_ip_is_public) - { - GNUNET_CONFIGURATION_set_value_string (ah->cfg, - "nat", - "BEHIND_NAT", - "YES"); - - if (ah->connected_back) - { - GNUNET_CONFIGURATION_set_value_string (ah->cfg, - "nat", - "PUNCHED_NAT", - "YES"); - } - else - { - GNUNET_CONFIGURATION_set_value_string (ah->cfg, - "nat", - "PUNCHED_NAT", - "NO"); - } - - if (ah->stun_ip) - { - GNUNET_CONFIGURATION_set_value_string (ah->cfg, - "nat", - "EXTERNAL_ADDRESS", - ah->stun_ip); - if (ah->connected_back) - { - ah->type = GNUNET_NAT_TYPE_STUN_PUNCHED_NAT; - GNUNET_CONFIGURATION_set_value_string (ah->cfg, - "nat", - "USE_STUN", - "YES"); - } - else - { - ah->type = GNUNET_NAT_TYPE_UNREACHABLE_NAT; - GNUNET_CONFIGURATION_set_value_string (ah->cfg, - "nat", - "USE_STUN", - "NO"); - } - - } - if (0 != ah->stun_port) - { - GNUNET_CONFIGURATION_set_value_number (ah->cfg, - "transport-udp", - "ADVERTISED_PORT", - ah->stun_port); - } - - } - else - { - //The internal IP is the same as public, but we didn't got a incoming connection - if (ah->connected_back) - { - ah->type = GNUNET_NAT_TYPE_NO_NAT; - GNUNET_CONFIGURATION_set_value_string (ah->cfg, - "nat", - "BEHIND_NAT", - "NO"); - } - else - { - GNUNET_CONFIGURATION_set_value_string (ah->cfg, - "nat", - "BEHIND_NAT", - "YES"); - ah->type = GNUNET_NAT_TYPE_UNREACHABLE_NAT; - if (ah->stun_ip) - { - GNUNET_CONFIGURATION_set_value_string (ah->cfg, - "nat", - "EXTERNAL_ADDRESS", - ah->stun_ip); - } - if (0 != ah->stun_port) - { - GNUNET_CONFIGURATION_set_value_number (ah->cfg, - "transport-udp", - "ADVERTISED_PORT", - ah->stun_port); - - } - } - } - - diff = GNUNET_CONFIGURATION_get_diff (ah->initial_cfg, - ah->cfg); - - - ah->fin_cb (ah->fin_cb_cls, - diff, - ah->ret, - ah->type); - GNUNET_CONFIGURATION_destroy (diff); - GNUNET_NAT_autoconfig_cancel (ah); - } -} - - -/** - * Start auto-configuration routine. The resolver service should - * be available when this function is called. - * - * @param cfg initial configuration - * @param cb function to call with autoconfiguration result - * @param cb_cls closure for @a cb - * @return handle to cancel operation - */ -struct GNUNET_NAT_AutoHandle * -GNUNET_NAT_autoconfig_start (const struct GNUNET_CONFIGURATION_Handle *cfg, - GNUNET_NAT_AutoResultCallback cb, - void *cb_cls) -{ - struct GNUNET_NAT_AutoHandle *ah; - - ah = GNUNET_new (struct GNUNET_NAT_AutoHandle); - ah->fin_cb = cb; - ah->fin_cb_cls = cb_cls; - ah->ret = GNUNET_NAT_ERROR_SUCCESS; - ah->cfg = GNUNET_CONFIGURATION_dup (cfg); - ah->initial_cfg = GNUNET_CONFIGURATION_dup (cfg); - - /* never use loopback addresses if user wanted autoconfiguration */ - GNUNET_CONFIGURATION_set_value_string (ah->cfg, - "nat", - "USE_LOCALADDR", - "NO"); - - next_phase (ah); - return ah; -} - - -/** - * Abort autoconfiguration. - * - * @param ah handle for operation to abort - */ -void -GNUNET_NAT_autoconfig_cancel (struct GNUNET_NAT_AutoHandle *ah) -{ - if (NULL != ah->tst) - { - GNUNET_NAT_test_stop (ah->tst); - ah->tst = NULL; - } - if (NULL != ah->eh) - { - GNUNET_NAT_mini_get_external_ipv4_cancel (ah->eh); - ah->eh = NULL; - } - if (NULL != ah->mq) - { - GNUNET_MQ_destroy (ah->mq); - ah->mq = NULL; - } - if (NULL != ah->task) - { - GNUNET_SCHEDULER_cancel (ah->task); - ah->task = NULL; - } - GNUNET_CONFIGURATION_destroy (ah->cfg); - GNUNET_CONFIGURATION_destroy (ah->initial_cfg); - GNUNET_free (ah); -} - - -/* end of nat_auto.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/nat/nat_test.c b/src/nat/nat_test.c deleted file mode 100644 index 803ff23e3..000000000 --- a/src/nat/nat_test.c +++ /dev/null @@ -1,645 +0,0 @@ -/* - This file is part of GNUnet. - Copyright (C) 2011, 2016 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_test.c - * @brief functions to test if the NAT configuration is successful at achieving NAT traversal (with the help of a gnunet-nat-server) - * @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__) - -#define NAT_SERVER_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 30) - -/** - * Entry we keep for each incoming connection. - */ -struct NatActivity -{ - /** - * This is a doubly-linked list. - */ - struct NatActivity *next; - - /** - * This is a doubly-linked list. - */ - struct NatActivity *prev; - - /** - * Socket of the incoming connection. - */ - struct GNUNET_NETWORK_Handle *sock; - - /** - * Handle of the master context. - */ - struct GNUNET_NAT_Test *h; - - /** - * Task reading from the incoming connection. - */ - struct GNUNET_SCHEDULER_Task *rtask; -}; - - -/** - * Entry we keep for each connection to the gnunet-nat-service. - */ -struct ClientActivity -{ - /** - * This is a doubly-linked list. - */ - struct ClientActivity *next; - - /** - * This is a doubly-linked list. - */ - struct ClientActivity *prev; - - /** - * Socket of the incoming connection. - */ - struct GNUNET_MQ_Handle *mq; - - /** - * Handle to overall NAT test. - */ - struct GNUNET_NAT_Test *h; - -}; - - -/** - * Handle to a NAT test. - */ -struct GNUNET_NAT_Test -{ - - /** - * Configuration used - */ - const struct GNUNET_CONFIGURATION_Handle *cfg; - - /** - * Function to call with success report - */ - GNUNET_NAT_TestCallback report; - - /** - * Closure for @e report. - */ - void *report_cls; - - /** - * Handle to NAT traversal in use - */ - struct GNUNET_NAT_Handle *nat; - - /** - * Handle to listen socket, or NULL - */ - struct GNUNET_NETWORK_Handle *lsock; - - /** - * Head of list of nat activities. - */ - struct NatActivity *na_head; - - /** - * Tail of list of nat activities. - */ - struct NatActivity *na_tail; - - /** - * Head of list of client activities. - */ - struct ClientActivity *ca_head; - - /** - * Tail of list of client activities. - */ - struct ClientActivity *ca_tail; - - /** - * Identity of task for the listen socket (if any) - */ - struct GNUNET_SCHEDULER_Task *ltask; - - /** - * Task identifier for the timeout (if any) - */ - struct GNUNET_SCHEDULER_Task *ttask; - - /** - * #GNUNET_YES if we're testing TCP - */ - int is_tcp; - - /** - * Data that should be transmitted or source-port. - */ - uint16_t data; - - /** - * Advertised port to the other peer. - */ - uint16_t adv_port; - - /** - * Status code to be reported to the timeout/status call - */ - enum GNUNET_NAT_StatusCode status; -}; - - -/** - * Function called from #GNUNET_NAT_register whenever someone asks us - * to do connection reversal. - * - * @param cls closure, our `struct GNUNET_NAT_Handle` - * @param addr public IP address of the other peer - * @param addrlen actual lenght of the @a addr - */ -static void -reversal_cb (void *cls, - const struct sockaddr *addr, - socklen_t addrlen) -{ - struct GNUNET_NAT_Test *h = cls; - const struct sockaddr_in *sa; - - if (sizeof (struct sockaddr_in) != addrlen) - return; - sa = (const struct sockaddr_in *) addr; - if (h->data != sa->sin_port) - { - LOG (GNUNET_ERROR_TYPE_DEBUG, - "Received connection reversal request for wrong port\n"); - return; /* wrong port */ - } - /* report success */ - h->report (h->report_cls, - GNUNET_NAT_ERROR_SUCCESS); -} - - -/** - * Activity on our incoming socket. Read data from the - * incoming connection. - * - * @param cls the `struct GNUNET_NAT_Test` - */ -static void -do_udp_read (void *cls) -{ - struct GNUNET_NAT_Test *tst = cls; - uint16_t data; - const struct GNUNET_SCHEDULER_TaskContext *tc; - - tc = GNUNET_SCHEDULER_get_task_context (); - tst->ltask = - GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL, - tst->lsock, - &do_udp_read, - tst); - if ((NULL != tc->write_ready) && - (GNUNET_NETWORK_fdset_isset (tc->read_ready, - tst->lsock)) && - (sizeof (data) == - GNUNET_NETWORK_socket_recv (tst->lsock, - &data, - sizeof (data)))) - { - if (data == tst->data) - tst->report (tst->report_cls, - GNUNET_NAT_ERROR_SUCCESS); - else - LOG (GNUNET_ERROR_TYPE_DEBUG, - "Received data mismatches expected value\n"); - } - else - LOG (GNUNET_ERROR_TYPE_DEBUG, - "Failed to receive data from inbound connection\n"); -} - - -/** - * Activity on our incoming socket. Read data from the - * incoming connection. - * - * @param cls the `struct NatActivity` - */ -static void -do_read (void *cls) -{ - struct NatActivity *na = cls; - struct GNUNET_NAT_Test *tst; - uint16_t data; - const struct GNUNET_SCHEDULER_TaskContext *tc; - - tc = GNUNET_SCHEDULER_get_task_context (); - na->rtask = NULL; - tst = na->h; - GNUNET_CONTAINER_DLL_remove (tst->na_head, - tst->na_tail, - na); - if ((NULL != tc->write_ready) && - (GNUNET_NETWORK_fdset_isset (tc->read_ready, - na->sock)) && - (sizeof (data) == - GNUNET_NETWORK_socket_recv (na->sock, - &data, - sizeof (data)))) - { - if (data == tst->data) - tst->report (tst->report_cls, - GNUNET_NAT_ERROR_SUCCESS); - else - LOG (GNUNET_ERROR_TYPE_DEBUG, - "Received data does not match expected value\n"); - } - else - LOG (GNUNET_ERROR_TYPE_DEBUG, - "Failed to receive data from inbound connection\n"); - GNUNET_NETWORK_socket_close (na->sock); - GNUNET_free (na); -} - - -/** - * Activity on our listen socket. Accept the - * incoming connection. - * - * @param cls the `struct GNUNET_NAT_Test` - */ -static void -do_accept (void *cls) -{ - struct GNUNET_NAT_Test *tst = cls; - struct GNUNET_NETWORK_Handle *s; - struct NatActivity *wl; - - tst->ltask = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL, - tst->lsock, - &do_accept, - tst); - s = GNUNET_NETWORK_socket_accept (tst->lsock, - NULL, - NULL); - if (NULL == s) - { - GNUNET_log_strerror (GNUNET_ERROR_TYPE_INFO, - "accept"); - return; /* odd error */ - } - LOG (GNUNET_ERROR_TYPE_DEBUG, - "Got an inbound connection, waiting for data\n"); - wl = GNUNET_new (struct NatActivity); - wl->sock = s; - wl->h = tst; - wl->rtask = - GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL, - wl->sock, - &do_read, - wl); - GNUNET_CONTAINER_DLL_insert (tst->na_head, - tst->na_tail, - wl); -} - - -/** - * We got disconnected from the NAT server. Stop - * waiting for a reply. - * - * @param cls the `struct ClientActivity` - * @param error error code - */ -static void -mq_error_handler (void *cls, - enum GNUNET_MQ_Error error) -{ - struct ClientActivity *ca = cls; - struct GNUNET_NAT_Test *tst = ca->h; - - GNUNET_CONTAINER_DLL_remove (tst->ca_head, - tst->ca_tail, - ca); - GNUNET_MQ_destroy (ca->mq); - GNUNET_free (ca); -} - - -/** - * Address-callback, used to send message to gnunet-nat-server. - * - * @param cls closure - * @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 length of the @a addr - */ -static void -addr_cb (void *cls, - int add_remove, - const struct sockaddr *addr, - socklen_t addrlen) -{ - struct GNUNET_NAT_Test *h = cls; - struct ClientActivity *ca; - struct GNUNET_MQ_Envelope *env; - struct GNUNET_NAT_TestMessage *msg; - const struct sockaddr_in *sa; - - if (GNUNET_YES != add_remove) - return; - if (addrlen != sizeof (struct sockaddr_in)) - { - LOG (GNUNET_ERROR_TYPE_DEBUG, - "NAT test ignores IPv6 address `%s' returned from NAT library\n", - GNUNET_a2s (addr, - addrlen)); - return; /* ignore IPv6 here */ - } - LOG (GNUNET_ERROR_TYPE_INFO, - "Asking gnunet-nat-server to connect to `%s'\n", - GNUNET_a2s (addr, - addrlen)); - - ca = GNUNET_new (struct ClientActivity); - ca->h = h; - ca->mq = GNUNET_CLIENT_connecT (h->cfg, - "gnunet-nat-server", - NULL, - &mq_error_handler, - ca); - if (NULL == ca->mq) - { - GNUNET_free (ca); - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - _("Failed to connect to `gnunet-nat-server'\n")); - return; - } - GNUNET_CONTAINER_DLL_insert (h->ca_head, - h->ca_tail, - ca); - sa = (const struct sockaddr_in *) addr; - env = GNUNET_MQ_msg (msg, - GNUNET_MESSAGE_TYPE_NAT_TEST); - msg->dst_ipv4 = sa->sin_addr.s_addr; - msg->dport = sa->sin_port; - msg->data = h->data; - msg->is_tcp = htonl ((uint32_t) h->is_tcp); - GNUNET_MQ_send (ca->mq, - env); -} - - -/** - * Timeout task for a nat test. - * Calls the report-callback with a timeout return value - * - * Destroys the nat handle after the callback has been processed. - * - * @param cls handle to the timed out NAT test - */ -static void -do_timeout (void *cls) -{ - struct GNUNET_NAT_Test *nh = cls; - - nh->ttask = NULL; - nh->report (nh->report_cls, - (GNUNET_NAT_ERROR_SUCCESS == nh->status) - ? GNUNET_NAT_ERROR_TIMEOUT - : nh->status); -} - - -/** - * Start testing if NAT traversal works using the - * given configuration (IPv4-only). - * - * ALL failures are reported directly to the report callback - * - * @param cfg configuration for the NAT traversal - * @param is_tcp #GNUNET_YES to test TCP, #GNUNET_NO to test UDP - * @param bnd_port port to bind to, 0 for connection reversal - * @param adv_port externally advertised port to use - * @param timeout delay after which the test should be aborted - * @param report function to call with the result of the test - * @param report_cls closure for @a report - * @return handle to cancel NAT test or NULL. The error is always indicated via the report callback - */ -struct GNUNET_NAT_Test * -GNUNET_NAT_test_start (const struct GNUNET_CONFIGURATION_Handle *cfg, - int is_tcp, - uint16_t bnd_port, - uint16_t adv_port, - struct GNUNET_TIME_Relative timeout, - GNUNET_NAT_TestCallback report, - void *report_cls) -{ - struct GNUNET_NAT_Test *nh; - struct sockaddr_in sa; - const struct sockaddr *addrs[] = { - (const struct sockaddr *) &sa - }; - const socklen_t addrlens[] = { - sizeof (sa) - }; - - memset (&sa, 0, sizeof (sa)); - sa.sin_family = AF_INET; - sa.sin_port = htons (bnd_port); -#if HAVE_SOCKADDR_IN_SIN_LEN - sa.sin_len = sizeof (sa); -#endif - - nh = GNUNET_new (struct GNUNET_NAT_Test); - nh->cfg = cfg; - nh->is_tcp = is_tcp; - nh->data = bnd_port; - nh->adv_port = adv_port; - nh->report = report; - nh->report_cls = report_cls; - nh->status = GNUNET_NAT_ERROR_SUCCESS; - if (0 == bnd_port) - { - nh->nat - = GNUNET_NAT_register (cfg, - is_tcp, - 0, - 0, - NULL, - NULL, - &addr_cb, - &reversal_cb, - nh, - NULL); - } - else - { - nh->lsock = - GNUNET_NETWORK_socket_create (AF_INET, - (is_tcp == - GNUNET_YES) ? SOCK_STREAM : SOCK_DGRAM, - 0); - if ((nh->lsock == NULL) || - (GNUNET_OK != - GNUNET_NETWORK_socket_bind (nh->lsock, - (const struct sockaddr *) &sa, - sizeof (sa)))) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - _("Failed to create listen socket bound to `%s' for NAT test: %s\n"), - GNUNET_a2s ((const struct sockaddr *) &sa, - sizeof (sa)), - STRERROR (errno)); - if (NULL != nh->lsock) - { - GNUNET_NETWORK_socket_close (nh->lsock); - nh->lsock = NULL; - } - nh->status = GNUNET_NAT_ERROR_INTERNAL_NETWORK_ERROR; - nh->ttask = GNUNET_SCHEDULER_add_now (&do_timeout, - nh); - return nh; - } - if (GNUNET_YES == is_tcp) - { - GNUNET_break (GNUNET_OK == - GNUNET_NETWORK_socket_listen (nh->lsock, - 5)); - nh->ltask = - GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL, - nh->lsock, - &do_accept, - nh); - } - else - { - nh->ltask = - GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL, - nh->lsock, - &do_udp_read, - nh); - } - LOG (GNUNET_ERROR_TYPE_INFO, - "NAT test listens on port %u (%s)\n", - bnd_port, - (GNUNET_YES == is_tcp) ? "tcp" : "udp"); - nh->nat = GNUNET_NAT_register (cfg, - is_tcp, - adv_port, - 1, - addrs, - addrlens, - &addr_cb, - NULL, - nh, - NULL); - if (NULL == nh->nat) - { - LOG (GNUNET_ERROR_TYPE_INFO, - _("NAT test failed to start NAT library\n")); - if (NULL != nh->ltask) - { - GNUNET_SCHEDULER_cancel (nh->ltask); - nh->ltask = NULL; - } - if (NULL != nh->lsock) - { - GNUNET_NETWORK_socket_close (nh->lsock); - nh->lsock = NULL; - } - nh->status = GNUNET_NAT_ERROR_NAT_REGISTER_FAILED; - nh->ttask = GNUNET_SCHEDULER_add_now (&do_timeout, - nh); - return nh; - } - } - nh->ttask = GNUNET_SCHEDULER_add_delayed (timeout, - &do_timeout, - nh); - return nh; -} - - -/** - * Stop an active NAT test. - * - * @param tst test to stop. - */ -void -GNUNET_NAT_test_stop (struct GNUNET_NAT_Test *tst) -{ - struct NatActivity *pos; - struct ClientActivity *cpos; - - LOG (GNUNET_ERROR_TYPE_DEBUG, - "Stopping NAT test\n"); - while (NULL != (cpos = tst->ca_head)) - { - GNUNET_CONTAINER_DLL_remove (tst->ca_head, - tst->ca_tail, - cpos); - GNUNET_MQ_destroy (cpos->mq); - GNUNET_free (cpos); - } - while (NULL != (pos = tst->na_head)) - { - GNUNET_CONTAINER_DLL_remove (tst->na_head, - tst->na_tail, - pos); - GNUNET_SCHEDULER_cancel (pos->rtask); - GNUNET_NETWORK_socket_close (pos->sock); - GNUNET_free (pos); - } - if (NULL != tst->ttask) - { - GNUNET_SCHEDULER_cancel (tst->ttask); - tst->ttask = NULL; - } - if (NULL != tst->ltask) - { - GNUNET_SCHEDULER_cancel (tst->ltask); - tst->ltask = NULL; - } - if (NULL != tst->lsock) - { - GNUNET_NETWORK_socket_close (tst->lsock); - tst->lsock = NULL; - } - if (NULL != tst->nat) - { - GNUNET_NAT_unregister (tst->nat); - tst->nat = NULL; - } - GNUNET_free (tst); -} - -/* end of nat_test.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 \ -- cgit v1.2.3