mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2024-11-27 22:03:31 +01:00
Merge branch 'bug11485_026_v2_squashed'
This commit is contained in:
commit
a3de2dfde6
3
changes/ticket11485
Normal file
3
changes/ticket11485
Normal file
@ -0,0 +1,3 @@
|
||||
o Features (hidden services):
|
||||
- Support mapping hidden service virtual ports to AF_UNIX sockets on
|
||||
suitable platforms. Resolves ticket #11485.
|
@ -56,6 +56,11 @@
|
||||
#include <pwd.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_SYS_UN_H
|
||||
#include <sys/socket.h>
|
||||
#include <sys/un.h>
|
||||
#endif
|
||||
|
||||
static connection_t *connection_listener_new(
|
||||
const struct sockaddr *listensockaddr,
|
||||
socklen_t listensocklen, int type,
|
||||
@ -1585,6 +1590,98 @@ connection_init_accepted_conn(connection_t *conn,
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
connection_connect_sockaddr(connection_t *conn,
|
||||
const struct sockaddr *sa,
|
||||
socklen_t sa_len,
|
||||
const struct sockaddr *bindaddr,
|
||||
socklen_t bindaddr_len,
|
||||
int *socket_error)
|
||||
{
|
||||
tor_socket_t s;
|
||||
int inprogress = 0;
|
||||
const or_options_t *options = get_options();
|
||||
int protocol_family;
|
||||
|
||||
tor_assert(conn);
|
||||
tor_assert(sa);
|
||||
tor_assert(socket_error);
|
||||
|
||||
if (get_n_open_sockets() >= get_options()->ConnLimit_-1) {
|
||||
warn_too_many_conns();
|
||||
*socket_error = SOCK_ERRNO(ENOBUFS);
|
||||
return -1;
|
||||
}
|
||||
|
||||
protocol_family = sa->sa_family;
|
||||
|
||||
if (get_options()->DisableNetwork) {
|
||||
/* We should never even try to connect anyplace if DisableNetwork is set.
|
||||
* Warn if we do, and refuse to make the connection. */
|
||||
static ratelim_t disablenet_violated = RATELIM_INIT(30*60);
|
||||
*socket_error = SOCK_ERRNO(ENETUNREACH);
|
||||
log_fn_ratelim(&disablenet_violated, LOG_WARN, LD_BUG,
|
||||
"Tried to open a socket with DisableNetwork set.");
|
||||
tor_fragile_assert();
|
||||
return -1;
|
||||
}
|
||||
|
||||
s = tor_open_socket_nonblocking(protocol_family, SOCK_STREAM, 0);
|
||||
if (! SOCKET_OK(s)) {
|
||||
*socket_error = tor_socket_errno(-1);
|
||||
log_warn(LD_NET,"Error creating network socket: %s",
|
||||
tor_socket_strerror(*socket_error));
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (make_socket_reuseable(s) < 0) {
|
||||
log_warn(LD_NET, "Error setting SO_REUSEADDR flag on new connection: %s",
|
||||
tor_socket_strerror(errno));
|
||||
}
|
||||
|
||||
if (bindaddr && bind(s, bindaddr, bindaddr_len) < 0) {
|
||||
*socket_error = tor_socket_errno(s);
|
||||
log_warn(LD_NET,"Error binding network socket: %s",
|
||||
tor_socket_strerror(*socket_error));
|
||||
tor_close_socket(s);
|
||||
return -1;
|
||||
}
|
||||
|
||||
tor_assert(options);
|
||||
if (options->ConstrainedSockets)
|
||||
set_constrained_socket_buffers(s, (int)options->ConstrainedSockSize);
|
||||
|
||||
if (connect(s, sa, sa_len) < 0) {
|
||||
int e = tor_socket_errno(s);
|
||||
if (!ERRNO_IS_CONN_EINPROGRESS(e)) {
|
||||
/* yuck. kill it. */
|
||||
*socket_error = e;
|
||||
log_info(LD_NET,
|
||||
"connect() to socket failed: %s",
|
||||
tor_socket_strerror(e));
|
||||
tor_close_socket(s);
|
||||
return -1;
|
||||
} else {
|
||||
inprogress = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* it succeeded. we're connected. */
|
||||
log_fn(inprogress ? LOG_DEBUG : LOG_INFO, LD_NET,
|
||||
"Connection to socket %s (sock "TOR_SOCKET_T_FORMAT").",
|
||||
inprogress ? "in progress" : "established", s);
|
||||
conn->s = s;
|
||||
if (connection_add_connecting(conn) < 0) {
|
||||
/* no space, forget it */
|
||||
*socket_error = SOCK_ERRNO(ENOBUFS);
|
||||
return -1;
|
||||
}
|
||||
return inprogress ? 0 : 1;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/** Take conn, make a nonblocking socket; try to connect to
|
||||
* addr:port (they arrive in *host order*). If fail, return -1 and if
|
||||
* applicable put your best guess about errno into *<b>socket_error</b>.
|
||||
@ -1598,49 +1695,19 @@ int
|
||||
connection_connect(connection_t *conn, const char *address,
|
||||
const tor_addr_t *addr, uint16_t port, int *socket_error)
|
||||
{
|
||||
tor_socket_t s;
|
||||
int inprogress = 0;
|
||||
struct sockaddr_storage addrbuf;
|
||||
struct sockaddr_storage bind_addr_ss;
|
||||
struct sockaddr *bind_addr = NULL;
|
||||
struct sockaddr *dest_addr;
|
||||
int dest_addr_len;
|
||||
int dest_addr_len, bind_addr_len = 0;
|
||||
const or_options_t *options = get_options();
|
||||
int protocol_family;
|
||||
|
||||
if (get_n_open_sockets() >= get_options()->ConnLimit_-1) {
|
||||
warn_too_many_conns();
|
||||
*socket_error = SOCK_ERRNO(ENOBUFS);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (tor_addr_family(addr) == AF_INET6)
|
||||
protocol_family = PF_INET6;
|
||||
else
|
||||
protocol_family = PF_INET;
|
||||
|
||||
if (get_options()->DisableNetwork) {
|
||||
/* We should never even try to connect anyplace if DisableNetwork is set.
|
||||
* Warn if we do, and refuse to make the connection. */
|
||||
static ratelim_t disablenet_violated = RATELIM_INIT(30*60);
|
||||
*socket_error = SOCK_ERRNO(ENETUNREACH);
|
||||
log_fn_ratelim(&disablenet_violated, LOG_WARN, LD_BUG,
|
||||
"Tried to open a socket with DisableNetwork set.");
|
||||
tor_fragile_assert();
|
||||
return -1;
|
||||
}
|
||||
|
||||
s = tor_open_socket_nonblocking(protocol_family,SOCK_STREAM,IPPROTO_TCP);
|
||||
if (! SOCKET_OK(s)) {
|
||||
*socket_error = tor_socket_errno(-1);
|
||||
log_warn(LD_NET,"Error creating network socket: %s",
|
||||
tor_socket_strerror(*socket_error));
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (make_socket_reuseable(s) < 0) {
|
||||
log_warn(LD_NET, "Error setting SO_REUSEADDR flag on new connection: %s",
|
||||
tor_socket_strerror(errno));
|
||||
}
|
||||
|
||||
if (!tor_addr_is_loopback(addr)) {
|
||||
const tor_addr_t *ext_addr = NULL;
|
||||
if (protocol_family == AF_INET &&
|
||||
@ -1650,33 +1717,21 @@ connection_connect(connection_t *conn, const char *address,
|
||||
!tor_addr_is_null(&options->OutboundBindAddressIPv6_))
|
||||
ext_addr = &options->OutboundBindAddressIPv6_;
|
||||
if (ext_addr) {
|
||||
struct sockaddr_storage ext_addr_sa;
|
||||
socklen_t ext_addr_len = 0;
|
||||
memset(&ext_addr_sa, 0, sizeof(ext_addr_sa));
|
||||
ext_addr_len = tor_addr_to_sockaddr(ext_addr, 0,
|
||||
(struct sockaddr *) &ext_addr_sa,
|
||||
sizeof(ext_addr_sa));
|
||||
memset(&bind_addr_ss, 0, sizeof(bind_addr_ss));
|
||||
bind_addr_len = tor_addr_to_sockaddr(ext_addr, 0,
|
||||
(struct sockaddr *) &bind_addr_ss,
|
||||
sizeof(bind_addr_ss));
|
||||
if (ext_addr_len == 0) {
|
||||
log_warn(LD_NET,
|
||||
"Error converting OutboundBindAddress %s into sockaddr. "
|
||||
"Ignoring.", fmt_and_decorate_addr(ext_addr));
|
||||
} else {
|
||||
if (bind(s, (struct sockaddr *) &ext_addr_sa, ext_addr_len) < 0) {
|
||||
*socket_error = tor_socket_errno(s);
|
||||
log_warn(LD_NET,"Error binding network socket to %s: %s",
|
||||
fmt_and_decorate_addr(ext_addr),
|
||||
tor_socket_strerror(*socket_error));
|
||||
tor_close_socket(s);
|
||||
return -1;
|
||||
}
|
||||
bind_addr = (struct sockaddr *)&bind_addr_ss;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tor_assert(options);
|
||||
if (options->ConstrainedSockets)
|
||||
set_constrained_socket_buffers(s, (int)options->ConstrainedSockSize);
|
||||
|
||||
memset(&addrbuf,0,sizeof(addrbuf));
|
||||
dest_addr = (struct sockaddr*) &addrbuf;
|
||||
dest_addr_len = tor_addr_to_sockaddr(addr, port, dest_addr, sizeof(addrbuf));
|
||||
@ -1685,36 +1740,51 @@ connection_connect(connection_t *conn, const char *address,
|
||||
log_debug(LD_NET, "Connecting to %s:%u.",
|
||||
escaped_safe_str_client(address), port);
|
||||
|
||||
if (connect(s, dest_addr, (socklen_t)dest_addr_len) < 0) {
|
||||
int e = tor_socket_errno(s);
|
||||
if (!ERRNO_IS_CONN_EINPROGRESS(e)) {
|
||||
/* yuck. kill it. */
|
||||
*socket_error = e;
|
||||
log_info(LD_NET,
|
||||
"connect() to %s:%u failed: %s",
|
||||
escaped_safe_str_client(address),
|
||||
port, tor_socket_strerror(e));
|
||||
tor_close_socket(s);
|
||||
return -1;
|
||||
} else {
|
||||
inprogress = 1;
|
||||
}
|
||||
}
|
||||
return connection_connect_sockaddr(conn, dest_addr, dest_addr_len,
|
||||
bind_addr, bind_addr_len, socket_error);
|
||||
}
|
||||
|
||||
/* it succeeded. we're connected. */
|
||||
log_fn(inprogress?LOG_DEBUG:LOG_INFO, LD_NET,
|
||||
"Connection to %s:%u %s (sock "TOR_SOCKET_T_FORMAT").",
|
||||
escaped_safe_str_client(address),
|
||||
port, inprogress?"in progress":"established", s);
|
||||
conn->s = s;
|
||||
if (connection_add_connecting(conn) < 0) {
|
||||
/* no space, forget it */
|
||||
*socket_error = SOCK_ERRNO(ENOBUFS);
|
||||
#ifdef HAVE_SYS_UN_H
|
||||
|
||||
/** Take conn, make a nonblocking socket; try to connect to
|
||||
* an AF_UNIX socket at socket_path. If fail, return -1 and if applicable
|
||||
* put your best guess about errno into *<b>socket_error</b>. Else assign s
|
||||
* to conn-\>s: if connected return 1, if EAGAIN return 0.
|
||||
*
|
||||
* On success, add conn to the list of polled connections.
|
||||
*/
|
||||
int
|
||||
connection_connect_unix(connection_t *conn, const char *socket_path,
|
||||
int *socket_error)
|
||||
{
|
||||
struct sockaddr_un dest_addr;
|
||||
|
||||
tor_assert(socket_path);
|
||||
|
||||
/* Check that we'll be able to fit it into dest_addr later */
|
||||
if (strlen(socket_path) + 1 > sizeof(dest_addr.sun_path)) {
|
||||
log_warn(LD_NET,
|
||||
"Path %s is too long for an AF_UNIX socket\n",
|
||||
escaped_safe_str_client(socket_path));
|
||||
*socket_error = SOCK_ERRNO(ENAMETOOLONG);
|
||||
return -1;
|
||||
}
|
||||
return inprogress ? 0 : 1;
|
||||
|
||||
memset(&dest_addr, 0, sizeof(dest_addr));
|
||||
dest_addr.sun_family = AF_UNIX;
|
||||
strlcpy(dest_addr.sun_path, socket_path, sizeof(dest_addr.sun_path));
|
||||
|
||||
log_debug(LD_NET,
|
||||
"Connecting to AF_UNIX socket at %s.",
|
||||
escaped_safe_str_client(socket_path));
|
||||
|
||||
return connection_connect_sockaddr(conn,
|
||||
(struct sockaddr *)&dest_addr, sizeof(dest_addr),
|
||||
NULL, 0, socket_error);
|
||||
}
|
||||
|
||||
#endif /* defined(HAVE_SYS_UN_H) */
|
||||
|
||||
/** Convert state number to string representation for logging purposes.
|
||||
*/
|
||||
static const char *
|
||||
|
@ -89,6 +89,13 @@ int connection_connect(connection_t *conn, const char *address,
|
||||
const tor_addr_t *addr,
|
||||
uint16_t port, int *socket_error);
|
||||
|
||||
#ifdef HAVE_SYS_UN_H
|
||||
|
||||
int connection_connect_unix(connection_t *conn, const char *socket_path,
|
||||
int *socket_error);
|
||||
|
||||
#endif /* defined(HAVE_SYS_UN_H) */
|
||||
|
||||
/** Maximum size of information that we can fit into SOCKS5 username
|
||||
or password fields. */
|
||||
#define MAX_SOCKS5_AUTH_FIELD_SIZE 255
|
||||
|
@ -2940,7 +2940,7 @@ connection_exit_connect(edge_connection_t *edge_conn)
|
||||
const tor_addr_t *addr;
|
||||
uint16_t port;
|
||||
connection_t *conn = TO_CONN(edge_conn);
|
||||
int socket_error = 0;
|
||||
int socket_error = 0, result;
|
||||
|
||||
if ( (!connection_edge_is_rendezvous_stream(edge_conn) &&
|
||||
router_compare_to_my_exit_policy(&edge_conn->base_.addr,
|
||||
@ -2955,14 +2955,36 @@ connection_exit_connect(edge_connection_t *edge_conn)
|
||||
return;
|
||||
}
|
||||
|
||||
addr = &conn->addr;
|
||||
port = conn->port;
|
||||
#ifdef HAVE_SYS_UN_H
|
||||
if (conn->socket_family != AF_UNIX) {
|
||||
#else
|
||||
{
|
||||
#endif /* defined(HAVE_SYS_UN_H) */
|
||||
addr = &conn->addr;
|
||||
port = conn->port;
|
||||
|
||||
if (tor_addr_family(addr) == AF_INET6)
|
||||
conn->socket_family = AF_INET6;
|
||||
if (tor_addr_family(addr) == AF_INET6)
|
||||
conn->socket_family = AF_INET6;
|
||||
|
||||
log_debug(LD_EXIT,"about to try connecting");
|
||||
switch (connection_connect(conn, conn->address, addr, port, &socket_error)) {
|
||||
log_debug(LD_EXIT, "about to try connecting");
|
||||
result = connection_connect(conn, conn->address,
|
||||
addr, port, &socket_error);
|
||||
#ifdef HAVE_SYS_UN_H
|
||||
} else {
|
||||
/*
|
||||
* In the AF_UNIX case, we expect to have already had conn->port = 1,
|
||||
* tor_addr_make_unspec(conn->addr) (cf. the way we mark in the incoming
|
||||
* case in connection_handle_listener_read()), and conn->address should
|
||||
* have the socket path to connect to.
|
||||
*/
|
||||
tor_assert(conn->address && strlen(conn->address) > 0);
|
||||
|
||||
log_debug(LD_EXIT, "about to try connecting");
|
||||
result = connection_connect_unix(conn, conn->address, &socket_error);
|
||||
#endif /* defined(HAVE_SYS_UN_H) */
|
||||
}
|
||||
|
||||
switch (result) {
|
||||
case -1: {
|
||||
int reason = errno_to_stream_end_reason(socket_error);
|
||||
connection_edge_end(edge_conn, reason);
|
||||
|
@ -66,9 +66,16 @@ static ssize_t rend_service_parse_intro_for_v3(
|
||||
* a real port on some IP.
|
||||
*/
|
||||
typedef struct rend_service_port_config_t {
|
||||
/* The incoming HS virtual port we're mapping */
|
||||
uint16_t virtual_port;
|
||||
/* Is this an AF_UNIX port? */
|
||||
unsigned int is_unix_addr:1;
|
||||
/* The outgoing TCP port to use, if !is_unix_addr */
|
||||
uint16_t real_port;
|
||||
/* The outgoing IPv4 or IPv6 address to use, if !is_unix_addr */
|
||||
tor_addr_t real_addr;
|
||||
/* The socket path to connect to, if is_unix_addr */
|
||||
char unix_addr[FLEXIBLE_ARRAY_MEMBER];
|
||||
} rend_service_port_config_t;
|
||||
|
||||
/** Try to maintain this many intro points per service by default. */
|
||||
@ -279,16 +286,48 @@ rend_add_service(rend_service_t *service)
|
||||
service->directory);
|
||||
for (i = 0; i < smartlist_len(service->ports); ++i) {
|
||||
p = smartlist_get(service->ports, i);
|
||||
log_debug(LD_REND,"Service maps port %d to %s",
|
||||
p->virtual_port, fmt_addrport(&p->real_addr, p->real_port));
|
||||
if (!(p->is_unix_addr)) {
|
||||
log_debug(LD_REND,
|
||||
"Service maps port %d to %s",
|
||||
p->virtual_port,
|
||||
fmt_addrport(&p->real_addr, p->real_port));
|
||||
} else {
|
||||
#ifdef HAVE_SYS_UN_H
|
||||
log_debug(LD_REND,
|
||||
"Service maps port %d to socket at \"%s\"",
|
||||
p->virtual_port, p->unix_addr);
|
||||
#else
|
||||
log_debug(LD_REND,
|
||||
"Service maps port %d to an AF_UNIX socket, but we "
|
||||
"have no AF_UNIX support on this platform. This is "
|
||||
"probably a bug.",
|
||||
p->virtual_port);
|
||||
#endif /* defined(HAVE_SYS_UN_H) */
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Return a new rend_service_port_config_t with its path set to
|
||||
* <b>socket_path</b> or empty if <b>socket_path</b> is NULL */
|
||||
static rend_service_port_config_t *
|
||||
rend_service_port_config_new(const char *socket_path)
|
||||
{
|
||||
if (!socket_path)
|
||||
return tor_malloc_zero(sizeof(rend_service_port_config_t));
|
||||
|
||||
const size_t pathlen = strlen(socket_path) + 1;
|
||||
rend_service_port_config_t *conf =
|
||||
tor_malloc_zero(sizeof(rend_service_port_config_t) + pathlen);
|
||||
memcpy(conf->unix_addr, socket_path, pathlen);
|
||||
conf->is_unix_addr = 1;
|
||||
return conf;
|
||||
}
|
||||
|
||||
/** Parses a real-port to virtual-port mapping and returns a new
|
||||
* rend_service_port_config_t.
|
||||
*
|
||||
* The format is: VirtualPort (IP|RealPort|IP:RealPort)?
|
||||
* The format is: VirtualPort (IP|RealPort|IP:RealPort|'socket':path)?
|
||||
*
|
||||
* IP defaults to 127.0.0.1; RealPort defaults to VirtualPort.
|
||||
*/
|
||||
@ -302,6 +341,9 @@ parse_port_config(const char *string)
|
||||
tor_addr_t addr;
|
||||
const char *addrport;
|
||||
rend_service_port_config_t *result = NULL;
|
||||
const char *socket_prefix = "socket:";
|
||||
unsigned int is_unix_addr = 0;
|
||||
char *socket_path = NULL;
|
||||
|
||||
sl = smartlist_new();
|
||||
smartlist_split_string(sl, string, " ",
|
||||
@ -324,7 +366,26 @@ parse_port_config(const char *string)
|
||||
tor_addr_from_ipv4h(&addr, 0x7F000001u); /* 127.0.0.1 */
|
||||
} else {
|
||||
addrport = smartlist_get(sl,1);
|
||||
if (strchr(addrport, ':') || strchr(addrport, '.')) {
|
||||
/* If it starts with socket:, try to parse it as a socket path */
|
||||
if (!strcmpstart(addrport, socket_prefix)) {
|
||||
if (strlen(addrport + strlen(socket_prefix)) > 0) {
|
||||
#ifdef HAVE_SYS_UN_H
|
||||
is_unix_addr = 1;
|
||||
socket_path = tor_strdup(addrport + strlen(socket_prefix));
|
||||
#else
|
||||
log_warn(LD_CONFIG,
|
||||
"Hidden service port configuration %s is for an AF_UNIX "
|
||||
"socket, but we have no support available on this platform",
|
||||
escaped(addrport));
|
||||
goto err;
|
||||
#endif /* defined(HAVE_SYS_UN_H) */
|
||||
} else {
|
||||
log_warn(LD_CONFIG,
|
||||
"Empty socket path in hidden service port configuration.");
|
||||
goto err;
|
||||
}
|
||||
} else if (strchr(addrport, ':') || strchr(addrport, '.')) {
|
||||
/* else try it as an IP:port pair if it has a : or . in it */
|
||||
if (tor_addr_port_lookup(addrport, &addr, &p)<0) {
|
||||
log_warn(LD_CONFIG,"Unparseable address in hidden service port "
|
||||
"configuration.");
|
||||
@ -343,13 +404,21 @@ parse_port_config(const char *string)
|
||||
}
|
||||
}
|
||||
|
||||
result = tor_malloc(sizeof(rend_service_port_config_t));
|
||||
/* Allow room for unix_addr */
|
||||
result = rend_service_port_config_new(socket_path);
|
||||
result->virtual_port = virtport;
|
||||
result->real_port = realport;
|
||||
tor_addr_copy(&result->real_addr, &addr);
|
||||
result->is_unix_addr = is_unix_addr;
|
||||
if (!is_unix_addr) {
|
||||
result->real_port = realport;
|
||||
tor_addr_copy(&result->real_addr, &addr);
|
||||
result->unix_addr[0] = '\0';
|
||||
}
|
||||
|
||||
err:
|
||||
SMARTLIST_FOREACH(sl, char *, c, tor_free(c));
|
||||
smartlist_free(sl);
|
||||
if (socket_path) tor_free(socket_path);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -3402,6 +3471,56 @@ rend_service_dump_stats(int severity)
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef HAVE_SYS_UN_H
|
||||
|
||||
/** Given <b>ports</b>, a smarlist containing rend_service_port_config_t,
|
||||
* add the given <b>p</b>, a AF_UNIX port to the list. Return 0 on success
|
||||
* else return -ENOSYS if AF_UNIX is not supported (see function in the
|
||||
* #else statement below). */
|
||||
static int
|
||||
add_unix_port(smartlist_t *ports, rend_service_port_config_t *p)
|
||||
{
|
||||
tor_assert(ports);
|
||||
tor_assert(p);
|
||||
tor_assert(p->is_unix_addr);
|
||||
|
||||
smartlist_add(ports, p);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** Given <b>conn</b> set it to use the given port <b>p</b> values. Return 0
|
||||
* on success else return -ENOSYS if AF_UNIX is not supported (see function
|
||||
* in the #else statement below). */
|
||||
static int
|
||||
set_unix_port(edge_connection_t *conn, rend_service_port_config_t *p)
|
||||
{
|
||||
tor_assert(conn);
|
||||
tor_assert(p);
|
||||
tor_assert(p->is_unix_addr);
|
||||
|
||||
conn->base_.socket_family = AF_UNIX;
|
||||
tor_addr_make_unspec(&conn->base_.addr);
|
||||
conn->base_.port = 1;
|
||||
conn->base_.address = tor_strdup(p->unix_addr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#else /* defined(HAVE_SYS_UN_H) */
|
||||
|
||||
static int
|
||||
set_unix_port(edge_connection_t *conn, rend_service_port_config_t *p)
|
||||
{
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
static int
|
||||
add_unix_port(smartlist_t *ports, rend_service_port_config_t *p)
|
||||
{
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
#endif /* HAVE_SYS_UN_H */
|
||||
|
||||
/** Given <b>conn</b>, a rendezvous exit stream, look up the hidden service for
|
||||
* 'circ', and look up the port and address based on conn-\>port.
|
||||
* Assign the actual conn-\>addr and conn-\>port. Return -2 on failure
|
||||
@ -3416,6 +3535,7 @@ rend_service_set_connection_addr_port(edge_connection_t *conn,
|
||||
char serviceid[REND_SERVICE_ID_LEN_BASE32+1];
|
||||
smartlist_t *matching_ports;
|
||||
rend_service_port_config_t *chosen_port;
|
||||
unsigned int warn_once = 0;
|
||||
|
||||
tor_assert(circ->base_.purpose == CIRCUIT_PURPOSE_S_REND_JOINED);
|
||||
tor_assert(circ->rend_data);
|
||||
@ -3433,19 +3553,45 @@ rend_service_set_connection_addr_port(edge_connection_t *conn,
|
||||
matching_ports = smartlist_new();
|
||||
SMARTLIST_FOREACH(service->ports, rend_service_port_config_t *, p,
|
||||
{
|
||||
if (conn->base_.port == p->virtual_port) {
|
||||
if (conn->base_.port != p->virtual_port) {
|
||||
continue;
|
||||
}
|
||||
if (!(p->is_unix_addr)) {
|
||||
smartlist_add(matching_ports, p);
|
||||
} else {
|
||||
if (add_unix_port(matching_ports, p)) {
|
||||
if (!warn_once) {
|
||||
/* Unix port not supported so warn only once. */
|
||||
log_warn(LD_REND,
|
||||
"Saw AF_UNIX virtual port mapping for port %d on service "
|
||||
"%s, which is unsupported on this platform. Ignoring it.",
|
||||
conn->base_.port, serviceid);
|
||||
}
|
||||
warn_once++;
|
||||
}
|
||||
}
|
||||
});
|
||||
chosen_port = smartlist_choose(matching_ports);
|
||||
smartlist_free(matching_ports);
|
||||
if (chosen_port) {
|
||||
tor_addr_copy(&conn->base_.addr, &chosen_port->real_addr);
|
||||
conn->base_.port = chosen_port->real_port;
|
||||
if (!(chosen_port->is_unix_addr)) {
|
||||
/* Get a non-AF_UNIX connection ready for connection_exit_connect() */
|
||||
tor_addr_copy(&conn->base_.addr, &chosen_port->real_addr);
|
||||
conn->base_.port = chosen_port->real_port;
|
||||
} else {
|
||||
if (set_unix_port(conn, chosen_port)) {
|
||||
/* Simply impossible to end up here else we were able to add a Unix
|
||||
* port without AF_UNIX support... ? */
|
||||
tor_assert(0);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
log_info(LD_REND, "No virtual port mapping exists for port %d on service %s",
|
||||
conn->base_.port,serviceid);
|
||||
|
||||
log_info(LD_REND,
|
||||
"No virtual port mapping exists for port %d on service %s",
|
||||
conn->base_.port, serviceid);
|
||||
|
||||
if (service->allow_unknown_ports)
|
||||
return -1;
|
||||
else
|
||||
|
Loading…
Reference in New Issue
Block a user