summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/common/address.c27
-rw-r--r--src/common/address.h8
-rw-r--r--src/common/compat_libevent.c35
-rw-r--r--src/common/compat_libevent.h37
-rw-r--r--src/common/container.c24
-rw-r--r--src/common/log.c17
-rw-r--r--src/common/torlog.h3
-rw-r--r--src/config/torrc.minimal.in-staging20
-rw-r--r--src/config/torrc.sample.in20
-rw-r--r--src/or/config.c9
-rw-r--r--src/or/control.c43
-rw-r--r--src/or/control.h3
-rw-r--r--src/or/include.am4
-rw-r--r--src/or/main.c3
-rw-r--r--src/or/or.h1
-rw-r--r--src/or/rendcache.c137
-rw-r--r--src/or/rendcache.h11
-rw-r--r--src/or/rendcommon.c7
-rw-r--r--src/or/rendservice.c150
-rw-r--r--src/or/routerset.c6
-rw-r--r--src/test/include.am4
-rw-r--r--src/test/log_test_helpers.c111
-rw-r--r--src/test/log_test_helpers.h31
-rw-r--r--src/test/test.c10
-rw-r--r--src/test/test_address.c95
-rwxr-xr-xsrc/test/test_bt.sh1
-rw-r--r--src/test/test_bt_cl.c11
-rw-r--r--src/test/test_compat_libevent.c238
-rw-r--r--src/test/test_routerset.c102
-rw-r--r--src/test/test_util_format.c238
-rw-r--r--src/trunnel/README10
-rw-r--r--src/trunnel/include.am4
32 files changed, 1255 insertions, 165 deletions
diff --git a/src/common/address.c b/src/common/address.c
index 163db59ac4..cfa8fd1dca 100644
--- a/src/common/address.c
+++ b/src/common/address.c
@@ -1506,8 +1506,8 @@ get_interface_addresses_ioctl(int severity)
* Return a new smartlist of tor_addr_t on success, and NULL on failure.
* (An empty smartlist indicates that we successfully learned that we have no
* addresses.) Log failure messages at <b>severity</b>. */
-STATIC smartlist_t *
-get_interface_addresses_raw(int severity)
+MOCK_IMPL(smartlist_t *,
+get_interface_addresses_raw,(int severity))
{
smartlist_t *result = NULL;
#if defined(HAVE_IFADDRS_TO_SMARTLIST)
@@ -1547,10 +1547,10 @@ tor_addr_is_multicast(const tor_addr_t *a)
* UDP socket trickery. Only look for address of given <b>family</b>.
* Set result to *<b>addr</b>. Return 0 on success, -1 on failure.
*/
-STATIC int
-get_interface_address6_via_udp_socket_hack(int severity,
- sa_family_t family,
- tor_addr_t *addr)
+MOCK_IMPL(int,
+get_interface_address6_via_udp_socket_hack,(int severity,
+ sa_family_t family,
+ tor_addr_t *addr))
{
struct sockaddr_storage my_addr, target_addr;
int sock=-1, r=-1;
@@ -1614,6 +1614,8 @@ get_interface_address6_via_udp_socket_hack(int severity,
err:
if (sock >= 0)
tor_close_socket(sock);
+ if (r == -1)
+ memset(addr, 0, sizeof(tor_addr_t));
return r;
}
@@ -1632,6 +1634,8 @@ get_interface_address6,(int severity, sa_family_t family, tor_addr_t *addr))
int rv = -1;
tor_assert(addr);
+ memset(addr, 0, sizeof(tor_addr_t));
+
/* Get a list of public or internal IPs in arbitrary order */
addrs = get_interface_address6_list(severity, family, 1);
@@ -1656,8 +1660,10 @@ get_interface_address6,(int severity, sa_family_t family, tor_addr_t *addr))
void
free_interface_address6_list(smartlist_t *addrs)
{
- SMARTLIST_FOREACH(addrs, tor_addr_t *, a, tor_free(a));
- smartlist_free(addrs);
+ if (addrs != NULL) {
+ 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
@@ -1711,7 +1717,8 @@ MOCK_IMPL(smartlist_t *,get_interface_address6_list,(int severity,
}
/* Okay, the smart way is out. */
- get_interface_address6_via_udp_socket_hack(severity,family,&addr);
+ if (get_interface_address6_via_udp_socket_hack(severity,family,&addr))
+ return smartlist_new();
if (!include_internal && tor_addr_is_internal(&addr, 0)) {
return smartlist_new();
} else {
@@ -1974,6 +1981,8 @@ get_interface_address,(int severity, uint32_t *addr))
tor_addr_t local_addr;
int r;
+ memset(addr, 0, sizeof(uint32_t));
+
r = get_interface_address6(severity, AF_INET, &local_addr);
if (r>=0)
*addr = tor_addr_to_ipv4h(&local_addr);
diff --git a/src/common/address.h b/src/common/address.h
index 7d49fb59bc..d2841e1c9d 100644
--- a/src/common/address.h
+++ b/src/common/address.h
@@ -310,11 +310,11 @@ get_interface_address_list(int severity, int include_internal)
tor_addr_port_t *tor_addr_port_new(const tor_addr_t *addr, uint16_t port);
#ifdef ADDRESS_PRIVATE
-STATIC smartlist_t *get_interface_addresses_raw(int severity);
+MOCK_DECL(smartlist_t *,get_interface_addresses_raw,(int severity));
STATIC int tor_addr_is_multicast(const tor_addr_t *a);
-STATIC int get_interface_address6_via_udp_socket_hack(int severity,
- sa_family_t family,
- tor_addr_t *addr);
+MOCK_DECL(int,get_interface_address6_via_udp_socket_hack,(int severity,
+ sa_family_t family,
+ tor_addr_t *addr));
#ifdef HAVE_IFADDRS_TO_SMARTLIST
STATIC smartlist_t *ifaddrs_to_smartlist(const struct ifaddrs *ifa);
diff --git a/src/common/compat_libevent.c b/src/common/compat_libevent.c
index a366b6c9c6..29e5c5f63c 100644
--- a/src/common/compat_libevent.c
+++ b/src/common/compat_libevent.c
@@ -11,6 +11,7 @@
#include "orconfig.h"
#include "compat.h"
+#define COMPAT_LIBEVENT_PRIVATE
#include "compat_libevent.h"
#include "crypto.h"
@@ -28,39 +29,11 @@
#include <event.h>
#endif
-/** A number representing a version of Libevent.
-
- This is a 4-byte number, with the first three bytes representing the
- major, minor, and patchlevel respectively of the library. The fourth
- byte is unused.
-
- This is equivalent to the format of LIBEVENT_VERSION_NUMBER on Libevent
- 2.0.1 or later. For versions of Libevent before 1.4.0, which followed the
- format of "1.0, 1.0a, 1.0b", we define 1.0 to be equivalent to 1.0.0, 1.0a
- to be equivalent to 1.0.1, and so on.
-*/
-typedef uint32_t le_version_t;
-
-/** @{ */
-/** Macros: returns the number of a libevent version as a le_version_t */
-#define V(major, minor, patch) \
- (((major) << 24) | ((minor) << 16) | ((patch) << 8))
-#define V_OLD(major, minor, patch) \
- V((major), (minor), (patch)-'a'+1)
-/** @} */
-
-/** Represetns a version of libevent so old we can't figure out what version
- * it is. */
-#define LE_OLD V(0,0,0)
-/** Represents a version of libevent so weird we can't figure out what version
- * it is. */
-#define LE_OTHER V(0,0,99)
-
/** A string which, if it appears in a libevent log, should be ignored. */
static const char *suppress_msg = NULL;
/** Callback function passed to event_set_log() so we can intercept
* log messages from libevent. */
-static void
+STATIC void
libevent_logging_callback(int severity, const char *msg)
{
char buf[1024];
@@ -291,7 +264,7 @@ tor_libevent_get_method(void)
/** Return the le_version_t for the version of libevent specified in the
* string <b>v</b>. If the version is very new or uses an unrecognized
* version, format, return LE_OTHER. */
-static le_version_t
+STATIC le_version_t
tor_decode_libevent_version(const char *v)
{
unsigned major, minor, patchlevel;
@@ -322,7 +295,7 @@ tor_decode_libevent_version(const char *v)
* Two different versions with different numbers are sure not to be binary
* compatible. Two different versions with the same numbers have a decent
* chance of binary compatibility.*/
-static int
+STATIC int
le_versions_compatibility(le_version_t v)
{
if (v == LE_OTHER)
diff --git a/src/common/compat_libevent.h b/src/common/compat_libevent.h
index 39181efb7b..8ee02c0b6d 100644
--- a/src/common/compat_libevent.h
+++ b/src/common/compat_libevent.h
@@ -91,5 +91,42 @@ void tor_gettimeofday_cache_set(const struct timeval *tv);
#endif
void tor_gettimeofday_cached_monotonic(struct timeval *tv);
+#ifdef COMPAT_LIBEVENT_PRIVATE
+/** A number representing a version of Libevent.
+
+ This is a 4-byte number, with the first three bytes representing the
+ major, minor, and patchlevel respectively of the library. The fourth
+ byte is unused.
+
+ This is equivalent to the format of LIBEVENT_VERSION_NUMBER on Libevent
+ 2.0.1 or later. For versions of Libevent before 1.4.0, which followed the
+ format of "1.0, 1.0a, 1.0b", we define 1.0 to be equivalent to 1.0.0, 1.0a
+ to be equivalent to 1.0.1, and so on.
+*/
+typedef uint32_t le_version_t;
+
+/** @{ */
+/** Macros: returns the number of a libevent version as a le_version_t */
+#define V(major, minor, patch) \
+ (((major) << 24) | ((minor) << 16) | ((patch) << 8))
+#define V_OLD(major, minor, patch) \
+ V((major), (minor), (patch)-'a'+1)
+/** @} */
+
+/** Represetns a version of libevent so old we can't figure out what version
+ * it is. */
+#define LE_OLD V(0,0,0)
+/** Represents a version of libevent so weird we can't figure out what version
+ * it is. */
+#define LE_OTHER V(0,0,99)
+
+STATIC void
+libevent_logging_callback(int severity, const char *msg);
+STATIC le_version_t
+tor_decode_libevent_version(const char *v);
+STATIC int
+le_versions_compatibility(le_version_t v);
+#endif
+
#endif
diff --git a/src/common/container.c b/src/common/container.c
index 636dfb6c57..c6f059170e 100644
--- a/src/common/container.c
+++ b/src/common/container.c
@@ -55,6 +55,7 @@ smartlist_free,(smartlist_t *sl))
void
smartlist_clear(smartlist_t *sl)
{
+ memset(sl->list, 0, sizeof(void *) * sl->num_used);
sl->num_used = 0;
}
@@ -82,9 +83,11 @@ smartlist_ensure_capacity(smartlist_t *sl, int size)
while (size > higher)
higher *= 2;
}
- sl->capacity = higher;
sl->list = tor_reallocarray(sl->list, sizeof(void *),
- ((size_t)sl->capacity));
+ ((size_t)higher));
+ memset(sl->list + sl->capacity, 0,
+ sizeof(void *) * (higher - sl->capacity));
+ sl->capacity = higher;
}
#undef ASSERT_CAPACITY
#undef MAX_CAPACITY
@@ -123,6 +126,7 @@ smartlist_remove(smartlist_t *sl, const void *element)
if (sl->list[i] == element) {
sl->list[i] = sl->list[--sl->num_used]; /* swap with the end */
i--; /* so we process the new i'th element */
+ sl->list[sl->num_used] = NULL;
}
}
@@ -132,9 +136,11 @@ void *
smartlist_pop_last(smartlist_t *sl)
{
tor_assert(sl);
- if (sl->num_used)
- return sl->list[--sl->num_used];
- else
+ if (sl->num_used) {
+ void *tmp = sl->list[--sl->num_used];
+ sl->list[sl->num_used] = NULL;
+ return tmp;
+ } else
return NULL;
}
@@ -165,6 +171,7 @@ smartlist_string_remove(smartlist_t *sl, const char *element)
tor_free(sl->list[i]);
sl->list[i] = sl->list[--sl->num_used]; /* swap with the end */
i--; /* so we process the new i'th element */
+ sl->list[sl->num_used] = NULL;
}
}
}
@@ -321,6 +328,7 @@ smartlist_intersect(smartlist_t *sl1, const smartlist_t *sl2)
if (!smartlist_contains(sl2, sl1->list[i])) {
sl1->list[i] = sl1->list[--sl1->num_used]; /* swap with the end */
i--; /* so we process the new i'th element */
+ sl1->list[sl1->num_used] = NULL;
}
}
@@ -345,6 +353,7 @@ smartlist_del(smartlist_t *sl, int idx)
tor_assert(idx>=0);
tor_assert(idx < sl->num_used);
sl->list[idx] = sl->list[--sl->num_used];
+ sl->list[sl->num_used] = NULL;
}
/** Remove the <b>idx</b>th element of sl; if idx is not the last element,
@@ -360,6 +369,7 @@ smartlist_del_keeporder(smartlist_t *sl, int idx)
--sl->num_used;
if (idx < sl->num_used)
memmove(sl->list+idx, sl->list+idx+1, sizeof(void*)*(sl->num_used-idx));
+ sl->list[sl->num_used] = NULL;
}
/** Insert the value <b>val</b> as the new <b>idx</b>th element of
@@ -937,9 +947,11 @@ smartlist_pqueue_pop(smartlist_t *sl,
*IDXP(top)=-1;
if (--sl->num_used) {
sl->list[0] = sl->list[sl->num_used];
+ sl->list[sl->num_used] = NULL;
UPDATE_IDX(0);
smartlist_heapify(sl, compare, idx_field_offset, 0);
}
+ sl->list[sl->num_used] = NULL;
return top;
}
@@ -959,9 +971,11 @@ smartlist_pqueue_remove(smartlist_t *sl,
--sl->num_used;
*IDXP(item) = -1;
if (idx == sl->num_used) {
+ sl->list[sl->num_used] = NULL;
return;
} else {
sl->list[idx] = sl->list[sl->num_used];
+ sl->list[sl->num_used] = NULL;
UPDATE_IDX(idx);
smartlist_heapify(sl, compare, idx_field_offset, idx);
}
diff --git a/src/common/log.c b/src/common/log.c
index e23691b6ab..7ede6100a2 100644
--- a/src/common/log.c
+++ b/src/common/log.c
@@ -1097,14 +1097,25 @@ add_file_log(const log_severity_list_t *severity, const char *filename,
#ifdef HAVE_SYSLOG_H
/**
* Add a log handler to send messages to they system log facility.
+ *
+ * If this is the first log handler, opens syslog with ident Tor or
+ * Tor-<syslog_identity_tag> if that is not NULL.
*/
int
-add_syslog_log(const log_severity_list_t *severity)
+add_syslog_log(const log_severity_list_t *severity,
+ const char* syslog_identity_tag)
{
logfile_t *lf;
- if (syslog_count++ == 0)
+ if (syslog_count++ == 0) {
/* This is the first syslog. */
- openlog("Tor", LOG_PID | LOG_NDELAY, LOGFACILITY);
+ static char buf[256];
+ if (syslog_identity_tag) {
+ tor_snprintf(buf, sizeof(buf), "Tor-%s", syslog_identity_tag);
+ } else {
+ tor_snprintf(buf, sizeof(buf), "Tor");
+ }
+ openlog(buf, LOG_PID | LOG_NDELAY, LOGFACILITY);
+ }
lf = tor_malloc_zero(sizeof(logfile_t));
lf->fd = -1;
diff --git a/src/common/torlog.h b/src/common/torlog.h
index 67edf14c04..722d595ee0 100644
--- a/src/common/torlog.h
+++ b/src/common/torlog.h
@@ -135,7 +135,8 @@ void add_stream_log(const log_severity_list_t *severity, const char *name,
int add_file_log(const log_severity_list_t *severity, const char *filename,
const int truncate);
#ifdef HAVE_SYSLOG_H
-int add_syslog_log(const log_severity_list_t *severity);
+int add_syslog_log(const log_severity_list_t *severity,
+ const char* syslog_identity_tag);
#endif
int add_callback_log(const log_severity_list_t *severity, log_callback cb);
void logs_set_domain_logging(int enabled);
diff --git a/src/config/torrc.minimal.in-staging b/src/config/torrc.minimal.in-staging
index ff324a96da..248cb5cf02 100644
--- a/src/config/torrc.minimal.in-staging
+++ b/src/config/torrc.minimal.in-staging
@@ -12,20 +12,20 @@
## Tor will look for this file in various places based on your platform:
## https://www.torproject.org/docs/faq#torrc
-## Tor opens a socks proxy on port 9050 by default -- even if you don't
-## configure one below. Set "SocksPort 0" if you plan to run Tor only
+## Tor opens a SOCKS proxy on port 9050 by default -- even if you don't
+## configure one below. Set "SOCKSPort 0" if you plan to run Tor only
## as a relay, and not make any local application connections yourself.
-#SocksPort 9050 # Default: Bind to localhost:9050 for local connections.
-#SocksPort 192.168.0.1:9100 # Bind to this address:port too.
+#SOCKSPort 9050 # Default: Bind to localhost:9050 for local connections.
+#SOCKSPort 192.168.0.1:9100 # Bind to this address:port too.
## Entry policies to allow/deny SOCKS requests based on IP address.
-## First entry that matches wins. If no SocksPolicy is set, we accept
-## all (and only) requests that reach a SocksPort. Untrusted users who
-## can access your SocksPort may be able to learn about the connections
+## First entry that matches wins. If no SOCKSPolicy is set, we accept
+## all (and only) requests that reach a SOCKSPort. Untrusted users who
+## can access your SOCKSPort may be able to learn about the connections
## you make.
-#SocksPolicy accept 192.168.0.0/16
-#SocksPolicy accept6 FC00::/7
-#SocksPolicy reject *
+#SOCKSPolicy accept 192.168.0.0/16
+#SOCKSPolicy accept6 FC00::/7
+#SOCKSPolicy reject *
## Logs go to stdout at level "notice" unless redirected by something
## else, like one of the below lines. You can have as many Log lines as
diff --git a/src/config/torrc.sample.in b/src/config/torrc.sample.in
index ff324a96da..248cb5cf02 100644
--- a/src/config/torrc.sample.in
+++ b/src/config/torrc.sample.in
@@ -12,20 +12,20 @@
## Tor will look for this file in various places based on your platform:
## https://www.torproject.org/docs/faq#torrc
-## Tor opens a socks proxy on port 9050 by default -- even if you don't
-## configure one below. Set "SocksPort 0" if you plan to run Tor only
+## Tor opens a SOCKS proxy on port 9050 by default -- even if you don't
+## configure one below. Set "SOCKSPort 0" if you plan to run Tor only
## as a relay, and not make any local application connections yourself.
-#SocksPort 9050 # Default: Bind to localhost:9050 for local connections.
-#SocksPort 192.168.0.1:9100 # Bind to this address:port too.
+#SOCKSPort 9050 # Default: Bind to localhost:9050 for local connections.
+#SOCKSPort 192.168.0.1:9100 # Bind to this address:port too.
## Entry policies to allow/deny SOCKS requests based on IP address.
-## First entry that matches wins. If no SocksPolicy is set, we accept
-## all (and only) requests that reach a SocksPort. Untrusted users who
-## can access your SocksPort may be able to learn about the connections
+## First entry that matches wins. If no SOCKSPolicy is set, we accept
+## all (and only) requests that reach a SOCKSPort. Untrusted users who
+## can access your SOCKSPort may be able to learn about the connections
## you make.
-#SocksPolicy accept 192.168.0.0/16
-#SocksPolicy accept6 FC00::/7
-#SocksPolicy reject *
+#SOCKSPolicy accept 192.168.0.0/16
+#SOCKSPolicy accept6 FC00::/7
+#SOCKSPolicy reject *
## Logs go to stdout at level "notice" unless redirected by something
## else, like one of the below lines. You can have as many Log lines as
diff --git a/src/or/config.c b/src/or/config.c
index fa860af337..f8fc757a2a 100644
--- a/src/or/config.c
+++ b/src/or/config.c
@@ -312,6 +312,7 @@ static config_var_t option_vars_[] = {
V(LogMessageDomains, BOOL, "0"),
V(LogTimeGranularity, MSEC_INTERVAL, "1 second"),
V(TruncateLogFile, BOOL, "0"),
+ V(SyslogIdentityTag, STRING, NULL),
V(LongLivedPorts, CSV,
"21,22,706,1863,5050,5190,5222,5223,6523,6667,6697,8300"),
VAR("MapAddress", LINELIST, AddressMap, NULL),
@@ -3996,6 +3997,12 @@ options_transition_allowed(const or_options_t *old,
return -1;
}
+ if (!opt_streq(old->SyslogIdentityTag, new_val->SyslogIdentityTag)) {
+ *msg = tor_strdup("While Tor is running, changing "
+ "SyslogIdentityTag is not allowed.");
+ return -1;
+ }
+
if ((old->HardwareAccel != new_val->HardwareAccel)
|| !opt_streq(old->AccelName, new_val->AccelName)
|| !opt_streq(old->AccelDir, new_val->AccelDir)) {
@@ -4937,7 +4944,7 @@ options_init_logs(const or_options_t *old_options, or_options_t *options,
!strcasecmp(smartlist_get(elts,0), "syslog")) {
#ifdef HAVE_SYSLOG_H
if (!validate_only) {
- add_syslog_log(severity);
+ add_syslog_log(severity, options->SyslogIdentityTag);
}
#else
log_warn(LD_CONFIG, "Syslog is not supported on this system. Sorry.");
diff --git a/src/or/control.c b/src/or/control.c
index 220e7e514f..7d72342293 100644
--- a/src/or/control.c
+++ b/src/or/control.c
@@ -1927,6 +1927,22 @@ getinfo_helper_dir(control_connection_t *control_conn,
*errmsg = "Not found in cache";
return -1;
}
+ } else if (!strcmpstart(question, "hs/service/desc/id/")) {
+ rend_cache_entry_t *e = NULL;
+
+ question += strlen("hs/service/desc/id/");
+ if (strlen(question) != REND_SERVICE_ID_LEN_BASE32) {
+ *errmsg = "Invalid address";
+ return -1;
+ }
+
+ if (!rend_cache_lookup_v2_desc_as_service(question, &e)) {
+ /* Descriptor found in cache */
+ *answer = tor_strdup(e->desc);
+ } else {
+ *errmsg = "Not found in cache";
+ return -1;
+ }
} else if (!strcmpstart(question, "md/id/")) {
const node_t *node = node_get_by_hex_id(question+strlen("md/id/"));
const microdesc_t *md = NULL;
@@ -2481,6 +2497,8 @@ static const getinfo_item_t getinfo_items[] = {
PREFIX("extra-info/digest/", dir, "Extra-info documents by digest."),
PREFIX("hs/client/desc/id", dir,
"Hidden Service descriptor in client's cache by onion."),
+ PREFIX("hs/service/desc/id/", dir,
+ "Hidden Service descriptor in services's cache by onion."),
PREFIX("net/listeners/", listeners, "Bound addresses by type"),
ITEM("ns/all", networkstatus,
"Brief summary of router status (v2 directory format)"),
@@ -6233,6 +6251,31 @@ get_desc_id_from_query(const rend_data_t *rend_data, const char *hsdir_fp)
return desc_id;
}
+/** send HS_DESC CREATED event when a local service generates a descriptor.
+ *
+ * <b>service_id</b> is the descriptor onion address.
+ * <b>desc_id_base32</b> is the descriptor ID.
+ * <b>replica</b> is the the descriptor replica number.
+ */
+void
+control_event_hs_descriptor_created(const char *service_id,
+ const char *desc_id_base32,
+ int replica)
+{
+ if (!service_id || !desc_id_base32) {
+ log_warn(LD_BUG, "Called with service_digest==%p, "
+ "desc_id_base32==%p", service_id, desc_id_base32);
+ return;
+ }
+
+ send_control_event(EVENT_HS_DESC,
+ "650 HS_DESC CREATED %s UNKNOWN UNKNOWN %s "
+ "REPLICA=%d\r\n",
+ service_id,
+ desc_id_base32,
+ replica);
+}
+
/** send HS_DESC upload event.
*
* <b>service_id</b> is the descriptor onion address.
diff --git a/src/or/control.h b/src/or/control.h
index fdf7903cb8..1f8e2bcdc6 100644
--- a/src/or/control.h
+++ b/src/or/control.h
@@ -117,6 +117,9 @@ MOCK_DECL(const char *, node_describe_longname_by_id,(const char *id_digest));
void control_event_hs_descriptor_requested(const rend_data_t *rend_query,
const char *desc_id_base32,
const char *hs_dir);
+void control_event_hs_descriptor_created(const char *service_id,
+ const char *desc_id_base32,
+ int replica);
void control_event_hs_descriptor_upload(const char *service_id,
const char *desc_id_base32,
const char *hs_dir);
diff --git a/src/or/include.am b/src/or/include.am
index 7b12b56eb1..d0e955f495 100644
--- a/src/or/include.am
+++ b/src/or/include.am
@@ -123,9 +123,9 @@ src_or_tor_cov_LDADD = src/or/libtor-testing.a src/common/libor-testing.a \
src/common/libor-event-testing.a src/trunnel/libor-trunnel-testing.a \
@TOR_ZLIB_LIBS@ @TOR_LIB_MATH@ @TOR_LIBEVENT_LIBS@ @TOR_OPENSSL_LIBS@ \
@TOR_LIB_WS32@ @TOR_LIB_GDI@ @CURVE25519_LIBS@ @TOR_SYSTEMD_LIBS@
-export TESTING_TOR_BINARY = $(top_builddir)/src/or/tor-cov
+export TESTING_TOR_BINARY=$(top_builddir)/src/or/tor-cov
else
-export TESTING_TOR_BINARY = $(top_builddir)/src/or/tor
+export TESTING_TOR_BINARY=$(top_builddir)/src/or/tor
endif
ORHEADERS = \
diff --git a/src/or/main.c b/src/or/main.c
index 693d13cd13..8f4c239567 100644
--- a/src/or/main.c
+++ b/src/or/main.c
@@ -1518,7 +1518,8 @@ run_scheduled_events(time_t now)
/* Remove old information from rephist and the rend cache. */
if (time_to.clean_caches < now) {
rep_history_clean(now - options->RephistTrackTime);
- rend_cache_clean(now);
+ rend_cache_clean(now, REND_CACHE_TYPE_CLIENT);
+ rend_cache_clean(now, REND_CACHE_TYPE_SERVICE);
rend_cache_clean_v2_descs_as_dir(now, 0);
microdesc_cache_rebuild(NULL, 0);
#define CLEAN_CACHES_INTERVAL (30*60)
diff --git a/src/or/or.h b/src/or/or.h
index 4496cbcec3..a80cd55b53 100644
--- a/src/or/or.h
+++ b/src/or/or.h
@@ -3424,6 +3424,7 @@ typedef struct {
* each log message occurs? */
int TruncateLogFile; /**< Boolean: Should we truncate the log file
before we start writing? */
+ char *SyslogIdentityTag; /**< Identity tag to add for syslog logging. */
char *DebugLogFile; /**< Where to send verbose log messages. */
char *DataDirectory; /**< OR only: where to store long-term data. */
diff --git a/src/or/rendcache.c b/src/or/rendcache.c
index 542d322c79..3d3beb0138 100644
--- a/src/or/rendcache.c
+++ b/src/or/rendcache.c
@@ -3,7 +3,7 @@
/**
* \file rendcache.c
- * \brief Hidden service desriptor cache.
+ * \brief Hidden service descriptor cache.
**/
#include "rendcache.h"
@@ -17,6 +17,9 @@
* rend_cache_entry_t. */
static strmap_t *rend_cache = NULL;
+/** Map from service id to rend_cache_entry_t; only for hidden services. */
+static strmap_t *rend_cache_local_service = NULL;
+
/** Map from descriptor id to rend_cache_entry_t; only for hidden service
* directories. */
static digestmap_t *rend_cache_v2_dir = NULL;
@@ -58,6 +61,7 @@ rend_cache_init(void)
{
rend_cache = strmap_new();
rend_cache_v2_dir = digestmap_new();
+ rend_cache_local_service = strmap_new();
rend_cache_failure = strmap_new();
}
@@ -218,9 +222,11 @@ rend_cache_free_all(void)
{
strmap_free(rend_cache, rend_cache_entry_free_);
digestmap_free(rend_cache_v2_dir, rend_cache_entry_free_);
+ strmap_free(rend_cache_local_service, rend_cache_entry_free_);
strmap_free(rend_cache_failure, rend_cache_failure_entry_free_);
rend_cache = NULL;
rend_cache_v2_dir = NULL;
+ rend_cache_local_service = NULL;
rend_cache_failure = NULL;
rend_cache_total_allocation = 0;
}
@@ -254,24 +260,33 @@ rend_cache_failure_clean(time_t now)
} STRMAP_FOREACH_END;
}
-/** Removes all old entries from the service descriptor cache.
+/** Removes all old entries from the client or service descriptor cache.
*/
void
-rend_cache_clean(time_t now)
+rend_cache_clean(time_t now, rend_cache_type_t cache_type)
{
strmap_iter_t *iter;
const char *key;
void *val;
rend_cache_entry_t *ent;
time_t cutoff = now - REND_CACHE_MAX_AGE - REND_CACHE_MAX_SKEW;
- for (iter = strmap_iter_init(rend_cache); !strmap_iter_done(iter); ) {
+ strmap_t *cache = NULL;
+
+ if (cache_type == REND_CACHE_TYPE_CLIENT) {
+ cache = rend_cache;
+ } else if (cache_type == REND_CACHE_TYPE_SERVICE) {
+ cache = rend_cache_local_service;
+ }
+ tor_assert(cache);
+
+ for (iter = strmap_iter_init(cache); !strmap_iter_done(iter); ) {
strmap_iter_get(iter, &key, &val);
ent = (rend_cache_entry_t*)val;
if (ent->parsed->timestamp < cutoff) {
- iter = strmap_iter_next_rmv(rend_cache, iter);
+ iter = strmap_iter_next_rmv(cache, iter);
rend_cache_entry_free(ent);
} else {
- iter = strmap_iter_next(rend_cache, iter);
+ iter = strmap_iter_next(cache, iter);
}
}
}
@@ -527,6 +542,42 @@ rend_cache_lookup_entry(const char *query, int version, rend_cache_entry_t **e)
return ret;
}
+/*
+ * Lookup the v2 service descriptor with the service ID <b>query</b> in the
+ * local service descriptor cache. Return 0 if found and if <b>e</b> is
+ * non NULL, set it with the entry found. Else, a negative value is returned
+ * and <b>e</b> is untouched.
+ * -EINVAL means that <b>query</b> is not a valid service id.
+ * -ENOENT means that no entry in the cache was found. */
+int
+rend_cache_lookup_v2_desc_as_service(const char *query, rend_cache_entry_t **e)
+{
+ int ret = 0;
+ rend_cache_entry_t *entry = NULL;
+
+ tor_assert(rend_cache_local_service);
+ tor_assert(query);
+
+ if (!rend_valid_service_id(query)) {
+ ret = -EINVAL;
+ goto end;
+ }
+
+ /* Lookup descriptor and return. */
+ entry = strmap_get_lc(rend_cache_local_service, query);
+ if (!entry) {
+ ret = -ENOENT;
+ goto end;
+ }
+
+ if (e) {
+ *e = entry;
+ }
+
+ end:
+ return ret;
+}
+
/** Lookup the v2 service descriptor with base32-encoded <b>desc_id</b> and
* copy the pointer to it to *<b>desc</b>. Return 1 on success, 0 on
* well-formed-but-not-found, and -1 on failure.
@@ -679,6 +730,80 @@ rend_cache_store_v2_desc_as_dir(const char *desc)
return RCS_OKAY;
}
+/** Parse the v2 service descriptor in <b>desc</b> and store it to the
+* local service rend cache. Don't attempt to decrypt the included list of
+* introduction points.
+*
+* If we have a newer descriptor with the same ID, ignore this one.
+* If we have an older descriptor with the same ID, replace it.
+*
+* Return an appropriate rend_cache_store_status_t.
+*/
+rend_cache_store_status_t
+rend_cache_store_v2_desc_as_service(const char *desc)
+{
+ rend_service_descriptor_t *parsed = NULL;
+ char desc_id[DIGEST_LEN];
+ char *intro_content = NULL;
+ size_t intro_size;
+ size_t encoded_size;
+ const char *next_desc;
+ char service_id[REND_SERVICE_ID_LEN_BASE32+1];
+ rend_cache_entry_t *e;
+ rend_cache_store_status_t retval = RCS_BADDESC;
+ tor_assert(rend_cache_local_service);
+ tor_assert(desc);
+
+ /* Parse the descriptor. */
+ if (rend_parse_v2_service_descriptor(&parsed, desc_id, &intro_content,
+ &intro_size, &encoded_size,
+ &next_desc, desc, 0) < 0) {
+ log_warn(LD_REND, "Could not parse descriptor.");
+ goto err;
+ }
+ /* Compute service ID from public key. */
+ if (rend_get_service_id(parsed->pk, service_id)<0) {
+ log_warn(LD_REND, "Couldn't compute service ID.");
+ goto err;
+ }
+
+ /* Do we already have a newer descriptor? Allow new descriptors with a
+ rounded timestamp equal to or newer than the current descriptor */
+ e = (rend_cache_entry_t*) strmap_get_lc(rend_cache_local_service,
+ service_id);
+ if (e && e->parsed->timestamp > parsed->timestamp) {
+ log_info(LD_REND, "We already have a newer service descriptor for "
+ "service ID %s.", safe_str_client(service_id));
+ goto okay;
+ }
+ /* We don't care about the introduction points. */
+ tor_free(intro_content);
+ if (!e) {
+ e = tor_malloc_zero(sizeof(rend_cache_entry_t));
+ strmap_set_lc(rend_cache_local_service, service_id, e);
+ } else {
+ rend_cache_decrement_allocation(rend_cache_entry_allocation(e));
+ rend_service_descriptor_free(e->parsed);
+ tor_free(e->desc);
+ }
+ e->parsed = parsed;
+ e->desc = tor_malloc_zero(encoded_size + 1);
+ strlcpy(e->desc, desc, encoded_size + 1);
+ e->len = encoded_size;
+ rend_cache_increment_allocation(rend_cache_entry_allocation(e));
+ log_debug(LD_REND,"Successfully stored rend desc '%s', len %d.",
+ safe_str_client(service_id), (int)encoded_size);
+ return RCS_OKAY;
+
+ okay:
+ retval = RCS_OKAY;
+
+ err:
+ rend_service_descriptor_free(parsed);
+ tor_free(intro_content);
+ return retval;
+}
+
/** Parse the v2 service descriptor in <b>desc</b>, decrypt the included list
* of introduction points with <b>descriptor_cookie</b> (which may also be
* <b>NULL</b> if decryption is not necessary), and store the descriptor to
diff --git a/src/or/rendcache.h b/src/or/rendcache.h
index 0512058054..a5ad2da3b4 100644
--- a/src/or/rendcache.h
+++ b/src/or/rendcache.h
@@ -48,14 +48,21 @@ typedef struct rend_cache_failure_t {
digestmap_t *intro_failures;
} rend_cache_failure_t;
+typedef enum {
+ REND_CACHE_TYPE_CLIENT = 1,
+ REND_CACHE_TYPE_SERVICE = 2,
+} rend_cache_type_t;
+
void rend_cache_init(void);
-void rend_cache_clean(time_t now);
+void rend_cache_clean(time_t now, rend_cache_type_t cache_type);
void rend_cache_failure_clean(time_t now);
void rend_cache_clean_v2_descs_as_dir(time_t now, size_t min_to_remove);
void rend_cache_purge(void);
void rend_cache_free_all(void);
int rend_cache_lookup_entry(const char *query, int version,
rend_cache_entry_t **entry_out);
+int rend_cache_lookup_v2_desc_as_service(const char *query,
+ rend_cache_entry_t **entry_out);
int rend_cache_lookup_v2_desc_as_dir(const char *query, const char **desc);
/** Return value from rend_cache_store_v2_desc_as_{dir,client}. */
typedef enum {
@@ -65,6 +72,8 @@ typedef enum {
} rend_cache_store_status_t;
rend_cache_store_status_t rend_cache_store_v2_desc_as_dir(const char *desc);
+rend_cache_store_status_t rend_cache_store_v2_desc_as_service(
+ const char *desc);
rend_cache_store_status_t rend_cache_store_v2_desc_as_client(const char *desc,
const char *desc_id_base32,
const rend_data_t *rend_query,
diff --git a/src/or/rendcommon.c b/src/or/rendcommon.c
index 22599e9830..f9d47d13f5 100644
--- a/src/or/rendcommon.c
+++ b/src/or/rendcommon.c
@@ -11,6 +11,7 @@
#include "or.h"
#include "circuitbuild.h"
#include "config.h"
+#include "control.h"
#include "rendclient.h"
#include "rendcommon.h"
#include "rendmid.h"
@@ -461,6 +462,7 @@ rend_encode_v2_descriptors(smartlist_t *descs_out,
smartlist_t *client_cookies)
{
char service_id[DIGEST_LEN];
+ char service_id_base32[REND_SERVICE_ID_LEN_BASE32+1];
uint32_t time_period;
char *ipos_base64 = NULL, *ipos = NULL, *ipos_encrypted = NULL,
*descriptor_cookie = NULL;
@@ -655,6 +657,11 @@ rend_encode_v2_descriptors(smartlist_t *descs_out,
goto err;
}
smartlist_add(descs_out, enc);
+ /* Add the uploaded descriptor to the local service's descriptor cache */
+ rend_cache_store_v2_desc_as_service(enc->desc_str);
+ base32_encode(service_id_base32, sizeof(service_id_base32),
+ service_id, REND_SERVICE_ID_LEN);
+ control_event_hs_descriptor_created(service_id_base32, desc_id_base32, k);
}
log_info(LD_REND, "Successfully encoded a v2 descriptor and "
diff --git a/src/or/rendservice.c b/src/or/rendservice.c
index 8ba5327b1d..da65c6793a 100644
--- a/src/or/rendservice.c
+++ b/src/or/rendservice.c
@@ -3202,39 +3202,72 @@ upload_service_descriptor(rend_service_t *service)
rendpostperiod = get_options()->RendPostPeriod;
- /* Upload descriptor? */
- if (get_options()->PublishHidServDescriptors) {
- networkstatus_t *c = networkstatus_get_latest_consensus();
- if (c && smartlist_len(c->routerstatus_list) > 0) {
- int seconds_valid, i, j, num_descs;
- smartlist_t *descs = smartlist_new();
- smartlist_t *client_cookies = smartlist_new();
- /* Either upload a single descriptor (including replicas) or one
- * descriptor for each authorized client in case of authorization
- * type 'stealth'. */
- num_descs = service->auth_type == REND_STEALTH_AUTH ?
- smartlist_len(service->clients) : 1;
- for (j = 0; j < num_descs; j++) {
- crypto_pk_t *client_key = NULL;
- rend_authorized_client_t *client = NULL;
- smartlist_clear(client_cookies);
- switch (service->auth_type) {
- case REND_NO_AUTH:
- /* Do nothing here. */
- break;
- case REND_BASIC_AUTH:
- SMARTLIST_FOREACH(service->clients, rend_authorized_client_t *,
- cl, smartlist_add(client_cookies, cl->descriptor_cookie));
- break;
- case REND_STEALTH_AUTH:
- client = smartlist_get(service->clients, j);
- client_key = client->client_key;
- smartlist_add(client_cookies, client->descriptor_cookie);
- break;
- }
- /* Encode the current descriptor. */
+ networkstatus_t *c = networkstatus_get_latest_consensus();
+ if (c && smartlist_len(c->routerstatus_list) > 0) {
+ int seconds_valid, i, j, num_descs;
+ smartlist_t *descs = smartlist_new();
+ smartlist_t *client_cookies = smartlist_new();
+ /* Either upload a single descriptor (including replicas) or one
+ * descriptor for each authorized client in case of authorization
+ * type 'stealth'. */
+ num_descs = service->auth_type == REND_STEALTH_AUTH ?
+ smartlist_len(service->clients) : 1;
+ for (j = 0; j < num_descs; j++) {
+ crypto_pk_t *client_key = NULL;
+ rend_authorized_client_t *client = NULL;
+ smartlist_clear(client_cookies);
+ switch (service->auth_type) {
+ case REND_NO_AUTH:
+ /* Do nothing here. */
+ break;
+ case REND_BASIC_AUTH:
+ SMARTLIST_FOREACH(service->clients, rend_authorized_client_t *,
+ cl, smartlist_add(client_cookies, cl->descriptor_cookie));
+ break;
+ case REND_STEALTH_AUTH:
+ client = smartlist_get(service->clients, j);
+ client_key = client->client_key;
+ smartlist_add(client_cookies, client->descriptor_cookie);
+ break;
+ }
+ /* Encode the current descriptor. */
+ seconds_valid = rend_encode_v2_descriptors(descs, service->desc,
+ now, 0,
+ service->auth_type,
+ client_key,
+ client_cookies);
+ if (seconds_valid < 0) {
+ log_warn(LD_BUG, "Internal error: couldn't encode service "
+ "descriptor; not uploading.");
+ smartlist_free(descs);
+ smartlist_free(client_cookies);
+ return;
+ }
+ rend_get_service_id(service->desc->pk, serviceid);
+ if (get_options()->PublishHidServDescriptors) {
+ /* Post the current descriptors to the hidden service directories. */
+ log_info(LD_REND, "Launching upload for hidden service %s",
+ serviceid);
+ directory_post_to_hs_dir(service->desc, descs, NULL, serviceid,
+ seconds_valid);
+ }
+ /* Free memory for descriptors. */
+ for (i = 0; i < smartlist_len(descs); i++)
+ rend_encoded_v2_service_descriptor_free(smartlist_get(descs, i));
+ smartlist_clear(descs);
+ /* Update next upload time. */
+ if (seconds_valid - REND_TIME_PERIOD_OVERLAPPING_V2_DESCS
+ > rendpostperiod)
+ service->next_upload_time = now + rendpostperiod;
+ else if (seconds_valid < REND_TIME_PERIOD_OVERLAPPING_V2_DESCS)
+ service->next_upload_time = now + seconds_valid + 1;
+ else
+ service->next_upload_time = now + seconds_valid -
+ REND_TIME_PERIOD_OVERLAPPING_V2_DESCS + 1;
+ /* Post also the next descriptors, if necessary. */
+ if (seconds_valid < REND_TIME_PERIOD_OVERLAPPING_V2_DESCS) {
seconds_valid = rend_encode_v2_descriptors(descs, service->desc,
- now, 0,
+ now, 1,
service->auth_type,
client_key,
client_cookies);
@@ -3245,51 +3278,23 @@ upload_service_descriptor(rend_service_t *service)
smartlist_free(client_cookies);
return;
}
- /* Post the current descriptors to the hidden service directories. */
- rend_get_service_id(service->desc->pk, serviceid);
- log_info(LD_REND, "Launching upload for hidden service %s",
- serviceid);
- directory_post_to_hs_dir(service->desc, descs, NULL, serviceid,
- seconds_valid);
+ if (get_options()->PublishHidServDescriptors) {
+ directory_post_to_hs_dir(service->desc, descs, NULL, serviceid,
+ seconds_valid);
+ }
/* Free memory for descriptors. */
for (i = 0; i < smartlist_len(descs); i++)
rend_encoded_v2_service_descriptor_free(smartlist_get(descs, i));
smartlist_clear(descs);
- /* Update next upload time. */
- if (seconds_valid - REND_TIME_PERIOD_OVERLAPPING_V2_DESCS
- > rendpostperiod)
- service->next_upload_time = now + rendpostperiod;
- else if (seconds_valid < REND_TIME_PERIOD_OVERLAPPING_V2_DESCS)
- service->next_upload_time = now + seconds_valid + 1;
- else
- service->next_upload_time = now + seconds_valid -
- REND_TIME_PERIOD_OVERLAPPING_V2_DESCS + 1;
- /* Post also the next descriptors, if necessary. */
- if (seconds_valid < REND_TIME_PERIOD_OVERLAPPING_V2_DESCS) {
- seconds_valid = rend_encode_v2_descriptors(descs, service->desc,
- now, 1,
- service->auth_type,
- client_key,
- client_cookies);
- if (seconds_valid < 0) {
- log_warn(LD_BUG, "Internal error: couldn't encode service "
- "descriptor; not uploading.");
- smartlist_free(descs);
- smartlist_free(client_cookies);
- return;
- }
- directory_post_to_hs_dir(service->desc, descs, NULL, serviceid,
- seconds_valid);
- /* Free memory for descriptors. */
- for (i = 0; i < smartlist_len(descs); i++)
- rend_encoded_v2_service_descriptor_free(smartlist_get(descs, i));
- smartlist_clear(descs);
- }
}
- smartlist_free(descs);
- smartlist_free(client_cookies);
- uploaded = 1;
+ }
+ smartlist_free(descs);
+ smartlist_free(client_cookies);
+ uploaded = 1;
+ if (get_options()->PublishHidServDescriptors) {
log_info(LD_REND, "Successfully uploaded v2 rend descriptors!");
+ } else {
+ log_info(LD_REND, "Successfully stored created v2 rend descriptors!");
}
}
@@ -3634,9 +3639,6 @@ rend_consider_services_upload(time_t now)
MIN_REND_INITIAL_POST_DELAY_TESTING :
MIN_REND_INITIAL_POST_DELAY);
- if (!get_options()->PublishHidServDescriptors)
- return;
-
for (i=0; i < smartlist_len(rend_service_list); ++i) {
service = smartlist_get(rend_service_list, i);
if (!service->next_upload_time) { /* never been uploaded yet */
diff --git a/src/or/routerset.c b/src/or/routerset.c
index 3be55d3404..debe9ec6e1 100644
--- a/src/or/routerset.c
+++ b/src/or/routerset.c
@@ -107,10 +107,12 @@ routerset_parse(routerset_t *target, const char *s, const char *description)
description);
smartlist_add(target->country_names, countryname);
added_countries = 1;
- } else if ((strchr(nick,'.') || strchr(nick, '*')) &&
- (p = router_parse_addr_policy_item_from_string(
+ } else if ((strchr(nick,'.') || strchr(nick, ':') || strchr(nick, '*'))
+ && (p = router_parse_addr_policy_item_from_string(
nick, ADDR_POLICY_REJECT,
&malformed_list))) {
+ /* IPv4 addresses contain '.', IPv6 addresses contain ':',
+ * and wildcard addresses contain '*'. */
log_debug(LD_CONFIG, "Adding address %s to %s", nick, description);
smartlist_add(target->policies, p);
} else if (malformed_list) {
diff --git a/src/test/include.am b/src/test/include.am
index a37fe23db8..a9d8b652b2 100644
--- a/src/test/include.am
+++ b/src/test/include.am
@@ -49,6 +49,7 @@ src_test_AM_CPPFLAGS = -DSHARE_DATADIR="\"$(datadir)\"" \
# matters a lot there, and is quite hard to debug if you forget to do it.
src_test_test_SOURCES = \
+ src/test/log_test_helpers.c \
src/test/test.c \
src/test/test_accounting.c \
src/test/test_addr.c \
@@ -61,6 +62,7 @@ src_test_test_SOURCES = \
src/test/test_checkdir.c \
src/test/test_circuitlist.c \
src/test/test_circuitmux.c \
+ src/test/test_compat_libevent.c \
src/test/test_config.c \
src/test/test_containers.c \
src/test/test_controller.c \
@@ -94,6 +96,7 @@ src_test_test_SOURCES = \
src/test/test_status.c \
src/test/test_threads.c \
src/test/test_util.c \
+ src/test/test_util_format.c \
src/test/test_helpers.c \
src/test/test_dns.c \
src/test/testing_common.c \
@@ -161,6 +164,7 @@ src_test_test_workqueue_LDADD = src/or/libtor-testing.a \
noinst_HEADERS+= \
src/test/fakechans.h \
+ src/test/log_test_helpers.h \
src/test/test.h \
src/test/test_helpers.h \
src/test/test_descriptors.inc \
diff --git a/src/test/log_test_helpers.c b/src/test/log_test_helpers.c
new file mode 100644
index 0000000000..51b5f9b7b1
--- /dev/null
+++ b/src/test/log_test_helpers.c
@@ -0,0 +1,111 @@
+/* Copyright (c) 2015, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+#define LOG_PRIVATE
+#include "torlog.h"
+#include "log_test_helpers.h"
+
+static smartlist_t *saved_logs = NULL;
+
+int
+setup_capture_of_logs(int new_level)
+{
+ int previous_log = log_global_min_severity_;
+ log_global_min_severity_ = new_level;
+ mock_clean_saved_logs();
+ MOCK(logv, mock_saving_logv);
+ return previous_log;
+}
+
+void
+teardown_capture_of_logs(int prev)
+{
+ UNMOCK(logv);
+ log_global_min_severity_ = prev;
+ mock_clean_saved_logs();
+}
+
+void
+mock_clean_saved_logs(void)
+{
+ if (!saved_logs)
+ return;
+ SMARTLIST_FOREACH(saved_logs, mock_saved_log_entry_t *, m,
+ { tor_free(m->generated_msg); tor_free(m); });
+ smartlist_free(saved_logs);
+ saved_logs = NULL;
+}
+
+static mock_saved_log_entry_t *
+mock_get_log_entry(int ix)
+{
+ int saved_log_count = mock_saved_log_number();
+ if (ix < 0) {
+ ix = saved_log_count + ix;
+ }
+
+ if (saved_log_count <= ix)
+ return NULL;
+
+ return smartlist_get(saved_logs, ix);
+}
+
+const char *
+mock_saved_log_at(int ix)
+{
+ mock_saved_log_entry_t *ent = mock_get_log_entry(ix);
+ if (ent)
+ return ent->generated_msg;
+ else
+ return "";
+}
+
+int
+mock_saved_severity_at(int ix)
+{
+ mock_saved_log_entry_t *ent = mock_get_log_entry(ix);
+ if (ent)
+ return ent->severity;
+ else
+ return -1;
+}
+
+int
+mock_saved_log_number(void)
+{
+ if (!saved_logs)
+ return 0;
+ return smartlist_len(saved_logs);
+}
+
+const smartlist_t *
+mock_saved_logs(void)
+{
+ return saved_logs;
+}
+
+void
+mock_saving_logv(int severity, log_domain_mask_t domain,
+ const char *funcname, const char *suffix,
+ const char *format, va_list ap)
+{
+ (void)domain;
+ char *buf = tor_malloc_zero(10240);
+ int n;
+ n = tor_vsnprintf(buf,10240,format,ap);
+ tor_assert(n < 10240-1);
+ buf[n]='\n';
+ buf[n+1]='\0';
+
+ mock_saved_log_entry_t *e = tor_malloc_zero(sizeof(mock_saved_log_entry_t));
+ e->severity = severity;
+ e->funcname = funcname;
+ e->suffix = suffix;
+ e->format = format;
+ e->generated_msg = tor_strdup(buf);
+ tor_free(buf);
+
+ if (!saved_logs)
+ saved_logs = smartlist_new();
+ smartlist_add(saved_logs, e);
+}
+
diff --git a/src/test/log_test_helpers.h b/src/test/log_test_helpers.h
new file mode 100644
index 0000000000..af8e8a60e7
--- /dev/null
+++ b/src/test/log_test_helpers.h
@@ -0,0 +1,31 @@
+/* Copyright (c) 2014-2015, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+#include "or.h"
+
+#ifndef TOR_LOG_TEST_HELPERS_H
+#define TOR_LOG_TEST_HELPERS_H
+
+typedef struct mock_saved_log_entry_t {
+ int severity;
+ const char *funcname;
+ const char *suffix;
+ const char *format;
+ char *generated_msg;
+ struct mock_saved_log_entry_t *next;
+} mock_saved_log_entry_t;
+
+void mock_saving_logv(int severity, log_domain_mask_t domain,
+ const char *funcname, const char *suffix,
+ const char *format, va_list ap)
+ CHECK_PRINTF(5, 0);
+void mock_clean_saved_logs(void);
+const smartlist_t *mock_saved_logs(void);
+int setup_capture_of_logs(int new_level);
+void teardown_capture_of_logs(int prev);
+const char *mock_saved_log_at(int ix);
+int mock_saved_severity_at(int ix);
+int mock_saved_log_number(void);
+
+#endif
+
diff --git a/src/test/test.c b/src/test/test.c
index e10e260266..1ab94fd9b4 100644
--- a/src/test/test.c
+++ b/src/test/test.c
@@ -47,6 +47,7 @@ double fabs(double x);
#include "connection_edge.h"
#include "geoip.h"
#include "rendcommon.h"
+#include "rendcache.h"
#include "test.h"
#include "torgzip.h"
#include "memarea.h"
@@ -494,6 +495,9 @@ test_rend_fns(void *arg)
tt_str_op(address6,OP_EQ, "abcdefghijklmnop");
tt_assert(BAD_HOSTNAME == parse_extended_hostname(address7));
+ /* Initialize the service cache. */
+ rend_cache_init();
+
pk1 = pk_generate(0);
pk2 = pk_generate(1);
generated = tor_malloc_zero(sizeof(rend_service_descriptor_t));
@@ -1106,7 +1110,7 @@ static struct testcase_t test_array[] = {
ENT(onion_queues),
{ "ntor_handshake", test_ntor_handshake, 0, NULL, NULL },
ENT(circuit_timeout),
- ENT(rend_fns),
+ FORK(rend_fns),
ENT(geoip),
FORK(geoip_with_pt),
FORK(stats),
@@ -1125,6 +1129,7 @@ extern struct testcase_t channeltls_tests[];
extern struct testcase_t checkdir_tests[];
extern struct testcase_t circuitlist_tests[];
extern struct testcase_t circuitmux_tests[];
+extern struct testcase_t compat_libevent_tests[];
extern struct testcase_t config_tests[];
extern struct testcase_t container_tests[];
extern struct testcase_t controller_tests[];
@@ -1158,6 +1163,7 @@ extern struct testcase_t socks_tests[];
extern struct testcase_t status_tests[];
extern struct testcase_t thread_tests[];
extern struct testcase_t util_tests[];
+extern struct testcase_t util_format_tests[];
extern struct testcase_t dns_tests[];
struct testgroup_t testgroups[] = {
@@ -1173,6 +1179,7 @@ struct testgroup_t testgroups[] = {
{ "checkdir/", checkdir_tests },
{ "circuitlist/", circuitlist_tests },
{ "circuitmux/", circuitmux_tests },
+ { "compat/libevent/", compat_libevent_tests },
{ "config/", config_tests },
{ "container/", container_tests },
{ "control/", controller_tests },
@@ -1203,6 +1210,7 @@ struct testgroup_t testgroups[] = {
{ "socks/", socks_tests },
{ "status/" , status_tests },
{ "util/", util_tests },
+ { "util/format/", util_format_tests },
{ "util/logging/", logging_tests },
{ "util/thread/", thread_tests },
{ "dns/", dns_tests },
diff --git a/src/test/test_address.c b/src/test/test_address.c
index 72742df2cd..e48c06a6c4 100644
--- a/src/test/test_address.c
+++ b/src/test/test_address.c
@@ -779,6 +779,99 @@ test_address_get_if_addrs6_list_no_internal(void *arg)
return;
}
+static int called_get_interface_addresses_raw = 0;
+
+static smartlist_t *
+mock_get_interface_addresses_raw_fail(int severity)
+{
+ (void)severity;
+
+ called_get_interface_addresses_raw++;
+ return smartlist_new();
+}
+
+static int called_get_interface_address6_via_udp_socket_hack = 0;
+
+static int
+mock_get_interface_address6_via_udp_socket_hack_fail(int severity,
+ sa_family_t family,
+ tor_addr_t *addr)
+{
+ (void)severity;
+ (void)family;
+ (void)addr;
+
+ called_get_interface_address6_via_udp_socket_hack++;
+ return -1;
+}
+
+static void
+test_address_get_if_addrs_internal_fail(void *arg)
+{
+ smartlist_t *results1 = NULL, *results2 = NULL;
+ int rv = 0;
+ uint32_t ipv4h_addr = 0;
+ tor_addr_t ipv6_addr;
+
+ memset(&ipv6_addr, 0, sizeof(tor_addr_t));
+
+ (void)arg;
+
+ MOCK(get_interface_addresses_raw,
+ mock_get_interface_addresses_raw_fail);
+ MOCK(get_interface_address6_via_udp_socket_hack,
+ mock_get_interface_address6_via_udp_socket_hack_fail);
+
+ results1 = get_interface_address6_list(LOG_ERR, AF_INET6, 1);
+ tt_assert(results1 != NULL);
+ tt_int_op(smartlist_len(results1),==,0);
+
+ results2 = get_interface_address_list(LOG_ERR, 1);
+ tt_assert(results2 != NULL);
+ tt_int_op(smartlist_len(results2),==,0);
+
+ rv = get_interface_address6(LOG_ERR, AF_INET6, &ipv6_addr);
+ tt_assert(rv == -1);
+
+ rv = get_interface_address(LOG_ERR, &ipv4h_addr);
+ tt_assert(rv == -1);
+
+ done:
+ UNMOCK(get_interface_addresses_raw);
+ UNMOCK(get_interface_address6_via_udp_socket_hack);
+ free_interface_address6_list(results1);
+ free_interface_address6_list(results2);
+ return;
+}
+
+static void
+test_address_get_if_addrs_no_internal_fail(void *arg)
+{
+ smartlist_t *results1 = NULL, *results2 = NULL;
+
+ (void)arg;
+
+ MOCK(get_interface_addresses_raw,
+ mock_get_interface_addresses_raw_fail);
+ MOCK(get_interface_address6_via_udp_socket_hack,
+ mock_get_interface_address6_via_udp_socket_hack_fail);
+
+ results1 = get_interface_address6_list(LOG_ERR, AF_INET6, 0);
+ tt_assert(results1 != NULL);
+ tt_int_op(smartlist_len(results1),==,0);
+
+ results2 = get_interface_address_list(LOG_ERR, 0);
+ tt_assert(results2 != NULL);
+ tt_int_op(smartlist_len(results2),==,0);
+
+ done:
+ UNMOCK(get_interface_addresses_raw);
+ UNMOCK(get_interface_address6_via_udp_socket_hack);
+ free_interface_address6_list(results1);
+ free_interface_address6_list(results2);
+ return;
+}
+
static void
test_address_get_if_addrs(void *arg)
{
@@ -838,6 +931,8 @@ struct testcase_t address_tests[] = {
ADDRESS_TEST(get_if_addrs_list_no_internal, 0),
ADDRESS_TEST(get_if_addrs6_list_internal, 0),
ADDRESS_TEST(get_if_addrs6_list_no_internal, 0),
+ ADDRESS_TEST(get_if_addrs_internal_fail, 0),
+ ADDRESS_TEST(get_if_addrs_no_internal_fail, 0),
ADDRESS_TEST(get_if_addrs, 0),
ADDRESS_TEST(get_if_addrs6, 0),
#ifdef HAVE_IFADDRS_TO_SMARTLIST
diff --git a/src/test/test_bt.sh b/src/test/test_bt.sh
index 56e6cc40f8..f55f451f92 100755
--- a/src/test/test_bt.sh
+++ b/src/test/test_bt.sh
@@ -3,6 +3,7 @@
exitcode=0
+"${builddir:-.}/src/test/test-bt-cl" backtraces || exit 77
"${builddir:-.}/src/test/test-bt-cl" assert | "${PYTHON:-python}" "${abs_top_srcdir:-.}/src/test/bt_test.py" || exitcode=1
"${builddir:-.}/src/test/test-bt-cl" crash | "${PYTHON:-python}" "${abs_top_srcdir:-.}/src/test/bt_test.py" || exitcode=1
diff --git a/src/test/test_bt_cl.c b/src/test/test_bt_cl.c
index 01c621eb0e..dabaee6e0a 100644
--- a/src/test/test_bt_cl.c
+++ b/src/test/test_bt_cl.c
@@ -84,15 +84,24 @@ main(int argc, char **argv)
if (argc < 2) {
puts("I take an argument. It should be \"assert\" or \"crash\" or "
- "\"none\"");
+ "\"backtraces\" or \"none\"");
return 1;
}
+
+#if !(defined(HAVE_EXECINFO_H) && defined(HAVE_BACKTRACE) && \
+ defined(HAVE_BACKTRACE_SYMBOLS_FD) && defined(HAVE_SIGACTION))
+ puts("Backtrace reporting is not supported on this platform");
+ return 77;
+#endif
+
if (!strcmp(argv[1], "assert")) {
crashtype = 1;
} else if (!strcmp(argv[1], "crash")) {
crashtype = 0;
} else if (!strcmp(argv[1], "none")) {
crashtype = -1;
+ } else if (!strcmp(argv[1], "backtraces")) {
+ return 0;
} else {
puts("Argument should be \"assert\" or \"crash\" or \"none\"");
return 1;
diff --git a/src/test/test_compat_libevent.c b/src/test/test_compat_libevent.c
new file mode 100644
index 0000000000..96502df308
--- /dev/null
+++ b/src/test/test_compat_libevent.c
@@ -0,0 +1,238 @@
+/* Copyright (c) 2010-2015, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+#define COMPAT_LIBEVENT_PRIVATE
+#include "orconfig.h"
+#include "or.h"
+
+#include "test.h"
+
+#include "compat_libevent.h"
+
+#ifdef HAVE_EVENT2_EVENT_H
+#include <event2/event.h>
+#include <event2/thread.h>
+#ifdef USE_BUFFEREVENTS
+#include <event2/bufferevent.h>
+#endif
+#else
+#include <event.h>
+#endif
+
+#include "log_test_helpers.h"
+
+#define NS_MODULE compat_libevent
+
+static void
+test_compat_libevent_logging_callback(void *ignored)
+{
+ (void)ignored;
+ int previous_log = setup_capture_of_logs(LOG_DEBUG);
+
+ libevent_logging_callback(_EVENT_LOG_DEBUG, "hello world");
+ tt_int_op(mock_saved_log_number(), OP_EQ, 1);
+ tt_str_op(mock_saved_log_at(0), OP_EQ,
+ "Message from libevent: hello world\n");
+ tt_int_op(mock_saved_severity_at(0), OP_EQ, LOG_DEBUG);
+
+ mock_clean_saved_logs();
+ libevent_logging_callback(_EVENT_LOG_MSG, "hello world another time");
+ tt_int_op(mock_saved_log_number(), OP_EQ, 1);
+ tt_str_op(mock_saved_log_at(0), OP_EQ,
+ "Message from libevent: hello world another time\n");
+ tt_int_op(mock_saved_severity_at(0), OP_EQ, LOG_INFO);
+
+ mock_clean_saved_logs();
+ libevent_logging_callback(_EVENT_LOG_WARN, "hello world a third time");
+ tt_int_op(mock_saved_log_number(), OP_EQ, 1);
+ tt_str_op(mock_saved_log_at(0), OP_EQ,
+ "Warning from libevent: hello world a third time\n");
+ tt_int_op(mock_saved_severity_at(0), OP_EQ, LOG_WARN);
+
+ mock_clean_saved_logs();
+ libevent_logging_callback(_EVENT_LOG_ERR, "hello world a fourth time");
+ tt_int_op(mock_saved_log_number(), OP_EQ, 1);
+ tt_str_op(mock_saved_log_at(0), OP_EQ,
+ "Error from libevent: hello world a fourth time\n");
+ tt_int_op(mock_saved_severity_at(0), OP_EQ, LOG_ERR);
+
+ mock_clean_saved_logs();
+ libevent_logging_callback(42, "hello world a fifth time");
+ tt_int_op(mock_saved_log_number(), OP_EQ, 1);
+ tt_str_op(mock_saved_log_at(0), OP_EQ,
+ "Message [42] from libevent: hello world a fifth time\n");
+ tt_int_op(mock_saved_severity_at(0), OP_EQ, LOG_WARN);
+
+ mock_clean_saved_logs();
+ libevent_logging_callback(_EVENT_LOG_DEBUG,
+ "012345678901234567890123456789"
+ "012345678901234567890123456789"
+ "012345678901234567890123456789"
+ "012345678901234567890123456789"
+ "012345678901234567890123456789"
+ "012345678901234567890123456789"
+ "012345678901234567890123456789"
+ "012345678901234567890123456789"
+ "012345678901234567890123456789"
+ "012345678901234567890123456789"
+ "012345678901234567890123456789"
+ "012345678901234567890123456789"
+ );
+ tt_int_op(mock_saved_log_number(), OP_EQ, 1);
+ tt_str_op(mock_saved_log_at(0), OP_EQ, "Message from libevent: "
+ "012345678901234567890123456789"
+ "012345678901234567890123456789"
+ "012345678901234567890123456789"
+ "012345678901234567890123456789"
+ "012345678901234567890123456789"
+ "012345678901234567890123456789"
+ "012345678901234567890123456789"
+ "012345678901234567890123456789"
+ "012345678901234567890123456789"
+ "012345678901234567890123456789"
+ "012345678901234567890123456789"
+ "012345678901234567890123456789\n");
+ tt_int_op(mock_saved_severity_at(0), OP_EQ, LOG_DEBUG);
+
+ mock_clean_saved_logs();
+ libevent_logging_callback(42, "xxx\n");
+ tt_int_op(mock_saved_log_number(), OP_EQ, 1);
+ tt_str_op(mock_saved_log_at(0), OP_EQ, "Message [42] from libevent: xxx\n");
+ tt_int_op(mock_saved_severity_at(0), OP_EQ, LOG_WARN);
+
+ suppress_libevent_log_msg("something");
+ mock_clean_saved_logs();
+ libevent_logging_callback(_EVENT_LOG_MSG, "hello there");
+ tt_int_op(mock_saved_log_number(), OP_EQ, 1);
+ tt_str_op(mock_saved_log_at(0), OP_EQ,
+ "Message from libevent: hello there\n");
+ tt_int_op(mock_saved_severity_at(0), OP_EQ, LOG_INFO);
+
+ mock_clean_saved_logs();
+ libevent_logging_callback(_EVENT_LOG_MSG, "hello there something else");
+ tt_int_op(mock_saved_log_number(), OP_EQ, 0);
+
+ // No way of verifying the result of this, it seems =/
+ configure_libevent_logging();
+
+ done:
+ suppress_libevent_log_msg(NULL);
+ teardown_capture_of_logs(previous_log);
+}
+
+static void
+test_compat_libevent_le_versions_compatibility(void *ignored)
+{
+ (void)ignored;
+ int res;
+
+ res = le_versions_compatibility(LE_OTHER);
+ tt_int_op(res, OP_EQ, 0);
+
+ res = le_versions_compatibility(V_OLD(0,9,'c'));
+ tt_int_op(res, OP_EQ, 1);
+
+ res = le_versions_compatibility(V(1,3,98));
+ tt_int_op(res, OP_EQ, 2);
+
+ res = le_versions_compatibility(V(1,4,98));
+ tt_int_op(res, OP_EQ, 3);
+
+ res = le_versions_compatibility(V(1,5,0));
+ tt_int_op(res, OP_EQ, 4);
+
+ res = le_versions_compatibility(V(2,0,0));
+ tt_int_op(res, OP_EQ, 4);
+
+ res = le_versions_compatibility(V(2,0,2));
+ tt_int_op(res, OP_EQ, 5);
+
+ done:
+ (void)0;
+}
+
+static void
+test_compat_libevent_tor_decode_libevent_version(void *ignored)
+{
+ (void)ignored;
+ le_version_t res;
+
+ res = tor_decode_libevent_version("SOMETHING WRONG");
+ tt_int_op(res, OP_EQ, LE_OTHER);
+
+ res = tor_decode_libevent_version("1.4.11");
+ tt_int_op(res, OP_EQ, V(1,4,11));
+
+ res = tor_decode_libevent_version("1.4.12b-stable");
+ tt_int_op(res, OP_EQ, V(1,4,12));
+
+ res = tor_decode_libevent_version("1.4.17b_stable");
+ tt_int_op(res, OP_EQ, V(1,4,17));
+
+ res = tor_decode_libevent_version("1.4.12!stable");
+ tt_int_op(res, OP_EQ, LE_OTHER);
+
+ res = tor_decode_libevent_version("1.4.12b!stable");
+ tt_int_op(res, OP_EQ, LE_OTHER);
+
+ res = tor_decode_libevent_version("1.4.13-");
+ tt_int_op(res, OP_EQ, V(1,4,13));
+
+ res = tor_decode_libevent_version("1.4.14_");
+ tt_int_op(res, OP_EQ, V(1,4,14));
+
+ res = tor_decode_libevent_version("1.4.15c-");
+ tt_int_op(res, OP_EQ, V(1,4,15));
+
+ res = tor_decode_libevent_version("1.4.16c_");
+ tt_int_op(res, OP_EQ, V(1,4,16));
+
+ res = tor_decode_libevent_version("1.4.17-s");
+ tt_int_op(res, OP_EQ, V(1,4,17));
+
+ res = tor_decode_libevent_version("1.5");
+ tt_int_op(res, OP_EQ, V(1,5,0));
+
+ res = tor_decode_libevent_version("1.2");
+ tt_int_op(res, OP_EQ, V(1,2,0));
+
+ res = tor_decode_libevent_version("1.2-");
+ tt_int_op(res, OP_EQ, LE_OTHER);
+
+ res = tor_decode_libevent_version("1.6e");
+ tt_int_op(res, OP_EQ, V_OLD(1,6,'e'));
+
+ done:
+ (void)0;
+}
+
+#if defined(LIBEVENT_VERSION)
+#define HEADER_VERSION LIBEVENT_VERSION
+#elif defined(_EVENT_VERSION)
+#define HEADER_VERSION _EVENT_VERSION
+#endif
+
+static void
+test_compat_libevent_header_version(void *ignored)
+{
+ (void)ignored;
+ const char *res;
+
+ res = tor_libevent_get_header_version_str();
+ tt_str_op(res, OP_EQ, HEADER_VERSION);
+
+ done:
+ (void)0;
+}
+
+struct testcase_t compat_libevent_tests[] = {
+ { "logging_callback", test_compat_libevent_logging_callback,
+ TT_FORK, NULL, NULL },
+ { "le_versions_compatibility",
+ test_compat_libevent_le_versions_compatibility, 0, NULL, NULL },
+ { "tor_decode_libevent_version",
+ test_compat_libevent_tor_decode_libevent_version, 0, NULL, NULL },
+ { "header_version", test_compat_libevent_header_version, 0, NULL, NULL },
+ END_OF_TESTCASES
+};
+
diff --git a/src/test/test_routerset.c b/src/test/test_routerset.c
index 90dfb28c6b..3e9317c54f 100644
--- a/src/test/test_routerset.c
+++ b/src/test/test_routerset.c
@@ -423,10 +423,10 @@ NS(test_main)(void *arg)
}
#undef NS_SUBMODULE
-#define NS_SUBMODULE ASPECT(routerset_parse, policy)
+#define NS_SUBMODULE ASPECT(routerset_parse, policy_wildcard)
/*
- * Structural test for routerset_parse, when given a valid policy.
+ * Structural test for routerset_parse, when given a valid wildcard policy.
*/
NS_DECL(addr_policy_t *, router_parse_addr_policy_item_from_string,
@@ -470,6 +470,100 @@ NS(router_parse_addr_policy_item_from_string)(const char *s,
}
#undef NS_SUBMODULE
+#define NS_SUBMODULE ASPECT(routerset_parse, policy_ipv4)
+
+/*
+ * Structural test for routerset_parse, when given a valid IPv4 address
+ * literal policy.
+ */
+
+NS_DECL(addr_policy_t *, router_parse_addr_policy_item_from_string,
+ (const char *s, int assume_action, int *bogus));
+
+addr_policy_t *NS(mock_addr_policy);
+
+static void
+NS(test_main)(void *arg)
+{
+ routerset_t *set;
+ const char *s;
+ int r;
+ (void)arg;
+
+ NS_MOCK(router_parse_addr_policy_item_from_string);
+ NS(mock_addr_policy) = tor_malloc_zero(sizeof(addr_policy_t));
+
+ set = routerset_new();
+ s = "127.0.0.1";
+ r = routerset_parse(set, s, "");
+ tt_int_op(r, OP_EQ, 0);
+ tt_int_op(smartlist_len(set->policies), OP_NE, 0);
+ tt_int_op(CALLED(router_parse_addr_policy_item_from_string), OP_EQ, 1);
+
+done:
+ routerset_free(set);
+}
+
+addr_policy_t *
+NS(router_parse_addr_policy_item_from_string)(const char *s, int assume_action,
+ int *bogus)
+{
+ (void)s;
+ (void)assume_action;
+ CALLED(router_parse_addr_policy_item_from_string)++;
+ *bogus = 0;
+
+ return NS(mock_addr_policy);
+}
+
+#undef NS_SUBMODULE
+#define NS_SUBMODULE ASPECT(routerset_parse, policy_ipv6)
+
+/*
+ * Structural test for routerset_parse, when given a valid IPv6 address
+ * literal policy.
+ */
+
+NS_DECL(addr_policy_t *, router_parse_addr_policy_item_from_string,
+ (const char *s, int assume_action, int *bad));
+
+addr_policy_t *NS(mock_addr_policy);
+
+static void
+NS(test_main)(void *arg)
+{
+ routerset_t *set;
+ const char *s;
+ int r;
+ (void)arg;
+
+ NS_MOCK(router_parse_addr_policy_item_from_string);
+ NS(mock_addr_policy) = tor_malloc_zero(sizeof(addr_policy_t));
+
+ set = routerset_new();
+ s = "::1";
+ r = routerset_parse(set, s, "");
+ tt_int_op(r, OP_EQ, 0);
+ tt_int_op(smartlist_len(set->policies), OP_NE, 0);
+ tt_int_op(CALLED(router_parse_addr_policy_item_from_string), OP_EQ, 1);
+
+done:
+ routerset_free(set);
+}
+
+addr_policy_t *
+NS(router_parse_addr_policy_item_from_string)(const char *s,
+ int assume_action, int *bad)
+{
+ (void)s;
+ (void)assume_action;
+ CALLED(router_parse_addr_policy_item_from_string)++;
+ *bad = 0;
+
+ return NS(mock_addr_policy);
+}
+
+#undef NS_SUBMODULE
#define NS_SUBMODULE ASPECT(routerset_union, source_bad)
/*
@@ -2109,7 +2203,9 @@ struct testcase_t routerset_tests[] = {
TEST_CASE_ASPECT(routerset_parse, valid_hexdigest),
TEST_CASE_ASPECT(routerset_parse, valid_nickname),
TEST_CASE_ASPECT(routerset_parse, get_countryname),
- TEST_CASE_ASPECT(routerset_parse, policy),
+ TEST_CASE_ASPECT(routerset_parse, policy_wildcard),
+ TEST_CASE_ASPECT(routerset_parse, policy_ipv4),
+ TEST_CASE_ASPECT(routerset_parse, policy_ipv6),
TEST_CASE(routerset_subtract_nodes),
TEST_CASE_ASPECT(routerset_subtract_nodes, null_routerset),
TEST_CASE(routerset_to_string),
diff --git a/src/test/test_util_format.c b/src/test/test_util_format.c
new file mode 100644
index 0000000000..af4997de97
--- /dev/null
+++ b/src/test/test_util_format.c
@@ -0,0 +1,238 @@
+/* Copyright (c) 2010-2015, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+#include "orconfig.h"
+#include "or.h"
+
+#include "test.h"
+
+#define UTIL_FORMAT_PRIVATE
+#include "util_format.h"
+
+#define NS_MODULE util_format
+
+static void
+test_util_format_base64_encode(void *ignored)
+{
+ (void)ignored;
+ int res;
+ int i;
+ char *src;
+ char *dst;
+
+ src = tor_malloc_zero(256);
+ dst = tor_malloc_zero(1000);
+
+ for (i=0;i<256;i++) {
+ src[i] = (char)i;
+ }
+
+ res = base64_encode(NULL, 1, src, 1, 0);
+ tt_int_op(res, OP_EQ, -1);
+
+ res = base64_encode(dst, 1, NULL, 1, 0);
+ tt_int_op(res, OP_EQ, -1);
+
+ res = base64_encode(dst, 1, src, 10, 0);
+ tt_int_op(res, OP_EQ, -1);
+
+ res = base64_encode(dst, SSIZE_MAX-1, src, 1, 0);
+ tt_int_op(res, OP_EQ, -1);
+
+ res = base64_encode(dst, SSIZE_MAX-1, src, 10, 0);
+ tt_int_op(res, OP_EQ, -1);
+
+ res = base64_encode(dst, 1000, src, 256, 0);
+ tt_int_op(res, OP_EQ, 344);
+ tt_str_op(dst, OP_EQ, "AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh"
+ "8gISIjJCUmJygpKissLS4vMDEyMzQ1Njc4OTo7PD0+P0BBQkNERUZH"
+ "SElKS0xNTk9QUVJTVFVWV1hZWltcXV5fYGFiY2RlZmdoaWprbG1ub3"
+ "BxcnN0dXZ3eHl6e3x9fn+AgYKDhIWGh4iJiouMjY6PkJGSk5SVlpeY"
+ "mZqbnJ2en6ChoqOkpaanqKmqq6ytrq+wsbKztLW2t7i5uru8vb6/wM"
+ "HCw8TFxsfIycrLzM3Oz9DR0tPU1dbX2Nna29zd3t/g4eLj5OXm5+jp"
+ "6uvs7e7v8PHy8/T19vf4+fr7/P3+/w==");
+
+ res = base64_encode(dst, 1000, src, 256, BASE64_ENCODE_MULTILINE);
+ tt_int_op(res, OP_EQ, 350);
+ tt_str_op(dst, OP_EQ,
+ "AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIjJCUmJygpKissLS4v\n"
+ "MDEyMzQ1Njc4OTo7PD0+P0BBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWltcXV5f\n"
+ "YGFiY2RlZmdoaWprbG1ub3BxcnN0dXZ3eHl6e3x9fn+AgYKDhIWGh4iJiouMjY6P\n"
+ "kJGSk5SVlpeYmZqbnJ2en6ChoqOkpaanqKmqq6ytrq+wsbKztLW2t7i5uru8vb6/\n"
+ "wMHCw8TFxsfIycrLzM3Oz9DR0tPU1dbX2Nna29zd3t/g4eLj5OXm5+jp6uvs7e7v\n"
+ "8PHy8/T19vf4+fr7/P3+/w==\n");
+
+ res = base64_encode(dst, 1000, src+1, 255, BASE64_ENCODE_MULTILINE);
+ tt_int_op(res, OP_EQ, 346);
+
+ for (i = 0;i<50;i++) {
+ src[i] = 0;
+ }
+ src[50] = 255;
+ src[51] = 255;
+ src[52] = 255;
+ src[53] = 255;
+
+ res = base64_encode(dst, 1000, src, 54, BASE64_ENCODE_MULTILINE);
+ tt_int_op(res, OP_EQ, 74);
+
+ res = base64_encode(dst, 1000, src+1, 53, BASE64_ENCODE_MULTILINE);
+ tt_int_op(res, OP_EQ, 74);
+
+ res = base64_encode(dst, 1000, src+2, 52, BASE64_ENCODE_MULTILINE);
+ tt_int_op(res, OP_EQ, 74);
+
+ res = base64_encode(dst, 1000, src+3, 51, BASE64_ENCODE_MULTILINE);
+ tt_int_op(res, OP_EQ, 70);
+
+ res = base64_encode(dst, 1000, src+4, 50, BASE64_ENCODE_MULTILINE);
+ tt_int_op(res, OP_EQ, 70);
+
+ res = base64_encode(dst, 1000, src+5, 49, BASE64_ENCODE_MULTILINE);
+ tt_int_op(res, OP_EQ, 70);
+
+ res = base64_encode(dst, 1000, src+6, 48, BASE64_ENCODE_MULTILINE);
+ tt_int_op(res, OP_EQ, 65);
+
+ res = base64_encode(dst, 1000, src+7, 47, BASE64_ENCODE_MULTILINE);
+ tt_int_op(res, OP_EQ, 65);
+
+ res = base64_encode(dst, 1000, src+8, 46, BASE64_ENCODE_MULTILINE);
+ tt_int_op(res, OP_EQ, 65);
+
+ done:
+ tor_free(src);
+ tor_free(dst);
+}
+
+static void
+test_util_format_base64_decode_nopad(void *ignored)
+{
+ (void)ignored;
+ int res;
+ int i;
+ char *src;
+ uint8_t *dst;
+
+ src = tor_malloc_zero(256);
+ dst = tor_malloc_zero(1000);
+
+ for (i=0;i<256;i++) {
+ src[i] = (char)i;
+ }
+
+ res = base64_decode_nopad(dst, 1, src, SIZE_T_CEILING);
+ tt_int_op(res, OP_EQ, -1);
+
+ res = base64_decode_nopad(dst, 1, src, 5);
+ tt_int_op(res, OP_EQ, -1);
+
+ const char *s = "SGVsbG8gd29ybGQ";
+ res = base64_decode_nopad(dst, 1000, s, strlen(s));
+ tt_int_op(res, OP_EQ, 11);
+ tt_mem_op(dst, OP_EQ, "Hello world", 11);
+
+ s = "T3BhIG11bmRv";
+ res = base64_decode_nopad(dst, 9, s, strlen(s));
+ tt_int_op(res, OP_EQ, 9);
+ tt_mem_op(dst, OP_EQ, "Opa mundo", 9);
+
+ done:
+ tor_free(src);
+ tor_free(dst);
+}
+
+static void
+test_util_format_base64_decode(void *ignored)
+{
+ (void)ignored;
+ int res;
+ int i;
+ char *src;
+ char *dst;
+
+ src = tor_malloc_zero(256);
+ dst = tor_malloc_zero(1000);
+
+ for (i=0;i<256;i++) {
+ src[i] = (char)i;
+ }
+
+ res = base64_decode(dst, 1, src, SIZE_T_CEILING);
+ tt_int_op(res, OP_EQ, -1);
+
+ res = base64_decode(dst, SIZE_T_CEILING+1, src, 10);
+ tt_int_op(res, OP_EQ, -1);
+
+ const char *s = "T3BhIG11bmRv";
+ res = base64_decode(dst, 9, s, strlen(s));
+ tt_int_op(res, OP_EQ, 9);
+ tt_mem_op(dst, OP_EQ, "Opa mundo", 9);
+
+ memset(dst, 0, 1000);
+ res = base64_decode(dst, 100, s, strlen(s));
+ tt_int_op(res, OP_EQ, 9);
+ tt_mem_op(dst, OP_EQ, "Opa mundo", 9);
+
+ s = "SGVsbG8gd29ybGQ=";
+ res = base64_decode(dst, 100, s, strlen(s));
+ tt_int_op(res, OP_EQ, 11);
+ tt_mem_op(dst, OP_EQ, "Hello world", 11);
+
+ done:
+ tor_free(src);
+ tor_free(dst);
+}
+
+static void
+test_util_format_base16_decode(void *ignored)
+{
+ (void)ignored;
+ int res;
+ int i;
+ char *src;
+ char *dst;
+
+ src = tor_malloc_zero(256);
+ dst = tor_malloc_zero(1000);
+
+ for (i=0;i<256;i++) {
+ src[i] = (char)i;
+ }
+
+ res = base16_decode(dst, 3, src, 3);
+ tt_int_op(res, OP_EQ, -1);
+
+ res = base16_decode(dst, 1, src, 10);
+ tt_int_op(res, OP_EQ, -1);
+
+ res = base16_decode(dst, SIZE_T_CEILING+2, src, 10);
+ tt_int_op(res, OP_EQ, -1);
+
+ res = base16_decode(dst, 1000, "", 0);
+ tt_int_op(res, OP_EQ, 0);
+
+ res = base16_decode(dst, 1000, "aabc", 4);
+ tt_int_op(res, OP_EQ, 0);
+ tt_mem_op(dst, OP_EQ, "\xaa\xbc", 2);
+
+ res = base16_decode(dst, 1000, "aabcd", 6);
+ tt_int_op(res, OP_EQ, -1);
+
+ res = base16_decode(dst, 1000, "axxx", 4);
+ tt_int_op(res, OP_EQ, -1);
+
+ done:
+ tor_free(src);
+ tor_free(dst);
+}
+
+struct testcase_t util_format_tests[] = {
+ { "base64_encode", test_util_format_base64_encode, 0, NULL, NULL },
+ { "base64_decode_nopad", test_util_format_base64_decode_nopad, 0,
+ NULL, NULL },
+ { "base64_decode", test_util_format_base64_decode, 0, NULL, NULL },
+ { "base16_decode", test_util_format_base16_decode, 0, NULL, NULL },
+ END_OF_TESTCASES
+};
+
diff --git a/src/trunnel/README b/src/trunnel/README
new file mode 100644
index 0000000000..383272cf78
--- /dev/null
+++ b/src/trunnel/README
@@ -0,0 +1,10 @@
+This directory contains code for use with, and code made by, the
+automatic code generation tool "Trunnel".
+
+The .trunnel files are the inputs here; the .c and .h files are the outputs.
+To regenerate the .c and .h files, run "scripts/codegen/run_trunnel.sh".
+
+For the Trunnel source code, and more documentation about using Trunnel,
+see https://gitweb.torproject.org/trunnel.git , especially
+ https://gitweb.torproject.org/trunnel.git/tree/README
+and https://gitweb.torproject.org/trunnel.git/tree/doc/trunnel.md
diff --git a/src/trunnel/include.am b/src/trunnel/include.am
index 9bf37fe58b..b1448b7cb2 100644
--- a/src/trunnel/include.am
+++ b/src/trunnel/include.am
@@ -36,3 +36,7 @@ src_trunnel_libor_trunnel_testing_a_CPPFLAGS = -DTRUNNEL_LOCAL_H $(AM_CPPFLAGS)
src_trunnel_libor_trunnel_testing_a_CFLAGS = $(AM_CFLAGS) $(TEST_CFLAGS)
noinst_HEADERS+= $(TRUNNELHEADERS)
+
+EXTRA_DIST += \
+ src/trunnel/README
+