From f88c3038697b00f50b2da12f46fc76ee0e20d646 Mon Sep 17 00:00:00 2001 From: George Kadianakis Date: Tue, 30 Oct 2012 04:17:13 +0200 Subject: Add a torrc option to specify the bind address of managed proxies. --- src/or/config.c | 101 +++++++++++++++++++++++++++++++++++++++++++++++++++++ src/or/config.h | 2 ++ src/or/or.h | 3 ++ src/or/statefile.c | 11 +++++- 4 files changed, 116 insertions(+), 1 deletion(-) (limited to 'src/or') diff --git a/src/or/config.c b/src/or/config.c index 6eace9f00..822bc629b 100644 --- a/src/or/config.c +++ b/src/or/config.c @@ -273,6 +273,7 @@ static config_var_t option_vars_[] = { V(HTTPSProxy, STRING, NULL), V(HTTPSProxyAuthenticator, STRING, NULL), VAR("ServerTransportPlugin", LINELIST, ServerTransportPlugin, NULL), + V(ServerTransportListenAddr, LINELIST, NULL), V(Socks4Proxy, STRING, NULL), V(Socks5Proxy, STRING, NULL), V(Socks5ProxyUsername, STRING, NULL), @@ -462,6 +463,9 @@ static int parse_bridge_line(const char *line, int validate_only); static int parse_client_transport_line(const char *line, int validate_only); static int parse_server_transport_line(const char *line, int validate_only); +static char *get_bindaddr_from_transport_listen_line(const char *line, + const char *transport); + static int parse_dir_server_line(const char *line, dirinfo_type_t required_type, int validate_only); @@ -2879,6 +2883,22 @@ options_validate(or_options_t *old_options, or_options_t *options, escaped(options->ServerTransportPlugin->value)); } + for (cl = options->ServerTransportListenAddr; cl; cl = cl->next) { + /** If get_bindaddr_from_transport_listen_line() fails with + 'transport' being NULL, it means that something went wrong + while parsing the ServerTransportListenAddr line. */ + char *bindaddr = get_bindaddr_from_transport_listen_line(cl->value, NULL); + if (!bindaddr) + REJECT("ServerTransportListenAddr did not parse. See logs for details."); + tor_free(bindaddr); + } + + if (options->ServerTransportListenAddr && !options->ServerTransportPlugin) { + log_notice(LD_GENERAL, "You need at least a single managed-proxy to " + "specify a transport listen address. The " + "ServerTransportListenAddr line will be ignored."); + } + if (options->ConstrainedSockets) { /* If the user wants to constrain socket buffer use, make sure the desired * limit is between MIN|MAX_TCPSOCK_BUFFER in k increments. */ @@ -4117,6 +4137,87 @@ parse_client_transport_line(const char *line, int validate_only) return r; } +/** Given a ServerTransportListenAddr line, return its + * string. Return NULL if the line was not + * well-formed. + * + * If transport is set, return NULL if the line is not + * referring to transport. + * + * The returned string is allocated on the heap and it's the + * responsibility of the caller to free it. */ +static char * +get_bindaddr_from_transport_listen_line(const char *line,const char *transport) +{ + smartlist_t *items = NULL; + const char *parsed_transport = NULL; + char *addrport = NULL; + char *addr = NULL; + uint16_t port = 0; + + items = smartlist_new(); + smartlist_split_string(items, line, NULL, + SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, -1); + + if (smartlist_len(items) < 2) { + log_warn(LD_CONFIG,"Too few arguments on ServerTransportListenAddr line."); + goto err; + } + + parsed_transport = smartlist_get(items, 0); + addrport = tor_strdup(smartlist_get(items, 1)); + + /* If 'transport' is given, check if it matches the one on the line */ + if (transport && strcmp(transport, parsed_transport)) + goto err; + + /* Validate addrport */ + if (tor_addr_port_split(LOG_WARN, addrport, &addr, &port)<0) { + log_warn(LD_CONFIG, "Error parsing ServerTransportListenAddr " + "address '%s'", addrport); + goto err; + } + + if (!port) { + log_warn(LD_CONFIG, + "ServerTransportListenAddr address '%s' has no port.", addrport); + goto err; + } + + goto done; + + err: + tor_free(addrport); + addrport = NULL; + + done: + SMARTLIST_FOREACH(items, char*, s, tor_free(s)); + smartlist_free(items); + tor_free(addr); + + return addrport; +} + +/** Given the name of a pluggable transport in transport, check + * the configuration file to see if the user has explicitly asked for + * it to listen on a specific port. Return a string if + * so, otherwise NULL. */ +char * +get_transport_bindaddr_from_config(const char *transport) +{ + config_line_t *cl; + const or_options_t *options = get_options(); + + for (cl = options->ServerTransportListenAddr; cl; cl = cl->next) { + char *bindaddr = + get_bindaddr_from_transport_listen_line(cl->value, transport); + if (bindaddr) + return bindaddr; + } + + return NULL; +} + /** Read the contents of a ServerTransportPlugin line from * line. Return 0 if the line is well-formed, and -1 if it * isn't. diff --git a/src/or/config.h b/src/or/config.h index f3b28adb7..336685d07 100644 --- a/src/or/config.h +++ b/src/or/config.h @@ -82,6 +82,8 @@ const char *tor_get_digests(void); uint32_t get_effective_bwrate(const or_options_t *options); uint32_t get_effective_bwburst(const or_options_t *options); +char *get_transport_bindaddr_from_config(const char *transport); + #ifdef CONFIG_PRIVATE /* Used only by config.c and test.c */ or_options_t *options_new(void); diff --git a/src/or/or.h b/src/or/or.h index b59c079c4..82e847a5a 100644 --- a/src/or/or.h +++ b/src/or/or.h @@ -3218,6 +3218,9 @@ typedef struct { config_line_t *ServerTransportPlugin; /**< List of client transport plugins. */ + /** List of TCP/IP addresses that transports should listen at. */ + config_line_t *ServerTransportListenAddr; + int BridgeRelay; /**< Boolean: are we acting as a bridge relay? We make * this explicit so we can change how we behave in the * future. */ diff --git a/src/or/statefile.c b/src/or/statefile.c index beb9cf81b..704c4e535 100644 --- a/src/or/statefile.c +++ b/src/or/statefile.c @@ -517,8 +517,17 @@ get_stored_bindaddr_for_server_transport(const char *transport) { char *default_addrport = NULL; const char *stored_bindaddr = NULL; + config_line_t *line = NULL; + + { + /* See if the user explicitly asked for a specific listening + address for this transport. */ + char *conf_bindaddr = get_transport_bindaddr_from_config(transport); + if (conf_bindaddr) + return conf_bindaddr; + } - config_line_t *line = get_transport_in_state_by_name(transport); + line = get_transport_in_state_by_name(transport); if (!line) /* Found no references in state for this transport. */ goto no_bindaddr_found; -- cgit v1.2.3