|
@@ -6898,6 +6898,22 @@ parse_ports(or_options_t *options, int validate_only,
|
|
|
return retval;
|
|
|
}
|
|
|
|
|
|
+
|
|
|
+static int port_binds_ipv4(const port_cfg_t *port)
|
|
|
+{
|
|
|
+ return tor_addr_family(&port->addr) == AF_INET ||
|
|
|
+ (tor_addr_family(&port->addr) == AF_UNSPEC
|
|
|
+ && !port->server_cfg.bind_ipv6_only);
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+static int port_binds_ipv6(const port_cfg_t *port)
|
|
|
+{
|
|
|
+ return tor_addr_family(&port->addr) == AF_INET6 ||
|
|
|
+ (tor_addr_family(&port->addr) == AF_UNSPEC
|
|
|
+ && !port->server_cfg.bind_ipv4_only);
|
|
|
+}
|
|
|
+
|
|
|
|
|
|
* consistency and warn as appropriate. Set *<b>n_low_ports_out</b> to the
|
|
|
* number of sub-1024 ports we will be binding. */
|
|
@@ -6923,9 +6939,7 @@ check_server_ports(const smartlist_t *ports,
|
|
|
} else if (port->type == CONN_TYPE_OR_LISTENER) {
|
|
|
if (! port->server_cfg.no_advertise) {
|
|
|
++n_orport_advertised;
|
|
|
- if (tor_addr_family(&port->addr) == AF_INET ||
|
|
|
- (tor_addr_family(&port->addr) == AF_UNSPEC &&
|
|
|
- !port->server_cfg.bind_ipv6_only))
|
|
|
+ if (port_binds_ipv4(port))
|
|
|
++n_orport_advertised_ipv4;
|
|
|
}
|
|
|
if (! port->server_cfg.no_listen)
|
|
@@ -7059,19 +7073,20 @@ get_first_listener_addrport_string(int listener_type)
|
|
|
}
|
|
|
|
|
|
|
|
|
- <b>address_family</b>. */
|
|
|
+ * <b>address_family</b>. Returns 0 when no port is found, and when passed
|
|
|
+ * AF_UNSPEC. */
|
|
|
int
|
|
|
get_first_advertised_port_by_type_af(int listener_type, int address_family)
|
|
|
{
|
|
|
+ if (address_family == AF_UNSPEC)
|
|
|
+ return 0;
|
|
|
+
|
|
|
const smartlist_t *conf_ports = get_configured_ports();
|
|
|
SMARTLIST_FOREACH_BEGIN(conf_ports, const port_cfg_t *, cfg) {
|
|
|
if (cfg->type == listener_type &&
|
|
|
- !cfg->server_cfg.no_advertise &&
|
|
|
- (tor_addr_family(&cfg->addr) == address_family ||
|
|
|
- tor_addr_family(&cfg->addr) == AF_UNSPEC)) {
|
|
|
- if (tor_addr_family(&cfg->addr) != AF_UNSPEC ||
|
|
|
- (address_family == AF_INET && !cfg->server_cfg.bind_ipv6_only) ||
|
|
|
- (address_family == AF_INET6 && !cfg->server_cfg.bind_ipv4_only)) {
|
|
|
+ !cfg->server_cfg.no_advertise) {
|
|
|
+ if ((address_family == AF_INET && port_binds_ipv4(cfg)) ||
|
|
|
+ (address_family == AF_INET6 && port_binds_ipv6(cfg))) {
|
|
|
return cfg->port;
|
|
|
}
|
|
|
}
|
|
@@ -7079,6 +7094,87 @@ get_first_advertised_port_by_type_af(int listener_type, int address_family)
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
+
|
|
|
+ * <b>address_family</b>. Returns NULL if there is no advertised address,
|
|
|
+ * and when passed AF_UNSPEC. */
|
|
|
+const tor_addr_t *
|
|
|
+get_first_advertised_addr_by_type_af(int listener_type, int address_family)
|
|
|
+{
|
|
|
+ if (address_family == AF_UNSPEC)
|
|
|
+ return NULL;
|
|
|
+ if (!configured_ports)
|
|
|
+ return NULL;
|
|
|
+ SMARTLIST_FOREACH_BEGIN(configured_ports, const port_cfg_t *, cfg) {
|
|
|
+ if (cfg->type == listener_type &&
|
|
|
+ !cfg->server_cfg.no_advertise) {
|
|
|
+ if ((address_family == AF_INET && port_binds_ipv4(cfg)) ||
|
|
|
+ (address_family == AF_INET6 && port_binds_ipv6(cfg))) {
|
|
|
+ return &cfg->addr;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } SMARTLIST_FOREACH_END(cfg);
|
|
|
+ return NULL;
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+ * <b>port</b>. If <b>check_wildcard</b> is true, INADDR[6]_ANY and AF_UNSPEC
|
|
|
+ * addresses match any address of the appropriate family; and port -1 matches
|
|
|
+ * any port.
|
|
|
+ * To match auto ports, pass CFG_PORT_AUTO. (Does not match on the actual
|
|
|
+ * automatically chosen listener ports.) */
|
|
|
+int
|
|
|
+port_exists_by_type_addr_port(int listener_type, const tor_addr_t *addr,
|
|
|
+ int port, int check_wildcard)
|
|
|
+{
|
|
|
+ if (!configured_ports || !addr)
|
|
|
+ return 0;
|
|
|
+ SMARTLIST_FOREACH_BEGIN(configured_ports, const port_cfg_t *, cfg) {
|
|
|
+ if (cfg->type == listener_type) {
|
|
|
+ if (cfg->port == port || (check_wildcard && port == -1)) {
|
|
|
+
|
|
|
+ if (tor_addr_eq(&cfg->addr, addr)) {
|
|
|
+ return 1;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!check_wildcard) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ const int cfg_v4 = port_binds_ipv4(cfg);
|
|
|
+ const int cfg_any_v4 = tor_addr_is_null(&cfg->addr) && cfg_v4;
|
|
|
+ const int addr_v4 = tor_addr_family(addr) == AF_INET ||
|
|
|
+ tor_addr_family(addr) == AF_UNSPEC;
|
|
|
+ const int addr_any_v4 = tor_addr_is_null(&cfg->addr) && addr_v4;
|
|
|
+ if ((cfg_any_v4 && addr_v4) || (cfg_v4 && addr_any_v4)) {
|
|
|
+ return 1;
|
|
|
+ }
|
|
|
+
|
|
|
+ const int cfg_v6 = port_binds_ipv6(cfg);
|
|
|
+ const int cfg_any_v6 = tor_addr_is_null(&cfg->addr) && cfg_v6;
|
|
|
+ const int addr_v6 = tor_addr_family(addr) == AF_INET6 ||
|
|
|
+ tor_addr_family(addr) == AF_UNSPEC;
|
|
|
+ const int addr_any_v6 = tor_addr_is_null(&cfg->addr) && addr_v6;
|
|
|
+ if ((cfg_any_v6 && addr_v6) || (cfg_v6 && addr_any_v6)) {
|
|
|
+ return 1;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } SMARTLIST_FOREACH_END(cfg);
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+ * instead. */
|
|
|
+int
|
|
|
+port_exists_by_type_addr32h_port(int listener_type, uint32_t addr_ipv4h,
|
|
|
+ int port, int check_wildcard)
|
|
|
+{
|
|
|
+ tor_addr_t ipv4;
|
|
|
+ tor_addr_from_ipv4h(&ipv4, addr_ipv4h);
|
|
|
+ return port_exists_by_type_addr_port(listener_type, &ipv4, port,
|
|
|
+ check_wildcard);
|
|
|
+}
|
|
|
+
|
|
|
|
|
|
* absent. Return 0 on success, -1 on failure. */
|
|
|
static int
|