summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Doxyfile.in26
-rw-r--r--changes/148817
-rw-r--r--changes/202734
-rw-r--r--changes/bug138273
-rw-r--r--changes/bug200484
-rw-r--r--changes/bug202694
-rw-r--r--changes/bug203894
-rw-r--r--changes/bug204354
-rw-r--r--changes/bug204593
-rw-r--r--changes/bug67695
-rw-r--r--changes/ticket198584
-rw-r--r--changes/ticket200775
-rw-r--r--configure.ac2
-rw-r--r--contrib/win32build/tor-mingw.nsi.in2
-rw-r--r--doc/tor.1.txt2
-rw-r--r--src/common/log.c2
-rw-r--r--src/common/util.c19
-rw-r--r--src/common/util.h1
-rw-r--r--src/common/util_bug.c2
-rw-r--r--src/ext/trunnel/trunnel-impl.h3
-rw-r--r--src/ext/trunnel/trunnel.c2
-rw-r--r--src/ext/trunnel/trunnel.h2
-rw-r--r--src/or/addressmap.c18
-rw-r--r--src/or/channel.c93
-rw-r--r--src/or/channel.h3
-rw-r--r--src/or/circpathbias.c8
-rw-r--r--src/or/circuitbuild.c15
-rw-r--r--src/or/circuitlist.c51
-rw-r--r--src/or/circuitmux_ewma.c2
-rw-r--r--src/or/circuituse.c118
-rw-r--r--src/or/config.c57
-rw-r--r--src/or/confparse.c11
-rw-r--r--src/or/connection_edge.c155
-rw-r--r--src/or/control.c12
-rw-r--r--src/or/directory.c116
-rw-r--r--src/or/directory.h6
-rw-r--r--src/or/dirserv.c12
-rw-r--r--src/or/dirvote.c99
-rw-r--r--src/or/dirvote.h10
-rw-r--r--src/or/dns.c4
-rw-r--r--src/or/dnsserv.c20
-rw-r--r--src/or/entrynodes.c625
-rw-r--r--src/or/entrynodes.h41
-rw-r--r--src/or/geoip.c2
-rw-r--r--src/or/main.c165
-rw-r--r--src/or/microdesc.c17
-rw-r--r--src/or/networkstatus.c30
-rw-r--r--src/or/nodelist.c26
-rw-r--r--src/or/or.h3
-rw-r--r--src/or/policies.c13
-rw-r--r--src/or/protover.c4
-rw-r--r--src/or/relay.c35
-rw-r--r--src/or/rendservice.c4
-rw-r--r--src/or/router.c20
-rw-r--r--src/or/routerkeys.c9
-rw-r--r--src/or/routerlist.c13
-rw-r--r--src/or/routerparse.c16
-rw-r--r--src/or/routerset.c8
-rw-r--r--src/or/scheduler.c113
-rw-r--r--src/or/torcert.c17
-rw-r--r--src/or/transports.c4
-rw-r--r--src/test/test_containers.c16
-rw-r--r--src/test/test_dir.c378
-rw-r--r--src/test/test_entryconn.c20
-rw-r--r--src/test/test_entrynodes.c18
-rw-r--r--src/test/test_policy.c8
-rw-r--r--src/test/test_pt.c8
-rw-r--r--src/test/test_routerlist.c68
-rw-r--r--src/test/test_routerset.c28
-rw-r--r--src/test/test_shared_random.c12
-rw-r--r--src/trunnel/ed25519_cert.c58
-rw-r--r--src/trunnel/ed25519_cert.h44
-rw-r--r--src/trunnel/link_handshake.c196
-rw-r--r--src/trunnel/link_handshake.h134
-rw-r--r--src/trunnel/pwbox.c46
-rw-r--r--src/trunnel/pwbox.h32
-rw-r--r--src/win32/orconfig.h2
77 files changed, 2445 insertions, 708 deletions
diff --git a/Doxyfile.in b/Doxyfile.in
index a39348f2cb..4cf9c30ded 100644
--- a/Doxyfile.in
+++ b/Doxyfile.in
@@ -446,12 +446,6 @@ MAX_INITIALIZER_LINES = 30
SHOW_USED_FILES = YES
-# If the sources in your project are distributed over multiple directories
-# then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy
-# in the documentation. The default is NO.
-
-SHOW_DIRECTORIES = NO
-
# Set the SHOW_FILES tag to NO to disable the generation of the Files page.
# This will remove the Files entry from the Quick Index and from the
# Folder Tree View (if specified). The default is YES.
@@ -760,12 +754,6 @@ HTML_FOOTER =
HTML_STYLESHEET =
-# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes,
-# files or namespaces will be aligned in HTML using tables. If set to
-# NO a bullet list will be used.
-
-HTML_ALIGN_MEMBERS = YES
-
# If the GENERATE_HTMLHELP tag is set to YES, additional index files
# will be generated that can be used as input for tools like the
# Microsoft HTML help workshop to generate a compiled HTML help file (.chm)
@@ -1047,18 +1035,6 @@ GENERATE_XML = NO
XML_OUTPUT = xml
-# The XML_SCHEMA tag can be used to specify an XML schema,
-# which can be used by a validating XML parser to check the
-# syntax of the XML files.
-
-XML_SCHEMA =
-
-# The XML_DTD tag can be used to specify an XML DTD,
-# which can be used by a validating XML parser to check the
-# syntax of the XML files.
-
-XML_DTD =
-
# If the XML_PROGRAMLISTING tag is set to YES Doxygen will
# dump the program listings (including syntax highlighting
# and cross-referencing information) to the XML output. Note that
@@ -1264,7 +1240,7 @@ HAVE_DOT = NO
# DOTFONTPATH environment variable or by setting DOT_FONTPATH to the directory
# containing the font.
-DOT_FONTNAME = FreeSans
+DOT_FONTNAME =
# By default doxygen will tell dot to use the output directory to look for the
# FreeSans.ttf font (which doxygen will put there itself). If you specify a
diff --git a/changes/14881 b/changes/14881
new file mode 100644
index 0000000000..e686c4d982
--- /dev/null
+++ b/changes/14881
@@ -0,0 +1,7 @@
+ o Minor bugfixes (consensus weight):
+ - Add new consensus method that initializes bw weights to 1 instead of 0. This
+ prevents a zero weight from making it all the way to the end (happens in
+ small testing networks) and causing an error. Fixes bug 14881.
+
+ o Minor features (unit tests):
+ - Add tests for networkstatus_compute_bw_weights_v10
diff --git a/changes/20273 b/changes/20273
new file mode 100644
index 0000000000..4b7584d65c
--- /dev/null
+++ b/changes/20273
@@ -0,0 +1,4 @@
+ o Minor bugfixes (comments):
+ - Change '1' to 'weight_scale' in consensus bw weights calculation
+ comments, as that is reality. Fixes bug 20273. Patch from pastly.
+
diff --git a/changes/bug13827 b/changes/bug13827
new file mode 100644
index 0000000000..2235a3fbd7
--- /dev/null
+++ b/changes/bug13827
@@ -0,0 +1,3 @@
+ o Code simplification and refactoring:
+ - Remove duplicate code in the channel_write_*cell() functions.
+ Closes ticket 13827; patch from Pingl.
diff --git a/changes/bug20048 b/changes/bug20048
new file mode 100644
index 0000000000..0874e97e7a
--- /dev/null
+++ b/changes/bug20048
@@ -0,0 +1,4 @@
+ o Minor bugfixes:
+ - Implement smartlist_add_strdup() function. Replaces the use of
+ smartlist_add(sl, tor_strdup(str)). Fixes bug 20048.
+
diff --git a/changes/bug20269 b/changes/bug20269
new file mode 100644
index 0000000000..5d580bf3cc
--- /dev/null
+++ b/changes/bug20269
@@ -0,0 +1,4 @@
+ o Minor bugfixes:
+ - When clients that use bridges start up with a cached consensus
+ on disk, they were ignoring it and downloading a new one. Now they
+ use the cached one. Fixes bug 20269; bugfix on 0.2.3.12-alpha.
diff --git a/changes/bug20389 b/changes/bug20389
new file mode 100644
index 0000000000..8f1b9f5e03
--- /dev/null
+++ b/changes/bug20389
@@ -0,0 +1,4 @@
+ o Minor features (controller):
+ - When HSFETCH arguments cannot be parsed, say "Invalid argument"
+ rather than "unrecognized." Closes ticket 20389; patch from
+ Ivan Markin.
diff --git a/changes/bug20435 b/changes/bug20435
new file mode 100644
index 0000000000..4fd7eb71d6
--- /dev/null
+++ b/changes/bug20435
@@ -0,0 +1,4 @@
+ o Documentation (man page):
+ - Set the default value from 250 KBytes to 2 MBytes for
+ AuthDirGuardBWGuarantee in the man page which is what the code is using;
+ bugfix on tor-0.2.5.6-alpha; Closes ticket 20345.
diff --git a/changes/bug20459 b/changes/bug20459
new file mode 100644
index 0000000000..68781887be
--- /dev/null
+++ b/changes/bug20459
@@ -0,0 +1,3 @@
+ o Minor bugfixes:
+ - Fix ewma_cmp_cmux never considering circuit policies to be different.
+ Introduced in 0.2.6. Fixes bug 20459.
diff --git a/changes/bug6769 b/changes/bug6769
new file mode 100644
index 0000000000..83e3aa8b9e
--- /dev/null
+++ b/changes/bug6769
@@ -0,0 +1,5 @@
+ o Minor bugfixes:
+ - Bridges and relays now use microdescriptors (like clients do)
+ rather than old-style router descriptors. Now bridges will blend in
+ with clients in terms of the circuits they build. Fixes bug 6769;
+ bugfix on 0.2.3.2-alpha.
diff --git a/changes/ticket19858 b/changes/ticket19858
new file mode 100644
index 0000000000..41cc961455
--- /dev/null
+++ b/changes/ticket19858
@@ -0,0 +1,4 @@
+ o Features (guards):
+ - Abolish all global guard context in entrynodes.c; replace with new
+ guard_selection_t structure as preparation for prop. 271. Closes
+ ticket 19858.
diff --git a/changes/ticket20077 b/changes/ticket20077
new file mode 100644
index 0000000000..d5510694ff
--- /dev/null
+++ b/changes/ticket20077
@@ -0,0 +1,5 @@
+ o Code simplification and refactoring:
+ - Remove redundant behavior of is_sensitive_dir_purpose, refactor to use
+ only purpose_needs_anonymity
+ - Refactor large if statement in purpose_needs_anonymity to use switch
+ statement instead.
diff --git a/configure.ac b/configure.ac
index d35f83cead..27d7577a5a 100644
--- a/configure.ac
+++ b/configure.ac
@@ -4,7 +4,7 @@ dnl Copyright (c) 2007-2015, The Tor Project, Inc.
dnl See LICENSE for licensing information
AC_PREREQ([2.63])
-AC_INIT([tor],[0.2.9.4-alpha-dev])
+AC_INIT([tor],[0.3.0.0-alpha-dev])
AC_CONFIG_SRCDIR([src/or/main.c])
AC_CONFIG_MACRO_DIR([m4])
diff --git a/contrib/win32build/tor-mingw.nsi.in b/contrib/win32build/tor-mingw.nsi.in
index 94bbfe28e2..a76bc2207b 100644
--- a/contrib/win32build/tor-mingw.nsi.in
+++ b/contrib/win32build/tor-mingw.nsi.in
@@ -8,7 +8,7 @@
!include "LogicLib.nsh"
!include "FileFunc.nsh"
!insertmacro GetParameters
-!define VERSION "0.2.9.4-alpha-dev"
+!define VERSION "0.3.0.0-alpha-dev"
!define INSTALLER "tor-${VERSION}-win32.exe"
!define WEBSITE "https://www.torproject.org/"
!define LICENSE "LICENSE"
diff --git a/doc/tor.1.txt b/doc/tor.1.txt
index 9d8b631e35..221c798257 100644
--- a/doc/tor.1.txt
+++ b/doc/tor.1.txt
@@ -2248,7 +2248,7 @@ on the public Tor network.
[[AuthDirGuardBWGuarantee]] **AuthDirGuardBWGuarantee** __N__ **bytes**|**KBytes**|**MBytes**|**GBytes**|**KBits**|**MBits**|**GBits**::
Authoritative directories only. If non-zero, this advertised capacity
or more is always sufficient to satisfy the bandwidth requirement
- for the Guard flag. (Default: 250 KBytes)
+ for the Guard flag. (Default: 2 MBytes)
[[AuthDirPinKeys]] **AuthDirPinKeys** **0**|**1**::
Authoritative directories only. If non-zero, do not allow any relay to
diff --git a/src/common/log.c b/src/common/log.c
index 56adc77f84..3b0eb882c3 100644
--- a/src/common/log.c
+++ b/src/common/log.c
@@ -682,7 +682,7 @@ tor_log_get_logfile_names(smartlist_t *out)
continue;
if (lf->filename == NULL)
continue;
- smartlist_add(out, tor_strdup(lf->filename));
+ smartlist_add_strdup(out, lf->filename);
}
UNLOCK_LOGS();
diff --git a/src/common/util.c b/src/common/util.c
index 9162967907..b1159e5334 100644
--- a/src/common/util.c
+++ b/src/common/util.c
@@ -3532,6 +3532,17 @@ smartlist_add_vasprintf(struct smartlist_t *sl, const char *pattern,
smartlist_add(sl, str);
}
+/** Append a copy of string to sl */
+void
+smartlist_add_strdup(struct smartlist_t *sl, const char *string)
+{
+ char *copy;
+
+ copy = tor_strdup(string);
+
+ smartlist_add(sl, copy);
+}
+
/** Return a new list containing the filenames in the directory <b>dirname</b>.
* Return NULL on error or if <b>dirname</b> is not a directory.
*/
@@ -3565,7 +3576,7 @@ tor_listdir, (const char *dirname))
#endif
if (strcmp(name, ".") &&
strcmp(name, "..")) {
- smartlist_add(result, tor_strdup(name));
+ smartlist_add_strdup(result, name);
}
if (!FindNextFile(handle, &findData)) {
DWORD err;
@@ -3591,7 +3602,7 @@ tor_listdir, (const char *dirname))
if (!strcmp(de->d_name, ".") ||
!strcmp(de->d_name, ".."))
continue;
- smartlist_add(result, tor_strdup(de->d_name));
+ smartlist_add_strdup(result, de->d_name);
}
closedir(d);
#endif
@@ -4862,7 +4873,7 @@ get_current_process_environment_variables(void)
char **environ_tmp; /* Not const char ** ? Really? */
for (environ_tmp = get_environment(); *environ_tmp; ++environ_tmp) {
- smartlist_add(sl, tor_strdup(*environ_tmp));
+ smartlist_add_strdup(sl, *environ_tmp);
}
return sl;
@@ -5245,7 +5256,7 @@ tor_get_lines_from_handle, (FILE *handle,
goto done;
if (!lines) lines = smartlist_new();
- smartlist_add(lines, tor_strdup(stdout_buf));
+ smartlist_add_strdup(lines, stdout_buf);
}
done:
diff --git a/src/common/util.h b/src/common/util.h
index 479fc8d610..37f4bed1cb 100644
--- a/src/common/util.h
+++ b/src/common/util.h
@@ -239,6 +239,7 @@ void smartlist_add_asprintf(struct smartlist_t *sl, const char *pattern, ...)
void smartlist_add_vasprintf(struct smartlist_t *sl, const char *pattern,
va_list args)
CHECK_PRINTF(2, 0);
+void smartlist_add_strdup(struct smartlist_t *sl, const char *string);
/* Time helpers */
long tv_udiff(const struct timeval *start, const struct timeval *end);
diff --git a/src/common/util_bug.c b/src/common/util_bug.c
index 08aba47974..c7bfdefe80 100644
--- a/src/common/util_bug.c
+++ b/src/common/util_bug.c
@@ -44,7 +44,7 @@ static void
add_captured_bug(const char *s)
{
--n_bugs_to_capture;
- smartlist_add(bug_messages, tor_strdup(s));
+ smartlist_add_strdup(bug_messages, s);
}
/** Set a callback to be invoked when we get any tor_bug_occurred_
* invocation. We use this in the unit tests so that a nonfatal
diff --git a/src/ext/trunnel/trunnel-impl.h b/src/ext/trunnel/trunnel-impl.h
index 3ffde6e09b..0cbd4f5637 100644
--- a/src/ext/trunnel/trunnel-impl.h
+++ b/src/ext/trunnel/trunnel-impl.h
@@ -1,4 +1,4 @@
-/* trunnel-impl.h -- copied from Trunnel v1.4.6
+/* trunnel-impl.h -- copied from Trunnel v1.5
* https://gitweb.torproject.org/trunnel.git
* You probably shouldn't edit this file.
*/
@@ -17,6 +17,7 @@
#include "trunnel.h"
#include <assert.h>
#include <string.h>
+#include <stdlib.h>
#if defined(_MSC_VER) && (_MSC_VER < 1600)
#define uint8_t unsigned char
diff --git a/src/ext/trunnel/trunnel.c b/src/ext/trunnel/trunnel.c
index 3994422643..f80a587a97 100644
--- a/src/ext/trunnel/trunnel.c
+++ b/src/ext/trunnel/trunnel.c
@@ -1,4 +1,4 @@
-/* trunnel.c -- copied from Trunnel v1.4.6
+/* trunnel.c -- copied from Trunnel v1.5
* https://gitweb.torproject.org/trunnel.git
* You probably shouldn't edit this file.
*/
diff --git a/src/ext/trunnel/trunnel.h b/src/ext/trunnel/trunnel.h
index 41068b8fb3..afd404db0f 100644
--- a/src/ext/trunnel/trunnel.h
+++ b/src/ext/trunnel/trunnel.h
@@ -1,4 +1,4 @@
-/* trunnel.h -- copied from Trunnel v1.4.6
+/* trunnel.h -- copied from Trunnel v1.5
* https://gitweb.torproject.org/trunnel.git
* You probably shouldn't edit this file.
*/
diff --git a/src/or/addressmap.c b/src/or/addressmap.c
index 33fd7e0f4a..85a6434f4a 100644
--- a/src/or/addressmap.c
+++ b/src/or/addressmap.c
@@ -376,29 +376,38 @@ addressmap_rewrite(char *address, size_t maxlen,
char *addr_orig = tor_strdup(address);
char *log_addr_orig = NULL;
+ /* We use a loop here to limit the total number of rewrites we do,
+ * so that we can't hit an infinite loop. */
for (rewrites = 0; rewrites < 16; rewrites++) {
int exact_match = 0;
log_addr_orig = tor_strdup(escaped_safe_str_client(address));
+ /* First check to see if there's an exact match for this address */
ent = strmap_get(addressmap, address);
if (!ent || !ent->new_address) {
+ /* And if we don't have an exact match, try to check whether
+ * we have a pattern-based match.
+ */
ent = addressmap_match_superdomains(address);
} else {
if (ent->src_wildcard && !ent->dst_wildcard &&
!strcasecmp(address, ent->new_address)) {
- /* This is a rule like *.example.com example.com, and we just got
- * "example.com" */
+ /* This is a rule like "rewrite *.example.com to example.com", and we
+ * just got "example.com". Instead of calling it an infinite loop,
+ * call it complete. */
goto done;
}
-
exact_match = 1;
}
if (!ent || !ent->new_address) {
+ /* We still have no match at all. We're done! */
goto done;
}
+ /* Check wither the flags we were passed tell us not to use this
+ * mapping. */
switch (ent->source) {
case ADDRMAPSRC_DNS:
{
@@ -431,6 +440,8 @@ addressmap_rewrite(char *address, size_t maxlen,
goto done;
}
+ /* Now fill in the address with the new address. That might be via
+ * appending some new stuff to the end, or via just replacing it. */
if (ent->dst_wildcard && !exact_match) {
strlcat(address, ".", maxlen);
strlcat(address, ent->new_address, maxlen);
@@ -438,6 +449,7 @@ addressmap_rewrite(char *address, size_t maxlen,
strlcpy(address, ent->new_address, maxlen);
}
+ /* Is this now a .exit address? If so, remember where we got it.*/
if (!strcmpend(address, ".exit") &&
strcmpend(addr_orig, ".exit") &&
exit_source == ADDRMAPSRC_NONE) {
diff --git a/src/or/channel.c b/src/or/channel.c
index f547aea1b3..75aab3cfef 100644
--- a/src/or/channel.c
+++ b/src/or/channel.c
@@ -1838,45 +1838,58 @@ channel_write_cell_queue_entry(channel_t *chan, cell_queue_entry_t *q)
}
}
-/**
- * Write a cell to a channel
+/** Write a generic cell type to a channel
*
- * Write a fixed-length cell to a channel using the write_cell() method.
- * This is equivalent to the pre-channels connection_or_write_cell_to_buf();
- * it is called by the transport-independent code to deliver a cell to a
- * channel for transmission.
+ * Write a generic cell to a channel. It is called by channel_write_cell(),
+ * channel_write_var_cell() and channel_write_packed_cell() in order to reduce
+ * code duplication. Notice that it takes cell as pointer of type void,
+ * this can be dangerous because no type check is performed.
*/
void
-channel_write_cell(channel_t *chan, cell_t *cell)
+channel_write_cell_generic_(channel_t *chan, const char *cell_type,
+ void *cell, cell_queue_entry_t *q)
{
- cell_queue_entry_t q;
tor_assert(chan);
tor_assert(cell);
if (CHANNEL_IS_CLOSING(chan)) {
- log_debug(LD_CHANNEL, "Discarding cell_t %p on closing channel %p with "
- "global ID "U64_FORMAT, cell, chan,
+ log_debug(LD_CHANNEL, "Discarding %c %p on closing channel %p with "
+ "global ID "U64_FORMAT, *cell_type, cell, chan,
U64_PRINTF_ARG(chan->global_identifier));
tor_free(cell);
return;
}
-
log_debug(LD_CHANNEL,
- "Writing cell_t %p to channel %p with global ID "
- U64_FORMAT,
+ "Writing %c %p to channel %p with global ID "
+ U64_FORMAT, *cell_type,
cell, chan, U64_PRINTF_ARG(chan->global_identifier));
- q.type = CELL_QUEUE_FIXED;
- q.u.fixed.cell = cell;
- channel_write_cell_queue_entry(chan, &q);
-
+ channel_write_cell_queue_entry(chan, q);
/* Update the queue size estimate */
channel_update_xmit_queue_size(chan);
}
/**
+ * Write a cell to a channel
+ *
+ * Write a fixed-length cell to a channel using the write_cell() method.
+ * This is equivalent to the pre-channels connection_or_write_cell_to_buf();
+ * it is called by the transport-independent code to deliver a cell to a
+ * channel for transmission.
+ */
+
+void
+channel_write_cell(channel_t *chan, cell_t *cell)
+{
+ cell_queue_entry_t q;
+ q.type = CELL_QUEUE_FIXED;
+ q.u.fixed.cell = cell;
+ channel_write_cell_generic_(chan, "cell_t", cell, &q);
+}
+
+/**
* Write a packed cell to a channel
*
* Write a packed cell to a channel using the write_cell() method. This is
@@ -1888,30 +1901,9 @@ void
channel_write_packed_cell(channel_t *chan, packed_cell_t *packed_cell)
{
cell_queue_entry_t q;
-
- tor_assert(chan);
- tor_assert(packed_cell);
-
- if (CHANNEL_IS_CLOSING(chan)) {
- log_debug(LD_CHANNEL, "Discarding packed_cell_t %p on closing channel %p "
- "with global ID "U64_FORMAT, packed_cell, chan,
- U64_PRINTF_ARG(chan->global_identifier));
- packed_cell_free(packed_cell);
- return;
- }
-
- log_debug(LD_CHANNEL,
- "Writing packed_cell_t %p to channel %p with global ID "
- U64_FORMAT,
- packed_cell, chan,
- U64_PRINTF_ARG(chan->global_identifier));
-
q.type = CELL_QUEUE_PACKED;
q.u.packed.packed_cell = packed_cell;
- channel_write_cell_queue_entry(chan, &q);
-
- /* Update the queue size estimate */
- channel_update_xmit_queue_size(chan);
+ channel_write_cell_generic_(chan, "packed_cell_t", packed_cell, &q);
}
/**
@@ -1927,30 +1919,9 @@ void
channel_write_var_cell(channel_t *chan, var_cell_t *var_cell)
{
cell_queue_entry_t q;
-
- tor_assert(chan);
- tor_assert(var_cell);
-
- if (CHANNEL_IS_CLOSING(chan)) {
- log_debug(LD_CHANNEL, "Discarding var_cell_t %p on closing channel %p "
- "with global ID "U64_FORMAT, var_cell, chan,
- U64_PRINTF_ARG(chan->global_identifier));
- var_cell_free(var_cell);
- return;
- }
-
- log_debug(LD_CHANNEL,
- "Writing var_cell_t %p to channel %p with global ID "
- U64_FORMAT,
- var_cell, chan,
- U64_PRINTF_ARG(chan->global_identifier));
-
q.type = CELL_QUEUE_VAR;
q.u.var.var_cell = var_cell;
- channel_write_cell_queue_entry(chan, &q);
-
- /* Update the queue size estimate */
- channel_update_xmit_queue_size(chan);
+ channel_write_cell_generic_(chan, "var_cell_t", var_cell, &q);
}
/**
diff --git a/src/or/channel.h b/src/or/channel.h
index a711b56d44..44a3901991 100644
--- a/src/or/channel.h
+++ b/src/or/channel.h
@@ -382,6 +382,9 @@ struct cell_queue_entry_s {
STATIC int chan_cell_queue_len(const chan_cell_queue_t *queue);
STATIC void cell_queue_entry_free(cell_queue_entry_t *q, int handed_off);
+
+void channel_write_cell_generic_(channel_t *chan, const char *cell_type,
+ void *cell, cell_queue_entry_t *q);
#endif
/* Channel operations for subclasses and internal use only */
diff --git a/src/or/circpathbias.c b/src/or/circpathbias.c
index 9f93e737f7..6ee69aac1e 100644
--- a/src/or/circpathbias.c
+++ b/src/or/circpathbias.c
@@ -11,6 +11,14 @@
* different tor nodes, in an attempt to detect attacks where
* an attacker deliberately causes circuits to fail until the client
* choses a path they like.
+ *
+ * This code is currently configured in a warning-only mode, though false
+ * positives appear to be rare in practice. There is also support for
+ * disabling really bad guards, but it's quite experimental and may have bad
+ * anonymity effects.
+ *
+ * The information here is associated with the entry_guard_t object for
+ * each guard, and stored persistently in the state file.
*/
#include "or.h"
diff --git a/src/or/circuitbuild.c b/src/or/circuitbuild.c
index cc9b184698..961c16691e 100644
--- a/src/or/circuitbuild.c
+++ b/src/or/circuitbuild.c
@@ -9,6 +9,20 @@
*
* \brief Implements the details of building circuits (by chosing paths,
* constructing/sending create/extend cells, and so on).
+ *
+ * On the client side, this module handles launching circuits. Circuit
+ * launches are srtarted from circuit_establish_circuit(), called from
+ * circuit_launch_by_extend_info()). To choose the path the circuit will
+ * take, onion_extend_cpath() calls into a maze of node selection functions.
+ *
+ * Once the circuit is ready to be launched, the first hop is treated as a
+ * special case with circuit_handle_first_hop(), since it might need to open a
+ * channel. As the channel opens, and later as CREATED and RELAY_EXTENDED
+ * cells arrive, the client will invoke circuit_send_next_onion_skin() to send
+ * CREATE or RELAY_EXTEND cells.
+ *
+ * On the server side, this module also handles the logic of responding to
+ * RELAY_EXTEND requests, using circuit_extend().
**/
#define CIRCUITBUILD_PRIVATE
@@ -2235,7 +2249,6 @@ choose_good_entry_server(uint8_t purpose, cpath_build_state_t *state)
* This is an incomplete fix, but is no worse than the previous behaviour,
* and only applies to minimal, testing tor networks
* (so it's no less secure) */
- /*XXXX++ use the using_as_guard flag to accomplish this.*/
if (options->UseEntryGuards
&& (!options->TestingTorNetwork ||
smartlist_len(nodelist_get_list()) > smartlist_len(get_entry_guards())
diff --git a/src/or/circuitlist.c b/src/or/circuitlist.c
index 2b3c4169cb..a0988c6d93 100644
--- a/src/or/circuitlist.c
+++ b/src/or/circuitlist.c
@@ -7,7 +7,48 @@
/**
* \file circuitlist.c
*
- * \brief Manage the global circuit list, and looking up circuits within it.
+ * \brief Manage global structures that list and index circuits, and
+ * look up circuits within them.
+ *
+ * One of the most frequent operations in Tor occurs every time that
+ * a relay cell arrives on a channel. When that happens, we need to
+ * find which circuit it is associated with, based on the channel and the
+ * circuit ID in the relay cell.
+ *
+ * To handle that, we maintain a global list of circuits, and a hashtable
+ * mapping [channel,circID] pairs to circuits. Circuits are added to and
+ * removed from this mapping using circuit_set_p_circid_chan() and
+ * circuit_set_n_circid_chan(). To look up a circuit from this map, most
+ * callers should use circuit_get_by_circid_channel(), though
+ * circuit_get_by_circid_channel_even_if_marked() is appropriate under some
+ * circumstances.
+ *
+ * We also need to allow for the possibility that we have blocked use of a
+ * circuit ID (because we are waiting to send a DESTROY cell), but the
+ * circuit is not there any more. For that case, we allow placeholder
+ * entries in the table, using channel_mark_circid_unusable().
+ *
+ * To efficiently handle a channel that has just opened, we also maintain a
+ * list of the circuits waiting for channels, so we can attach them as
+ * needed without iterating through the whole list of circuits, using
+ * circuit_get_all_pending_on_channel().
+ *
+ * In this module, we also handle the list of circuits that have been
+ * marked for close elsewhere, and close them as needed. (We use this
+ * "mark now, close later" pattern here and elsewhere to avoid
+ * unpredictable recursion if we closed every circuit immediately upon
+ * realizing it needed to close.) See circuit_mark_for_close() for the
+ * mark function, and circuit_close_all_marked() for the close function.
+ *
+ * For hidden services, we need to be able to look up introduction point
+ * circuits and rendezvous circuits by cookie, key, etc. These are
+ * currently handled with linear searches in
+ * circuit_get_ready_rend_circuit_by_rend_data(),
+ * circuit_get_next_by_pk_and_purpose(), and with hash lookups in
+ * circuit_get_rendezvous() and circuit_get_intro_point().
+ *
+ * This module is also the entry point for our out-of-memory handler
+ * logic, which was originally circuit-focused.
**/
#define CIRCUITLIST_PRIVATE
#include "or.h"
@@ -1539,6 +1580,14 @@ circuit_set_intro_point_digest(or_circuit_t *circ, const uint8_t *digest)
* cannibalize.
*
* If !CIRCLAUNCH_NEED_UPTIME, prefer returning non-uptime circuits.
+ *
+ * To "cannibalize" a circuit means to extend it an extra hop, and use it
+ * for some other purpose than we had originally intended. We do this when
+ * we want to perform some low-bandwidth task at a specific relay, and we
+ * would like the circuit to complete as soon as possible. (If we were going
+ * to use a lot of bandwidth, we wouldn't want a circuit with an extra hop.
+ * If we didn't care about circuit completion latency, we would just build
+ * a new circuit.)
*/
origin_circuit_t *
circuit_find_to_cannibalize(uint8_t purpose, extend_info_t *info,
diff --git a/src/or/circuitmux_ewma.c b/src/or/circuitmux_ewma.c
index 5c2ebde73b..0219459cdb 100644
--- a/src/or/circuitmux_ewma.c
+++ b/src/or/circuitmux_ewma.c
@@ -500,7 +500,7 @@ ewma_cmp_cmux(circuitmux_t *cmux_1, circuitmux_policy_data_t *pol_data_1,
tor_assert(pol_data_2);
p1 = TO_EWMA_POL_DATA(pol_data_1);
- p2 = TO_EWMA_POL_DATA(pol_data_1);
+ p2 = TO_EWMA_POL_DATA(pol_data_2);
if (p1 != p2) {
/* Get the head cell_ewma_t from each queue */
diff --git a/src/or/circuituse.c b/src/or/circuituse.c
index f344703331..11d78201f4 100644
--- a/src/or/circuituse.c
+++ b/src/or/circuituse.c
@@ -6,7 +6,25 @@
/**
* \file circuituse.c
- * \brief Launch the right sort of circuits and attach streams to them.
+ * \brief Launch the right sort of circuits and attach the right streams to
+ * them.
+ *
+ * As distinct from circuitlist.c, which manages lookups to find circuits, and
+ * circuitbuild.c, which handles the logistics of circuit construction, this
+ * module keeps track of which streams can be attached to which circuits (in
+ * circuit_get_best()), and attaches streams to circuits (with
+ * circuit_try_attaching_streams(), connection_ap_handshake_attach_circuit(),
+ * and connection_ap_handshake_attach_chosen_circuit() ).
+ *
+ * This module also makes sure that we are building circuits for all of the
+ * predicted ports, using circuit_remove_handled_ports(),
+ * circuit_stream_is_being_handled(), and circuit_build_needed_cirs(). It
+ * handles launching circuits for specific targets using
+ * circuit_launch_by_extend_info().
+ *
+ * This is also where we handle expiring circuits that have been around for
+ * too long without actually completing, along with the circuit_build_timeout
+ * logic in circuitstats.c.
**/
#include "or.h"
@@ -1858,16 +1876,22 @@ circuit_get_open_circ_or_launch(entry_connection_t *conn,
c->state, conn_state_to_string(c->type, c->state));
}
tor_assert(ENTRY_TO_CONN(conn)->state == AP_CONN_STATE_CIRCUIT_WAIT);
+
+ /* Will the exit policy of the exit node apply to this stream? */
check_exit_policy =
conn->socks_request->command == SOCKS_COMMAND_CONNECT &&
!conn->use_begindir &&
!connection_edge_is_rendezvous_stream(ENTRY_TO_EDGE_CONN(conn));
+
+ /* Does this connection want a one-hop circuit? */
want_onehop = conn->want_onehop;
+ /* Do we need a high-uptime circuit? */
need_uptime = !conn->want_onehop && !conn->use_begindir &&
smartlist_contains_int_as_string(options->LongLivedPorts,
conn->socks_request->port);
+ /* Do we need an "internal" circuit? */
if (desired_circuit_purpose != CIRCUIT_PURPOSE_C_GENERAL)
need_internal = 1;
else if (conn->use_begindir || conn->want_onehop)
@@ -1875,21 +1899,31 @@ circuit_get_open_circ_or_launch(entry_connection_t *conn,
else
need_internal = 0;
- circ = circuit_get_best(conn, 1, desired_circuit_purpose,
+ /* We now know what kind of circuit we need. See if there is an
+ * open circuit that we can use for this stream */
+ circ = circuit_get_best(conn, 1 /* Insist on open circuits */,
+ desired_circuit_purpose,
need_uptime, need_internal);
if (circ) {
+ /* We got a circuit that will work for this stream! We can return it. */
*circp = circ;
return 1; /* we're happy */
}
+ /* Okay, there's no circuit open that will work for this stream. Let's
+ * see if there's an in-progress circuit or if we have to launch one */
+
+ /* Do we know enough directory info to build circuits at all? */
int have_path = have_enough_path_info(!need_internal);
if (!want_onehop && (!router_have_minimum_dir_info() || !have_path)) {
+ /* If we don't have enough directory information, we can't build
+ * multihop circuits.
+ */
if (!connection_get_by_type(CONN_TYPE_DIR)) {
int severity = LOG_NOTICE;
- /* FFFF if this is a tunneled directory fetch, don't yell
- * as loudly. the user doesn't even know it's happening. */
+ /* Retry some stuff that might help the connection work. */
if (entry_list_is_constrained(options) &&
entries_known_but_down(options)) {
log_fn(severity, LD_APP|LD_DIR,
@@ -1910,14 +1944,16 @@ circuit_get_open_circ_or_launch(entry_connection_t *conn,
routerlist_retry_directory_downloads(time(NULL));
}
}
- /* the stream will be dealt with when router_have_minimum_dir_info becomes
- * 1, or when all directory attempts fail and directory_all_unreachable()
+ /* Since we didn't have enough directory info, we can't attach now. The
+ * stream will be dealt with when router_have_minimum_dir_info becomes 1,
+ * or when all directory attempts fail and directory_all_unreachable()
* kills it.
*/
return 0;
}
- /* Do we need to check exit policy? */
+ /* Check whether the exit policy of the chosen exit, or the exit policies
+ * of _all_ nodes, would forbid this node. */
if (check_exit_policy) {
if (!conn->chosen_exit_name) {
struct in_addr in;
@@ -1958,16 +1994,25 @@ circuit_get_open_circ_or_launch(entry_connection_t *conn,
}
}
- /* is one already on the way? */
- circ = circuit_get_best(conn, 0, desired_circuit_purpose,
+ /* Now, check whether there already a circuit on the way that could handle
+ * this stream. This check matches the one above, but this time we
+ * do not require that the circuit will work. */
+ circ = circuit_get_best(conn, 0 /* don't insist on open circuits */,
+ desired_circuit_purpose,
need_uptime, need_internal);
if (circ)
log_debug(LD_CIRC, "one on the way!");
+
if (!circ) {
+ /* No open or in-progress circuit could handle this stream! We
+ * will have to launch one!
+ */
+
+ /* THe chosen exit node, if there is one. */
extend_info_t *extend_info=NULL;
- uint8_t new_circ_purpose;
const int n_pending = count_pending_general_client_circuits();
+ /* Do we have too many pending circuits? */
if (n_pending >= options->MaxClientCircuitsPending) {
static ratelim_t delay_limit = RATELIM_INIT(10*60);
char *m;
@@ -1981,6 +2026,8 @@ circuit_get_open_circ_or_launch(entry_connection_t *conn,
return 0;
}
+ /* If this is a hidden service trying to start an introduction point,
+ * handle that case. */
if (desired_circuit_purpose == CIRCUIT_PURPOSE_C_INTRODUCE_ACK_WAIT) {
/* need to pick an intro point */
rend_data_t *rend_data = ENTRY_TO_EDGE_CONN(conn)->rend_data;
@@ -2018,7 +2065,7 @@ circuit_get_open_circ_or_launch(entry_connection_t *conn,
"Discarding this circuit.", conn->chosen_exit_name);
return -1;
}
- } else {
+ } else { /* ! (r && node_has_descriptor(r)) */
log_debug(LD_DIR, "considering %d, %s",
want_onehop, conn->chosen_exit_name);
if (want_onehop && conn->chosen_exit_name[0] == '$') {
@@ -2041,7 +2088,7 @@ circuit_get_open_circ_or_launch(entry_connection_t *conn,
extend_info = extend_info_new(conn->chosen_exit_name+1,
digest, NULL, NULL, &addr,
conn->socks_request->port);
- } else {
+ } else { /* ! (want_onehop && conn->chosen_exit_name[0] == '$') */
/* We will need an onion key for the router, and we
* don't have one. Refuse or relax requirements. */
log_fn(opt ? LOG_INFO : LOG_WARN, LD_APP,
@@ -2059,8 +2106,10 @@ circuit_get_open_circ_or_launch(entry_connection_t *conn,
}
}
}
- }
+ } /* Done checking for general circutis with chosen exits. */
+ /* What purpose do we need to launch this circuit with? */
+ uint8_t new_circ_purpose;
if (desired_circuit_purpose == CIRCUIT_PURPOSE_C_REND_JOINED)
new_circ_purpose = CIRCUIT_PURPOSE_C_ESTABLISH_REND;
else if (desired_circuit_purpose == CIRCUIT_PURPOSE_C_INTRODUCE_ACK_WAIT)
@@ -2069,6 +2118,8 @@ circuit_get_open_circ_or_launch(entry_connection_t *conn,
new_circ_purpose = desired_circuit_purpose;
#ifdef ENABLE_TOR2WEB_MODE
+ /* If tor2Web is on, then hidden service requests should be one-hop.
+ */
if (options->Tor2webMode &&
(new_circ_purpose == CIRCUIT_PURPOSE_C_ESTABLISH_REND ||
new_circ_purpose == CIRCUIT_PURPOSE_C_INTRODUCING)) {
@@ -2076,6 +2127,7 @@ circuit_get_open_circ_or_launch(entry_connection_t *conn,
}
#endif
+ /* Determine what kind of a circuit to launch, and actually launch it. */
{
int flags = CIRCLAUNCH_NEED_CAPACITY;
if (want_onehop) flags |= CIRCLAUNCH_ONEHOP_TUNNEL;
@@ -2087,6 +2139,8 @@ circuit_get_open_circ_or_launch(entry_connection_t *conn,
extend_info_free(extend_info);
+ /* Now trigger things that need to happen when we launch circuits */
+
if (desired_circuit_purpose == CIRCUIT_PURPOSE_C_GENERAL) {
/* We just caused a circuit to get built because of this stream.
* If this stream has caused a _lot_ of circuits to be built, that's
@@ -2110,6 +2164,10 @@ circuit_get_open_circ_or_launch(entry_connection_t *conn,
}
}
} /* endif (!circ) */
+
+ /* We either found a good circuit, or launched a new circuit, or failed to
+ * do so. Report success, and delay. */
+
if (circ) {
/* Mark the circuit with the isolation fields for this connection.
* When the circuit arrives, we'll clear these flags: this is
@@ -2309,7 +2367,9 @@ connection_ap_handshake_attach_chosen_circuit(entry_connection_t *conn,
pathbias_count_use_attempt(circ);
+ /* Now, actually link the connection. */
link_apconn_to_circ(conn, circ, cpath);
+
tor_assert(conn->socks_request);
if (conn->socks_request->command == SOCKS_COMMAND_CONNECT) {
if (!conn->use_begindir)
@@ -2324,12 +2384,11 @@ connection_ap_handshake_attach_chosen_circuit(entry_connection_t *conn,
return 1;
}
-/** Try to find a safe live circuit for CONN_TYPE_AP connection conn. If
- * we don't find one: if conn cannot be handled by any known nodes,
- * warn and return -1 (conn needs to die, and is maybe already marked);
- * else launch new circuit (if necessary) and return 0.
- * Otherwise, associate conn with a safe live circuit, do the
- * right next step, and return 1.
+/** Try to find a safe live circuit for stream <b>conn</b>. If we find one,
+ * attach the stream, send appropriate cells, and return 1. Otherwise,
+ * try to launch new circuit(s) for the stream. If we can launch
+ * circuits, return 0. Otherwise, if we simply can't proceed with
+ * this stream, return -1. (conn needs to die, and is maybe already marked).
*/
/* XXXX this function should mark for close whenever it returns -1;
* its callers shouldn't have to worry about that. */
@@ -2348,6 +2407,7 @@ connection_ap_handshake_attach_circuit(entry_connection_t *conn)
conn_age = (int)(time(NULL) - base_conn->timestamp_created);
+ /* Is this connection so old that we should give up on it? */
if (conn_age >= get_options()->SocksTimeout) {
int severity = (tor_addr_is_null(&base_conn->addr) && !base_conn->port) ?
LOG_INFO : LOG_NOTICE;
@@ -2358,12 +2418,14 @@ connection_ap_handshake_attach_circuit(entry_connection_t *conn)
return -1;
}
+ /* We handle "general" (non-onion) connections much more straightforwardly.
+ */
if (!connection_edge_is_rendezvous_stream(ENTRY_TO_EDGE_CONN(conn))) {
/* we're a general conn */
origin_circuit_t *circ=NULL;
/* Are we linked to a dir conn that aims to fetch a consensus?
- * We check here because this conn might no longer be needed. */
+ * We check here because the conn might no longer be needed. */
if (base_conn->linked_conn &&
base_conn->linked_conn->type == CONN_TYPE_DIR &&
base_conn->linked_conn->purpose == DIR_PURPOSE_FETCH_CONSENSUS) {
@@ -2381,6 +2443,9 @@ connection_ap_handshake_attach_circuit(entry_connection_t *conn)
}
}
+ /* If we have a chosen exit, we need to use a circuit that's
+ * open to that exit. See what exit we meant, and whether we can use it.
+ */
if (conn->chosen_exit_name) {
const node_t *node = node_get_by_nickname(conn->chosen_exit_name, 1);
int opt = conn->chosen_exit_optional;
@@ -2394,6 +2459,7 @@ connection_ap_handshake_attach_circuit(entry_connection_t *conn)
"Requested exit point '%s' is not known. %s.",
conn->chosen_exit_name, opt ? "Trying others" : "Closing");
if (opt) {
+ /* If we are allowed to ignore the .exit request, do so */
conn->chosen_exit_optional = 0;
tor_free(conn->chosen_exit_name);
return 0;
@@ -2406,6 +2472,7 @@ connection_ap_handshake_attach_circuit(entry_connection_t *conn)
"would refuse request. %s.",
conn->chosen_exit_name, opt ? "Trying others" : "Closing");
if (opt) {
+ /* If we are allowed to ignore the .exit request, do so */
conn->chosen_exit_optional = 0;
tor_free(conn->chosen_exit_name);
return 0;
@@ -2414,11 +2481,15 @@ connection_ap_handshake_attach_circuit(entry_connection_t *conn)
}
}
- /* find the circuit that we should use, if there is one. */
+ /* Find the circuit that we should use, if there is one. Otherwise
+ * launch it. */
retval = circuit_get_open_circ_or_launch(
conn, CIRCUIT_PURPOSE_C_GENERAL, &circ);
- if (retval < 1) // XXXX++ if we totally fail, this still returns 0 -RD
+ if (retval < 1) {
+ /* We were either told "-1" (complete failure) or 0 (circuit in
+ * progress); we can't attach this stream yet. */
return retval;
+ }
log_debug(LD_APP|LD_CIRC,
"Attaching apconn to circ %u (stream %d sec old).",
@@ -2427,7 +2498,8 @@ connection_ap_handshake_attach_circuit(entry_connection_t *conn)
* sucking. */
circuit_log_path(LOG_INFO,LD_APP|LD_CIRC,circ);
- /* We have found a suitable circuit for our conn. Hurray. */
+ /* We have found a suitable circuit for our conn. Hurray. Do
+ * the attachment. */
return connection_ap_handshake_attach_chosen_circuit(conn, circ, NULL);
} else { /* we're a rendezvous conn */
diff --git a/src/or/config.c b/src/or/config.c
index 08c576e3d4..fef12083e0 100644
--- a/src/or/config.c
+++ b/src/or/config.c
@@ -6,7 +6,56 @@
/**
* \file config.c
- * \brief Code to parse and interpret configuration files.
+ * \brief Code to interpret the user's configuration of Tor.
+ *
+ * This module handles torrc configuration file, including parsing it,
+ * combining it with torrc.defaults and the command line, allowing
+ * user changes to it (via editing and SIGHUP or via the control port),
+ * writing it back to disk (because of SAVECONF from the control port),
+ * and -- most importantly, acting on it.
+ *
+ * The module additionally has some tools for manipulating and
+ * inspecting values that are calculated as a result of the
+ * configured options.
+ *
+ * <h3>How to add new options</h3>
+ *
+ * To add new items to the torrc, there are a minimum of three places to edit:
+ * <ul>
+ * <li>The or_options_t structure in or.h, where the options are stored.
+ * <li>The option_vars_ array below in this module, which configures
+ * the names of the torrc options, their types, their multiplicities,
+ * and their mappings to fields in or_options_t.
+ * <li>The manual in doc/tor.1.txt, to document what the new option
+ * is, and how it works.
+ * </ul>
+ *
+ * Additionally, you might need to edit these places too:
+ * <ul>
+ * <li>options_validate() below, in case you want to reject some possible
+ * values of the new configuration option.
+ * <li>options_transition_allowed() below, in case you need to
+ * forbid some or all changes in the option while Tor is
+ * running.
+ * <li>options_transition_affects_workers(), in case changes in the option
+ * might require Tor to relaunch or reconfigure its worker threads.
+ * <li>options_transition_affects_descriptor(), in case changes in the
+ * option might require a Tor relay to build and publish a new server
+ * descriptor.
+ * <li>options_act() and/or options_act_reversible(), in case there's some
+ * action that needs to be taken immediately based on the option's
+ * value.
+ * </ul>
+ *
+ * <h3>Changing the value of an option</h3>
+ *
+ * Because of the SAVECONF command from the control port, it's a bad
+ * idea to change the value of any user-configured option in the
+ * or_options_t. If you want to sometimes do this anyway, we recommend
+ * that you create a secondary field in or_options_t; that you have the
+ * user option linked only to the secondary field; that you use the
+ * secondary field to initialize the one that Tor actually looks at; and that
+ * you use the one Tor looks as the one that you modify.
**/
#define CONFIG_PRIVATE
@@ -781,7 +830,7 @@ set_options(or_options_t *new_val, char **msg)
tor_free(line);
}
} else {
- smartlist_add(elements, tor_strdup(options_format.vars[i].name));
+ smartlist_add_strdup(elements, options_format.vars[i].name);
smartlist_add(elements, NULL);
}
}
@@ -5335,7 +5384,7 @@ options_init_logs(const or_options_t *old_options, or_options_t *options,
SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 2);
if (smartlist_len(elts) == 0)
- smartlist_add(elts, tor_strdup("stdout"));
+ smartlist_add_strdup(elts, "stdout");
if (smartlist_len(elts) == 1 &&
(!strcasecmp(smartlist_get(elts,0), "stdout") ||
@@ -5870,7 +5919,7 @@ get_options_from_transport_options_line(const char *line,const char *transport)
}
/* add it to the options smartlist */
- smartlist_add(options, tor_strdup(option));
+ smartlist_add_strdup(options, option);
log_debug(LD_CONFIG, "Added %s to the list of options", escaped(option));
} SMARTLIST_FOREACH_END(option);
diff --git a/src/or/confparse.c b/src/or/confparse.c
index efcf4f981e..ca54284dba 100644
--- a/src/or/confparse.c
+++ b/src/or/confparse.c
@@ -1,3 +1,4 @@
+
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
@@ -9,6 +10,16 @@
*
* \brief Back-end for parsing and generating key-value files, used to
* implement the torrc file format and the state file.
+ *
+ * This module is used by config.c to parse and encode torrc
+ * configuration files, and by statefile.c to parse and encode the
+ * $DATADIR/state file.
+ *
+ * To use this module, its callers provide an instance of
+ * config_format_t to describe the mappings from a set of configuration
+ * options to a number of fields in a C structure. With this mapping,
+ * the functions here can convert back and forth between the C structure
+ * specified, and a linked list of key-value pairs.
*/
#include "or.h"
diff --git a/src/or/connection_edge.c b/src/or/connection_edge.c
index 24842e4107..27a025173c 100644
--- a/src/or/connection_edge.c
+++ b/src/or/connection_edge.c
@@ -830,7 +830,8 @@ connection_ap_rescan_and_attach_pending(void)
#endif
/** Tell any AP streams that are listed as waiting for a new circuit to try
- * again, either attaching to an available circ or launching a new one.
+ * again. If there is an available circuit for a stream, attach it. Otherwise,
+ * launch a new circuit.
*
* If <b>retry</b> is false, only check the list if it contains at least one
* streams that we have not yet tried to attach to a circuit.
@@ -845,8 +846,9 @@ connection_ap_attach_pending(int retry)
if (untried_pending_connections == 0 && !retry)
return;
- /* Don't allow modifications to pending_entry_connections while we are
- * iterating over it. */
+ /* Don't allow any modifications to list while we are iterating over
+ * it. We'll put streams back on this list if we can't attach them
+ * immediately. */
smartlist_t *pending = pending_entry_connections;
pending_entry_connections = smartlist_new();
@@ -873,6 +875,7 @@ connection_ap_attach_pending(int retry)
continue;
}
+ /* Okay, we're through the sanity checks. Try to handle this stream. */
if (connection_ap_handshake_attach_circuit(entry_conn) < 0) {
if (!conn->marked_for_close)
connection_mark_unattached_ap(entry_conn,
@@ -882,12 +885,17 @@ connection_ap_attach_pending(int retry)
if (! conn->marked_for_close &&
conn->type == CONN_TYPE_AP &&
conn->state == AP_CONN_STATE_CIRCUIT_WAIT) {
+ /* Is it still waiting for a circuit? If so, we didn't attach it,
+ * so it's still pending. Put it back on the list.
+ */
if (!smartlist_contains(pending_entry_connections, entry_conn)) {
smartlist_add(pending_entry_connections, entry_conn);
continue;
}
}
+ /* If we got here, then we either closed the connection, or
+ * we attached it. */
UNMARK();
} SMARTLIST_FOREACH_END(entry_conn);
@@ -1186,6 +1194,8 @@ connection_ap_handshake_rewrite(entry_connection_t *conn,
/* Remember the original address so we can tell the user about what
* they actually said, not just what it turned into. */
+ /* XXX yes, this is the same as out->orig_address above. One is
+ * in the output, and one is in the connection. */
if (! conn->original_dest_address) {
/* Is the 'if' necessary here? XXXX */
conn->original_dest_address = tor_strdup(conn->socks_request->address);
@@ -1193,7 +1203,7 @@ connection_ap_handshake_rewrite(entry_connection_t *conn,
/* First, apply MapAddress and MAPADDRESS mappings. We need to do
* these only for non-reverse lookups, since they don't exist for those.
- * We need to do this before we consider automapping, since we might
+ * We also need to do this before we consider automapping, since we might
* e.g. resolve irc.oftc.net into irconionaddress.onion, at which point
* we'd need to automap it. */
if (socks->command != SOCKS_COMMAND_RESOLVE_PTR) {
@@ -1205,9 +1215,12 @@ connection_ap_handshake_rewrite(entry_connection_t *conn,
}
}
- /* Now, handle automapping. Automapping happens when we're asked to
- * resolve a hostname, and AutomapHostsOnResolve is set, and
- * the hostname has a suffix listed in AutomapHostsSuffixes.
+ /* Now see if we need to create or return an existing Hostname->IP
+ * automapping. Automapping happens when we're asked to resolve a
+ * hostname, and AutomapHostsOnResolve is set, and the hostname has a
+ * suffix listed in AutomapHostsSuffixes. It's a handy feature
+ * that lets you have Tor assign e.g. IPv6 addresses for .onion
+ * names, and return them safely from DNSPort.
*/
if (socks->command == SOCKS_COMMAND_RESOLVE &&
tor_addr_parse(&addr_tmp, socks->address)<0 &&
@@ -1247,7 +1260,8 @@ connection_ap_handshake_rewrite(entry_connection_t *conn,
}
/* Now handle reverse lookups, if they're in the cache. This doesn't
- * happen too often, since client-side DNS caching is off by default. */
+ * happen too often, since client-side DNS caching is off by default,
+ * and very deprecated. */
if (socks->command == SOCKS_COMMAND_RESOLVE_PTR) {
unsigned rewrite_flags = 0;
if (conn->entry_cfg.use_cached_ipv4_answers)
@@ -1292,11 +1306,12 @@ connection_ap_handshake_rewrite(entry_connection_t *conn,
}
}
- /* If we didn't automap it before, then this is still the address
- * that came straight from the user, mapped according to any
- * MapAddress/MAPADDRESS commands. Now other mappings, including
- * previously registered Automap entries, TrackHostExits entries,
- * and client-side DNS cache entries (not recommended).
+ /* If we didn't automap it before, then this is still the address that
+ * came straight from the user, mapped according to any
+ * MapAddress/MAPADDRESS commands. Now apply other mappings,
+ * including previously registered Automap entries (IP back to
+ * hostname), TrackHostExits entries, and client-side DNS cache
+ * entries (if they're turned on).
*/
if (socks->command != SOCKS_COMMAND_RESOLVE_PTR &&
!out->automap) {
@@ -1361,11 +1376,14 @@ connection_ap_handshake_rewrite_and_attach(entry_connection_t *conn,
time_t now = time(NULL);
rewrite_result_t rr;
+ /* First we'll do the rewrite part. Let's see if we get a reasonable
+ * answer.
+ */
memset(&rr, 0, sizeof(rr));
connection_ap_handshake_rewrite(conn,&rr);
if (rr.should_close) {
- /* connection_ap_handshake_rewrite told us to close the connection,
+ /* connection_ap_handshake_rewrite told us to close the connection:
* either because it sent back an answer, or because it sent back an
* error */
connection_mark_unattached_ap(conn, rr.end_reason);
@@ -1379,8 +1397,8 @@ connection_ap_handshake_rewrite_and_attach(entry_connection_t *conn,
const int automap = rr.automap;
const addressmap_entry_source_t exit_source = rr.exit_source;
- /* Parse the address provided by SOCKS. Modify it in-place if it
- * specifies a hidden-service (.onion) or particular exit node (.exit).
+ /* Now, we parse the address to see if it's an .onion or .exit or
+ * other special address.
*/
const hostname_type_t addresstype = parse_extended_hostname(socks->address);
@@ -1394,8 +1412,8 @@ connection_ap_handshake_rewrite_and_attach(entry_connection_t *conn,
}
/* If this is a .exit hostname, strip off the .name.exit part, and
- * see whether we're going to connect there, and otherwise handle it.
- * (The ".exit" part got stripped off by "parse_extended_hostname").
+ * see whether we're willing to connect there, and and otherwise handle the
+ * .exit address.
*
* We'll set chosen_exit_name and/or close the connection as appropriate.
*/
@@ -1407,7 +1425,7 @@ connection_ap_handshake_rewrite_and_attach(entry_connection_t *conn,
const node_t *node = NULL;
/* If this .exit was added by an AUTOMAP, then it came straight from
- * a user. Make sure that options->AllowDotExit permits that. */
+ * a user. Make sure that options->AllowDotExit permits that! */
if (exit_source == ADDRMAPSRC_AUTOMAP && !options->AllowDotExit) {
/* Whoops; this one is stale. It must have gotten added earlier,
* when AllowDotExit was on. */
@@ -1436,7 +1454,12 @@ connection_ap_handshake_rewrite_and_attach(entry_connection_t *conn,
}
tor_assert(!automap);
- /* Now, find the character before the .(name) part. */
+
+ /* Now, find the character before the .(name) part.
+ * (The ".exit" part got stripped off by "parse_extended_hostname").
+ *
+ * We're going to put the exit name into conn->chosen_exit_name, and
+ * look up a node correspondingly. */
char *s = strrchr(socks->address,'.');
if (s) {
/* The address was of the form "(stuff).(name).exit */
@@ -1492,10 +1515,12 @@ connection_ap_handshake_rewrite_and_attach(entry_connection_t *conn,
implies no. */
}
- /* Now, handle everything that isn't a .onion address. */
+ /* Now, we handle everything that isn't a .onion address. */
if (addresstype != ONION_HOSTNAME) {
/* Not a hidden-service request. It's either a hostname or an IP,
- * possibly with a .exit that we stripped off. */
+ * possibly with a .exit that we stripped off. We're going to check
+ * if we're allowed to connect/resolve there, and then launch the
+ * appropriate request. */
/* Check for funny characters in the address. */
if (address_is_invalid_destination(socks->address, 1)) {
@@ -1542,30 +1567,37 @@ connection_ap_handshake_rewrite_and_attach(entry_connection_t *conn,
}
/* Then check if we have a hostname or IP address, and whether DNS or
- * the IP address family are permitted */
+ * the IP address family are permitted. Reject if not. */
tor_addr_t dummy_addr;
int socks_family = tor_addr_parse(&dummy_addr, socks->address);
/* family will be -1 for a non-onion hostname that's not an IP */
- if (socks_family == -1 && !conn->entry_cfg.dns_request) {
- log_warn(LD_APP, "Refusing to connect to hostname %s "
- "because Port has NoDNSRequest set.",
- safe_str_client(socks->address));
- connection_mark_unattached_ap(conn, END_STREAM_REASON_ENTRYPOLICY);
- return -1;
- } else if (socks_family == AF_INET && !conn->entry_cfg.ipv4_traffic) {
- log_warn(LD_APP, "Refusing to connect to IPv4 address %s because "
- "Port has NoIPv4Traffic set.",
- safe_str_client(socks->address));
- connection_mark_unattached_ap(conn, END_STREAM_REASON_ENTRYPOLICY);
- return -1;
- } else if (socks_family == AF_INET6 && !conn->entry_cfg.ipv6_traffic) {
- log_warn(LD_APP, "Refusing to connect to IPv6 address %s because "
- "Port has NoIPv6Traffic set.",
- safe_str_client(socks->address));
- connection_mark_unattached_ap(conn, END_STREAM_REASON_ENTRYPOLICY);
- return -1;
+ if (socks_family == -1) {
+ if (!conn->entry_cfg.dns_request) {
+ log_warn(LD_APP, "Refusing to connect to hostname %s "
+ "because Port has NoDNSRequest set.",
+ safe_str_client(socks->address));
+ connection_mark_unattached_ap(conn, END_STREAM_REASON_ENTRYPOLICY);
+ return -1;
+ }
+ } else if (socks_family == AF_INET) {
+ if (!conn->entry_cfg.ipv4_traffic) {
+ log_warn(LD_APP, "Refusing to connect to IPv4 address %s because "
+ "Port has NoIPv4Traffic set.",
+ safe_str_client(socks->address));
+ connection_mark_unattached_ap(conn, END_STREAM_REASON_ENTRYPOLICY);
+ return -1;
+ }
+ } else if (socks_family == AF_INET6) {
+ if (!conn->entry_cfg.ipv6_traffic) {
+ log_warn(LD_APP, "Refusing to connect to IPv6 address %s because "
+ "Port has NoIPv6Traffic set.",
+ safe_str_client(socks->address));
+ connection_mark_unattached_ap(conn, END_STREAM_REASON_ENTRYPOLICY);
+ return -1;
+ }
+ } else {
+ tor_assert_nonfatal_unreached_once();
}
- /* No else, we've covered all possible returned value. */
/* See if this is a hostname lookup that we can answer immediately.
* (For example, an attempt to look up the IP address for an IP address.)
@@ -1585,7 +1617,10 @@ connection_ap_handshake_rewrite_and_attach(entry_connection_t *conn,
}
tor_assert(!automap);
rep_hist_note_used_resolve(now); /* help predict this next time */
- } else if (socks->command == SOCKS_COMMAND_CONNECT) {
+ }
+
+ /* Now see if this is a connect request that we can reject immediately */
+ if (socks->command == SOCKS_COMMAND_CONNECT) {
/* Special handling for attempts to connect */
tor_assert(!automap);
/* Don't allow connections to port 0. */
@@ -1639,7 +1674,9 @@ connection_ap_handshake_rewrite_and_attach(entry_connection_t *conn,
} /* end "if we should check for internal addresses" */
/* Okay. We're still doing a CONNECT, and it wasn't a private
- * address. Do special handling for literal IP addresses */
+ * address. Here we do special handling for literal IP addresses,
+ * to see if we should reject this preemptively, and to set up
+ * fields in conn->entry_cfg to tell the exit what AF we want. */
{
tor_addr_t addr;
/* XXX Duplicate call to tor_addr_parse. */
@@ -1682,11 +1719,15 @@ connection_ap_handshake_rewrite_and_attach(entry_connection_t *conn,
}
}
+ /* we never allow IPv6 answers on socks4. (TODO: Is this smart?) */
if (socks->socks_version == 4)
conn->entry_cfg.ipv6_traffic = 0;
/* Still handling CONNECT. Now, check for exit enclaves. (Which we
- * don't do on BEGINDIR, or there is a chosen exit.)
+ * don't do on BEGINDIR, or when there is a chosen exit.)
+ *
+ * TODO: Should we remove this? Exit enclaves are nutty and don't
+ * work very well
*/
if (!conn->use_begindir && !conn->chosen_exit_name && !circ) {
/* see if we can find a suitable enclave exit */
@@ -1710,7 +1751,8 @@ connection_ap_handshake_rewrite_and_attach(entry_connection_t *conn,
if (consider_plaintext_ports(conn, socks->port) < 0)
return -1;
- /* Remember the port so that we do predicted requests there. */
+ /* Remember the port so that we will predict that more requests
+ there will happen in the future. */
if (!conn->use_begindir) {
/* help predict this next time */
rep_hist_note_used_port(now, socks->port);
@@ -1735,6 +1777,8 @@ connection_ap_handshake_rewrite_and_attach(entry_connection_t *conn,
if (circ) {
rv = connection_ap_handshake_attach_chosen_circuit(conn, circ, cpath);
} else {
+ /* We'll try to attach it at the next event loop, or whenever
+ * we call connection_ap_attach_pending() */
connection_ap_mark_as_pending_circuit(conn);
rv = 0;
}
@@ -1811,8 +1855,8 @@ connection_ap_handshake_rewrite_and_attach(entry_connection_t *conn,
log_info(LD_REND,"Got a hidden service request for ID '%s'",
safe_str_client(rend_data->onion_address));
- /* Lookup the given onion address. If invalid, stop right now else we
- * might have it in the cache or not, it will be tested later on. */
+ /* Lookup the given onion address. If invalid, stop right now.
+ * Otherwise, we might have it in the cache or not. */
unsigned int refetch_desc = 0;
rend_cache_entry_t *entry = NULL;
const int rend_cache_lookup_result =
@@ -1826,6 +1870,7 @@ connection_ap_handshake_rewrite_and_attach(entry_connection_t *conn,
connection_mark_unattached_ap(conn, END_STREAM_REASON_TORPROTOCOL);
return -1;
case ENOENT:
+ /* We didn't have this; we should look it up. */
refetch_desc = 1;
break;
default:
@@ -1835,8 +1880,9 @@ connection_ap_handshake_rewrite_and_attach(entry_connection_t *conn,
}
}
- /* Help predict this next time. We're not sure if it will need
- * a stable circuit yet, but we know we'll need *something*. */
+ /* Help predict that we'll want to do hidden service circuits in the
+ * future. We're not sure if it will need a stable circuit yet, but
+ * we know we'll need *something*. */
rep_hist_note_used_internal(now, 0, 1);
/* Now we have a descriptor but is it usable or not? If not, refetch.
@@ -1851,9 +1897,12 @@ connection_ap_handshake_rewrite_and_attach(entry_connection_t *conn,
return 0;
}
- /* We have the descriptor so launch a connection to the HS. */
+ /* We have the descriptor! So launch a connection to the HS. */
base_conn->state = AP_CONN_STATE_CIRCUIT_WAIT;
log_info(LD_REND, "Descriptor is here. Great.");
+
+ /* We'll try to attach it at the next event loop, or whenever
+ * we call connection_ap_attach_pending() */
connection_ap_mark_as_pending_circuit(conn);
return 0;
}
@@ -2434,7 +2483,9 @@ connection_ap_handshake_send_begin(entry_connection_t *ap_conn)
* Otherwise, directory connections are typically one-hop.
* This matches the earlier check for directory connection path anonymity
* in directory_initiate_command_rend(). */
- if (is_sensitive_dir_purpose(linked_dir_conn_base->purpose)) {
+ if (purpose_needs_anonymity(linked_dir_conn_base->purpose,
+ TO_DIR_CONN(linked_dir_conn_base)->router_purpose,
+ TO_DIR_CONN(linked_dir_conn_base)->requested_resource)) {
assert_circ_anonymity_ok(circ, options);
}
} else {
diff --git a/src/or/control.c b/src/or/control.c
index a4f8e3713b..6e45fe99e9 100644
--- a/src/or/control.c
+++ b/src/or/control.c
@@ -942,7 +942,7 @@ control_setconf_helper(control_connection_t *conn, uint32_t len, char *body,
++body;
}
- smartlist_add(entries, tor_strdup(""));
+ smartlist_add_strdup(entries, "");
config = smartlist_join_strings(entries, "\n", 0, NULL);
SMARTLIST_FOREACH(entries, char *, cp, tor_free(cp));
smartlist_free(entries);
@@ -3139,7 +3139,7 @@ handle_control_getinfo(control_connection_t *conn, uint32_t len,
if (!ans) {
smartlist_add(unrecognized, (char*)q);
} else {
- smartlist_add(answers, tor_strdup(q));
+ smartlist_add_strdup(answers, q);
smartlist_add(answers, ans);
}
} SMARTLIST_FOREACH_END(q);
@@ -4081,7 +4081,7 @@ handle_control_hsfetch(control_connection_t *conn, uint32_t len,
* of the id. */
desc_id = digest;
} else {
- connection_printf_to_buf(conn, "513 Unrecognized \"%s\"\r\n",
+ connection_printf_to_buf(conn, "513 Invalid argument \"%s\"\r\n",
arg1);
goto done;
}
@@ -6045,9 +6045,9 @@ control_event_networkstatus_changed_helper(smartlist_t *statuses,
return 0;
strs = smartlist_new();
- smartlist_add(strs, tor_strdup("650+"));
- smartlist_add(strs, tor_strdup(event_string));
- smartlist_add(strs, tor_strdup("\r\n"));
+ smartlist_add_strdup(strs, "650+");
+ smartlist_add_strdup(strs, event_string);
+ smartlist_add_strdup(strs, "\r\n");
SMARTLIST_FOREACH(statuses, const routerstatus_t *, rs,
{
s = networkstatus_getinfo_helper_single(rs);
diff --git a/src/or/directory.c b/src/or/directory.c
index 1f894d9fb3..fdfb3391a8 100644
--- a/src/or/directory.c
+++ b/src/or/directory.c
@@ -40,9 +40,38 @@
/**
* \file directory.c
- * \brief Code to send and fetch directories and router
- * descriptors via HTTP. Directories use dirserv.c to generate the
- * results; clients use routers.c to parse them.
+ * \brief Code to send and fetch information from directory authorities and
+ * caches via HTTP.
+ *
+ * Directory caches and authorities use dirserv.c to generate the results of a
+ * query and stream them to the connection; clients use routerparse.c to parse
+ * them.
+ *
+ * Every directory request has a dir_connection_t on the client side and on
+ * the server side. In most cases, the dir_connection_t object is a linked
+ * connection, tunneled through an edge_connection_t so that it can be a
+ * stream on the Tor network. The only non-tunneled connections are those
+ * that are used to upload material (descriptors and votes) to authorities.
+ * Among tunneled connections, some use one-hop circuits, and others use
+ * multi-hop circuits for anonymity.
+ *
+ * Directory requests are launched by calling
+ * directory_initiate_command_rend() or one of its numerous variants. This
+ * launch the connection, will construct an HTTP request with
+ * directory_send_command(), send the and wait for a response. The client
+ * later handles the response with connection_dir_client_reached_eof(),
+ * which passes the information received to another part of Tor.
+ *
+ * On the server side, requests are read in directory_handle_command(),
+ * which dispatches first on the request type (GET or POST), and then on
+ * the URL requested. GET requests are processed with a table-based
+ * dispatcher in url_table[]. The process of handling larger GET requests
+ * is complicated because we need to avoid allocating a copy of all the
+ * data to be sent to the client in one huge buffer. Instead, we spool the
+ * data into the buffer using logic in connection_dirserv_flushed_some() in
+ * dirserv.c. (TODO: If we extended buf.c to have a zero-copy
+ * reference-based buffer type, we could remove most of that code, at the
+ * cost of a bit more reference counting.)
**/
/* In-points to directory.c:
@@ -120,29 +149,55 @@ static void connection_dir_close_consensus_fetches(
/********* END VARIABLES ************/
-/** Return true iff the directory purpose <b>dir_purpose</b> (and if it's
- * fetching descriptors, it's fetching them for <b>router_purpose</b>)
- * must use an anonymous connection to a directory. */
+/** Return false if the directory purpose <b>dir_purpose</b>
+ * does not require an anonymous (three-hop) connection.
+ *
+ * Return true 1) by default, 2) if all directory actions have
+ * specifically been configured to be over an anonymous connection,
+ * or 3) if the router is a bridge */
int
-purpose_needs_anonymity(uint8_t dir_purpose, uint8_t router_purpose)
+purpose_needs_anonymity(uint8_t dir_purpose, uint8_t router_purpose,
+ const char *resource)
{
if (get_options()->AllDirActionsPrivate)
return 1;
- if (router_purpose == ROUTER_PURPOSE_BRIDGE)
+
+ if (router_purpose == ROUTER_PURPOSE_BRIDGE) {
+ if (dir_purpose == DIR_PURPOSE_FETCH_SERVERDESC
+ && resource && !strcmp(resource, "authority.z")) {
+ /* We are asking a bridge for its own descriptor. That doesn't need
+ anonymity. */
+ return 0;
+ }
+ /* Assume all other bridge stuff needs anonymity. */
return 1; /* if no circuits yet, this might break bootstrapping, but it's
* needed to be safe. */
- if (dir_purpose == DIR_PURPOSE_UPLOAD_DIR ||
- dir_purpose == DIR_PURPOSE_UPLOAD_VOTE ||
- dir_purpose == DIR_PURPOSE_UPLOAD_SIGNATURES ||
- dir_purpose == DIR_PURPOSE_FETCH_STATUS_VOTE ||
- dir_purpose == DIR_PURPOSE_FETCH_DETACHED_SIGNATURES ||
- dir_purpose == DIR_PURPOSE_FETCH_CONSENSUS ||
- dir_purpose == DIR_PURPOSE_FETCH_CERTIFICATE ||
- dir_purpose == DIR_PURPOSE_FETCH_SERVERDESC ||
- dir_purpose == DIR_PURPOSE_FETCH_EXTRAINFO ||
- dir_purpose == DIR_PURPOSE_FETCH_MICRODESC)
- return 0;
- return 1;
+ }
+
+ switch (dir_purpose)
+ {
+ case DIR_PURPOSE_UPLOAD_DIR:
+ case DIR_PURPOSE_UPLOAD_VOTE:
+ case DIR_PURPOSE_UPLOAD_SIGNATURES:
+ case DIR_PURPOSE_FETCH_STATUS_VOTE:
+ case DIR_PURPOSE_FETCH_DETACHED_SIGNATURES:
+ case DIR_PURPOSE_FETCH_CONSENSUS:
+ case DIR_PURPOSE_FETCH_CERTIFICATE:
+ case DIR_PURPOSE_FETCH_SERVERDESC:
+ case DIR_PURPOSE_FETCH_EXTRAINFO:
+ case DIR_PURPOSE_FETCH_MICRODESC:
+ return 0;
+ case DIR_PURPOSE_HAS_FETCHED_RENDDESC_V2:
+ case DIR_PURPOSE_UPLOAD_RENDDESC_V2:
+ case DIR_PURPOSE_FETCH_RENDDESC_V2:
+ return 1;
+ case DIR_PURPOSE_SERVER:
+ default:
+ log_warn(LD_BUG, "Called with dir_purpose=%d, router_purpose=%d",
+ dir_purpose, router_purpose);
+ tor_assert_nonfatal_unreached();
+ return 1; /* Assume it needs anonymity; better safe than sorry. */
+ }
}
/** Return a newly allocated string describing <b>auth</b>. Only describes
@@ -347,7 +402,7 @@ directory_post_to_dirservers(uint8_t dir_purpose, uint8_t router_purpose,
log_info(LD_DIR, "Uploading an extrainfo too (length %d)",
(int) extrainfo_len);
}
- if (purpose_needs_anonymity(dir_purpose, router_purpose)) {
+ if (purpose_needs_anonymity(dir_purpose, router_purpose, NULL)) {
indirection = DIRIND_ANONYMOUS;
} else if (!fascist_firewall_allows_dir_server(ds,
FIREWALL_DIR_CONNECTION,
@@ -441,7 +496,8 @@ MOCK_IMPL(void, directory_get_from_dirserver, (
int prefer_authority = (directory_fetches_from_authorities(options)
|| want_authority == DL_WANT_AUTHORITY);
int require_authority = 0;
- int get_via_tor = purpose_needs_anonymity(dir_purpose, router_purpose);
+ int get_via_tor = purpose_needs_anonymity(dir_purpose, router_purpose,
+ resource);
dirinfo_type_t type = dir_fetch_type(dir_purpose, router_purpose, resource);
time_t if_modified_since = 0;
@@ -575,7 +631,7 @@ MOCK_IMPL(void, directory_get_from_dirserver, (
"While fetching directory info, "
"no running dirservers known. Will try again later. "
"(purpose %d)", dir_purpose);
- if (!purpose_needs_anonymity(dir_purpose, router_purpose)) {
+ if (!purpose_needs_anonymity(dir_purpose, router_purpose, resource)) {
/* remember we tried them all and failed. */
directory_all_unreachable(time(NULL));
}
@@ -1078,18 +1134,6 @@ directory_initiate_command(const tor_addr_t *or_addr, uint16_t or_port,
if_modified_since, NULL);
}
-/** Return non-zero iff a directory connection with purpose
- * <b>dir_purpose</b> reveals sensitive information about a Tor
- * instance's client activities. (Such connections must be performed
- * through normal three-hop Tor circuits.) */
-int
-is_sensitive_dir_purpose(uint8_t dir_purpose)
-{
- return ((dir_purpose == DIR_PURPOSE_HAS_FETCHED_RENDDESC_V2) ||
- (dir_purpose == DIR_PURPOSE_UPLOAD_RENDDESC_V2) ||
- (dir_purpose == DIR_PURPOSE_FETCH_RENDDESC_V2));
-}
-
/** Same as directory_initiate_command(), but accepts rendezvous data to
* fetch a hidden service descriptor, and takes its address & port arguments
* as tor_addr_port_t. */
@@ -1137,7 +1181,7 @@ directory_initiate_command_rend(const tor_addr_port_t *or_addr_port,
log_debug(LD_DIR, "Initiating %s", dir_conn_purpose_to_string(dir_purpose));
- if (is_sensitive_dir_purpose(dir_purpose)) {
+ if (purpose_needs_anonymity(dir_purpose, router_purpose, resource)) {
tor_assert(anonymized_connection ||
rend_non_anonymous_mode_enabled(options));
}
diff --git a/src/or/directory.h b/src/or/directory.h
index 9477948aa0..f1cdd9fcfe 100644
--- a/src/or/directory.h
+++ b/src/or/directory.h
@@ -132,10 +132,8 @@ int download_status_get_n_failures(const download_status_t *dls);
int download_status_get_n_attempts(const download_status_t *dls);
time_t download_status_get_next_attempt_at(const download_status_t *dls);
-/* Yes, these two functions are confusingly similar.
- * Let's sort that out in #20077. */
-int purpose_needs_anonymity(uint8_t dir_purpose, uint8_t router_purpose);
-int is_sensitive_dir_purpose(uint8_t dir_purpose);
+int purpose_needs_anonymity(uint8_t dir_purpose, uint8_t router_purpose,
+ const char *resource);
#ifdef TOR_UNIT_TESTS
/* Used only by directory.c and test_dir.c */
diff --git a/src/or/dirserv.c b/src/or/dirserv.c
index 41945fe1d1..6e25323bf9 100644
--- a/src/or/dirserv.c
+++ b/src/or/dirserv.c
@@ -948,7 +948,7 @@ list_server_status_v1(smartlist_t *routers, char **router_status_out,
if (!node->is_running)
*cp++ = '!';
router_get_verbose_nickname(cp, ri);
- smartlist_add(rs_entries, tor_strdup(name_buf));
+ smartlist_add_strdup(rs_entries, name_buf);
} else if (ri->cache_info.published_on >= cutoff) {
smartlist_add(rs_entries, list_single_server_status(ri,
node->is_running));
@@ -1948,7 +1948,7 @@ routerstatus_format_entry(const routerstatus_t *rs, const char *version,
vrs->status.guardfraction_percentage);
}
- smartlist_add(chunks, tor_strdup("\n"));
+ smartlist_add_strdup(chunks, "\n");
if (desc) {
summary = policy_summarize(desc->exit_policy, AF_INET);
@@ -1958,7 +1958,7 @@ routerstatus_format_entry(const routerstatus_t *rs, const char *version,
if (format == NS_V3_VOTE && vrs) {
if (tor_mem_is_zero((char*)vrs->ed25519_id, ED25519_PUBKEY_LEN)) {
- smartlist_add(chunks, tor_strdup("id ed25519 none\n"));
+ smartlist_add_strdup(chunks, "id ed25519 none\n");
} else {
char ed_b64[BASE64_DIGEST256_LEN+1];
digest256_to_base64(ed_b64, (const char*)vrs->ed25519_id);
@@ -2967,7 +2967,7 @@ dirserv_generate_networkstatus_vote_obj(crypto_pk_t *private_key,
config_line_t *cl;
for (cl = get_options()->RecommendedPackages; cl; cl = cl->next) {
if (validate_recommended_package_line(cl->value))
- smartlist_add(v3_out->package_lines, tor_strdup(cl->value));
+ smartlist_add_strdup(v3_out->package_lines, cl->value);
}
}
@@ -2976,9 +2976,9 @@ dirserv_generate_networkstatus_vote_obj(crypto_pk_t *private_key,
"Authority Exit Fast Guard Stable V2Dir Valid HSDir",
0, SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0);
if (vote_on_reachability)
- smartlist_add(v3_out->known_flags, tor_strdup("Running"));
+ smartlist_add_strdup(v3_out->known_flags, "Running");
if (listbadexits)
- smartlist_add(v3_out->known_flags, tor_strdup("BadExit"));
+ smartlist_add_strdup(v3_out->known_flags, "BadExit");
smartlist_sort_strings(v3_out->known_flags);
if (options->ConsensusParams) {
diff --git a/src/or/dirvote.c b/src/or/dirvote.c
index 2c10e784b4..d14af41667 100644
--- a/src/or/dirvote.c
+++ b/src/or/dirvote.c
@@ -26,6 +26,39 @@
/**
* \file dirvote.c
* \brief Functions to compute directory consensus, and schedule voting.
+ *
+ * This module is the center of the consensus-voting based directory
+ * authority system. With this system, a set of authorities first
+ * publish vote based on their opinions of the network, and then compute
+ * a consensus from those votes. Each authority signs the consensus,
+ * and clients trust the consensus if enough known authorities have
+ * signed it.
+ *
+ * The code in this module is only invoked on directory authorities. It's
+ * responsible for:
+ *
+ * <ul>
+ * <li>Generating this authority's vote networkstatus, based on the
+ * authority's view of the network as represented in dirserv.c
+ * <li>Formatting the vote networkstatus objects.
+ * <li>Generating the microdescriptors that correspond to our own
+ * vote.
+ * <li>Sending votes to all the other authorities.
+ * <li>Trying to fetch missing votes from other authorities.
+ * <li>Computing the consensus from a set of votes, as well as
+ * a "detached signature" object for other authorities to fetch.
+ * <li>Collecting other authorities' signatures on the same consensus,
+ * until there are enough.
+ * <li>Publishing the consensus to the reset of the directory system.
+ * <li>Scheduling all of the above operations.
+ * </ul>
+ *
+ * The main entry points are in dirvote_act(), which handles scheduled
+ * actions; and dirvote_add_vote() and dirvote_add_signatures(), which
+ * handle uploaded and downloaded votes and signatures.
+ *
+ * (See dir-spec.txt from torspec.git for a complete specification of
+ * the directory protocol and voting algorithms.)
**/
/** A consensus that we have built and are appending signatures to. Once it's
@@ -250,11 +283,11 @@ format_networkstatus_vote(crypto_pk_t *private_signing_key,
smartlist_add(chunks, rsf);
for (h = vrs->microdesc; h; h = h->next) {
- smartlist_add(chunks, tor_strdup(h->microdesc_hash_line));
+ smartlist_add_strdup(chunks, h->microdesc_hash_line);
}
} SMARTLIST_FOREACH_END(vrs);
- smartlist_add(chunks, tor_strdup("directory-footer\n"));
+ smartlist_add_strdup(chunks, "directory-footer\n");
/* The digest includes everything up through the space after
* directory-signature. (Yuck.) */
@@ -880,7 +913,7 @@ networkstatus_check_weights(int64_t Wgg, int64_t Wgd, int64_t Wmg,
*
* It returns true if weights could be computed, false otherwise.
*/
-static int
+int
networkstatus_compute_bw_weights_v10(smartlist_t *chunks, int64_t G,
int64_t M, int64_t E, int64_t D,
int64_t T, int64_t weight_scale)
@@ -962,7 +995,7 @@ networkstatus_compute_bw_weights_v10(smartlist_t *chunks, int64_t G,
Wgd = weight_scale;
}
} else { // Subcase b: R+D >= S
- casename = "Case 2b1 (Wgg=1, Wmd=Wgd)";
+ casename = "Case 2b1 (Wgg=weight_scale, Wmd=Wgd)";
Wee = (weight_scale*(E - G + M))/E;
Wed = (weight_scale*(D - 2*E + 4*G - 2*M))/(3*D);
Wme = (weight_scale*(G-M))/E;
@@ -975,7 +1008,7 @@ networkstatus_compute_bw_weights_v10(smartlist_t *chunks, int64_t G,
weight_scale, G, M, E, D, T, 10, 1);
if (berr) {
- casename = "Case 2b2 (Wgg=1, Wee=1)";
+ casename = "Case 2b2 (Wgg=weight_scale, Wee=weight_scale)";
Wgg = weight_scale;
Wee = weight_scale;
Wed = (weight_scale*(D - 2*E + G + M))/(3*D);
@@ -1044,7 +1077,7 @@ networkstatus_compute_bw_weights_v10(smartlist_t *chunks, int64_t G,
} else { // Subcase b: S+D >= T/3
// D != 0 because S+D >= T/3
if (G < E) {
- casename = "Case 3bg (G scarce, Wgg=1, Wmd == Wed)";
+ casename = "Case 3bg (G scarce, Wgg=weight_scale, Wmd == Wed)";
Wgg = weight_scale;
Wgd = (weight_scale*(D - 2*G + E + M))/(3*D);
Wmg = 0;
@@ -1056,7 +1089,7 @@ networkstatus_compute_bw_weights_v10(smartlist_t *chunks, int64_t G,
berr = networkstatus_check_weights(Wgg, Wgd, Wmg, Wme, Wmd, Wee,
Wed, weight_scale, G, M, E, D, T, 10, 1);
} else { // G >= E
- casename = "Case 3be (E scarce, Wee=1, Wmd == Wgd)";
+ casename = "Case 3be (E scarce, Wee=weight_scale, Wmd == Wgd)";
Wee = weight_scale;
Wed = (weight_scale*(D - 2*E + G + M))/(3*D);
Wme = 0;
@@ -1090,7 +1123,7 @@ networkstatus_compute_bw_weights_v10(smartlist_t *chunks, int64_t G,
tor_assert(0 < weight_scale && weight_scale <= INT32_MAX);
/*
- * Provide Wgm=Wgg, Wmm=1, Wem=Wee, Weg=Wed. May later determine
+ * Provide Wgm=Wgg, Wmm=weight_scale, Wem=Wee, Weg=Wed. May later determine
* that middle nodes need different bandwidth weights for dirport traffic,
* or that weird exit policies need special weight, or that bridges
* need special weight.
@@ -1273,7 +1306,17 @@ compute_nth_protocol_set(int n, int n_voters, const smartlist_t *votes)
* value in a newly allocated string.
*
* Note: this function DOES NOT check whether the votes are from
- * recognized authorities. (dirvote_add_vote does that.) */
+ * recognized authorities. (dirvote_add_vote does that.)
+ *
+ * <strong>WATCH OUT</strong>: You need to think before you change the
+ * behavior of this function, or of the functions it calls! If some
+ * authorities compute the consensus with a different algorithm than
+ * others, they will not reach the same result, and they will not all
+ * sign the same thing! If you really need to change the algorithm
+ * here, you should allocate a new "consensus_method" for the new
+ * behavior, and make the new behavior conditional on a new-enough
+ * consensus_method.
+ **/
char *
networkstatus_compute_consensus(smartlist_t *votes,
int total_authorities,
@@ -1292,7 +1335,7 @@ networkstatus_compute_consensus(smartlist_t *votes,
smartlist_t *flags;
const char *flavor_name;
uint32_t max_unmeasured_bw_kb = DEFAULT_MAX_UNMEASURED_BW_KB;
- int64_t G=0, M=0, E=0, D=0, T=0; /* For bandwidth weights */
+ int64_t G, M, E, D, T; /* For bandwidth weights */
const routerstatus_format_type_t rs_format =
flavor == FLAV_NS ? NS_V3_CONSENSUS : NS_V3_CONSENSUS_MICRODESC;
char *params = NULL;
@@ -1324,6 +1367,16 @@ networkstatus_compute_consensus(smartlist_t *votes,
consensus_method = MAX_SUPPORTED_CONSENSUS_METHOD;
}
+ if (consensus_method >= MIN_METHOD_FOR_INIT_BW_WEIGHTS_ONE) {
+ /* It's smarter to initialize these weights to 1, so that later on,
+ * we can't accidentally divide by zero. */
+ G = M = E = D = 1;
+ T = 4;
+ } else {
+ /* ...but originally, they were set to zero. */
+ G = M = E = D = T = 0;
+ }
+
/* Compute medians of time-related things, and figure out how many
* routers we might need to talk about. */
{
@@ -1363,7 +1416,7 @@ networkstatus_compute_consensus(smartlist_t *votes,
smartlist_free(sv); /* elements get freed later. */
}
SMARTLIST_FOREACH(v->known_flags, const char *, cp,
- smartlist_add(flags, tor_strdup(cp)));
+ smartlist_add_strdup(flags, cp));
} SMARTLIST_FOREACH_END(v);
valid_after = median_time(va_times, n_votes);
fresh_until = median_time(fu_times, n_votes);
@@ -1396,7 +1449,7 @@ networkstatus_compute_consensus(smartlist_t *votes,
smartlist_free(combined_client_versions);
if (consensus_method >= MIN_METHOD_FOR_ED25519_ID_VOTING)
- smartlist_add(flags, tor_strdup("NoEdConsensus"));
+ smartlist_add_strdup(flags, "NoEdConsensus");
smartlist_sort_strings(flags);
smartlist_uniq_strings(flags);
@@ -1460,9 +1513,9 @@ networkstatus_compute_consensus(smartlist_t *votes,
total_authorities);
if (smartlist_len(param_list)) {
params = smartlist_join_strings(param_list, " ", 0, NULL);
- smartlist_add(chunks, tor_strdup("params "));
+ smartlist_add_strdup(chunks, "params ");
smartlist_add(chunks, params);
- smartlist_add(chunks, tor_strdup("\n"));
+ smartlist_add_strdup(chunks, "\n");
}
if (consensus_method >= MIN_METHOD_FOR_SHARED_RANDOM) {
@@ -2049,10 +2102,10 @@ networkstatus_compute_consensus(smartlist_t *votes,
smartlist_join_strings(chosen_flags, " ", 0, NULL));
/* Now the version line. */
if (chosen_version) {
- smartlist_add(chunks, tor_strdup("\nv "));
- smartlist_add(chunks, tor_strdup(chosen_version));
+ smartlist_add_strdup(chunks, "\nv ");
+ smartlist_add_strdup(chunks, chosen_version);
}
- smartlist_add(chunks, tor_strdup("\n"));
+ smartlist_add_strdup(chunks, "\n");
if (chosen_protocol_list &&
consensus_method >= MIN_METHOD_FOR_RS_PROTOCOLS) {
smartlist_add_asprintf(chunks, "pr %s\n", chosen_protocol_list);
@@ -2105,7 +2158,7 @@ networkstatus_compute_consensus(smartlist_t *votes,
}
/* Mark the directory footer region */
- smartlist_add(chunks, tor_strdup("directory-footer\n"));
+ smartlist_add_strdup(chunks, "directory-footer\n");
{
int64_t weight_scale = BW_WEIGHT_SCALE;
@@ -2156,7 +2209,7 @@ networkstatus_compute_consensus(smartlist_t *votes,
const char *algname = crypto_digest_algorithm_get_name(digest_alg);
char *signature;
- smartlist_add(chunks, tor_strdup("directory-signature "));
+ smartlist_add_strdup(chunks, "directory-signature ");
/* Compute the hash of the chunks. */
crypto_digest_smartlist(digest, digest_len, chunks, "", digest_alg);
@@ -2183,7 +2236,7 @@ networkstatus_compute_consensus(smartlist_t *votes,
smartlist_add(chunks, signature);
if (legacy_id_key_digest && legacy_signing_key) {
- smartlist_add(chunks, tor_strdup("directory-signature "));
+ smartlist_add_strdup(chunks, "directory-signature ");
base16_encode(fingerprint, sizeof(fingerprint),
legacy_id_key_digest, DIGEST_LEN);
crypto_pk_get_fingerprint(legacy_signing_key,
@@ -2496,7 +2549,7 @@ networkstatus_format_signatures(networkstatus_t *consensus,
base64_encode(buf, sizeof(buf), sig->signature, sig->signature_len,
BASE64_ENCODE_MULTILINE);
strlcat(buf, "-----END SIGNATURE-----\n", sizeof(buf));
- smartlist_add(elements, tor_strdup(buf));
+ smartlist_add_strdup(elements, buf);
} SMARTLIST_FOREACH_END(sig);
} SMARTLIST_FOREACH_END(v);
@@ -3606,8 +3659,8 @@ dirvote_add_signatures(const char *detached_signatures_body,
"Queuing it for the next consensus.", source);
if (!pending_consensus_signature_list)
pending_consensus_signature_list = smartlist_new();
- smartlist_add(pending_consensus_signature_list,
- tor_strdup(detached_signatures_body));
+ smartlist_add_strdup(pending_consensus_signature_list,
+ detached_signatures_body);
*msg = "Signature queued";
return 0;
}
diff --git a/src/or/dirvote.h b/src/or/dirvote.h
index efd233ef5f..ac7db69db2 100644
--- a/src/or/dirvote.h
+++ b/src/or/dirvote.h
@@ -55,7 +55,7 @@
#define MIN_SUPPORTED_CONSENSUS_METHOD 13
/** The highest consensus method that we currently support. */
-#define MAX_SUPPORTED_CONSENSUS_METHOD 25
+#define MAX_SUPPORTED_CONSENSUS_METHOD 26
/** Lowest consensus method where microdesc consensuses omit any entry
* with no microdesc. */
@@ -111,6 +111,10 @@
* entries. */
#define MIN_METHOD_FOR_RS_PROTOCOLS 25
+/** Lowest consensus method where authorities initialize bandwidth weights to 1
+ * instead of 0. See #14881 */
+#define MIN_METHOD_FOR_INIT_BW_WEIGHTS_ONE 26
+
/** Default bandwidth to clip unmeasured bandwidths to using method >=
* MIN_METHOD_TO_CLIP_UNMEASURED_BW. (This is not a consensus method; do not
* get confused with the above macros.) */
@@ -234,6 +238,10 @@ STATIC smartlist_t *dirvote_compute_params(smartlist_t *votes, int method,
int total_authorities);
STATIC char *compute_consensus_package_lines(smartlist_t *votes);
STATIC char *make_consensus_method_list(int low, int high, const char *sep);
+STATIC int
+networkstatus_compute_bw_weights_v10(smartlist_t *chunks, int64_t G,
+ int64_t M, int64_t E, int64_t D,
+ int64_t T, int64_t weight_scale);
#endif
#endif
diff --git a/src/or/dns.c b/src/or/dns.c
index 5f9813b912..388104f8da 100644
--- a/src/or/dns.c
+++ b/src/or/dns.c
@@ -1750,7 +1750,7 @@ wildcard_increment_answer(const char *id)
"invalid addresses. Apparently they are hijacking DNS failures. "
"I'll try to correct for this by treating future occurrences of "
"\"%s\" as 'not found'.", id, *ip, id);
- smartlist_add(dns_wildcard_list, tor_strdup(id));
+ smartlist_add_strdup(dns_wildcard_list, id);
}
if (!dns_wildcard_notice_given)
control_event_server_status(LOG_NOTICE, "DNS_HIJACKED");
@@ -1774,7 +1774,7 @@ add_wildcarded_test_address(const char *address)
n_test_addrs = get_options()->ServerDNSTestAddresses ?
smartlist_len(get_options()->ServerDNSTestAddresses) : 0;
- smartlist_add(dns_wildcarded_test_address_list, tor_strdup(address));
+ smartlist_add_strdup(dns_wildcarded_test_address_list, address);
n = smartlist_len(dns_wildcarded_test_address_list);
if (n > n_test_addrs/2) {
tor_log(dns_wildcarded_test_address_notice_given ? LOG_INFO : LOG_NOTICE,
diff --git a/src/or/dnsserv.c b/src/or/dnsserv.c
index f5a4f2ac0f..c5c0a88b09 100644
--- a/src/or/dnsserv.c
+++ b/src/or/dnsserv.c
@@ -3,10 +3,22 @@
/**
* \file dnsserv.c
- * \brief Implements client-side DNS proxy server code. Note:
- * this is the DNS Server code, not the Server DNS code. Confused? This code
- * runs on client-side, and acts as a DNS server. The code in dns.c, on the
- * other hand, runs on Tor servers, and acts as a DNS client.
+ * \brief Implements client-side DNS proxy server code.
+ *
+ * When a user enables the DNSPort configuration option to have their local
+ * Tor client handle DNS requests, this module handles it. It functions as a
+ * "DNS Server" on the client side, which client applications use.
+ *
+ * Inbound DNS requests are represented as entry_connection_t here (since
+ * that's how Tor represents client-side streams), which are kept associated
+ * with an evdns_server_request structure as exposed by Libevent's
+ * evdns code.
+ *
+ * Upon receiving a DNS request, libevent calls our evdns_server_callback()
+ * function here, which causes this module to create an entry_connection_t
+ * request as appropriate. Later, when that request is answered,
+ * connection_edge.c calls dnsserv_resolved() so we can finish up and tell the
+ * DNS client.
**/
#include "or.h"
diff --git a/src/or/entrynodes.c b/src/or/entrynodes.c
index 265b6dcda1..b3fa31df7b 100644
--- a/src/or/entrynodes.c
+++ b/src/or/entrynodes.c
@@ -63,17 +63,42 @@ typedef struct {
smartlist_t *socks_args;
} bridge_info_t;
-/** A list of our chosen entry guards. */
-static smartlist_t *entry_guards = NULL;
-/** A value of 1 means that the entry_guards list has changed
- * and those changes need to be flushed to disk. */
-static int entry_guards_dirty = 0;
+/** All the context for guard selection on a particular client */
+
+struct guard_selection_s {
+ /**
+ * A value of 1 means that guard_selection_t structures have changed
+ * and those changes need to be flushed to disk.
+ *
+ * XXX we don't know how to flush multiple guard contexts to disk yet;
+ * fix that as soon as any way to change the default exists, or at least
+ * make sure this gets set on change.
+ */
+ int dirty;
+
+ /**
+ * A list of our chosen entry guards, as entry_guard_t structures; this
+ * preserves the pre-Prop271 behavior.
+ */
+ smartlist_t *chosen_entry_guards;
+
+ /**
+ * When we try to choose an entry guard, should we parse and add
+ * config's EntryNodes first? This was formerly a global.
+ */
+ int should_add_entry_nodes;
+};
+
+static smartlist_t *guard_contexts = NULL;
+static guard_selection_t *curr_guard_context = NULL;
static void bridge_free(bridge_info_t *bridge);
-static const node_t *choose_random_entry_impl(cpath_build_state_t *state,
+static const node_t *choose_random_entry_impl(guard_selection_t *gs,
+ cpath_build_state_t *state,
int for_directory,
dirinfo_type_t dirtype,
int *n_options_out);
+static guard_selection_t * guard_selection_new(void);
static int num_bridges_usable(void);
/* Default number of entry guards in the case where the NumEntryGuards
@@ -84,13 +109,52 @@ static int num_bridges_usable(void);
#define MIN_N_GUARDS 1
#define MAX_N_GUARDS 10
-/** Return the list of entry guards, creating it if necessary. */
+/** Allocate a new guard_selection_t */
+
+static guard_selection_t *
+guard_selection_new(void)
+{
+ guard_selection_t *gs;
+
+ gs = tor_malloc_zero(sizeof(*gs));
+ gs->chosen_entry_guards = smartlist_new();
+
+ return gs;
+}
+
+/** Get current default guard_selection_t, creating it if necessary */
+guard_selection_t *
+get_guard_selection_info(void)
+{
+ if (!guard_contexts) {
+ guard_contexts = smartlist_new();
+ }
+
+ if (!curr_guard_context) {
+ curr_guard_context = guard_selection_new();
+ smartlist_add(guard_contexts, curr_guard_context);
+ }
+
+ return curr_guard_context;
+}
+
+/** Return the list of entry guards for a guard_selection_t, creating it
+ * if necessary. */
+const smartlist_t *
+get_entry_guards_for_guard_selection(guard_selection_t *gs)
+{
+ tor_assert(gs != NULL);
+ tor_assert(gs->chosen_entry_guards != NULL);
+
+ return gs->chosen_entry_guards;
+}
+
+/** Return the list of entry guards for the default guard_selection_t,
+ * creating it if necessary. */
const smartlist_t *
get_entry_guards(void)
{
- if (! entry_guards)
- entry_guards = smartlist_new();
- return entry_guards;
+ return get_entry_guards_for_guard_selection(get_guard_selection_info());
}
/** Check whether the entry guard <b>e</b> is usable, given the directory
@@ -286,21 +350,28 @@ entry_is_live(const entry_guard_t *e, entry_is_live_flags_t flags,
return node;
}
-/** Return the number of entry guards that we think are usable. */
+/** Return the number of entry guards that we think are usable, in the
+ * context of the given guard_selection_t */
int
-num_live_entry_guards(int for_directory)
+num_live_entry_guards_for_guard_selection(guard_selection_t *gs,
+ int for_directory)
{
int n = 0;
const char *msg;
+
+ tor_assert(gs != NULL);
+
/* Set the entry node attributes we are interested in. */
entry_is_live_flags_t entry_flags = ENTRY_NEED_CAPACITY;
if (!for_directory) {
entry_flags |= ENTRY_NEED_DESCRIPTOR;
}
- if (! entry_guards)
+ if (!(gs->chosen_entry_guards)) {
return 0;
- SMARTLIST_FOREACH_BEGIN(entry_guards, entry_guard_t *, entry) {
+ }
+
+ SMARTLIST_FOREACH_BEGIN(gs->chosen_entry_guards, entry_guard_t *, entry) {
if (for_directory && !entry->is_dir_cache)
continue;
if (entry_is_live(entry, entry_flags, &msg))
@@ -309,27 +380,57 @@ num_live_entry_guards(int for_directory)
return n;
}
+/** Return the number of entry guards that we think are usable, for the
+ * default guard selection */
+int
+num_live_entry_guards(int for_directory)
+{
+ return num_live_entry_guards_for_guard_selection(
+ get_guard_selection_info(), for_directory);
+}
+
/** If <b>digest</b> matches the identity of any node in the
- * entry_guards list, return that node. Else return NULL. */
+ * entry_guards list for the provided guard selection state,
+ return that node. Else return NULL. */
entry_guard_t *
-entry_guard_get_by_id_digest(const char *digest)
+entry_guard_get_by_id_digest_for_guard_selection(guard_selection_t *gs,
+ const char *digest)
{
- SMARTLIST_FOREACH(entry_guards, entry_guard_t *, entry,
+ tor_assert(gs != NULL);
+
+ SMARTLIST_FOREACH(gs->chosen_entry_guards, entry_guard_t *, entry,
if (tor_memeq(digest, entry->identity, DIGEST_LEN))
return entry;
);
return NULL;
}
-/** Dump a description of our list of entry guards to the log at level
- * <b>severity</b>. */
+/** If <b>digest</b> matches the identity of any node in the
+ * entry_guards list for the default guard selection state,
+ return that node. Else return NULL. */
+entry_guard_t *
+entry_guard_get_by_id_digest(const char *digest)
+{
+ return entry_guard_get_by_id_digest_for_guard_selection(
+ get_guard_selection_info(), digest);
+}
+
+/** Dump a description of our list of entry guards in the given guard
+ * selection context to the log at level <b>severity</b>. */
static void
-log_entry_guards(int severity)
+log_entry_guards_for_guard_selection(guard_selection_t *gs, int severity)
{
smartlist_t *elements = smartlist_new();
char *s;
- SMARTLIST_FOREACH_BEGIN(entry_guards, entry_guard_t *, e)
+ /*
+ * TODO this should probably log more info about prop-271 state too
+ * when it's implemented.
+ */
+
+ tor_assert(gs != NULL);
+
+ SMARTLIST_FOREACH_BEGIN(gs->chosen_entry_guards, entry_guard_t *, e)
{
const char *msg = NULL;
if (entry_is_live(e, ENTRY_NEED_CAPACITY, &msg))
@@ -386,23 +487,28 @@ control_event_guard_deferred(void)
/** Largest amount that we'll backdate chosen_on_date */
#define CHOSEN_ON_DATE_SLOP (30*86400)
-/** Add a new (preferably stable and fast) router to our
- * entry_guards list. Return a pointer to the router if we succeed,
- * or NULL if we can't find any more suitable entries.
+/** Add a new (preferably stable and fast) router to our chosen_entry_guards
+ * list for the supplied guard selection. Return a pointer to the router if
+ * we succeed, or NULL if we can't find any more suitable entries.
*
* If <b>chosen</b> is defined, use that one, and if it's not
* already in our entry_guards list, put it at the *beginning*.
* Else, put the one we pick at the end of the list. */
STATIC const node_t *
-add_an_entry_guard(const node_t *chosen, int reset_status, int prepend,
+add_an_entry_guard(guard_selection_t *gs,
+ const node_t *chosen, int reset_status, int prepend,
int for_discovery, int for_directory)
{
const node_t *node;
entry_guard_t *entry;
+ tor_assert(gs != NULL);
+ tor_assert(gs->chosen_entry_guards != NULL);
+
if (chosen) {
node = chosen;
- entry = entry_guard_get_by_id_digest(node->identity);
+ entry = entry_guard_get_by_id_digest_for_guard_selection(gs,
+ node->identity);
if (entry) {
if (reset_status) {
entry->bad_since = 0;
@@ -428,13 +534,11 @@ add_an_entry_guard(const node_t *chosen, int reset_status, int prepend,
if (!node)
return NULL;
}
- if (node->using_as_guard)
- return NULL;
- if (entry_guard_get_by_id_digest(node->identity) != NULL) {
+ if (entry_guard_get_by_id_digest_for_guard_selection(gs, node->identity)
+ != NULL) {
log_info(LD_CIRC, "I was about to add a duplicate entry guard.");
/* This can happen if we choose a guard, then the node goes away, then
* comes back. */
- ((node_t*) node)->using_as_guard = 1;
return NULL;
}
entry = tor_malloc_zero(sizeof(entry_guard_t));
@@ -466,14 +570,15 @@ add_an_entry_guard(const node_t *chosen, int reset_status, int prepend,
if (!for_discovery)
entry->made_contact = 1;
- ((node_t*)node)->using_as_guard = 1;
if (prepend)
- smartlist_insert(entry_guards, 0, entry);
+ smartlist_insert(gs->chosen_entry_guards, 0, entry);
else
- smartlist_add(entry_guards, entry);
+ smartlist_add(gs->chosen_entry_guards, entry);
+
control_event_guard(entry->nickname, entry->identity, "NEW");
control_event_guard_deferred();
- log_entry_guards(LOG_INFO);
+ log_entry_guards_for_guard_selection(gs, LOG_INFO);
+
return node;
}
@@ -503,20 +608,25 @@ decide_num_guards(const or_options_t *options, int for_directory)
/** If the use of entry guards is configured, choose more entry guards
* until we have enough in the list. */
static void
-pick_entry_guards(const or_options_t *options, int for_directory)
+pick_entry_guards(guard_selection_t *gs,
+ const or_options_t *options,
+ int for_directory)
{
int changed = 0;
const int num_needed = decide_num_guards(options, for_directory);
- tor_assert(entry_guards);
+ tor_assert(gs != NULL);
+ tor_assert(gs->chosen_entry_guards != NULL);
- while (num_live_entry_guards(for_directory) < num_needed) {
- if (!add_an_entry_guard(NULL, 0, 0, 0, for_directory))
+ while (num_live_entry_guards_for_guard_selection(gs, for_directory)
+ < num_needed) {
+ if (!add_an_entry_guard(gs, NULL, 0, 0, 0, for_directory))
break;
changed = 1;
}
+
if (changed)
- entry_guards_changed();
+ entry_guards_changed_for_guard_selection(gs);
}
/** How long (in seconds) do we allow an entry guard to be nonfunctional,
@@ -559,19 +669,23 @@ guards_get_lifetime(void)
MAX_GUARD_LIFETIME) + CHOSEN_ON_DATE_SLOP;
}
-/** Remove any entry guard which was selected by an unknown version of Tor,
- * or which was selected by a version of Tor that's known to select
- * entry guards badly, or which was selected more 2 months ago. */
+/** Remove from a guard selection context any entry guard which was selected
+ * by an unknown version of Tor, or which was selected by a version of Tor
+ * that's known to select entry guards badly, or which was selected more 2
+ * months ago. */
/* XXXX The "obsolete guards" and "chosen long ago guards" things should
* probably be different functions. */
static int
-remove_obsolete_entry_guards(time_t now)
+remove_obsolete_entry_guards(guard_selection_t *gs, time_t now)
{
int changed = 0, i;
int32_t guard_lifetime = guards_get_lifetime();
- for (i = 0; i < smartlist_len(entry_guards); ++i) {
- entry_guard_t *entry = smartlist_get(entry_guards, i);
+ tor_assert(gs != NULL);
+ if (!(gs->chosen_entry_guards)) goto done;
+
+ for (i = 0; i < smartlist_len(gs->chosen_entry_guards); ++i) {
+ entry_guard_t *entry = smartlist_get(gs->chosen_entry_guards, i);
const char *ver = entry->chosen_by_version;
const char *msg = NULL;
tor_version_t v;
@@ -598,28 +712,32 @@ remove_obsolete_entry_guards(time_t now)
entry->nickname, dbuf, msg, ver?escaped(ver):"none");
control_event_guard(entry->nickname, entry->identity, "DROPPED");
entry_guard_free(entry);
- smartlist_del_keeporder(entry_guards, i--);
- log_entry_guards(LOG_INFO);
+ smartlist_del_keeporder(gs->chosen_entry_guards, i--);
+ log_entry_guards_for_guard_selection(gs, LOG_INFO);
changed = 1;
}
}
+ done:
return changed ? 1 : 0;
}
-/** Remove all entry guards that have been down or unlisted for so
- * long that we don't think they'll come up again. Return 1 if we
- * removed any, or 0 if we did nothing. */
+/** Remove all entry guards from this guard selection context that have
+ * been down or unlisted for so long that we don't think they'll come up
+ * again. Return 1 if we removed any, or 0 if we did nothing. */
static int
-remove_dead_entry_guards(time_t now)
+remove_dead_entry_guards(guard_selection_t *gs, time_t now)
{
char dbuf[HEX_DIGEST_LEN+1];
char tbuf[ISO_TIME_LEN+1];
int i;
int changed = 0;
- for (i = 0; i < smartlist_len(entry_guards); ) {
- entry_guard_t *entry = smartlist_get(entry_guards, i);
+ tor_assert(gs != NULL);
+ if (!(gs->chosen_entry_guards)) goto done;
+
+ for (i = 0; i < smartlist_len(gs->chosen_entry_guards); ) {
+ entry_guard_t *entry = smartlist_get(gs->chosen_entry_guards, i);
if (entry->bad_since &&
! entry->path_bias_disabled &&
entry->bad_since + ENTRY_GUARD_REMOVE_AFTER < now) {
@@ -631,32 +749,47 @@ remove_dead_entry_guards(time_t now)
entry->nickname, dbuf, tbuf);
control_event_guard(entry->nickname, entry->identity, "DROPPED");
entry_guard_free(entry);
- smartlist_del_keeporder(entry_guards, i);
- log_entry_guards(LOG_INFO);
+ smartlist_del_keeporder(gs->chosen_entry_guards, i);
+ log_entry_guards_for_guard_selection(gs, LOG_INFO);
changed = 1;
} else
++i;
}
+
+ done:
return changed ? 1 : 0;
}
-/** Remove all currently listed entry guards. So new ones will be chosen. */
+/** Remove all currently listed entry guards for a given guard selection
+ * context */
void
-remove_all_entry_guards(void)
+remove_all_entry_guards_for_guard_selection(guard_selection_t *gs)
{
char dbuf[HEX_DIGEST_LEN+1];
- while (smartlist_len(entry_guards)) {
- entry_guard_t *entry = smartlist_get(entry_guards, 0);
- base16_encode(dbuf, sizeof(dbuf), entry->identity, DIGEST_LEN);
- log_info(LD_CIRC, "Entry guard '%s' (%s) has been dropped.",
- entry->nickname, dbuf);
- control_event_guard(entry->nickname, entry->identity, "DROPPED");
- entry_guard_free(entry);
- smartlist_del(entry_guards, 0);
+ tor_assert(gs != NULL);
+
+ if (gs->chosen_entry_guards) {
+ while (smartlist_len(gs->chosen_entry_guards)) {
+ entry_guard_t *entry = smartlist_get(gs->chosen_entry_guards, 0);
+ base16_encode(dbuf, sizeof(dbuf), entry->identity, DIGEST_LEN);
+ log_info(LD_CIRC, "Entry guard '%s' (%s) has been dropped.",
+ entry->nickname, dbuf);
+ control_event_guard(entry->nickname, entry->identity, "DROPPED");
+ entry_guard_free(entry);
+ smartlist_del(gs->chosen_entry_guards, 0);
+ }
}
- log_entry_guards(LOG_INFO);
- entry_guards_changed();
+
+ log_entry_guards_for_guard_selection(gs, LOG_INFO);
+ entry_guards_changed_for_guard_selection(gs);
+}
+
+/** Remove all currently listed entry guards. So new ones will be chosen. */
+void
+remove_all_entry_guards(void)
+{
+ remove_all_entry_guards_for_guard_selection(get_guard_selection_info());
}
/** A new directory or router-status has arrived; update the down/listed
@@ -669,19 +802,21 @@ remove_all_entry_guards(void)
* think that things are unlisted.
*/
void
-entry_guards_compute_status(const or_options_t *options, time_t now)
+entry_guards_compute_status_for_guard_selection(guard_selection_t *gs,
+ const or_options_t *options,
+ time_t now)
{
int changed = 0;
digestmap_t *reasons;
- if (! entry_guards)
+ if ((!gs) || !(gs->chosen_entry_guards))
return;
if (options->EntryNodes) /* reshuffle the entry guard list if needed */
entry_nodes_should_be_added();
reasons = digestmap_new();
- SMARTLIST_FOREACH_BEGIN(entry_guards, entry_guard_t *, entry)
+ SMARTLIST_FOREACH_BEGIN(gs->chosen_entry_guards, entry_guard_t *, entry)
{
const node_t *r = node_get_by_id(entry->identity);
const char *reason = NULL;
@@ -695,13 +830,14 @@ entry_guards_compute_status(const or_options_t *options, time_t now)
}
SMARTLIST_FOREACH_END(entry);
- if (remove_dead_entry_guards(now))
+ if (remove_dead_entry_guards(gs, now))
changed = 1;
- if (remove_obsolete_entry_guards(now))
+ if (remove_obsolete_entry_guards(gs, now))
changed = 1;
if (changed) {
- SMARTLIST_FOREACH_BEGIN(entry_guards, entry_guard_t *, entry) {
+ SMARTLIST_FOREACH_BEGIN(gs->chosen_entry_guards, entry_guard_t *,
+ entry) {
const char *reason = digestmap_get(reasons, entry->identity);
const char *live_msg = "";
const node_t *r = entry_is_live(entry, ENTRY_NEED_CAPACITY, &live_msg);
@@ -716,14 +852,31 @@ entry_guards_compute_status(const or_options_t *options, time_t now)
r ? "" : live_msg);
} SMARTLIST_FOREACH_END(entry);
log_info(LD_CIRC, " (%d/%d entry guards are usable/new)",
- num_live_entry_guards(0), smartlist_len(entry_guards));
- log_entry_guards(LOG_INFO);
- entry_guards_changed();
+ num_live_entry_guards_for_guard_selection(gs, 0),
+ smartlist_len(gs->chosen_entry_guards));
+ log_entry_guards_for_guard_selection(gs, LOG_INFO);
+ entry_guards_changed_for_guard_selection(gs);
}
digestmap_free(reasons, NULL);
}
+/** A new directory or router-status has arrived; update the down/listed
+ * status of the entry guards.
+ *
+ * An entry is 'down' if the directory lists it as nonrunning.
+ * An entry is 'unlisted' if the directory doesn't include it.
+ *
+ * Don't call this on startup; only on a fresh download. Otherwise we'll
+ * think that things are unlisted.
+ */
+void
+entry_guards_compute_status(const or_options_t *options, time_t now)
+{
+ entry_guards_compute_status_for_guard_selection(get_guard_selection_info(),
+ options, now);
+}
+
/** Called when a connection to an OR with the identity digest <b>digest</b>
* is established (<b>succeeded</b>==1) or has failed (<b>succeeded</b>==0).
* If the OR is an entry, change that entry's up/down status.
@@ -736,8 +889,9 @@ entry_guards_compute_status(const or_options_t *options, time_t now)
* Too many boolean arguments is a recipe for confusion.
*/
int
-entry_guard_register_connect_status(const char *digest, int succeeded,
- int mark_relay_status, time_t now)
+entry_guard_register_connect_status_for_guard_selection(
+ guard_selection_t *gs, const char *digest, int succeeded,
+ int mark_relay_status, time_t now)
{
int changed = 0;
int refuse_conn = 0;
@@ -746,10 +900,11 @@ entry_guard_register_connect_status(const char *digest, int succeeded,
int idx = -1;
char buf[HEX_DIGEST_LEN+1];
- if (! entry_guards)
+ if (!(gs) || !(gs->chosen_entry_guards)) {
return 0;
+ }
- SMARTLIST_FOREACH_BEGIN(entry_guards, entry_guard_t *, e) {
+ SMARTLIST_FOREACH_BEGIN(gs->chosen_entry_guards, entry_guard_t *, e) {
tor_assert(e);
if (tor_memeq(e->identity, digest, DIGEST_LEN)) {
entry = e;
@@ -784,11 +939,12 @@ entry_guard_register_connect_status(const char *digest, int succeeded,
"Connection to never-contacted entry guard '%s' (%s) failed. "
"Removing from the list. %d/%d entry guards usable/new.",
entry->nickname, buf,
- num_live_entry_guards(0)-1, smartlist_len(entry_guards)-1);
+ num_live_entry_guards_for_guard_selection(gs, 0) - 1,
+ smartlist_len(gs->chosen_entry_guards)-1);
control_event_guard(entry->nickname, entry->identity, "DROPPED");
entry_guard_free(entry);
- smartlist_del_keeporder(entry_guards, idx);
- log_entry_guards(LOG_INFO);
+ smartlist_del_keeporder(gs->chosen_entry_guards, idx);
+ log_entry_guards_for_guard_selection(gs, LOG_INFO);
changed = 1;
} else if (!entry->unreachable_since) {
log_info(LD_CIRC, "Unable to connect to entry guard '%s' (%s). "
@@ -818,7 +974,7 @@ entry_guard_register_connect_status(const char *digest, int succeeded,
* came back? We should give our earlier entries another try too,
* and close this connection so we don't use it before we've given
* the others a shot. */
- SMARTLIST_FOREACH_BEGIN(entry_guards, entry_guard_t *, e) {
+ SMARTLIST_FOREACH_BEGIN(gs->chosen_entry_guards, entry_guard_t *, e) {
if (e == entry)
break;
if (e->made_contact) {
@@ -837,56 +993,68 @@ entry_guard_register_connect_status(const char *digest, int succeeded,
"Connected to new entry guard '%s' (%s). Marking earlier "
"entry guards up. %d/%d entry guards usable/new.",
entry->nickname, buf,
- num_live_entry_guards(0), smartlist_len(entry_guards));
- log_entry_guards(LOG_INFO);
+ num_live_entry_guards_for_guard_selection(gs, 0),
+ smartlist_len(gs->chosen_entry_guards));
+ log_entry_guards_for_guard_selection(gs, LOG_INFO);
changed = 1;
}
}
if (changed)
- entry_guards_changed();
+ entry_guards_changed_for_guard_selection(gs);
return refuse_conn ? -1 : 0;
}
-/** When we try to choose an entry guard, should we parse and add
- * config's EntryNodes first? */
-static int should_add_entry_nodes = 0;
+/** Called when a connection to an OR with the identity digest <b>digest</b>
+ * is established (<b>succeeded</b>==1) or has failed (<b>succeeded</b>==0).
+ * If the OR is an entry, change that entry's up/down status in the default
+ * guard selection context.
+ * Return 0 normally, or -1 if we want to tear down the new connection.
+ *
+ * If <b>mark_relay_status</b>, also call router_set_status() on this
+ * relay.
+ */
+int
+entry_guard_register_connect_status(const char *digest, int succeeded,
+ int mark_relay_status, time_t now)
+{
+ return entry_guard_register_connect_status_for_guard_selection(
+ get_guard_selection_info(), digest, succeeded, mark_relay_status, now);
+}
/** Called when the value of EntryNodes changes in our configuration. */
void
-entry_nodes_should_be_added(void)
+entry_nodes_should_be_added_for_guard_selection(guard_selection_t *gs)
{
+ tor_assert(gs != NULL);
+
log_info(LD_CIRC, "EntryNodes config option set. Putting configured "
"relays at the front of the entry guard list.");
- should_add_entry_nodes = 1;
+ gs->should_add_entry_nodes = 1;
}
-/** Update the using_as_guard fields of all the nodes. We do this after we
- * remove entry guards from the list: This is the only function that clears
- * the using_as_guard field. */
-static void
-update_node_guard_status(void)
-{
- smartlist_t *nodes = nodelist_get_list();
- SMARTLIST_FOREACH(nodes, node_t *, node, node->using_as_guard = 0);
- SMARTLIST_FOREACH_BEGIN(entry_guards, entry_guard_t *, entry) {
- node_t *node = node_get_mutable_by_id(entry->identity);
- if (node)
- node->using_as_guard = 1;
- } SMARTLIST_FOREACH_END(entry);
+/** Called when the value of EntryNodes changes in our configuration. */
+void
+entry_nodes_should_be_added(void)
+{
+ entry_nodes_should_be_added_for_guard_selection(
+ get_guard_selection_info());
}
/** Adjust the entry guards list so that it only contains entries from
* EntryNodes, adding new entries from EntryNodes to the list as needed. */
STATIC void
-entry_guards_set_from_config(const or_options_t *options)
+entry_guards_set_from_config(guard_selection_t *gs,
+ const or_options_t *options)
{
smartlist_t *entry_nodes, *worse_entry_nodes, *entry_fps;
smartlist_t *old_entry_guards_on_list, *old_entry_guards_not_on_list;
const int numentryguards = decide_num_guards(options, 0);
- tor_assert(entry_guards);
- should_add_entry_nodes = 0;
+ tor_assert(gs != NULL);
+ tor_assert(gs->chosen_entry_guards != NULL);
+
+ gs->should_add_entry_nodes = 0;
if (!options->EntryNodes) {
/* It's possible that a controller set EntryNodes, thus making
@@ -915,7 +1083,7 @@ entry_guards_set_from_config(const or_options_t *options)
SMARTLIST_FOREACH(entry_nodes, const node_t *,node,
smartlist_add(entry_fps, (void*)node->identity));
- SMARTLIST_FOREACH(entry_guards, entry_guard_t *, e, {
+ SMARTLIST_FOREACH(gs->chosen_entry_guards, entry_guard_t *, e, {
if (smartlist_contains_digest(entry_fps, e->identity))
smartlist_add(old_entry_guards_on_list, e);
else
@@ -925,7 +1093,8 @@ entry_guards_set_from_config(const or_options_t *options)
/* Remove all currently configured guard nodes, excluded nodes, unreachable
* nodes, or non-Guard nodes from entry_nodes. */
SMARTLIST_FOREACH_BEGIN(entry_nodes, const node_t *, node) {
- if (entry_guard_get_by_id_digest(node->identity)) {
+ if (entry_guard_get_by_id_digest_for_guard_selection(gs,
+ node->identity)) {
SMARTLIST_DEL_CURRENT(entry_nodes, node);
continue;
} else if (routerset_contains_node(options->ExcludeNodes, node)) {
@@ -942,9 +1111,9 @@ entry_guards_set_from_config(const or_options_t *options)
} SMARTLIST_FOREACH_END(node);
/* Now build the new entry_guards list. */
- smartlist_clear(entry_guards);
+ smartlist_clear(gs->chosen_entry_guards);
/* First, the previously configured guards that are in EntryNodes. */
- smartlist_add_all(entry_guards, old_entry_guards_on_list);
+ smartlist_add_all(gs->chosen_entry_guards, old_entry_guards_on_list);
/* Next, scramble the rest of EntryNodes, putting the guards first. */
smartlist_shuffle(entry_nodes);
smartlist_shuffle(worse_entry_nodes);
@@ -952,24 +1121,23 @@ entry_guards_set_from_config(const or_options_t *options)
/* Next, the rest of EntryNodes */
SMARTLIST_FOREACH_BEGIN(entry_nodes, const node_t *, node) {
- add_an_entry_guard(node, 0, 0, 1, 0);
- if (smartlist_len(entry_guards) > numentryguards * 10)
+ add_an_entry_guard(gs, node, 0, 0, 1, 0);
+ if (smartlist_len(gs->chosen_entry_guards) > numentryguards * 10)
break;
} SMARTLIST_FOREACH_END(node);
- log_notice(LD_GENERAL, "%d entries in guards", smartlist_len(entry_guards));
+ log_notice(LD_GENERAL, "%d entries in guards",
+ smartlist_len(gs->chosen_entry_guards));
/* Finally, free the remaining previously configured guards that are not in
* EntryNodes. */
SMARTLIST_FOREACH(old_entry_guards_not_on_list, entry_guard_t *, e,
entry_guard_free(e));
- update_node_guard_status();
-
smartlist_free(entry_nodes);
smartlist_free(worse_entry_nodes);
smartlist_free(entry_fps);
smartlist_free(old_entry_guards_on_list);
smartlist_free(old_entry_guards_not_on_list);
- entry_guards_changed();
+ entry_guards_changed_for_guard_selection(gs);
}
/** Return 0 if we're fine adding arbitrary routers out of the
@@ -996,7 +1164,8 @@ entry_list_is_constrained(const or_options_t *options)
const node_t *
choose_random_entry(cpath_build_state_t *state)
{
- return choose_random_entry_impl(state, 0, NO_DIRINFO, NULL);
+ return choose_random_entry_impl(get_guard_selection_info(),
+ state, 0, NO_DIRINFO, NULL);
}
/** Pick a live (up and listed) directory guard from entry_guards for
@@ -1004,7 +1173,8 @@ choose_random_entry(cpath_build_state_t *state)
const node_t *
choose_random_dirguard(dirinfo_type_t type)
{
- return choose_random_entry_impl(NULL, 1, type, NULL);
+ return choose_random_entry_impl(get_guard_selection_info(),
+ NULL, 1, type, NULL);
}
/** Filter <b>all_entry_guards</b> for usable entry guards and put them
@@ -1095,7 +1265,8 @@ populate_live_entry_guards(smartlist_t *live_entry_guards,
return retval;
}
-/** Pick a node to be used as the entry guard of a circuit.
+/** Pick a node to be used as the entry guard of a circuit, relative to
+ * a supplied guard selection context.
*
* If <b>state</b> is set, it contains the information we know about
* the upcoming circuit.
@@ -1116,7 +1287,8 @@ populate_live_entry_guards(smartlist_t *live_entry_guards,
* Helper for choose_random{entry,dirguard}.
*/
static const node_t *
-choose_random_entry_impl(cpath_build_state_t *state, int for_directory,
+choose_random_entry_impl(guard_selection_t *gs,
+ cpath_build_state_t *state, int for_directory,
dirinfo_type_t dirinfo_type, int *n_options_out)
{
const or_options_t *options = get_options();
@@ -1130,18 +1302,18 @@ choose_random_entry_impl(cpath_build_state_t *state, int for_directory,
const int num_needed = decide_num_guards(options, for_directory);
int retval = 0;
+ tor_assert(gs != NULL);
+ tor_assert(gs->chosen_entry_guards != NULL);
+
if (n_options_out)
*n_options_out = 0;
- if (!entry_guards)
- entry_guards = smartlist_new();
-
- if (should_add_entry_nodes)
- entry_guards_set_from_config(options);
+ if (gs->should_add_entry_nodes)
+ entry_guards_set_from_config(gs, options);
if (!entry_list_is_constrained(options) &&
- smartlist_len(entry_guards) < num_needed)
- pick_entry_guards(options, for_directory);
+ smartlist_len(gs->chosen_entry_guards) < num_needed)
+ pick_entry_guards(gs, options, for_directory);
retry:
smartlist_clear(live_entry_guards);
@@ -1149,7 +1321,7 @@ choose_random_entry_impl(cpath_build_state_t *state, int for_directory,
/* Populate the list of live entry guards so that we pick one of
them. */
retval = populate_live_entry_guards(live_entry_guards,
- entry_guards,
+ gs->chosen_entry_guards,
chosen_exit,
dirinfo_type,
for_directory,
@@ -1177,9 +1349,9 @@ choose_random_entry_impl(cpath_build_state_t *state, int for_directory,
/* XXX if guard doesn't imply fast and stable, then we need
* to tell add_an_entry_guard below what we want, or it might
* be a long time til we get it. -RD */
- node = add_an_entry_guard(NULL, 0, 0, 1, for_directory);
+ node = add_an_entry_guard(gs, NULL, 0, 0, 1, for_directory);
if (node) {
- entry_guards_changed();
+ entry_guards_changed_for_guard_selection(gs);
/* XXX we start over here in case the new node we added shares
* a family with our exit node. There's a chance that we'll just
* load up on entry guards here, if the network we're using is
@@ -1219,13 +1391,15 @@ choose_random_entry_impl(cpath_build_state_t *state, int for_directory,
}
/** Parse <b>state</b> and learn about the entry guards it describes.
- * If <b>set</b> is true, and there are no errors, replace the global
- * entry_list with what we find.
+ * If <b>set</b> is true, and there are no errors, replace the guard
+ * list in the provided guard selection context with what we find.
* On success, return 0. On failure, alloc into *<b>msg</b> a string
* describing the error, and return -1.
*/
int
-entry_guards_parse_state(or_state_t *state, int set, char **msg)
+entry_guards_parse_state_for_guard_selection(
+ guard_selection_t *gs,
+ or_state_t *state, int set, char **msg)
{
entry_guard_t *node = NULL;
smartlist_t *new_entry_guards = smartlist_new();
@@ -1234,6 +1408,8 @@ entry_guards_parse_state(or_state_t *state, int set, char **msg)
const char *state_version = state->TorVersion;
digestmap_t *added_by = digestmap_new();
+ tor_assert(gs != NULL);
+
*msg = NULL;
for (line = state->EntryGuards; line; line = line->next) {
if (!strcasecmp(line->key, "EntryGuard")) {
@@ -1469,24 +1645,36 @@ entry_guards_parse_state(or_state_t *state, int set, char **msg)
entry_guard_free(e));
smartlist_free(new_entry_guards);
} else { /* !err && set */
- if (entry_guards) {
- SMARTLIST_FOREACH(entry_guards, entry_guard_t *, e,
+ if (gs->chosen_entry_guards) {
+ SMARTLIST_FOREACH(gs->chosen_entry_guards, entry_guard_t *, e,
entry_guard_free(e));
- smartlist_free(entry_guards);
+ smartlist_free(gs->chosen_entry_guards);
}
- entry_guards = new_entry_guards;
- entry_guards_dirty = 0;
+ gs->chosen_entry_guards = new_entry_guards;
+ gs->dirty = 0;
/* XXX hand new_entry_guards to this func, and move it up a
* few lines, so we don't have to re-dirty it */
- if (remove_obsolete_entry_guards(now))
- entry_guards_dirty = 1;
-
- update_node_guard_status();
+ if (remove_obsolete_entry_guards(gs, now))
+ gs->dirty = 1;
}
digestmap_free(added_by, tor_free_);
return *msg ? -1 : 0;
}
+/** Parse <b>state</b> and learn about the entry guards it describes.
+ * If <b>set</b> is true, and there are no errors, replace the guard
+ * list in the default guard selection context with what we find.
+ * On success, return 0. On failure, alloc into *<b>msg</b> a string
+ * describing the error, and return -1.
+ */
+int
+entry_guards_parse_state(or_state_t *state, int set, char **msg)
+{
+ return entry_guards_parse_state_for_guard_selection(
+ get_guard_selection_info(),
+ state, set, msg);
+}
+
/** How long will we let a change in our guard nodes stay un-saved
* when we are trying to avoid disk writes? */
#define SLOW_GUARD_STATE_FLUSH_TIME 600
@@ -1494,15 +1682,18 @@ entry_guards_parse_state(or_state_t *state, int set, char **msg)
* when we are not trying to avoid disk writes? */
#define FAST_GUARD_STATE_FLUSH_TIME 30
-/** Our list of entry guards has changed, or some element of one
- * of our entry guards has changed. Write the changes to disk within
- * the next few minutes.
+/** Our list of entry guards has changed for a particular guard selection
+ * context, or some element of one of our entry guards has changed for one.
+ * Write the changes to disk within the next few minutes.
*/
void
-entry_guards_changed(void)
+entry_guards_changed_for_guard_selection(guard_selection_t *gs)
{
time_t when;
- entry_guards_dirty = 1;
+
+ tor_assert(gs != NULL);
+
+ gs->dirty = 1;
if (get_options()->AvoidDiskWrites)
when = time(NULL) + SLOW_GUARD_STATE_FLUSH_TIME;
@@ -1513,24 +1704,42 @@ entry_guards_changed(void)
or_state_mark_dirty(get_or_state(), when);
}
+/** Our list of entry guards has changed for the default guard selection
+ * context, or some element of one of our entry guards has changed. Write
+ * the changes to disk within the next few minutes.
+ */
+void
+entry_guards_changed(void)
+{
+ entry_guards_changed_for_guard_selection(get_guard_selection_info());
+}
+
/** If the entry guard info has not changed, do nothing and return.
* Otherwise, free the EntryGuards piece of <b>state</b> and create
* a new one out of the global entry_guards list, and then mark
* <b>state</b> dirty so it will get saved to disk.
+ *
+ * XXX this should get totally redesigned around storing multiple
+ * entry guard contexts. For the initial refactor we'll just
+ * always use the current default. Fix it as soon as we actually
+ * have any way that default can change.
*/
void
entry_guards_update_state(or_state_t *state)
{
config_line_t **next, *line;
- if (! entry_guards_dirty)
+ guard_selection_t *gs = get_guard_selection_info();
+
+ tor_assert(gs != NULL);
+ tor_assert(gs->chosen_entry_guards != NULL);
+
+ if (!gs->dirty)
return;
config_free_lines(state->EntryGuards);
next = &state->EntryGuards;
*next = NULL;
- if (!entry_guards)
- entry_guards = smartlist_new();
- SMARTLIST_FOREACH_BEGIN(entry_guards, entry_guard_t *, e) {
+ SMARTLIST_FOREACH_BEGIN(gs->chosen_entry_guards, entry_guard_t *, e) {
char dbuf[HEX_DIGEST_LEN+1];
if (!e->made_contact)
continue; /* don't write this one to disk */
@@ -1596,7 +1805,7 @@ entry_guards_update_state(or_state_t *state)
} SMARTLIST_FOREACH_END(e);
if (!get_options()->AvoidDiskWrites)
or_state_mark_dirty(get_or_state(), 0);
- entry_guards_dirty = 0;
+ gs->dirty = 0;
}
/** If <b>question</b> is the string "entry-guards", then dump
@@ -1604,12 +1813,20 @@ entry_guards_update_state(or_state_t *state)
* the nodes in the global entry_guards list. See control-spec.txt
* for details.
* For backward compatibility, we also handle the string "helper-nodes".
+ *
+ * XXX this should be totally redesigned after prop 271 too, and that's
+ * going to take some control spec work.
* */
int
getinfo_helper_entry_guards(control_connection_t *conn,
const char *question, char **answer,
const char **errmsg)
{
+ guard_selection_t *gs = get_guard_selection_info();
+
+ tor_assert(gs != NULL);
+ tor_assert(gs->chosen_entry_guards != NULL);
+
(void) conn;
(void) errmsg;
@@ -1618,9 +1835,8 @@ getinfo_helper_entry_guards(control_connection_t *conn,
smartlist_t *sl = smartlist_new();
char tbuf[ISO_TIME_LEN+1];
char nbuf[MAX_VERBOSE_NICKNAME_LEN+1];
- if (!entry_guards)
- entry_guards = smartlist_new();
- SMARTLIST_FOREACH_BEGIN(entry_guards, entry_guard_t *, e) {
+
+ SMARTLIST_FOREACH_BEGIN(gs->chosen_entry_guards, entry_guard_t *, e) {
const char *status = NULL;
time_t when = 0;
const node_t *node;
@@ -2042,6 +2258,42 @@ bridge_add_from_config(bridge_line_t *bridge_line)
smartlist_add(bridge_list, b);
}
+/** Returns true iff the node is used as a guard in the specified guard
+ * context */
+int
+is_node_used_as_guard_for_guard_selection(guard_selection_t *gs,
+ const node_t *node)
+{
+ int res = 0;
+
+ /*
+ * We used to have a using_as_guard flag in node_t, but it had to go away
+ * to allow for multiple guard selection contexts. Instead, search the
+ * guard list for a matching digest.
+ */
+
+ tor_assert(gs != NULL);
+ tor_assert(node != NULL);
+
+ SMARTLIST_FOREACH_BEGIN(gs->chosen_entry_guards, entry_guard_t *, e) {
+ if (tor_memeq(e->identity, node->identity, DIGEST_LEN)) {
+ res = 1;
+ break;
+ }
+ } SMARTLIST_FOREACH_END(e);
+
+ return res;
+}
+
+/** Returns true iff the node is used as a guard in the default guard
+ * context */
+MOCK_IMPL(int,
+is_node_used_as_guard, (const node_t *node))
+{
+ return is_node_used_as_guard_for_guard_selection(
+ get_guard_selection_info(), node);
+}
+
/** Return true iff <b>routerset</b> contains the bridge <b>bridge</b>. */
static int
routerset_contains_bridge(const routerset_t *routerset,
@@ -2383,7 +2635,7 @@ learned_bridge_descriptor(routerinfo_t *ri, int from_cache)
fmt_and_decorate_addr(&bridge->addr),
(int) bridge->port);
}
- add_an_entry_guard(node, 1, 1, 0, 0);
+ add_an_entry_guard(get_guard_selection_info(), node, 1, 1, 0, 0);
log_notice(LD_DIR, "new bridge descriptor '%s' (%s): %s", ri->nickname,
from_cache ? "cached" : "fresh", router_describe(ri));
@@ -2419,7 +2671,8 @@ num_bridges_usable(void)
{
int n_options = 0;
tor_assert(get_options()->UseBridges);
- (void) choose_random_entry_impl(NULL, 0, 0, &n_options);
+ (void) choose_random_entry_impl(get_guard_selection_info(),
+ NULL, 0, 0, &n_options);
return n_options;
}
@@ -2472,9 +2725,12 @@ entries_retry_helper(const or_options_t *options, int act)
int any_known = 0;
int any_running = 0;
int need_bridges = options->UseBridges != 0;
- if (!entry_guards)
- entry_guards = smartlist_new();
- SMARTLIST_FOREACH_BEGIN(entry_guards, entry_guard_t *, e) {
+ guard_selection_t *gs = get_guard_selection_info();
+
+ tor_assert(gs != NULL);
+ tor_assert(gs->chosen_entry_guards != NULL);
+
+ SMARTLIST_FOREACH_BEGIN(gs->chosen_entry_guards, entry_guard_t *, e) {
node = node_get_by_id(e->identity);
if (node && node_has_descriptor(node) &&
node_is_bridge(node) == need_bridges &&
@@ -2521,25 +2777,20 @@ entries_retry_all(const or_options_t *options)
entries_retry_helper(options, 1);
}
-/** Return true if at least one of our bridges runs a Tor version that can
- * provide microdescriptors to us. If not, we'll fall back to asking for
- * full descriptors. */
-int
-any_bridge_supports_microdescriptors(void)
+/** Free one guard selection context */
+static void
+guard_selection_free(guard_selection_t *gs)
{
- const node_t *node;
- if (!get_options()->UseBridges || !entry_guards)
- return 0;
- SMARTLIST_FOREACH_BEGIN(entry_guards, entry_guard_t *, e) {
- node = node_get_by_id(e->identity);
- if (node && node->is_running &&
- node_is_bridge(node) && node_is_a_configured_bridge(node)) {
- /* This is one of our current bridges, and we know enough about
- * it to know that it will be able to answer our questions. */
- return 1;
- }
- } SMARTLIST_FOREACH_END(e);
- return 0;
+ if (!gs) return;
+
+ if (gs->chosen_entry_guards) {
+ SMARTLIST_FOREACH(gs->chosen_entry_guards, entry_guard_t *, e,
+ entry_guard_free(e));
+ smartlist_free(gs->chosen_entry_guards);
+ gs->chosen_entry_guards = NULL;
+ }
+
+ tor_free(gs);
}
/** Release all storage held by the list of entry guards and related
@@ -2547,11 +2798,15 @@ any_bridge_supports_microdescriptors(void)
void
entry_guards_free_all(void)
{
- if (entry_guards) {
- SMARTLIST_FOREACH(entry_guards, entry_guard_t *, e,
- entry_guard_free(e));
- smartlist_free(entry_guards);
- entry_guards = NULL;
+ /* Null out the default */
+ curr_guard_context = NULL;
+ /* Free all the guard contexts */
+ if (guard_contexts != NULL) {
+ SMARTLIST_FOREACH_BEGIN(guard_contexts, guard_selection_t *, gs) {
+ guard_selection_free(gs);
+ } SMARTLIST_FOREACH_END(gs);
+ smartlist_free(guard_contexts);
+ guard_contexts = NULL;
}
clear_bridge_list();
smartlist_free(bridge_list);
diff --git a/src/or/entrynodes.h b/src/or/entrynodes.h
index 1021e67d43..00f96916b6 100644
--- a/src/or/entrynodes.h
+++ b/src/or/entrynodes.h
@@ -16,6 +16,9 @@
/* XXXX NM I would prefer that all of this stuff be private to
* entrynodes.c. */
+/* Forward declare for guard_selection_t; entrynodes.c has the real struct */
+typedef struct guard_selection_s guard_selection_t;
+
/** An entry_guard_t represents our information about a chosen long-term
* first hop, known as a "helper" node in the literature. We can't just
* use a node_t, since we want to remember these even when we
@@ -53,6 +56,14 @@ typedef struct entry_guard_t {
time_t last_attempted; /**< 0 if we can connect to this guard, or the time
* at which we last failed to connect to it. */
+ /**
+ * @name circpathbias fields
+ *
+ * These fields are used in circpathbias.c to try to detect entry
+ * nodes that are failing circuits at a suspicious frequency.
+ */
+ /**@{*/
+
double circ_attempts; /**< Number of circuits this guard has "attempted" */
double circ_successes; /**< Number of successfully built circuits using
* this guard as first hop. */
@@ -68,20 +79,30 @@ typedef struct entry_guard_t {
double use_attempts; /**< Number of circuits we tried to use with streams */
double use_successes; /**< Number of successfully used circuits using
* this guard as first hop. */
+ /**@}*/
} entry_guard_t;
+entry_guard_t *entry_guard_get_by_id_digest_for_guard_selection(
+ guard_selection_t *gs, const char *digest);
entry_guard_t *entry_guard_get_by_id_digest(const char *digest);
+void entry_guards_changed_for_guard_selection(guard_selection_t *gs);
void entry_guards_changed(void);
+guard_selection_t * get_guard_selection_info(void);
+const smartlist_t *get_entry_guards_for_guard_selection(
+ guard_selection_t *gs);
const smartlist_t *get_entry_guards(void);
+int num_live_entry_guards_for_guard_selection(
+ guard_selection_t *gs,
+ int for_directory);
int num_live_entry_guards(int for_directory);
#endif
#ifdef ENTRYNODES_PRIVATE
-STATIC const node_t *add_an_entry_guard(const node_t *chosen,
+STATIC const node_t *add_an_entry_guard(guard_selection_t *gs,
+ const node_t *chosen,
int reset_status, int prepend,
int for_discovery, int for_directory);
-
STATIC int populate_live_entry_guards(smartlist_t *live_entry_guards,
const smartlist_t *all_entry_guards,
const node_t *chosen_exit,
@@ -90,7 +111,8 @@ STATIC int populate_live_entry_guards(smartlist_t *live_entry_guards,
int need_uptime, int need_capacity);
STATIC int decide_num_guards(const or_options_t *options, int for_directory);
-STATIC void entry_guards_set_from_config(const or_options_t *options);
+STATIC void entry_guards_set_from_config(guard_selection_t *gs,
+ const or_options_t *options);
/** Flags to be passed to entry_is_live() to indicate what kind of
* entry nodes we are looking for. */
@@ -109,20 +131,32 @@ STATIC int entry_is_time_to_retry(const entry_guard_t *e, time_t now);
#endif
+void remove_all_entry_guards_for_guard_selection(guard_selection_t *gs);
void remove_all_entry_guards(void);
+void entry_guards_compute_status_for_guard_selection(
+ guard_selection_t *gs, const or_options_t *options, time_t now);
void entry_guards_compute_status(const or_options_t *options, time_t now);
+int entry_guard_register_connect_status_for_guard_selection(
+ guard_selection_t *gs, const char *digest, int succeeded,
+ int mark_relay_status, time_t now);
int entry_guard_register_connect_status(const char *digest, int succeeded,
int mark_relay_status, time_t now);
+void entry_nodes_should_be_added_for_guard_selection(guard_selection_t *gs);
void entry_nodes_should_be_added(void);
int entry_list_is_constrained(const or_options_t *options);
const node_t *choose_random_entry(cpath_build_state_t *state);
const node_t *choose_random_dirguard(dirinfo_type_t t);
+int entry_guards_parse_state_for_guard_selection(
+ guard_selection_t *gs, or_state_t *state, int set, char **msg);
int entry_guards_parse_state(or_state_t *state, int set, char **msg);
void entry_guards_update_state(or_state_t *state);
int getinfo_helper_entry_guards(control_connection_t *conn,
const char *question, char **answer,
const char **errmsg);
+int is_node_used_as_guard_for_guard_selection(guard_selection_t *gs,
+ const node_t *node);
+MOCK_DECL(int, is_node_used_as_guard, (const node_t *node));
void mark_bridge_list(void);
void sweep_bridge_list(void);
@@ -143,7 +177,6 @@ int any_bridge_descriptors_known(void);
int entries_known_but_down(const or_options_t *options);
void entries_retry_all(const or_options_t *options);
-int any_bridge_supports_microdescriptors(void);
const smartlist_t *get_socks_args_by_bridge_addrport(const tor_addr_t *addr,
uint16_t port);
diff --git a/src/or/geoip.c b/src/or/geoip.c
index ba65dfe56c..74811ea643 100644
--- a/src/or/geoip.c
+++ b/src/or/geoip.c
@@ -880,7 +880,7 @@ geoip_get_transport_history(void)
/* If it's the first time we see this transport, note it. */
if (val == 1)
- smartlist_add(transports_used, tor_strdup(transport_name));
+ smartlist_add_strdup(transports_used, transport_name);
log_debug(LD_GENERAL, "Client from '%s' with transport '%s'. "
"I've now seen %d clients.",
diff --git a/src/or/main.c b/src/or/main.c
index 013e301aff..617c784f91 100644
--- a/src/or/main.c
+++ b/src/or/main.c
@@ -8,6 +8,42 @@
* \file main.c
* \brief Toplevel module. Handles signals, multiplexes between
* connections, implements main loop, and drives scheduled events.
+ *
+ * For the main loop itself; see run_main_loop_once(). It invokes the rest of
+ * Tor mostly through Libevent callbacks. Libevent callbacks can happen when
+ * a timer elapses, a signal is received, a socket is ready to read or write,
+ * or an event is manually activated.
+ *
+ * Most events in Tor are driven from these callbacks:
+ * <ul>
+ * <li>conn_read_callback() and conn_write_callback() here, which are
+ * invoked when a socket is ready to read or write respectively.
+ * <li>signal_callback(), which handles incoming signals.
+ * </ul>
+ * Other events are used for specific purposes, or for building more complex
+ * control structures. If you search for usage of tor_libevent_new(), you
+ * will find all the events that we construct in Tor.
+ *
+ * Tor has numerous housekeeping operations that need to happen
+ * regularly. They are handled in different ways:
+ * <ul>
+ * <li>The most frequent operations are handled after every read or write
+ * event, at the end of connection_handle_read() and
+ * connection_handle_write().
+ *
+ * <li>The next most frequent operations happen after each invocation of the
+ * main loop, in run_main_loop_once().
+ *
+ * <li>Once per second, we run all of the operations listed in
+ * second_elapsed_callback(), and in its child, run_scheduled_events().
+ *
+ * <li>Once-a-second operations are handled in second_elapsed_callback().
+ *
+ * <li>More infrequent operations take place based on the periodic event
+ * driver in periodic.c . These are stored in the periodic_events[]
+ * table.
+ * </ul>
+ *
**/
#define MAIN_PRIVATE
@@ -1408,13 +1444,13 @@ run_scheduled_events(time_t now)
pt_configure_remaining_proxies();
}
+/* Periodic callback: Every MIN_ONION_KEY_LIFETIME seconds, rotate the onion
+ * keys, shut down and restart all cpuworkers, and update our descriptor if
+ * necessary.
+ */
static int
rotate_onion_key_callback(time_t now, const or_options_t *options)
{
- /* 1a. Every MIN_ONION_KEY_LIFETIME seconds, rotate the onion keys,
- * shut down and restart all cpuworkers, and update the directory if
- * necessary.
- */
if (server_mode(options)) {
time_t rotation_time = get_onion_key_set_at()+MIN_ONION_KEY_LIFETIME;
if (rotation_time > now) {
@@ -1434,6 +1470,9 @@ rotate_onion_key_callback(time_t now, const or_options_t *options)
return PERIODIC_EVENT_NO_UPDATE;
}
+/* Periodic callback: Every 30 seconds, check whether it's time to make new
+ * Ed25519 subkeys.
+ */
static int
check_ed_keys_callback(time_t now, const or_options_t *options)
{
@@ -1451,6 +1490,11 @@ check_ed_keys_callback(time_t now, const or_options_t *options)
return PERIODIC_EVENT_NO_UPDATE;
}
+/**
+ * Periodic callback: Every {LAZY,GREEDY}_DESCRIPTOR_RETRY_INTERVAL,
+ * see about fetching descriptors, microdescriptors, and extrainfo
+ * documents.
+ */
static int
launch_descriptor_fetches_callback(time_t now, const or_options_t *options)
{
@@ -1465,6 +1509,10 @@ launch_descriptor_fetches_callback(time_t now, const or_options_t *options)
return GREEDY_DESCRIPTOR_RETRY_INTERVAL;
}
+/**
+ * Periodic event: Rotate our X.509 certificates and TLS keys once every
+ * MAX_SSL_KEY_LIFETIME_INTERNAL.
+ */
static int
rotate_x509_certificate_callback(time_t now, const or_options_t *options)
{
@@ -1490,6 +1538,10 @@ rotate_x509_certificate_callback(time_t now, const or_options_t *options)
return MAX_SSL_KEY_LIFETIME_INTERNAL;
}
+/**
+ * Periodic callback: once an hour, grab some more entropy from the
+ * kernel and feed it to our CSPRNG.
+ **/
static int
add_entropy_callback(time_t now, const or_options_t *options)
{
@@ -1506,6 +1558,10 @@ add_entropy_callback(time_t now, const or_options_t *options)
return ENTROPY_INTERVAL;
}
+/**
+ * Periodic callback: if we're an authority, make sure we test
+ * the routers on the network for reachability.
+ */
static int
launch_reachability_tests_callback(time_t now, const or_options_t *options)
{
@@ -1517,6 +1573,10 @@ launch_reachability_tests_callback(time_t now, const or_options_t *options)
return REACHABILITY_TEST_INTERVAL;
}
+/**
+ * Periodic callback: if we're an authority, discount the stability
+ * information (and other rephist information) that's older.
+ */
static int
downrate_stability_callback(time_t now, const or_options_t *options)
{
@@ -1528,6 +1588,10 @@ downrate_stability_callback(time_t now, const or_options_t *options)
return safe_timer_diff(now, next);
}
+/**
+ * Periodic callback: if we're an authority, record our measured stability
+ * information from rephist in an mtbf file.
+ */
static int
save_stability_callback(time_t now, const or_options_t *options)
{
@@ -1540,6 +1604,10 @@ save_stability_callback(time_t now, const or_options_t *options)
return SAVE_STABILITY_INTERVAL;
}
+/**
+ * Periodic callback: if we're an authority, check on our authority
+ * certificate (the one that authenticates our authority signing key).
+ */
static int
check_authority_cert_callback(time_t now, const or_options_t *options)
{
@@ -1552,6 +1620,10 @@ check_authority_cert_callback(time_t now, const or_options_t *options)
return CHECK_V3_CERTIFICATE_INTERVAL;
}
+/**
+ * Periodic callback: If our consensus is too old, recalculate whether
+ * we can actually use it.
+ */
static int
check_expired_networkstatus_callback(time_t now, const or_options_t *options)
{
@@ -1571,6 +1643,9 @@ check_expired_networkstatus_callback(time_t now, const or_options_t *options)
return CHECK_EXPIRED_NS_INTERVAL;
}
+/**
+ * Periodic callback: Write statistics to disk if appropriate.
+ */
static int
write_stats_file_callback(time_t now, const or_options_t *options)
{
@@ -1618,6 +1693,9 @@ write_stats_file_callback(time_t now, const or_options_t *options)
return safe_timer_diff(now, next_time_to_write_stats_files);
}
+/**
+ * Periodic callback: Write bridge statistics to disk if appropriate.
+ */
static int
record_bridge_stats_callback(time_t now, const or_options_t *options)
{
@@ -1645,6 +1723,9 @@ record_bridge_stats_callback(time_t now, const or_options_t *options)
return PERIODIC_EVENT_NO_UPDATE;
}
+/**
+ * Periodic callback: Clean in-memory caches every once in a while
+ */
static int
clean_caches_callback(time_t now, const or_options_t *options)
{
@@ -1658,6 +1739,10 @@ clean_caches_callback(time_t now, const or_options_t *options)
return CLEAN_CACHES_INTERVAL;
}
+/**
+ * Periodic callback: Clean the cache of failed hidden service lookups
+ * frequently frequently.
+ */
static int
rend_cache_failure_clean_callback(time_t now, const or_options_t *options)
{
@@ -1669,20 +1754,21 @@ rend_cache_failure_clean_callback(time_t now, const or_options_t *options)
return 30;
}
+/**
+ * Periodic callback: If we're a server and initializing dns failed, retry.
+ */
static int
retry_dns_callback(time_t now, const or_options_t *options)
{
(void)now;
#define RETRY_DNS_INTERVAL (10*60)
- /* If we're a server and initializing dns failed, retry periodically. */
if (server_mode(options) && has_dns_init_failed())
dns_init();
return RETRY_DNS_INTERVAL;
}
- /* 2. Periodically, we consider force-uploading our descriptor
- * (if we've passed our internal checks). */
-
+/** Periodic callback: consider rebuilding or and re-uploading our descriptor
+ * (if we've passed our internal checks). */
static int
check_descriptor_callback(time_t now, const or_options_t *options)
{
@@ -1709,6 +1795,11 @@ check_descriptor_callback(time_t now, const or_options_t *options)
return CHECK_DESCRIPTOR_INTERVAL;
}
+/**
+ * Periodic callback: check whether we're reachable (as a relay), and
+ * whether our bandwidth has changed enough that we need to
+ * publish a new descriptor.
+ */
static int
check_for_reachability_bw_callback(time_t now, const or_options_t *options)
{
@@ -1745,13 +1836,13 @@ check_for_reachability_bw_callback(time_t now, const or_options_t *options)
return CHECK_DESCRIPTOR_INTERVAL;
}
+/**
+ * Periodic event: once a minute, (or every second if TestingTorNetwork, or
+ * during client bootstrap), check whether we want to download any
+ * networkstatus documents. */
static int
fetch_networkstatus_callback(time_t now, const or_options_t *options)
{
- /* 2c. Every minute (or every second if TestingTorNetwork, or during
- * client bootstrap), check whether we want to download any networkstatus
- * documents. */
-
/* How often do we check whether we should download network status
* documents? */
const int we_are_bootstrapping = networkstatus_consensus_is_bootstrapping(
@@ -1773,12 +1864,13 @@ fetch_networkstatus_callback(time_t now, const or_options_t *options)
return networkstatus_dl_check_interval;
}
+/**
+ * Periodic callback: Every 60 seconds, we relaunch listeners if any died. */
static int
retry_listeners_callback(time_t now, const or_options_t *options)
{
(void)now;
(void)options;
- /* 3d. And every 60 seconds, we relaunch listeners if any died. */
if (!net_is_disabled()) {
retry_all_listeners(NULL, NULL, 0);
return 60;
@@ -1786,6 +1878,9 @@ retry_listeners_callback(time_t now, const or_options_t *options)
return PERIODIC_EVENT_NO_UPDATE;
}
+/**
+ * Periodic callback: as a server, see if we have any old unused circuits
+ * that should be expired */
static int
expire_old_ciruits_serverside_callback(time_t now, const or_options_t *options)
{
@@ -1795,6 +1890,10 @@ expire_old_ciruits_serverside_callback(time_t now, const or_options_t *options)
return 11;
}
+/**
+ * Periodic event: if we're an exit, see if our DNS server is telling us
+ * obvious lies.
+ */
static int
check_dns_honesty_callback(time_t now, const or_options_t *options)
{
@@ -1817,6 +1916,10 @@ check_dns_honesty_callback(time_t now, const or_options_t *options)
return 12*3600 + crypto_rand_int(12*3600);
}
+/**
+ * Periodic callback: if we're the bridge authority, write a networkstatus
+ * file to disk.
+ */
static int
write_bridge_ns_callback(time_t now, const or_options_t *options)
{
@@ -1829,6 +1932,9 @@ write_bridge_ns_callback(time_t now, const or_options_t *options)
return PERIODIC_EVENT_NO_UPDATE;
}
+/**
+ * Periodic callback: poke the tor-fw-helper app if we're using one.
+ */
static int
check_fw_helper_app_callback(time_t now, const or_options_t *options)
{
@@ -1852,7 +1958,9 @@ check_fw_helper_app_callback(time_t now, const or_options_t *options)
return PORT_FORWARDING_CHECK_INTERVAL;
}
-/** Callback to write heartbeat message in the logs. */
+/**
+ * Periodic callback: write the heartbeat message in the logs.
+ */
static int
heartbeat_callback(time_t now, const or_options_t *options)
{
@@ -2358,19 +2466,26 @@ run_main_loop_once(void)
/* Make it easier to tell whether libevent failure is our fault or not. */
errno = 0;
#endif
- /* All active linked conns should get their read events activated. */
+
+ /* All active linked conns should get their read events activated,
+ * so that libevent knows to run their callbacks. */
SMARTLIST_FOREACH(active_linked_connection_lst, connection_t *, conn,
event_active(conn->read_event, EV_READ, 1));
called_loop_once = smartlist_len(active_linked_connection_lst) ? 1 : 0;
+ /* Make sure we know (about) what time it is. */
update_approx_time(time(NULL));
- /* poll until we have an event, or the second ends, or until we have
- * some active linked connections to trigger events for. */
+ /* Here it is: the main loop. Here we tell Libevent to poll until we have
+ * an event, or the second ends, or until we have some active linked
+ * connections to trigger events for. Libevent will wait till one
+ * of these happens, then run all the appropriate callbacks. */
loop_result = event_base_loop(tor_libevent_get_base(),
called_loop_once ? EVLOOP_ONCE : 0);
- /* let catch() handle things like ^c, and otherwise don't worry about it */
+ /* Oh, the loop failed. That might be an error that we need to
+ * catch, but more likely, it's just an interrupted poll() call or something,
+ * and we should try again. */
if (loop_result < 0) {
int e = tor_socket_errno(-1);
/* let the program survive things like ^z */
@@ -2393,9 +2508,17 @@ run_main_loop_once(void)
}
}
- /* This will be pretty fast if nothing new is pending. Note that this gets
- * called once per libevent loop, which will make it happen once per group
- * of events that fire, or once per second. */
+ /* And here is where we put callbacks that happen "every time the event loop
+ * runs." They must be very fast, or else the whole Tor process will get
+ * slowed down.
+ *
+ * Note that this gets called once per libevent loop, which will make it
+ * happen once per group of events that fire, or once per second. */
+
+ /* If there are any pending client connections, try attaching them to
+ * circuits (if we can.) This will be pretty fast if nothing new is
+ * pending.
+ */
connection_ap_attach_pending(0);
return 1;
diff --git a/src/or/microdesc.c b/src/or/microdesc.c
index a81dc54628..140117f683 100644
--- a/src/or/microdesc.c
+++ b/src/or/microdesc.c
@@ -917,20 +917,9 @@ update_microdescs_from_networkstatus(time_t now)
int
we_use_microdescriptors_for_circuits(const or_options_t *options)
{
- int ret = options->UseMicrodescriptors;
- if (ret == -1) {
- /* UseMicrodescriptors is "auto"; we need to decide: */
- /* If we are configured to use bridges and none of our bridges
- * know what a microdescriptor is, the answer is no. */
- if (options->UseBridges && !any_bridge_supports_microdescriptors())
- return 0;
- /* Otherwise, we decide that we'll use microdescriptors iff we are
- * not a server, and we're not autofetching everything. */
- /* XXXX++ what does not being a server have to do with it? also there's
- * a partitioning issue here where bridges differ from clients. */
- ret = !server_mode(options) && !options->FetchUselessDescriptors;
- }
- return ret;
+ if (options->UseMicrodescriptors == 0)
+ return 0; /* the user explicitly picked no */
+ return 1; /* yes and auto both mean yes */
}
/** Return true iff we should try to download microdescriptors at all. */
diff --git a/src/or/networkstatus.c b/src/or/networkstatus.c
index f30fe1607c..85a73c8e63 100644
--- a/src/or/networkstatus.c
+++ b/src/or/networkstatus.c
@@ -6,8 +6,34 @@
/**
* \file networkstatus.c
- * \brief Functions and structures for handling network status documents as a
- * client or cache.
+ * \brief Functions and structures for handling networkstatus documents as a
+ * client or as a directory cache.
+ *
+ * A consensus networkstatus object is created by the directory
+ * authorities. It authenticates a set of network parameters--most
+ * importantly, the list of all the relays in the network. This list
+ * of relays is represented as an array of routerstatus_t objects.
+ *
+ * There are currently two flavors of consensus. With the older "NS"
+ * flavor, each relay is associated with a digest of its router
+ * descriptor. Tor instances that use this consensus keep the list of
+ * router descriptors as routerinfo_t objects stored and managed in
+ * routerlist.c. With the newer "microdesc" flavor, each relay is
+ * associated with a digest of the microdescriptor that the authorities
+ * made for it. These are stored and managed in microdesc.c. Information
+ * about the router is divided between the the networkstatus and the
+ * microdescriptor according to the general rule that microdescriptors
+ * should hold information that changes much less frequently than the
+ * information in the networkstatus.
+ *
+ * Modern clients use microdescriptor networkstatuses. Directory caches
+ * need to keep both kinds of networkstatus document, so they can serve them.
+ *
+ * This module manages fetching, holding, storing, updating, and
+ * validating networkstatus objects. The download-and-validate process
+ * is slightly complicated by the fact that the keys you need to
+ * validate a consensus are stored in the authority certificates, which
+ * you might not have yet when you download the consensus.
*/
#define NETWORKSTATUS_PRIVATE
diff --git a/src/or/nodelist.c b/src/or/nodelist.c
index 070e2e9e0d..2802d5b9e0 100644
--- a/src/or/nodelist.c
+++ b/src/or/nodelist.c
@@ -10,6 +10,32 @@
* \brief Structures and functions for tracking what we know about the routers
* on the Tor network, and correlating information from networkstatus,
* routerinfo, and microdescs.
+ *
+ * The key structure here is node_t: that's the canonical way to refer
+ * to a Tor relay that we might want to build a circuit through. Every
+ * node_t has either a routerinfo_t, or a routerstatus_t from the current
+ * networkstatus consensus. If it has a routerstatus_t, it will also
+ * need to have a microdesc_t before you can use it for circuits.
+ *
+ * The nodelist_t is a global singleton that maps identities to node_t
+ * objects. Access them with the node_get_*() functions. The nodelist_t
+ * is maintained by calls throughout the codebase
+ *
+ * Generally, other code should not have to reach inside a node_t to
+ * see what information it has. Instead, you should call one of the
+ * many accessor functions that works on a generic node_t. If there
+ * isn't one that does what you need, it's better to make such a function,
+ * and then use it.
+ *
+ * For historical reasons, some of the functions that select a node_t
+ * from the list of all usable node_t objects are in the routerlist.c
+ * module, since they originally selected a routerinfo_t. (TODO: They
+ * should move!)
+ *
+ * (TODO: Perhaps someday we should abstract the remaining ways of
+ * talking about a relay to also be node_t instances. Those would be
+ * routerstatus_t as used for directory requests, and dir_server_t as
+ * used for authorities and fallback directories.)
*/
#include "or.h"
diff --git a/src/or/or.h b/src/or/or.h
index 66717792b4..d0570a9249 100644
--- a/src/or/or.h
+++ b/src/or/or.h
@@ -2365,9 +2365,6 @@ typedef struct node_t {
/** Local info: we treat this node as if it rejects everything */
unsigned int rejects_all:1;
- /** Local info: this node is in our list of guards */
- unsigned int using_as_guard:1;
-
/* Local info: derived. */
/** True if the IPv6 OR port is preferred over the IPv4 OR port.
diff --git a/src/or/policies.c b/src/or/policies.c
index 44a46d2fe2..9e4e73dfea 100644
--- a/src/or/policies.c
+++ b/src/or/policies.c
@@ -6,6 +6,13 @@
/**
* \file policies.c
* \brief Code to parse and use address policies and exit policies.
+ *
+ * We have two key kinds of address policy: full and compressed. A full
+ * policy is an array of accept/reject patterns, to be applied in order.
+ * A short policy is simply a list of ports. This module handles both
+ * kinds, including generic functions to apply them to addresses, and
+ * also including code to manage the global policies that we apply to
+ * incoming and outgoing connections.
**/
#define POLICIES_PRIVATE
@@ -2463,9 +2470,9 @@ policy_summarize(smartlist_t *policy, sa_family_t family)
tor_snprintf(buf, sizeof(buf), "%d-%d", start_prt, AT(i)->prt_max);
if (AT(i)->accepted)
- smartlist_add(accepts, tor_strdup(buf));
+ smartlist_add_strdup(accepts, buf);
else
- smartlist_add(rejects, tor_strdup(buf));
+ smartlist_add_strdup(rejects, buf);
if (last)
break;
@@ -2646,7 +2653,7 @@ write_short_policy(const short_policy_t *policy)
smartlist_add_asprintf(sl, "%d-%d", e->min_port, e->max_port);
}
if (i < policy->n_entries-1)
- smartlist_add(sl, tor_strdup(","));
+ smartlist_add_strdup(sl, ",");
}
answer = smartlist_join_strings(sl, "", 0, NULL);
SMARTLIST_FOREACH(sl, char *, a, tor_free(a));
diff --git a/src/or/protover.c b/src/or/protover.c
index a6a5d18f36..335be29e61 100644
--- a/src/or/protover.c
+++ b/src/or/protover.c
@@ -347,7 +347,7 @@ encode_protocol_list(const smartlist_t *sl)
const char *separator = "";
smartlist_t *chunks = smartlist_new();
SMARTLIST_FOREACH_BEGIN(sl, const proto_entry_t *, ent) {
- smartlist_add(chunks, tor_strdup(separator));
+ smartlist_add_strdup(chunks, separator);
proto_entry_encode_into(chunks, ent);
@@ -476,7 +476,7 @@ contract_protocol_list(const smartlist_t *proto_strings)
smartlist_sort(lst, cmp_single_ent_by_version);
if (! first_entry)
- smartlist_add(chunks, tor_strdup(" "));
+ smartlist_add_strdup(chunks, " ");
/* We're going to construct this entry from the ranges. */
proto_entry_t *entry = tor_malloc_zero(sizeof(proto_entry_t));
diff --git a/src/or/relay.c b/src/or/relay.c
index 1794215378..823e0743bd 100644
--- a/src/or/relay.c
+++ b/src/or/relay.c
@@ -8,6 +8,41 @@
* \file relay.c
* \brief Handle relay cell encryption/decryption, plus packaging and
* receiving from circuits, plus queuing on circuits.
+ *
+ * This is a core modules that makes Tor work. It's responsible for
+ * dealing with RELAY cells (the ones that travel more than one hop along a
+ * circuit), by:
+ * <ul>
+ * <li>constructing relays cells,
+ * <li>encrypting relay cells,
+ * <li>decrypting relay cells,
+ * <li>demultiplexing relay cells as they arrive on a connection,
+ * <li>queueing relay cells for retransmission,
+ * <li>or handling relay cells that are for us to receive (as an exit or a
+ * client).
+ * </ul>
+ *
+ * RELAY cells are generated throughout the code at the client or relay side,
+ * using relay_send_command_from_edge() or one of the functions like
+ * connection_edge_send_command() that calls it. Of particular interest is
+ * connection_edge_package_raw_inbuf(), which takes information that has
+ * arrived on an edge connection socket, and packages it as a RELAY_DATA cell
+ * -- this is how information is actually sent across the Tor network. The
+ * cryptography for these functions is handled deep in
+ * circuit_package_relay_cell(), which either adds a single layer of
+ * encryption (if we're an exit), or multiple layers (if we're the origin of
+ * the circuit). After construction and encryption, the RELAY cells are
+ * passed to append_cell_to_circuit_queue(), which queues them for
+ * transmission and tells the circuitmux (see circuitmux.c) that the circuit
+ * is waiting to send something.
+ *
+ * Incoming RELAY cells arrive at circuit_receive_relay_cell(), called from
+ * command.c. There they are decrypted and, if they are for us, are passed to
+ * connection_edge_process_relay_cell(). If they're not for us, they're
+ * re-queued for retransmission again with append_cell_to_circuit_queue().
+ *
+ * The connection_edge_process_relay_cell() function handles all the different
+ * types of relay cells, launching requests or transmitting data as needed.
**/
#define RELAY_PRIVATE
diff --git a/src/or/rendservice.c b/src/or/rendservice.c
index 3afe880554..ab7ec3f5f1 100644
--- a/src/or/rendservice.c
+++ b/src/or/rendservice.c
@@ -984,7 +984,7 @@ rend_service_sos_poison_path(const rend_service_t *service)
return rend_service_path(service, sos_poison_fname);
}
-/** Return True if hidden services <b>service> has been poisoned by single
+/** Return True if hidden services <b>service</b> has been poisoned by single
* onion mode. */
static int
service_is_single_onion_poisoned(const rend_service_t *service)
@@ -1222,7 +1222,7 @@ rend_services_add_filenames_to_lists(smartlist_t *open_lst,
SMARTLIST_FOREACH_BEGIN(rend_service_list, rend_service_t *, s) {
if (s->directory) {
rend_service_add_filenames_to_list(open_lst, s);
- smartlist_add(stat_lst, tor_strdup(s->directory));
+ smartlist_add_strdup(stat_lst, s->directory);
}
} SMARTLIST_FOREACH_END(s);
}
diff --git a/src/or/router.c b/src/or/router.c
index 10498e8ae1..e45f233634 100644
--- a/src/or/router.c
+++ b/src/or/router.c
@@ -2195,7 +2195,7 @@ router_build_fresh_descriptor(routerinfo_t **r, extrainfo_t **e)
log_warn(LD_CONFIG, "There is a router named \"%s\" in my "
"declared family, but that isn't a legal nickname. "
"Skipping it.", escaped(name));
- smartlist_add(warned_nonexistent_family, tor_strdup(name));
+ smartlist_add_strdup(warned_nonexistent_family, name);
}
if (is_legal) {
smartlist_add(ri->declared_family, name);
@@ -2870,7 +2870,7 @@ router_dump_router_to_string(routerinfo_t *router,
/* Write the exit policy to the end of 's'. */
if (!router->exit_policy || !smartlist_len(router->exit_policy)) {
- smartlist_add(chunks, tor_strdup("reject *:*\n"));
+ smartlist_add_strdup(chunks, "reject *:*\n");
} else if (router->exit_policy) {
char *exit_policy = router_dump_exit_policy_to_string(router,1,0);
@@ -2892,12 +2892,12 @@ router_dump_router_to_string(routerinfo_t *router,
if (decide_to_advertise_begindir(options,
router->supports_tunnelled_dir_requests)) {
- smartlist_add(chunks, tor_strdup("tunnelled-dir-server\n"));
+ smartlist_add_strdup(chunks, "tunnelled-dir-server\n");
}
/* Sign the descriptor with Ed25519 */
if (emit_ed_sigs) {
- smartlist_add(chunks, tor_strdup("router-sig-ed25519 "));
+ smartlist_add_strdup(chunks, "router-sig-ed25519 ");
crypto_digest_smartlist_prefix(digest, DIGEST256_LEN,
ED_DESC_SIGNATURE_PREFIX,
chunks, "", DIGEST_SHA256);
@@ -2913,7 +2913,7 @@ router_dump_router_to_string(routerinfo_t *router,
}
/* Sign the descriptor with RSA */
- smartlist_add(chunks, tor_strdup("router-signature\n"));
+ smartlist_add_strdup(chunks, "router-signature\n");
crypto_digest_smartlist(digest, DIGEST_LEN, chunks, "", DIGEST_SHA1);
@@ -2928,7 +2928,7 @@ router_dump_router_to_string(routerinfo_t *router,
}
/* include a last '\n' */
- smartlist_add(chunks, tor_strdup("\n"));
+ smartlist_add_strdup(chunks, "\n");
output = smartlist_join_strings(chunks, "", 0, NULL);
@@ -3186,13 +3186,13 @@ extrainfo_dump_to_string(char **s_out, extrainfo_t *extrainfo,
if (should_record_bridge_info(options) && write_stats_to_extrainfo) {
const char *bridge_stats = geoip_get_bridge_stats_extrainfo(now);
if (bridge_stats) {
- smartlist_add(chunks, tor_strdup(bridge_stats));
+ smartlist_add_strdup(chunks, bridge_stats);
}
}
if (emit_ed_sigs) {
char sha256_digest[DIGEST256_LEN];
- smartlist_add(chunks, tor_strdup("router-sig-ed25519 "));
+ smartlist_add_strdup(chunks, "router-sig-ed25519 ");
crypto_digest_smartlist_prefix(sha256_digest, DIGEST256_LEN,
ED_DESC_SIGNATURE_PREFIX,
chunks, "", DIGEST_SHA256);
@@ -3207,7 +3207,7 @@ extrainfo_dump_to_string(char **s_out, extrainfo_t *extrainfo,
smartlist_add_asprintf(chunks, "%s\n", buf);
}
- smartlist_add(chunks, tor_strdup("router-signature\n"));
+ smartlist_add_strdup(chunks, "router-signature\n");
s = smartlist_join_strings(chunks, "", 0, NULL);
while (strlen(s) > MAX_EXTRAINFO_UPLOAD_SIZE - DIROBJ_MAX_SIG_LEN) {
@@ -3242,7 +3242,7 @@ extrainfo_dump_to_string(char **s_out, extrainfo_t *extrainfo,
"descriptor.");
goto err;
}
- smartlist_add(chunks, tor_strdup(sig));
+ smartlist_add_strdup(chunks, sig);
tor_free(s);
s = smartlist_join_strings(chunks, "", 0, NULL);
diff --git a/src/or/routerkeys.c b/src/or/routerkeys.c
index ca32228fc7..7a1a2c9b2d 100644
--- a/src/or/routerkeys.c
+++ b/src/or/routerkeys.c
@@ -5,8 +5,13 @@
* \file routerkeys.c
*
* \brief Functions and structures to handle generating and maintaining the
- * set of keypairs necessary to be an OR. (Some of the code in router.c
- * belongs here.)
+ * set of keypairs necessary to be an OR.
+ *
+ * The keys handled here now are the Ed25519 keys that Tor relays use to sign
+ * descriptors, authenticate themselves on links, and identify one another
+ * uniquely. Other keys are maintained in router.c and rendservice.c.
+ *
+ * (TODO: The keys in router.c should go here too.)
*/
#include "or.h"
diff --git a/src/or/routerlist.c b/src/or/routerlist.c
index 85eb999ad6..2681025c81 100644
--- a/src/or/routerlist.c
+++ b/src/or/routerlist.c
@@ -929,7 +929,8 @@ authority_certs_fetch_resource_impl(const char *resource,
const routerstatus_t *rs)
{
const or_options_t *options = get_options();
- int get_via_tor = purpose_needs_anonymity(DIR_PURPOSE_FETCH_CERTIFICATE, 0);
+ int get_via_tor = purpose_needs_anonymity(DIR_PURPOSE_FETCH_CERTIFICATE, 0,
+ resource);
/* Make sure bridge clients never connect to anything but a bridge */
if (options->UseBridges) {
@@ -1202,7 +1203,7 @@ authority_certs_fetch_missing(networkstatus_t *status, time_t now,
int need_plus = 0;
smartlist_t *fps = smartlist_new();
- smartlist_add(fps, tor_strdup("fp/"));
+ smartlist_add_strdup(fps, "fp/");
SMARTLIST_FOREACH_BEGIN(missing_id_digests, const char *, d) {
char *fp = NULL;
@@ -1242,7 +1243,7 @@ authority_certs_fetch_missing(networkstatus_t *status, time_t now,
int need_plus = 0;
smartlist_t *fp_pairs = smartlist_new();
- smartlist_add(fp_pairs, tor_strdup("fp-sk/"));
+ smartlist_add_strdup(fp_pairs, "fp-sk/");
SMARTLIST_FOREACH_BEGIN(missing_cert_digests, const fp_pair_t *, d) {
char *fp_pair = NULL;
@@ -2037,9 +2038,9 @@ router_pick_directory_server_impl(dirinfo_type_t type, int flags,
!router_supports_extrainfo(node->identity, is_trusted_extrainfo))
continue;
/* Don't make the same node a guard twice */
- if (for_guard && node->using_as_guard) {
- continue;
- }
+ if (for_guard && is_node_used_as_guard(node)) {
+ continue;
+ }
/* Ensure that a directory guard is actually a guard node. */
if (for_guard && !node->is_possible_guard) {
continue;
diff --git a/src/or/routerparse.c b/src/or/routerparse.c
index 93484660d2..7f7d38234d 100644
--- a/src/or/routerparse.c
+++ b/src/or/routerparse.c
@@ -2220,7 +2220,7 @@ router_parse_entry_from_string(const char *s, const char *end,
escaped(tok->args[i]));
goto err;
}
- smartlist_add(router->declared_family, tor_strdup(tok->args[i]));
+ smartlist_add_strdup(router->declared_family, tok->args[i]);
}
}
@@ -3723,9 +3723,9 @@ networkstatus_parse_vote_from_string(const char *s, const char **eos_out,
tok = find_opt_by_keyword(tokens, K_CONSENSUS_METHODS);
if (tok) {
for (i=0; i < tok->n_args; ++i)
- smartlist_add(ns->supported_methods, tor_strdup(tok->args[i]));
+ smartlist_add_strdup(ns->supported_methods, tok->args[i]);
} else {
- smartlist_add(ns->supported_methods, tor_strdup("1"));
+ smartlist_add_strdup(ns->supported_methods, "1");
}
} else {
tok = find_opt_by_keyword(tokens, K_CONSENSUS_METHOD);
@@ -3807,7 +3807,7 @@ networkstatus_parse_vote_from_string(const char *s, const char **eos_out,
ns->package_lines = smartlist_new();
if (package_lst) {
SMARTLIST_FOREACH(package_lst, directory_token_t *, t,
- smartlist_add(ns->package_lines, tor_strdup(t->args[0])));
+ smartlist_add_strdup(ns->package_lines, t->args[0]));
}
smartlist_free(package_lst);
}
@@ -3816,7 +3816,7 @@ networkstatus_parse_vote_from_string(const char *s, const char **eos_out,
ns->known_flags = smartlist_new();
inorder = 1;
for (i = 0; i < tok->n_args; ++i) {
- smartlist_add(ns->known_flags, tor_strdup(tok->args[i]));
+ smartlist_add_strdup(ns->known_flags, tok->args[i]);
if (i>0 && strcmp(tok->args[i-1], tok->args[i])>= 0) {
log_warn(LD_DIR, "%s >= %s", tok->args[i-1], tok->args[i]);
inorder = 0;
@@ -3868,7 +3868,7 @@ networkstatus_parse_vote_from_string(const char *s, const char **eos_out,
}
tor_free(last_kwd);
last_kwd = tor_strndup(tok->args[i], eq_pos);
- smartlist_add(ns->net_params, tor_strdup(tok->args[i]));
+ smartlist_add_strdup(ns->net_params, tok->args[i]);
}
if (!inorder) {
log_warn(LD_DIR, "params not in order");
@@ -4111,7 +4111,7 @@ networkstatus_parse_vote_from_string(const char *s, const char **eos_out,
log_warn(LD_DIR, "Bad element '%s' in params", escaped(tok->args[i]));
goto err;
}
- smartlist_add(ns->weight_params, tor_strdup(tok->args[i]));
+ smartlist_add_strdup(ns->weight_params, tok->args[i]);
}
}
@@ -5476,7 +5476,7 @@ microdescs_parse_from_string(const char *s, const char *eos,
escaped(tok->args[i]));
goto next;
}
- smartlist_add(md->family, tor_strdup(tok->args[i]));
+ smartlist_add_strdup(md->family, tok->args[i]);
}
}
diff --git a/src/or/routerset.c b/src/or/routerset.c
index 58b66ea777..4182dbc5c4 100644
--- a/src/or/routerset.c
+++ b/src/or/routerset.c
@@ -262,12 +262,12 @@ routerset_add_unknown_ccs(routerset_t **setp, int only_if_some_cc_set)
geoip_get_country("A1") >= 0;
if (add_unknown) {
- smartlist_add(set->country_names, tor_strdup("??"));
- smartlist_add(set->list, tor_strdup("{??}"));
+ smartlist_add_strdup(set->country_names, "??");
+ smartlist_add_strdup(set->list, "{??}");
}
if (add_a1) {
- smartlist_add(set->country_names, tor_strdup("a1"));
- smartlist_add(set->list, tor_strdup("{a1}"));
+ smartlist_add_strdup(set->country_names, "a1");
+ smartlist_add_strdup(set->list, "{a1}");
}
if (add_unknown || add_a1) {
diff --git a/src/or/scheduler.c b/src/or/scheduler.c
index 49ac1b939a..033e6d119c 100644
--- a/src/or/scheduler.c
+++ b/src/or/scheduler.c
@@ -1,11 +1,6 @@
/* * Copyright (c) 2013-2016, The Tor Project, Inc. */
/* See LICENSE for licensing information */
-/**
- * \file scheduler.c
- * \brief Relay scheduling system
- **/
-
#include "or.h"
#define TOR_CHANNEL_INTERNAL_ /* For channel_flush_some_cells() */
@@ -32,66 +27,102 @@ static uint32_t sched_q_high_water = 32768;
static uint32_t sched_max_flush_cells = 16;
-/*
- * Write scheduling works by keeping track of which channels can
+/**
+ * \file scheduler.c
+ * \brief Channel scheduling system: decides which channels should send and
+ * receive when.
+ *
+ * This module implements a scheduler algorithm, to decide
+ * which channels should send/receive when.
+ *
+ * The earliest versions of Tor approximated a kind of round-robin system
+ * among active connections, but only approximated it.
+ *
+ * Now, write scheduling works by keeping track of which channels can
* accept cells, and have cells to write. From the scheduler's perspective,
* a channel can be in four possible states:
*
- * 1.) Not open for writes, no cells to send
- * - Not much to do here, and the channel will have scheduler_state ==
- * SCHED_CHAN_IDLE
- * - Transitions from:
- * - Open for writes/has cells by simultaneously draining all circuit
+ * <ol>
+ * <li>
+ * Not open for writes, no cells to send.
+ * <ul><li> Not much to do here, and the channel will have scheduler_state
+ * == SCHED_CHAN_IDLE
+ * <li> Transitions from:
+ * <ul>
+ * <li>Open for writes/has cells by simultaneously draining all circuit
* queues and filling the output buffer.
- * - Transitions to:
- * - Not open for writes/has cells by arrival of cells on an attached
+ * </ul>
+ * <li> Transitions to:
+ * <ul>
+ * <li> Not open for writes/has cells by arrival of cells on an attached
* circuit (this would be driven from append_cell_to_circuit_queue())
- * - Open for writes/no cells by a channel type specific path;
+ * <li> Open for writes/no cells by a channel type specific path;
* driven from connection_or_flushed_some() for channel_tls_t.
+ * </ul>
+ * </ul>
*
- * 2.) Open for writes, no cells to send
- * - Not much here either; this will be the state an idle but open channel
- * can be expected to settle in. It will have scheduler_state ==
- * SCHED_CHAN_WAITING_FOR_CELLS
- * - Transitions from:
- * - Not open for writes/no cells by flushing some of the output
+ * <li> Open for writes, no cells to send
+ * <ul>
+ * <li>Not much here either; this will be the state an idle but open
+ * channel can be expected to settle in. It will have scheduler_state
+ * == SCHED_CHAN_WAITING_FOR_CELLS
+ * <li> Transitions from:
+ * <ul>
+ * <li>Not open for writes/no cells by flushing some of the output
* buffer.
- * - Open for writes/has cells by the scheduler moving cells from
+ * <li>Open for writes/has cells by the scheduler moving cells from
* circuit queues to channel output queue, but not having enough
* to fill the output queue.
- * - Transitions to:
- * - Open for writes/has cells by arrival of new cells on an attached
+ * </ul>
+ * <li> Transitions to:
+ * <ul>
+ * <li>Open for writes/has cells by arrival of new cells on an attached
* circuit, in append_cell_to_circuit_queue()
+ * </ul>
+ * </ul>
*
- * 3.) Not open for writes, cells to send
- * - This is the state of a busy circuit limited by output bandwidth;
+ * <li>Not open for writes, cells to send
+ * <ul>
+ * <li>This is the state of a busy circuit limited by output bandwidth;
* cells have piled up in the circuit queues waiting to be relayed.
* The channel will have scheduler_state == SCHED_CHAN_WAITING_TO_WRITE.
- * - Transitions from:
- * - Not open for writes/no cells by arrival of cells on an attached
+ * <li> Transitions from:
+ * <ul>
+ * <li>Not open for writes/no cells by arrival of cells on an attached
* circuit
- * - Open for writes/has cells by filling an output buffer without
+ * <li> Open for writes/has cells by filling an output buffer without
* draining all cells from attached circuits
- * - Transitions to:
- * - Opens for writes/has cells by draining some of the output buffer
+ * </ul>
+ * <li> Transitions to:
+ * <ul>
+ * <li>Opens for writes/has cells by draining some of the output buffer
* via the connection_or_flushed_some() path (for channel_tls_t).
+ * </ul>
+ * </ul>
*
- * 4.) Open for writes, cells to send
- * - This connection is ready to relay some cells and waiting for
+ * <li>Open for writes, cells to send
+ * <ul>
+ * <li>This connection is ready to relay some cells and waiting for
* the scheduler to choose it. The channel will have scheduler_state ==
* SCHED_CHAN_PENDING.
- * - Transitions from:
- * - Not open for writes/has cells by the connection_or_flushed_some()
+ * <li>Transitions from:
+ * <ul>
+ * <li> Not open for writes/has cells by the connection_or_flushed_some()
* path
- * - Open for writes/no cells by the append_cell_to_circuit_queue()
+ * <li> Open for writes/no cells by the append_cell_to_circuit_queue()
* path
- * - Transitions to:
- * - Not open for writes/no cells by draining all circuit queues and
- * simultaneously filling the output buffer.
- * - Not open for writes/has cells by writing enough cells to fill the
+ * </ul>
+ * <li> Transitions to:
+ * <ul>
+ * <li>Not open for writes/no cells by draining all circuit queues and
+ * simultaneously filling the output buffer.
+ * <li>Not open for writes/has cells by writing enough cells to fill the
* output buffer
- * - Open for writes/no cells by draining all attached circuit queues
+ * <li>Open for writes/no cells by draining all attached circuit queues
* without also filling the output buffer
+ * </ul>
+ * </ul>
+ * </ol>
*
* Other event-driven parts of the code move channels between these scheduling
* states by calling scheduler functions; the scheduler only runs on open-for-
diff --git a/src/or/torcert.c b/src/or/torcert.c
index a6a33c675a..37a201ea60 100644
--- a/src/or/torcert.c
+++ b/src/or/torcert.c
@@ -6,6 +6,23 @@
*
* \brief Implementation for ed25519-signed certificates as used in the Tor
* protocol.
+ *
+ * This certificate format is designed to be simple and compact; it's
+ * documented in tor-spec.txt in the torspec.git repository. All of the
+ * certificates in this format are signed with an Ed25519 key; the
+ * contents themselves may be another Ed25519 key, a digest of a
+ * RSA key, or some other material.
+ *
+ * In this module there is also support for a crooss-certification of
+ * Ed25519 identities using (older) RSA1024 identities.
+ *
+ * Tor uses other types of certificate too, beyond those described in this
+ * module. Notably, our use of TLS requires us to touch X.509 certificates,
+ * even though sensible people would stay away from those. Our X.509
+ * certificates are represented with tor_x509_cert_t, and implemented in
+ * tortls.c. We also have a separate certificate type that authorities
+ * use to authenticate their RSA signing keys with their RSA identity keys:
+ * that one is authority_cert_t, and it's mostly handled in routerlist.c.
*/
#include "crypto.h"
diff --git a/src/or/transports.c b/src/or/transports.c
index be77c871c4..614b28c168 100644
--- a/src/or/transports.c
+++ b/src/or/transports.c
@@ -430,7 +430,7 @@ add_transport_to_proxy(const char *transport, managed_proxy_t *mp)
{
tor_assert(mp->transports_to_launch);
if (!smartlist_contains_string(mp->transports_to_launch, transport))
- smartlist_add(mp->transports_to_launch, tor_strdup(transport));
+ smartlist_add_strdup(mp->transports_to_launch, transport);
}
/** Called when a SIGHUP occurs. Returns true if managed proxy
@@ -1322,7 +1322,7 @@ create_managed_proxy_environment(const managed_proxy_t *mp)
tor_free(state_tmp);
}
- smartlist_add(envs, tor_strdup("TOR_PT_MANAGED_TRANSPORT_VER=1"));
+ smartlist_add_strdup(envs, "TOR_PT_MANAGED_TRANSPORT_VER=1");
{
char *transports_to_launch =
diff --git a/src/test/test_containers.c b/src/test/test_containers.c
index d8b82e0661..d7291a2ce2 100644
--- a/src/test/test_containers.c
+++ b/src/test/test_containers.c
@@ -501,13 +501,13 @@ test_container_smartlist_pos(void *arg)
(void) arg;
smartlist_t *sl = smartlist_new();
- smartlist_add(sl, tor_strdup("This"));
- smartlist_add(sl, tor_strdup("is"));
- smartlist_add(sl, tor_strdup("a"));
- smartlist_add(sl, tor_strdup("test"));
- smartlist_add(sl, tor_strdup("for"));
- smartlist_add(sl, tor_strdup("a"));
- smartlist_add(sl, tor_strdup("function"));
+ smartlist_add_strdup(sl, "This");
+ smartlist_add_strdup(sl, "is");
+ smartlist_add_strdup(sl, "a");
+ smartlist_add_strdup(sl, "test");
+ smartlist_add_strdup(sl, "for");
+ smartlist_add_strdup(sl, "a");
+ smartlist_add_strdup(sl, "function");
/* Test string_pos */
tt_int_op(smartlist_string_pos(NULL, "Fred"), ==, -1);
@@ -830,7 +830,7 @@ test_container_strmap(void *arg)
found_keys = smartlist_new();
while (!strmap_iter_done(iter)) {
strmap_iter_get(iter,&k,&v);
- smartlist_add(found_keys, tor_strdup(k));
+ smartlist_add_strdup(found_keys, k);
tt_ptr_op(v,OP_EQ, strmap_get(map, k));
if (!strcmp(k, "K2")) {
diff --git a/src/test/test_dir.c b/src/test/test_dir.c
index 77c5dc13c8..cf0b94c574 100644
--- a/src/test/test_dir.c
+++ b/src/test/test_dir.c
@@ -678,16 +678,16 @@ test_dir_parse_router_list(void *arg)
routerinfo_t *ri = NULL;
char d[DIGEST_LEN];
- smartlist_add(chunks, tor_strdup(EX_RI_MINIMAL)); // ri 0
- smartlist_add(chunks, tor_strdup(EX_RI_BAD_PORTS)); // bad ri 0
- smartlist_add(chunks, tor_strdup(EX_EI_MAXIMAL)); // ei 0
- smartlist_add(chunks, tor_strdup(EX_EI_BAD_SIG2)); // bad ei --
- smartlist_add(chunks, tor_strdup(EX_EI_BAD_NICKNAME));// bad ei 0
- smartlist_add(chunks, tor_strdup(EX_RI_BAD_SIG1)); // bad ri --
- smartlist_add(chunks, tor_strdup(EX_EI_BAD_PUBLISHED)); // bad ei 1
- smartlist_add(chunks, tor_strdup(EX_RI_MAXIMAL)); // ri 1
- smartlist_add(chunks, tor_strdup(EX_RI_BAD_FAMILY)); // bad ri 1
- smartlist_add(chunks, tor_strdup(EX_EI_MINIMAL)); // ei 1
+ smartlist_add_strdup(chunks, EX_RI_MINIMAL); // ri 0
+ smartlist_add_strdup(chunks, EX_RI_BAD_PORTS); // bad ri 0
+ smartlist_add_strdup(chunks, EX_EI_MAXIMAL); // ei 0
+ smartlist_add_strdup(chunks, EX_EI_BAD_SIG2); // bad ei --
+ smartlist_add_strdup(chunks, EX_EI_BAD_NICKNAME);// bad ei 0
+ smartlist_add_strdup(chunks, EX_RI_BAD_SIG1); // bad ri --
+ smartlist_add_strdup(chunks, EX_EI_BAD_PUBLISHED); // bad ei 1
+ smartlist_add_strdup(chunks, EX_RI_MAXIMAL); // ri 1
+ smartlist_add_strdup(chunks, EX_RI_BAD_FAMILY); // bad ri 1
+ smartlist_add_strdup(chunks, EX_EI_MINIMAL); // ei 1
list = smartlist_join_strings(chunks, "", 0, NULL);
@@ -812,19 +812,19 @@ test_dir_load_routers(void *arg)
#define ADD(str) \
do { \
tt_int_op(0,OP_EQ,router_get_router_hash(str, strlen(str), buf)); \
- smartlist_add(wanted, tor_strdup(hex_str(buf, DIGEST_LEN))); \
+ smartlist_add_strdup(wanted, hex_str(buf, DIGEST_LEN)); \
} while (0)
MOCK(router_get_dl_status_by_descriptor_digest, mock_router_get_dl_status);
update_approx_time(1412510400);
- smartlist_add(chunks, tor_strdup(EX_RI_MINIMAL));
- smartlist_add(chunks, tor_strdup(EX_RI_BAD_FINGERPRINT));
- smartlist_add(chunks, tor_strdup(EX_RI_BAD_SIG2));
- smartlist_add(chunks, tor_strdup(EX_RI_MAXIMAL));
- smartlist_add(chunks, tor_strdup(EX_RI_BAD_PORTS));
- smartlist_add(chunks, tor_strdup(EX_RI_BAD_TOKENS));
+ smartlist_add_strdup(chunks, EX_RI_MINIMAL);
+ smartlist_add_strdup(chunks, EX_RI_BAD_FINGERPRINT);
+ smartlist_add_strdup(chunks, EX_RI_BAD_SIG2);
+ smartlist_add_strdup(chunks, EX_RI_MAXIMAL);
+ smartlist_add_strdup(chunks, EX_RI_BAD_PORTS);
+ smartlist_add_strdup(chunks, EX_RI_BAD_TOKENS);
/* not ADDing MINIMIAL */
ADD(EX_RI_MAXIMAL);
@@ -932,18 +932,18 @@ test_dir_load_extrainfo(void *arg)
#define ADD(str) \
do { \
tt_int_op(0,OP_EQ,router_get_extrainfo_hash(str, strlen(str), buf)); \
- smartlist_add(wanted, tor_strdup(hex_str(buf, DIGEST_LEN))); \
+ smartlist_add_strdup(wanted, hex_str(buf, DIGEST_LEN)); \
} while (0)
mock_ei_insert_list = smartlist_new();
MOCK(router_get_by_extrainfo_digest, mock_get_by_ei_desc_digest);
MOCK(extrainfo_insert, mock_ei_insert);
- smartlist_add(chunks, tor_strdup(EX_EI_MINIMAL));
- smartlist_add(chunks, tor_strdup(EX_EI_BAD_NICKNAME));
- smartlist_add(chunks, tor_strdup(EX_EI_MAXIMAL));
- smartlist_add(chunks, tor_strdup(EX_EI_BAD_PUBLISHED));
- smartlist_add(chunks, tor_strdup(EX_EI_BAD_TOKENS));
+ smartlist_add_strdup(chunks, EX_EI_MINIMAL);
+ smartlist_add_strdup(chunks, EX_EI_BAD_NICKNAME);
+ smartlist_add_strdup(chunks, EX_EI_MAXIMAL);
+ smartlist_add_strdup(chunks, EX_EI_BAD_PUBLISHED);
+ smartlist_add_strdup(chunks, EX_EI_BAD_TOKENS);
/* not ADDing MINIMIAL */
ADD(EX_EI_MAXIMAL);
@@ -1874,6 +1874,249 @@ test_routerstatus_for_v3ns(routerstatus_t *rs, time_t now)
return;
}
+static void
+test_dir_networkstatus_compute_bw_weights_v10(void *arg)
+{
+ (void) arg;
+ smartlist_t *chunks = smartlist_new();
+ int64_t G, M, E, D, T, weight_scale;
+ int ret;
+ weight_scale = 10000;
+
+ /* no case. one or more of the values is 0 */
+ G = M = E = D = 0;
+ T = G + M + E + D;
+ ret = networkstatus_compute_bw_weights_v10(chunks, G, M, E, D, T,
+ weight_scale);
+ tt_int_op(ret, OP_EQ, 0);
+ tt_int_op(smartlist_len(chunks), OP_EQ, 0);
+
+ /* case 1 */
+ /* XXX dir-spec not followed? See #20272. If it isn't closed, then this is
+ * testing current behavior, not spec. */
+ G = E = 10;
+ M = D = 1;
+ T = G + M + E + D;
+ ret = networkstatus_compute_bw_weights_v10(chunks, G, M, E, D, T,
+ weight_scale);
+ tt_int_op(ret, OP_EQ, 1);
+ tt_int_op(smartlist_len(chunks), OP_EQ, 1);
+ tt_str_op(smartlist_get(chunks, 0), OP_EQ, "bandwidth-weights Wbd=3333 "
+ "Wbe=3000 Wbg=3000 Wbm=10000 Wdb=10000 Web=10000 Wed=3333 Wee=7000 "
+ "Weg=3333 Wem=7000 Wgb=10000 Wgd=3333 Wgg=7000 Wgm=7000 Wmb=10000 "
+ "Wmd=3333 Wme=3000 Wmg=3000 Wmm=10000\n");
+ SMARTLIST_FOREACH(chunks, char *, cp, tor_free(cp));
+ smartlist_clear(chunks);
+
+ /* case 2a E scarce */
+ M = 100;
+ G = 20;
+ E = D = 5;
+ T = G + M + E + D;
+ ret = networkstatus_compute_bw_weights_v10(chunks, G, M, E, D, T,
+ weight_scale);
+ tt_int_op(ret, OP_EQ, 1);
+ tt_str_op(smartlist_get(chunks, 0), OP_EQ, "bandwidth-weights Wbd=0 Wbe=0 "
+ "Wbg=0 Wbm=10000 Wdb=10000 Web=10000 Wed=10000 Wee=10000 Weg=10000 "
+ "Wem=10000 Wgb=10000 Wgd=0 Wgg=10000 Wgm=10000 Wmb=10000 Wmd=0 Wme=0 "
+ "Wmg=0 Wmm=10000\n");
+ SMARTLIST_FOREACH(chunks, char *, cp, tor_free(cp));
+ smartlist_clear(chunks);
+
+ /* case 2a G scarce */
+ M = 100;
+ E = 20;
+ G = D = 5;
+ T = G + M + E + D;
+ ret = networkstatus_compute_bw_weights_v10(chunks, G, M, E, D, T,
+ weight_scale);
+ tt_int_op(ret, OP_EQ, 1);
+ tt_str_op(smartlist_get(chunks, 0), OP_EQ, "bandwidth-weights Wbd=0 Wbe=0 "
+ "Wbg=0 Wbm=10000 Wdb=10000 Web=10000 Wed=0 Wee=10000 Weg=0 Wem=10000 "
+ "Wgb=10000 Wgd=10000 Wgg=10000 Wgm=10000 Wmb=10000 Wmd=0 Wme=0 Wmg=0 "
+ "Wmm=10000\n");
+ SMARTLIST_FOREACH(chunks, char *, cp, tor_free(cp));
+ smartlist_clear(chunks);
+
+ /* case 2b1 (Wgg=1, Wmd=Wgd) */
+ M = 10;
+ E = 30;
+ G = 10;
+ D = 100;
+ T = G + M + E + D;
+ ret = networkstatus_compute_bw_weights_v10(chunks, G, M, E, D, T,
+ weight_scale);
+ tt_int_op(ret, OP_EQ, 1);
+ tt_str_op(smartlist_get(chunks, 0), OP_EQ, "bandwidth-weights Wbd=4000 "
+ "Wbe=0 Wbg=0 Wbm=10000 Wdb=10000 Web=10000 Wed=2000 Wee=10000 Weg=2000 "
+ "Wem=10000 Wgb=10000 Wgd=4000 Wgg=10000 Wgm=10000 Wmb=10000 Wmd=4000 "
+ "Wme=0 Wmg=0 Wmm=10000\n");
+ SMARTLIST_FOREACH(chunks, char *, cp, tor_free(cp));
+ smartlist_clear(chunks);
+
+ /* case 2b2 */
+ M = 60;
+ E = 30;
+ G = 10;
+ D = 100;
+ T = G + M + E + D;
+ ret = networkstatus_compute_bw_weights_v10(chunks, G, M, E, D, T,
+ weight_scale);
+ tt_int_op(ret, OP_EQ, 1);
+ tt_str_op(smartlist_get(chunks, 0), OP_EQ, "bandwidth-weights Wbd=666 Wbe=0 "
+ "Wbg=0 Wbm=10000 Wdb=10000 Web=10000 Wed=3666 Wee=10000 Weg=3666 "
+ "Wem=10000 Wgb=10000 Wgd=5668 Wgg=10000 Wgm=10000 Wmb=10000 Wmd=666 "
+ "Wme=0 Wmg=0 Wmm=10000\n");
+ SMARTLIST_FOREACH(chunks, char *, cp, tor_free(cp));
+ smartlist_clear(chunks);
+
+ /* case 2b3 */
+ /* XXX I can't get a combination of values that hits this case without error,
+ * so this just tests that it fails. See #20285. Also see #20284 as 2b3 does
+ * not follow dir-spec. */
+ /* (E < T/3 && G < T/3) && (E+D>=G || G+D>=E) && (M > T/3) */
+ M = 80;
+ E = 30;
+ G = 30;
+ D = 30;
+ T = G + M + E + D;
+ ret = networkstatus_compute_bw_weights_v10(chunks, G, M, E, D, T,
+ weight_scale);
+ tt_int_op(ret, OP_EQ, 0);
+ SMARTLIST_FOREACH(chunks, char *, cp, tor_free(cp));
+ smartlist_clear(chunks);
+
+ /* case 3a G scarce */
+ M = 10;
+ E = 30;
+ G = 10;
+ D = 5;
+ T = G + M + E + D;
+ ret = networkstatus_compute_bw_weights_v10(chunks, G, M, E, D, T,
+ weight_scale);
+ tt_int_op(ret, OP_EQ, 1);
+ tt_str_op(smartlist_get(chunks, 0), OP_EQ, "bandwidth-weights Wbd=0 "
+ "Wbe=3333 Wbg=0 Wbm=10000 Wdb=10000 Web=10000 Wed=0 Wee=6667 Weg=0 "
+ "Wem=6667 Wgb=10000 Wgd=10000 Wgg=10000 Wgm=10000 Wmb=10000 Wmd=0 "
+ "Wme=3333 Wmg=0 Wmm=10000\n");
+ SMARTLIST_FOREACH(chunks, char *, cp, tor_free(cp));
+ smartlist_clear(chunks);
+
+ /* case 3a E scarce */
+ M = 10;
+ E = 10;
+ G = 30;
+ D = 5;
+ T = G + M + E + D;
+ ret = networkstatus_compute_bw_weights_v10(chunks, G, M, E, D, T,
+ weight_scale);
+ tt_int_op(ret, OP_EQ, 1);
+ tt_str_op(smartlist_get(chunks, 0), OP_EQ, "bandwidth-weights Wbd=0 Wbe=0 "
+ "Wbg=3333 Wbm=10000 Wdb=10000 Web=10000 Wed=10000 Wee=10000 Weg=10000 "
+ "Wem=10000 Wgb=10000 Wgd=0 Wgg=6667 Wgm=6667 Wmb=10000 Wmd=0 Wme=0 "
+ "Wmg=3333 Wmm=10000\n");
+ SMARTLIST_FOREACH(chunks, char *, cp, tor_free(cp));
+ smartlist_clear(chunks);
+
+ /* case 3bg */
+ M = 10;
+ E = 30;
+ G = 10;
+ D = 10;
+ T = G + M + E + D;
+ ret = networkstatus_compute_bw_weights_v10(chunks, G, M, E, D, T,
+ weight_scale);
+ tt_int_op(ret, OP_EQ, 1);
+ tt_str_op(smartlist_get(chunks, 0), OP_EQ, "bandwidth-weights Wbd=0 "
+ "Wbe=3334 Wbg=0 Wbm=10000 Wdb=10000 Web=10000 Wed=0 Wee=6666 Weg=0 "
+ "Wem=6666 Wgb=10000 Wgd=10000 Wgg=10000 Wgm=10000 Wmb=10000 Wmd=0 "
+ "Wme=3334 Wmg=0 Wmm=10000\n");
+ SMARTLIST_FOREACH(chunks, char *, cp, tor_free(cp));
+ smartlist_clear(chunks);
+
+ /* case 3be */
+ M = 10;
+ E = 10;
+ G = 30;
+ D = 10;
+ T = G + M + E + D;
+ ret = networkstatus_compute_bw_weights_v10(chunks, G, M, E, D, T,
+ weight_scale);
+ tt_int_op(ret, OP_EQ, 1);
+ tt_str_op(smartlist_get(chunks, 0), OP_EQ, "bandwidth-weights Wbd=0 Wbe=0 "
+ "Wbg=3334 Wbm=10000 Wdb=10000 Web=10000 Wed=10000 Wee=10000 Weg=10000 "
+ "Wem=10000 Wgb=10000 Wgd=0 Wgg=6666 Wgm=6666 Wmb=10000 Wmd=0 Wme=0 "
+ "Wmg=3334 Wmm=10000\n");
+ SMARTLIST_FOREACH(chunks, char *, cp, tor_free(cp));
+ smartlist_clear(chunks);
+
+ /* case from 21 Jul 2013 (3be) */
+ G = 5483409;
+ M = 1455379;
+ E = 980834;
+ D = 3385803;
+ T = 11305425;
+ tt_i64_op(G+M+E+D, OP_EQ, T);
+ ret = networkstatus_compute_bw_weights_v10(chunks, G, M, E, D, T,
+ weight_scale);
+ tt_str_op(smartlist_get(chunks, 0), OP_EQ, "bandwidth-weights Wbd=883 Wbe=0 "
+ "Wbg=3673 Wbm=10000 Wdb=10000 Web=10000 Wed=8233 Wee=10000 Weg=8233 "
+ "Wem=10000 Wgb=10000 Wgd=883 Wgg=6327 Wgm=6327 Wmb=10000 Wmd=883 Wme=0 "
+ "Wmg=3673 Wmm=10000\n");
+ SMARTLIST_FOREACH(chunks, char *, cp, tor_free(cp));
+ smartlist_clear(chunks);
+
+ /* case from 04 Oct 2016 (3a E scarce) */
+ G=29322240;
+ M=4721546;
+ E=1522058;
+ D=9273571;
+ T=44839415;
+ tt_i64_op(G+M+E+D, OP_EQ, T);
+ ret = networkstatus_compute_bw_weights_v10(chunks, G, M, E, D, T,
+ weight_scale);
+ tt_str_op(smartlist_get(chunks, 0), OP_EQ, "bandwidth-weights Wbd=0 Wbe=0 "
+ "Wbg=4194 Wbm=10000 Wdb=10000 Web=10000 Wed=10000 Wee=10000 Weg=10000 "
+ "Wem=10000 Wgb=10000 Wgd=0 Wgg=5806 Wgm=5806 Wmb=10000 Wmd=0 Wme=0 "
+ "Wmg=4194 Wmm=10000\n");
+ SMARTLIST_FOREACH(chunks, char *, cp, tor_free(cp));
+ smartlist_clear(chunks);
+
+ /* case from 04 Sep 2013 (2b1) */
+ G=3091352;
+ M=1838837;
+ E=2109300;
+ D=2469369;
+ T=9508858;
+ tt_i64_op(G+M+E+D, OP_EQ, T);
+ ret = networkstatus_compute_bw_weights_v10(chunks, G, M, E, D, T,
+ weight_scale);
+ tt_str_op(smartlist_get(chunks, 0), OP_EQ, "bandwidth-weights Wbd=317 "
+ "Wbe=5938 Wbg=0 Wbm=10000 Wdb=10000 Web=10000 Wed=9366 Wee=4061 "
+ "Weg=9366 Wem=4061 Wgb=10000 Wgd=317 Wgg=10000 Wgm=10000 Wmb=10000 "
+ "Wmd=317 Wme=5938 Wmg=0 Wmm=10000\n");
+ SMARTLIST_FOREACH(chunks, char *, cp, tor_free(cp));
+ smartlist_clear(chunks);
+
+ /* explicitly test initializing weights to 1*/
+ G=1;
+ M=1;
+ E=1;
+ D=1;
+ T=4;
+ tt_i64_op(G+M+E+D, OP_EQ, T);
+ ret = networkstatus_compute_bw_weights_v10(chunks, G, M, E, D, T,
+ weight_scale);
+ tt_str_op(smartlist_get(chunks, 0), OP_EQ, "bandwidth-weights Wbd=3333 "
+ "Wbe=0 Wbg=0 Wbm=10000 Wdb=10000 Web=10000 Wed=3333 Wee=10000 Weg=3333 "
+ "Wem=10000 Wgb=10000 Wgd=3333 Wgg=10000 Wgm=10000 Wmb=10000 Wmd=3333 "
+ "Wme=0 Wmg=0 Wmm=10000\n");
+
+ done:
+ SMARTLIST_FOREACH(chunks, char *, cp, tor_free(cp));
+ smartlist_free(chunks);
+}
+
static authority_cert_t *mock_cert;
static authority_cert_t *
@@ -3253,17 +3496,83 @@ test_dir_http_handling(void *args)
}
static void
-test_dir_purpose_needs_anonymity(void *arg)
+test_dir_purpose_needs_anonymity_returns_true_by_default(void *arg)
{
(void)arg;
- tt_int_op(1, ==, purpose_needs_anonymity(0, ROUTER_PURPOSE_BRIDGE));
- tt_int_op(1, ==, purpose_needs_anonymity(0, ROUTER_PURPOSE_GENERAL));
- tt_int_op(0, ==, purpose_needs_anonymity(DIR_PURPOSE_FETCH_MICRODESC,
- ROUTER_PURPOSE_GENERAL));
+
+ tor_capture_bugs_(1);
+ tt_int_op(1, ==, purpose_needs_anonymity(0, 0, NULL));
+ tt_int_op(1, ==, smartlist_len(tor_get_captured_bug_log_()));
+ tor_end_capture_bugs_();
done: ;
}
static void
+test_dir_purpose_needs_anonymity_returns_true_for_bridges(void *arg)
+{
+ (void)arg;
+
+ tt_int_op(1, ==, purpose_needs_anonymity(0, ROUTER_PURPOSE_BRIDGE, NULL));
+ tt_int_op(1, ==, purpose_needs_anonymity(0, ROUTER_PURPOSE_BRIDGE,
+ "foobar"));
+ tt_int_op(1, ==, purpose_needs_anonymity(DIR_PURPOSE_HAS_FETCHED_RENDDESC_V2,
+ ROUTER_PURPOSE_BRIDGE, NULL));
+ done: ;
+}
+
+static void
+test_dir_purpose_needs_anonymity_returns_false_for_own_bridge_desc(void *arg)
+{
+ (void)arg;
+ tt_int_op(0, ==, purpose_needs_anonymity(DIR_PURPOSE_FETCH_SERVERDESC,
+ ROUTER_PURPOSE_BRIDGE,
+ "authority.z"));
+ done: ;
+}
+
+static void
+test_dir_purpose_needs_anonymity_returns_true_for_sensitive_purpose(void *arg)
+{
+ (void)arg;
+
+ tt_int_op(1, ==, purpose_needs_anonymity(
+ DIR_PURPOSE_HAS_FETCHED_RENDDESC_V2,
+ ROUTER_PURPOSE_GENERAL, NULL));
+ tt_int_op(1, ==, purpose_needs_anonymity(
+ DIR_PURPOSE_UPLOAD_RENDDESC_V2, 0, NULL));
+ tt_int_op(1, ==, purpose_needs_anonymity(
+ DIR_PURPOSE_FETCH_RENDDESC_V2, 0, NULL));
+ done: ;
+}
+
+static void
+test_dir_purpose_needs_anonymity_ret_false_for_non_sensitive_conn(void *arg)
+{
+ (void)arg;
+
+ tt_int_op(0, ==, purpose_needs_anonymity(DIR_PURPOSE_UPLOAD_DIR,
+ ROUTER_PURPOSE_GENERAL, NULL));
+ tt_int_op(0, ==, purpose_needs_anonymity(DIR_PURPOSE_UPLOAD_VOTE, 0, NULL));
+ tt_int_op(0, ==,
+ purpose_needs_anonymity(DIR_PURPOSE_UPLOAD_SIGNATURES, 0, NULL));
+ tt_int_op(0, ==,
+ purpose_needs_anonymity(DIR_PURPOSE_FETCH_STATUS_VOTE, 0, NULL));
+ tt_int_op(0, ==, purpose_needs_anonymity(
+ DIR_PURPOSE_FETCH_DETACHED_SIGNATURES, 0, NULL));
+ tt_int_op(0, ==,
+ purpose_needs_anonymity(DIR_PURPOSE_FETCH_CONSENSUS, 0, NULL));
+ tt_int_op(0, ==,
+ purpose_needs_anonymity(DIR_PURPOSE_FETCH_CERTIFICATE, 0, NULL));
+ tt_int_op(0, ==,
+ purpose_needs_anonymity(DIR_PURPOSE_FETCH_SERVERDESC, 0, NULL));
+ tt_int_op(0, ==,
+ purpose_needs_anonymity(DIR_PURPOSE_FETCH_EXTRAINFO, 0, NULL));
+ tt_int_op(0, ==,
+ purpose_needs_anonymity(DIR_PURPOSE_FETCH_MICRODESC, 0, NULL));
+ done: ;
+}
+
+static void
test_dir_fetch_type(void *arg)
{
(void)arg;
@@ -5142,9 +5451,9 @@ listdir_mock(const char *dname)
(void)dname;
l = smartlist_new();
- smartlist_add(l, tor_strdup("foo"));
- smartlist_add(l, tor_strdup("bar"));
- smartlist_add(l, tor_strdup("baz"));
+ smartlist_add_strdup(l, "foo");
+ smartlist_add_strdup(l, "bar");
+ smartlist_add_strdup(l, "baz");
return l;
}
@@ -5464,7 +5773,11 @@ struct testcase_t dir_tests[] = {
DIR(fmt_control_ns, 0),
DIR(dirserv_set_routerstatus_testing, 0),
DIR(http_handling, 0),
- DIR(purpose_needs_anonymity, 0),
+ DIR(purpose_needs_anonymity_returns_true_for_bridges, 0),
+ DIR(purpose_needs_anonymity_returns_false_for_own_bridge_desc, 0),
+ DIR(purpose_needs_anonymity_returns_true_by_default, 0),
+ DIR(purpose_needs_anonymity_returns_true_for_sensitive_purpose, 0),
+ DIR(purpose_needs_anonymity_ret_false_for_non_sensitive_conn, 0),
DIR(fetch_type, 0),
DIR(packages, 0),
DIR(download_status_schedule, 0),
@@ -5485,6 +5798,7 @@ struct testcase_t dir_tests[] = {
DIR_ARG(find_dl_schedule, TT_FORK, "cf"),
DIR_ARG(find_dl_schedule, TT_FORK, "ca"),
DIR(assumed_flags, 0),
+ DIR(networkstatus_compute_bw_weights_v10, 0),
END_OF_TESTCASES
};
diff --git a/src/test/test_entryconn.c b/src/test/test_entryconn.c
index 9580a1fd3f..50848cfec2 100644
--- a/src/test/test_entryconn.c
+++ b/src/test/test_entryconn.c
@@ -100,7 +100,7 @@ test_entryconn_rewrite_automap_ipv4(void *arg)
ec3 = entry_connection_new(CONN_TYPE_AP, AF_INET);
get_options_mutable()->AutomapHostsOnResolve = 1;
- smartlist_add(get_options_mutable()->AutomapHostsSuffixes, tor_strdup("."));
+ smartlist_add_strdup(get_options_mutable()->AutomapHostsSuffixes, ".");
parse_virtual_addr_network("127.202.0.0/16", AF_INET, 0, &msg);
/* Automap this on resolve. */
@@ -173,7 +173,7 @@ test_entryconn_rewrite_automap_ipv6(void *arg)
ec3 = entry_connection_new(CONN_TYPE_AP, AF_INET6);
get_options_mutable()->AutomapHostsOnResolve = 1;
- smartlist_add(get_options_mutable()->AutomapHostsSuffixes, tor_strdup("."));
+ smartlist_add_strdup(get_options_mutable()->AutomapHostsSuffixes, ".");
parse_virtual_addr_network("FE80::/32", AF_INET6, 0, &msg);
/* Automap this on resolve. */
@@ -489,8 +489,8 @@ test_entryconn_rewrite_automap_exit(void *arg)
get_options_mutable()->AutomapHostsOnResolve = 1;
get_options_mutable()->AllowDotExit = 1;
- smartlist_add(get_options_mutable()->AutomapHostsSuffixes,
- tor_strdup(".EXIT"));
+ smartlist_add_strdup(get_options_mutable()->AutomapHostsSuffixes,
+ ".EXIT");
parse_virtual_addr_network("127.1.0.0/16", AF_INET, 0, &msg);
/* Automap this on resolve. */
@@ -574,8 +574,8 @@ test_entryconn_rewrite_mapaddress_automap_onion(void *arg)
get_options_mutable()->AutomapHostsOnResolve = 1;
get_options_mutable()->AllowDotExit = 1;
- smartlist_add(get_options_mutable()->AutomapHostsSuffixes,
- tor_strdup(".onion"));
+ smartlist_add_strdup(get_options_mutable()->AutomapHostsSuffixes,
+ ".onion");
parse_virtual_addr_network("192.168.0.0/16", AF_INET, 0, &msg);
config_line_append(&get_options_mutable()->AddressMap,
"MapAddress", "foo.onion abcdefghijklmnop.onion");
@@ -709,8 +709,8 @@ test_entryconn_rewrite_mapaddress_automap_onion2(void *arg)
{
char *msg = NULL;
get_options_mutable()->AutomapHostsOnResolve = 1;
- smartlist_add(get_options_mutable()->AutomapHostsSuffixes,
- tor_strdup(".onion"));
+ smartlist_add_strdup(get_options_mutable()->AutomapHostsSuffixes,
+ ".onion");
parse_virtual_addr_network("192.168.0.0/16", AF_INET, 0, &msg);
config_line_append(&get_options_mutable()->AddressMap,
"MapAddress", "irc.example.com abcdefghijklmnop.onion");
@@ -736,8 +736,8 @@ test_entryconn_rewrite_mapaddress_automap_onion4(void *arg)
{
char *msg = NULL;
get_options_mutable()->AutomapHostsOnResolve = 1;
- smartlist_add(get_options_mutable()->AutomapHostsSuffixes,
- tor_strdup(".onion"));
+ smartlist_add_strdup(get_options_mutable()->AutomapHostsSuffixes,
+ ".onion");
parse_virtual_addr_network("192.168.0.0/16", AF_INET, 0, &msg);
test_entryconn_rewrite_mapaddress_automap_onion_common(arg, 0, 1);
diff --git a/src/test/test_entrynodes.c b/src/test/test_entrynodes.c
index b1c3accfab..8e4f4061c6 100644
--- a/src/test/test_entrynodes.c
+++ b/src/test/test_entrynodes.c
@@ -254,7 +254,9 @@ populate_live_entry_guards_test_helper(int num_needed)
{
smartlist_t *our_nodelist = NULL;
smartlist_t *live_entry_guards = smartlist_new();
- const smartlist_t *all_entry_guards = get_entry_guards();
+ guard_selection_t *gs = get_guard_selection_info();
+ const smartlist_t *all_entry_guards =
+ get_entry_guards_for_guard_selection(gs);
or_options_t *options = get_options_mutable();
int retval;
@@ -271,7 +273,7 @@ populate_live_entry_guards_test_helper(int num_needed)
SMARTLIST_FOREACH_BEGIN(our_nodelist, const node_t *, node) {
const node_t *node_tmp;
- node_tmp = add_an_entry_guard(node, 0, 1, 0, 0);
+ node_tmp = add_an_entry_guard(gs, node, 0, 1, 0, 0);
tt_assert(node_tmp);
} SMARTLIST_FOREACH_END(node);
@@ -582,7 +584,9 @@ static void
test_entry_guards_set_from_config(void *arg)
{
or_options_t *options = get_options_mutable();
- const smartlist_t *all_entry_guards = get_entry_guards();
+ guard_selection_t *gs = get_guard_selection_info();
+ const smartlist_t *all_entry_guards =
+ get_entry_guards_for_guard_selection(gs);
const char *entrynodes_str = "test003r";
const node_t *chosen_entry = NULL;
int retval;
@@ -597,7 +601,7 @@ test_entry_guards_set_from_config(void *arg)
tt_int_op(retval, OP_GE, 0);
/* Read nodes from EntryNodes */
- entry_guards_set_from_config(options);
+ entry_guards_set_from_config(gs, options);
/* Test that only one guard was added. */
tt_int_op(smartlist_len(all_entry_guards), OP_EQ, 1);
@@ -689,7 +693,9 @@ static void
test_entry_is_live(void *arg)
{
smartlist_t *our_nodelist = NULL;
- const smartlist_t *all_entry_guards = get_entry_guards();
+ guard_selection_t *gs = get_guard_selection_info();
+ const smartlist_t *all_entry_guards =
+ get_entry_guards_for_guard_selection(gs);
const node_t *test_node = NULL;
const entry_guard_t *test_entry = NULL;
const char *msg;
@@ -706,7 +712,7 @@ test_entry_is_live(void *arg)
SMARTLIST_FOREACH_BEGIN(our_nodelist, const node_t *, node) {
const node_t *node_tmp;
- node_tmp = add_an_entry_guard(node, 0, 1, 0, 0);
+ node_tmp = add_an_entry_guard(gs, node, 0, 1, 0, 0);
tt_assert(node_tmp);
tt_int_op(node->is_stable, OP_EQ, 0);
diff --git a/src/test/test_policy.c b/src/test/test_policy.c
index 0d4a3b104f..b89de01b7b 100644
--- a/src/test/test_policy.c
+++ b/src/test/test_policy.c
@@ -525,10 +525,10 @@ test_policies_general(void *arg)
{
char *policy_strng = NULL;
smartlist_t *chunks = smartlist_new();
- smartlist_add(chunks, tor_strdup("accept "));
+ smartlist_add_strdup(chunks, "accept ");
for (i=1; i<10000; ++i)
smartlist_add_asprintf(chunks, "%d,", i);
- smartlist_add(chunks, tor_strdup("20000"));
+ smartlist_add_strdup(chunks, "20000");
policy_strng = smartlist_join_strings(chunks, "", 0, NULL);
SMARTLIST_FOREACH(chunks, char *, ch, tor_free(ch));
smartlist_free(chunks);
@@ -542,9 +542,9 @@ test_policies_general(void *arg)
for (i=1; i<2000; i+=2) {
char buf[POLICY_BUF_LEN];
tor_snprintf(buf, sizeof(buf), "reject *:%d", i);
- smartlist_add(sm, tor_strdup(buf));
+ smartlist_add_strdup(sm, buf);
}
- smartlist_add(sm, tor_strdup("accept *:*"));
+ smartlist_add_strdup(sm, "accept *:*");
policy_str = smartlist_join_strings(sm, ",", 0, NULL);
test_policy_summary_helper( policy_str,
"accept 2,4,6,8,10,12,14,16,18,20,22,24,26,28,30,32,34,36,38,40,42,44,"
diff --git a/src/test/test_pt.c b/src/test/test_pt.c
index e5cdc5f3cd..f93019f1c4 100644
--- a/src/test/test_pt.c
+++ b/src/test/test_pt.c
@@ -155,9 +155,9 @@ test_pt_get_transport_options(void *arg)
opt_str = get_transport_options_for_server_proxy(mp);
tt_ptr_op(opt_str, OP_EQ, NULL);
- smartlist_add(mp->transports_to_launch, tor_strdup("gruyere"));
- smartlist_add(mp->transports_to_launch, tor_strdup("roquefort"));
- smartlist_add(mp->transports_to_launch, tor_strdup("stnectaire"));
+ smartlist_add_strdup(mp->transports_to_launch, "gruyere");
+ smartlist_add_strdup(mp->transports_to_launch, "roquefort");
+ smartlist_add_strdup(mp->transports_to_launch, "stnectaire");
tt_assert(options);
@@ -305,7 +305,7 @@ tor_get_lines_from_handle_replacement(STDIN_HANDLE *handle,
smartlist_add_asprintf(retval_sl, "SMETHOD mock%d 127.0.0.1:555%d",
times_called, times_called);
} else {
- smartlist_add(retval_sl, tor_strdup("SMETHODS DONE"));
+ smartlist_add_strdup(retval_sl, "SMETHODS DONE");
}
return retval_sl;
diff --git a/src/test/test_routerlist.c b/src/test/test_routerlist.c
index 088bd257c3..af5c121ce2 100644
--- a/src/test/test_routerlist.c
+++ b/src/test/test_routerlist.c
@@ -15,6 +15,7 @@
#include "container.h"
#include "directory.h"
#include "dirvote.h"
+#include "entrynodes.h"
#include "microdesc.h"
#include "networkstatus.h"
#include "nodelist.h"
@@ -203,6 +204,53 @@ mock_usable_consensus_flavor(void)
return mock_usable_consensus_flavor_value;
}
+static smartlist_t *mock_is_guard_list = NULL;
+
+static int
+mock_is_node_used_as_guard(const node_t *n)
+{
+ if (mock_is_guard_list) {
+ SMARTLIST_FOREACH_BEGIN(mock_is_guard_list, node_t *, e) {
+ if (e == n) return 1;
+ } SMARTLIST_FOREACH_END(e);
+ }
+
+ return 0;
+}
+
+static void
+mark_node_used_as_guard(node_t *n)
+{
+ if (!n) return;
+
+ if (!mock_is_guard_list) {
+ mock_is_guard_list = smartlist_new();
+ }
+
+ if (!mock_is_node_used_as_guard(n)) {
+ smartlist_add(mock_is_guard_list, n);
+ }
+}
+
+static void
+mark_node_unused_as_guard(node_t *n)
+{
+ if (!n) return;
+
+ if (!mock_is_guard_list) return;
+
+ smartlist_remove(mock_is_guard_list, n);
+}
+
+static void
+clear_mock_guard_list(void)
+{
+ if (mock_is_guard_list) {
+ smartlist_free(mock_is_guard_list);
+ mock_is_guard_list = NULL;
+ }
+}
+
static void
test_router_pick_directory_server_impl(void *arg)
{
@@ -223,6 +271,7 @@ test_router_pick_directory_server_impl(void *arg)
(void)arg;
MOCK(usable_consensus_flavor, mock_usable_consensus_flavor);
+ MOCK(is_node_used_as_guard, mock_is_node_used_as_guard);
/* With no consensus, we must be bootstrapping, regardless of time or flavor
*/
@@ -336,28 +385,28 @@ test_router_pick_directory_server_impl(void *arg)
node_router3->is_valid = 1;
flags |= PDS_FOR_GUARD;
- node_router1->using_as_guard = 1;
- node_router2->using_as_guard = 1;
- node_router3->using_as_guard = 1;
+ mark_node_used_as_guard(node_router1);
+ mark_node_used_as_guard(node_router2);
+ mark_node_used_as_guard(node_router3);
rs = router_pick_directory_server_impl(V3_DIRINFO, flags, NULL);
tt_assert(rs == NULL);
- node_router1->using_as_guard = 0;
+ mark_node_unused_as_guard(node_router1);
rs = router_pick_directory_server_impl(V3_DIRINFO, flags, NULL);
tt_assert(rs != NULL);
tt_assert(tor_memeq(rs->identity_digest, router1_id, DIGEST_LEN));
rs = NULL;
- node_router2->using_as_guard = 0;
- node_router3->using_as_guard = 0;
+ mark_node_unused_as_guard(node_router2);
+ mark_node_unused_as_guard(node_router3);
/* One not valid, one guard. This should leave one remaining */
node_router1->is_valid = 0;
- node_router2->using_as_guard = 1;
+ mark_node_used_as_guard(node_router2);
rs = router_pick_directory_server_impl(V3_DIRINFO, flags, NULL);
tt_assert(rs != NULL);
tt_assert(tor_memeq(rs->identity_digest, router3_id, DIGEST_LEN));
rs = NULL;
node_router1->is_valid = 1;
- node_router2->using_as_guard = 0;
+ mark_node_unused_as_guard(node_router2);
/* Manipulate overloaded */
@@ -420,6 +469,9 @@ test_router_pick_directory_server_impl(void *arg)
done:
UNMOCK(usable_consensus_flavor);
+ UNMOCK(is_node_used_as_guard);
+ clear_mock_guard_list();
+
if (router1_id)
tor_free(router1_id);
if (router2_id)
diff --git a/src/test/test_routerset.c b/src/test/test_routerset.c
index 1b526d430b..7efd042ed5 100644
--- a/src/test/test_routerset.c
+++ b/src/test/test_routerset.c
@@ -623,7 +623,7 @@ NS(test_main)(void *arg)
(void)arg;
tgt = routerset_new();
- smartlist_add(src->list, tor_strdup("{xx}"));
+ smartlist_add_strdup(src->list, "{xx}");
routerset_union(tgt, src);
tt_int_op(smartlist_len(tgt->list), OP_NE, 0);
@@ -745,7 +745,7 @@ NS(test_main)(void *arg)
tt_int_op(is_empty, OP_NE, 0);
set = routerset_new();
- smartlist_add(set->list, tor_strdup("{xx}"));
+ smartlist_add_strdup(set->list, "{xx}");
is_empty = routerset_is_empty(set);
routerset_free(set);
set = NULL;
@@ -1616,7 +1616,7 @@ NS(test_main)(void *arg)
NS_MOCK(node_get_by_nickname);
NS(mock_nickname) = "foo";
- smartlist_add(set->list, tor_strdup(NS(mock_nickname)));
+ smartlist_add_strdup(set->list, NS(mock_nickname));
routerset_get_all_nodes(out, set, NULL, 0);
out_len = smartlist_len(out);
@@ -1667,7 +1667,7 @@ NS(test_main)(void *arg)
NS(mock_node).is_running = 0;
NS(mock_nickname) = "foo";
- smartlist_add(set->list, tor_strdup(NS(mock_nickname)));
+ smartlist_add_strdup(set->list, NS(mock_nickname));
routerset_get_all_nodes(out, set, NULL, 1);
out_len = smartlist_len(out);
@@ -1766,7 +1766,7 @@ NS(test_main)(void *arg)
NS_MOCK(nodelist_get_list);
- smartlist_add(set->country_names, tor_strdup("{xx}"));
+ smartlist_add_strdup(set->country_names, "{xx}");
NS(mock_smartlist) = smartlist_new();
routerset_get_all_nodes(out, set, NULL, 1);
@@ -1813,7 +1813,7 @@ NS(test_main)(void *arg)
NS_MOCK(nodelist_get_list);
- smartlist_add(set->country_names, tor_strdup("{xx}"));
+ smartlist_add_strdup(set->country_names, "{xx}");
NS(mock_smartlist) = smartlist_new();
NS(mock_node).is_running = 0;
smartlist_add(NS(mock_smartlist), (void *)&NS(mock_node));
@@ -1985,7 +1985,7 @@ NS(test_main)(void *arg)
int r;
(void)arg;
- smartlist_add(b->list, tor_strdup("{xx}"));
+ smartlist_add_strdup(b->list, "{xx}");
r = routerset_equal(a, b);
routerset_free(a);
routerset_free(b);
@@ -2010,9 +2010,9 @@ NS(test_main)(void *arg)
int r;
(void)arg;
- smartlist_add(a->list, tor_strdup("{aa}"));
- smartlist_add(b->list, tor_strdup("{b1}"));
- smartlist_add(b->list, tor_strdup("{b2}"));
+ smartlist_add_strdup(a->list, "{aa}");
+ smartlist_add_strdup(b->list, "{b1}");
+ smartlist_add_strdup(b->list, "{b2}");
r = routerset_equal(a, b);
routerset_free(a);
routerset_free(b);
@@ -2037,8 +2037,8 @@ NS(test_main)(void *arg)
int r;
(void)arg;
- smartlist_add(a->list, tor_strdup("foo"));
- smartlist_add(b->list, tor_strdup("bar"));
+ smartlist_add_strdup(a->list, "foo");
+ smartlist_add_strdup(b->list, "bar");
r = routerset_equal(a, b);
routerset_free(a);
routerset_free(b);
@@ -2063,8 +2063,8 @@ NS(test_main)(void *arg)
int r;
(void)arg;
- smartlist_add(a->list, tor_strdup("foo"));
- smartlist_add(b->list, tor_strdup("foo"));
+ smartlist_add_strdup(a->list, "foo");
+ smartlist_add_strdup(b->list, "foo");
r = routerset_equal(a, b);
routerset_free(a);
routerset_free(b);
diff --git a/src/test/test_shared_random.c b/src/test/test_shared_random.c
index 056f199b94..d511f163e3 100644
--- a/src/test/test_shared_random.c
+++ b/src/test/test_shared_random.c
@@ -348,12 +348,12 @@ test_sr_commit(void *arg)
/* We'll build a list of values from our commit that our parsing function
* takes from a vote line and see if we can parse it correctly. */
{
- smartlist_add(args, tor_strdup("1"));
- smartlist_add(args,
- tor_strdup(crypto_digest_algorithm_get_name(our_commit->alg)));
- smartlist_add(args, tor_strdup(sr_commit_get_rsa_fpr(our_commit)));
- smartlist_add(args, tor_strdup(our_commit->encoded_commit));
- smartlist_add(args, tor_strdup(our_commit->encoded_reveal));
+ smartlist_add_strdup(args, "1");
+ smartlist_add_strdup(args,
+ crypto_digest_algorithm_get_name(our_commit->alg));
+ smartlist_add_strdup(args, sr_commit_get_rsa_fpr(our_commit));
+ smartlist_add_strdup(args, our_commit->encoded_commit);
+ smartlist_add_strdup(args, our_commit->encoded_reveal);
parsed_commit = sr_parse_commit(args);
tt_assert(parsed_commit);
/* That parsed commit should be _EXACTLY_ like our original commit (we
diff --git a/src/trunnel/ed25519_cert.c b/src/trunnel/ed25519_cert.c
index 24988d510b..a492ada417 100644
--- a/src/trunnel/ed25519_cert.c
+++ b/src/trunnel/ed25519_cert.c
@@ -1,4 +1,4 @@
-/* ed25519_cert.c -- generated by Trunnel v1.4.6.
+/* ed25519_cert.c -- generated by Trunnel v1.5.
* https://gitweb.torproject.org/trunnel.git
* You probably shouldn't edit this file.
*/
@@ -97,12 +97,17 @@ ed25519_cert_extension_getlen_un_signing_key(const ed25519_cert_extension_t *inp
}
uint8_t
-ed25519_cert_extension_get_un_signing_key(const ed25519_cert_extension_t *inp, size_t idx)
+ed25519_cert_extension_get_un_signing_key(ed25519_cert_extension_t *inp, size_t idx)
{
trunnel_assert(idx < 32);
return inp->un_signing_key[idx];
}
+uint8_t
+ed25519_cert_extension_getconst_un_signing_key(const ed25519_cert_extension_t *inp, size_t idx)
+{
+ return ed25519_cert_extension_get_un_signing_key((ed25519_cert_extension_t*)inp, idx);
+}
int
ed25519_cert_extension_set_un_signing_key(ed25519_cert_extension_t *inp, size_t idx, uint8_t elt)
{
@@ -116,6 +121,11 @@ ed25519_cert_extension_getarray_un_signing_key(ed25519_cert_extension_t *inp)
{
return inp->un_signing_key;
}
+const uint8_t *
+ed25519_cert_extension_getconstarray_un_signing_key(const ed25519_cert_extension_t *inp)
+{
+ return (const uint8_t *)ed25519_cert_extension_getarray_un_signing_key((ed25519_cert_extension_t*)inp);
+}
size_t
ed25519_cert_extension_getlen_un_unparsed(const ed25519_cert_extension_t *inp)
{
@@ -128,6 +138,11 @@ ed25519_cert_extension_get_un_unparsed(ed25519_cert_extension_t *inp, size_t idx
return TRUNNEL_DYNARRAY_GET(&inp->un_unparsed, idx);
}
+uint8_t
+ed25519_cert_extension_getconst_un_unparsed(const ed25519_cert_extension_t *inp, size_t idx)
+{
+ return ed25519_cert_extension_get_un_unparsed((ed25519_cert_extension_t*)inp, idx);
+}
int
ed25519_cert_extension_set_un_unparsed(ed25519_cert_extension_t *inp, size_t idx, uint8_t elt)
{
@@ -149,6 +164,11 @@ ed25519_cert_extension_getarray_un_unparsed(ed25519_cert_extension_t *inp)
{
return inp->un_unparsed.elts_;
}
+const uint8_t *
+ed25519_cert_extension_getconstarray_un_unparsed(const ed25519_cert_extension_t *inp)
+{
+ return (const uint8_t *)ed25519_cert_extension_getarray_un_unparsed((ed25519_cert_extension_t*)inp);
+}
int
ed25519_cert_extension_setlen_un_unparsed(ed25519_cert_extension_t *inp, size_t newlen)
{
@@ -502,12 +522,17 @@ ed25519_cert_getlen_certified_key(const ed25519_cert_t *inp)
}
uint8_t
-ed25519_cert_get_certified_key(const ed25519_cert_t *inp, size_t idx)
+ed25519_cert_get_certified_key(ed25519_cert_t *inp, size_t idx)
{
trunnel_assert(idx < 32);
return inp->certified_key[idx];
}
+uint8_t
+ed25519_cert_getconst_certified_key(const ed25519_cert_t *inp, size_t idx)
+{
+ return ed25519_cert_get_certified_key((ed25519_cert_t*)inp, idx);
+}
int
ed25519_cert_set_certified_key(ed25519_cert_t *inp, size_t idx, uint8_t elt)
{
@@ -521,6 +546,11 @@ ed25519_cert_getarray_certified_key(ed25519_cert_t *inp)
{
return inp->certified_key;
}
+const uint8_t *
+ed25519_cert_getconstarray_certified_key(const ed25519_cert_t *inp)
+{
+ return (const uint8_t *)ed25519_cert_getarray_certified_key((ed25519_cert_t*)inp);
+}
uint8_t
ed25519_cert_get_n_extensions(ed25519_cert_t *inp)
{
@@ -544,6 +574,11 @@ ed25519_cert_get_ext(ed25519_cert_t *inp, size_t idx)
return TRUNNEL_DYNARRAY_GET(&inp->ext, idx);
}
+ const struct ed25519_cert_extension_st *
+ed25519_cert_getconst_ext(const ed25519_cert_t *inp, size_t idx)
+{
+ return ed25519_cert_get_ext((ed25519_cert_t*)inp, idx);
+}
int
ed25519_cert_set_ext(ed25519_cert_t *inp, size_t idx, struct ed25519_cert_extension_st * elt)
{
@@ -577,6 +612,11 @@ ed25519_cert_getarray_ext(ed25519_cert_t *inp)
{
return inp->ext.elts_;
}
+const struct ed25519_cert_extension_st * const *
+ed25519_cert_getconstarray_ext(const ed25519_cert_t *inp)
+{
+ return (const struct ed25519_cert_extension_st * const *)ed25519_cert_getarray_ext((ed25519_cert_t*)inp);
+}
int
ed25519_cert_setlen_ext(ed25519_cert_t *inp, size_t newlen)
{
@@ -604,12 +644,17 @@ ed25519_cert_getlen_signature(const ed25519_cert_t *inp)
}
uint8_t
-ed25519_cert_get_signature(const ed25519_cert_t *inp, size_t idx)
+ed25519_cert_get_signature(ed25519_cert_t *inp, size_t idx)
{
trunnel_assert(idx < 64);
return inp->signature[idx];
}
+uint8_t
+ed25519_cert_getconst_signature(const ed25519_cert_t *inp, size_t idx)
+{
+ return ed25519_cert_get_signature((ed25519_cert_t*)inp, idx);
+}
int
ed25519_cert_set_signature(ed25519_cert_t *inp, size_t idx, uint8_t elt)
{
@@ -623,6 +668,11 @@ ed25519_cert_getarray_signature(ed25519_cert_t *inp)
{
return inp->signature;
}
+const uint8_t *
+ed25519_cert_getconstarray_signature(const ed25519_cert_t *inp)
+{
+ return (const uint8_t *)ed25519_cert_getarray_signature((ed25519_cert_t*)inp);
+}
const char *
ed25519_cert_check(const ed25519_cert_t *obj)
{
diff --git a/src/trunnel/ed25519_cert.h b/src/trunnel/ed25519_cert.h
index 28f6feef31..9804d843d4 100644
--- a/src/trunnel/ed25519_cert.h
+++ b/src/trunnel/ed25519_cert.h
@@ -1,4 +1,4 @@
-/* ed25519_cert.h -- generated by by Trunnel v1.4.6.
+/* ed25519_cert.h -- generated by by Trunnel v1.5.
* https://gitweb.torproject.org/trunnel.git
* You probably shouldn't edit this file.
*/
@@ -105,7 +105,11 @@ size_t ed25519_cert_extension_getlen_un_signing_key(const ed25519_cert_extension
/** Return the element at position 'idx' of the fixed array field
* un_signing_key of the ed25519_cert_extension_t in 'inp'.
*/
-uint8_t ed25519_cert_extension_get_un_signing_key(const ed25519_cert_extension_t *inp, size_t idx);
+uint8_t ed25519_cert_extension_get_un_signing_key(ed25519_cert_extension_t *inp, size_t idx);
+/** As ed25519_cert_extension_get_un_signing_key, but take and return
+ * a const pointer
+ */
+uint8_t ed25519_cert_extension_getconst_un_signing_key(const ed25519_cert_extension_t *inp, size_t idx);
/** Change the element at position 'idx' of the fixed array field
* un_signing_key of the ed25519_cert_extension_t in 'inp', so that it
* will hold the value 'elt'.
@@ -115,6 +119,10 @@ int ed25519_cert_extension_set_un_signing_key(ed25519_cert_extension_t *inp, siz
* 'inp'.
*/
uint8_t * ed25519_cert_extension_getarray_un_signing_key(ed25519_cert_extension_t *inp);
+/** As ed25519_cert_extension_get_un_signing_key, but take and return
+ * a const pointer
+ */
+const uint8_t * ed25519_cert_extension_getconstarray_un_signing_key(const ed25519_cert_extension_t *inp);
/** Return the length of the dynamic array holding the un_unparsed
* field of the ed25519_cert_extension_t in 'inp'.
*/
@@ -123,6 +131,10 @@ size_t ed25519_cert_extension_getlen_un_unparsed(const ed25519_cert_extension_t
* un_unparsed of the ed25519_cert_extension_t in 'inp'.
*/
uint8_t ed25519_cert_extension_get_un_unparsed(ed25519_cert_extension_t *inp, size_t idx);
+/** As ed25519_cert_extension_get_un_unparsed, but take and return a
+ * const pointer
+ */
+uint8_t ed25519_cert_extension_getconst_un_unparsed(const ed25519_cert_extension_t *inp, size_t idx);
/** Change the element at position 'idx' of the dynamic array field
* un_unparsed of the ed25519_cert_extension_t in 'inp', so that it
* will hold the value 'elt'.
@@ -136,6 +148,10 @@ int ed25519_cert_extension_add_un_unparsed(ed25519_cert_extension_t *inp, uint8_
* 'inp'.
*/
uint8_t * ed25519_cert_extension_getarray_un_unparsed(ed25519_cert_extension_t *inp);
+/** As ed25519_cert_extension_get_un_unparsed, but take and return a
+ * const pointer
+ */
+const uint8_t * ed25519_cert_extension_getconstarray_un_unparsed(const ed25519_cert_extension_t *inp);
/** Change the length of the variable-length array field un_unparsed
* of 'inp' to 'newlen'.Fill extra elements with 0. Return 0 on
* success; return -1 and set the error code on 'inp' on failure.
@@ -219,7 +235,11 @@ size_t ed25519_cert_getlen_certified_key(const ed25519_cert_t *inp);
/** Return the element at position 'idx' of the fixed array field
* certified_key of the ed25519_cert_t in 'inp'.
*/
-uint8_t ed25519_cert_get_certified_key(const ed25519_cert_t *inp, size_t idx);
+uint8_t ed25519_cert_get_certified_key(ed25519_cert_t *inp, size_t idx);
+/** As ed25519_cert_get_certified_key, but take and return a const
+ * pointer
+ */
+uint8_t ed25519_cert_getconst_certified_key(const ed25519_cert_t *inp, size_t idx);
/** Change the element at position 'idx' of the fixed array field
* certified_key of the ed25519_cert_t in 'inp', so that it will hold
* the value 'elt'.
@@ -229,6 +249,10 @@ int ed25519_cert_set_certified_key(ed25519_cert_t *inp, size_t idx, uint8_t elt)
* 'inp'.
*/
uint8_t * ed25519_cert_getarray_certified_key(ed25519_cert_t *inp);
+/** As ed25519_cert_get_certified_key, but take and return a const
+ * pointer
+ */
+const uint8_t * ed25519_cert_getconstarray_certified_key(const ed25519_cert_t *inp);
/** Return the value of the n_extensions field of the ed25519_cert_t
* in 'inp'
*/
@@ -246,6 +270,9 @@ size_t ed25519_cert_getlen_ext(const ed25519_cert_t *inp);
* ext of the ed25519_cert_t in 'inp'.
*/
struct ed25519_cert_extension_st * ed25519_cert_get_ext(ed25519_cert_t *inp, size_t idx);
+/** As ed25519_cert_get_ext, but take and return a const pointer
+ */
+ const struct ed25519_cert_extension_st * ed25519_cert_getconst_ext(const ed25519_cert_t *inp, size_t idx);
/** Change the element at position 'idx' of the dynamic array field
* ext of the ed25519_cert_t in 'inp', so that it will hold the value
* 'elt'. Free the previous value, if any.
@@ -261,6 +288,9 @@ int ed25519_cert_add_ext(ed25519_cert_t *inp, struct ed25519_cert_extension_st *
/** Return a pointer to the variable-length array field ext of 'inp'.
*/
struct ed25519_cert_extension_st * * ed25519_cert_getarray_ext(ed25519_cert_t *inp);
+/** As ed25519_cert_get_ext, but take and return a const pointer
+ */
+const struct ed25519_cert_extension_st * const * ed25519_cert_getconstarray_ext(const ed25519_cert_t *inp);
/** Change the length of the variable-length array field ext of 'inp'
* to 'newlen'.Fill extra elements with NULL; free removed elements.
* Return 0 on success; return -1 and set the error code on 'inp' on
@@ -274,7 +304,10 @@ size_t ed25519_cert_getlen_signature(const ed25519_cert_t *inp);
/** Return the element at position 'idx' of the fixed array field
* signature of the ed25519_cert_t in 'inp'.
*/
-uint8_t ed25519_cert_get_signature(const ed25519_cert_t *inp, size_t idx);
+uint8_t ed25519_cert_get_signature(ed25519_cert_t *inp, size_t idx);
+/** As ed25519_cert_get_signature, but take and return a const pointer
+ */
+uint8_t ed25519_cert_getconst_signature(const ed25519_cert_t *inp, size_t idx);
/** Change the element at position 'idx' of the fixed array field
* signature of the ed25519_cert_t in 'inp', so that it will hold the
* value 'elt'.
@@ -283,6 +316,9 @@ int ed25519_cert_set_signature(ed25519_cert_t *inp, size_t idx, uint8_t elt);
/** Return a pointer to the 64-element array field signature of 'inp'.
*/
uint8_t * ed25519_cert_getarray_signature(ed25519_cert_t *inp);
+/** As ed25519_cert_get_signature, but take and return a const pointer
+ */
+const uint8_t * ed25519_cert_getconstarray_signature(const ed25519_cert_t *inp);
#endif
diff --git a/src/trunnel/link_handshake.c b/src/trunnel/link_handshake.c
index c2717f36bf..a4b1fe034a 100644
--- a/src/trunnel/link_handshake.c
+++ b/src/trunnel/link_handshake.c
@@ -1,4 +1,4 @@
-/* link_handshake.c -- generated by Trunnel v1.4.6.
+/* link_handshake.c -- generated by Trunnel v1.5.
* https://gitweb.torproject.org/trunnel.git
* You probably shouldn't edit this file.
*/
@@ -64,12 +64,17 @@ auth_challenge_cell_getlen_challenge(const auth_challenge_cell_t *inp)
}
uint8_t
-auth_challenge_cell_get_challenge(const auth_challenge_cell_t *inp, size_t idx)
+auth_challenge_cell_get_challenge(auth_challenge_cell_t *inp, size_t idx)
{
trunnel_assert(idx < 32);
return inp->challenge[idx];
}
+uint8_t
+auth_challenge_cell_getconst_challenge(const auth_challenge_cell_t *inp, size_t idx)
+{
+ return auth_challenge_cell_get_challenge((auth_challenge_cell_t*)inp, idx);
+}
int
auth_challenge_cell_set_challenge(auth_challenge_cell_t *inp, size_t idx, uint8_t elt)
{
@@ -83,6 +88,11 @@ auth_challenge_cell_getarray_challenge(auth_challenge_cell_t *inp)
{
return inp->challenge;
}
+const uint8_t *
+auth_challenge_cell_getconstarray_challenge(const auth_challenge_cell_t *inp)
+{
+ return (const uint8_t *)auth_challenge_cell_getarray_challenge((auth_challenge_cell_t*)inp);
+}
uint16_t
auth_challenge_cell_get_n_methods(auth_challenge_cell_t *inp)
{
@@ -106,6 +116,11 @@ auth_challenge_cell_get_methods(auth_challenge_cell_t *inp, size_t idx)
return TRUNNEL_DYNARRAY_GET(&inp->methods, idx);
}
+uint16_t
+auth_challenge_cell_getconst_methods(const auth_challenge_cell_t *inp, size_t idx)
+{
+ return auth_challenge_cell_get_methods((auth_challenge_cell_t*)inp, idx);
+}
int
auth_challenge_cell_set_methods(auth_challenge_cell_t *inp, size_t idx, uint16_t elt)
{
@@ -131,6 +146,11 @@ auth_challenge_cell_getarray_methods(auth_challenge_cell_t *inp)
{
return inp->methods.elts_;
}
+const uint16_t *
+auth_challenge_cell_getconstarray_methods(const auth_challenge_cell_t *inp)
+{
+ return (const uint16_t *)auth_challenge_cell_getarray_methods((auth_challenge_cell_t*)inp);
+}
int
auth_challenge_cell_setlen_methods(auth_challenge_cell_t *inp, size_t newlen)
{
@@ -415,6 +435,11 @@ certs_cell_cert_get_body(certs_cell_cert_t *inp, size_t idx)
return TRUNNEL_DYNARRAY_GET(&inp->body, idx);
}
+uint8_t
+certs_cell_cert_getconst_body(const certs_cell_cert_t *inp, size_t idx)
+{
+ return certs_cell_cert_get_body((certs_cell_cert_t*)inp, idx);
+}
int
certs_cell_cert_set_body(certs_cell_cert_t *inp, size_t idx, uint8_t elt)
{
@@ -440,6 +465,11 @@ certs_cell_cert_getarray_body(certs_cell_cert_t *inp)
{
return inp->body.elts_;
}
+const uint8_t *
+certs_cell_cert_getconstarray_body(const certs_cell_cert_t *inp)
+{
+ return (const uint8_t *)certs_cell_cert_getarray_body((certs_cell_cert_t*)inp);
+}
int
certs_cell_cert_setlen_body(certs_cell_cert_t *inp, size_t newlen)
{
@@ -652,12 +682,17 @@ rsa_ed_crosscert_getlen_ed_key(const rsa_ed_crosscert_t *inp)
}
uint8_t
-rsa_ed_crosscert_get_ed_key(const rsa_ed_crosscert_t *inp, size_t idx)
+rsa_ed_crosscert_get_ed_key(rsa_ed_crosscert_t *inp, size_t idx)
{
trunnel_assert(idx < 32);
return inp->ed_key[idx];
}
+uint8_t
+rsa_ed_crosscert_getconst_ed_key(const rsa_ed_crosscert_t *inp, size_t idx)
+{
+ return rsa_ed_crosscert_get_ed_key((rsa_ed_crosscert_t*)inp, idx);
+}
int
rsa_ed_crosscert_set_ed_key(rsa_ed_crosscert_t *inp, size_t idx, uint8_t elt)
{
@@ -671,6 +706,11 @@ rsa_ed_crosscert_getarray_ed_key(rsa_ed_crosscert_t *inp)
{
return inp->ed_key;
}
+const uint8_t *
+rsa_ed_crosscert_getconstarray_ed_key(const rsa_ed_crosscert_t *inp)
+{
+ return (const uint8_t *)rsa_ed_crosscert_getarray_ed_key((rsa_ed_crosscert_t*)inp);
+}
uint32_t
rsa_ed_crosscert_get_expiration(rsa_ed_crosscert_t *inp)
{
@@ -710,6 +750,11 @@ rsa_ed_crosscert_get_sig(rsa_ed_crosscert_t *inp, size_t idx)
return TRUNNEL_DYNARRAY_GET(&inp->sig, idx);
}
+uint8_t
+rsa_ed_crosscert_getconst_sig(const rsa_ed_crosscert_t *inp, size_t idx)
+{
+ return rsa_ed_crosscert_get_sig((rsa_ed_crosscert_t*)inp, idx);
+}
int
rsa_ed_crosscert_set_sig(rsa_ed_crosscert_t *inp, size_t idx, uint8_t elt)
{
@@ -735,6 +780,11 @@ rsa_ed_crosscert_getarray_sig(rsa_ed_crosscert_t *inp)
{
return inp->sig.elts_;
}
+const uint8_t *
+rsa_ed_crosscert_getconstarray_sig(const rsa_ed_crosscert_t *inp)
+{
+ return (const uint8_t *)rsa_ed_crosscert_getarray_sig((rsa_ed_crosscert_t*)inp);
+}
int
rsa_ed_crosscert_setlen_sig(rsa_ed_crosscert_t *inp, size_t newlen)
{
@@ -964,12 +1014,17 @@ auth1_getlen_type(const auth1_t *inp)
}
uint8_t
-auth1_get_type(const auth1_t *inp, size_t idx)
+auth1_get_type(auth1_t *inp, size_t idx)
{
trunnel_assert(idx < 8);
return inp->type[idx];
}
+uint8_t
+auth1_getconst_type(const auth1_t *inp, size_t idx)
+{
+ return auth1_get_type((auth1_t*)inp, idx);
+}
int
auth1_set_type(auth1_t *inp, size_t idx, uint8_t elt)
{
@@ -983,6 +1038,11 @@ auth1_getarray_type(auth1_t *inp)
{
return inp->type;
}
+const uint8_t *
+auth1_getconstarray_type(const auth1_t *inp)
+{
+ return (const uint8_t *)auth1_getarray_type((auth1_t*)inp);
+}
size_t
auth1_getlen_cid(const auth1_t *inp)
{
@@ -990,12 +1050,17 @@ auth1_getlen_cid(const auth1_t *inp)
}
uint8_t
-auth1_get_cid(const auth1_t *inp, size_t idx)
+auth1_get_cid(auth1_t *inp, size_t idx)
{
trunnel_assert(idx < 32);
return inp->cid[idx];
}
+uint8_t
+auth1_getconst_cid(const auth1_t *inp, size_t idx)
+{
+ return auth1_get_cid((auth1_t*)inp, idx);
+}
int
auth1_set_cid(auth1_t *inp, size_t idx, uint8_t elt)
{
@@ -1009,6 +1074,11 @@ auth1_getarray_cid(auth1_t *inp)
{
return inp->cid;
}
+const uint8_t *
+auth1_getconstarray_cid(const auth1_t *inp)
+{
+ return (const uint8_t *)auth1_getarray_cid((auth1_t*)inp);
+}
size_t
auth1_getlen_sid(const auth1_t *inp)
{
@@ -1016,12 +1086,17 @@ auth1_getlen_sid(const auth1_t *inp)
}
uint8_t
-auth1_get_sid(const auth1_t *inp, size_t idx)
+auth1_get_sid(auth1_t *inp, size_t idx)
{
trunnel_assert(idx < 32);
return inp->sid[idx];
}
+uint8_t
+auth1_getconst_sid(const auth1_t *inp, size_t idx)
+{
+ return auth1_get_sid((auth1_t*)inp, idx);
+}
int
auth1_set_sid(auth1_t *inp, size_t idx, uint8_t elt)
{
@@ -1035,6 +1110,11 @@ auth1_getarray_sid(auth1_t *inp)
{
return inp->sid;
}
+const uint8_t *
+auth1_getconstarray_sid(const auth1_t *inp)
+{
+ return (const uint8_t *)auth1_getarray_sid((auth1_t*)inp);
+}
size_t
auth1_getlen_u1_cid_ed(const auth1_t *inp)
{
@@ -1042,12 +1122,17 @@ auth1_getlen_u1_cid_ed(const auth1_t *inp)
}
uint8_t
-auth1_get_u1_cid_ed(const auth1_t *inp, size_t idx)
+auth1_get_u1_cid_ed(auth1_t *inp, size_t idx)
{
trunnel_assert(idx < 32);
return inp->u1_cid_ed[idx];
}
+uint8_t
+auth1_getconst_u1_cid_ed(const auth1_t *inp, size_t idx)
+{
+ return auth1_get_u1_cid_ed((auth1_t*)inp, idx);
+}
int
auth1_set_u1_cid_ed(auth1_t *inp, size_t idx, uint8_t elt)
{
@@ -1061,6 +1146,11 @@ auth1_getarray_u1_cid_ed(auth1_t *inp)
{
return inp->u1_cid_ed;
}
+const uint8_t *
+auth1_getconstarray_u1_cid_ed(const auth1_t *inp)
+{
+ return (const uint8_t *)auth1_getarray_u1_cid_ed((auth1_t*)inp);
+}
size_t
auth1_getlen_u1_sid_ed(const auth1_t *inp)
{
@@ -1068,12 +1158,17 @@ auth1_getlen_u1_sid_ed(const auth1_t *inp)
}
uint8_t
-auth1_get_u1_sid_ed(const auth1_t *inp, size_t idx)
+auth1_get_u1_sid_ed(auth1_t *inp, size_t idx)
{
trunnel_assert(idx < 32);
return inp->u1_sid_ed[idx];
}
+uint8_t
+auth1_getconst_u1_sid_ed(const auth1_t *inp, size_t idx)
+{
+ return auth1_get_u1_sid_ed((auth1_t*)inp, idx);
+}
int
auth1_set_u1_sid_ed(auth1_t *inp, size_t idx, uint8_t elt)
{
@@ -1087,6 +1182,11 @@ auth1_getarray_u1_sid_ed(auth1_t *inp)
{
return inp->u1_sid_ed;
}
+const uint8_t *
+auth1_getconstarray_u1_sid_ed(const auth1_t *inp)
+{
+ return (const uint8_t *)auth1_getarray_u1_sid_ed((auth1_t*)inp);
+}
size_t
auth1_getlen_slog(const auth1_t *inp)
{
@@ -1094,12 +1194,17 @@ auth1_getlen_slog(const auth1_t *inp)
}
uint8_t
-auth1_get_slog(const auth1_t *inp, size_t idx)
+auth1_get_slog(auth1_t *inp, size_t idx)
{
trunnel_assert(idx < 32);
return inp->slog[idx];
}
+uint8_t
+auth1_getconst_slog(const auth1_t *inp, size_t idx)
+{
+ return auth1_get_slog((auth1_t*)inp, idx);
+}
int
auth1_set_slog(auth1_t *inp, size_t idx, uint8_t elt)
{
@@ -1113,6 +1218,11 @@ auth1_getarray_slog(auth1_t *inp)
{
return inp->slog;
}
+const uint8_t *
+auth1_getconstarray_slog(const auth1_t *inp)
+{
+ return (const uint8_t *)auth1_getarray_slog((auth1_t*)inp);
+}
size_t
auth1_getlen_clog(const auth1_t *inp)
{
@@ -1120,12 +1230,17 @@ auth1_getlen_clog(const auth1_t *inp)
}
uint8_t
-auth1_get_clog(const auth1_t *inp, size_t idx)
+auth1_get_clog(auth1_t *inp, size_t idx)
{
trunnel_assert(idx < 32);
return inp->clog[idx];
}
+uint8_t
+auth1_getconst_clog(const auth1_t *inp, size_t idx)
+{
+ return auth1_get_clog((auth1_t*)inp, idx);
+}
int
auth1_set_clog(auth1_t *inp, size_t idx, uint8_t elt)
{
@@ -1139,6 +1254,11 @@ auth1_getarray_clog(auth1_t *inp)
{
return inp->clog;
}
+const uint8_t *
+auth1_getconstarray_clog(const auth1_t *inp)
+{
+ return (const uint8_t *)auth1_getarray_clog((auth1_t*)inp);
+}
size_t
auth1_getlen_scert(const auth1_t *inp)
{
@@ -1146,12 +1266,17 @@ auth1_getlen_scert(const auth1_t *inp)
}
uint8_t
-auth1_get_scert(const auth1_t *inp, size_t idx)
+auth1_get_scert(auth1_t *inp, size_t idx)
{
trunnel_assert(idx < 32);
return inp->scert[idx];
}
+uint8_t
+auth1_getconst_scert(const auth1_t *inp, size_t idx)
+{
+ return auth1_get_scert((auth1_t*)inp, idx);
+}
int
auth1_set_scert(auth1_t *inp, size_t idx, uint8_t elt)
{
@@ -1165,6 +1290,11 @@ auth1_getarray_scert(auth1_t *inp)
{
return inp->scert;
}
+const uint8_t *
+auth1_getconstarray_scert(const auth1_t *inp)
+{
+ return (const uint8_t *)auth1_getarray_scert((auth1_t*)inp);
+}
size_t
auth1_getlen_tlssecrets(const auth1_t *inp)
{
@@ -1172,12 +1302,17 @@ auth1_getlen_tlssecrets(const auth1_t *inp)
}
uint8_t
-auth1_get_tlssecrets(const auth1_t *inp, size_t idx)
+auth1_get_tlssecrets(auth1_t *inp, size_t idx)
{
trunnel_assert(idx < 32);
return inp->tlssecrets[idx];
}
+uint8_t
+auth1_getconst_tlssecrets(const auth1_t *inp, size_t idx)
+{
+ return auth1_get_tlssecrets((auth1_t*)inp, idx);
+}
int
auth1_set_tlssecrets(auth1_t *inp, size_t idx, uint8_t elt)
{
@@ -1191,6 +1326,11 @@ auth1_getarray_tlssecrets(auth1_t *inp)
{
return inp->tlssecrets;
}
+const uint8_t *
+auth1_getconstarray_tlssecrets(const auth1_t *inp)
+{
+ return (const uint8_t *)auth1_getarray_tlssecrets((auth1_t*)inp);
+}
const uint8_t *
auth1_get_end_of_fixed_part(const auth1_t *inp)
{
@@ -1203,12 +1343,17 @@ auth1_getlen_rand(const auth1_t *inp)
}
uint8_t
-auth1_get_rand(const auth1_t *inp, size_t idx)
+auth1_get_rand(auth1_t *inp, size_t idx)
{
trunnel_assert(idx < 24);
return inp->rand[idx];
}
+uint8_t
+auth1_getconst_rand(const auth1_t *inp, size_t idx)
+{
+ return auth1_get_rand((auth1_t*)inp, idx);
+}
int
auth1_set_rand(auth1_t *inp, size_t idx, uint8_t elt)
{
@@ -1222,6 +1367,11 @@ auth1_getarray_rand(auth1_t *inp)
{
return inp->rand;
}
+const uint8_t *
+auth1_getconstarray_rand(const auth1_t *inp)
+{
+ return (const uint8_t *)auth1_getarray_rand((auth1_t*)inp);
+}
const uint8_t *
auth1_get_end_of_signed(const auth1_t *inp)
{
@@ -1239,6 +1389,11 @@ auth1_get_sig(auth1_t *inp, size_t idx)
return TRUNNEL_DYNARRAY_GET(&inp->sig, idx);
}
+uint8_t
+auth1_getconst_sig(const auth1_t *inp, size_t idx)
+{
+ return auth1_get_sig((auth1_t*)inp, idx);
+}
int
auth1_set_sig(auth1_t *inp, size_t idx, uint8_t elt)
{
@@ -1260,6 +1415,11 @@ auth1_getarray_sig(auth1_t *inp)
{
return inp->sig.elts_;
}
+const uint8_t *
+auth1_getconstarray_sig(const auth1_t *inp)
+{
+ return (const uint8_t *)auth1_getarray_sig((auth1_t*)inp);
+}
int
auth1_setlen_sig(auth1_t *inp, size_t newlen)
{
@@ -1669,6 +1829,11 @@ certs_cell_get_certs(certs_cell_t *inp, size_t idx)
return TRUNNEL_DYNARRAY_GET(&inp->certs, idx);
}
+ const struct certs_cell_cert_st *
+certs_cell_getconst_certs(const certs_cell_t *inp, size_t idx)
+{
+ return certs_cell_get_certs((certs_cell_t*)inp, idx);
+}
int
certs_cell_set_certs(certs_cell_t *inp, size_t idx, struct certs_cell_cert_st * elt)
{
@@ -1702,6 +1867,11 @@ certs_cell_getarray_certs(certs_cell_t *inp)
{
return inp->certs.elts_;
}
+const struct certs_cell_cert_st * const *
+certs_cell_getconstarray_certs(const certs_cell_t *inp)
+{
+ return (const struct certs_cell_cert_st * const *)certs_cell_getarray_certs((certs_cell_t*)inp);
+}
int
certs_cell_setlen_certs(certs_cell_t *inp, size_t newlen)
{
diff --git a/src/trunnel/link_handshake.h b/src/trunnel/link_handshake.h
index 54611b96e8..0b2ad344ab 100644
--- a/src/trunnel/link_handshake.h
+++ b/src/trunnel/link_handshake.h
@@ -1,4 +1,4 @@
-/* link_handshake.h -- generated by by Trunnel v1.4.6.
+/* link_handshake.h -- generated by by Trunnel v1.5.
* https://gitweb.torproject.org/trunnel.git
* You probably shouldn't edit this file.
*/
@@ -121,7 +121,11 @@ size_t auth_challenge_cell_getlen_challenge(const auth_challenge_cell_t *inp);
/** Return the element at position 'idx' of the fixed array field
* challenge of the auth_challenge_cell_t in 'inp'.
*/
-uint8_t auth_challenge_cell_get_challenge(const auth_challenge_cell_t *inp, size_t idx);
+uint8_t auth_challenge_cell_get_challenge(auth_challenge_cell_t *inp, size_t idx);
+/** As auth_challenge_cell_get_challenge, but take and return a const
+ * pointer
+ */
+uint8_t auth_challenge_cell_getconst_challenge(const auth_challenge_cell_t *inp, size_t idx);
/** Change the element at position 'idx' of the fixed array field
* challenge of the auth_challenge_cell_t in 'inp', so that it will
* hold the value 'elt'.
@@ -130,6 +134,10 @@ int auth_challenge_cell_set_challenge(auth_challenge_cell_t *inp, size_t idx, ui
/** Return a pointer to the 32-element array field challenge of 'inp'.
*/
uint8_t * auth_challenge_cell_getarray_challenge(auth_challenge_cell_t *inp);
+/** As auth_challenge_cell_get_challenge, but take and return a const
+ * pointer
+ */
+const uint8_t * auth_challenge_cell_getconstarray_challenge(const auth_challenge_cell_t *inp);
/** Return the value of the n_methods field of the
* auth_challenge_cell_t in 'inp'
*/
@@ -147,6 +155,10 @@ size_t auth_challenge_cell_getlen_methods(const auth_challenge_cell_t *inp);
* methods of the auth_challenge_cell_t in 'inp'.
*/
uint16_t auth_challenge_cell_get_methods(auth_challenge_cell_t *inp, size_t idx);
+/** As auth_challenge_cell_get_methods, but take and return a const
+ * pointer
+ */
+uint16_t auth_challenge_cell_getconst_methods(const auth_challenge_cell_t *inp, size_t idx);
/** Change the element at position 'idx' of the dynamic array field
* methods of the auth_challenge_cell_t in 'inp', so that it will hold
* the value 'elt'.
@@ -160,6 +172,10 @@ int auth_challenge_cell_add_methods(auth_challenge_cell_t *inp, uint16_t elt);
* 'inp'.
*/
uint16_t * auth_challenge_cell_getarray_methods(auth_challenge_cell_t *inp);
+/** As auth_challenge_cell_get_methods, but take and return a const
+ * pointer
+ */
+const uint16_t * auth_challenge_cell_getconstarray_methods(const auth_challenge_cell_t *inp);
/** Change the length of the variable-length array field methods of
* 'inp' to 'newlen'.Fill extra elements with 0. Return 0 on success;
* return -1 and set the error code on 'inp' on failure.
@@ -242,6 +258,9 @@ size_t certs_cell_cert_getlen_body(const certs_cell_cert_t *inp);
* body of the certs_cell_cert_t in 'inp'.
*/
uint8_t certs_cell_cert_get_body(certs_cell_cert_t *inp, size_t idx);
+/** As certs_cell_cert_get_body, but take and return a const pointer
+ */
+uint8_t certs_cell_cert_getconst_body(const certs_cell_cert_t *inp, size_t idx);
/** Change the element at position 'idx' of the dynamic array field
* body of the certs_cell_cert_t in 'inp', so that it will hold the
* value 'elt'.
@@ -254,6 +273,9 @@ int certs_cell_cert_add_body(certs_cell_cert_t *inp, uint8_t elt);
/** Return a pointer to the variable-length array field body of 'inp'.
*/
uint8_t * certs_cell_cert_getarray_body(certs_cell_cert_t *inp);
+/** As certs_cell_cert_get_body, but take and return a const pointer
+ */
+const uint8_t * certs_cell_cert_getconstarray_body(const certs_cell_cert_t *inp);
/** Change the length of the variable-length array field body of 'inp'
* to 'newlen'.Fill extra elements with 0. Return 0 on success; return
* -1 and set the error code on 'inp' on failure.
@@ -302,7 +324,11 @@ size_t rsa_ed_crosscert_getlen_ed_key(const rsa_ed_crosscert_t *inp);
/** Return the element at position 'idx' of the fixed array field
* ed_key of the rsa_ed_crosscert_t in 'inp'.
*/
-uint8_t rsa_ed_crosscert_get_ed_key(const rsa_ed_crosscert_t *inp, size_t idx);
+uint8_t rsa_ed_crosscert_get_ed_key(rsa_ed_crosscert_t *inp, size_t idx);
+/** As rsa_ed_crosscert_get_ed_key, but take and return a const
+ * pointer
+ */
+uint8_t rsa_ed_crosscert_getconst_ed_key(const rsa_ed_crosscert_t *inp, size_t idx);
/** Change the element at position 'idx' of the fixed array field
* ed_key of the rsa_ed_crosscert_t in 'inp', so that it will hold the
* value 'elt'.
@@ -311,6 +337,10 @@ int rsa_ed_crosscert_set_ed_key(rsa_ed_crosscert_t *inp, size_t idx, uint8_t elt
/** Return a pointer to the 32-element array field ed_key of 'inp'.
*/
uint8_t * rsa_ed_crosscert_getarray_ed_key(rsa_ed_crosscert_t *inp);
+/** As rsa_ed_crosscert_get_ed_key, but take and return a const
+ * pointer
+ */
+const uint8_t * rsa_ed_crosscert_getconstarray_ed_key(const rsa_ed_crosscert_t *inp);
/** Return the value of the expiration field of the rsa_ed_crosscert_t
* in 'inp'
*/
@@ -340,6 +370,9 @@ size_t rsa_ed_crosscert_getlen_sig(const rsa_ed_crosscert_t *inp);
* sig of the rsa_ed_crosscert_t in 'inp'.
*/
uint8_t rsa_ed_crosscert_get_sig(rsa_ed_crosscert_t *inp, size_t idx);
+/** As rsa_ed_crosscert_get_sig, but take and return a const pointer
+ */
+uint8_t rsa_ed_crosscert_getconst_sig(const rsa_ed_crosscert_t *inp, size_t idx);
/** Change the element at position 'idx' of the dynamic array field
* sig of the rsa_ed_crosscert_t in 'inp', so that it will hold the
* value 'elt'.
@@ -352,6 +385,9 @@ int rsa_ed_crosscert_add_sig(rsa_ed_crosscert_t *inp, uint8_t elt);
/** Return a pointer to the variable-length array field sig of 'inp'.
*/
uint8_t * rsa_ed_crosscert_getarray_sig(rsa_ed_crosscert_t *inp);
+/** As rsa_ed_crosscert_get_sig, but take and return a const pointer
+ */
+const uint8_t * rsa_ed_crosscert_getconstarray_sig(const rsa_ed_crosscert_t *inp);
/** Change the length of the variable-length array field sig of 'inp'
* to 'newlen'.Fill extra elements with 0. Return 0 on success; return
* -1 and set the error code on 'inp' on failure.
@@ -398,7 +434,10 @@ size_t auth1_getlen_type(const auth1_t *inp);
/** Return the element at position 'idx' of the fixed array field type
* of the auth1_t in 'inp'.
*/
-uint8_t auth1_get_type(const auth1_t *inp, size_t idx);
+uint8_t auth1_get_type(auth1_t *inp, size_t idx);
+/** As auth1_get_type, but take and return a const pointer
+ */
+uint8_t auth1_getconst_type(const auth1_t *inp, size_t idx);
/** Change the element at position 'idx' of the fixed array field type
* of the auth1_t in 'inp', so that it will hold the value 'elt'.
*/
@@ -406,6 +445,9 @@ int auth1_set_type(auth1_t *inp, size_t idx, uint8_t elt);
/** Return a pointer to the 8-element array field type of 'inp'.
*/
uint8_t * auth1_getarray_type(auth1_t *inp);
+/** As auth1_get_type, but take and return a const pointer
+ */
+const uint8_t * auth1_getconstarray_type(const auth1_t *inp);
/** Return the (constant) length of the array holding the cid field of
* the auth1_t in 'inp'.
*/
@@ -413,7 +455,10 @@ size_t auth1_getlen_cid(const auth1_t *inp);
/** Return the element at position 'idx' of the fixed array field cid
* of the auth1_t in 'inp'.
*/
-uint8_t auth1_get_cid(const auth1_t *inp, size_t idx);
+uint8_t auth1_get_cid(auth1_t *inp, size_t idx);
+/** As auth1_get_cid, but take and return a const pointer
+ */
+uint8_t auth1_getconst_cid(const auth1_t *inp, size_t idx);
/** Change the element at position 'idx' of the fixed array field cid
* of the auth1_t in 'inp', so that it will hold the value 'elt'.
*/
@@ -421,6 +466,9 @@ int auth1_set_cid(auth1_t *inp, size_t idx, uint8_t elt);
/** Return a pointer to the 32-element array field cid of 'inp'.
*/
uint8_t * auth1_getarray_cid(auth1_t *inp);
+/** As auth1_get_cid, but take and return a const pointer
+ */
+const uint8_t * auth1_getconstarray_cid(const auth1_t *inp);
/** Return the (constant) length of the array holding the sid field of
* the auth1_t in 'inp'.
*/
@@ -428,7 +476,10 @@ size_t auth1_getlen_sid(const auth1_t *inp);
/** Return the element at position 'idx' of the fixed array field sid
* of the auth1_t in 'inp'.
*/
-uint8_t auth1_get_sid(const auth1_t *inp, size_t idx);
+uint8_t auth1_get_sid(auth1_t *inp, size_t idx);
+/** As auth1_get_sid, but take and return a const pointer
+ */
+uint8_t auth1_getconst_sid(const auth1_t *inp, size_t idx);
/** Change the element at position 'idx' of the fixed array field sid
* of the auth1_t in 'inp', so that it will hold the value 'elt'.
*/
@@ -436,6 +487,9 @@ int auth1_set_sid(auth1_t *inp, size_t idx, uint8_t elt);
/** Return a pointer to the 32-element array field sid of 'inp'.
*/
uint8_t * auth1_getarray_sid(auth1_t *inp);
+/** As auth1_get_sid, but take and return a const pointer
+ */
+const uint8_t * auth1_getconstarray_sid(const auth1_t *inp);
/** Return the (constant) length of the array holding the u1_cid_ed
* field of the auth1_t in 'inp'.
*/
@@ -443,7 +497,10 @@ size_t auth1_getlen_u1_cid_ed(const auth1_t *inp);
/** Return the element at position 'idx' of the fixed array field
* u1_cid_ed of the auth1_t in 'inp'.
*/
-uint8_t auth1_get_u1_cid_ed(const auth1_t *inp, size_t idx);
+uint8_t auth1_get_u1_cid_ed(auth1_t *inp, size_t idx);
+/** As auth1_get_u1_cid_ed, but take and return a const pointer
+ */
+uint8_t auth1_getconst_u1_cid_ed(const auth1_t *inp, size_t idx);
/** Change the element at position 'idx' of the fixed array field
* u1_cid_ed of the auth1_t in 'inp', so that it will hold the value
* 'elt'.
@@ -452,6 +509,9 @@ int auth1_set_u1_cid_ed(auth1_t *inp, size_t idx, uint8_t elt);
/** Return a pointer to the 32-element array field u1_cid_ed of 'inp'.
*/
uint8_t * auth1_getarray_u1_cid_ed(auth1_t *inp);
+/** As auth1_get_u1_cid_ed, but take and return a const pointer
+ */
+const uint8_t * auth1_getconstarray_u1_cid_ed(const auth1_t *inp);
/** Return the (constant) length of the array holding the u1_sid_ed
* field of the auth1_t in 'inp'.
*/
@@ -459,7 +519,10 @@ size_t auth1_getlen_u1_sid_ed(const auth1_t *inp);
/** Return the element at position 'idx' of the fixed array field
* u1_sid_ed of the auth1_t in 'inp'.
*/
-uint8_t auth1_get_u1_sid_ed(const auth1_t *inp, size_t idx);
+uint8_t auth1_get_u1_sid_ed(auth1_t *inp, size_t idx);
+/** As auth1_get_u1_sid_ed, but take and return a const pointer
+ */
+uint8_t auth1_getconst_u1_sid_ed(const auth1_t *inp, size_t idx);
/** Change the element at position 'idx' of the fixed array field
* u1_sid_ed of the auth1_t in 'inp', so that it will hold the value
* 'elt'.
@@ -468,6 +531,9 @@ int auth1_set_u1_sid_ed(auth1_t *inp, size_t idx, uint8_t elt);
/** Return a pointer to the 32-element array field u1_sid_ed of 'inp'.
*/
uint8_t * auth1_getarray_u1_sid_ed(auth1_t *inp);
+/** As auth1_get_u1_sid_ed, but take and return a const pointer
+ */
+const uint8_t * auth1_getconstarray_u1_sid_ed(const auth1_t *inp);
/** Return the (constant) length of the array holding the slog field
* of the auth1_t in 'inp'.
*/
@@ -475,7 +541,10 @@ size_t auth1_getlen_slog(const auth1_t *inp);
/** Return the element at position 'idx' of the fixed array field slog
* of the auth1_t in 'inp'.
*/
-uint8_t auth1_get_slog(const auth1_t *inp, size_t idx);
+uint8_t auth1_get_slog(auth1_t *inp, size_t idx);
+/** As auth1_get_slog, but take and return a const pointer
+ */
+uint8_t auth1_getconst_slog(const auth1_t *inp, size_t idx);
/** Change the element at position 'idx' of the fixed array field slog
* of the auth1_t in 'inp', so that it will hold the value 'elt'.
*/
@@ -483,6 +552,9 @@ int auth1_set_slog(auth1_t *inp, size_t idx, uint8_t elt);
/** Return a pointer to the 32-element array field slog of 'inp'.
*/
uint8_t * auth1_getarray_slog(auth1_t *inp);
+/** As auth1_get_slog, but take and return a const pointer
+ */
+const uint8_t * auth1_getconstarray_slog(const auth1_t *inp);
/** Return the (constant) length of the array holding the clog field
* of the auth1_t in 'inp'.
*/
@@ -490,7 +562,10 @@ size_t auth1_getlen_clog(const auth1_t *inp);
/** Return the element at position 'idx' of the fixed array field clog
* of the auth1_t in 'inp'.
*/
-uint8_t auth1_get_clog(const auth1_t *inp, size_t idx);
+uint8_t auth1_get_clog(auth1_t *inp, size_t idx);
+/** As auth1_get_clog, but take and return a const pointer
+ */
+uint8_t auth1_getconst_clog(const auth1_t *inp, size_t idx);
/** Change the element at position 'idx' of the fixed array field clog
* of the auth1_t in 'inp', so that it will hold the value 'elt'.
*/
@@ -498,6 +573,9 @@ int auth1_set_clog(auth1_t *inp, size_t idx, uint8_t elt);
/** Return a pointer to the 32-element array field clog of 'inp'.
*/
uint8_t * auth1_getarray_clog(auth1_t *inp);
+/** As auth1_get_clog, but take and return a const pointer
+ */
+const uint8_t * auth1_getconstarray_clog(const auth1_t *inp);
/** Return the (constant) length of the array holding the scert field
* of the auth1_t in 'inp'.
*/
@@ -505,7 +583,10 @@ size_t auth1_getlen_scert(const auth1_t *inp);
/** Return the element at position 'idx' of the fixed array field
* scert of the auth1_t in 'inp'.
*/
-uint8_t auth1_get_scert(const auth1_t *inp, size_t idx);
+uint8_t auth1_get_scert(auth1_t *inp, size_t idx);
+/** As auth1_get_scert, but take and return a const pointer
+ */
+uint8_t auth1_getconst_scert(const auth1_t *inp, size_t idx);
/** Change the element at position 'idx' of the fixed array field
* scert of the auth1_t in 'inp', so that it will hold the value
* 'elt'.
@@ -514,6 +595,9 @@ int auth1_set_scert(auth1_t *inp, size_t idx, uint8_t elt);
/** Return a pointer to the 32-element array field scert of 'inp'.
*/
uint8_t * auth1_getarray_scert(auth1_t *inp);
+/** As auth1_get_scert, but take and return a const pointer
+ */
+const uint8_t * auth1_getconstarray_scert(const auth1_t *inp);
/** Return the (constant) length of the array holding the tlssecrets
* field of the auth1_t in 'inp'.
*/
@@ -521,7 +605,10 @@ size_t auth1_getlen_tlssecrets(const auth1_t *inp);
/** Return the element at position 'idx' of the fixed array field
* tlssecrets of the auth1_t in 'inp'.
*/
-uint8_t auth1_get_tlssecrets(const auth1_t *inp, size_t idx);
+uint8_t auth1_get_tlssecrets(auth1_t *inp, size_t idx);
+/** As auth1_get_tlssecrets, but take and return a const pointer
+ */
+uint8_t auth1_getconst_tlssecrets(const auth1_t *inp, size_t idx);
/** Change the element at position 'idx' of the fixed array field
* tlssecrets of the auth1_t in 'inp', so that it will hold the value
* 'elt'.
@@ -531,6 +618,9 @@ int auth1_set_tlssecrets(auth1_t *inp, size_t idx, uint8_t elt);
* 'inp'.
*/
uint8_t * auth1_getarray_tlssecrets(auth1_t *inp);
+/** As auth1_get_tlssecrets, but take and return a const pointer
+ */
+const uint8_t * auth1_getconstarray_tlssecrets(const auth1_t *inp);
/** Return the position for end_of_fixed_part when we parsed this
* object
*/
@@ -542,7 +632,10 @@ size_t auth1_getlen_rand(const auth1_t *inp);
/** Return the element at position 'idx' of the fixed array field rand
* of the auth1_t in 'inp'.
*/
-uint8_t auth1_get_rand(const auth1_t *inp, size_t idx);
+uint8_t auth1_get_rand(auth1_t *inp, size_t idx);
+/** As auth1_get_rand, but take and return a const pointer
+ */
+uint8_t auth1_getconst_rand(const auth1_t *inp, size_t idx);
/** Change the element at position 'idx' of the fixed array field rand
* of the auth1_t in 'inp', so that it will hold the value 'elt'.
*/
@@ -550,6 +643,9 @@ int auth1_set_rand(auth1_t *inp, size_t idx, uint8_t elt);
/** Return a pointer to the 24-element array field rand of 'inp'.
*/
uint8_t * auth1_getarray_rand(auth1_t *inp);
+/** As auth1_get_rand, but take and return a const pointer
+ */
+const uint8_t * auth1_getconstarray_rand(const auth1_t *inp);
/** Return the position for end_of_signed when we parsed this object
*/
const uint8_t * auth1_get_end_of_signed(const auth1_t *inp);
@@ -561,6 +657,9 @@ size_t auth1_getlen_sig(const auth1_t *inp);
* sig of the auth1_t in 'inp'.
*/
uint8_t auth1_get_sig(auth1_t *inp, size_t idx);
+/** As auth1_get_sig, but take and return a const pointer
+ */
+uint8_t auth1_getconst_sig(const auth1_t *inp, size_t idx);
/** Change the element at position 'idx' of the dynamic array field
* sig of the auth1_t in 'inp', so that it will hold the value 'elt'.
*/
@@ -572,6 +671,9 @@ int auth1_add_sig(auth1_t *inp, uint8_t elt);
/** Return a pointer to the variable-length array field sig of 'inp'.
*/
uint8_t * auth1_getarray_sig(auth1_t *inp);
+/** As auth1_get_sig, but take and return a const pointer
+ */
+const uint8_t * auth1_getconstarray_sig(const auth1_t *inp);
/** Change the length of the variable-length array field sig of 'inp'
* to 'newlen'.Fill extra elements with 0. Return 0 on success; return
* -1 and set the error code on 'inp' on failure.
@@ -627,6 +729,9 @@ size_t certs_cell_getlen_certs(const certs_cell_t *inp);
* certs of the certs_cell_t in 'inp'.
*/
struct certs_cell_cert_st * certs_cell_get_certs(certs_cell_t *inp, size_t idx);
+/** As certs_cell_get_certs, but take and return a const pointer
+ */
+ const struct certs_cell_cert_st * certs_cell_getconst_certs(const certs_cell_t *inp, size_t idx);
/** Change the element at position 'idx' of the dynamic array field
* certs of the certs_cell_t in 'inp', so that it will hold the value
* 'elt'. Free the previous value, if any.
@@ -643,6 +748,9 @@ int certs_cell_add_certs(certs_cell_t *inp, struct certs_cell_cert_st * elt);
* 'inp'.
*/
struct certs_cell_cert_st * * certs_cell_getarray_certs(certs_cell_t *inp);
+/** As certs_cell_get_certs, but take and return a const pointer
+ */
+const struct certs_cell_cert_st * const * certs_cell_getconstarray_certs(const certs_cell_t *inp);
/** Change the length of the variable-length array field certs of
* 'inp' to 'newlen'.Fill extra elements with NULL; free removed
* elements. Return 0 on success; return -1 and set the error code on
diff --git a/src/trunnel/pwbox.c b/src/trunnel/pwbox.c
index 62662a9369..059fcfd7da 100644
--- a/src/trunnel/pwbox.c
+++ b/src/trunnel/pwbox.c
@@ -1,4 +1,4 @@
-/* pwbox.c -- generated by Trunnel v1.4.6.
+/* pwbox.c -- generated by Trunnel v1.5.
* https://gitweb.torproject.org/trunnel.git
* You probably shouldn't edit this file.
*/
@@ -114,6 +114,11 @@ pwbox_encoded_get_skey_header(pwbox_encoded_t *inp, size_t idx)
return TRUNNEL_DYNARRAY_GET(&inp->skey_header, idx);
}
+uint8_t
+pwbox_encoded_getconst_skey_header(const pwbox_encoded_t *inp, size_t idx)
+{
+ return pwbox_encoded_get_skey_header((pwbox_encoded_t*)inp, idx);
+}
int
pwbox_encoded_set_skey_header(pwbox_encoded_t *inp, size_t idx, uint8_t elt)
{
@@ -139,6 +144,11 @@ pwbox_encoded_getarray_skey_header(pwbox_encoded_t *inp)
{
return inp->skey_header.elts_;
}
+const uint8_t *
+pwbox_encoded_getconstarray_skey_header(const pwbox_encoded_t *inp)
+{
+ return (const uint8_t *)pwbox_encoded_getarray_skey_header((pwbox_encoded_t*)inp);
+}
int
pwbox_encoded_setlen_skey_header(pwbox_encoded_t *inp, size_t newlen)
{
@@ -166,12 +176,17 @@ pwbox_encoded_getlen_iv(const pwbox_encoded_t *inp)
}
uint8_t
-pwbox_encoded_get_iv(const pwbox_encoded_t *inp, size_t idx)
+pwbox_encoded_get_iv(pwbox_encoded_t *inp, size_t idx)
{
trunnel_assert(idx < 16);
return inp->iv[idx];
}
+uint8_t
+pwbox_encoded_getconst_iv(const pwbox_encoded_t *inp, size_t idx)
+{
+ return pwbox_encoded_get_iv((pwbox_encoded_t*)inp, idx);
+}
int
pwbox_encoded_set_iv(pwbox_encoded_t *inp, size_t idx, uint8_t elt)
{
@@ -185,6 +200,11 @@ pwbox_encoded_getarray_iv(pwbox_encoded_t *inp)
{
return inp->iv;
}
+const uint8_t *
+pwbox_encoded_getconstarray_iv(const pwbox_encoded_t *inp)
+{
+ return (const uint8_t *)pwbox_encoded_getarray_iv((pwbox_encoded_t*)inp);
+}
size_t
pwbox_encoded_getlen_data(const pwbox_encoded_t *inp)
{
@@ -197,6 +217,11 @@ pwbox_encoded_get_data(pwbox_encoded_t *inp, size_t idx)
return TRUNNEL_DYNARRAY_GET(&inp->data, idx);
}
+uint8_t
+pwbox_encoded_getconst_data(const pwbox_encoded_t *inp, size_t idx)
+{
+ return pwbox_encoded_get_data((pwbox_encoded_t*)inp, idx);
+}
int
pwbox_encoded_set_data(pwbox_encoded_t *inp, size_t idx, uint8_t elt)
{
@@ -218,6 +243,11 @@ pwbox_encoded_getarray_data(pwbox_encoded_t *inp)
{
return inp->data.elts_;
}
+const uint8_t *
+pwbox_encoded_getconstarray_data(const pwbox_encoded_t *inp)
+{
+ return (const uint8_t *)pwbox_encoded_getarray_data((pwbox_encoded_t*)inp);
+}
int
pwbox_encoded_setlen_data(pwbox_encoded_t *inp, size_t newlen)
{
@@ -241,12 +271,17 @@ pwbox_encoded_getlen_hmac(const pwbox_encoded_t *inp)
}
uint8_t
-pwbox_encoded_get_hmac(const pwbox_encoded_t *inp, size_t idx)
+pwbox_encoded_get_hmac(pwbox_encoded_t *inp, size_t idx)
{
trunnel_assert(idx < 32);
return inp->hmac[idx];
}
+uint8_t
+pwbox_encoded_getconst_hmac(const pwbox_encoded_t *inp, size_t idx)
+{
+ return pwbox_encoded_get_hmac((pwbox_encoded_t*)inp, idx);
+}
int
pwbox_encoded_set_hmac(pwbox_encoded_t *inp, size_t idx, uint8_t elt)
{
@@ -260,6 +295,11 @@ pwbox_encoded_getarray_hmac(pwbox_encoded_t *inp)
{
return inp->hmac;
}
+const uint8_t *
+pwbox_encoded_getconstarray_hmac(const pwbox_encoded_t *inp)
+{
+ return (const uint8_t *)pwbox_encoded_getarray_hmac((pwbox_encoded_t*)inp);
+}
const char *
pwbox_encoded_check(const pwbox_encoded_t *obj)
{
diff --git a/src/trunnel/pwbox.h b/src/trunnel/pwbox.h
index 77a813d123..9376a7cd1b 100644
--- a/src/trunnel/pwbox.h
+++ b/src/trunnel/pwbox.h
@@ -1,4 +1,4 @@
-/* pwbox.h -- generated by by Trunnel v1.4.6.
+/* pwbox.h -- generated by by Trunnel v1.5.
* https://gitweb.torproject.org/trunnel.git
* You probably shouldn't edit this file.
*/
@@ -93,6 +93,10 @@ size_t pwbox_encoded_getlen_skey_header(const pwbox_encoded_t *inp);
* skey_header of the pwbox_encoded_t in 'inp'.
*/
uint8_t pwbox_encoded_get_skey_header(pwbox_encoded_t *inp, size_t idx);
+/** As pwbox_encoded_get_skey_header, but take and return a const
+ * pointer
+ */
+uint8_t pwbox_encoded_getconst_skey_header(const pwbox_encoded_t *inp, size_t idx);
/** Change the element at position 'idx' of the dynamic array field
* skey_header of the pwbox_encoded_t in 'inp', so that it will hold
* the value 'elt'.
@@ -106,6 +110,10 @@ int pwbox_encoded_add_skey_header(pwbox_encoded_t *inp, uint8_t elt);
* 'inp'.
*/
uint8_t * pwbox_encoded_getarray_skey_header(pwbox_encoded_t *inp);
+/** As pwbox_encoded_get_skey_header, but take and return a const
+ * pointer
+ */
+const uint8_t * pwbox_encoded_getconstarray_skey_header(const pwbox_encoded_t *inp);
/** Change the length of the variable-length array field skey_header
* of 'inp' to 'newlen'.Fill extra elements with 0. Return 0 on
* success; return -1 and set the error code on 'inp' on failure.
@@ -118,7 +126,10 @@ size_t pwbox_encoded_getlen_iv(const pwbox_encoded_t *inp);
/** Return the element at position 'idx' of the fixed array field iv
* of the pwbox_encoded_t in 'inp'.
*/
-uint8_t pwbox_encoded_get_iv(const pwbox_encoded_t *inp, size_t idx);
+uint8_t pwbox_encoded_get_iv(pwbox_encoded_t *inp, size_t idx);
+/** As pwbox_encoded_get_iv, but take and return a const pointer
+ */
+uint8_t pwbox_encoded_getconst_iv(const pwbox_encoded_t *inp, size_t idx);
/** Change the element at position 'idx' of the fixed array field iv
* of the pwbox_encoded_t in 'inp', so that it will hold the value
* 'elt'.
@@ -127,6 +138,9 @@ int pwbox_encoded_set_iv(pwbox_encoded_t *inp, size_t idx, uint8_t elt);
/** Return a pointer to the 16-element array field iv of 'inp'.
*/
uint8_t * pwbox_encoded_getarray_iv(pwbox_encoded_t *inp);
+/** As pwbox_encoded_get_iv, but take and return a const pointer
+ */
+const uint8_t * pwbox_encoded_getconstarray_iv(const pwbox_encoded_t *inp);
/** Return the length of the dynamic array holding the data field of
* the pwbox_encoded_t in 'inp'.
*/
@@ -135,6 +149,9 @@ size_t pwbox_encoded_getlen_data(const pwbox_encoded_t *inp);
* data of the pwbox_encoded_t in 'inp'.
*/
uint8_t pwbox_encoded_get_data(pwbox_encoded_t *inp, size_t idx);
+/** As pwbox_encoded_get_data, but take and return a const pointer
+ */
+uint8_t pwbox_encoded_getconst_data(const pwbox_encoded_t *inp, size_t idx);
/** Change the element at position 'idx' of the dynamic array field
* data of the pwbox_encoded_t in 'inp', so that it will hold the
* value 'elt'.
@@ -147,6 +164,9 @@ int pwbox_encoded_add_data(pwbox_encoded_t *inp, uint8_t elt);
/** Return a pointer to the variable-length array field data of 'inp'.
*/
uint8_t * pwbox_encoded_getarray_data(pwbox_encoded_t *inp);
+/** As pwbox_encoded_get_data, but take and return a const pointer
+ */
+const uint8_t * pwbox_encoded_getconstarray_data(const pwbox_encoded_t *inp);
/** Change the length of the variable-length array field data of 'inp'
* to 'newlen'.Fill extra elements with 0. Return 0 on success; return
* -1 and set the error code on 'inp' on failure.
@@ -159,7 +179,10 @@ size_t pwbox_encoded_getlen_hmac(const pwbox_encoded_t *inp);
/** Return the element at position 'idx' of the fixed array field hmac
* of the pwbox_encoded_t in 'inp'.
*/
-uint8_t pwbox_encoded_get_hmac(const pwbox_encoded_t *inp, size_t idx);
+uint8_t pwbox_encoded_get_hmac(pwbox_encoded_t *inp, size_t idx);
+/** As pwbox_encoded_get_hmac, but take and return a const pointer
+ */
+uint8_t pwbox_encoded_getconst_hmac(const pwbox_encoded_t *inp, size_t idx);
/** Change the element at position 'idx' of the fixed array field hmac
* of the pwbox_encoded_t in 'inp', so that it will hold the value
* 'elt'.
@@ -168,6 +191,9 @@ int pwbox_encoded_set_hmac(pwbox_encoded_t *inp, size_t idx, uint8_t elt);
/** Return a pointer to the 32-element array field hmac of 'inp'.
*/
uint8_t * pwbox_encoded_getarray_hmac(pwbox_encoded_t *inp);
+/** As pwbox_encoded_get_hmac, but take and return a const pointer
+ */
+const uint8_t * pwbox_encoded_getconstarray_hmac(const pwbox_encoded_t *inp);
#endif
diff --git a/src/win32/orconfig.h b/src/win32/orconfig.h
index d90242320a..c113efb402 100644
--- a/src/win32/orconfig.h
+++ b/src/win32/orconfig.h
@@ -218,7 +218,7 @@
#define USING_TWOS_COMPLEMENT
/* Version number of package */
-#define VERSION "0.2.9.4-alpha-dev"
+#define VERSION "0.3.0.0-alpha-dev"