From 4b266c6e72254d848b2ca4f594c0b41770104d81 Mon Sep 17 00:00:00 2001 From: Robert Ransom Date: Sun, 15 May 2011 08:23:04 -0700 Subject: Implement __OwningControllerProcess option Implements part of feature 3049. --- src/or/config.c | 18 ++++++++++++ src/or/control.c | 86 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/or/control.h | 2 ++ src/or/or.h | 5 ++++ 4 files changed, 111 insertions(+) (limited to 'src/or') diff --git a/src/or/config.c b/src/or/config.c index 34208e85b..b2bc9f3e9 100644 --- a/src/or/config.c +++ b/src/or/config.c @@ -38,6 +38,8 @@ #include #endif +#include "procmon.h" + /** Enumeration of types which option values can take */ typedef enum config_type_t { CONFIG_TYPE_STRING = 0, /**< An arbitrary string. */ @@ -393,6 +395,7 @@ static config_var_t _option_vars[] = { VAR("__LeaveStreamsUnattached",BOOL, LeaveStreamsUnattached, "0"), VAR("__HashedControlSessionPassword", LINELIST, HashedControlSessionPassword, NULL), + VAR("__OwningControllerProcess",STRING,OwningControllerProcess, NULL), V(MinUptimeHidServDirectoryV2, INTERVAL, "24 hours"), V(_UsingTestNetworkDefaults, BOOL, "0"), @@ -1229,6 +1232,11 @@ options_act(or_options_t *old_options) return -1; } + if (monitor_owning_controller_process(options->OwningControllerProcess)) { + log_warn(LD_CONFIG, "Error monitoring owning controller process"); + return -1; + } + /* reload keys as needed for rendezvous services. */ if (rend_service_load_keys()<0) { log_warn(LD_GENERAL,"Error loading rendezvous service keys"); @@ -3446,6 +3454,16 @@ options_validate(or_options_t *old_options, or_options_t *options, } } + if (options->OwningControllerProcess) { + const char *validate_pspec_msg = NULL; + if (tor_validate_process_specifier(options->OwningControllerProcess, + &validate_pspec_msg)) { + tor_asprintf(msg, "Bad OwningControllerProcess: %s", + validate_pspec_msg); + return -1; + } + } + if (options->ControlListenAddress) { int all_are_local = 1; config_line_t *ln; diff --git a/src/or/control.c b/src/or/control.c index 926a46520..3a9690443 100644 --- a/src/or/control.c +++ b/src/or/control.c @@ -32,6 +32,8 @@ #include "routerlist.h" #include "routerparse.h" +#include "procmon.h" + /** Yield true iff s is the state of a control_connection_t that has * finished authentication and is accepting commands. */ #define STATE_IS_OPEN(s) ((s) == CONTROL_CONN_STATE_OPEN) @@ -3779,6 +3781,90 @@ init_cookie_authentication(int enabled) return 0; } +/** A copy of the process specifier of Tor's owning controller, or + * NULL if this Tor instance is not currently owned by a process. */ +static char *owning_controller_process_spec = NULL; + +/** A process-termination monitor for Tor's owning controller, or NULL + * if this Tor instance is not currently owned by a process. */ +static tor_process_monitor_t *owning_controller_process_monitor = NULL; + +/** Process-termination monitor callback for Tor's owning controller + * process. */ +static void +owning_controller_procmon_cb(void *unused) +{ + int shutdown_slowly = server_mode(get_options()); + + (void)unused; + + log_notice(LD_CONTROL, "Owning controller process has vanished -- " + "%s.", + shutdown_slowly ? "shutting down" : "exiting now"); + + /* XXXX This chunk of code should be a separate function, called + * here and by process_signal(SIGINT). */ + + if (!shutdown_slowly) { + tor_cleanup(); + exit(0); + } + /* XXXX This will close all listening sockets except control-port + * listeners. Perhaps we should close those too. */ + hibernate_begin_shutdown(); +} + +/** Set process_spec as Tor's owning controller process. + * Return 0 on success, -1 on failure. */ +int +monitor_owning_controller_process(const char *process_spec) +{ + const char *msg; + + tor_assert((owning_controller_process_spec == NULL) == + (owning_controller_process_monitor == NULL)); + + if (owning_controller_process_spec != NULL) { + if ((process_spec != NULL) && !strcmp(process_spec, + owning_controller_process_spec)) { + /* Same process -- return now, instead of disposing of and + * recreating the process-termination monitor. */ + return 0; + } + + /* We are currently owned by a process, and we should no longer be + * owned by it. Free the process-termination monitor. */ + tor_process_monitor_free(owning_controller_process_monitor); + owning_controller_process_monitor = NULL; + + tor_free(owning_controller_process_spec); + owning_controller_process_spec = NULL; + } + + tor_assert((owning_controller_process_spec == NULL) && + (owning_controller_process_monitor == NULL)); + + if (process_spec == NULL) + return 0; + + owning_controller_process_spec = tor_strdup(process_spec); + owning_controller_process_monitor = + tor_process_monitor_new(tor_libevent_get_base(), + owning_controller_process_spec, + LD_CONTROL, + owning_controller_procmon_cb, NULL, + &msg); + + if (owning_controller_process_monitor == NULL) { + log_warn(LD_CONTROL, "Couldn't create process-termination monitor for " + "owning controller: %s", + msg); + return -1; + } + + return 0; +} + /** Convert the name of a bootstrapping phase s into strings * tag and summary suitable for display by the controller. */ static int diff --git a/src/or/control.h b/src/or/control.h index 2ae96b4b8..81c23010d 100644 --- a/src/or/control.h +++ b/src/or/control.h @@ -70,6 +70,8 @@ smartlist_t *decode_hashed_passwords(config_line_t *passwords); void disable_control_logging(void); void enable_control_logging(void); +int monitor_owning_controller_process(const char *process_spec); + void control_event_bootstrap(bootstrap_status_t status, int progress); void control_event_bootstrap_problem(const char *warn, int reason); diff --git a/src/or/or.h b/src/or/or.h index d667358eb..546c38a9a 100644 --- a/src/or/or.h +++ b/src/or/or.h @@ -2669,6 +2669,11 @@ typedef struct { int DisablePredictedCircuits; /**< Boolean: does Tor preemptively * make circuits in the background (0), * or not (1)? */ + + /** Process specifier for a controller that ‘owns’ this Tor + * instance. Tor will terminate if its owning controller does. */ + char *OwningControllerProcess; + int ShutdownWaitLength; /**< When we get a SIGINT and we're a server, how * long do we wait before exiting? */ char *SafeLogging; /**< Contains "relay", "1", "0" (meaning no scrubbing). */ -- cgit v1.2.3 From b3133d1cadec0540105a855b1fd2eb741d4eec9d Mon Sep 17 00:00:00 2001 From: Robert Ransom Date: Mon, 16 May 2011 10:25:59 -0700 Subject: Exit immediately if we can't monitor our owning controller process tor_process_monitor_new can't currently return NULL, but if it ever can, we want that to be an explicitly fatal error, without relying on the fact that monitor_owning_controller_process's chain of caller will exit if it fails. --- src/or/config.c | 5 +---- src/or/control.c | 20 ++++++++++---------- src/or/control.h | 2 +- 3 files changed, 12 insertions(+), 15 deletions(-) (limited to 'src/or') diff --git a/src/or/config.c b/src/or/config.c index b2bc9f3e9..0d1c37f6b 100644 --- a/src/or/config.c +++ b/src/or/config.c @@ -1232,10 +1232,7 @@ options_act(or_options_t *old_options) return -1; } - if (monitor_owning_controller_process(options->OwningControllerProcess)) { - log_warn(LD_CONFIG, "Error monitoring owning controller process"); - return -1; - } + monitor_owning_controller_process(options->OwningControllerProcess); /* reload keys as needed for rendezvous services. */ if (rend_service_load_keys()<0) { diff --git a/src/or/control.c b/src/or/control.c index 3a9690443..67e8b00d1 100644 --- a/src/or/control.c +++ b/src/or/control.c @@ -3815,8 +3815,8 @@ owning_controller_procmon_cb(void *unused) } /** Set process_spec as Tor's owning controller process. - * Return 0 on success, -1 on failure. */ -int + * Exit on failure. */ +void monitor_owning_controller_process(const char *process_spec) { const char *msg; @@ -3829,7 +3829,7 @@ monitor_owning_controller_process(const char *process_spec) owning_controller_process_spec)) { /* Same process -- return now, instead of disposing of and * recreating the process-termination monitor. */ - return 0; + return; } /* We are currently owned by a process, and we should no longer be @@ -3845,7 +3845,7 @@ monitor_owning_controller_process(const char *process_spec) (owning_controller_process_monitor == NULL)); if (process_spec == NULL) - return 0; + return; owning_controller_process_spec = tor_strdup(process_spec); owning_controller_process_monitor = @@ -3856,13 +3856,13 @@ monitor_owning_controller_process(const char *process_spec) &msg); if (owning_controller_process_monitor == NULL) { - log_warn(LD_CONTROL, "Couldn't create process-termination monitor for " - "owning controller: %s", - msg); - return -1; + log_err(LD_BUG, "Couldn't create process-termination monitor for " + "owning controller: %s. Exiting.", + msg); + owning_controller_process_spec = NULL; + tor_cleanup(); + exit(0); } - - return 0; } /** Convert the name of a bootstrapping phase s into strings diff --git a/src/or/control.h b/src/or/control.h index 81c23010d..a83e3747e 100644 --- a/src/or/control.h +++ b/src/or/control.h @@ -70,7 +70,7 @@ smartlist_t *decode_hashed_passwords(config_line_t *passwords); void disable_control_logging(void); void enable_control_logging(void); -int monitor_owning_controller_process(const char *process_spec); +void monitor_owning_controller_process(const char *process_spec); void control_event_bootstrap(bootstrap_status_t status, int progress); void control_event_bootstrap_problem(const char *warn, int reason); -- cgit v1.2.3 From 90f810801e92e8ee5d0b1341172f83e844af56c8 Mon Sep 17 00:00:00 2001 From: Robert Ransom Date: Wed, 18 May 2011 04:13:21 -0700 Subject: Fix trailing asterisk in the output of "GETINFO info/names" --- src/or/control.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/or') diff --git a/src/or/control.c b/src/or/control.c index 67e8b00d1..f7ff92ab3 100644 --- a/src/or/control.c +++ b/src/or/control.c @@ -1907,8 +1907,8 @@ static const getinfo_item_t getinfo_items[] = { "v2 networkstatus docs as retrieved from a DirPort."), ITEM("dir/status-vote/current/consensus", dir, "v3 Networkstatus consensus as retrieved from a DirPort."), - PREFIX("exit-policy/default", policies, - "The default value appended to the configured exit policy."), + ITEM("exit-policy/default", policies, + "The default value appended to the configured exit policy."), PREFIX("ip-to-country/", geoip, "Perform a GEOIP lookup"), { NULL, NULL, NULL, 0 } }; -- cgit v1.2.3 From 36afdebe1ac08fe02c938a73270bd2f11999d677 Mon Sep 17 00:00:00 2001 From: Robert Ransom Date: Wed, 18 May 2011 04:33:48 -0700 Subject: Add an XXX --- src/or/control.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'src/or') diff --git a/src/or/control.c b/src/or/control.c index f7ff92ab3..47e708182 100644 --- a/src/or/control.c +++ b/src/or/control.c @@ -2894,6 +2894,9 @@ connection_control_process_inbuf(control_connection_t *conn) return 0; } + /* XXXX Why is this not implemented as a table like the GETINFO + * items are? Even handling the plus signs at the beginnings of + * commands wouldn't be very hard with proper macros. */ cmd_data_len = (uint32_t)data_len; if (!strcasecmp(conn->incoming_cmd, "SETCONF")) { if (handle_control_setconf(conn, cmd_data_len, args)) -- cgit v1.2.3 From 86aeb152cab3d0c9d5d8b301e5eb5e3afe497ea9 Mon Sep 17 00:00:00 2001 From: Robert Ransom Date: Wed, 18 May 2011 04:35:20 -0700 Subject: Fix comment typo --- src/or/or.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/or') diff --git a/src/or/or.h b/src/or/or.h index 546c38a9a..52da63a94 100644 --- a/src/or/or.h +++ b/src/or/or.h @@ -1009,7 +1009,7 @@ typedef struct connection_t { /* XXXX023 move this field, and all the listener-only fields (just socket_family, I think), into a new listener_connection_t subtype. */ /** If the connection is a CONN_TYPE_AP_DNS_LISTENER, this field points - * to the evdns_server_port is uses to listen to and answer connections. */ + * to the evdns_server_port it uses to listen to and answer connections. */ struct evdns_server_port *dns_server_port; /** Unique ID for measuring tunneled network status requests. */ -- cgit v1.2.3 From 338a0266101e3addecbaf5771f62a860244896b3 Mon Sep 17 00:00:00 2001 From: Robert Ransom Date: Thu, 19 May 2011 16:27:51 -0700 Subject: Split control connection cleanup out of connection_free --- src/or/connection.c | 3 +-- src/or/control.c | 10 ++++++++++ src/or/control.h | 2 ++ 3 files changed, 13 insertions(+), 2 deletions(-) (limited to 'src/or') diff --git a/src/or/connection.c b/src/or/connection.c index fc2097f9a..24ab593fe 100644 --- a/src/or/connection.c +++ b/src/or/connection.c @@ -479,8 +479,7 @@ connection_free(connection_t *conn) } } if (conn->type == CONN_TYPE_CONTROL) { - TO_CONTROL_CONN(conn)->event_mask = 0; - control_update_global_event_mask(); + connection_control_closed(TO_CONTROL_CONN(conn)); } connection_unregister_events(conn); _connection_free(conn); diff --git a/src/or/control.c b/src/or/control.c index 47e708182..0ddbee99c 100644 --- a/src/or/control.c +++ b/src/or/control.c @@ -2739,6 +2739,16 @@ connection_control_reached_eof(control_connection_t *conn) return 0; } +/** Called when conn is being freed. */ +void +connection_control_closed(control_connection_t *conn) +{ + tor_assert(conn); + + conn->event_mask = 0; + control_update_global_event_mask(); +} + /** Return true iff cmd is allowable (or at least forgivable) at this * stage of the protocol. */ static int diff --git a/src/or/control.h b/src/or/control.h index a83e3747e..6694c9643 100644 --- a/src/or/control.h +++ b/src/or/control.h @@ -25,6 +25,8 @@ void control_adjust_event_log_severity(void); int connection_control_finished_flushing(control_connection_t *conn); int connection_control_reached_eof(control_connection_t *conn); +void connection_control_closed(control_connection_t *conn); + int connection_control_process_inbuf(control_connection_t *conn); #define EVENT_AUTHDIR_NEWDESCS 0x000D -- cgit v1.2.3 From bb860cedb29be0d95740bcf50577ae96bf666a18 Mon Sep 17 00:00:00 2001 From: Robert Ransom Date: Thu, 19 May 2011 16:34:40 -0700 Subject: Implement TAKEOWNERSHIP command --- src/or/control.c | 44 +++++++++++++++++++++++++++++++++++++++++++- src/or/or.h | 3 +++ 2 files changed, 46 insertions(+), 1 deletion(-) (limited to 'src/or') diff --git a/src/or/control.c b/src/or/control.c index 0ddbee99c..b6f802d76 100644 --- a/src/or/control.c +++ b/src/or/control.c @@ -1230,6 +1230,26 @@ handle_control_signal(control_connection_t *conn, uint32_t len, return 0; } +/** Called when we get a TAKEOWNERSHIP command. Mark this connection + * as an owning connection, so that we will exit if the connection + * closes. */ +static int +handle_control_takeownership(control_connection_t *conn, uint32_t len, + const char *body) +{ + (void)len; + (void)body; + + conn->is_owning_control_connection = 1; + + log_info(LD_CONTROL, "Control connection %d has taken ownership of this " + "Tor instance.", + (int)(conn->_base.s)); + + send_control_done(conn); + return 0; +} + /** Called when we get a MAPADDRESS command; try to bind all listed addresses, * and report success or failure. */ static int @@ -2747,6 +2767,25 @@ connection_control_closed(control_connection_t *conn) conn->event_mask = 0; control_update_global_event_mask(); + + if (conn->is_owning_control_connection) { + int shutdown_slowly = server_mode(get_options()); + + log_notice(LD_CONTROL, "Owning controller connection has closed -- %s.", + shutdown_slowly ? "shutting down" : "exiting now"); + + /* XXXX This chunk of code should be a separate function, called + * here, in owning_controller_procmon_cb, and by + * process_signal(SIGINT). */ + + if (!shutdown_slowly) { + tor_cleanup(); + exit(0); + } + /* XXXX This will close all listening sockets except control-port + * listeners. Perhaps we should close those too. */ + hibernate_begin_shutdown(); + } } /** Return true iff cmd is allowable (or at least forgivable) at this @@ -2932,6 +2971,9 @@ connection_control_process_inbuf(control_connection_t *conn) } else if (!strcasecmp(conn->incoming_cmd, "SIGNAL")) { if (handle_control_signal(conn, cmd_data_len, args)) return -1; + } else if (!strcasecmp(conn->incoming_cmd, "TAKEOWNERSHIP")) { + if (handle_control_takeownership(conn, cmd_data_len, args)) + return -1; } else if (!strcasecmp(conn->incoming_cmd, "MAPADDRESS")) { if (handle_control_mapaddress(conn, cmd_data_len, args)) return -1; @@ -3816,7 +3858,7 @@ owning_controller_procmon_cb(void *unused) shutdown_slowly ? "shutting down" : "exiting now"); /* XXXX This chunk of code should be a separate function, called - * here and by process_signal(SIGINT). */ + * here, in connection_control_closed, and by process_signal(SIGINT). */ if (!shutdown_slowly) { tor_cleanup(); diff --git a/src/or/or.h b/src/or/or.h index 52da63a94..cbfe36259 100644 --- a/src/or/or.h +++ b/src/or/or.h @@ -1242,6 +1242,9 @@ typedef struct control_connection_t { /** True if we have sent a protocolinfo reply on this connection. */ unsigned int have_sent_protocolinfo:1; + /** True if we have received a takeownership command on this + * connection. */ + unsigned int is_owning_control_connection:1; /** Amount of space allocated in incoming_cmd. */ uint32_t incoming_cmd_len; -- cgit v1.2.3 From 7b34e3a9659a0f992dc43a568c2ea8af57e9c6d3 Mon Sep 17 00:00:00 2001 From: Robert Ransom Date: Fri, 20 May 2011 08:21:11 -0700 Subject: Split out owning-controller-loss shutdown code into a function --- src/or/control.c | 57 +++++++++++++++++++++++++------------------------------- 1 file changed, 25 insertions(+), 32 deletions(-) (limited to 'src/or') diff --git a/src/or/control.c b/src/or/control.c index b6f802d76..b7e90473b 100644 --- a/src/or/control.c +++ b/src/or/control.c @@ -2759,6 +2759,29 @@ connection_control_reached_eof(control_connection_t *conn) return 0; } +/** Shut down this Tor instance in the same way that SIGINT would, but + * with a log message appropriate for the loss of an owning controller. */ +static void +lost_owning_controller(const char *owner_type, const char *loss_manner) +{ + int shutdown_slowly = server_mode(get_options()); + + log_notice(LD_CONTROL, "Owning controller %s has %s -- %s.", + owner_type, loss_manner, + shutdown_slowly ? "shutting down" : "exiting now"); + + /* XXXX Perhaps this chunk of code should be a separate function, + * called here and by process_signal(SIGINT). */ + + if (!shutdown_slowly) { + tor_cleanup(); + exit(0); + } + /* XXXX This will close all listening sockets except control-port + * listeners. Perhaps we should close those too. */ + hibernate_begin_shutdown(); +} + /** Called when conn is being freed. */ void connection_control_closed(control_connection_t *conn) @@ -2769,22 +2792,7 @@ connection_control_closed(control_connection_t *conn) control_update_global_event_mask(); if (conn->is_owning_control_connection) { - int shutdown_slowly = server_mode(get_options()); - - log_notice(LD_CONTROL, "Owning controller connection has closed -- %s.", - shutdown_slowly ? "shutting down" : "exiting now"); - - /* XXXX This chunk of code should be a separate function, called - * here, in owning_controller_procmon_cb, and by - * process_signal(SIGINT). */ - - if (!shutdown_slowly) { - tor_cleanup(); - exit(0); - } - /* XXXX This will close all listening sockets except control-port - * listeners. Perhaps we should close those too. */ - hibernate_begin_shutdown(); + lost_owning_controller("connection", "closed"); } } @@ -3849,24 +3857,9 @@ static tor_process_monitor_t *owning_controller_process_monitor = NULL; static void owning_controller_procmon_cb(void *unused) { - int shutdown_slowly = server_mode(get_options()); - (void)unused; - log_notice(LD_CONTROL, "Owning controller process has vanished -- " - "%s.", - shutdown_slowly ? "shutting down" : "exiting now"); - - /* XXXX This chunk of code should be a separate function, called - * here, in connection_control_closed, and by process_signal(SIGINT). */ - - if (!shutdown_slowly) { - tor_cleanup(); - exit(0); - } - /* XXXX This will close all listening sockets except control-port - * listeners. Perhaps we should close those too. */ - hibernate_begin_shutdown(); + lost_owning_controller("process", "vanished"); } /** Set process_spec as Tor's owning controller process. -- cgit v1.2.3 From 6b54edef4f93748e8247067242aad7158e82a148 Mon Sep 17 00:00:00 2001 From: Roger Dingledine Date: Sat, 21 May 2011 18:34:55 -0400 Subject: finish a comment nickm started in 8ebceeb3 --- src/or/router.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src/or') diff --git a/src/or/router.c b/src/or/router.c index 0beb960f6..777441aff 100644 --- a/src/or/router.c +++ b/src/or/router.c @@ -503,7 +503,8 @@ init_keys(void) if (!key_lock) key_lock = tor_mutex_new(); - /* There are a couple of paths that put us here before */ + /* There are a couple of paths that put us here before we've asked + * openssl to initialize itself. */ if (crypto_global_init(get_options()->HardwareAccel, get_options()->AccelName, get_options()->AccelDir)) { -- cgit v1.2.3 From 1ba1bdee4bd8f3c00e603fe9b0fd2f14eeb60466 Mon Sep 17 00:00:00 2001 From: Roger Dingledine Date: Sat, 21 May 2011 18:55:23 -0400 Subject: naked constants are ugly --- src/or/router.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/or') diff --git a/src/or/router.c b/src/or/router.c index 777441aff..184715b75 100644 --- a/src/or/router.c +++ b/src/or/router.c @@ -490,8 +490,8 @@ init_keys(void) char fingerprint_line[MAX_NICKNAME_LEN+FINGERPRINT_LEN+3]; const char *mydesc; crypto_pk_env_t *prkey; - char digest[20]; - char v3_digest[20]; + char digest[DIGEST_LEN]; + char v3_digest[DIGEST_LEN]; char *cp; or_options_t *options = get_options(); authority_type_t type; -- cgit v1.2.3