metrics: Add number of opened circuits to MetricsPort
[tor.git] / src / feature / relay / transport_config.c
blob23e024fbee8418119eae052d486206a7073079ca
1 /* Copyright (c) 2001 Matej Pfajfar.
2 * Copyright (c) 2001-2004, Roger Dingledine.
3 * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
4 * Copyright (c) 2007-2021, The Tor Project, Inc. */
5 /* See LICENSE for licensing information */
7 /**
8 * @file transport_config.c
9 * @brief Code to interpret the user's configuration of Tor's server
10 * pluggable transports.
11 **/
13 #include "orconfig.h"
14 #define RELAY_TRANSPORT_CONFIG_PRIVATE
15 #include "feature/relay/transport_config.h"
17 #include "lib/encoding/confline.h"
18 #include "lib/encoding/keyval.h"
20 #include "lib/container/smartlist.h"
22 /* Required for dirinfo_type_t in or_options_t */
23 #include "core/or/or.h"
24 #include "app/config/config.h"
26 #include "feature/relay/ext_orport.h"
27 #include "feature/relay/routermode.h"
29 /* Copied from config.c, we will refactor later in 29211. */
30 #define REJECT(arg) \
31 STMT_BEGIN *msg = tor_strdup(arg); return -1; STMT_END
33 /** Given a ServerTransportListenAddr <b>line</b>, return its
34 * <address:port> string. Return NULL if the line was not
35 * well-formed.
37 * If <b>transport</b> is set, return NULL if the line is not
38 * referring to <b>transport</b>.
40 * The returned string is allocated on the heap and it's the
41 * responsibility of the caller to free it. */
42 static char *
43 get_bindaddr_from_transport_listen_line(const char *line,
44 const char *transport)
46 smartlist_t *items = NULL;
47 const char *parsed_transport = NULL;
48 char *addrport = NULL;
49 tor_addr_t addr;
50 uint16_t port = 0;
52 items = smartlist_new();
53 smartlist_split_string(items, line, NULL,
54 SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, -1);
56 if (smartlist_len(items) < 2) {
57 log_warn(LD_CONFIG,"Too few arguments on ServerTransportListenAddr line.");
58 goto err;
61 parsed_transport = smartlist_get(items, 0);
62 addrport = tor_strdup(smartlist_get(items, 1));
64 /* If 'transport' is given, check if it matches the one on the line */
65 if (transport && strcmp(transport, parsed_transport))
66 goto err;
68 /* Validate addrport */
69 if (tor_addr_port_parse(LOG_WARN, addrport, &addr, &port, -1)<0) {
70 log_warn(LD_CONFIG, "Error parsing ServerTransportListenAddr "
71 "address '%s'", addrport);
72 goto err;
75 goto done;
77 err:
78 tor_free(addrport);
79 addrport = NULL;
81 done:
82 SMARTLIST_FOREACH(items, char*, s, tor_free(s));
83 smartlist_free(items);
85 return addrport;
88 /** Given the name of a pluggable transport in <b>transport</b>, check
89 * the configuration file to see if the user has explicitly asked for
90 * it to listen on a specific port. Return a <address:port> string if
91 * so, otherwise NULL. */
92 char *
93 pt_get_bindaddr_from_config(const char *transport)
95 config_line_t *cl;
96 const or_options_t *options = get_options();
98 for (cl = options->ServerTransportListenAddr; cl; cl = cl->next) {
99 char *bindaddr =
100 get_bindaddr_from_transport_listen_line(cl->value, transport);
101 if (bindaddr)
102 return bindaddr;
105 return NULL;
108 /** Given a ServerTransportOptions <b>line</b>, return a smartlist
109 * with the options. Return NULL if the line was not well-formed.
111 * If <b>transport</b> is set, return NULL if the line is not
112 * referring to <b>transport</b>.
114 * The returned smartlist and its strings are allocated on the heap
115 * and it's the responsibility of the caller to free it. */
116 STATIC smartlist_t *
117 get_options_from_transport_options_line(const char *line,
118 const char *transport)
120 smartlist_t *items = smartlist_new();
121 smartlist_t *pt_options = smartlist_new();
122 const char *parsed_transport = NULL;
124 smartlist_split_string(items, line, NULL,
125 SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, -1);
127 if (smartlist_len(items) < 2) {
128 log_warn(LD_CONFIG,"Too few arguments on ServerTransportOptions line.");
129 goto err;
132 parsed_transport = smartlist_get(items, 0);
133 /* If 'transport' is given, check if it matches the one on the line */
134 if (transport && strcmp(transport, parsed_transport))
135 goto err;
137 SMARTLIST_FOREACH_BEGIN(items, const char *, option) {
138 if (option_sl_idx == 0) /* skip the transport field (first field)*/
139 continue;
141 /* validate that it's a k=v value */
142 if (!string_is_key_value(LOG_WARN, option)) {
143 log_warn(LD_CONFIG, "%s is not a k=v value.", escaped(option));
144 goto err;
147 /* add it to the options smartlist */
148 smartlist_add_strdup(pt_options, option);
149 log_debug(LD_CONFIG, "Added %s to the list of options", escaped(option));
150 } SMARTLIST_FOREACH_END(option);
152 goto done;
154 err:
155 SMARTLIST_FOREACH(pt_options, char*, s, tor_free(s));
156 smartlist_free(pt_options);
157 pt_options = NULL;
159 done:
160 SMARTLIST_FOREACH(items, char*, s, tor_free(s));
161 smartlist_free(items);
163 return pt_options;
166 /** Given the name of a pluggable transport in <b>transport</b>, check
167 * the configuration file to see if the user has asked us to pass any
168 * parameters to the pluggable transport. Return a smartlist
169 * containing the parameters, otherwise NULL. */
170 smartlist_t *
171 pt_get_options_for_server_transport(const char *transport)
173 config_line_t *cl;
174 const or_options_t *options = get_options();
176 for (cl = options->ServerTransportOptions; cl; cl = cl->next) {
177 smartlist_t *options_sl =
178 get_options_from_transport_options_line(cl->value, transport);
179 if (options_sl)
180 return options_sl;
183 return NULL;
187 * Legacy validation/normalization function for the server transport options.
188 * Uses old_options as the previous options.
190 * Returns 0 on success, returns -1 and sets *msg to a newly allocated string
191 * on error.
194 options_validate_server_transport(const or_options_t *old_options,
195 or_options_t *options,
196 char **msg)
198 (void)old_options;
200 if (BUG(!options))
201 return -1;
203 if (BUG(!msg))
204 return -1;
206 config_line_t *cl;
208 if (options->ServerTransportPlugin && !server_mode(options)) {
209 log_notice(LD_GENERAL, "Tor is not configured as a relay but you specified"
210 " a ServerTransportPlugin line (%s). The ServerTransportPlugin "
211 "line will be ignored.",
212 escaped(options->ServerTransportPlugin->value));
215 if (options->ServerTransportListenAddr && !options->ServerTransportPlugin) {
216 log_notice(LD_GENERAL, "You need at least a single managed-proxy to "
217 "specify a transport listen address. The "
218 "ServerTransportListenAddr line will be ignored.");
221 for (cl = options->ServerTransportPlugin; cl; cl = cl->next) {
222 if (pt_parse_transport_line(options, cl->value, 1, 1) < 0)
223 REJECT("Invalid server transport line. See logs for details.");
226 for (cl = options->ServerTransportListenAddr; cl; cl = cl->next) {
227 /** If get_bindaddr_from_transport_listen_line() fails with
228 'transport' being NULL, it means that something went wrong
229 while parsing the ServerTransportListenAddr line. */
230 char *bindaddr = get_bindaddr_from_transport_listen_line(cl->value, NULL);
231 if (!bindaddr)
232 REJECT("ServerTransportListenAddr did not parse. See logs for details.");
233 tor_free(bindaddr);
236 for (cl = options->ServerTransportOptions; cl; cl = cl->next) {
237 /** If get_options_from_transport_options_line() fails with
238 'transport' being NULL, it means that something went wrong
239 while parsing the ServerTransportOptions line. */
240 smartlist_t *options_sl =
241 get_options_from_transport_options_line(cl->value, NULL);
242 if (!options_sl)
243 REJECT("ServerTransportOptions did not parse. See logs for details.");
245 SMARTLIST_FOREACH(options_sl, char *, cp, tor_free(cp));
246 smartlist_free(options_sl);
249 return 0;
252 /** Fetch the active option list, and take server pluggable transport actions
253 * based on it. All of the things we do should survive being done repeatedly.
254 * If present, <b>old_options</b> contains the previous value of the options.
256 * Return 0 if all goes well, return -1 if it's time to die.
258 * Note: We haven't moved all the "act on new configuration" logic
259 * into the options_act* functions yet. Some is still in do_hup() and other
260 * places.
263 options_act_server_transport(const or_options_t *old_options)
265 (void)old_options;
267 config_line_t *cl;
268 const or_options_t *options = get_options();
269 int running_tor = options->command == CMD_RUN_TOR;
271 /* If we are a bridge with a pluggable transport proxy but no
272 Extended ORPort, inform the user that they are missing out. */
273 if (options->ServerTransportPlugin &&
274 !options->ExtORPort_lines) {
275 log_notice(LD_CONFIG, "We use pluggable transports but the Extended "
276 "ORPort is disabled. Tor and your pluggable transports proxy "
277 "communicate with each other via the Extended ORPort so it "
278 "is suggested you enable it: it will also allow your Bridge "
279 "to collect statistics about its clients that use pluggable "
280 "transports. Please enable it using the ExtORPort torrc option "
281 "(e.g. set 'ExtORPort auto').");
284 /* If we have an ExtORPort, initialize its auth cookie. */
285 if (running_tor &&
286 init_ext_or_cookie_authentication(!!options->ExtORPort_lines) < 0) {
287 log_warn(LD_CONFIG,"Error creating Extended ORPort cookie file.");
288 return -1;
291 if (!options->DisableNetwork) {
292 if (options->ServerTransportPlugin) {
293 for (cl = options->ServerTransportPlugin; cl; cl = cl->next) {
294 if (pt_parse_transport_line(options, cl->value, 0, 1) < 0) {
295 // LCOV_EXCL_START
296 log_warn(LD_BUG,
297 "Previously validated ServerTransportPlugin line "
298 "could not be added!");
299 return -1;
300 // LCOV_EXCL_STOP
306 return 0;