diff options
-rw-r--r-- | changes/bug1692 | 5 | ||||
-rw-r--r-- | src/common/util.c | 24 | ||||
-rw-r--r-- | src/common/util.h | 5 | ||||
-rw-r--r-- | src/or/config.c | 28 | ||||
-rw-r--r-- | src/or/control.c | 36 | ||||
-rw-r--r-- | src/or/control.h | 1 |
6 files changed, 97 insertions, 2 deletions
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. + diff --git a/src/common/util.c b/src/common/util.c index 542093fb5d..c387318c0e 100644 --- a/src/common/util.c +++ b/src/common/util.c @@ -2681,6 +2681,30 @@ tor_sscanf(const char *buf, const char *pattern, ...) return r; } +/** Append the string produced by tor_asprintf(<b>pattern</b>, <b>...</b>) + * to <b>sl</b>. */ +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 <b>dirname</b>. * Return NULL on error or if <b>dirname</b> 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); diff --git a/src/or/config.c b/src/or/config.c index 1f574c8233..e2e5cd3a6b 100644 --- a/src/or/config.c +++ b/src/or/config.c @@ -696,6 +696,9 @@ get_options(void) int set_options(or_options_t *new_val, char **msg) { + int i; + 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 @@ -710,7 +713,30 @@ 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, 1); + + if (line) { + for (; line; line = line->next) { + smartlist_add(elements, line->key); + smartlist_add(elements, line->value); + } + } else { + smartlist_add(elements, options_format.vars[i].name); + smartlist_add(elements, NULL); + } + } + } + control_event_conf_changed(elements); + 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..afd0662df0 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 <b>any</b> 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,38 @@ 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 <b>elements</b> is + * a smartlist_t containing (key, value, ...) pairs in sequence. + * <b>value</b> can be NULL. */ +int +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) { + 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) { + smartlist_asprintf_add(lines, "650-%s", k); + } else { + smartlist_asprintf_add(lines, "650-%s=%s", k, v); + } + } + 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; +} + /** 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..544a9fcc9e 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(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); |