Line data Source code
1 : /* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
2 : * Copyright (c) 2007-2021, The Tor Project, Inc. */
3 : /* See LICENSE for licensing information */
4 :
5 : /**
6 : * \file predict_ports.c
7 : * \brief Remember what ports we've needed so we can have circuits ready.
8 : *
9 : * Predicted ports are used by clients to remember how long it's been
10 : * since they opened an exit connection to each given target
11 : * port. Clients use this information in order to try to keep circuits
12 : * open to exit nodes that can connect to the ports that they care
13 : * about. (The predicted ports mechanism also handles predicted circuit
14 : * usage that _isn't_ port-specific, such as resolves, internal circuits,
15 : * and so on.)
16 : **/
17 :
18 : #include "core/or/or.h"
19 :
20 : #include "app/config/config.h"
21 : #include "core/or/channelpadding.h"
22 : #include "core/or/circuituse.h"
23 : #include "feature/relay/routermode.h"
24 : #include "feature/relay/selftest.h"
25 : #include "feature/stats/predict_ports.h"
26 : #include "lib/container/bitarray.h"
27 : #include "lib/time/tvdiff.h"
28 :
29 : static size_t predicted_ports_total_alloc = 0;
30 :
31 : static void predicted_ports_alloc(void);
32 :
33 : /** A single predicted port: used to remember which ports we've made
34 : * connections to, so that we can try to keep making circuits that can handle
35 : * those ports. */
36 : typedef struct predicted_port_t {
37 : /** The port we connected to */
38 : uint16_t port;
39 : /** The time at which we last used it */
40 : time_t time;
41 : } predicted_port_t;
42 :
43 : /** A list of port numbers that have been used recently. */
44 : static smartlist_t *predicted_ports_list=NULL;
45 : /** How long do we keep predicting circuits? */
46 : static time_t prediction_timeout=0;
47 : /** When was the last time we added a prediction entry (HS or port) */
48 : static time_t last_prediction_add_time=0;
49 :
50 : /**
51 : * How much time left until we stop predicting circuits?
52 : */
53 : int
54 204 : predicted_ports_prediction_time_remaining(time_t now)
55 : {
56 204 : time_t seconds_waited;
57 204 : time_t seconds_left;
58 :
59 : /* Protect against overflow of return value. This can happen if the clock
60 : * jumps backwards in time. Update the last prediction time (aka last
61 : * active time) to prevent it. This update is preferable to using monotonic
62 : * time because it prevents clock jumps into the past from simply causing
63 : * very long idle timeouts while the monotonic time stands still. */
64 204 : seconds_waited = time_diff(last_prediction_add_time, now);
65 204 : if (seconds_waited == TIME_MAX) {
66 0 : last_prediction_add_time = now;
67 0 : seconds_waited = 0;
68 : }
69 :
70 : /* Protect against underflow of the return value. This can happen for very
71 : * large periods of inactivity/system sleep. */
72 204 : if (seconds_waited > prediction_timeout)
73 : return 0;
74 :
75 204 : seconds_left = time_diff(seconds_waited, prediction_timeout);
76 204 : if (BUG(seconds_left == TIME_MAX))
77 0 : return INT_MAX;
78 :
79 204 : return (int)(seconds_left);
80 : }
81 :
82 : /** We just got an application request for a connection with
83 : * port <b>port</b>. Remember it for the future, so we can keep
84 : * some circuits open that will exit to this port.
85 : */
86 : static void
87 203 : add_predicted_port(time_t now, uint16_t port)
88 : {
89 203 : predicted_port_t *pp = tor_malloc(sizeof(predicted_port_t));
90 :
91 : // If the list is empty, re-randomize predicted ports lifetime
92 203 : if (!any_predicted_circuits(now)) {
93 406 : prediction_timeout =
94 203 : (time_t)channelpadding_get_circuits_available_timeout();
95 : }
96 :
97 203 : last_prediction_add_time = now;
98 :
99 203 : log_info(LD_CIRC,
100 : "New port prediction added. Will continue predictive circ building "
101 : "for %d more seconds.",
102 : predicted_ports_prediction_time_remaining(now));
103 :
104 203 : pp->port = port;
105 203 : pp->time = now;
106 203 : predicted_ports_total_alloc += sizeof(*pp);
107 203 : smartlist_add(predicted_ports_list, pp);
108 203 : }
109 :
110 : /** Remember that <b>port</b> has been asked for as of time <b>now</b>.
111 : * This is used for predicting what sorts of streams we'll make in the
112 : * future and making exit circuits to anticipate that.
113 : */
114 : void
115 0 : rep_hist_note_used_port(time_t now, uint16_t port)
116 : {
117 0 : tor_assert(predicted_ports_list);
118 :
119 0 : if (!port) /* record nothing */
120 : return;
121 :
122 0 : SMARTLIST_FOREACH_BEGIN(predicted_ports_list, predicted_port_t *, pp) {
123 0 : if (pp->port == port) {
124 0 : pp->time = now;
125 :
126 0 : last_prediction_add_time = now;
127 0 : log_info(LD_CIRC,
128 : "New port prediction added. Will continue predictive circ "
129 : "building for %d more seconds.",
130 : predicted_ports_prediction_time_remaining(now));
131 0 : return;
132 : }
133 0 : } SMARTLIST_FOREACH_END(pp);
134 : /* it's not there yet; we need to add it */
135 0 : add_predicted_port(now, port);
136 : }
137 :
138 : /** Return a newly allocated pointer to a list of uint16_t * for ports that
139 : * are likely to be asked for in the near future.
140 : */
141 : smartlist_t *
142 3 : rep_hist_get_predicted_ports(time_t now)
143 : {
144 3 : int predicted_circs_relevance_time;
145 3 : smartlist_t *out = smartlist_new();
146 3 : tor_assert(predicted_ports_list);
147 :
148 3 : predicted_circs_relevance_time = (int)prediction_timeout;
149 :
150 : /* clean out obsolete entries */
151 6 : SMARTLIST_FOREACH_BEGIN(predicted_ports_list, predicted_port_t *, pp) {
152 3 : if (pp->time + predicted_circs_relevance_time < now) {
153 0 : log_debug(LD_CIRC, "Expiring predicted port %d", pp->port);
154 :
155 0 : predicted_ports_total_alloc -= sizeof(predicted_port_t);
156 0 : tor_free(pp);
157 0 : SMARTLIST_DEL_CURRENT(predicted_ports_list, pp);
158 : } else {
159 3 : smartlist_add(out, tor_memdup(&pp->port, sizeof(uint16_t)));
160 : }
161 3 : } SMARTLIST_FOREACH_END(pp);
162 3 : return out;
163 : }
164 :
165 : /**
166 : * Take a list of uint16_t *, and remove every port in the list from the
167 : * current list of predicted ports.
168 : */
169 : void
170 0 : rep_hist_remove_predicted_ports(const smartlist_t *rmv_ports)
171 : {
172 : /* Let's do this on O(N), not O(N^2). */
173 0 : bitarray_t *remove_ports = bitarray_init_zero(UINT16_MAX);
174 0 : SMARTLIST_FOREACH(rmv_ports, const uint16_t *, p,
175 : bitarray_set(remove_ports, *p));
176 0 : SMARTLIST_FOREACH_BEGIN(predicted_ports_list, predicted_port_t *, pp) {
177 0 : if (bitarray_is_set(remove_ports, pp->port)) {
178 0 : tor_free(pp);
179 0 : predicted_ports_total_alloc -= sizeof(*pp);
180 0 : SMARTLIST_DEL_CURRENT(predicted_ports_list, pp);
181 : }
182 0 : } SMARTLIST_FOREACH_END(pp);
183 0 : bitarray_free(remove_ports);
184 0 : }
185 :
186 : /** The user asked us to do a resolve. Rather than keeping track of
187 : * timings and such of resolves, we fake it for now by treating
188 : * it the same way as a connection to port 80. This way we will continue
189 : * to have circuits lying around if the user only uses Tor for resolves.
190 : */
191 : void
192 0 : rep_hist_note_used_resolve(time_t now)
193 : {
194 0 : rep_hist_note_used_port(now, 80);
195 0 : }
196 :
197 : /** The last time at which we needed an internal circ. */
198 : static time_t predicted_internal_time = 0;
199 : /** The last time we needed an internal circ with good uptime. */
200 : static time_t predicted_internal_uptime_time = 0;
201 : /** The last time we needed an internal circ with good capacity. */
202 : static time_t predicted_internal_capacity_time = 0;
203 :
204 : /** Remember that we used an internal circ at time <b>now</b>. */
205 : void
206 1 : rep_hist_note_used_internal(time_t now, int need_uptime, int need_capacity)
207 : {
208 : // If the list is empty, re-randomize predicted ports lifetime
209 1 : if (!any_predicted_circuits(now)) {
210 0 : prediction_timeout = channelpadding_get_circuits_available_timeout();
211 : }
212 :
213 1 : last_prediction_add_time = now;
214 :
215 1 : log_info(LD_CIRC,
216 : "New port prediction added. Will continue predictive circ building "
217 : "for %d more seconds.",
218 : predicted_ports_prediction_time_remaining(now));
219 :
220 1 : predicted_internal_time = now;
221 1 : if (need_uptime)
222 0 : predicted_internal_uptime_time = now;
223 1 : if (need_capacity)
224 1 : predicted_internal_capacity_time = now;
225 1 : }
226 :
227 : /** Return 1 if we've used an internal circ recently; else return 0. */
228 : int
229 0 : rep_hist_get_predicted_internal(time_t now, int *need_uptime,
230 : int *need_capacity)
231 : {
232 0 : int predicted_circs_relevance_time;
233 :
234 0 : predicted_circs_relevance_time = (int)prediction_timeout;
235 :
236 0 : if (!predicted_internal_time) { /* initialize it */
237 0 : predicted_internal_time = now;
238 0 : predicted_internal_uptime_time = now;
239 0 : predicted_internal_capacity_time = now;
240 : }
241 0 : if (predicted_internal_time + predicted_circs_relevance_time < now)
242 : return 0; /* too long ago */
243 0 : if (predicted_internal_uptime_time + predicted_circs_relevance_time >= now)
244 0 : *need_uptime = 1;
245 : // Always predict that we need capacity.
246 0 : *need_capacity = 1;
247 0 : return 1;
248 : }
249 :
250 : /** Any ports used lately? These are pre-seeded if we just started
251 : * up or if we're running a hidden service. */
252 : int
253 225 : any_predicted_circuits(time_t now)
254 : {
255 225 : int predicted_circs_relevance_time;
256 225 : predicted_circs_relevance_time = (int)prediction_timeout;
257 :
258 225 : return smartlist_len(predicted_ports_list) ||
259 203 : predicted_internal_time + predicted_circs_relevance_time >= now;
260 : }
261 :
262 : /** Return 1 if we have no need for circuits currently, else return 0. */
263 : int
264 21 : rep_hist_circbuilding_dormant(time_t now)
265 : {
266 21 : const or_options_t *options = get_options();
267 :
268 21 : if (any_predicted_circuits(now))
269 : return 0;
270 :
271 : /* see if we'll still need to build testing circuits */
272 0 : if (server_mode(options) &&
273 0 : (!router_all_orports_seem_reachable(options) ||
274 0 : !circuit_enough_testing_circs()))
275 0 : return 0;
276 :
277 : return 1;
278 : }
279 :
280 : /**
281 : * Allocate whatever memory and structs are needed for predicting
282 : * which ports will be used. Also seed it with port 80, so we'll build
283 : * circuits on start-up.
284 : */
285 : static void
286 203 : predicted_ports_alloc(void)
287 : {
288 203 : predicted_ports_list = smartlist_new();
289 203 : }
290 :
291 : void
292 203 : predicted_ports_init(void)
293 : {
294 203 : predicted_ports_alloc();
295 203 : add_predicted_port(time(NULL), 443); // Add a port to get us started
296 203 : }
297 :
298 : /** Free whatever memory is needed for predicting which ports will
299 : * be used.
300 : */
301 : void
302 235 : predicted_ports_free_all(void)
303 : {
304 235 : if (!predicted_ports_list)
305 : return;
306 194 : predicted_ports_total_alloc -=
307 194 : smartlist_len(predicted_ports_list)*sizeof(predicted_port_t);
308 388 : SMARTLIST_FOREACH(predicted_ports_list, predicted_port_t *,
309 : pp, tor_free(pp));
310 194 : smartlist_free(predicted_ports_list);
311 : }
|