tor  master
Macros | Functions
transports.c File Reference

Pluggable Transports related code. More...

#include "or.h"
#include "bridges.h"
#include "config.h"
#include "circuitbuild.h"
#include "transports.h"
#include "util.h"
#include "router.h"
#include "statefile.h"
#include "connection_or.h"
#include "ext_orport.h"
#include "control.h"
Include dependency graph for transports.c:

Macros

#define PT_PRIVATE
 
#define parse_server_method_error(l)   parse_method_error(l, 1)
 
#define parse_client_method_error(l)   parse_method_error(l, 0)
 
#define PROTO_ENV_ERROR   "ENV-ERROR"
 
#define PROTO_NEG_SUCCESS   "VERSION"
 
#define PROTO_NEG_FAIL   "VERSION-ERROR no-version"
 
#define PROTO_CMETHOD   "CMETHOD"
 
#define PROTO_SMETHOD   "SMETHOD"
 
#define PROTO_CMETHOD_ERROR   "CMETHOD-ERROR"
 
#define PROTO_SMETHOD_ERROR   "SMETHOD-ERROR"
 
#define PROTO_CMETHODS_DONE   "CMETHODS DONE"
 
#define PROTO_SMETHODS_DONE   "SMETHODS DONE"
 
#define PROTO_PROXY_DONE   "PROXY DONE"
 
#define PROTO_PROXY_ERROR   "PROXY-ERROR"
 
#define PROTO_VERSION_ONE   1
 

Functions

STATIC transport_ttransport_new (const tor_addr_t *addr, uint16_t port, const char *name, int socks_ver, const char *extra_info_args)
 
void transport_free_ (transport_t *transport)
 
void mark_transport_list (void)
 
void sweep_transport_list (void)
 
 MOCK_IMPL (transport_t *, transport_get_by_name,(const char *name))
 
 MOCK_IMPL (int, transport_add_from_config,(const tor_addr_t *addr, uint16_t port, const char *name, int socks_ver))
 
int pt_proxies_configuration_pending (void)
 
void pt_configure_remaining_proxies (void)
 
STATIC int configure_proxy (managed_proxy_t *mp)
 
STATIC void managed_proxy_destroy (managed_proxy_t *mp, int also_terminate_process)
 
STATIC char * get_pt_proxy_uri (void)
 
STATIC void handle_proxy_line (const char *line, managed_proxy_t *mp)
 
STATIC void parse_env_error (const char *line)
 
STATIC int parse_version (const char *line, managed_proxy_t *mp)
 
STATIC int parse_smethod_line (const char *line, managed_proxy_t *mp)
 
STATIC int parse_cmethod_line (const char *line, managed_proxy_t *mp)
 
STATIC void parse_proxy_error (const char *line)
 
STATIC char * get_transport_options_for_server_proxy (const managed_proxy_t *mp)
 
STATIC managed_proxy_t * managed_proxy_create (const smartlist_t *with_transport_list, char **proxy_argv, int is_server)
 
 MOCK_IMPL (void, pt_kickstart_proxy,(const smartlist_t *with_transport_list, char **proxy_argv, int is_server))
 
STATIC void free_execve_args (char **arg)
 
void pt_prepare_proxy_list_for_config_read (void)
 
smartlist_tget_transport_proxy_ports (void)
 
char * pt_get_extra_info_descriptor_string (void)
 
char * pt_stringify_socks_args (const smartlist_t *socks_args)
 
char * pt_get_socks_args_for_proxy_addrport (const tor_addr_t *addr, uint16_t port)
 
void sweep_proxy_list (void)
 
void pt_free_all (void)
 

Detailed Description

Pluggable Transports related code.

Each managed proxy is represented by a managed_proxy_t. Each managed proxy can support multiple transports. Each managed proxy gets configured through a multistep process.

::managed_proxy_list contains all the managed proxies this tor instance is supporting. In the ::managed_proxy_list there are ::unconfigured_proxies_n managed proxies that are still unconfigured.

In every run_scheduled_event() tick, we attempt to launch and then configure the unconfiged managed proxies, using the configuration protocol defined in the 180_pluggable_transport.txt proposal. A managed proxy might need several ticks to get fully configured.

When a managed proxy is fully configured, we register all its transports to the circuitbuild.c subsystem. At that point the transports are owned by the circuitbuild.c subsystem.

When a managed proxy fails to follow the 180 configuration protocol, it gets marked as broken and gets destroyed.

In a little more detail:

While we are serially parsing torrc, we store all the transports that a proxy should spawn in its transports_to_launch element.

When we finish reading the torrc, we spawn the managed proxy and expect {S,C}METHOD lines from its output. We add transports described by METHOD lines to its transports element, as transport_t structs.

When the managed proxy stops spitting METHOD lines (signified by a '{S,C}METHODS DONE' message) we pass copies of its transports to the bridge subsystem. We keep copies of the 'transport_t's on the managed proxy to be able to associate the proxy with its transports, and we pass copies to the bridge subsystem so that transports can be associated with bridges. [ XXX We should try see whether the two copies are really needed and maybe cut it into a single copy of the 'transport_t' shared between the managed proxy and the bridge subsystem. Preliminary analysis shows that both copies are needed with the current code logic, because of race conditions that can cause dangling pointers. ]

In even more detail, this is what happens when a config read (like a SIGHUP or a SETCONF) occurs:

We immediately destroy all unconfigured proxies (We shouldn't have unconfigured proxies in the first place, except when the config read happens immediately after tor is launched.).

We mark all managed proxies and transports to signify that they must be removed if they don't contribute by the new torrc (we mark using the marked_for_removal element). We also mark all managed proxies to signify that they might need to be restarted so that they end up supporting all the transports the new torrc wants them to support (we mark using the was_around_before_config_read element). We also clear their transports_to_launch list so that we can put there the transports we need to launch according to the new torrc.

We then start parsing torrc again.

Everytime we encounter a transport line using a managed proxy that was around before the config read, we cleanse that proxy from the removal mark. We also toggle the check_if_restarts_needed flag, so that on the next pt_configure_remaining_proxies tick, we investigate whether we need to restart the proxy so that it also spawns the new transports. If the post-config-read transports_to_launch list is identical to the pre-config-read one, it means that no changes were introduced to this proxy during the config read and no restart has to take place.

During the post-config-read torrc parsing, we unmark all transports spawned by managed proxies that we find in our torrc. We do that so that if we don't need to restart a managed proxy, we can continue using its old transports normally. If we end up restarting the proxy, we destroy and unregister all old transports from the circuitbuild.c subsystem.

Macro Definition Documentation

◆ PROTO_ENV_ERROR

#define PROTO_ENV_ERROR   "ENV-ERROR"

Managed proxy protocol strings

◆ PROTO_VERSION_ONE

#define PROTO_VERSION_ONE   1

The first and only supported - at the moment - configuration protocol version.

Function Documentation

◆ configure_proxy()

STATIC int configure_proxy ( managed_proxy_t *  mp)

Attempt to continue configuring managed proxy mp. Return 1 if the transport configuration finished, and return 0 otherwise (if we still have more configuring to do for this proxy).

◆ free_execve_args()

STATIC void free_execve_args ( char **  arg)

Frees the array of pointers in arg used as arguments to execve(2).

Here is the call graph for this function:

◆ get_pt_proxy_uri()

STATIC char* get_pt_proxy_uri ( void  )

Convert the tor proxy options to a URI suitable for TOR_PT_PROXY. Return a newly allocated string containing the URI, or NULL if no proxy is set.

Here is the call graph for this function:

◆ get_transport_options_for_server_proxy()

STATIC char* get_transport_options_for_server_proxy ( const managed_proxy_t *  mp)

Return a newly allocated string that tor should place in TOR_PT_SERVER_TRANSPORT_OPTIONS while configuring the server manged proxy in mp. Return NULL if no such options are found.

Loop over the transports of the proxy. If we have options for any of them, format them appropriately and place them in our smartlist. Finally, join our smartlist to get the final string.

Loop over the options of this transport, escape them, and place them in the smartlist.

Here is the call graph for this function:

◆ get_transport_proxy_ports()

smartlist_t* get_transport_proxy_ports ( void  )

Return a smartlist containing the ports where our pluggable transports are listening.

XXX assume that external proxy ports have been forwarded manually

Here is the call graph for this function:
Here is the caller graph for this function:

◆ handle_proxy_line()

STATIC void handle_proxy_line ( const char *  line,
managed_proxy_t *  mp 
)

Handle a configuration protocol line received from a managed proxy mp.

◆ managed_proxy_create()

STATIC managed_proxy_t* managed_proxy_create ( const smartlist_t with_transport_list,
char **  proxy_argv,
int  is_server 
)

Create and return a new managed proxy for transport using proxy_argv. Also, add it to the global managed proxy list. If is_server is true, it's a server managed proxy. Takes ownership of proxy_argv.

Requires that proxy_argv have at least one element.

◆ managed_proxy_destroy()

STATIC void managed_proxy_destroy ( managed_proxy_t *  mp,
int  also_terminate_process 
)

Free memory allocated by managed proxy mp.

◆ mark_transport_list()

void mark_transport_list ( void  )

Mark every entry of the transport list to be removed on our next call to sweep_transport_list unless it has first been un-marked.

◆ MOCK_IMPL() [1/3]

MOCK_IMPL ( transport_t ,
transport_get_by_name  ,
(const char *name)   
)

Returns the transport in our transport list that has the name name. Else returns NULL.

◆ MOCK_IMPL() [2/3]

MOCK_IMPL ( int  ,
transport_add_from_config  ,
(const tor_addr_t *addr, uint16_t port, const char *name, int socks_ver)   
)

Remember a new pluggable transport proxy at addr:port. name is set to the name of the protocol this proxy uses. socks_ver is set to the SOCKS version of the proxy.

◆ MOCK_IMPL() [3/3]

MOCK_IMPL ( void  ,
pt_kickstart_proxy  ,
(const smartlist_t *with_transport_list, char **proxy_argv, int is_server)   
)

Register proxy with proxy_argv, supporting transports in transport_list, to the managed proxy subsystem. If is_server is true, then the proxy is a server proxy.

Takes ownership of proxy_argv.

Requires that proxy_argv be a NULL-terminated array of command-line elements, containing at least one element.

◆ parse_cmethod_line()

STATIC int parse_cmethod_line ( const char *  line,
managed_proxy_t *  mp 
)

Parses a CMETHOD line, and if well-formed it registers the new transport in mp.

◆ parse_env_error()

STATIC void parse_env_error ( const char *  line)

Parses an ENV-ERROR line and warns the user accordingly.

◆ parse_proxy_error()

STATIC void parse_proxy_error ( const char *  line)

Parses an PROXY-ERROR line and warns the user accordingly.

◆ parse_smethod_line()

STATIC int parse_smethod_line ( const char *  line,
managed_proxy_t *  mp 
)

Parses an SMETHOD line and if well-formed it registers the new transport in mp.

◆ parse_version()

STATIC int parse_version ( const char *  line,
managed_proxy_t *  mp 
)

Handles a VERSION line. Updates the configuration protocol version in mp.

◆ pt_configure_remaining_proxies()

void pt_configure_remaining_proxies ( void  )

Check if any of the managed proxies we are currently trying to configure has anything new to say.

◆ pt_free_all()

void pt_free_all ( void  )

Release all storage held by the pluggable transports subsystem.

◆ pt_get_extra_info_descriptor_string()

char* pt_get_extra_info_descriptor_string ( void  )

Return the pluggable transport string that we should display in our extra-info descriptor. If we shouldn't display such a string, or we have nothing to display, return NULL. The string is allocated on the heap and it's the responsibility of the caller to free it.

Here is the call graph for this function:

◆ pt_get_socks_args_for_proxy_addrport()

char* pt_get_socks_args_for_proxy_addrport ( const tor_addr_t addr,
uint16_t  port 
)

Return a string of the SOCKS arguments that we should pass to the pluggable transports proxy in addr:port according to 180_pluggable_transport.txt. The string is allocated on the heap and it's the responsibility of the caller to free it after use.

Here is the call graph for this function:

◆ pt_prepare_proxy_list_for_config_read()

void pt_prepare_proxy_list_for_config_read ( void  )

Tor will read its config. Prepare the managed proxy list so that proxies not used in the new config will shutdown, and proxies that need to spawn different transports will do so.

◆ pt_proxies_configuration_pending()

int pt_proxies_configuration_pending ( void  )

Return true if there are still unconfigured managed proxies, or proxies that need restarting.

Here is the caller graph for this function:

◆ pt_stringify_socks_args()

char* pt_stringify_socks_args ( const smartlist_t socks_args)

Stringify the SOCKS arguments in socks_args according to 180_pluggable_transport.txt. The string is allocated on the heap and it's the responsibility of the caller to free it after use.

Here is the call graph for this function:
Here is the caller graph for this function:

◆ sweep_proxy_list()

void sweep_proxy_list ( void  )

The tor config was read. Destroy all managed proxies that were marked by a previous call to prepare_proxy_list_for_config_read() and are not used by the new config.

◆ sweep_transport_list()

void sweep_transport_list ( void  )

Remove every entry of the transport list that was marked with mark_transport_list if it has not subsequently been un-marked.

◆ transport_free_()

void transport_free_ ( transport_t transport)

Free the pluggable transport struct transport.

◆ transport_new()

STATIC transport_t* transport_new ( const tor_addr_t addr,
uint16_t  port,
const char *  name,
int  socks_ver,
const char *  extra_info_args 
)

Returns a transport_t struct for a transport proxy supporting the protocol name listening at addr:port using SOCKS version socks_ver.