summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--configure.ac2
-rw-r--r--doc/man/Makefile.am1
-rw-r--r--doc/man/gnunet-nat-auto.159
-rw-r--r--doc/man/gnunet-nat.113
-rw-r--r--po/POTFILES.in8
-rw-r--r--src/Makefile.am1
-rw-r--r--src/include/Makefile.am1
-rw-r--r--src/include/gnunet_nat_auto_service.h224
-rw-r--r--src/include/gnunet_nat_service.h407
-rw-r--r--src/include/gnunet_protocols.h2
-rw-r--r--src/nat-auto/.gitignore3
-rw-r--r--src/nat-auto/Makefile.am58
-rw-r--r--src/nat-auto/gnunet-nat-auto.c428
-rw-r--r--src/nat-auto/gnunet-nat-server.c (renamed from src/nat/gnunet-nat-server.c)2
-rw-r--r--src/nat-auto/gnunet-service-nat-auto.c481
-rw-r--r--src/nat-auto/nat-auto.conf.in15
-rw-r--r--src/nat-auto/nat-auto.h110
-rw-r--r--src/nat-auto/nat_auto_api.c (renamed from src/nat/nat_api_auto.c)8
-rw-r--r--src/nat-auto/nat_auto_api_test.c (renamed from src/nat/nat_api_test.c)4
-rw-r--r--src/nat/Makefile.am9
-rw-r--r--src/nat/gnunet-nat.c279
-rw-r--r--src/nat/gnunet-service-nat.c355
-rw-r--r--src/nat/nat.conf.in5
-rw-r--r--src/nat/nat.h39
24 files changed, 1527 insertions, 987 deletions
diff --git a/configure.ac b/configure.ac
index c41bcc4b5..dade7d211 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1596,6 +1596,8 @@ src/namestore/Makefile
src/namestore/namestore.conf
src/nat/Makefile
src/nat/nat.conf
+src/nat-auto/Makefile
+src/nat-auto/nat-auto.conf
src/nse/Makefile
src/nse/nse.conf
src/peerinfo/Makefile
diff --git a/doc/man/Makefile.am b/doc/man/Makefile.am
index ff1e462b7..c40363b59 100644
--- a/doc/man/Makefile.am
+++ b/doc/man/Makefile.am
@@ -25,6 +25,7 @@ man_MANS = \
gnunet-namestore.1 \
gnunet-namestore-fcfsd.1 \
gnunet-nat.1 \
+ gnunet-nat-auto.1 \
gnunet-nat-server.1 \
gnunet-peerinfo.1 \
gnunet-publish.1 \
diff --git a/doc/man/gnunet-nat-auto.1 b/doc/man/gnunet-nat-auto.1
new file mode 100644
index 000000000..310f14d43
--- /dev/null
+++ b/doc/man/gnunet-nat-auto.1
@@ -0,0 +1,59 @@
+.TH GNUNET\-NAT\-AUTO 1 "6 Jan 2017" "GNUnet"
+
+.SH NAME
+gnunet\-nat\-auto \- autoconfigure and test NAT traversal
+
+.SH SYNOPSIS
+.B gnunet\-nat\-auto
+.RI [ options ]
+.br
+
+.SH DESCRIPTION
+
+This tool allows testing various NAT traversal functions, as well
+as attempting auto\-configuration.
+
+.SH OPTIONS
+.B
+.IP "\-a, \-\-auto"
+Attempt auto\-configuration for NAT traversal.
+
+.B
+.IP "\-b ADDRESS, \-\-bind=ADDRESS"
+Assume that the service is (locally) bound to ADDRESS.
+
+.B
+.IP "\-c FILENAME, \-\-config=FILENAME"
+Use the configuration file FILENAME.
+
+.B
+.IP "\-e ADDRESS, \-\-external=ADDRESS"
+Assume that ADDRESS is the globally visible address of the peer.
+
+.IP "\-t, \-\-tcp"
+Use TCP.
+
+.B
+.IP "\-u, \-\-udp"
+Use UDP.
+
+.B
+.IP "\-w, \-\-write"
+Write configuration to configuration file, useful in combination with autoconfiguration (\-a).
+
+.SH EXAMPLES
+.PP
+
+\fBAutomatic configuration:\fR
+
+Probe and write result to configuration:
+
+ # gnunet\-nat\-auto \-aw
+
+
+.SH BUGS
+Report bugs by using Mantis <https://gnunet.org/bugs/> or by sending electronic mail to <gnunet\-developers@gnu.org>
+
+.SH SEE ALSO
+gnunet\-transport(1) gnunet\-nat(1)
+
diff --git a/doc/man/gnunet-nat.1 b/doc/man/gnunet-nat.1
index 01e0267a4..a8a82883b 100644
--- a/doc/man/gnunet-nat.1
+++ b/doc/man/gnunet-nat.1
@@ -14,9 +14,6 @@ This tool allows testing various NAT traversal functions, as well
as attempting auto\-configuration.
.SH OPTIONS
-.B
-.IP "\-a, \-\-auto"
-Attempt auto\-configuration for NAT traversal.
.B
.IP "\-b ADDRESS, \-\-bind=ADDRESS"
@@ -55,10 +52,6 @@ Use TCP.
Use UDP.
.B
-.IP "\-w, \-\-write"
-Write configuration to configuration file, useful in combination with autoconfiguration (\-a).
-
-.B
.IP "\-W, \-\-watch"
Watch for connection reversal requests.
@@ -103,12 +96,6 @@ XXX:
# gnunet-nat FIXME -s
-\fBAutomatic configuration:\fR
-
-Probe and write result to configuration:
-
- # gnunet-nat -aw
-
.SH BUGS
Report bugs by using Mantis <https://gnunet.org/bugs/> or by sending electronic mail to <gnunet\-developers@gnu.org>
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 56af200ff..e1c3ec697 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -237,19 +237,23 @@ src/namestore/plugin_namestore_flat.c
src/namestore/plugin_namestore_postgres.c
src/namestore/plugin_namestore_sqlite.c
src/namestore/plugin_rest_namestore.c
+src/nat-auto/gnunet-nat-auto.c
+src/nat-auto/gnunet-nat-server.c
+src/nat-auto/gnunet-service-nat-auto.c
+src/nat-auto/nat_auto_api.c
+src/nat-auto/nat_auto_api_test.c
src/nat/gnunet-helper-nat-client.c
src/nat/gnunet-helper-nat-client-windows.c
src/nat/gnunet-helper-nat-server.c
src/nat/gnunet-helper-nat-server-windows.c
src/nat/gnunet-nat.c
-src/nat/gnunet-nat-server.c
src/nat/gnunet-service-nat.c
+src/nat/gnunet-service-nat_externalip.c
src/nat/gnunet-service-nat_helper.c
src/nat/gnunet-service-nat_mini.c
src/nat/gnunet-service-nat_stun.c
src/nat/nat_api.c
src/nat/nat_api_stun.c
-src/nat/nat_api_test.c
src/nat/nat_auto.c
src/nat/nat.c
src/nat/nat_mini.c
diff --git a/src/Makefile.am b/src/Makefile.am
index 6925788d5..d04cba9dd 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -85,6 +85,7 @@ SUBDIRS = \
template \
ats \
nat \
+ nat-auto \
fragmentation \
transport \
ats-tool \
diff --git a/src/include/Makefile.am b/src/include/Makefile.am
index f27fd6e36..639d3bfd7 100644
--- a/src/include/Makefile.am
+++ b/src/include/Makefile.am
@@ -79,6 +79,7 @@ gnunetinclude_HEADERS = \
gnunet_namestore_plugin.h \
gnunet_namestore_service.h \
gnunet_nat_lib.h \
+ gnunet_nat_auto_service.h \
gnunet_nat_service.h \
gnunet_nc_lib.h \
gnunet_network_lib.h \
diff --git a/src/include/gnunet_nat_auto_service.h b/src/include/gnunet_nat_auto_service.h
new file mode 100644
index 000000000..90115ff8c
--- /dev/null
+++ b/src/include/gnunet_nat_auto_service.h
@@ -0,0 +1,224 @@
+/*
+ This file is part of GNUnet.
+ Copyright (C) 2007-2017 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.
+*/
+
+/**
+ * @author Christian Grothoff
+ * @author Milan Bouchet-Valat
+ *
+ * @file
+ * Service for testing and autoconfiguration of
+ * NAT traversal functionality
+ *
+ * @defgroup nat NAT testing library
+ *
+ * @{
+ */
+
+#ifndef GNUNET_NAT_AUTO_SERVICE_H
+#define GNUNET_NAT_AUTO_SERVICE_H
+
+#include "gnunet_util_lib.h"
+
+
+/**
+ * Handle to a NAT test.
+ */
+struct GNUNET_NAT_Test;
+
+
+/**
+ * Function called to report success or failure for
+ * NAT configuration test.
+ *
+ * @param cls closure
+ * @param result #GNUNET_NAT_ERROR_SUCCESS on success, otherwise the specific error code
+ */
+typedef void
+(*GNUNET_NAT_TestCallback) (void *cls,
+ enum GNUNET_NAT_StatusCode result);
+
+
+/**
+ * Handle an incoming STUN message. This function is useful as
+ * some GNUnet service may be listening on a UDP port and might
+ * thus receive STUN messages while trying to receive other data.
+ * In this case, this function can be used to process replies
+ * to STUN requests.
+ *
+ * The function does some basic sanity checks on packet size and
+ * content, try to extract a bit of information.
+ *
+ * At the moment this only processes BIND requests, and returns the
+ * externally visible address of the request to the rest of the
+ * NAT logic.
+ *
+ * @param nh handle to the NAT service
+ * @param sender_addr address from which we got @a data
+ * @param sender_addr_len number of bytes in @a sender_addr
+ * @param data the packet
+ * @param data_size number of bytes in @a data
+ * @return #GNUNET_OK on success
+ * #GNUNET_NO if the packet is not a STUN packet
+ * #GNUNET_SYSERR on internal error handling the packet
+ */
+int
+GNUNET_NAT_stun_handle_packet (struct GNUNET_NAT_Handle *nh,
+ const struct sockaddr *sender_addr,
+ size_t sender_addr_len,
+ const void *data,
+ size_t data_size);
+
+
+/**
+ * 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;
+
+
+/**
+ * Make Generic STUN request. Sends a generic stun request to the
+ * server specified using the specified socket. If we do this,
+ * we need to watch for possible responses and call
+ * #GNUNET_NAT_stun_handle_packet() on incoming packets.
+ *
+ * @param server the address of the stun server
+ * @param port port of the stun server, in host byte order
+ * @param sock the socket used to send the request, must be a
+ * UDP socket
+ * @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_TestCallback cb,
+ void *cb_cls);
+
+
+/**
+ * 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);
+
+
+/**
+ * Start testing if NAT traversal works using the given configuration
+ * (IPv4-only). The transport adapters should be down while using
+ * this function.
+ *
+ * @param cfg configuration for the NAT traversal
+ * @param proto protocol to test, i.e. IPPROTO_TCP or IPPROTO_UDP
+ * @param bind_ip IPv4 address to bind to
+ * @param bnd_port port to bind to, 0 to test connection reversal
+ * @param extern_ip IPv4 address to externally advertise
+ * @param extern_port externally advertised port to use
+ * @param report function to call with the result of the test
+ * @param report_cls closure for @a report
+ * @return handle to cancel NAT test
+ */
+struct GNUNET_NAT_Test *
+GNUNET_NAT_test_start (const struct GNUNET_CONFIGURATION_Handle *cfg,
+ uint8_t proto,
+ struct in_addr bind_ip,
+ uint16_t bnd_port,
+ struct in_addr extern_ip,
+ uint16_t extern_port,
+ GNUNET_NAT_TestCallback report,
+ void *report_cls);
+
+
+/**
+ * Stop an active NAT test.
+ *
+ * @param tst test to stop.
+ */
+void
+GNUNET_NAT_test_stop (struct GNUNET_NAT_Test *tst);
+
+
+/**
+ * Handle to auto-configuration in progress.
+ */
+struct GNUNET_NAT_AutoHandle;
+
+
+/**
+ * Converts `enum GNUNET_NAT_StatusCode` to string
+ *
+ * @param err error code to resolve to a string
+ * @return point to a static string containing the error code
+ */
+const char *
+GNUNET_NAT_status2string (enum GNUNET_NAT_StatusCode err);
+
+
+/**
+ * Function called with the result from the autoconfiguration.
+ *
+ * @param cls closure
+ * @param diff minimal suggested changes to the original configuration
+ * to make it work (as best as we can)
+ * @param result #GNUNET_NAT_ERROR_SUCCESS on success, otherwise the specific error code
+ * @param type what the situation of the NAT
+ */
+typedef void
+(*GNUNET_NAT_AutoResultCallback)(void *cls,
+ const struct GNUNET_CONFIGURATION_Handle *diff,
+ enum GNUNET_NAT_StatusCode result,
+ enum GNUNET_NAT_Type type);
+
+
+/**
+ * Start auto-configuration routine. The transport adapters should
+ * be stopped while 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);
+
+
+/**
+ * Abort autoconfiguration.
+ *
+ * @param ah handle for operation to abort
+ */
+void
+GNUNET_NAT_autoconfig_cancel (struct GNUNET_NAT_AutoHandle *ah);
+
+
+#endif
+
+/** @} */ /* end of group */
+
+/* end of gnunet_nat_auto_service.h */
diff --git a/src/include/gnunet_nat_service.h b/src/include/gnunet_nat_service.h
index 6b9650306..94f8a8555 100644
--- a/src/include/gnunet_nat_service.h
+++ b/src/include/gnunet_nat_service.h
@@ -1,6 +1,6 @@
/*
This file is part of GNUnet.
- Copyright (C) 2007-2016 GNUnet e.V.
+ Copyright (C) 2007-2017 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
@@ -137,132 +137,6 @@ enum GNUNET_NAT_AddressClass
/**
- * Signature of the callback passed to #GNUNET_NAT_register() for
- * a function to call whenever our set of 'valid' addresses changes.
- *
- * @param cls closure
- * @param add_remove #GNUNET_YES to add a new public IP address,
- * #GNUNET_NO to remove a previous (now invalid) one
- * @param ac address class the address belongs to
- * @param addr either the previous or the new public IP address
- * @param addrlen actual length of the @a addr
- */
-typedef void
-(*GNUNET_NAT_AddressCallback) (void *cls,
- int add_remove,
- enum GNUNET_NAT_AddressClass ac,
- const struct sockaddr *addr,
- socklen_t addrlen);
-
-
-/**
- * Signature of the callback passed to #GNUNET_NAT_register().
- * for a function to call whenever someone asks us to do connection
- * reversal.
- *
- * @param cls closure
- * @param remote_addr public IP address of the other peer
- * @param remote_addrlen actual length of the @a remote_addr
- */
-typedef void
-(*GNUNET_NAT_ReversalCallback) (void *cls,
- const struct sockaddr *remote_addr,
- socklen_t remote_addrlen);
-
-
-/**
- * Handle for active NAT registrations.
- */
-struct GNUNET_NAT_Handle;
-
-
-/**
- * Attempt to enable port redirection and detect public IP address
- * contacting UPnP or NAT-PMP routers on the local network. Use @a
- * 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. The NAT module should call the given @a
- * address_callback for any 'plausible' external address.
- *
- * @param cfg configuration to use
- * @param config_section name of the configuration section for optionsx
- * @param proto protocol this is about, IPPROTO_TCP or IPPROTO_UDP
- * @param num_addrs number of addresses in @a addrs
- * @param addrs list of local addresses packets should be redirected to
- * @param addrlens actual lengths of the addresses in @a addrs
- * @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,
- * NULL if connection reversal is not supported
- * @param callback_cls closure for callbacks
- * @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,
- const char *config_section,
- uint8_t proto,
- 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);
-
-
-/**
- * Test if the given address is (currently) a plausible IP address for
- * this peer. Mostly a convenience function so that clients do not
- * have to explicitly track all IPs that the #GNUNET_NAT_AddressCallback
- * has returned so far.
- *
- * @param nh 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 *nh,
- const void *addr,
- socklen_t addrlen);
-
-
-/**
- * We learned about a peer (possibly behind NAT) so run the
- * gnunet-nat-client to send dummy ICMP responses to cause
- * that peer to connect to us (connection reversal).
- *
- * @param nh handle (used for configuration)
- * @param local_sa our local address of the peer (IPv4-only)
- * @param remote_sa the remote address of the peer (IPv4-only)
- * @return #GNUNET_SYSERR on error,
- * #GNUNET_NO if connection reversal is unavailable,
- * #GNUNET_OK otherwise (presumably in progress)
- */
-int
-GNUNET_NAT_request_reversal (struct GNUNET_NAT_Handle *nh,
- const struct sockaddr_in *local_sa,
- const struct sockaddr_in *remote_sa);
-
-
-/**
- * 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 nh the handle to unregister
- */
-void
-GNUNET_NAT_unregister (struct GNUNET_NAT_Handle *nh);
-
-
-/**
- * Handle to a NAT test.
- */
-struct GNUNET_NAT_Test;
-
-
-/**
* Error Types for the NAT subsystem (which can then later be converted/resolved to a string)
*/
enum GNUNET_NAT_StatusCode
@@ -365,129 +239,6 @@ enum GNUNET_NAT_StatusCode
};
-/**
- * Function called to report success or failure for
- * NAT configuration test.
- *
- * @param cls closure
- * @param result #GNUNET_NAT_ERROR_SUCCESS on success, otherwise the specific error code
- */
-typedef void
-(*GNUNET_NAT_TestCallback) (void *cls,
- enum GNUNET_NAT_StatusCode result);
-
-
-/**
- * Handle an incoming STUN message. This function is useful as
- * some GNUnet service may be listening on a UDP port and might
- * thus receive STUN messages while trying to receive other data.
- * In this case, this function can be used to process replies
- * to STUN requests.
- *
- * The function does some basic sanity checks on packet size and
- * content, try to extract a bit of information.
- *
- * At the moment this only processes BIND requests, and returns the
- * externally visible address of the request to the rest of the
- * NAT logic.
- *
- * @param nh handle to the NAT service
- * @param sender_addr address from which we got @a data
- * @param sender_addr_len number of bytes in @a sender_addr
- * @param data the packet
- * @param data_size number of bytes in @a data
- * @return #GNUNET_OK on success
- * #GNUNET_NO if the packet is not a STUN packet
- * #GNUNET_SYSERR on internal error handling the packet
- */
-int
-GNUNET_NAT_stun_handle_packet (struct GNUNET_NAT_Handle *nh,
- const struct sockaddr *sender_addr,
- size_t sender_addr_len,
- const void *data,
- size_t data_size);
-
-
-/**
- * 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;
-
-
-/**
- * Make Generic STUN request. Sends a generic stun request to the
- * server specified using the specified socket. If we do this,
- * we need to watch for possible responses and call
- * #GNUNET_NAT_stun_handle_packet() on incoming packets.
- *
- * @param server the address of the stun server
- * @param port port of the stun server, in host byte order
- * @param sock the socket used to send the request, must be a
- * UDP socket
- * @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_TestCallback cb,
- void *cb_cls);
-
-
-/**
- * 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);
-
-
-/**
- * Start testing if NAT traversal works using the given configuration
- * (IPv4-only). The transport adapters should be down while using
- * this function.
- *
- * @param cfg configuration for the NAT traversal
- * @param proto protocol to test, i.e. IPPROTO_TCP or IPPROTO_UDP
- * @param bind_ip IPv4 address to bind to
- * @param bnd_port port to bind to, 0 to test connection reversal
- * @param extern_ip IPv4 address to externally advertise
- * @param extern_port externally advertised port to use
- * @param report function to call with the result of the test
- * @param report_cls closure for @a report
- * @return handle to cancel NAT test
- */
-struct GNUNET_NAT_Test *
-GNUNET_NAT_test_start (const struct GNUNET_CONFIGURATION_Handle *cfg,
- uint8_t proto,
- struct in_addr bind_ip,
- uint16_t bnd_port,
- struct in_addr extern_ip,
- uint16_t extern_port,
- GNUNET_NAT_TestCallback report,
- void *report_cls);
-
-
-/**
- * Stop an active NAT test.
- *
- * @param tst test to stop.
- */
-void
-GNUNET_NAT_test_stop (struct GNUNET_NAT_Test *tst);
-
-
-/**
- * Handle to auto-configuration in progress.
- */
-struct GNUNET_NAT_AutoHandle;
-
/**
* What the situation of the NAT connectivity
@@ -522,54 +273,156 @@ enum GNUNET_NAT_Type
};
+
/**
- * Converts `enum GNUNET_NAT_StatusCode` to string
+ * Signature of the callback passed to #GNUNET_NAT_register() for
+ * a function to call whenever our set of 'valid' addresses changes.
*
- * @param err error code to resolve to a string
- * @return point to a static string containing the error code
+ * @param cls closure
+ * @param add_remove #GNUNET_YES to add a new public IP address,
+ * #GNUNET_NO to remove a previous (now invalid) one
+ * @param ac address class the address belongs to
+ * @param addr either the previous or the new public IP address
+ * @param addrlen actual length of the @a addr
*/
-const char *
-GNUNET_NAT_status2string (enum GNUNET_NAT_StatusCode err);
+typedef void
+(*GNUNET_NAT_AddressCallback) (void *cls,
+ int add_remove,
+ enum GNUNET_NAT_AddressClass ac,
+ const struct sockaddr *addr,
+ socklen_t addrlen);
/**
- * Function called with the result from the autoconfiguration.
+ * Signature of the callback passed to #GNUNET_NAT_register().
+ * for a function to call whenever someone asks us to do connection
+ * reversal.
*
* @param cls closure
- * @param diff minimal suggested changes to the original configuration
- * to make it work (as best as we can)
- * @param result #GNUNET_NAT_ERROR_SUCCESS on success, otherwise the specific error code
- * @param type what the situation of the NAT
+ * @param remote_addr public IP address of the other peer
+ * @param remote_addrlen actual length of the @a remote_addr
*/
typedef void
-(*GNUNET_NAT_AutoResultCallback)(void *cls,
- const struct GNUNET_CONFIGURATION_Handle *diff,
- enum GNUNET_NAT_StatusCode result,
- enum GNUNET_NAT_Type type);
+(*GNUNET_NAT_ReversalCallback) (void *cls,
+ const struct sockaddr *remote_addr,
+ socklen_t remote_addrlen);
+
+
+/**
+ * Handle for active NAT registrations.
+ */
+struct GNUNET_NAT_Handle;
/**
- * Start auto-configuration routine. The transport adapters should
- * be stopped while this function is called.
+ * Attempt to enable port redirection and detect public IP address
+ * contacting UPnP or NAT-PMP routers on the local network. Use @a
+ * 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. The NAT module should call the given @a
+ * address_callback for any 'plausible' external address.
*
- * @param cfg initial configuration
- * @param cb function to call with autoconfiguration result
- * @param cb_cls closure for @a cb
- * @return handle to cancel operation
+ * @param cfg configuration to use
+ * @param config_section name of the configuration section for options
+ * @param proto protocol this is about, IPPROTO_TCP or IPPROTO_UDP
+ * @param num_addrs number of addresses in @a addrs
+ * @param addrs list of local addresses packets should be redirected to
+ * @param addrlens actual lengths of the addresses in @a addrs
+ * @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,
+ * NULL if connection reversal is not supported
+ * @param callback_cls closure for callbacks
+ * @return NULL on error, otherwise handle that can be used to unregister
*/
-struct GNUNET_NAT_AutoHandle *
-GNUNET_NAT_autoconfig_start (const struct GNUNET_CONFIGURATION_Handle *cfg,
- GNUNET_NAT_AutoResultCallback cb,
- void *cb_cls);
+struct GNUNET_NAT_Handle *
+GNUNET_NAT_register (const struct GNUNET_CONFIGURATION_Handle *cfg,
+ const char *config_section,
+ uint8_t proto,
+ 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);
+
+
+/**
+ * Test if the given address is (currently) a plausible IP address for
+ * this peer. Mostly a convenience function so that clients do not
+ * have to explicitly track all IPs that the #GNUNET_NAT_AddressCallback
+ * has returned so far.
+ *
+ * @param nh 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 *nh,
+ const void *addr,
+ socklen_t addrlen);
/**
- * Abort autoconfiguration.
+ * We learned about a peer (possibly behind NAT) so run the
+ * gnunet-nat-client to send dummy ICMP responses to cause
+ * that peer to connect to us (connection reversal).
*
- * @param ah handle for operation to abort
+ * @param nh handle (used for configuration)
+ * @param local_sa our local address of the peer (IPv4-only)
+ * @param remote_sa the remote address of the peer (IPv4-only)
+ * @return #GNUNET_SYSERR on error,
+ * #GNUNET_NO if connection reversal is unavailable,
+ * #GNUNET_OK otherwise (presumably in progress)
+ */
+int
+GNUNET_NAT_request_reversal (struct GNUNET_NAT_Handle *nh,
+ const struct sockaddr_in *local_sa,
+ const struct sockaddr_in *remote_sa);
+
+
+/**
+ * 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 nh the handle to unregister
*/
void
-GNUNET_NAT_autoconfig_cancel (struct GNUNET_NAT_AutoHandle *ah);
+GNUNET_NAT_unregister (struct GNUNET_NAT_Handle *nh);
+
+
+/**
+ * Handle an incoming STUN message. This function is useful as
+ * some GNUnet service may be listening on a UDP port and might
+ * thus receive STUN messages while trying to receive other data.
+ * In this case, this function can be used to process replies
+ * to STUN requests.
+ *
+ * The function does some basic sanity checks on packet size and
+ * content, try to extract a bit of information.
+ *
+ * At the moment this only processes BIND requests, and returns the
+ * externally visible address of the request to the rest of the
+ * NAT logic.
+ *
+ * @param nh handle to the NAT service
+ * @param sender_addr address from which we got @a data
+ * @param sender_addr_len number of bytes in @a sender_addr
+ * @param data the packet
+ * @param data_size number of bytes in @a data
+ * @return #GNUNET_OK on success
+ * #GNUNET_NO if the packet is not a STUN packet
+ * #GNUNET_SYSERR on internal error handling the packet
+ */
+int
+GNUNET_NAT_stun_handle_packet (struct GNUNET_NAT_Handle *nh,
+ const struct sockaddr *sender_addr,
+ size_t sender_addr_len,
+ const void *data,
+ size_t data_size);
#endif
diff --git a/src/include/gnunet_protocols.h b/src/include/gnunet_protocols.h
index f9b7d3cb8..fdabfee18 100644
--- a/src/include/gnunet_protocols.h
+++ b/src/include/gnunet_protocols.h
@@ -2820,7 +2820,7 @@ extern "C"
/**
* Message to ask NAT service to request autoconfiguration.
*/
-#define GNUNET_MESSAGE_TYPE_NAT_REQUEST_AUTO_CFG 1067
+#define GNUNET_MESSAGE_TYPE_NAT_AUTO_REQUEST_CFG 1067
/**
* Message from NAT service with the autoconfiguration result.
diff --git a/src/nat-auto/.gitignore b/src/nat-auto/.gitignore
new file mode 100644
index 000000000..6ba53d72f
--- /dev/null
+++ b/src/nat-auto/.gitignore
@@ -0,0 +1,3 @@
+gnunet-service-nat-auto
+gnunet-nat-auto
+gnunet-nat-server
diff --git a/src/nat-auto/Makefile.am b/src/nat-auto/Makefile.am
new file mode 100644
index 000000000..dbe910306
--- /dev/null
+++ b/src/nat-auto/Makefile.am
@@ -0,0 +1,58 @@
+# This Makefile.am is in the public domain
+AM_CPPFLAGS = -I$(top_srcdir)/src/include
+
+libexecdir= $(pkglibdir)/libexec/
+
+pkgcfgdir= $(pkgdatadir)/config.d/
+
+pkgcfg_DATA = \
+ nat-auto.conf
+
+bin_PROGRAMS = \
+ gnunet-nat-auto \
+ gnunet-nat-server
+
+libexec_PROGRAMS = \
+ gnunet-service-nat-auto
+
+gnunet_nat_server_SOURCES = \
+ gnunet-nat-server.c nat-auto.h
+gnunet_nat_server_LDADD = \
+ $(top_builddir)/src/nat/libgnunetnat.la \
+ $(top_builddir)/src/util/libgnunetutil.la
+
+gnunet_nat_auto_SOURCES = \
+ gnunet-nat-auto.c nat-auto.h
+gnunet_nat_auto_LDADD = \
+ libgnunetnatauto.la \
+ $(top_builddir)/src/util/libgnunetutil.la
+
+
+if USE_COVERAGE
+ AM_CFLAGS = -fprofile-arcs -ftest-coverage
+endif
+
+lib_LTLIBRARIES = \
+ libgnunetnatauto.la
+
+libgnunetnatauto_la_SOURCES = \
+ nat_auto_api.c \
+ nat_auto_api_test.c
+libgnunetnatauto_la_LIBADD = \
+ $(top_builddir)/src/nat/libgnunetnatnew.la \
+ $(top_builddir)/src/util/libgnunetutil.la \
+ $(GN_LIBINTL) @EXT_LIBS@
+libgnunetnatauto_la_LDFLAGS = \
+ $(GN_LIB_LDFLAGS) $(WINFLAGS) \
+ -version-info 0:0:0
+
+gnunet_service_nat_auto_SOURCES = \
+ gnunet-service-nat-auto.c
+gnunet_service_nat_auto_LDADD = \
+ $(top_builddir)/src/util/libgnunetutil.la \
+ $(top_builddir)/src/statistics/libgnunetstatistics.la \
+ $(top_builddir)/src/nat/libgnunetnatnew.la \
+ $(LIBGCRYPT_LIBS) \
+ -lgcrypt \
+ $(GN_LIBINTL)
+
diff --git a/src/nat-auto/gnunet-nat-auto.c b/src/nat-auto/gnunet-nat-auto.c
new file mode 100644
index 000000000..3b9a5fa94
--- /dev/null
+++ b/src/nat-auto/gnunet-nat-auto.c
@@ -0,0 +1,428 @@
+/*
+ This file is part of GNUnet.
+ Copyright (C) 2015, 2016, 2017 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 src/nat/gnunet-nat-auto.c
+ * @brief Command-line tool for testing and autoconfiguration of NAT traversal
+ * @author Christian Grothoff
+ * @author Bruno Cabral
+ */
+#include "platform.h"
+#include "gnunet_util_lib.h"
+#include "gnunet_nat_service.h"
+#include "gnunet_nat_auto_service.h"
+
+/**
+ * Value to return from #main().
+ */
+static int global_ret;
+
+/**
+ * Handle to ongoing autoconfiguration.
+ */
+static struct GNUNET_NAT_AutoHandle *ah;
+
+/**
+ * If we do auto-configuration, should we write the result
+ * to a file?
+ */
+static int write_cfg;
+
+/**
+ * Configuration filename.
+ */
+static const char *cfg_file;
+
+/**
+ * Original configuration.
+ */
+static const struct GNUNET_CONFIGURATION_Handle *cfg;
+
+/**
+ * Address we are bound to (in test), or should bind to
+ * (if #do_stun is set).
+ */
+static char *bind_addr;
+
+/**
+ * External IP address and port to use for the test.
+ * If not set, use #bind_addr.
+ */
+static char *extern_addr;
+
+/**
+ * Should we run autoconfiguration?
+ */
+static unsigned int do_auto;
+
+/**
+ * Handle to a NAT test operation.
+ */
+static struct GNUNET_NAT_Test *nt;
+
+/**
+ * Flag set to 1 if we use IPPROTO_UDP.
+ */
+static int use_udp;
+
+/**
+ * Flag set to 1 if we use IPPROTO_TCP.
+ */
+static int use_tcp;
+
+/**
+ * Protocol to use.
+ */
+static uint8_t proto;
+
+/**
+ * Test if all activities have finished, and if so,
+ * terminate.
+ */
+static void
+test_finished ()
+{
+ if (NULL != ah)
+ return;
+ if (NULL != nt)
+ return;
+ GNUNET_SCHEDULER_shutdown ();
+}
+
+
+/**
+ * Function to iterate over sugested changes options
+ *
+ * @param cls closure
+ * @param section name of the section
+ * @param option name of the option
+ * @param value value of the option
+ */
+static void
+auto_conf_iter (void *cls,
+ const char *section,
+ const char *option,
+ const char *value)
+{
+ struct GNUNET_CONFIGURATION_Handle *new_cfg = cls;
+
+ PRINTF ("%s: %s\n",
+ option,
+ value);
+ if (NULL != new_cfg)
+ GNUNET_CONFIGURATION_set_value_string (new_cfg,
+ section,
+ option,
+ value);
+}
+
+
+/**
+ * Function called with the result from the autoconfiguration.
+ *
+ * @param cls closure
+ * @param diff minimal suggested changes to the original configuration
+ * to make it work (as best as we can)
+ * @param result #GNUNET_NAT_ERROR_SUCCESS on success, otherwise the specific error code
+ * @param type what the situation of the NAT
+ */
+static void
+auto_config_cb (void *cls,
+ const struct GNUNET_CONFIGURATION_Handle *diff,
+ enum GNUNET_NAT_StatusCode result,
+ enum GNUNET_NAT_Type type)
+{
+ const char *nat_type;
+ char unknown_type[64];
+ struct GNUNET_CONFIGURATION_Handle *new_cfg;
+
+ ah = NULL;
+ switch (type)
+ {
+ case GNUNET_NAT_TYPE_NO_NAT:
+ nat_type = "NO NAT";
+ break;
+ case GNUNET_NAT_TYPE_UNREACHABLE_NAT:
+ nat_type = "NAT but we can traverse";
+ break;
+ case GNUNET_NAT_TYPE_STUN_PUNCHED_NAT:
+ nat_type = "NAT but STUN is able to identify the correct information";
+ break;
+ case GNUNET_NAT_TYPE_UPNP_NAT:
+ nat_type = "NAT but UPNP opened the ports";
+ break;
+ default:
+ SPRINTF (unknown_type,
+ "NAT unknown, type %u",
+ type);
+ nat_type = unknown_type;
+ break;
+ }
+
+ GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
+ "NAT status: %s/%s\n",
+ GNUNET_NAT_status2string (result),
+ nat_type);
+
+ /* Shortcut: if there are no changes suggested, bail out early. */
+ if (GNUNET_NO ==
+ GNUNET_CONFIGURATION_is_dirty (diff))
+ {
+ test_finished ();
+ return;
+ }
+
+ /* Apply diff to original configuration and show changes
+ to the user */
+ new_cfg = write_cfg ? GNUNET_CONFIGURATION_dup (cfg) : NULL;
+
+ if (NULL != diff)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
+ _("Suggested configuration changes:\n"));
+ GNUNET_CONFIGURATION_iterate_section_values (diff,
+ "nat",
+ &auto_conf_iter,
+ new_cfg);
+ }
+
+ /* If desired, write configuration to file; we write only the
+ changes to the defaults to keep things compact. */
+ if ( (write_cfg) &&
+ (NULL != diff) )
+ {
+ struct GNUNET_CONFIGURATION_Handle *def_cfg;
+
+ GNUNET_CONFIGURATION_set_value_string (new_cfg,
+ "ARM",
+ "CONFIG",
+ NULL);
+ def_cfg = GNUNET_CONFIGURATION_create ();
+ GNUNET_break (GNUNET_OK ==
+ GNUNET_CONFIGURATION_load (def_cfg,
+ NULL));
+ if (GNUNET_OK !=
+ GNUNET_CONFIGURATION_write_diffs (def_cfg,
+ new_cfg,
+ cfg_file))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
+ _("Failed to write configuration to `%s'\n"),
+ cfg_file);
+ global_ret = 1;
+ }
+ else
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
+ _("Wrote updated configuration to `%s'\n"),
+ cfg_file);
+ }
+ GNUNET_CONFIGURATION_destroy (def_cfg);
+ }
+
+ if (NULL != new_cfg)
+ GNUNET_CONFIGURATION_destroy (new_cfg);
+ test_finished ();
+}
+
+
+/**
+ * Function called to report success or failure for
+ * NAT configuration test.
+ *
+ * @param cls closure
+ * @param result #GNUNET_NAT_ERROR_SUCCESS on success, otherwise the specific error code
+ */
+static void
+test_report_cb (void *cls,
+ enum GNUNET_NAT_StatusCode result)
+{
+ nt = NULL;
+ PRINTF ("NAT test result: %s\n",
+ GNUNET_NAT_status2string (result));
+ test_finished ();
+}
+
+
+/**
+ * Task run on shutdown.
+ *
+ * @param cls NULL
+ */
+static void
+do_shutdown (void *cls)
+{
+ if (NULL != ah)
+ {
+ GNUNET_NAT_autoconfig_cancel (ah);
+ ah = NULL;
+ }
+ if (NULL != nt)
+ {
+ GNUNET_NAT_test_stop (nt);
+ nt = NULL;
+ }
+}
+
+
+/**
+ * Main function that will be run.
+ *
+ * @param cls closure
+ * @param args remaining command-line arguments
+ * @param cfgfile name of the configuration file used (for saving, can be NULL!)
+ * @param c configuration
+ */
+static void
+run (void *cls,
+ char *const *args,
+ const char *cfgfile,
+ const struct GNUNET_CONFIGURATION_Handle *c)
+{
+ struct sockaddr_in bind_sa;
+ struct sockaddr_in extern_sa;
+
+ cfg_file = cfgfile;
+ cfg = c;
+
+ GNUNET_SCHEDULER_add_shutdown (&do_shutdown,
+ NULL);
+
+ if (do_auto)
+ {
+ ah = GNUNET_NAT_autoconfig_start (c,
+ &auto_config_cb,
+ NULL);
+ }
+
+ if (use_tcp && use_udp)
+ {
+ if (do_auto)
+ return;
+ GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
+ "Cannot use TCP and UDP\n");
+ global_ret = 1;
+ return;
+ }
+ proto = 0;
+ if (use_tcp)
+ proto = IPPROTO_TCP;
+ if (use_udp)
+ proto = IPPROTO_UDP;
+
+ if (NULL != bind_addr)
+ {
+ if (GNUNET_OK !=
+ GNUNET_STRINGS_to_address_ipv4 (bind_addr,
+ strlen (bind_addr),
+ &bind_sa))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
+ "Invalid socket address `%s'\n",
+ bind_addr);
+ global_ret = 1;
+ return;
+ }
+ }
+ if (NULL != extern_addr)
+ {
+ if (GNUNET_OK !=
+ GNUNET_STRINGS_to_address_ipv4 (extern_addr,
+ strlen (extern_addr),
+ &extern_sa))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
+ "Invalid socket address `%s'\n",
+ extern_addr);
+ global_ret = 1;
+ return;
+ }
+ }
+
+ if (NULL != bind_addr)
+ {
+ if (NULL == extern_addr)
+ extern_sa = bind_sa;
+ nt = GNUNET_NAT_test_start (c,
+ proto,
+ bind_sa.sin_addr,
+ ntohs (bind_sa.sin_port),
+ extern_sa.sin_addr,
+ ntohs (extern_sa.sin_port),
+ &test_report_cb,
+ NULL);
+ }
+ test_finished ();
+}
+
+
+/**
+ * Main function of gnunet-nat
+ *
+ * @param argc number of command-line arguments
+ * @param argv command line
+ * @return 0 on success, -1 on error
+ */
+int
+main (int argc,
+ char *const argv[])
+{
+ static const struct GNUNET_GETOPT_CommandLineOption options[] = {
+ {'a', "auto", NULL,
+ gettext_noop ("run autoconfiguration"),
+ GNUNET_NO, &GNUNET_GETOPT_set_one, &do_auto },
+ {'b', "bind", "ADDRESS",
+ gettext_noop ("which IP and port are we bound to"),
+ GNUNET_YES, &GNUNET_GETOPT_set_string, &bind_addr },
+ {'e', "external", "ADDRESS",
+ gettext_noop ("which external IP and port should be used to test"),
+ GNUNET_YES, &GNUNET_GETOPT_set_string, &extern_addr },
+ {'t', "tcp", NULL,
+ gettext_noop ("use TCP"),
+ GNUNET_NO, &GNUNET_GETOPT_set_one, &use_tcp },
+ {'u', "udp", NULL,
+ gettext_noop ("use UDP"),
+ GNUNET_NO, &GNUNET_GETOPT_set_one, &use_udp },
+ {'w', "write", NULL,
+ gettext_noop ("write configuration file (for autoconfiguration)"),
+ GNUNET_NO, &GNUNET_GETOPT_set_one, &write_cfg },
+ GNUNET_GETOPT_OPTION_END
+ };
+
+ if (GNUNET_OK !=
+ GNUNET_STRINGS_get_utf8_args (argc, argv,
+ &argc, &argv))
+ return 2;
+ if (GNUNET_OK !=
+ GNUNET_PROGRAM_run (argc, argv,
+ "gnunet-nat-auto [options]",
+ _("GNUnet NAT traversal autoconfiguration"),
+ options,
+ &run,
+ NULL))
+ {
+ global_ret = 1;
+ }
+ GNUNET_free ((void*) argv);
+ return global_ret;
+}
+
+
+/* end of gnunet-nat-auto.c */
diff --git a/src/nat/gnunet-nat-server.c b/src/nat-auto/gnunet-nat-server.c
index 1692a8ef1..93352f5f0 100644
--- a/src/nat/gnunet-nat-server.c
+++ b/src/nat-auto/gnunet-nat-server.c
@@ -27,7 +27,7 @@
#include "gnunet_util_lib.h"
#include "gnunet_nat_lib.h"
#include "gnunet_protocols.h"
-#include "nat.h"
+#include "nat-auto.h"
/**
diff --git a/src/nat-auto/gnunet-service-nat-auto.c b/src/nat-auto/gnunet-service-nat-auto.c
new file mode 100644
index 000000000..897d6feb2
--- /dev/null
+++ b/src/nat-auto/gnunet-service-nat-auto.c
@@ -0,0 +1,481 @@
+/*
+ This file is part of GNUnet.
+ Copyright (C) 2016, 2017 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-auto/gnunet-service-nat-auto.c
+ * @brief NAT autoconfiguration service
+ * @author Christian Grothoff
+ *
+ * TODO:
+ * - merge client handle and autoconfig context
+ * - implement "more" autoconfig:
+ * + re-work gnunet-nat-server & integrate!
+ * + test manually punched NAT (how?)
+ */
+#include "platform.h"
+#include <math.h>
+#include "gnunet_util_lib.h"
+#include "gnunet_protocols.h"
+#include "gnunet_signatures.h"
+#include "gnunet_nat_service.h"
+#include "gnunet_statistics_service.h"
+#include "gnunet_resolver_service.h"
+#include "nat-auto.h"
+#include <gcrypt.h>
+
+
+/**
+ * How long do we wait until we forcefully terminate autoconfiguration?
+ */
+#define AUTOCONFIG_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5)
+
+
+/**
+ * Internal data structure we track for each of our clients.
+ */
+struct ClientHandle
+{
+
+ /**
+ * Kept in a DLL.
+ */
+ struct ClientHandle *next;
+
+ /**
+ * Kept in a DLL.
+ */
+ struct ClientHandle *prev;
+
+ /**
+ * Underlying handle for this client with the service.
+ */
+ struct GNUNET_SERVICE_Client *client;
+
+ /**
+ * Message queue for communicating with the client.
+ */
+ struct GNUNET_MQ_Handle *mq;
+};
+
+
+/**
+ * Context for autoconfiguration operations.
+ */
+struct AutoconfigContext
+{
+ /**
+ * Kept in a DLL.
+ */
+ struct AutoconfigContext *prev;
+
+ /**
+ * Kept in a DLL.
+ */
+ struct AutoconfigContext *next;
+
+ /**
+ * Which client asked the question.
+ */
+ struct ClientHandle *ch;
+
+ /**
+ * Configuration we are creating.
+ */
+ struct GNUNET_CONFIGURATION_Handle *c;
+
+ /**
+ * Original configuration (for diffing).
+ */
+ struct GNUNET_CONFIGURATION_Handle *orig;
+
+ /**
+ * Timeout task to force termination.
+ */
+ struct GNUNET_SCHEDULER_Task *timeout_task;
+
+ /**
+ * #GNUNET_YES if upnpc should be used,
+ * #GNUNET_NO if upnpc should not be used,
+ * #GNUNET_SYSERR if we should simply not change the option.
+ */
+ int enable_upnpc;
+
+ /**
+ * Status code to return to the client.
+ */
+ enum GNUNET_NAT_StatusCode status_code;
+
+ /**
+ * NAT type to return to the client.
+ */
+ enum GNUNET_NAT_Type type;
+};
+
+
+/**
+ * Head of client DLL.
+ */
+static struct ClientHandle *ch_head;
+
+/**
+ * Tail of client DLL.
+ */
+static struct ClientHandle *ch_tail;
+
+/**
+ * DLL of our autoconfiguration operations.
+ */
+static struct AutoconfigContext *ac_head;
+
+/**
+ * DLL of our autoconfiguration operations.
+ */
+static struct AutoconfigContext *ac_tail;
+
+/**
+ * Handle to our current configuration.
+ */
+static const struct GNUNET_CONFIGURATION_Handle *cfg;
+
+/**
+ * Handle to the statistics service.
+ */
+static struct GNUNET_STATISTICS_Handle *stats;
+
+
+/**
+ * Check validity of #GNUNET_MESSAGE_TYPE_NAT_REQUEST_AUTO_CFG message
+ * from client.
+ *
+ * @param cls client who sent the message
+ * @param message the message received
+ * @return #GNUNET_OK if message is well-formed
+ */
+static int
+check_autoconfig_request (void *cls,
+ const struct GNUNET_NAT_AutoconfigRequestMessage *message)
+{
+ return GNUNET_OK; /* checked later */
+}
+
+
+/**
+ * Stop all pending activities with respect to the @a ac
+ *
+ * @param ac autoconfiguration to terminate activities for
+ */
+static void
+terminate_ac_activities (struct AutoconfigContext *ac)
+{
+ if (NULL != ac->timeout_task)
+ {
+ GNUNET_SCHEDULER_cancel (ac->timeout_task);
+ ac->timeout_task = NULL;
+ }
+}
+
+
+/**
+ * Finish handling the autoconfiguration request and send
+ * the response to the client.
+ *
+ * @param cls the `struct AutoconfigContext` to conclude
+ */
+static void
+conclude_autoconfig_request (void *cls)
+{
+ struct AutoconfigContext *ac = cls;
+ struct ClientHandle *ch = ac->ch;
+ struct GNUNET_NAT_AutoconfigResultMessage *arm;
+ struct GNUNET_MQ_Envelope *env;
+ size_t c_size;
+ char *buf;
+ struct GNUNET_CONFIGURATION_Handle *diff;
+
+ ac->timeout_task = NULL;
+ terminate_ac_activities (ac);
+
+ /* Send back response */
+ diff = GNUNET_CONFIGURATION_get_diff (ac->orig,
+ ac->c);
+ buf = GNUNET_CONFIGURATION_serialize (diff,
+ &c_size);
+ GNUNET_CONFIGURATION_destroy (diff);
+ env = GNUNET_MQ_msg_extra (arm,
+ c_size,
+ GNUNET_MESSAGE_TYPE_NAT_AUTO_CFG_RESULT);
+ arm->status_code = htonl ((uint32_t) ac->status_code);
+ arm->type = htonl ((uint32_t) ac->type);
+ GNUNET_memcpy (&arm[1],
+ buf,
+ c_size);
+ GNUNET_free (buf);
+ GNUNET_MQ_send (ch->mq,
+ env);
+
+ /* clean up */
+ GNUNET_CONFIGURATION_destroy (ac->orig);
+ GNUNET_CONFIGURATION_destroy (ac->c);
+ GNUNET_CONTAINER_DLL_remove (ac_head,
+ ac_tail,
+ ac);
+ GNUNET_free (ac);
+ GNUNET_SERVICE_client_continue (ch->client);
+}
+
+
+/**
+ * Check if all autoconfiguration operations have concluded,
+ * and if they have, send the result back to the client.
+ *
+ * @param ac autoconfiguation context to check
+ */
+static void
+check_autoconfig_finished (struct AutoconfigContext *ac)
+{
+ GNUNET_SCHEDULER_cancel (ac->timeout_task);
+ ac->timeout_task
+ = GNUNET_SCHEDULER_add_now (&conclude_autoconfig_request,
+ ac);
+}
+
+
+/**
+ * Update ENABLE_UPNPC configuration option.
+ *
+ * @param ac autoconfiguration to update
+ */
+static void
+update_enable_upnpc_option (struct AutoconfigContext *ac)
+{
+ switch (ac->enable_upnpc)
+ {
+ case GNUNET_YES:
+ GNUNET_CONFIGURATION_set_value_string (ac->c,
+ "NAT",
+ "ENABLE_UPNP",
+ "YES");
+ break;
+ case GNUNET_NO:
+ GNUNET_CONFIGURATION_set_value_string (ac->c,
+ "NAT",
+ "ENABLE_UPNP",
+ "NO");
+ break;
+ case GNUNET_SYSERR:
+ /* We are unsure, do not change option */
+ break;
+ }
+}
+
+
+/**
+ * Handler for #GNUNET_MESSAGE_TYPE_NAT_REQUEST_AUTO_CFG message from
+ * client.
+ *
+ * @param cls client who sent the message
+ * @param message the message received
+ */
+static void
+handle_autoconfig_request (void *cls,
+ const struct GNUNET_NAT_AutoconfigRequestMessage *message)
+{
+ struct ClientHandle *ch = cls;
+ size_t left = ntohs (message->header.size) - sizeof (*message);
+ struct AutoconfigContext *ac;
+
+ ac = GNUNET_new (struct AutoconfigContext);
+ ac->status_code = GNUNET_NAT_ERROR_SUCCESS;
+ ac->ch = ch;
+ ac->c = GNUNET_CONFIGURATION_create ();
+ if (GNUNET_OK !=
+ GNUNET_CONFIGURATION_deserialize (ac->c,
+ (const char *) &message[1],
+ left,
+ GNUNET_NO))
+ {
+ GNUNET_break (0);
+ GNUNET_SERVICE_client_drop (ch->client);
+ GNUNET_CONFIGURATION_destroy (ac->c);
+ GNUNET_free (ac);
+ return;
+ }
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Received REQUEST_AUTO_CONFIG message from client\n");
+
+ GNUNET_CONTAINER_DLL_insert (ac_head,
+ ac_tail,
+ ac);
+ ac->orig
+ = GNUNET_CONFIGURATION_dup (ac->c);
+ ac->timeout_task
+ = GNUNET_SCHEDULER_add_delayed (AUTOCONFIG_TIMEOUT,
+ &conclude_autoconfig_request,
+ ac);
+ ac->enable_upnpc = GNUNET_SYSERR; /* undecided */
+
+ /* Probe for upnpc */
+ if (GNUNET_SYSERR ==
+ GNUNET_OS_check_helper_binary ("upnpc",
+ GNUNET_NO,
+ NULL))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ _("UPnP client `upnpc` command not found, disabling UPnP\n"));
+ ac->enable_upnpc = GNUNET_NO;
+ }
+ else
+ {
+ /* We might at some point be behind NAT, try upnpc */
+ ac->enable_upnpc = GNUNET_YES;
+ }
+ update_enable_upnpc_option (ac);
+
+ /* Finally, check if we are already done */
+ check_autoconfig_finished (ac);
+}
+
+
+/**
+ * Task run during shutdown.
+ *
+ * @param cls unused
+ */
+static void
+shutdown_task (void *cls)
+{
+ struct AutoconfigContext *ac;
+
+ while (NULL != (ac = ac_head))
+ {
+ GNUNET_CONTAINER_DLL_remove (ac_head,
+ ac_tail,
+ ac);
+ terminate_ac_activities (ac);
+ GNUNET_free (ac);
+ }
+ if (NULL != stats)
+ {
+ GNUNET_STATISTICS_destroy (stats,
+ GNUNET_NO);
+ stats = NULL;
+ }
+}
+
+
+/**
+ * Setup NAT service.
+ *
+ * @param cls closure
+ * @param c configuration to use
+ * @param service the initialized service
+ */
+static void
+run (void *cls,
+ const struct GNUNET_CONFIGURATION_Handle *c,
+ struct GNUNET_SERVICE_Handle *service)
+{
+ cfg = c;
+ GNUNET_SCHEDULER_add_shutdown (&shutdown_task,
+ NULL);
+ stats = GNUNET_STATISTICS_create ("nat-auto",
+ cfg);
+}
+
+
+/**
+ * Callback called when a client connects to the service.
+ *
+ * @param cls closure for the service
+ * @param c the new client that connected to the service
+ * @param mq the message queue used to send messages to the client
+ * @return a `struct ClientHandle`
+ */
+static void *
+client_connect_cb (void *cls,
+ struct GNUNET_SERVICE_Client *c,
+ struct GNUNET_MQ_Handle *mq)
+{
+ struct ClientHandle *ch;
+
+ ch = GNUNET_new (struct ClientHandle);
+ ch->mq = mq;
+ ch->client = c;
+ GNUNET_CONTAINER_DLL_insert (ch_head,
+ ch_tail,
+ ch);
+ return ch;
+}
+
+
+/**
+ * Callback called when a client disconnected from the service
+ *
+ * @param cls closure for the service
+ * @param c the client that disconnected
+ * @param internal_cls a `struct ClientHandle *`
+ */
+static void
+client_disconnect_cb (void *cls,
+ struct GNUNET_SERVICE_Client *c,
+ void *internal_cls)
+{
+ struct ClientHandle *ch = internal_cls;
+
+ GNUNET_CONTAINER_DLL_remove (ch_head,
+ ch_tail,
+ ch);
+ GNUNET_free (ch);
+}
+
+
+/**
+ * Define "main" method using service macro.
+ */
+GNUNET_SERVICE_MAIN
+("nat",
+ GNUNET_SERVICE_OPTION_NONE,
+ &run,
+ &client_connect_cb,
+ &client_disconnect_cb,
+ NULL,
+ GNUNET_MQ_hd_var_size (autoconfig_request,
+ GNUNET_MESSAGE_TYPE_NAT_AUTO_REQUEST_CFG,
+ struct GNUNET_NAT_AutoconfigRequestMessage,
+ NULL),
+ GNUNET_MQ_handler_end ());
+
+
+#if defined(LINUX) && defined(__GLIBC__)
+#include <malloc.h>
+
+/**
+ * MINIMIZE heap size (way below 128k) since this process doesn't need much.
+ */
+void __attribute__ ((constructor))
+GNUNET_ARM_memory_init ()
+{
+ mallopt (M_TRIM_THRESHOLD, 4 * 1024);
+ mallopt (M_TOP_PAD, 1 * 1024);
+ malloc_trim (0);
+}
+#endif
+
+/* end of gnunet-service-nat.c */
diff --git a/src/nat-auto/nat-auto.conf.in b/src/nat-auto/nat-auto.conf.in
new file mode 100644
index 000000000..daa3e389d
--- /dev/null
+++ b/src/nat-auto/nat-auto.conf.in
@@ -0,0 +1,15 @@
+[nat]
+AUTOSTART = @AUTOSTART@
+@UNIXONLY@ PORT = 2124
+HOSTNAME = localhost
+BINARY = gnunet-service-nat-auto
+ACCEPT_FROM = 127.0.0.1;
+ACCEPT_FROM6 = ::1;
+UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-service-nat-auto.sock
+UNIX_MATCH_UID = YES
+UNIX_MATCH_GID = YES
+
+[gnunet-nat-server]
+HOSTNAME = gnunet.org
+PORT = 5724
+NOARMBIND = YES
diff --git a/src/nat-auto/nat-auto.h b/src/nat-auto/nat-auto.h
new file mode 100644
index 000000000..150dc32c2
--- /dev/null
+++ b/src/nat-auto/nat-auto.h
@@ -0,0 +1,110 @@
+/*
+ This file is part of GNUnet.
+ Copyright (C) 2011, 2016, 2017 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 src/nat-auto/nat-auto.h
+ * @brief Messages for interaction with gnunet-nat-auto-service
+ * @author Christian Grothoff
+ *
+ */
+#ifndef NAT_AUTO_H
+#define NAT_AUTO_H
+#include "gnunet_util_lib.h"
+
+
+
+GNUNET_NETWORK_STRUCT_BEGIN
+
+/**
+ * Request to test NAT traversal, sent to the gnunet-nat-server
+ * (not the service!).
+ */
+struct GNUNET_NAT_TestMessage
+{
+ /**
+ * Header with type #GNUNET_MESSAGE_TYPE_NAT_TEST
+ */
+ struct GNUNET_MessageHeader header;
+
+ /**
+ * IPv4 target IP address
+ */
+ uint32_t dst_ipv4;
+
+ /**
+ * Port to use, 0 to send dummy ICMP response.
+ */
+ uint16_t dport;
+
+ /**
+ * Data to send OR advertised-port (in NBO) to use for dummy ICMP.
+ */
+ uint16_t data;
+
+ /**
+ * #GNUNET_YES for TCP, #GNUNET_NO for UDP.
+ */
+ int32_t is_tcp;
+
+};
+
+
+/**
+ * Client requesting automatic configuration.
+ */
+struct GNUNET_NAT_AutoconfigRequestMessage
+{
+ /**
+ * Header with type #GNUNET_MESSAGE_TYPE_NAT_REQUEST_AUTO_CFG
+ */
+ struct GNUNET_MessageHeader header;
+
+ /* Followed by configuration (diff, serialized, compressed) */
+
+};
+
+
+/**
+ * Service responding with proposed configuration.
+ */
+struct GNUNET_NAT_AutoconfigResultMessage
+{
+ /**
+ * Header with type #GNUNET_MESSAGE_TYPE_NAT_AUTO_CFG_RESULT
+ */
+ struct GNUNET_MessageHeader header;
+
+ /**
+ * An `enum GNUNET_NAT_StatusCode` in NBO.
+ */
+ int32_t status_code GNUNET_PACKED;
+
+ /**
+ * An `enum GNUNET_NAT_Type` in NBO.
+ */
+ int32_t type GNUNET_PACKED;
+
+ /* Followed by configuration (diff, serialized, compressed) */
+};
+
+
+GNUNET_NETWORK_STRUCT_END
+
+#endif
diff --git a/src/nat/nat_api_auto.c b/src/nat-auto/nat_auto_api.c
index c5c5fa67a..e6b0512c6 100644
--- a/src/nat/nat_api_auto.c
+++ b/src/nat-auto/nat_auto_api.c
@@ -23,13 +23,13 @@
* @author Christian Grothoff
* @author Milan Bouchet-Valat
*
- * @file nat/nat_api_auto.c
+ * @file nat/nat_auto_api.c
* Routines for NAT auto configuration.
*/
#include "platform.h"
#include "gnunet_nat_service.h"
-#include "nat.h"
-#include "nat_stun.h"
+#include "gnunet_nat_auto_service.h"
+#include "nat-auto.h"
@@ -248,7 +248,7 @@ GNUNET_NAT_autoconfig_start (const struct GNUNET_CONFIGURATION_Handle *cfg,
}
env = GNUNET_MQ_msg_extra (req,
size,
- GNUNET_MESSAGE_TYPE_NAT_REQUEST_AUTO_CFG);
+ GNUNET_MESSAGE_TYPE_NAT_AUTO_REQUEST_CFG);
GNUNET_memcpy (&req[1],
buf,
size);
diff --git a/src/nat/nat_api_test.c b/src/nat-auto/nat_auto_api_test.c
index d47c14094..056d2a2bf 100644
--- a/src/nat/nat_api_test.c
+++ b/src/nat-auto/nat_auto_api_test.c
@@ -18,14 +18,14 @@
Boston, MA 02110-1301, USA.
*/
/**
- * @file nat/nat_api_test.c
+ * @file nat/nat_auto_api_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"
+#include "nat-auto.h"
#define LOG(kind,...) GNUNET_log_from (kind, "nat", __VA_ARGS__)
diff --git a/src/nat/Makefile.am b/src/nat/Makefile.am
index b2b9c4f50..456ddfb62 100644
--- a/src/nat/Makefile.am
+++ b/src/nat/Makefile.am
@@ -34,7 +34,6 @@ install-exec-hook:
endif
bin_PROGRAMS = \
- gnunet-nat-server \
gnunet-nat
libexec_PROGRAMS = \
@@ -42,12 +41,6 @@ libexec_PROGRAMS = \
gnunet-service-nat
-gnunet_nat_server_SOURCES = \
- gnunet-nat-server.c nat.h
-gnunet_nat_server_LDADD = \
- libgnunetnat.la \
- $(top_builddir)/src/util/libgnunetutil.la
-
gnunet_helper_nat_server_SOURCES = \
$(NATSERVER)
@@ -85,9 +78,7 @@ libgnunetnat_la_LDFLAGS = \
libgnunetnatnew_la_SOURCES = \
nat_api.c \
- nat_api_auto.c \
nat_api_stun.c nat_stun.h \
- nat_api_test.c \
nat.h
libgnunetnatnew_la_LIBADD = \
$(top_builddir)/src/util/libgnunetutil.la \
diff --git a/src/nat/gnunet-nat.c b/src/nat/gnunet-nat.c
index 4171babf9..02d68d787 100644
--- a/src/nat/gnunet-nat.c
+++ b/src/nat/gnunet-nat.c
@@ -34,11 +34,6 @@
static int global_ret;
/**
- * Handle to ongoing autoconfiguration.
- */
-static struct GNUNET_NAT_AutoHandle *ah;
-
-/**
* Name of section in configuration file to use for
* additional options.
*/
@@ -60,39 +55,11 @@ static int listen_reversal;
static int use_tcp;
/**
- * If we do auto-configuration, should we write the result
- * to a file?
- */
-static int write_cfg;
-
-/**
- * Configuration filename.
- */
-static const char *cfg_file;
-
-/**
- * Original configuration.
- */
-static const struct GNUNET_CONFIGURATION_Handle *cfg;
-
-/**
* Protocol to use.
*/
static uint8_t proto;
/**
- * Address we are bound to (in test), or should bind to
- * (if #do_stun is set).
- */
-static char *bind_addr;
-
-/**
- * External IP address and port to use for the test.
- * If not set, use #bind_addr.
- */
-static char *extern_addr;
-
-/**
* Local address to use for connection reversal request.
*/
static char *local_addr;
@@ -108,16 +75,6 @@ static char *remote_addr;
static unsigned int do_stun;
/**
- * Should we run autoconfiguration?
- */
-static unsigned int do_auto;
-
-/**
- * Handle to a NAT test operation.
- */
-static struct GNUNET_NAT_Test *nt;
-
-/**
* Handle to NAT operation.
*/
static struct GNUNET_NAT_Handle *nh;
@@ -140,10 +97,6 @@ static struct GNUNET_SCHEDULER_Task *rtask;
static void
test_finished ()
{
- if (NULL != ah)
- return;
- if (NULL != nt)
- return;
if (NULL != nh)
return;
if (NULL != rtask)
@@ -153,160 +106,6 @@ test_finished ()
/**
- * Function to iterate over sugested changes options
- *
- * @param cls closure
- * @param section name of the section
- * @param option name of the option
- * @param value value of the option
- */
-static void
-auto_conf_iter (void *cls,
- const char *section,
- const char *option,
- const char *value)
-{
- struct GNUNET_CONFIGURATION_Handle *new_cfg = cls;
-
- PRINTF ("%s: %s\n",
- option,
- value);
- if (NULL != new_cfg)
- GNUNET_CONFIGURATION_set_value_string (new_cfg,
- section,
- option,
- value);
-}
-
-
-/**
- * Function called with the result from the autoconfiguration.
- *
- * @param cls closure
- * @param diff minimal suggested changes to the original configuration
- * to make it work (as best as we can)
- * @param result #GNUNET_NAT_ERROR_SUCCESS on success, otherwise the specific error code
- * @param type what the situation of the NAT
- */
-static void
-auto_config_cb (void *cls,
- const struct GNUNET_CONFIGURATION_Handle *diff,
- enum GNUNET_NAT_StatusCode result,
- enum GNUNET_NAT_Type type)
-{
- const char *nat_type;
- char unknown_type[64];
- struct GNUNET_CONFIGURATION_Handle *new_cfg;
-
- ah = NULL;
- switch (type)
- {
- case GNUNET_NAT_TYPE_NO_NAT:
- nat_type = "NO NAT";
- break;
- case GNUNET_NAT_TYPE_UNREACHABLE_NAT:
- nat_type = "NAT but we can traverse";
- break;
- case GNUNET_NAT_TYPE_STUN_PUNCHED_NAT:
- nat_type = "NAT but STUN is able to identify the correct information";
- break;
- case GNUNET_NAT_TYPE_UPNP_NAT:
- nat_type = "NAT but UPNP opened the ports";
- break;
- default:
- SPRINTF (unknown_type,
- "NAT unknown, type %u",
- type);
- nat_type = unknown_type;
- break;
- }
-
- GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
- "NAT status: %s/%s\n",
- GNUNET_NAT_status2string (result),
- nat_type);
-
- /* Shortcut: if there are no changes suggested, bail out early. */
- if (GNUNET_NO ==
- GNUNET_CONFIGURATION_is_dirty (diff))
- {
- test_finished ();
- return;
- }
-
- /* Apply diff to original configuration and show changes
- to the user */
- new_cfg = write_cfg ? GNUNET_CONFIGURATION_dup (cfg) : NULL;
-
- if (NULL != diff)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
- _("Suggested configuration changes:\n"));
- GNUNET_CONFIGURATION_iterate_section_values (diff,
- "nat",
- &auto_conf_iter,
- new_cfg);
- }
-
- /* If desired, write configuration to file; we write only the
- changes to the defaults to keep things compact. */
- if ( (write_cfg) &&
- (NULL != diff) )
- {
- struct GNUNET_CONFIGURATION_Handle *def_cfg;
-
- GNUNET_CONFIGURATION_set_value_string (new_cfg,
- "ARM",
- "CONFIG",
- NULL);
- def_cfg = GNUNET_CONFIGURATION_create ();
- GNUNET_break (GNUNET_OK ==
- GNUNET_CONFIGURATION_load (def_cfg,
- NULL));
- if (GNUNET_OK !=
- GNUNET_CONFIGURATION_write_diffs (def_cfg,
- new_cfg,
- cfg_file))
- {
- GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
- _("Failed to write configuration to `%s'\n"),
- cfg_file);
- global_ret = 1;
- }
- else
- {
- GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
- _("Wrote updated configuration to `%s'\n"),
- cfg_file);
- }
- GNUNET_CONFIGURATION_destroy (def_cfg);
- }
-
- if (NULL != new_cfg)
- GNUNET_CONFIGURATION_destroy (new_cfg);
- test_finished ();
-}
-
-
-/**
- * Function called to report success or failure for
- * NAT configuration test.
- *
- * @param cls closure
- * @param result #GNUNET_NAT_ERROR_SUCCESS on success, otherwise the specific error code
- */
-static void
-test_report_cb (void *cls,
- enum GNUNET_NAT_StatusCode result)
-{
- nt = NULL;
- PRINTF ("NAT test result: %s\n",
- GNUNET_NAT_status2string (result));
- test_finished ();
-}
-
-
-/**
* Signature of the callback passed to #GNUNET_NAT_register() for
* a function to call whenever our set of 'valid' addresses changes.
*
@@ -362,16 +161,6 @@ reversal_cb (void *cls,
static void
do_shutdown (void *cls)
{
- if (NULL != ah)
- {
- GNUNET_NAT_autoconfig_cancel (ah);
- ah = NULL;
- }
- if (NULL != nt)
- {
- GNUNET_NAT_test_stop (nt);
- nt = NULL;
- }
if (NULL != nh)
{
GNUNET_NAT_unregister (nh);
@@ -452,16 +241,11 @@ run (void *cls,
const struct GNUNET_CONFIGURATION_Handle *c)
{
uint8_t af;
- struct sockaddr_in bind_sa;
- struct sockaddr_in extern_sa;
struct sockaddr *local_sa;
struct sockaddr *remote_sa;
socklen_t local_len;
size_t remote_len;
- cfg_file = cfgfile;
- cfg = c;
-
if (use_tcp && use_udp)
{
GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
@@ -478,50 +262,13 @@ run (void *cls,
GNUNET_SCHEDULER_add_shutdown (&do_shutdown,
NULL);
- if (do_auto)
- {
- ah = GNUNET_NAT_autoconfig_start (c,
- &auto_config_cb,
- NULL);
- }
-
if (0 == proto)
{
- if (do_auto)
- return; /* all good, we just run auto config */
GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
"Must specify either TCP or UDP\n");
global_ret = 1;
return;
}
- if (NULL != bind_addr)
- {
- if (GNUNET_OK !=
- GNUNET_STRINGS_to_address_ipv4 (bind_addr,
- strlen (bind_addr),
- &bind_sa))
- {
- GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
- "Invalid socket address `%s'\n",
- bind_addr);
- global_ret = 1;
- return;
- }
- }
- if (NULL != extern_addr)
- {
- if (GNUNET_OK !=
- GNUNET_STRINGS_to_address_ipv4 (extern_addr,
- strlen (extern_addr),
- &extern_sa))
- {
- GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
- "Invalid socket address `%s'\n",
- extern_addr);
- global_ret = 1;
- return;
- }
- }
if (NULL != local_addr)
{
local_len = (socklen_t) GNUNET_STRINGS_parse_socket_addr (local_addr,
@@ -551,20 +298,6 @@ run (void *cls,
}
}
- if (NULL != bind_addr)
- {
- if (NULL == extern_addr)
- extern_sa = bind_sa;
- nt = GNUNET_NAT_test_start (c,
- proto,
- bind_sa.sin_addr,
- ntohs (bind_sa.sin_port),
- extern_sa.sin_addr,
- ntohs (extern_sa.sin_port),
- &test_report_cb,
- NULL);
- }
-
if (NULL != local_addr)
{
nh = GNUNET_NAT_register (c,
@@ -683,15 +416,6 @@ main (int argc,
char *const argv[])
{
static const struct GNUNET_GETOPT_CommandLineOption options[] = {
- {'a', "auto", NULL,
- gettext_noop ("run autoconfiguration"),
- GNUNET_NO, &GNUNET_GETOPT_set_one, &do_auto },
- {'b', "bind", "ADDRESS",
- gettext_noop ("which IP and port are we bound to"),
- GNUNET_YES, &GNUNET_GETOPT_set_string, &bind_addr },
- {'e', "external", "ADDRESS",
- gettext_noop ("which external IP and port should be used to test"),
- GNUNET_YES, &GNUNET_GETOPT_set_string, &extern_addr },
{'i', "in", "ADDRESS",
gettext_noop ("which IP and port are we locally using to bind/listen to"),
GNUNET_YES, &GNUNET_GETOPT_set_string, &local_addr },
@@ -710,9 +434,6 @@ main (int argc,
{'u', "udp", NULL,
gettext_noop ("use UDP"),
GNUNET_NO, &GNUNET_GETOPT_set_one, &use_udp },
- {'w', "write", NULL,
- gettext_noop ("write configuration file (for autoconfiguration)"),
- GNUNET_NO, &GNUNET_GETOPT_set_one, &write_cfg },
{'W', "watch", NULL,
gettext_noop ("watch for connection reversal requests"),
GNUNET_NO, &GNUNET_GETOPT_set_one, &listen_reversal },
diff --git a/src/nat/gnunet-service-nat.c b/src/nat/gnunet-service-nat.c
index 79f806f27..2cb2b30ff 100644
--- a/src/nat/gnunet-service-nat.c
+++ b/src/nat/gnunet-service-nat.c
@@ -284,80 +284,6 @@ struct StunExternalIP
/**
- * Context for autoconfiguration operations.
- */
-struct AutoconfigContext
-{
- /**
- * Kept in a DLL.
- */
- struct AutoconfigContext *prev;
-
- /**
- * Kept in a DLL.
- */
- struct AutoconfigContext *next;
-
- /**
- * Which client asked the question.
- */
- struct ClientHandle *ch;
-
- /**
- * Configuration we are creating.
- */
- struct GNUNET_CONFIGURATION_Handle *c;
-
- /**
- * Original configuration (for diffing).
- */
- struct GNUNET_CONFIGURATION_Handle *orig;
-
- /**
- * Timeout task to force termination.
- */
- struct GNUNET_SCHEDULER_Task *timeout_task;
-
- /**
- * What type of system are we on?
- */
- char *system_type;
-
- /**
- * Handle to activity to probe for our external IP.
- */
- struct GNUNET_NAT_ExternalHandle *probe_external;
-
- /**
- * #GNUNET_YES if upnpc should be used,
- * #GNUNET_NO if upnpc should not be used,
- * #GNUNET_SYSERR if we should simply not change the option.
- */
- int enable_upnpc;
-
- /**
- * Status code to return to the client.
- */
- enum GNUNET_NAT_StatusCode status_code;
-
- /**
- * NAT type to return to the client.
- */
- enum GNUNET_NAT_Type type;
-};
-
-
-/**
- * DLL of our autoconfiguration operations.
- */
-static struct AutoconfigContext *ac_head;
-
-/**
- * DLL of our autoconfiguration operations.
- */
-static struct AutoconfigContext *ac_tail;
-
-/**
* Timeout to use when STUN data is considered stale.
*/
static struct GNUNET_TIME_Relative stun_stale_timeout;
@@ -1920,274 +1846,6 @@ handle_request_connection_reversal (void *cls,
/**
- * Check validity of #GNUNET_MESSAGE_TYPE_NAT_REQUEST_AUTO_CFG message
- * from client.
- *
- * @param cls client who sent the message
- * @param message the message received
- * @return #GNUNET_OK if message is well-formed
- */
-static int
-check_autoconfig_request (void *cls,
- const struct GNUNET_NAT_AutoconfigRequestMessage *message)
-{
- return GNUNET_OK; /* checked later */
-}
-
-
-/**
- * Stop all pending activities with respect to the @a ac
- *
- * @param ac autoconfiguration to terminate activities for
- */
-static void
-terminate_ac_activities (struct AutoconfigContext *ac)
-{
- if (NULL != ac->probe_external)
- {
- GNUNET_NAT_mini_get_external_ipv4_cancel_ (ac->probe_external);
- ac->probe_external = NULL;
- }
- if (NULL != ac->timeout_task)
- {
- GNUNET_SCHEDULER_cancel (ac->timeout_task);
- ac->timeout_task = NULL;
- }
-}
-
-
-/**
- * Finish handling the autoconfiguration request and send
- * the response to the client.
- *
- * @param cls the `struct AutoconfigContext` to conclude
- */
-static void
-conclude_autoconfig_request (void *cls)
-{
- struct AutoconfigContext *ac = cls;
- struct ClientHandle *ch = ac->ch;
- struct GNUNET_NAT_AutoconfigResultMessage *arm;
- struct GNUNET_MQ_Envelope *env;
- size_t c_size;
- char *buf;
- struct GNUNET_CONFIGURATION_Handle *diff;
-
- ac->timeout_task = NULL;
- terminate_ac_activities (ac);
-
- /* Send back response */
- diff = GNUNET_CONFIGURATION_get_diff (ac->orig,
- ac->c);
- buf = GNUNET_CONFIGURATION_serialize (diff,
- &c_size);
- GNUNET_CONFIGURATION_destroy (diff);
- env = GNUNET_MQ_msg_extra (arm,
- c_size,
- GNUNET_MESSAGE_TYPE_NAT_AUTO_CFG_RESULT);
- arm->status_code = htonl ((uint32_t) ac->status_code);
- arm->type = htonl ((uint32_t) ac->type);
- GNUNET_memcpy (&arm[1],
- buf,
- c_size);
- GNUNET_free (buf);
- GNUNET_MQ_send (ch->mq,
- env);
-
- /* clean up */
- GNUNET_free (ac->system_type);
- GNUNET_CONFIGURATION_destroy (ac->orig);
- GNUNET_CONFIGURATION_destroy (ac->c);
- GNUNET_CONTAINER_DLL_remove (ac_head,
- ac_tail,
- ac);
- GNUNET_free (ac);
- GNUNET_SERVICE_client_continue (ch->client);
-}
-
-
-/**
- * Check if all autoconfiguration operations have concluded,
- * and if they have, send the result back to the client.
- *
- * @param ac autoconfiguation context to check
- */
-static void
-check_autoconfig_finished (struct AutoconfigContext *ac)
-{
- if (NULL != ac->probe_external)
- return;
- GNUNET_SCHEDULER_cancel (ac->timeout_task);
- ac->timeout_task
- = GNUNET_SCHEDULER_add_now (&conclude_autoconfig_request,
- ac);
-}
-
-
-/**
- * Update ENABLE_UPNPC configuration option.
- *
- * @param ac autoconfiguration to update
- */
-static void
-update_enable_upnpc_option (struct AutoconfigContext *ac)
-{
- switch (ac->enable_upnpc)
- {
- case GNUNET_YES:
- GNUNET_CONFIGURATION_set_value_string (ac->c,
- "NAT",
- "ENABLE_UPNP",
- "YES");
- break;
- case GNUNET_NO:
- GNUNET_CONFIGURATION_set_value_string (ac->c,
- "NAT",
- "ENABLE_UPNP",
- "NO");
- break;
- case GNUNET_SYSERR:
- /* We are unsure, do not change option */
- break;
- }
-}
-
-
-/**
- * Handle result from external IP address probe during
- * autoconfiguration.
- *
- * @param cls our `struct AutoconfigContext`
- * @param addr the address, NULL on errors
- * @param result #GNUNET_NAT_ERROR_SUCCESS on success, otherwise the specific error code
- */
-static void
-auto_external_result_cb (void *cls,
- const struct in_addr *addr,
- enum GNUNET_NAT_StatusCode result)
-{
- struct AutoconfigContext *ac = cls;
-
- ac->probe_external = NULL;
- switch (result)
- {
- case GNUNET_NAT_ERROR_SUCCESS:
- ac->enable_upnpc = GNUNET_YES;
- break;
- case GNUNET_NAT_ERROR_EXTERNAL_IP_UTILITY_OUTPUT_INVALID:
- case GNUNET_NAT_ERROR_EXTERNAL_IP_ADDRESS_INVALID:
- case GNUNET_NAT_ERROR_IPC_FAILURE:
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "Disabling UPNPC: %d\n",
- (int) result);
- ac->enable_upnpc = GNUNET_NO; /* did not work */
- break;
- default:
- GNUNET_break (0); /* unexpected */
- ac->enable_upnpc = GNUNET_SYSERR;
- break;
- }
- update_enable_upnpc_option (ac);
- check_autoconfig_finished (ac);
-}
-
-
-/**
- * Handler for #GNUNET_MESSAGE_TYPE_NAT_REQUEST_AUTO_CFG message from
- * client.
- *
- * @param cls client who sent the message
- * @param message the message received
- */
-static void
-handle_autoconfig_request (void *cls,
- const struct GNUNET_NAT_AutoconfigRequestMessage *message)
-{
- struct ClientHandle *ch = cls;
- size_t left = ntohs (message->header.size) - sizeof (*message);
- struct LocalAddressList *lal;
- struct AutoconfigContext *ac;
-
- ac = GNUNET_new (struct AutoconfigContext);
- ac->status_code = GNUNET_NAT_ERROR_SUCCESS;
- ac->ch = ch;
- ac->c = GNUNET_CONFIGURATION_create ();
- if (GNUNET_OK !=
- GNUNET_CONFIGURATION_deserialize (ac->c,
- (const char *) &message[1],
- left,
- GNUNET_NO))
- {
- GNUNET_break (0);
- GNUNET_SERVICE_client_drop (ch->client);
- GNUNET_CONFIGURATION_destroy (ac->c);
- GNUNET_free (ac);
- return;
- }
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Received REQUEST_AUTO_CONFIG message from client\n");
-
- if (GNUNET_OK !=
- GNUNET_CONFIGURATION_get_value_string (ac->c,
- "PEER",
- "SYSTEM_TYPE",
- &ac->system_type))
- ac->system_type = GNUNET_strdup ("UNKNOWN");
-
- GNUNET_CONTAINER_DLL_insert (ac_head,
- ac_tail,
- ac);
- ac->orig
- = GNUNET_CONFIGURATION_dup (ac->c);
- ac->timeout_task
- = GNUNET_SCHEDULER_add_delayed (AUTOCONFIG_TIMEOUT,
- &conclude_autoconfig_request,
- ac);
- ac->enable_upnpc = GNUNET_SYSERR; /* undecided */
-
- /* Probe for upnpc */
- if (GNUNET_SYSERR ==
- GNUNET_OS_check_helper_binary ("upnpc",
- GNUNET_NO,
- NULL))
- {
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- _("UPnP client `upnpc` command not found, disabling UPnP\n"));
- ac->enable_upnpc = GNUNET_NO;
- }
- else
- {
- for (lal = lal_head; NULL != lal; lal = lal->next)
- if (GNUNET_NAT_AC_LAN == (lal->ac & GNUNET_NAT_AC_LAN))
- /* we are behind NAT, useful to try upnpc */
- ac->enable_upnpc = GNUNET_YES;
- }
- if (GNUNET_YES == ac->enable_upnpc)
- {
- /* If we are a mobile device, always leave it on as the network
- may change to one that supports UPnP anytime. If we are
- stationary, check if our network actually supports UPnP, and if
- not, disable it. */
- if ( (0 == strcasecmp (ac->system_type,
- "INFRASTRUCTURE")) ||
- (0 == strcasecmp (ac->system_type,
- "DESKTOP")) )
- {
- /* Check if upnpc gives us an external IP */
- ac->probe_external
- = GNUNET_NAT_mini_get_external_ipv4_ (&auto_external_result_cb,
- ac);
- }
- }
- if (NULL == ac->probe_external)
- update_enable_upnpc_option (ac);
-
- /* Finally, check if we are already done */
- check_autoconfig_finished (ac);
-}
-
-
-/**
* Task run during shutdown.
*
* @param cls unused
@@ -2196,16 +1854,7 @@ static void
shutdown_task (void *cls)
{
struct StunExternalIP *se;
- struct AutoconfigContext *ac;
- while (NULL != (ac = ac_head))
- {
- GNUNET_CONTAINER_DLL_remove (ac_head,
- ac_tail,
- ac);
- terminate_ac_activities (ac);
- GNUNET_free (ac);
- }
while (NULL != (se = se_head))
{
GNUNET_CONTAINER_DLL_remove (se_head,
@@ -2386,10 +2035,6 @@ GNUNET_SERVICE_MAIN
GNUNET_MESSAGE_TYPE_NAT_REQUEST_CONNECTION_REVERSAL,
struct GNUNET_NAT_RequestConnectionReversalMessage,
NULL),
- GNUNET_MQ_hd_var_size (autoconfig_request,
- GNUNET_MESSAGE_TYPE_NAT_REQUEST_AUTO_CFG,
- struct GNUNET_NAT_AutoconfigRequestMessage,
- NULL),
GNUNET_MQ_handler_end ());
diff --git a/src/nat/nat.conf.in b/src/nat/nat.conf.in
index 304db3c15..88975c424 100644
--- a/src/nat/nat.conf.in
+++ b/src/nat/nat.conf.in
@@ -67,8 +67,3 @@ STUN_SERVERS = stun.gnunet.org stun.services.mozilla.com:3478 stun.ekiga.net:347
# After how long do we consider STUN data stale?
STUN_STALE = 60 min
-
-[gnunet-nat-server]
-HOSTNAME = gnunet.org
-PORT = 5724
-NOARMBIND = YES
diff --git a/src/nat/nat.h b/src/nat/nat.h
index 02bae71e9..d34900bd1 100644
--- a/src/nat/nat.h
+++ b/src/nat/nat.h
@@ -224,45 +224,6 @@ struct GNUNET_NAT_AddressChangeNotificationMessage
};
-/**
- * Client requesting automatic configuration.
- */
-struct GNUNET_NAT_AutoconfigRequestMessage
-{
- /**
- * Header with type #GNUNET_MESSAGE_TYPE_NAT_REQUEST_AUTO_CFG
- */
- struct GNUNET_MessageHeader header;
-
- /* Followed by configuration (diff, serialized, compressed) */
-
-};
-
-
-/**
- * Service responding with proposed configuration.
- */
-struct GNUNET_NAT_AutoconfigResultMessage
-{
- /**
- * Header with type #GNUNET_MESSAGE_TYPE_NAT_AUTO_CFG_RESULT
- */
- struct GNUNET_MessageHeader header;
-
- /**
- * An `enum GNUNET_NAT_StatusCode` in NBO.
- */
- int32_t status_code GNUNET_PACKED;
-
- /**
- * An `enum GNUNET_NAT_Type` in NBO.
- */
- int32_t type GNUNET_PACKED;
-
- /* Followed by configuration (diff, serialized, compressed) */
-};
-
-
GNUNET_NETWORK_STRUCT_END
#endif