diff options
author | George Kadianakis <desnacked@gmail.com> | 2011-08-07 18:05:40 +0200 |
---|---|---|
committer | George Kadianakis <desnacked@gmail.com> | 2011-08-07 18:05:40 +0200 |
commit | 941709ee50654b9ef59836fadbd8c4e7029c9fc1 (patch) | |
tree | a26ba33202de41b41c5bcf2e96d070e72484c6af /src/or | |
parent | cfb473ed348063e1f1abd709ac313f14d33cadf5 (diff) | |
download | tor-941709ee50654b9ef59836fadbd8c4e7029c9fc1.tar tor-941709ee50654b9ef59836fadbd8c4e7029c9fc1.tar.gz |
Server transport proxies should bind on the same port each time, if possible.
Diffstat (limited to 'src/or')
-rw-r--r-- | src/or/circuitbuild.c | 2 | ||||
-rw-r--r-- | src/or/config.c | 235 | ||||
-rw-r--r-- | src/or/config.h | 4 | ||||
-rw-r--r-- | src/or/or.h | 2 | ||||
-rw-r--r-- | src/or/transports.c | 78 | ||||
-rw-r--r-- | src/or/transports.h | 4 |
6 files changed, 276 insertions, 49 deletions
diff --git a/src/or/circuitbuild.c b/src/or/circuitbuild.c index 3dba83ba3..fe57070ac 100644 --- a/src/or/circuitbuild.c +++ b/src/or/circuitbuild.c @@ -4610,7 +4610,7 @@ transport_get_by_name(const char *name) if (!transport_list) return NULL; - + SMARTLIST_FOREACH_BEGIN(transport_list, const transport_t *, transport) { if (!strcmp(transport->name, name)) return transport; diff --git a/src/or/config.c b/src/or/config.c index 02925f39b..dced47c03 100644 --- a/src/or/config.c +++ b/src/or/config.c @@ -473,6 +473,9 @@ static config_var_t _state_vars[] = { VAR("EntryGuardAddedBy", LINELIST_S, EntryGuards, NULL), V(EntryGuards, LINELIST_V, NULL), + VAR("TransportProxy", LINELIST_S, TransportProxies, NULL), + V(TransportProxies, LINELIST_V, NULL), + V(BWHistoryReadEnds, ISOTIME, NULL), V(BWHistoryReadInterval, UINT, "900"), V(BWHistoryReadValues, CSV, ""), @@ -499,7 +502,6 @@ static config_var_t _state_vars[] = { V(CircuitBuildAbandonedCount, UINT, "0"), VAR("CircuitBuildTimeBin", LINELIST_S, BuildtimeHistogram, NULL), VAR("BuildtimeHistogram", LINELIST_V, BuildtimeHistogram, NULL), - { NULL, CONFIG_TYPE_OBSOLETE, 0, NULL } }; @@ -1212,29 +1214,6 @@ options_act(or_options_t *old_options) if (consider_adding_dir_authorities(options, old_options) < 0) return -1; - clear_transport_list(); - if (options->ClientTransportPlugin) { - for (cl = options->ClientTransportPlugin; cl; cl = cl->next) { - if (parse_client_transport_line(cl->value, 0)<0) { - log_warn(LD_BUG, - "Previously validated ClientTransportPlugin line " - "could not be added!"); - return -1; - } - } - } - - if (options->ServerTransportPlugin) { - for (cl = options->ServerTransportPlugin; cl; cl = cl->next) { - if (parse_server_transport_line(cl->value, 0)<0) { - log_warn(LD_BUG, - "Previously validated ServerTransportPlugin line " - "could not be added!"); - return -1; - } - } - } - if (options->Bridges) { mark_bridge_list(); for (cl = options->Bridges; cl; cl = cl->next) { @@ -1271,6 +1250,30 @@ options_act(or_options_t *old_options) rep_hist_load_mtbf_data(time(NULL)); } + + clear_transport_list(); + if (options->ClientTransportPlugin) { + for (cl = options->ClientTransportPlugin; cl; cl = cl->next) { + if (parse_client_transport_line(cl->value, 0)<0) { + log_warn(LD_BUG, + "Previously validated ClientTransportPlugin line " + "could not be added!"); + return -1; + } + } + } + + if (options->ServerTransportPlugin) { + for (cl = options->ServerTransportPlugin; cl; cl = cl->next) { + if (parse_server_transport_line(cl->value, 0)<0) { + log_warn(LD_BUG, + "Previously validated ServerTransportPlugin line " + "could not be added!"); + return -1; + } + } + } + /* Bail out at this point if we're not going to be a client or server: * we want to not fork, and to log stuff to stderr. */ if (!running_tor) @@ -5465,6 +5468,74 @@ options_get_datadir_fname2_suffix(or_options_t *options, return fname; } +/** Return true if <b>line</b> is a valid state TransportProxy line. + * Return false otherwise. */ +static int +state_transport_line_is_valid(char *line) +{ + smartlist_t *items = NULL; + char *addrport=NULL; + tor_addr_t addr; + uint16_t port = 0; + int r; + + items = smartlist_create(); + smartlist_split_string(items, line, NULL, + SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, -1); + + if (smartlist_len(items) != 2) { + log_warn(LD_CONFIG, "state: Not enough arguments in TransportProxy line."); + goto err; + } + + addrport = smartlist_get(items, 1); + if (tor_addr_port_parse(addrport, &addr, &port) < 0) { + log_warn(LD_CONFIG, "state: Could not parse addrport."); + goto err; + } + + if (!port) { + log_warn(LD_CONFIG, "state: Transport line did not contain port."); + goto err; + } + + r = 1; + goto done; + + err: + r = 0; + + done: + SMARTLIST_FOREACH(items, char*, s, tor_free(s)); + smartlist_free(items); + return r; +} + +/** Return 0 if all TransportProxy lines in <b>state</b> are well + * formed. Otherwise, return -1. */ +static int +validate_transports_in_state(or_state_t *state) +{ + int broken = 0; + + config_var_t *var = config_find_option(&state_format,"TransportProxies"); + if (!var) + return 0; + + config_line_t **value = STRUCT_VAR_P(state, var->var_offset); + config_line_t *search = NULL; + + for (search = *value ; search ; search = search->next) { + if (!state_transport_line_is_valid(search->value)<0) + broken = 1; + } + + if (broken) + log_warn(LD_CONFIG, "state: State file seems to be broken."); + + return 0; +} + /** Return 0 if every setting in <b>state</b> is reasonable, and a * permissible transition from <b>old_state</b>. Else warn and return -1. * Should have no side effects, except for normalizing the contents of @@ -5483,6 +5554,9 @@ or_state_validate(or_state_t *old_state, or_state_t *state, if (entry_guards_parse_state(state, 0, msg)<0) return -1; + if (validate_transports_in_state(state)<0) + return -1; + return 0; } @@ -5715,6 +5789,118 @@ or_state_save(time_t now) return 0; } +/** Return the config line for transport <b>transport</b> in the current state. + * Return NULL if there is no config line for <b>transport</b>. */ +static config_line_t * +get_transport_in_state_by_name(const char *transport) +{ + config_var_t *var = config_find_option(&state_format,"TransportProxies"); + if (!var) + return NULL; + + config_line_t **value = STRUCT_VAR_P(get_or_state(), var->var_offset); + config_line_t *search = *value; + + while (search) { + if (!strcmpstart(search->value, transport)) + return search; + + search = search->next; + } + return NULL; +} + +/** Return string containing the address:port part of the + * TransportProxy <b>line</b> for transport <b>transport</b>. If the + * line is corrupted, return NULL. */ +const char * +get_transport_bindaddr(const char *line, const char *transport) +{ + if (strlen(line) < strlen(transport) + 2) + return NULL; + else + return (line+strlen(transport)+1); +} + +/** Return a string containing the address:port that <b>transport</b> + * should use. */ +const char * +get_bindaddr_for_transport(const char *transport) +{ + static const char default_addrport[] = "127.0.0.1:0"; + const char *bindaddr = NULL; + + config_line_t *line = get_transport_in_state_by_name(transport); + if (!line) + return default_addrport; + + bindaddr = get_transport_bindaddr(line->value, transport); + + return bindaddr ? bindaddr : default_addrport; +} + +/** Save <b>transport</b> listening at <b>addr</b>:<b>port</b> to + * state */ +void +save_transport_to_state(const char *transport, + tor_addr_t *addr, uint16_t port) +{ + or_state_t *state = get_or_state(); + + char *transport_addrport=NULL; + + /** find where to write on the state */ + config_line_t **next, *line; + + /* see if this transport is already stored in state */ + config_line_t *transport_line = + get_transport_in_state_by_name(transport); + + if (transport_line) { /* if transport_exists_in_state() */ + const char *prev_bindaddr = /* get addrport stored in state */ + get_transport_bindaddr(transport_line->value, transport); + tor_asprintf(&transport_addrport, "%s:%d", fmt_addr(addr), (int)port); + + /* if transport in state has the same address as this one, life is good */ + if (!strcmp(prev_bindaddr, transport_addrport)) { + log_warn(LD_CONFIG, "Transport seems to have spawned on its usual address:port."); + goto done; + } else { /* addrport in state is different than the one we got */ + log_warn(LD_CONFIG, "Transport seems to have spawned on different address:port." + "Let's update the state file with the new address:port"); + tor_free(transport_line->value); /* free the old line */ + tor_asprintf(&transport_line->value, "%s %s:%d", transport, + fmt_addr(addr), + (int) port); /* replace old addrport line with new line */ + } + } else { /* never seen this one before; save it in state for next time */ + log_warn(LD_CONFIG, "It's the first time we see this transport. " + "Let's save its address:port"); + next = &state->TransportProxies; + /* find the last TransportProxy line in the state and point 'next' + right after it */ + line = state->TransportProxies; + while (line) { + next = &(line->next); + line = line->next; + } + + /* allocate space for the new line and fill it in */ + *next = line = tor_malloc_zero(sizeof(config_line_t)); + line->key = tor_strdup("TransportProxy"); + tor_asprintf(&line->value, "%s %s:%d", transport, + fmt_addr(addr), (int) port); + + next = &(line->next); + } + + if (!get_options()->AvoidDiskWrites) + or_state_mark_dirty(state, 0); + + done: + tor_free(transport_addrport); +} + /** Given a file name check to see whether the file exists but has not been * modified for a very long time. If so, remove it. */ void @@ -5782,4 +5968,3 @@ getinfo_helper_config(control_connection_t *conn, } return 0; } - diff --git a/src/or/config.h b/src/or/config.h index 49f7e25be..dc3a82874 100644 --- a/src/or/config.h +++ b/src/or/config.h @@ -63,6 +63,10 @@ or_state_t *get_or_state(void); int did_last_state_file_write_fail(void); int or_state_save(time_t now); +void save_transport_to_state(const char *transport_name, + tor_addr_t *addr, uint16_t port); +const char * get_bindaddr_for_transport(const char *transport); + int options_need_geoip_info(or_options_t *options, const char **reason_out); int getinfo_helper_config(control_connection_t *conn, const char *question, char **answer, diff --git a/src/or/or.h b/src/or/or.h index 8bcfc82ce..d07422f27 100644 --- a/src/or/or.h +++ b/src/or/or.h @@ -3139,6 +3139,8 @@ typedef struct { /** A list of Entry Guard-related configuration lines. */ config_line_t *EntryGuards; + config_line_t *TransportProxies; + /** These fields hold information on the history of bandwidth usage for * servers. The "Ends" fields hold the time when we last updated the * bandwidth usage. The "Interval" fields hold the granularity, in seconds, diff --git a/src/or/transports.c b/src/or/transports.c index 21d76f80d..b96792f54 100644 --- a/src/or/transports.c +++ b/src/or/transports.c @@ -19,10 +19,11 @@ static INLINE int proxy_configuration_finished(managed_proxy_t *mp); static void managed_proxy_destroy(managed_proxy_t *mp, int also_free_transports); -static void register_proxy_transports(managed_proxy_t *mp); static void handle_finished_proxy(managed_proxy_t *mp); static void configure_proxy(managed_proxy_t *mp); +static void register_server_proxy(managed_proxy_t *mp); + static void parse_method_error(char *line, int is_server_method); #define parse_server_method_error(l) parse_method_error(l, 1) #define parse_client_method_error(l) parse_method_error(l, 0) @@ -119,6 +120,7 @@ pt_managed_launch_proxy(const char *method, mp->conf_state = PT_PROTO_INFANT; mp->stdout = stdout_read; mp->transports = smartlist_create(); + mp->is_server = is_server; /* register the managed proxy */ if (!unconfigured_proxy_list) @@ -179,6 +181,42 @@ configure_proxy(managed_proxy_t *mp) } } +/** Register server managed proxy <b>mp</b> transports to state */ +static void +register_server_proxy(managed_proxy_t *mp) +{ + if (mp->is_server) { + SMARTLIST_FOREACH_BEGIN(mp->transports, transport_t *, t) { + save_transport_to_state(t->name,&t->addr,t->port); /* pass tor_addr_t? */ + } SMARTLIST_FOREACH_END(t); + } +} + +/** Register all the transports supported by client managed proxy + * <b>mp</b> to the bridge subsystem. */ +static void +register_client_proxy(managed_proxy_t *mp) +{ + SMARTLIST_FOREACH_BEGIN(mp->transports, transport_t *, t) { + if (transport_add(t)<0) { + log_warn(LD_GENERAL, "Could not add transport %s. Skipping.", t->name); + transport_free(t); + } else { + log_warn(LD_GENERAL, "Succesfully registered transport %s", t->name); + } + } SMARTLIST_FOREACH_END(t); +} + +/** Register the transports of managed proxy <b>mp</b>. */ +static INLINE void +register_proxy(managed_proxy_t *mp) +{ + if (mp->is_server) + register_server_proxy(mp); + else + register_client_proxy(mp); +} + /** Handle a configured or broken managed proxy <b>mp</b>. */ static void handle_finished_proxy(managed_proxy_t *mp) @@ -188,7 +226,7 @@ handle_finished_proxy(managed_proxy_t *mp) managed_proxy_destroy(mp, 1); /* destroy it and all its transports */ break; case PT_PROTO_CONFIGURED: /* if configured correctly: */ - register_proxy_transports(mp); /* register all its transports, */ + register_proxy(mp); /* register transports */ mp->conf_state = PT_PROTO_COMPLETED; /* mark it as completed, */ managed_proxy_destroy(mp, 0); /* destroy the managed proxy struct, keeping the transports intact */ @@ -203,20 +241,6 @@ handle_finished_proxy(managed_proxy_t *mp) tor_assert(n_unconfigured_proxies >= 0); } -/** Register all the transports supported by managed proxy <b>mp</b>. */ -static void -register_proxy_transports(managed_proxy_t *mp) -{ - SMARTLIST_FOREACH_BEGIN(mp->transports, transport_t *, t) { - if (transport_add(t)<0) { - log_warn(LD_GENERAL, "Could not add transport %s. Skipping.", t->name); - transport_free(t); - } else { - log_warn(LD_GENERAL, "Succesfully registered transport %s", t->name); - } - } SMARTLIST_FOREACH_END(t); -} - /** Free memory allocated by managed proxy <b>mp</b>. * If <b>also_free_transports</b> is set, also free the transports * associated with this managed proxy. */ @@ -254,8 +278,6 @@ proxy_configuration_finished(managed_proxy_t *mp) void handle_proxy_line(char *line, managed_proxy_t *mp) { - log_debug(LD_CONFIG, "Judging line: %s\n", line); - if (strlen(line) < SMALLEST_MANAGED_LINE_SIZE) { log_warn(LD_GENERAL, "Managed proxy configuration line is too small. " "Discarding"); @@ -401,7 +423,8 @@ parse_method_error(char *line, int is_server) line+strlen(error)+1); } -/** Parses an SMETHOD <b>line</b>. */ +/** Parses an SMETHOD <b>line</b> and if well-formed it registers the + * new transport in <b>mp</b>. */ int parse_smethod_line(char *line, managed_proxy_t *mp) { @@ -414,6 +437,8 @@ parse_smethod_line(char *line, managed_proxy_t *mp) tor_addr_t addr; uint16_t port = 0; + transport_t *transport=NULL; + items = smartlist_create(); smartlist_split_string(items, line, NULL, SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, -1); @@ -440,6 +465,12 @@ parse_smethod_line(char *line, managed_proxy_t *mp) goto err; } + transport = transport_create(&addr, port, method_name, PROXY_NONE); + if (!transport) + goto err; + + smartlist_add(mp->transports, transport); + /* For now, notify the user so that he knows where the server transport is listening. */ log_warn(LD_CONFIG, "Server transport %s at %s:%d.", @@ -553,23 +584,26 @@ set_environ(char ***envp, const char *method, int is_server) *envp = tor_malloc(sizeof(char*)*(n_envs+1)); tmp = *envp; + state_loc = get_datadir_fname("pt_state/"); + /* these should all be customizable */ tor_asprintf(tmp++, "HOME=%s", getenv("HOME")); tor_asprintf(tmp++, "PATH=%s", getenv("PATH")); - state_loc = get_datadir_fname("pt_state/"); tor_asprintf(tmp++, "TOR_PT_STATE_LOCATION=%s", state_loc); - tor_free(state_loc); tor_asprintf(tmp++, "TOR_PT_MANAGED_TRANSPORT_VER=1"); /* temp */ if (is_server) { /* ASN check for ORPort values, should we be here if it's 0? */ tor_asprintf(tmp++, "TOR_PT_ORPORT=127.0.0.1:%d", options->ORPort); /* temp */ - tor_asprintf(tmp++, "TOR_PT_SERVER_BINDADDR=127.0.0.1:0"); + tor_asprintf(tmp++, "TOR_PT_SERVER_BINDADDR=%s", + get_bindaddr_for_transport(method)); tor_asprintf(tmp++, "TOR_PT_SERVER_TRANSPORTS=%s", method); tor_asprintf(tmp++, "TOR_PT_EXTENDED_SERVER_PORT=127.0.0.1:4200"); /* temp*/ } else { tor_asprintf(tmp++, "TOR_PT_CLIENT_TRANSPORTS=%s", method); } *tmp = NULL; + + tor_free(state_loc); } /* ASN is this too ugly/stupid? */ diff --git a/src/or/transports.h b/src/or/transports.h index 17a68030d..8bd79fe64 100644 --- a/src/or/transports.h +++ b/src/or/transports.h @@ -40,10 +40,12 @@ typedef struct { enum pt_proto_state conf_state; /* the current configuration state */ int conf_protocol; /* the configuration protocol version used */ + int is_server; /* is it a server proxy? */ + FILE *stdout; /* a stream to its stdout (closed in managed_proxy_destroy()) */ - smartlist_t *transports; /* list of transports this proxy spawns */ + smartlist_t *transports; /* list of transport_t this proxy spawns */ } managed_proxy_t; int parse_cmethod_line(char *line, managed_proxy_t *mp); |