diff --git a/changes/bug19677 b/changes/bug19677
new file mode 100644
index 0000000000..e8ba3dd61a
--- /dev/null
+++ b/changes/bug19677
@@ -0,0 +1,6 @@
+ o Minor bug fixes (option parsing):
+ - Count unix sockets when counting client listeners (SOCKS, Trans,
+ NATD, and DNS). This has no user-visible behaviour changes: these
+ options are set once, and never read.
+ Required for correct behaviour in ticket #17178.
+ Fixes bug #19677, patch by teor.
diff --git a/src/or/config.c b/src/or/config.c
index 98b32708c6..136958c6aa 100644
--- a/src/or/config.c
+++ b/src/or/config.c
@@ -6739,14 +6739,17 @@ parse_port_config(smartlist_t *out,
}
/** Return the number of ports which are actually going to listen with type
- * listenertype. Do not count no_listen ports. Do not count unix
- * sockets. */
+ * listenertype. Do not count no_listen ports. Only count unix
+ * sockets if count_sockets is true. */
static int
-count_real_listeners(const smartlist_t *ports, int listenertype)
+count_real_listeners(const smartlist_t *ports, int listenertype,
+ int count_sockets)
{
int n = 0;
SMARTLIST_FOREACH_BEGIN(ports, port_cfg_t *, port) {
- if (port->server_cfg.no_listen || port->is_unix_addr)
+ if (port->server_cfg.no_listen)
+ continue;
+ if (!count_sockets && port->is_unix_addr)
continue;
if (port->type != listenertype)
continue;
@@ -6755,9 +6758,8 @@ count_real_listeners(const smartlist_t *ports, int listenertype)
return n;
}
-/** Parse all client port types (Socks, DNS, Trans, NATD) from
- * options. On success, set *n_ports_out to the number
- * of ports that are listed, update the *Port_set values in
+/** Parse all ports from options. On success, set *n_ports_out
+ * to the number of ports that are listed, update the *Port_set values in
* options, and return 0. On failure, set *msg to a
* description of the problem and return -1.
*
@@ -6883,21 +6885,22 @@ parse_ports(or_options_t *options, int validate_only,
/* Update the *Port_set options. The !! here is to force a boolean out of
an integer. */
options->ORPort_set =
- !! count_real_listeners(ports, CONN_TYPE_OR_LISTENER);
+ !! count_real_listeners(ports, CONN_TYPE_OR_LISTENER, 0);
options->SocksPort_set =
- !! count_real_listeners(ports, CONN_TYPE_AP_LISTENER);
+ !! count_real_listeners(ports, CONN_TYPE_AP_LISTENER, 1);
options->TransPort_set =
- !! count_real_listeners(ports, CONN_TYPE_AP_TRANS_LISTENER);
+ !! count_real_listeners(ports, CONN_TYPE_AP_TRANS_LISTENER, 1);
options->NATDPort_set =
- !! count_real_listeners(ports, CONN_TYPE_AP_NATD_LISTENER);
+ !! count_real_listeners(ports, CONN_TYPE_AP_NATD_LISTENER, 1);
+ /* Use options->ControlSocket to test if a control socket is set */
options->ControlPort_set =
- !! count_real_listeners(ports, CONN_TYPE_CONTROL_LISTENER);
+ !! count_real_listeners(ports, CONN_TYPE_CONTROL_LISTENER, 0);
options->DirPort_set =
- !! count_real_listeners(ports, CONN_TYPE_DIR_LISTENER);
+ !! count_real_listeners(ports, CONN_TYPE_DIR_LISTENER, 0);
options->DNSPort_set =
- !! count_real_listeners(ports, CONN_TYPE_AP_DNS_LISTENER);
+ !! count_real_listeners(ports, CONN_TYPE_AP_DNS_LISTENER, 1);
options->ExtORPort_set =
- !! count_real_listeners(ports, CONN_TYPE_EXT_OR_LISTENER);
+ !! count_real_listeners(ports, CONN_TYPE_EXT_OR_LISTENER, 0);
if (world_writable_control_socket) {
SMARTLIST_FOREACH(ports, port_cfg_t *, p,
diff --git a/src/or/or.h b/src/or/or.h
index 34089ad994..574f184a13 100644
--- a/src/or/or.h
+++ b/src/or/or.h
@@ -3604,9 +3604,13 @@ typedef struct {
/** @name port booleans
*
- * Derived booleans: True iff there is a non-listener port on an AF_INET or
- * AF_INET6 address of the given type configured in one of the _lines
- * options above.
+ * Derived booleans: For server ports and ControlPort, true iff there is a
+ * non-listener port on an AF_INET or AF_INET6 address of the given type
+ * configured in one of the _lines options above.
+ * For client ports, also true if there is a unix socket configured.
+ * If you are checking for client ports, you may want to use:
+ * SocksPort_set || TransPort_set || NATDPort_set || DNSPort_set
+ * rather than SocksPort_set.
*
* @{
*/