From 5a801a8c8b71c9551a80913398135809cb10cecd Mon Sep 17 00:00:00 2001 From: Kamran Riaz Khan Date: Mon, 8 Aug 2011 04:38:53 +0500 Subject: [PATCH 01/10] Emits CONF_CHANGED events whenever Tor's configuration values change. --- src/or/config.c | 33 +++++++++++++++++++++++++++++++++ src/or/control.c | 17 ++++++++++++++++- src/or/control.h | 1 + 3 files changed, 50 insertions(+), 1 deletion(-) diff --git a/src/or/config.c b/src/or/config.c index 088617bb49..653e23dca7 100644 --- a/src/or/config.c +++ b/src/or/config.c @@ -10,6 +10,7 @@ **/ #define CONFIG_PRIVATE +#define CONTROL_PRIVATE #include "or.h" #include "circuitbuild.h" @@ -693,6 +694,10 @@ get_options(void) int set_options(or_options_t *new_val, char **msg) { + int i; + char *result; + smartlist_t *elements; + config_line_t *line; or_options_t *old_options = global_options; global_options = new_val; /* Note that we pass the *old* options below, for comparison. It @@ -707,7 +712,35 @@ set_options(or_options_t *new_val, char **msg) "Acting on config options left us in a broken state. Dying."); exit(1); } + /* Issues a CONF_CHANGED event to notify controller of the change. If Tor is + * just starting up then the old_options will be undefined. */ + if (old_options) { + elements = smartlist_create(); + for (i=0; options_format.vars[i].name; ++i) { + if (!option_is_same(&options_format, new_val, old_options, + options_format.vars[i].name)) { + line = get_assigned_option(&options_format, new_val, + options_format.vars[i].name, 0); + if (line) { + for (; line; line = line->next) { + char *tmp; + tor_asprintf(&tmp, "650-%s=%s", line->key, line->value); + smartlist_add(elements, tmp); + } + } else { + char *tmp; + tor_asprintf(&tmp, "650-%s", options_format.vars[i].name); + smartlist_add(elements, tmp); + } + } + } + result = smartlist_join_strings(elements, "\r\n", 0, NULL); + control_event_conf_changed(result); + tor_free(result); + SMARTLIST_FOREACH(elements, char *, cp, tor_free(cp)); + smartlist_free(elements); + } config_free(&options_format, old_options); return 0; diff --git a/src/or/control.c b/src/or/control.c index ad11350fbd..0b19a25d99 100644 --- a/src/or/control.c +++ b/src/or/control.c @@ -74,7 +74,8 @@ #define EVENT_NEWCONSENSUS 0x0016 #define EVENT_BUILDTIMEOUT_SET 0x0017 #define EVENT_SIGNAL 0x0018 -#define _EVENT_MAX 0x0018 +#define EVENT_CONF_CHANGED 0x0019 +#define _EVENT_MAX 0x0019 /* If _EVENT_MAX ever hits 0x0020, we need to make the mask wider. */ /** Bitfield: The bit 1<<e is set if any open control @@ -946,6 +947,7 @@ static const struct control_event_t control_event_table[] = { { EVENT_NEWCONSENSUS, "NEWCONSENSUS" }, { EVENT_BUILDTIMEOUT_SET, "BUILDTIMEOUT_SET" }, { EVENT_SIGNAL, "SIGNAL" }, + { EVENT_CONF_CHANGED, "CONF_CHANGED"}, { 0, NULL }, }; @@ -3996,6 +3998,19 @@ control_event_guard(const char *nickname, const char *digest, return 0; } +/** Called when a configuration option changes. This is generally triggered + * by SETCONF requests and RELOAD/SIGHUP signals. The values are the + * keyword/value pairs for the configuration changes tor is using. */ +int +control_event_conf_changed(const char *values) +{ + if(strlen(values) > 0) { + send_control_event(EVENT_CONF_CHANGED, 0, + "650-CONF_CHANGED\r\n%s\r\n650 OK\r\n", values); + } + return 0; +} + /** Helper: Return a newly allocated string containing a path to the * file where we store our authentication cookie. */ static char * diff --git a/src/or/control.h b/src/or/control.h index 147a5af0bb..ed83f53ac4 100644 --- a/src/or/control.h +++ b/src/or/control.h @@ -66,6 +66,7 @@ int control_event_server_status(int severity, const char *format, ...) CHECK_PRINTF(2,3); int control_event_guard(const char *nickname, const char *digest, const char *status); +int control_event_conf_changed(const char *values); int control_event_buildtimeout_set(const circuit_build_times_t *cbt, buildtimeout_set_event_t type); int control_event_signal(uintptr_t signal); From 02c62b2966083ce549fc6ba6c743d5c37f357fe6 Mon Sep 17 00:00:00 2001 From: Kamran Riaz Khan Date: Mon, 8 Aug 2011 19:19:06 +0500 Subject: [PATCH 02/10] Refactor to do CONF_CHANGED event formatting inside control.c --- src/or/config.c | 17 +++++------------ src/or/control.c | 30 ++++++++++++++++++++++++++---- src/or/control.h | 2 +- 3 files changed, 32 insertions(+), 17 deletions(-) diff --git a/src/or/config.c b/src/or/config.c index 653e23dca7..02dc7eba5a 100644 --- a/src/or/config.c +++ b/src/or/config.c @@ -10,7 +10,6 @@ **/ #define CONFIG_PRIVATE -#define CONTROL_PRIVATE #include "or.h" #include "circuitbuild.h" @@ -695,7 +694,6 @@ int set_options(or_options_t *new_val, char **msg) { int i; - char *result; smartlist_t *elements; config_line_t *line; or_options_t *old_options = global_options; @@ -724,21 +722,16 @@ set_options(or_options_t *new_val, char **msg) if (line) { for (; line; line = line->next) { - char *tmp; - tor_asprintf(&tmp, "650-%s=%s", line->key, line->value); - smartlist_add(elements, tmp); + smartlist_add(elements, line->key); + smartlist_add(elements, line->value); } } else { - char *tmp; - tor_asprintf(&tmp, "650-%s", options_format.vars[i].name); - smartlist_add(elements, tmp); + smartlist_add(elements, options_format.vars[i].name); + smartlist_add(elements, NULL); } } } - result = smartlist_join_strings(elements, "\r\n", 0, NULL); - control_event_conf_changed(result); - tor_free(result); - SMARTLIST_FOREACH(elements, char *, cp, tor_free(cp)); + control_event_conf_changed(elements); smartlist_free(elements); } config_free(&options_format, old_options); diff --git a/src/or/control.c b/src/or/control.c index 0b19a25d99..05797038de 100644 --- a/src/or/control.c +++ b/src/or/control.c @@ -4002,12 +4002,34 @@ control_event_guard(const char *nickname, const char *digest, * by SETCONF requests and RELOAD/SIGHUP signals. The values are the * keyword/value pairs for the configuration changes tor is using. */ int -control_event_conf_changed(const char *values) +control_event_conf_changed(smartlist_t *elements) { - if(strlen(values) > 0) { - send_control_event(EVENT_CONF_CHANGED, 0, - "650-CONF_CHANGED\r\n%s\r\n650 OK\r\n", values); + int i; + char *result; + smartlist_t *lines; + if (smartlist_len(elements) == 0) { + return 0; } + lines = smartlist_create(); + for (i = 0; i < smartlist_len(elements); i += 2) { + char *k = smartlist_get(elements, i); + char *v = smartlist_get(elements, i+1); + if (v == NULL) { + char *tmp; + tor_asprintf(&tmp, "650-%s", k); + smartlist_add(lines, tmp); + } else { + char *tmp; + tor_asprintf(&tmp, "650-%s=%s", k, v); + smartlist_add(lines, tmp); + } + } + result = smartlist_join_strings(lines, "\r\n", 0, NULL); + send_control_event(EVENT_CONF_CHANGED, 0, + "650-CONF_CHANGED\r\n%s\r\n650 OK\r\n", result); + tor_free(result); + SMARTLIST_FOREACH(lines, char *, cp, tor_free(cp)); + smartlist_free(lines); return 0; } diff --git a/src/or/control.h b/src/or/control.h index ed83f53ac4..544a9fcc9e 100644 --- a/src/or/control.h +++ b/src/or/control.h @@ -66,7 +66,7 @@ int control_event_server_status(int severity, const char *format, ...) CHECK_PRINTF(2,3); int control_event_guard(const char *nickname, const char *digest, const char *status); -int control_event_conf_changed(const char *values); +int control_event_conf_changed(smartlist_t *elements); int control_event_buildtimeout_set(const circuit_build_times_t *cbt, buildtimeout_set_event_t type); int control_event_signal(uintptr_t signal); From 23ef12462adab98d5d63bc9579892dbc6f1dea6f Mon Sep 17 00:00:00 2001 From: Kamran Riaz Khan Date: Mon, 8 Aug 2011 19:58:43 +0500 Subject: [PATCH 03/10] Minor comment fix. --- src/or/control.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/or/control.c b/src/or/control.c index 05797038de..f679493d34 100644 --- a/src/or/control.c +++ b/src/or/control.c @@ -3999,8 +3999,9 @@ control_event_guard(const char *nickname, const char *digest, } /** Called when a configuration option changes. This is generally triggered - * by SETCONF requests and RELOAD/SIGHUP signals. The values are the - * keyword/value pairs for the configuration changes tor is using. */ + * by SETCONF requests and RELOAD/SIGHUP signals. The elements is + * a smartlist_t containing (key, value, ...) pairs in sequence. + * value can be NULL. */ int control_event_conf_changed(smartlist_t *elements) { From 3b85fe8a5dd0fed88163ffc3bcb4eec8bf2053bc Mon Sep 17 00:00:00 2001 From: Kamran Riaz Khan Date: Tue, 9 Aug 2011 03:02:40 +0500 Subject: [PATCH 04/10] Add changes file. --- changes/bug1692 | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 changes/bug1692 diff --git a/changes/bug1692 b/changes/bug1692 new file mode 100644 index 0000000000..c2a71cc428 --- /dev/null +++ b/changes/bug1692 @@ -0,0 +1,5 @@ + o Minor features: + - CONF_CHANGED event is provided so that controllers can be notified + of any configuration changes made by other controllers/SETCONF/HUP. + Implements #1692. + From 5f624805e71d3f160ed7de28b17ecad892827758 Mon Sep 17 00:00:00 2001 From: Kamran Riaz Khan Date: Tue, 9 Aug 2011 03:17:21 +0500 Subject: [PATCH 05/10] Minor code readability fix. --- src/or/control.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/or/control.c b/src/or/control.c index f679493d34..3943aff96c 100644 --- a/src/or/control.c +++ b/src/or/control.c @@ -4015,15 +4015,13 @@ control_event_conf_changed(smartlist_t *elements) for (i = 0; i < smartlist_len(elements); i += 2) { char *k = smartlist_get(elements, i); char *v = smartlist_get(elements, i+1); + char *tmp; if (v == NULL) { - char *tmp; tor_asprintf(&tmp, "650-%s", k); - smartlist_add(lines, tmp); } else { - char *tmp; tor_asprintf(&tmp, "650-%s=%s", k, v); - smartlist_add(lines, tmp); } + smartlist_add(lines, tmp); } result = smartlist_join_strings(lines, "\r\n", 0, NULL); send_control_event(EVENT_CONF_CHANGED, 0, From e42a74e56351a41c0a68999ed5fce48ab03166d7 Mon Sep 17 00:00:00 2001 From: Robert Ransom Date: Wed, 3 Aug 2011 15:49:39 -0700 Subject: [PATCH 06/10] Add smartlist_[v]asprintf_add I should have added this before implementing #2411. --- src/common/util.c | 24 ++++++++++++++++++++++++ src/common/util.h | 5 +++++ 2 files changed, 29 insertions(+) diff --git a/src/common/util.c b/src/common/util.c index 601f2be3e2..1e5e454c64 100644 --- a/src/common/util.c +++ b/src/common/util.c @@ -2679,6 +2679,30 @@ tor_sscanf(const char *buf, const char *pattern, ...) return r; } +/** Append the string produced by tor_asprintf(pattern, ...) + * to sl. */ +void +smartlist_asprintf_add(struct smartlist_t *sl, const char *pattern, ...) +{ + va_list ap; + va_start(ap, pattern); + smartlist_vasprintf_add(sl, pattern, ap); + va_end(ap); +} + +/** va_list-based backend of smartlist_asprintf_add. */ +void +smartlist_vasprintf_add(struct smartlist_t *sl, const char *pattern, + va_list args) +{ + char *str = NULL; + + tor_vasprintf(&str, pattern, args); + tor_assert(str != NULL); + + smartlist_add(sl, str); +} + /** Return a new list containing the filenames in the directory dirname. * Return NULL on error or if dirname is not a directory. */ diff --git a/src/common/util.h b/src/common/util.h index 99355871f6..a1def6cc3f 100644 --- a/src/common/util.h +++ b/src/common/util.h @@ -220,6 +220,11 @@ int tor_sscanf(const char *buf, const char *pattern, ...) #endif ; +void smartlist_asprintf_add(struct smartlist_t *sl, const char *pattern, ...) + CHECK_PRINTF(2, 3); +void smartlist_vasprintf_add(struct smartlist_t *sl, const char *pattern, + va_list args); + int hex_decode_digit(char c); void base16_encode(char *dest, size_t destlen, const char *src, size_t srclen); int base16_decode(char *dest, size_t destlen, const char *src, size_t srclen); From 86f68ed6953620e14c7f9894e01ab2eafea250e7 Mon Sep 17 00:00:00 2001 From: Kamran Riaz Khan Date: Tue, 9 Aug 2011 15:18:57 +0500 Subject: [PATCH 07/10] Use smartlist_asprintf_add() to improve readability. --- src/or/control.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/or/control.c b/src/or/control.c index 3943aff96c..706d871d69 100644 --- a/src/or/control.c +++ b/src/or/control.c @@ -4015,13 +4015,11 @@ control_event_conf_changed(smartlist_t *elements) for (i = 0; i < smartlist_len(elements); i += 2) { char *k = smartlist_get(elements, i); char *v = smartlist_get(elements, i+1); - char *tmp; if (v == NULL) { - tor_asprintf(&tmp, "650-%s", k); + smartlist_asprintf_add(lines, "650-%s", k); } else { - tor_asprintf(&tmp, "650-%s=%s", k, v); + smartlist_asprintf_add(lines, "650-%s=%s", k, v); } - smartlist_add(lines, tmp); } result = smartlist_join_strings(lines, "\r\n", 0, NULL); send_control_event(EVENT_CONF_CHANGED, 0, From 643913de75b51b4fa50f3c6b0c68e25f6e7a96c1 Mon Sep 17 00:00:00 2001 From: Kamran Riaz Khan Date: Tue, 9 Aug 2011 15:25:16 +0500 Subject: [PATCH 08/10] Escape configuration values before sending them via CONF_CHANGED. --- src/or/config.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/or/config.c b/src/or/config.c index 02dc7eba5a..28c83adc4f 100644 --- a/src/or/config.c +++ b/src/or/config.c @@ -718,7 +718,7 @@ set_options(or_options_t *new_val, char **msg) if (!option_is_same(&options_format, new_val, old_options, options_format.vars[i].name)) { line = get_assigned_option(&options_format, new_val, - options_format.vars[i].name, 0); + options_format.vars[i].name, 1); if (line) { for (; line; line = line->next) { From 73f07c558b16db14e72b6b738dffd75a890a1001 Mon Sep 17 00:00:00 2001 From: Kamran Riaz Khan Date: Tue, 9 Aug 2011 15:28:17 +0500 Subject: [PATCH 09/10] Return if CONF_CHANGED isn't interesting. --- src/or/control.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/or/control.c b/src/or/control.c index 706d871d69..8f3a488f34 100644 --- a/src/or/control.c +++ b/src/or/control.c @@ -4008,7 +4008,7 @@ control_event_conf_changed(smartlist_t *elements) int i; char *result; smartlist_t *lines; - if (smartlist_len(elements) == 0) { + if (!EVENT_IS_INTERESTING(EVENT_CONF_CHANGED) && smartlist_len(elements) == 0) { return 0; } lines = smartlist_create(); From 02a735dfa847e9cb7b78b58ef1f69d865e4d21bf Mon Sep 17 00:00:00 2001 From: Kamran Riaz Khan Date: Tue, 9 Aug 2011 22:21:04 +0500 Subject: [PATCH 10/10] Fix condition reported by nickm. --- src/or/control.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/or/control.c b/src/or/control.c index 8f3a488f34..afd0662df0 100644 --- a/src/or/control.c +++ b/src/or/control.c @@ -4008,7 +4008,7 @@ control_event_conf_changed(smartlist_t *elements) int i; char *result; smartlist_t *lines; - if (!EVENT_IS_INTERESTING(EVENT_CONF_CHANGED) && smartlist_len(elements) == 0) { + if (!EVENT_IS_INTERESTING(EVENT_CONF_CHANGED) || smartlist_len(elements) == 0) { return 0; } lines = smartlist_create();