[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[GNUnet-SVN] r34396 - in gnunet/src: include transport util
From: |
gnunet |
Subject: |
[GNUnet-SVN] r34396 - in gnunet/src: include transport util |
Date: |
Sun, 2 Nov 2014 21:54:51 +0100 |
Author: grothoff
Date: 2014-11-02 21:54:51 +0100 (Sun, 02 Nov 2014)
New Revision: 34396
Modified:
gnunet/src/include/gnunet_connection_lib.h
gnunet/src/include/gnunet_service_lib.h
gnunet/src/transport/plugin_transport_http_common.h
gnunet/src/transport/plugin_transport_tcp.c
gnunet/src/util/connection.c
gnunet/src/util/network.c
gnunet/src/util/service.c
Log:
adding TCP_STEALTH support to TCP plugin
Modified: gnunet/src/include/gnunet_connection_lib.h
===================================================================
--- gnunet/src/include/gnunet_connection_lib.h 2014-11-02 15:18:57 UTC (rev
34395)
+++ gnunet/src/include/gnunet_connection_lib.h 2014-11-02 20:54:51 UTC (rev
34396)
@@ -123,16 +123,32 @@
* reach the other side before the process is terminated.
*
* @param connection the connection to make flushing and blocking
- * @return GNUNET_OK on success
+ * @return #GNUNET_OK on success
*/
int
GNUNET_CONNECTION_disable_corking (struct GNUNET_CONNECTION_Handle
*connection);
/**
+ * Create a connection handle by (asynchronously) connecting to a host.
+ * This function returns immediately, even if the connection has not
+ * yet been established. This function only creates TCP connections.
+ *
+ * @param s socket to connect
+ * @param serv_addr server address
+ * @param addrlen length of server address
+ * @return the connection handle
+ */
+struct GNUNET_CONNECTION_Handle *
+GNUNET_CONNECTION_connect_socket (struct GNUNET_NETWORK_Handle *s,
+ const struct sockaddr *serv_addr,
+ socklen_t addrlen);
+
+
+/**
* Create a connection handle by boxing an existing OS socket. The OS
* socket should henceforth be no longer used directly.
- * GNUNET_CONNECTION_destroy will close it.
+ * #GNUNET_CONNECTION_destroy() will close it.
*
* @param osSocket existing socket to box
* @return the boxed socket handle
Modified: gnunet/src/include/gnunet_service_lib.h
===================================================================
--- gnunet/src/include/gnunet_service_lib.h 2014-11-02 15:18:57 UTC (rev
34395)
+++ gnunet/src/include/gnunet_service_lib.h 2014-11-02 20:54:51 UTC (rev
34396)
@@ -159,6 +159,17 @@
/**
+ * Get the NULL-terminated array of listen sockets for this service.
+ *
+ * @param ctx service context to query
+ * @return NULL if there are no listen sockets, otherwise NULL-terminated
+ * array of listen sockets.
+ */
+struct GNUNET_NETWORK_Handle **
+GNUNET_SERVICE_get_listen_sockets (struct GNUNET_SERVICE_Context *ctx);
+
+
+/**
* Stop a service that was started with #GNUNET_SERVICE_start.
*
* @param sctx the service context returned from the start function
Modified: gnunet/src/transport/plugin_transport_http_common.h
===================================================================
--- gnunet/src/transport/plugin_transport_http_common.h 2014-11-02 15:18:57 UTC
(rev 34395)
+++ gnunet/src/transport/plugin_transport_http_common.h 2014-11-02 20:54:51 UTC
(rev 34396)
@@ -57,9 +57,21 @@
#define HTTP_DEFAULT_PORT 80
#define HTTPS_DEFAULT_PORT 443
-enum HTTP_ADDRESS_OPTIONS
+/**
+ * Bits in the `options` field of HTTP addresses.
+ */
+enum HttpAddressOptions
{
+ /**
+ * No bits set.
+ */
HTTP_OPTIONS_NONE = 0,
+
+ /**
+ * Verify X509 server certificate, it should be valid.
+ * (if this bit is not set, it is probably just self-
+ * signed and not expected to be verified).
+ */
HTTP_OPTIONS_VERIFY_CERTIFICATE = 1
};
@@ -73,6 +85,7 @@
{
/**
* Address options
+ * see `enum HttpAddressOptions`
*/
uint32_t options;
Modified: gnunet/src/transport/plugin_transport_tcp.c
===================================================================
--- gnunet/src/transport/plugin_transport_tcp.c 2014-11-02 15:18:57 UTC (rev
34395)
+++ gnunet/src/transport/plugin_transport_tcp.c 2014-11-02 20:54:51 UTC (rev
34396)
@@ -121,6 +121,28 @@
struct Plugin *plugin;
};
+/**
+ * Bits in the `options` field of TCP addresses.
+ */
+enum TcpAddressOptions
+{
+
+ /**
+ * No bits set.
+ */
+ TCP_OPTIONS_NONE = 0,
+
+ /**
+ * See #HTTP_OPTIONS_VERIFY_CERTIFICATE.
+ */
+ TCP_OPTIONS_RESERVED = 1,
+
+ /**
+ * Enable TCP Stealth-style port knocking.
+ */
+ TCP_OPTIONS_TCP_STEALTH = 2
+};
+
GNUNET_NETWORK_STRUCT_BEGIN
/**
@@ -129,7 +151,8 @@
struct IPv4TcpAddress
{
/**
- * Optional options and flags for this address
+ * Optional options and flags for this address,
+ * see `enum TcpAddressOptions`
*/
uint32_t options;
@@ -152,6 +175,7 @@
{
/**
* Optional flags for this address
+ * see `enum TcpAddressOptions`
*/
uint32_t options;
@@ -1488,9 +1512,13 @@
struct sockaddr_in6 a6;
const struct IPv4TcpAddress *t4;
const struct IPv6TcpAddress *t6;
+ unsigned int options;
struct GNUNET_ATS_Information ats;
unsigned int is_natd = GNUNET_NO;
size_t addrlen;
+#ifdef SO_TCPSTEALTH
+ struct GNUNET_NETWORK_Handle *s;
+#endif
addrlen = address->address_length;
LOG(GNUNET_ERROR_TYPE_DEBUG,
@@ -1537,6 +1565,7 @@
{
GNUNET_assert(NULL != address->address); /* make static analysis happy */
t6 = address->address;
+ options = t6->options;
af = AF_INET6;
memset (&a6, 0, sizeof(a6));
#if HAVE_SOCKADDR_IN_SIN_LEN
@@ -1554,6 +1583,7 @@
{
GNUNET_assert(NULL != address->address); /* make static analysis happy */
t4 = address->address;
+ options = t4->options;
af = AF_INET;
memset (&a4, 0, sizeof(a4));
#if HAVE_SOCKADDR_IN_SIN_LEN
@@ -1571,7 +1601,7 @@
{
GNUNET_STATISTICS_update (plugin->env->stats, gettext_noop
("# requests to create session with invalid address"), 1, GNUNET_NO);
- return NULL ;
+ return NULL;
}
ats = plugin->env->get_address_type (plugin->env->cls, sb, sbs);
@@ -1579,13 +1609,13 @@
if ((is_natd == GNUNET_YES) && (addrlen == sizeof(struct IPv6TcpAddress)))
{
/* NAT client only works with IPv4 addresses */
- return NULL ;
+ return NULL;
}
if (plugin->cur_connections >= plugin->max_connections)
{
/* saturated */
- return NULL ;
+ return NULL;
}
if ((is_natd == GNUNET_YES)
@@ -1594,7 +1624,7 @@
&address->peer)))
{
/* Only do one NAT punch attempt per peer identity */
- return NULL ;
+ return NULL;
}
if ((is_natd == GNUNET_YES) && (NULL != plugin->nat) &&
@@ -1634,13 +1664,51 @@
/* create new outbound session */
GNUNET_assert(plugin->cur_connections <= plugin->max_connections);
- sa = GNUNET_CONNECTION_create_from_sockaddr (af, sb, sbs);
+
+ if (0 != (options & TCP_OPTIONS_TCP_STEALTH))
+ {
+#ifdef SO_TCPSTEALTH
+ s = GNUNET_NETWORK_socket_create (af, SOCK_STREAM, 0);
+ if (NULL == s)
+ {
+ GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING | GNUNET_ERROR_TYPE_BULK,
+ "socket");
+ sa = NULL;
+ }
+ else
+ {
+ if (GNUNET_OK !=
+ GNUNET_NETWORK_socket_setsockopt (s,
+ IPPROTO_TCP,
+ SO_TCPSTEALTH,
+ &session->target,
+ sizeof (struct
GNUNET_PeerIdentity)))
+ {
+ /* TCP STEALTH not supported by kernel */
+ GNUNET_break (GNUNET_OK ==
+ GNUNET_NETWORK_socket_close (s));
+ sa = NULL;
+ }
+ else
+ {
+ sa = GNUNET_CONNECTION_connect_socket (s, sb, sbs);
+ }
+ }
+#else
+ sa = NULL;
+#endif
+ }
+ else
+ {
+ sa = GNUNET_CONNECTION_create_from_sockaddr (af, sb, sbs);
+ }
if (NULL == sa)
{
- LOG(GNUNET_ERROR_TYPE_DEBUG,
- "Failed to create connection to `%4s' at `%s'\n",
- GNUNET_i2s (&address->peer), GNUNET_a2s (sb, sbs));
- return NULL ;
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ "Failed to create connection to `%4s' at `%s'\n",
+ GNUNET_i2s (&address->peer),
+ GNUNET_a2s (sb, sbs));
+ return NULL;
}
plugin->cur_connections++;
if (plugin->cur_connections == plugin->max_connections)
@@ -1651,7 +1719,8 @@
GNUNET_i2s (&address->peer), GNUNET_a2s (sb, sbs));
session = create_session (plugin, address,
- GNUNET_SERVER_connect_socket (plugin->server, sa), GNUNET_NO);
+ GNUNET_SERVER_connect_socket (plugin->server, sa),
+ GNUNET_NO);
session->ats_address_network_type = (enum GNUNET_ATS_Network_Type) ntohl (
ats.value);
GNUNET_break(session->ats_address_network_type !=
GNUNET_ATS_NET_UNSPECIFIED);
@@ -2100,7 +2169,7 @@
case AF_INET:
s4 = vaddr;
t4 = GNUNET_new (struct IPv4TcpAddress);
- t4->options = htonl(0);
+ t4->options = htonl (TCP_OPTIONS_NONE);
t4->t4_port = s4->sin_port;
t4->ipv4_addr = s4->sin_addr.s_addr;
session->address = GNUNET_HELLO_address_allocate (
@@ -2111,7 +2180,7 @@
case AF_INET6:
s6 = vaddr;
t6 = GNUNET_new (struct IPv6TcpAddress);
- t6->options = htonl(0);
+ t6->options = htonl (TCP_OPTIONS_NONE);
t6->t6_port = s6->sin6_port;
memcpy (&t6->ipv6_addr, &s6->sin6_addr, sizeof(struct in6_addr));
session->address = GNUNET_HELLO_address_allocate (
@@ -2209,7 +2278,7 @@
{
s4 = vaddr;
memset (&t4, '\0', sizeof (t4));
- t4.options = htonl (0);
+ t4.options = htonl (TCP_OPTIONS_NONE);
t4.t4_port = s4->sin_port;
t4.ipv4_addr = s4->sin_addr.s_addr;
address = GNUNET_HELLO_address_allocate (&wm->clientIdentity,
@@ -2220,7 +2289,7 @@
{
s6 = vaddr;
memset (&t6, '\0', sizeof (t6));
- t6.options = htonl (0);
+ t6.options = htonl (TCP_OPTIONS_NONE);
t6.t6_port = s6->sin6_port;
memcpy (&t6.ipv6_addr, &s6->sin6_addr, sizeof(struct in6_addr));
address = GNUNET_HELLO_address_allocate (&wm->clientIdentity,
@@ -2609,6 +2678,9 @@
unsigned long long max_connections;
unsigned int i;
struct GNUNET_TIME_Relative idle_timeout;
+#ifdef SO_TCPSTEALTH
+ struct GNUNET_NETWORK_Handle **lsocks;
+#endif
int ret;
int ret_s;
struct sockaddr **addrs;
@@ -2635,28 +2707,30 @@
max_connections = 128;
aport = 0;
- if ((GNUNET_OK
- != GNUNET_CONFIGURATION_get_value_number (env->cfg, "transport-tcp",
- "PORT", &bport)) || (bport > 65535)
- || ((GNUNET_OK
- == GNUNET_CONFIGURATION_get_value_number (env->cfg, "transport-tcp",
- "ADVERTISED-PORT", &aport)) && (aport > 65535)))
+ if ((GNUNET_OK !=
+ GNUNET_CONFIGURATION_get_value_number (env->cfg, "transport-tcp",
+ "PORT", &bport)) ||
+ (bport > 65535) ||
+ ((GNUNET_OK ==
+ GNUNET_CONFIGURATION_get_value_number (env->cfg, "transport-tcp",
+ "ADVERTISED-PORT", &aport)) &&
+ (aport > 65535) ))
{
LOG(GNUNET_ERROR_TYPE_ERROR,
_("Require valid port number for service `%s' in configuration!\n"),
"transport-tcp");
return NULL ;
}
- if (aport == 0)
+ if (0 == aport)
aport = bport;
- if (bport == 0)
+ if (0 == bport)
aport = 0;
- if (bport != 0)
+ if (0 != bport)
{
service = GNUNET_SERVICE_start ("transport-tcp",
env->cfg,
GNUNET_SERVICE_OPTION_NONE);
- if (service == NULL)
+ if (NULL == service)
{
LOG (GNUNET_ERROR_TYPE_WARNING,
_("Failed to start service.\n"));
@@ -2666,14 +2740,51 @@
else
service = NULL;
+ api = NULL;
plugin = GNUNET_new (struct Plugin);
plugin->sessionmap = GNUNET_CONTAINER_multipeermap_create (max_connections,
- GNUNET_YES);
+ GNUNET_YES);
plugin->max_connections = max_connections;
plugin->open_port = bport;
plugin->adv_port = aport;
plugin->env = env;
- if ( (service != NULL) &&
+
+ if ( (NULL != service) &&
+ (GNUNET_YES ==
+ GNUNET_CONFIGURATION_get_value_yesno (env->cfg,
+ "transport-tcp",
+ "TCP_STEALTH")) )
+ {
+#ifdef SO_TCPSTEALTH
+ plugin->myoptions |= TCP_OPTIONS_TCP_STEALTH;
+ lsocks = GNUNET_SERVICE_get_listen_sockets (service);
+ if (NULL != lsocks)
+ {
+ for (i=0;NULL!=lsocks[i];i++)
+ {
+ if (GNUNET_OK !=
+ GNUNET_NETWORK_socket_setsockopt (lsocks[i],
+ IPPROTO_TCP,
+ SO_TCPSTEALTH,
+ env->my_identity,
+ sizeof (struct
GNUNET_PeerIdentity)))
+ {
+ /* TCP STEALTH not supported by kernel */
+ GNUNET_assert (0 == i);
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ _("TCP_STEALTH not supported on this platform.\n"));
+ goto die;
+ }
+ }
+ }
+#else
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ _("TCP_STEALTH not supported on this platform.\n"));
+ goto die;
+#endif
+ }
+
+ if ( (NULL != service) &&
(GNUNET_SYSERR !=
(ret_s =
GNUNET_SERVICE_get_server_addresses ("transport-tcp",
@@ -2736,11 +2847,7 @@
GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
"transport-tcp",
"TIMEOUT");
- if (NULL != plugin->nat)
- GNUNET_NAT_unregister (plugin->nat);
- GNUNET_free(plugin);
- GNUNET_free(api);
- return NULL;
+ goto die;
}
plugin->server
= GNUNET_SERVER_create_with_sockets (&plugin_tcp_access_check,
@@ -2775,6 +2882,16 @@
0,
GNUNET_NO);
return api;
+
+ die:
+ if (NULL != plugin->nat)
+ GNUNET_NAT_unregister (plugin->nat);
+ GNUNET_CONTAINER_multipeermap_destroy (plugin->sessionmap);
+ if (NULL != service)
+ GNUNET_SERVICE_stop (service);
+ GNUNET_free (plugin);
+ GNUNET_free_non_null (api);
+ return NULL;
}
Modified: gnunet/src/util/connection.c
===================================================================
--- gnunet/src/util/connection.c 2014-11-02 15:18:57 UTC (rev 34395)
+++ gnunet/src/util/connection.c 2014-11-02 20:54:51 UTC (rev 34396)
@@ -789,8 +789,8 @@
* @return the connection handle
*/
struct GNUNET_CONNECTION_Handle *
-GNUNET_CONNECTION_create_from_connect (const struct GNUNET_CONFIGURATION_Handle
- *cfg, const char *hostname,
+GNUNET_CONNECTION_create_from_connect (const struct
GNUNET_CONFIGURATION_Handle *cfg,
+ const char *hostname,
uint16_t port)
{
struct GNUNET_CONNECTION_Handle *connection;
@@ -883,31 +883,25 @@
* This function returns immediately, even if the connection has not
* yet been established. This function only creates TCP connections.
*
- * @param af_family address family to use
+ * @param s socket to connect
* @param serv_addr server address
* @param addrlen length of server address
* @return the connection handle
*/
struct GNUNET_CONNECTION_Handle *
-GNUNET_CONNECTION_create_from_sockaddr (int af_family,
- const struct sockaddr *serv_addr,
- socklen_t addrlen)
+GNUNET_CONNECTION_connect_socket (struct GNUNET_NETWORK_Handle *s,
+ const struct sockaddr *serv_addr,
+ socklen_t addrlen)
{
- struct GNUNET_NETWORK_Handle *s;
struct GNUNET_CONNECTION_Handle *connection;
- s = GNUNET_NETWORK_socket_create (af_family, SOCK_STREAM, 0);
- if (NULL == s)
- {
- LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING | GNUNET_ERROR_TYPE_BULK,
"socket");
- return NULL;
- }
if ((GNUNET_OK != GNUNET_NETWORK_socket_connect (s, serv_addr, addrlen)) &&
(EINPROGRESS != errno))
{
/* maybe refused / unsupported address, try next */
LOG_STRERROR (GNUNET_ERROR_TYPE_INFO, "connect");
- LOG (GNUNET_ERROR_TYPE_INFO, _("Attempt to connect to `%s' failed\n"),
+ LOG (GNUNET_ERROR_TYPE_INFO,
+ _("Attempt to connect to `%s' failed\n"),
GNUNET_a2s (serv_addr, addrlen));
GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (s));
return NULL;
@@ -916,19 +910,48 @@
connection->addr = GNUNET_malloc (addrlen);
memcpy (connection->addr, serv_addr, addrlen);
connection->addrlen = addrlen;
- LOG (GNUNET_ERROR_TYPE_INFO, _("Trying to connect to `%s' (%p)\n"),
+ LOG (GNUNET_ERROR_TYPE_INFO,
+ _("Trying to connect to `%s' (%p)\n"),
GNUNET_a2s (serv_addr, addrlen), connection);
return connection;
}
/**
+ * Create a connection handle by creating a socket and
+ * (asynchronously) connecting to a host. This function returns
+ * immediately, even if the connection has not yet been established.
+ * This function only creates TCP connections.
+ *
+ * @param af_family address family to use
+ * @param serv_addr server address
+ * @param addrlen length of @a serv_addr
+ * @return the connection handle
+ */
+struct GNUNET_CONNECTION_Handle *
+GNUNET_CONNECTION_create_from_sockaddr (int af_family,
+ const struct sockaddr *serv_addr,
+ socklen_t addrlen)
+{
+ struct GNUNET_NETWORK_Handle *s;
+
+ s = GNUNET_NETWORK_socket_create (af_family, SOCK_STREAM, 0);
+ if (NULL == s)
+ {
+ LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING | GNUNET_ERROR_TYPE_BULK,
"socket");
+ return NULL;
+ }
+ return GNUNET_CONNECTION_connect_socket (s, serv_addr, addrlen);
+}
+
+
+/**
* Check if connection is valid (no fatal errors have happened so far).
* Note that a connection that is still trying to connect is considered
* valid.
*
* @param connection connection to check
- * @return GNUNET_YES if valid, GNUNET_NO otherwise
+ * @return #GNUNET_YES if valid, #GNUNET_NO otherwise
*/
int
GNUNET_CONNECTION_check (struct GNUNET_CONNECTION_Handle *connection)
Modified: gnunet/src/util/network.c
===================================================================
--- gnunet/src/util/network.c 2014-11-02 15:18:57 UTC (rev 34395)
+++ gnunet/src/util/network.c 2014-11-02 20:54:51 UTC (rev 34396)
@@ -829,17 +829,23 @@
* @param level protocol level of the option
* @param option_name option identifier
* @param option_value value to set
- * @param option_len size of option_value
+ * @param option_len size of @a option_value
* @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise
*/
int
-GNUNET_NETWORK_socket_setsockopt (struct GNUNET_NETWORK_Handle *fd, int level,
- int option_name, const void *option_value,
+GNUNET_NETWORK_socket_setsockopt (struct GNUNET_NETWORK_Handle *fd,
+ int level,
+ int option_name,
+ const void *option_value,
socklen_t option_len)
{
int ret;
- ret = setsockopt (fd->fd, level, option_name, option_value, option_len);
+ ret = setsockopt (fd->fd,
+ level,
+ option_name,
+ option_value,
+ option_len);
#ifdef MINGW
if (SOCKET_ERROR == ret)
SetErrnoFromWinsockError (WSAGetLastError ());
Modified: gnunet/src/util/service.c
===================================================================
--- gnunet/src/util/service.c 2014-11-02 15:18:57 UTC (rev 34395)
+++ gnunet/src/util/service.c 2014-11-02 20:54:51 UTC (rev 34396)
@@ -142,7 +142,7 @@
GNUNET_SERVICE_Main task;
/**
- * Closure for task.
+ * Closure for @e task.
*/
void *task_cls;
@@ -1628,6 +1628,20 @@
/**
+ * Get the NULL-terminated array of listen sockets for this service.
+ *
+ * @param ctx service context to query
+ * @return NULL if there are no listen sockets, otherwise NULL-terminated
+ * array of listen sockets.
+ */
+struct GNUNET_NETWORK_Handle **
+GNUNET_SERVICE_get_listen_sockets (struct GNUNET_SERVICE_Context *ctx)
+{
+ return ctx->lsocks;
+}
+
+
+/**
* Stop a service that was started with "GNUNET_SERVICE_start".
*
* @param sctx the service context returned from the start function
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [GNUnet-SVN] r34396 - in gnunet/src: include transport util,
gnunet <=