summaryrefslogtreecommitdiff
path: root/src/common/address.c
diff options
context:
space:
mode:
authorteor (Tim Wilson-Brown) <teor2345@gmail.com>2015-09-16 09:09:54 +1000
committerteor (Tim Wilson-Brown) <teor2345@gmail.com>2015-09-16 09:09:54 +1000
commita659a3fced83ddb2586cade138f6fa1376d1402d (patch)
treea9ff0d82f7859a5f7c237ff86766d820478f2e97 /src/common/address.c
parentfd85f2cd706fe86499962f2364f99daa220186a8 (diff)
parenteb1759e63cccc9fb870dfb2f87b21ce1e6d4df2d (diff)
downloadtor-a659a3fced83ddb2586cade138f6fa1376d1402d.tar.gz
tor-a659a3fced83ddb2586cade138f6fa1376d1402d.zip
Merge branch 'bug17027-reject-private-all-interfaces-v2' into bug16069-bug17027
src/test/test_policy.c: Merged calls to policies_parse_exit_policy by adding additional arguments. fixup to remaining instance of ~EXIT_POLICY_IPV6_ENABLED. Compacting logic test now produces previous list length of 4, corrected this. src/config/torrc.sample.in: src/config/torrc.minimal.in-staging: Merged torrc modification dates in favour of latest.
Diffstat (limited to 'src/common/address.c')
-rw-r--r--src/common/address.c114
1 files changed, 91 insertions, 23 deletions
diff --git a/src/common/address.c b/src/common/address.c
index 066355373a..163db59ac4 100644
--- a/src/common/address.c
+++ b/src/common/address.c
@@ -1527,7 +1527,7 @@ get_interface_addresses_raw(int severity)
}
/** Return true iff <b>a</b> is a multicast address. */
-static int
+STATIC int
tor_addr_is_multicast(const tor_addr_t *a)
{
sa_family_t family = tor_addr_family(a);
@@ -1617,43 +1617,108 @@ get_interface_address6_via_udp_socket_hack(int severity,
return r;
}
-/** Set *<b>addr</b> to the IP address (if any) of whatever interface
- * connects to the Internet. This address should only be used in checking
- * whether our address has changed. Return 0 on success, -1 on failure.
+/** Set *<b>addr</b> to an arbitrary IP address (if any) of an interface that
+ * connects to the Internet. Prefer public IP addresses to internal IP
+ * addresses. This address should only be used in checking whether our
+ * address has changed, as it may be an internal IP address. Return 0 on
+ * success, -1 on failure.
+ * Prefer get_interface_address6_list for a list of all addresses on all
+ * interfaces which connect to the Internet.
*/
MOCK_IMPL(int,
get_interface_address6,(int severity, sa_family_t family, tor_addr_t *addr))
{
- /* XXX really, this function should yield a smartlist of addresses. */
smartlist_t *addrs;
+ int rv = -1;
tor_assert(addr);
+ /* Get a list of public or internal IPs in arbitrary order */
+ addrs = get_interface_address6_list(severity, family, 1);
+
+ /* Find the first non-internal address, or the last internal address
+ * Ideally, we want the default route, see #12377 for details */
+ SMARTLIST_FOREACH_BEGIN(addrs, tor_addr_t *, a) {
+ tor_addr_copy(addr, a);
+ rv = 0;
+
+ /* If we found a non-internal address, declare success. Otherwise,
+ * keep looking. */
+ if (!tor_addr_is_internal(a, 0))
+ break;
+ } SMARTLIST_FOREACH_END(a);
+
+ free_interface_address6_list(addrs);
+ return rv;
+}
+
+/** Free a smartlist of IP addresses returned by get_interface_address6_list.
+ */
+void
+free_interface_address6_list(smartlist_t *addrs)
+{
+ SMARTLIST_FOREACH(addrs, tor_addr_t *, a, tor_free(a));
+ smartlist_free(addrs);
+}
+
+/** Return a smartlist of the IP addresses of type family from all interfaces
+ * on the server. Excludes loopback and multicast addresses. Only includes
+ * internal addresses if include_internal is true. (Note that a relay behind
+ * NAT may use an internal address to connect to the Internet.)
+ * An empty smartlist means that there are no addresses of the selected type
+ * matching these criteria.
+ * Returns NULL on failure.
+ * Use free_interface_address6_list to free the returned list.
+ */
+MOCK_IMPL(smartlist_t *,get_interface_address6_list,(int severity,
+ sa_family_t family,
+ int include_internal))
+{
+ smartlist_t *addrs;
+ tor_addr_t addr;
+
/* Try to do this the smart way if possible. */
if ((addrs = get_interface_addresses_raw(severity))) {
- int rv = -1;
- SMARTLIST_FOREACH_BEGIN(addrs, tor_addr_t *, a) {
- if (family != AF_UNSPEC && family != tor_addr_family(a))
+ SMARTLIST_FOREACH_BEGIN(addrs, tor_addr_t *, a)
+ {
+ if (family != AF_UNSPEC && family != tor_addr_family(a)) {
+ SMARTLIST_DEL_CURRENT(addrs, a);
+ tor_free(a);
continue;
+ }
+
if (tor_addr_is_loopback(a) ||
- tor_addr_is_multicast(a))
+ tor_addr_is_multicast(a)) {
+ SMARTLIST_DEL_CURRENT(addrs, a);
+ tor_free(a);
continue;
+ }
- tor_addr_copy(addr, a);
- rv = 0;
-
- /* If we found a non-internal address, declare success. Otherwise,
- * keep looking. */
- if (!tor_addr_is_internal(a, 0))
- break;
+ if (!include_internal && tor_addr_is_internal(a, 0)) {
+ SMARTLIST_DEL_CURRENT(addrs, a);
+ tor_free(a);
+ continue;
+ }
} SMARTLIST_FOREACH_END(a);
+ }
+
+ if (addrs && smartlist_len(addrs) > 0) {
+ return addrs;
+ }
- SMARTLIST_FOREACH(addrs, tor_addr_t *, a, tor_free(a));
+ /* if we removed all entries as unsuitable */
+ if (addrs) {
smartlist_free(addrs);
- return rv;
}
/* Okay, the smart way is out. */
- return get_interface_address6_via_udp_socket_hack(severity,family,addr);
+ get_interface_address6_via_udp_socket_hack(severity,family,&addr);
+ if (!include_internal && tor_addr_is_internal(&addr, 0)) {
+ return smartlist_new();
+ } else {
+ addrs = smartlist_new();
+ smartlist_add(addrs, tor_dup_addr(&addr));
+ return addrs;
+ }
}
/* ======
@@ -1895,10 +1960,13 @@ tor_dup_ip(uint32_t addr)
}
/**
- * Set *<b>addr</b> to the host-order IPv4 address (if any) of whatever
- * interface connects to the Internet. This address should only be used in
- * checking whether our address has changed. Return 0 on success, -1 on
- * failure.
+ * Set *<b>addr</b> to a host-order IPv4 address (if any) of an
+ * interface that connects to the Internet. Prefer public IP addresses to
+ * internal IP addresses. This address should only be used in checking
+ * whether our address has changed, as it may be an internal IPv4 address.
+ * Return 0 on success, -1 on failure.
+ * Prefer get_interface_address_list6 for a list of all IPv4 and IPv6
+ * addresses on all interfaces which connect to the Internet.
*/
MOCK_IMPL(int,
get_interface_address,(int severity, uint32_t *addr))