[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]
[tor-commits] [tor/master] addr: Refactor find_my_address() to simplify it
commit 59f5c3d26337ba82be2a7cb2af02ba77e02c1b87
Author: David Goulet <dgoulet@xxxxxxxxxxxxxx>
Date: Wed Jun 24 10:35:27 2020 -0400
addr: Refactor find_my_address() to simplify it
Instead of a complex if/else block, use a table of functions that have the
same interface and each of them attempt to find the address one after the
other.
Pointed out by nickm's during review.
Signed-off-by: David Goulet <dgoulet@xxxxxxxxxxxxxx>
---
src/app/config/resolve_addr.c | 177 +++++++++++++++++++++++-------------------
1 file changed, 99 insertions(+), 78 deletions(-)
diff --git a/src/app/config/resolve_addr.c b/src/app/config/resolve_addr.c
index dada4dabf..cd19402f9 100644
--- a/src/app/config/resolve_addr.c
+++ b/src/app/config/resolve_addr.c
@@ -22,19 +22,6 @@
/** Maximum "Address" statement allowed in our configuration. */
#define MAX_CONFIG_ADDRESS 2
-/** Errors use when finding our IP address. Some are transient and some are
- * persistent, just attach semantic to the values. They are all negative so
- * one can do a catch all. */
-
-#define ERR_FAIL_RESOLVE -1 /* Hostname resolution failed. */
-#define ERR_GET_HOSTNAME -2 /* Unable to get local hostname. */
-#define ERR_NO_OPT_ADDRESS -3 /* No Address in config. */
-#define ERR_TOO_MANY_ADDRESS -4 /* Too many Address for one family. */
-#define ERR_GET_INTERFACE -5 /* Unable to query network interface. */
-#define ERR_UNUSABLE_ADDRESS -6 /* Unusable address. It is internal. */
-#define ERR_DEFAULT_DIRAUTH -7 /* Using default authorities. */
-#define ERR_ADDRESS_IS_INTERNAL -8 /* IP is internal. */
-
/** Ease our life. Arrays containing state per address family. These are to
* add semantic to the code so we know what is accessed. */
#define IDX_NULL 0 /* Index to zeroed address object. */
@@ -42,6 +29,18 @@
#define IDX_IPV6 2 /* Index to AF_INET6. */
#define IDX_SIZE 3 /* How many indexes do we have. */
+/** Function in our address function table return one of these code. */
+typedef enum {
+ /* The address has been found. */
+ FN_RET_OK = 0,
+ /* The failure requirements were not met and thus it is recommended that the
+ * caller stops the search. */
+ FN_RET_BAIL = 1,
+ /* The address was not found or failure is transient so the caller should go
+ * to the next method. */
+ FN_RET_NEXT = 2,
+} fn_address_ret_t;
+
/** Last resolved addresses. */
static tor_addr_t last_resolved_addrs[IDX_SIZE];
@@ -80,6 +79,11 @@ resolved_addr_reset_last(int family)
tor_addr_make_null(&last_resolved_addrs[af_to_idx(family)], family);
}
+/** Errors returned by address_can_be_used() in order for the caller to know
+ * why the address is denied or not. */
+#define ERR_DEFAULT_DIRAUTH -1 /* Using default authorities. */
+#define ERR_ADDRESS_IS_INTERNAL -2 /* IP is internal. */
+
/** @brief Return true iff the given IP address can be used as a valid
* external resolved address.
*
@@ -151,11 +155,12 @@ address_can_be_used(const tor_addr_t *addr, const or_options_t *options,
* @return Return 0 on success that is an address has been found or resolved
* successfully. Return error code ERR_* found at the top of the file.
*/
-static int
+static fn_address_ret_t
get_address_from_config(const or_options_t *options, int warn_severity,
int family, const char **method_out,
char **hostname_out, tor_addr_t *addr_out)
{
+ int ret;
bool explicit_ip = false;
int num_valid_addr = 0;
@@ -172,7 +177,8 @@ get_address_from_config(const or_options_t *options, int warn_severity,
if (!options->Address) {
log_info(LD_CONFIG, "No Address option found in configuration.");
- return ERR_NO_OPT_ADDRESS;
+ /* No Address statement, inform caller to try next method. */
+ return FN_RET_NEXT;
}
for (const config_line_t *cfg = options->Address; cfg != NULL;
@@ -199,11 +205,10 @@ get_address_from_config(const or_options_t *options, int warn_severity,
num_valid_addr++;
continue;
} else {
- /* If we have hostname we are unable to resolve, it is an persistent
- * error and thus we stop right away. */
+ /* Hostname that can't be resolved, this is a fatal error. */
log_fn(warn_severity, LD_CONFIG,
"Could not resolve local Address '%s'. Failing.", cfg->value);
- return ERR_FAIL_RESOLVE;
+ return FN_RET_BAIL;
}
}
@@ -211,18 +216,32 @@ get_address_from_config(const or_options_t *options, int warn_severity,
log_fn(warn_severity, LD_CONFIG,
"No Address option found for family %s in configuration.",
fmt_af_family(family));
- return ERR_NO_OPT_ADDRESS;
+ /* No Address statement for family, inform caller to try next method. */
+ return FN_RET_NEXT;
}
if (num_valid_addr >= MAX_CONFIG_ADDRESS) {
+ /* Too many Address for same family. This is a fatal error. */
log_fn(warn_severity, LD_CONFIG,
"Found %d Address statement of address family %s. "
"Only one is allowed.", num_valid_addr, fmt_af_family(family));
- return ERR_TOO_MANY_ADDRESS;
+ return FN_RET_BAIL;
}
/* Great, we found an address. */
- return address_can_be_used(addr_out, options, warn_severity, explicit_ip);
+ ret = address_can_be_used(addr_out, options, warn_severity, explicit_ip);
+ if (ret != 0) {
+ /* One of the requirement of this interface is if an internal Address is
+ * used, custom authorities must be defined else it is a fatal error.
+ * Furthermore, if the Address was resolved to an internal interface, we
+ * stop immediately. */
+ return FN_RET_BAIL;
+ }
+
+ /* Address can be used. We are done. */
+ log_fn(warn_severity, LD_CONFIG, "Address found in configuration: %s",
+ fmt_addr(addr_out));
+ return FN_RET_OK;
}
/** @brief Get IP address from the local hostname by calling gethostbyname()
@@ -240,7 +259,7 @@ get_address_from_config(const or_options_t *options, int warn_severity,
* @return Return 0 on success that is an address has been found and resolved
* successfully. Return error code ERR_* found at the top of the file.
*/
-static int
+static fn_address_ret_t
get_address_from_hostname(const or_options_t *options, int warn_severity,
int family, const char **method_out,
char **hostname_out, tor_addr_t *addr_out)
@@ -259,24 +278,33 @@ get_address_from_hostname(const or_options_t *options, int warn_severity,
if (tor_gethostname(hostname, sizeof(hostname)) < 0) {
log_fn(warn_severity, LD_NET, "Error obtaining local hostname");
- return ERR_GET_HOSTNAME;
+ /* Unable to obtain the local hostname is a fatal error. */
+ return FN_RET_BAIL;
}
if (tor_addr_lookup(hostname, family, addr_out)) {
log_fn(warn_severity, LD_NET,
"Could not resolve local hostname '%s'. Failing.", hostname);
- return ERR_FAIL_RESOLVE;
+ /* Unable to resolve, inform caller to try next method. */
+ return FN_RET_NEXT;
}
ret = address_can_be_used(addr_out, options, warn_severity, false);
- if (ret < 0) {
- return ret;
+ if (ret == ERR_DEFAULT_DIRAUTH) {
+ /* Non custom authorities, inform caller to try next method. */
+ return FN_RET_NEXT;
+ } else if (ret == ERR_ADDRESS_IS_INTERNAL) {
+ /* Internal address is a fatal error. */
+ return FN_RET_BAIL;
}
/* addr_out contains the address of the local hostname. */
*method_out = "GETHOSTNAME";
*hostname_out = tor_strdup(hostname);
- return 0;
+ /* Found it! */
+ log_fn(warn_severity, LD_CONFIG, "Address found from local hostname: %s",
+ fmt_addr(addr_out));
+ return FN_RET_OK;
}
/** @brief Get IP address from a network interface.
@@ -286,40 +314,49 @@ get_address_from_hostname(const or_options_t *options, int warn_severity,
* @param family IP address family. Only AF_INET and AF_INET6 are supported.
* @param method_out OUT: Always "INTERFACE" on success which is detailed in
* the control-spec.txt as actions for "STATUS_SERVER".
+ * @param hostname_out OUT: String containing the local hostname. For this
+ * function, it is always set to NULL.
* @param addr_out OUT: Tor address found attached to the interface.
*
* @return Return 0 on success that is an address has been found. Return
* error code ERR_* found at the top of the file.
*/
-static int
+static fn_address_ret_t
get_address_from_interface(const or_options_t *options, int warn_severity,
int family, const char **method_out,
- tor_addr_t *addr_out)
+ char **hostname_out, tor_addr_t *addr_out)
{
int ret;
tor_assert(method_out);
+ tor_assert(hostname_out);
tor_assert(addr_out);
/* Set them to NULL for safety reasons. */
*method_out = NULL;
+ *hostname_out = NULL;
log_debug(LD_CONFIG, "Attempting to get address from network interface");
if (get_interface_address6(warn_severity, family, addr_out) < 0) {
log_fn(warn_severity, LD_CONFIG,
"Could not get local interface IP address.");
- return ERR_GET_INTERFACE;
+ /* Unable to get IP from interface. Inform caller to try next method. */
+ return FN_RET_NEXT;
}
ret = address_can_be_used(addr_out, options, warn_severity, false);
if (ret < 0) {
- return ret;
+ /* Unable to use address. Inform caller to try next method. */
+ return FN_RET_NEXT;
}
*method_out = "INTERFACE";
- return 0;
+ /* Found it! */
+ log_fn(warn_severity, LD_CONFIG, "Address found from interface: %s",
+ fmt_addr(addr_out));
+ return FN_RET_OK;
}
/** @brief Update the last resolved address cache using the given address.
@@ -393,6 +430,21 @@ update_resolved_cache(const tor_addr_t *addr, const char *method_used,
*done_one_resolve = true;
}
+/** Address discovery function table. The order matters as in the first one is
+ * executed first and so on. */
+static fn_address_ret_t
+ (*fn_address_table[])(
+ const or_options_t *options, int warn_severity, int family,
+ const char **method_out, char **hostname_out, tor_addr_t *addr_out) =
+{
+ /* These functions are in order for our find address algorithm. */
+ get_address_from_config,
+ get_address_from_hostname,
+ get_address_from_interface,
+};
+/** Length of address table as in how many functions. */
+static const size_t fn_address_table_len = ARRAY_LENGTH(fn_address_table);
+
/** @brief Attempt to find our IP address that can be used as our external
* reachable address.
*
@@ -465,8 +517,7 @@ find_my_address(const or_options_t *options, int family, int warn_severity,
tor_addr_t *addr_out, const char **method_out,
char **hostname_out)
{
- int ret;
- const char *method_used;
+ const char *method_used = NULL;
char *hostname_used = NULL;
tor_addr_t my_addr;
@@ -481,51 +532,24 @@ find_my_address(const or_options_t *options, int family, int warn_severity,
* Step 1: Discover address by attempting 3 different methods consecutively.
*/
- /* Attempt #1: Get address from configuration. */
- ret = get_address_from_config(options, warn_severity, family, &method_used,
- &hostname_used, &my_addr);
- if (ret == 0) {
- log_fn(warn_severity, LD_CONFIG, "Address found in configuration: %s",
- fmt_addr(&my_addr));
- } else {
- /* Unable to resolve an Address statement is a failure. Also, using
- * default dirauth error means that the configured address is internal
- * which is only accepted if custom authorities are used. */
- if (ret == ERR_FAIL_RESOLVE || ret == ERR_DEFAULT_DIRAUTH) {
+ /* Go over the function table. They are in order. */
+ for (size_t idx = 0; idx < fn_address_table_len; idx++) {
+ fn_address_ret_t ret = fn_address_table[idx](options, warn_severity,
+ family, &method_used,
+ &hostname_used, &my_addr);
+ if (ret == FN_RET_BAIL) {
return false;
+ } else if (ret == FN_RET_OK) {
+ goto found;
}
-
- /* Attempt #2: Get local hostname and resolve it. */
- ret = get_address_from_hostname(options, warn_severity, family,
- &method_used, &hostname_used, &my_addr);
- if (ret == 0) {
- log_fn(warn_severity, LD_CONFIG, "Address found from local hostname: "
- "%s", fmt_addr(&my_addr));
- } else if (ret < 0) {
- /* Unable to get the hostname results in a failure. If the address is
- * internal, we stop right away. */
- if (ret == ERR_GET_HOSTNAME || ret == ERR_ADDRESS_IS_INTERNAL) {
- return false;
- }
-
- /* Attempt #3: Get address from interface. */
- ret = get_address_from_interface(options, warn_severity, family,
- &method_used, &my_addr);
- if (ret == 0) {
- log_fn(warn_severity, LD_CONFIG, "Address found from interface: %s",
- fmt_addr(&my_addr));
- } else {
- /* We've exhausted our attempts. Failure. */
- log_fn(warn_severity, LD_CONFIG, "Unable to find our IP address.");
- return false;
- }
- }
+ tor_assert(ret == FN_RET_NEXT);
}
- tor_assert(method_used);
- /* From here, my_addr is a valid IP address of "family" and can be used as
- * our external IP address. */
+ /* We've exhausted our attempts. Failure. */
+ log_fn(warn_severity, LD_CONFIG, "Unable to find our IP address.");
+ return false;
+ found:
/*
* Step 2: Update last resolved address cache and inform the control port.
*/
@@ -535,10 +559,7 @@ find_my_address(const or_options_t *options, int family, int warn_severity,
*method_out = method_used;
}
if (hostname_out) {
- *hostname_out = NULL;
- if (hostname_used) {
- *hostname_out = hostname_used;
- }
+ *hostname_out = hostname_used;
} else {
tor_free(hostname_used);
}
_______________________________________________
tor-commits mailing list
tor-commits@xxxxxxxxxxxxxxxxxxxx
https://lists.torproject.org/cgi-bin/mailman/listinfo/tor-commits