|
@@ -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,8 +286,24 @@ 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) */
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
}
|
|
@@ -345,6 +368,8 @@ parse_port_config(const char *string)
|
|
|
|
|
|
result = tor_malloc(sizeof(rend_service_port_config_t));
|
|
|
result->virtual_port = virtport;
|
|
|
+ /* TODO actually support AF_UNIX here */
|
|
|
+ result->is_unix_addr = 0;
|
|
|
result->real_port = realport;
|
|
|
tor_addr_copy(&result->real_addr, &addr);
|
|
|
err:
|
|
@@ -3416,6 +3441,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;
|
|
|
+ int unix_addrs;
|
|
|
|
|
|
tor_assert(circ->base_.purpose == CIRCUIT_PURPOSE_S_REND_JOINED);
|
|
|
tor_assert(circ->rend_data);
|
|
@@ -3431,10 +3457,19 @@ rend_service_set_connection_addr_port(edge_connection_t *conn,
|
|
|
return -2;
|
|
|
}
|
|
|
matching_ports = smartlist_new();
|
|
|
+ unix_addrs = 0;
|
|
|
SMARTLIST_FOREACH(service->ports, rend_service_port_config_t *, p,
|
|
|
{
|
|
|
+ /*
|
|
|
+ * TODO don't just ignore AF_UNIX ports, but set up edge_connection_t
|
|
|
+ * properly to use them.
|
|
|
+ */
|
|
|
if (conn->base_.port == p->virtual_port) {
|
|
|
- smartlist_add(matching_ports, p);
|
|
|
+ if (!(p->is_unix_addr)) {
|
|
|
+ smartlist_add(matching_ports, p);
|
|
|
+ } else {
|
|
|
+ ++unix_addrs;
|
|
|
+ }
|
|
|
}
|
|
|
});
|
|
|
chosen_port = smartlist_choose(matching_ports);
|
|
@@ -3444,8 +3479,23 @@ rend_service_set_connection_addr_port(edge_connection_t *conn,
|
|
|
conn->base_.port = chosen_port->real_port;
|
|
|
return 0;
|
|
|
}
|
|
|
- log_info(LD_REND, "No virtual port mapping exists for port %d on service %s",
|
|
|
- conn->base_.port,serviceid);
|
|
|
+ if (!unix_addrs) {
|
|
|
+ log_info(LD_REND,
|
|
|
+ "No virtual port mapping exists for port %d on service %s",
|
|
|
+ conn->base_.port, serviceid);
|
|
|
+ } else {
|
|
|
+#ifdef HAVE_SYS_UN_H
|
|
|
+ log_info(LD_REND,
|
|
|
+ "Only AF_UNIX virtual port mappings exists for port %d "
|
|
|
+ "on service %s, and support is not yet implemented",
|
|
|
+ conn->base_.port, serviceid);
|
|
|
+#else
|
|
|
+ log_info(LD_REND,
|
|
|
+ "Only AF_UNIX virtual port mappings exists for port %d "
|
|
|
+ "on service %s, and support is not available on this platform",
|
|
|
+ conn->base_.port, serviceid);
|
|
|
+#endif /* defined(HAVE_SYS_UN_H) */
|
|
|
+ }
|
|
|
if (service->allow_unknown_ports)
|
|
|
return -1;
|
|
|
else
|