aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2016-12-16 10:53:58 +0100
committerChristian Grothoff <christian@grothoff.org>2016-12-16 10:53:58 +0100
commit8108e41d89bb771fe8bcf887919de3f581f1cc0d (patch)
tree970c382485c663f8c8516b59e34790d33878dbfb
parentf88d55e43f3d3a4468c2faa0621044ad17594e5f (diff)
add PORT to NAT configuration, generate nat.conf from nat.conf.in, implement more of new NAT service
-rw-r--r--configure.ac1
-rw-r--r--src/conversation/conversation.conf.in2
-rw-r--r--src/include/gnunet_nat_service.h10
-rw-r--r--src/nat/Makefile.am2
-rw-r--r--src/nat/gnunet-service-nat.c274
-rw-r--r--src/nat/gnunet-service-nat_helper.c40
-rw-r--r--src/nat/gnunet-service-nat_helper.h8
-rw-r--r--src/nat/nat.conf.in (renamed from src/nat/nat.conf)10
-rw-r--r--src/rps/rps.conf.in2
9 files changed, 217 insertions, 132 deletions
diff --git a/configure.ac b/configure.ac
index ebe5753aaa..faf058849b 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1595,6 +1595,7 @@ src/namecache/namecache.conf
src/namestore/Makefile
src/namestore/namestore.conf
src/nat/Makefile
+src/nat/nat.conf
src/nse/Makefile
src/nse/nse.conf
src/peerinfo/Makefile
diff --git a/src/conversation/conversation.conf.in b/src/conversation/conversation.conf.in
index fb0478f4ed..e966ed6d9f 100644
--- a/src/conversation/conversation.conf.in
+++ b/src/conversation/conversation.conf.in
@@ -3,7 +3,7 @@ AUTOSTART = @AUTOSTART@
BINARY = gnunet-service-conversation
UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-service-conversation.sock
HOSTNAME = localhost
-@UNIXONLY@ PORT = 2106
+@UNIXONLY@ PORT = 2120
# Desired phone line. Change if multiple users are using
# the same peer and we thus need disjoint phone lines.
diff --git a/src/include/gnunet_nat_service.h b/src/include/gnunet_nat_service.h
index 378f5a8cbd..b66b442405 100644
--- a/src/include/gnunet_nat_service.h
+++ b/src/include/gnunet_nat_service.h
@@ -64,7 +64,7 @@ enum GNUNET_NAT_AddressClass
GNUNET_NAT_AC_OTHER = 1,
/**
- * Addresses that are highly sensitive
+ * Flag for addresses that are highly sensitive
* (i.e. IPv6 with our MAC).
*/
GNUNET_NAT_AC_PRIVATE = 2,
@@ -83,6 +83,7 @@ enum GNUNET_NAT_AddressClass
/**
* Addresses useful in the local wired network,
* i.e. a MAC. Sensitive, but obvious to people nearby.
+
* Useful for broadcasts.
*/
GNUNET_NAT_AC_LAN = 8,
@@ -113,6 +114,13 @@ enum GNUNET_NAT_AddressClass
GNUNET_NAT_AC_LOOPBACK = 64,
/**
+ * Addresses that should be our global external IP address
+ * on the outside of a NAT. Might be incorrectly determined.
+ * Used as a bit in combination with #GNUNET_NAT_AC_GLOBAL.
+ */
+ GNUNET_NAT_AC_GLOBAL_EXTERN = 128,
+
+ /**
* Bitmask for "any" address.
*/
GNUNET_NAT_AC_ANY = 65535
diff --git a/src/nat/Makefile.am b/src/nat/Makefile.am
index d304a57d07..c62a8d2cf9 100644
--- a/src/nat/Makefile.am
+++ b/src/nat/Makefile.am
@@ -12,7 +12,7 @@ libexecdir= $(pkglibdir)/libexec/
pkgcfgdir= $(pkgdatadir)/config.d/
-dist_pkgcfg_DATA = \
+pkgcfg_DATA = \
nat.conf
if LINUX
diff --git a/src/nat/gnunet-service-nat.c b/src/nat/gnunet-service-nat.c
index f4755659f2..1ebf75608e 100644
--- a/src/nat/gnunet-service-nat.c
+++ b/src/nat/gnunet-service-nat.c
@@ -28,10 +28,8 @@
* knowledge about the local network topology.
*
* TODO:
- * - call GN_start_gnunet_nat_server_() if possible (i.e.
- * when we find we have a non-global IPv4 address)
+ * - implement UPnPC/PMP-based NAT traversal
* - implement autoconfig
- * - implmeent UPnPC/PMP-based NAT traversal
* - implement NEW logic for external IP detection
*/
#include "platform.h"
@@ -91,6 +89,11 @@ struct ClientHandle
enum GNUNET_NAT_RegisterFlags flags;
/**
+ * Is any of the @e addrs in a reserved subnet for NAT?
+ */
+ int natted_address;
+
+ /**
* Port we would like as we are configured to use this one for
* advertising (in addition to the one we are binding to).
*/
@@ -306,6 +309,108 @@ check_register (void *cls,
/**
+ * Check if @a ip is in @a network with @a bits netmask.
+ *
+ * @param network to test
+ * @param ip IP address to test
+ * @param bits bitmask for the network
+ * @return #GNUNET_YES if @a ip is in @a network
+ */
+static int
+match_ipv4 (const char *network,
+ const struct in_addr *ip,
+ uint8_t bits)
+{
+ struct in_addr net;
+
+ if (0 == bits)
+ return GNUNET_YES;
+ GNUNET_assert (1 == inet_pton (AF_INET,
+ network,
+ &net));
+ return ! ((ip->s_addr ^ net.s_addr) & htonl (0xFFFFFFFFu << (32 - bits)));
+}
+
+
+/**
+ * Check if @a ip is in @a network with @a bits netmask.
+ *
+ * @param network to test
+ * @param ip IP address to test
+ * @param bits bitmask for the network
+ * @return #GNUNET_YES if @a ip is in @a network
+ */
+static int
+match_ipv6 (const char *network,
+ const struct in6_addr *ip,
+ uint8_t bits)
+{
+ struct in6_addr net;
+ struct in6_addr mask;
+ unsigned int off;
+
+ if (0 == bits)
+ return GNUNET_YES;
+ GNUNET_assert (1 == inet_pton (AF_INET,
+ network,
+ &net));
+ memset (&mask, 0, sizeof (mask));
+ off = 0;
+ while (bits > 8)
+ {
+ mask.s6_addr[off++] = 0xFF;
+ bits -= 8;
+ }
+ while (bits > 0)
+ {
+ mask.s6_addr[off] = (mask.s6_addr[off] >> 1) + 0x80;
+ bits--;
+ }
+ for (unsigned j = 0; j < sizeof (struct in6_addr) / sizeof (uint32_t); j++)
+ if (((((uint32_t *) ip)[j] & ((uint32_t *) &mask)[j])) !=
+ (((uint32_t *) &net)[j] & ((int *) &mask)[j]))
+ return GNUNET_NO;
+ return GNUNET_YES;
+}
+
+
+/**
+ * Test if the given IPv4 address is in a known range
+ * for private networks.
+ *
+ * @param ip address to test
+ * @return #GNUNET_YES if @a ip is in a NAT range
+ */
+static int
+is_nat_v4 (const struct in_addr *ip)
+{
+ return
+ match_ipv4 ("10.0.0.0", ip, 8) || /* RFC 1918 */
+ match_ipv4 ("100.64.0.0", ip, 10) || /* CG-NAT, RFC 6598 */
+ match_ipv4 ("192.168.0.0", ip, 12) || /* RFC 1918 */
+ match_ipv4 ("169.254.0.0", ip, 16) || /* AUTO, RFC 3927 */
+ match_ipv4 ("172.16.0.0", ip, 16); /* RFC 1918 */
+}
+
+
+/**
+ * Test if the given IPv6 address is in a known range
+ * for private networks.
+ *
+ * @param ip address to test
+ * @return #GNUNET_YES if @a ip is in a NAT range
+ */
+static int
+is_nat_v6 (const struct in6_addr *ip)
+{
+ return
+ match_ipv6 ("fc00::", ip, 7) || /* RFC 4193 */
+ match_ipv6 ("fec0::", ip, 10) || /* RFC 3879 */
+ match_ipv6 ("fe80::", ip, 10); /* RFC 4291, link-local */
+}
+
+
+/**
* Handler for #GNUNET_MESSAGE_TYPE_NAT_REGISTER message from client.
* We remember the client for updates upon future NAT events.
*
@@ -352,10 +457,22 @@ handle_register (void *cls,
switch (sa->sa_family)
{
case AF_INET:
- alen = sizeof (struct sockaddr_in);
+ {
+ const struct sockaddr_in *s4 = (const struct sockaddr_in *) sa;
+
+ alen = sizeof (struct sockaddr_in);
+ if (is_nat_v4 (&s4->sin_addr))
+ ch->natted_address = GNUNET_YES;
+ }
break;
case AF_INET6:
- alen = sizeof (struct sockaddr_in6);
+ {
+ const struct sockaddr_in6 *s6 = (const struct sockaddr_in6 *) sa;
+
+ alen = sizeof (struct sockaddr_in6);
+ if (is_nat_v6 (&s6->sin6_addr))
+ ch->natted_address = GNUNET_YES;
+ }
break;
#if AF_UNIX
case AF_UNIX:
@@ -418,7 +535,30 @@ static void
notify_clients_stun_change (const struct sockaddr_in *ip,
int add)
{
- /* FIXME: notify clients about add/drop */
+ for (struct ClientHandle *ch = ch_head;
+ NULL != ch;
+ ch = ch->next)
+ {
+ struct sockaddr_in v4;
+ struct GNUNET_NAT_AddressChangeNotificationMessage *msg;
+ struct GNUNET_MQ_Envelope *env;
+
+ if (! ch->natted_address)
+ continue;
+ v4 = *ip;
+ v4.sin_port = htons (ch->adv_port);
+ env = GNUNET_MQ_msg_extra (msg,
+ sizeof (v4),
+ GNUNET_MESSAGE_TYPE_NAT_ADDRESS_CHANGE);
+ msg->add_remove = htonl ((int32_t) add);
+ msg->addr_class = htonl (GNUNET_NAT_AC_GLOBAL_EXTERN |
+ GNUNET_NAT_AC_GLOBAL);
+ GNUNET_memcpy (&msg[1],
+ &v4,
+ sizeof (v4));
+ GNUNET_MQ_send (ch->mq,
+ env);
+ }
}
@@ -599,6 +739,9 @@ handle_request_connection_reversal (void *cls,
size_t remote_sa_len = ntohs (message->remote_addr_size);
const struct sockaddr *local_sa = (const struct sockaddr *) &buf[0];
const struct sockaddr *remote_sa = (const struct sockaddr *) &buf[local_sa_len];
+ const struct sockaddr_in *l4 = NULL;
+ const struct sockaddr_in *r4;
+ int ret;
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Received REQUEST CONNECTION REVERSAL message from client\n");
@@ -611,6 +754,7 @@ handle_request_connection_reversal (void *cls,
GNUNET_SERVICE_client_drop (ch->client);
return;
}
+ l4 = (const struct sockaddr_in *) local_sa;
break;
case AF_INET6:
if (local_sa_len != sizeof (struct sockaddr_in6))
@@ -619,6 +763,9 @@ handle_request_connection_reversal (void *cls,
GNUNET_SERVICE_client_drop (ch->client);
return;
}
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ _("Connection reversal for IPv6 not supported yet\n"));
+ ret = GNUNET_SYSERR;
break;
default:
GNUNET_break (0);
@@ -634,6 +781,10 @@ handle_request_connection_reversal (void *cls,
GNUNET_SERVICE_client_drop (ch->client);
return;
}
+ r4 = (const struct sockaddr_in *) remote_sa;
+ ret = GN_request_connection_reversal (&l4->sin_addr,
+ ntohs (l4->sin_port),
+ &r4->sin_addr);
break;
case AF_INET6:
if (remote_sa_len != sizeof (struct sockaddr_in6))
@@ -642,15 +793,18 @@ handle_request_connection_reversal (void *cls,
GNUNET_SERVICE_client_drop (ch->client);
return;
}
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ _("Connection reversal for IPv6 not supported yet\n"));
+ ret = GNUNET_SYSERR;
break;
default:
GNUNET_break (0);
GNUNET_SERVICE_client_drop (ch->client);
return;
}
- /* FIXME: actually run the logic by
- calling 'GN_request_connection_reversal()' */
-
+ if (GNUNET_OK != ret)
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ _("Connection reversal request failed\n"));
GNUNET_SERVICE_client_continue (ch->client);
}
@@ -757,108 +911,6 @@ struct IfcProcContext
/**
- * Check if @a ip is in @a network with @a bits netmask.
- *
- * @param network to test
- * @param ip IP address to test
- * @param bits bitmask for the network
- * @return #GNUNET_YES if @a ip is in @a network
- */
-static int
-match_ipv4 (const char *network,
- const struct in_addr *ip,
- uint8_t bits)
-{
- struct in_addr net;
-
- if (0 == bits)
- return GNUNET_YES;
- GNUNET_assert (1 == inet_pton (AF_INET,
- network,
- &net));
- return ! ((ip->s_addr ^ net.s_addr) & htonl (0xFFFFFFFFu << (32 - bits)));
-}
-
-
-/**
- * Check if @a ip is in @a network with @a bits netmask.
- *
- * @param network to test
- * @param ip IP address to test
- * @param bits bitmask for the network
- * @return #GNUNET_YES if @a ip is in @a network
- */
-static int
-match_ipv6 (const char *network,
- const struct in6_addr *ip,
- uint8_t bits)
-{
- struct in6_addr net;
- struct in6_addr mask;
- unsigned int off;
-
- if (0 == bits)
- return GNUNET_YES;
- GNUNET_assert (1 == inet_pton (AF_INET,
- network,
- &net));
- memset (&mask, 0, sizeof (mask));
- off = 0;
- while (bits > 8)
- {
- mask.s6_addr[off++] = 0xFF;
- bits -= 8;
- }
- while (bits > 0)
- {
- mask.s6_addr[off] = (mask.s6_addr[off] >> 1) + 0x80;
- bits--;
- }
- for (unsigned j = 0; j < sizeof (struct in6_addr) / sizeof (uint32_t); j++)
- if (((((uint32_t *) ip)[j] & ((uint32_t *) &mask)[j])) !=
- (((uint32_t *) &net)[j] & ((int *) &mask)[j]))
- return GNUNET_NO;
- return GNUNET_YES;
-}
-
-
-/**
- * Test if the given IPv4 address is in a known range
- * for private networks.
- *
- * @param ip address to test
- * @return #GNUNET_YES if @a ip is in a NAT range
- */
-static int
-is_nat_v4 (const struct in_addr *ip)
-{
- return
- match_ipv4 ("10.0.0.0", ip, 8) || /* RFC 1918 */
- match_ipv4 ("100.64.0.0", ip, 10) || /* CG-NAT, RFC 6598 */
- match_ipv4 ("192.168.0.0", ip, 12) || /* RFC 1918 */
- match_ipv4 ("169.254.0.0", ip, 16) || /* AUTO, RFC 3927 */
- match_ipv4 ("172.16.0.0", ip, 16); /* RFC 1918 */
-}
-
-
-/**
- * Test if the given IPv6 address is in a known range
- * for private networks.
- *
- * @param ip address to test
- * @return #GNUNET_YES if @a ip is in a NAT range
- */
-static int
-is_nat_v6 (const struct in6_addr *ip)
-{
- return
- match_ipv6 ("fc00::", ip, 7) || /* RFC 4193 */
- match_ipv6 ("fec0::", ip, 10) || /* RFC 3879 */
- match_ipv6 ("fe80::", ip, 10); /* RFC 4291, link-local */
-}
-
-
-/**
* Callback function invoked for each interface found. Adds them
* to our new address list.
*
diff --git a/src/nat/gnunet-service-nat_helper.c b/src/nat/gnunet-service-nat_helper.c
index e476da12d2..379603ae27 100644
--- a/src/nat/gnunet-service-nat_helper.c
+++ b/src/nat/gnunet-service-nat_helper.c
@@ -319,7 +319,7 @@ GN_stop_gnunet_nat_server_ (struct HelperContext *h)
GNUNET_SCHEDULER_cancel (h->server_read_task);
h->server_read_task = NULL;
}
- if (NULL != h->server_proc)
+ if (NULL != h->server_proc)
{
if (0 != GNUNET_OS_process_kill (h->server_proc,
GNUNET_TERM_SIG))
@@ -349,23 +349,25 @@ GN_stop_gnunet_nat_server_ (struct HelperContext *h)
* that peer to connect to us (connection reversal).
*
* @param internal_address out internal address to use
- * @param sa the address of the peer (IPv4-only)
+ * @param internal_port port to use
+ * @param remote_v4 the address of the peer (IPv4-only)
* @return #GNUNET_SYSERR on error,
* #GNUNET_OK otherwise
*/
int
-GN_request_connection_reversal (const char *internal_address,
- const struct sockaddr_in *sa)
+GN_request_connection_reversal (const struct in_addr *internal_address,
+ uint16_t internal_port,
+ const struct in_addr *remote_v4)
{
- char inet4[INET_ADDRSTRLEN];
+ char intv4[INET_ADDRSTRLEN];
+ char remv4[INET_ADDRSTRLEN];
char port_as_string[6];
struct GNUNET_OS_Process *proc;
char *binary;
- GNUNET_assert (sa->sin_family == AF_INET);
if (NULL == inet_ntop (AF_INET,
- &sa->sin_addr,
- inet4,
+ internal_address,
+ intv4,
INET_ADDRSTRLEN))
{
GNUNET_log_from_strerror (GNUNET_ERROR_TYPE_WARNING,
@@ -373,15 +375,25 @@ GN_request_connection_reversal (const char *internal_address,
"inet_ntop");
return GNUNET_SYSERR;
}
+ if (NULL == inet_ntop (AF_INET,
+ remote_v4,
+ remv4,
+ 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",
- ntohs (sa->sin_port));
+ internal_port);
LOG (GNUNET_ERROR_TYPE_DEBUG,
_("Running gnunet-helper-nat-client %s %s %u\n"),
- internal_address,
- inet4,
- ntohs (sa->sin_port));
+ intv4,
+ remv4,
+ internal_port);
binary
= GNUNET_OS_get_libexec_binary_path ("gnunet-helper-nat-client");
proc
@@ -392,8 +404,8 @@ GN_request_connection_reversal (const char *internal_address,
NULL,
binary,
"gnunet-helper-nat-client",
- internal_address,
- inet4,
+ intv4,
+ remv4,
port_as_string,
NULL);
GNUNET_free (binary);
diff --git a/src/nat/gnunet-service-nat_helper.h b/src/nat/gnunet-service-nat_helper.h
index 861d62c1d5..d3f1a757c7 100644
--- a/src/nat/gnunet-service-nat_helper.h
+++ b/src/nat/gnunet-service-nat_helper.h
@@ -77,13 +77,15 @@ GN_stop_gnunet_nat_server_ (struct HelperContext *h);
* that peer to connect to us (connection reversal).
*
* @param internal_address out internal address to use
- * @param sa the address of the peer (IPv4-only)
+ * @param internal_port internal port to use
+ * @param remote_v4 the address of the peer (IPv4-only)
* @return #GNUNET_SYSERR on error,
* #GNUNET_OK otherwise
*/
int
-GN_request_connection_reversal (const char *internal_address,
- const struct sockaddr_in *sa);
+GN_request_connection_reversal (const struct in_addr *internal_address,
+ uint16_t internal_port,
+ const struct in_addr *sa);
/* end of gnunet-service-nat_helper.h */
diff --git a/src/nat/nat.conf b/src/nat/nat.conf.in
index 4493a6ec95..304db3c153 100644
--- a/src/nat/nat.conf
+++ b/src/nat/nat.conf.in
@@ -1,4 +1,14 @@
[nat]
+AUTOSTART = @AUTOSTART@
+@UNIXONLY@ PORT = 2121
+HOSTNAME = localhost
+BINARY = gnunet-service-nat
+ACCEPT_FROM = 127.0.0.1;
+ACCEPT_FROM6 = ::1;
+UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-service-nat.sock
+UNIX_MATCH_UID = YES
+UNIX_MATCH_GID = YES
+
# Are we behind NAT?
BEHIND_NAT = NO
diff --git a/src/rps/rps.conf.in b/src/rps/rps.conf.in
index 046a8b5d93..b5feb1bd25 100644
--- a/src/rps/rps.conf.in
+++ b/src/rps/rps.conf.in
@@ -8,7 +8,7 @@ UNIX_MATCH_GID = YES
HOSTNAME = localhost
ACCEPT_FROM = 127.0.0.1;
ACCEPT_FROM6 = ::1;
-# PORT = 2106
+# PORT = 2119
@UNIXONLY@ PORT = 2119
# This is the timeinterval between the rounds