|
@@ -19,6 +19,7 @@
|
|
*/
|
|
*/
|
|
#define TOR_CHANNEL_INTERNAL_
|
|
#define TOR_CHANNEL_INTERNAL_
|
|
#define CONNECTION_PRIVATE
|
|
#define CONNECTION_PRIVATE
|
|
|
|
+#include "backtrace.h"
|
|
#include "channel.h"
|
|
#include "channel.h"
|
|
#include "channeltls.h"
|
|
#include "channeltls.h"
|
|
#include "circuitbuild.h"
|
|
#include "circuitbuild.h"
|
|
@@ -1721,6 +1722,66 @@ connection_connect_sockaddr,(connection_t *conn,
|
|
return inprogress ? 0 : 1;
|
|
return inprogress ? 0 : 1;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+/* Log a message if connection violates ClientUseIPv4 0 or ClientUseIPv6 0.
|
|
|
|
+ * Log a less severe message if we couldn't conform to ClientPreferIPv6ORPort
|
|
|
|
+ * or ClientPreferIPv6ORPort. */
|
|
|
|
+static void
|
|
|
|
+connection_connect_log_client_use_ip_version(const connection_t *conn)
|
|
|
|
+{
|
|
|
|
+ const or_options_t *options = get_options();
|
|
|
|
+
|
|
|
|
+ /* Only non-bridge clients care about ClientUseIPv4/6, bail out early on
|
|
|
|
+ * servers and bridge clients */
|
|
|
|
+ if (options->UseBridges || server_mode(options) || !conn
|
|
|
|
+ || conn->type == CONN_TYPE_EXIT) {
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /* We're only prepared to log OR and DIR connections here */
|
|
|
|
+ if (conn->type != CONN_TYPE_OR && conn->type != CONN_TYPE_DIR) {
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ const int must_ipv4 = (options->ClientUseIPv6 == 0);
|
|
|
|
+ const int must_ipv6 = (options->ClientUseIPv4 == 0);
|
|
|
|
+ const int pref_ipv6 = (conn->type == CONN_TYPE_OR
|
|
|
|
+ ? nodelist_prefer_ipv6_orport(options)
|
|
|
|
+ : nodelist_prefer_ipv6_dirport(options));
|
|
|
|
+ tor_addr_t real_addr;
|
|
|
|
+ tor_addr_make_null(&real_addr, AF_UNSPEC);
|
|
|
|
+
|
|
|
|
+ /* OR conns keep the original address in real_addr, as addr gets overwritten
|
|
|
|
+ * with the descriptor address */
|
|
|
|
+ if (conn->type == CONN_TYPE_OR) {
|
|
|
|
+ const or_connection_t *or_conn = TO_OR_CONN((connection_t *)conn);
|
|
|
|
+ tor_addr_copy(&real_addr, &or_conn->real_addr);
|
|
|
|
+ } else if (conn->type == CONN_TYPE_DIR) {
|
|
|
|
+ tor_addr_copy(&real_addr, &conn->addr);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /* Check if we broke a mandatory address family restriction */
|
|
|
|
+ if ((must_ipv4 && tor_addr_family(&real_addr) == AF_INET6)
|
|
|
|
+ || (must_ipv6 && tor_addr_family(&real_addr) == AF_INET)) {
|
|
|
|
+ log_warn(LD_BUG, "%s connection to %s violated ClientUseIPv%s 0.",
|
|
|
|
+ conn->type == CONN_TYPE_OR ? "OR" : "Dir",
|
|
|
|
+ fmt_addr(&real_addr),
|
|
|
|
+ options->ClientUseIPv4 == 0 ? "4" : "6");
|
|
|
|
+ log_backtrace(LOG_WARN, LD_BUG, "Address came from");
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /* Check if we couldn't satisfy an address family preference */
|
|
|
|
+ if ((!pref_ipv6 && tor_addr_family(&real_addr) == AF_INET6)
|
|
|
|
+ || (pref_ipv6 && tor_addr_family(&real_addr) == AF_INET)) {
|
|
|
|
+ log_info(LD_NET, "Connection to %s doesn't satisfy ClientPreferIPv6%sPort "
|
|
|
|
+ "%d, with ClientUseIPv4 %d and ClientUseIPv6 %d.",
|
|
|
|
+ fmt_addr(&real_addr),
|
|
|
|
+ conn->type == CONN_TYPE_OR ? "OR" : "Dir",
|
|
|
|
+ conn->type == CONN_TYPE_OR ? options->ClientPreferIPv6ORPort
|
|
|
|
+ : options->ClientPreferIPv6DirPort,
|
|
|
|
+ options->ClientUseIPv4, options->ClientUseIPv4);
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
/** Take conn, make a nonblocking socket; try to connect to
|
|
/** Take conn, make a nonblocking socket; try to connect to
|
|
* addr:port (port arrives in *host order*). If fail, return -1 and if
|
|
* addr:port (port arrives in *host order*). If fail, return -1 and if
|
|
* applicable put your best guess about errno into *<b>socket_error</b>.
|
|
* applicable put your best guess about errno into *<b>socket_error</b>.
|
|
@@ -1745,6 +1806,10 @@ connection_connect(connection_t *conn, const char *address,
|
|
const or_options_t *options = get_options();
|
|
const or_options_t *options = get_options();
|
|
int protocol_family;
|
|
int protocol_family;
|
|
|
|
|
|
|
|
+ /* Log if we didn't stick to ClientUseIPv4/6 or ClientPreferIPv6OR/DirPort
|
|
|
|
+ */
|
|
|
|
+ connection_connect_log_client_use_ip_version(conn);
|
|
|
|
+
|
|
if (tor_addr_family(addr) == AF_INET6)
|
|
if (tor_addr_family(addr) == AF_INET6)
|
|
protocol_family = PF_INET6;
|
|
protocol_family = PF_INET6;
|
|
else
|
|
else
|