Reduce pointer indirection for global list_t variables
[tinc] / src / net.c
1 /*
2     net.c -- most of the network code
3     Copyright (C) 1998-2005 Ivo Timmermans,
4                   2000-2021 Guus Sliepen <guus@tinc-vpn.org>
5                   2006      Scott Lamb <slamb@slamb.org>
6                   2011      Loïc Grenié <loic.grenie@gmail.com>
7
8     This program is free software; you can redistribute it and/or modify
9     it under the terms of the GNU General Public License as published by
10     the Free Software Foundation; either version 2 of the License, or
11     (at your option) any later version.
12
13     This program is distributed in the hope that it will be useful,
14     but WITHOUT ANY WARRANTY; without even the implied warranty of
15     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16     GNU General Public License for more details.
17
18     You should have received a copy of the GNU General Public License along
19     with this program; if not, write to the Free Software Foundation, Inc.,
20     51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21 */
22
23 #include "system.h"
24
25 #include "autoconnect.h"
26 #include "conf_net.h"
27 #include "conf.h"
28 #include "connection.h"
29 #include "graph.h"
30 #include "logger.h"
31 #include "meta.h"
32 #include "names.h"
33 #include "net.h"
34 #include "protocol.h"
35 #include "subnet.h"
36 #include "utils.h"
37
38 int contradicting_add_edge = 0;
39 int contradicting_del_edge = 0;
40 static int sleeptime = 10;
41 time_t last_config_check = 0;
42 static timeout_t pingtimer;
43 static timeout_t periodictimer;
44 static struct timeval last_periodic_run_time;
45
46 /* Purge edges and subnets of unreachable nodes. Use carefully. */
47
48 void purge(void) {
49         logger(DEBUG_PROTOCOL, LOG_DEBUG, "Purging unreachable nodes");
50
51         /* Remove all edges and subnets owned by unreachable nodes. */
52
53         for splay_each(node_t, n, node_tree) {
54                 if(!n->status.reachable) {
55                         logger(DEBUG_SCARY_THINGS, LOG_DEBUG, "Purging node %s (%s)", n->name, n->hostname);
56
57                         for splay_each(subnet_t, s, n->subnet_tree) {
58                                 send_del_subnet(everyone, s);
59
60                                 if(!strictsubnets) {
61                                         subnet_del(n, s);
62                                 }
63                         }
64
65                         for splay_each(edge_t, e, n->edge_tree) {
66                                 if(!tunnelserver) {
67                                         send_del_edge(everyone, e);
68                                 }
69
70                                 edge_del(e);
71                         }
72                 }
73         }
74
75         /* Check if anyone else claims to have an edge to an unreachable node. If not, delete node. */
76
77         for splay_each(node_t, n, node_tree) {
78                 if(!n->status.reachable) {
79                         for splay_each(edge_t, e, edge_weight_tree)
80                                 if(e->to == n) {
81                                         return;
82                                 }
83
84                         if(!autoconnect && (!strictsubnets || !n->subnet_tree->head))
85                                 /* in strictsubnets mode do not delete nodes with subnets */
86                         {
87                                 node_del(n);
88                         }
89                 }
90         }
91 }
92
93 /* Put a misbehaving connection in the tarpit */
94 void tarpit(int fd) {
95         static int pits[10] = {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1};
96         static unsigned int next_pit = 0;
97
98         if(pits[next_pit] != -1) {
99                 closesocket(pits[next_pit]);
100         }
101
102         pits[next_pit++] = fd;
103
104         if(next_pit >= sizeof pits / sizeof pits[0]) {
105                 next_pit = 0;
106         }
107 }
108
109 /*
110   Terminate a connection:
111   - Mark it as inactive
112   - Remove the edge representing this connection
113   - Kill it with fire
114   - Check if we need to retry making an outgoing connection
115 */
116 void terminate_connection(connection_t *c, bool report) {
117         logger(DEBUG_CONNECTIONS, LOG_NOTICE, "Closing connection with %s (%s)", c->name, c->hostname);
118
119         if(c->node) {
120                 if(c->node->connection == c) {
121                         c->node->connection = NULL;
122                 }
123
124                 if(c->edge) {
125                         if(report && !tunnelserver) {
126                                 send_del_edge(everyone, c->edge);
127                         }
128
129                         edge_del(c->edge);
130                         c->edge = NULL;
131
132                         /* Run MST and SSSP algorithms */
133
134                         graph();
135
136                         /* If the node is not reachable anymore but we remember it had an edge to us, clean it up */
137
138                         if(report && !c->node->status.reachable) {
139                                 edge_t *e;
140                                 e = lookup_edge(c->node, myself);
141
142                                 if(e) {
143                                         if(!tunnelserver) {
144                                                 send_del_edge(everyone, e);
145                                         }
146
147                                         edge_del(e);
148                                 }
149                         }
150                 }
151         }
152
153         outgoing_t *outgoing = c->outgoing;
154         connection_del(c);
155
156         /* Check if this was our outgoing connection */
157
158         if(outgoing) {
159                 do_outgoing_connection(outgoing);
160         }
161
162 #ifndef HAVE_MINGW
163         /* Clean up dead proxy processes */
164
165         while(waitpid(-1, NULL, WNOHANG) > 0);
166
167 #endif
168 }
169
170 /*
171   Check if the other end is active.
172   If we have sent packets, but didn't receive any,
173   then possibly the other end is dead. We send a
174   PING request over the meta connection. If the other
175   end does not reply in time, we consider them dead
176   and close the connection.
177 */
178 static void timeout_handler(void *data) {
179
180         bool close_all_connections = false;
181
182         /*
183                  timeout_handler will start after 30 seconds from start of tincd
184                  hold information about the elapsed time since last time the handler
185                  has been run
186         */
187         long sleep_time = now.tv_sec - last_periodic_run_time.tv_sec;
188
189         /*
190                  It seems that finding sane default value is harder than expected
191                  Since we send every second a UDP packet to make holepunching work
192                  And default UDP state expire on firewalls is between 15-30 seconds
193                  we drop all connections after 60 Seconds - UDPDiscoveryTimeout=30
194                  by default
195         */
196         if(sleep_time > 2 * udp_discovery_timeout) {
197                 logger(DEBUG_ALWAYS, LOG_ERR, "Awaking from dead after %ld seconds of sleep", sleep_time);
198                 /*
199                         Do not send any packets to tinc after we wake up.
200                         The other node probably closed our connection but we still
201                         are holding context information to them. This may happen on
202                         laptops or any other hardware which can be suspended for some time.
203                         Sending any data to node that wasn't expecting it will produce
204                         annoying and misleading errors on the other side about failed signature
205                         verification and or about missing sptps context
206                 */
207                 close_all_connections = true;
208         }
209
210         last_periodic_run_time = now;
211
212         for list_each(connection_t, c, &connection_list) {
213                 // control connections (eg. tinc ctl) do not have any timeout
214                 if(c->status.control) {
215                         continue;
216                 }
217
218                 if(close_all_connections) {
219                         logger(DEBUG_ALWAYS, LOG_ERR, "Forcing connection close after sleep time %s (%s)", c->name, c->hostname);
220                         terminate_connection(c, c->edge);
221                         continue;
222                 }
223
224                 // Bail out early if we haven't reached the ping timeout for this node yet
225                 if(c->last_ping_time + pingtimeout > now.tv_sec) {
226                         continue;
227                 }
228
229                 // timeout during connection establishing
230                 if(!c->edge) {
231                         if(c->status.connecting) {
232                                 logger(DEBUG_CONNECTIONS, LOG_WARNING, "Timeout while connecting to %s (%s)", c->name, c->hostname);
233                         } else {
234                                 logger(DEBUG_CONNECTIONS, LOG_WARNING, "Timeout from %s (%s) during authentication", c->name, c->hostname);
235                                 c->status.tarpit = true;
236                         }
237
238                         terminate_connection(c, c->edge);
239                         continue;
240                 }
241
242                 // helps in UDP holepunching
243                 try_tx(c->node, false);
244
245                 // timeout during ping
246                 if(c->status.pinged) {
247                         logger(DEBUG_CONNECTIONS, LOG_INFO, "%s (%s) didn't respond to PING in %ld seconds", c->name, c->hostname, (long)(now.tv_sec - c->last_ping_time));
248                         terminate_connection(c, c->edge);
249                         continue;
250                 }
251
252                 // check whether we need to send a new ping
253                 if(c->last_ping_time + pinginterval <= now.tv_sec) {
254                         send_ping(c);
255                 }
256         }
257
258         timeout_set(data, &(struct timeval) {
259                 1, rand() % 100000
260         });
261 }
262
263 static void periodic_handler(void *data) {
264         /* Check if there are too many contradicting ADD_EDGE and DEL_EDGE messages.
265            This usually only happens when another node has the same Name as this node.
266            If so, sleep for a short while to prevent a storm of contradicting messages.
267         */
268
269         if(contradicting_del_edge > 100 && contradicting_add_edge > 100) {
270                 logger(DEBUG_ALWAYS, LOG_WARNING, "Possible node with same Name as us! Sleeping %d seconds.", sleeptime);
271                 nanosleep(&(struct timespec) {
272                         sleeptime, 0
273                 }, NULL);
274                 sleeptime *= 2;
275
276                 if(sleeptime < 0) {
277                         sleeptime = 3600;
278                 }
279         } else {
280                 sleeptime /= 2;
281
282                 if(sleeptime < 10) {
283                         sleeptime = 10;
284                 }
285         }
286
287         contradicting_add_edge = 0;
288         contradicting_del_edge = 0;
289
290         /* If AutoConnect is set, check if we need to make or break connections. */
291
292         if(autoconnect && node_tree->count > 1) {
293                 do_autoconnect();
294         }
295
296         timeout_set(data, &(struct timeval) {
297                 5, rand() % 100000
298         });
299 }
300
301 void handle_meta_connection_data(connection_t *c) {
302         if(!receive_meta(c)) {
303                 if(!c->status.control) {
304                         c->status.tarpit = true;
305                 }
306
307                 terminate_connection(c, c->edge);
308                 return;
309         }
310 }
311
312 #ifndef HAVE_MINGW
313 static void sigterm_handler(void *data) {
314         logger(DEBUG_ALWAYS, LOG_NOTICE, "Got %s signal", strsignal(((signal_t *)data)->signum));
315         event_exit();
316 }
317
318 static void sighup_handler(void *data) {
319         logger(DEBUG_ALWAYS, LOG_NOTICE, "Got %s signal", strsignal(((signal_t *)data)->signum));
320         reopenlogger();
321
322         if(reload_configuration()) {
323                 exit(1);
324         }
325 }
326
327 static void sigalrm_handler(void *data) {
328         logger(DEBUG_ALWAYS, LOG_NOTICE, "Got %s signal", strsignal(((signal_t *)data)->signum));
329         retry();
330 }
331 #endif
332
333 int reload_configuration(void) {
334         char fname[PATH_MAX];
335
336         /* Reread our own configuration file */
337
338         exit_configuration(&config_tree);
339         init_configuration(&config_tree);
340
341         if(!read_server_config(config_tree)) {
342                 logger(DEBUG_ALWAYS, LOG_ERR, "Unable to reread configuration file.");
343                 return EINVAL;
344         }
345
346         read_config_options(config_tree, NULL);
347
348         snprintf(fname, sizeof(fname), "%s" SLASH "hosts" SLASH "%s", confbase, myself->name);
349         read_config_file(config_tree, fname, true);
350
351         /* Parse some options that are allowed to be changed while tinc is running */
352
353         setup_myself_reloadable();
354
355         /* If StrictSubnet is set, expire deleted Subnets and read new ones in */
356
357         if(strictsubnets) {
358                 for splay_each(subnet_t, subnet, subnet_tree)
359                         if(subnet->owner) {
360                                 subnet->expires = 1;
361                         }
362         }
363
364         for splay_each(node_t, n, node_tree) {
365                 n->status.has_address = false;
366         }
367
368         load_all_nodes();
369
370         if(strictsubnets) {
371                 for splay_each(subnet_t, subnet, subnet_tree) {
372                         if(!subnet->owner) {
373                                 continue;
374                         }
375
376                         if(subnet->expires == 1) {
377                                 send_del_subnet(everyone, subnet);
378
379                                 if(subnet->owner->status.reachable) {
380                                         subnet_update(subnet->owner, subnet, false);
381                                 }
382
383                                 subnet_del(subnet->owner, subnet);
384                         } else if(subnet->expires == -1) {
385                                 subnet->expires = 0;
386                         } else {
387                                 send_add_subnet(everyone, subnet);
388
389                                 if(subnet->owner->status.reachable) {
390                                         subnet_update(subnet->owner, subnet, true);
391                                 }
392                         }
393                 }
394         } else { /* Only read our own subnets back in */
395                 for splay_each(subnet_t, subnet, myself->subnet_tree)
396                         if(!subnet->expires) {
397                                 subnet->expires = 1;
398                         }
399
400                 config_t *cfg = lookup_config(config_tree, "Subnet");
401
402                 while(cfg) {
403                         subnet_t *subnet, *s2;
404
405                         if(get_config_subnet(cfg, &subnet)) {
406                                 if((s2 = lookup_subnet(myself, subnet))) {
407                                         if(s2->expires == 1) {
408                                                 s2->expires = 0;
409                                         }
410
411                                         free_subnet(subnet);
412                                 } else {
413                                         subnet_add(myself, subnet);
414                                         send_add_subnet(everyone, subnet);
415                                         subnet_update(myself, subnet, true);
416                                 }
417                         }
418
419                         cfg = lookup_config_next(config_tree, cfg);
420                 }
421
422                 for splay_each(subnet_t, subnet, myself->subnet_tree) {
423                         if(subnet->expires == 1) {
424                                 send_del_subnet(everyone, subnet);
425                                 subnet_update(myself, subnet, false);
426                                 subnet_del(myself, subnet);
427                         }
428                 }
429         }
430
431         /* Try to make outgoing connections */
432
433         try_outgoing_connections();
434
435         /* Close connections to hosts that have a changed or deleted host config file */
436
437         for list_each(connection_t, c, &connection_list) {
438                 if(c->status.control) {
439                         continue;
440                 }
441
442                 snprintf(fname, sizeof(fname), "%s" SLASH "hosts" SLASH "%s", confbase, c->name);
443                 struct stat s;
444
445                 if(stat(fname, &s) || s.st_mtime > last_config_check) {
446                         logger(DEBUG_CONNECTIONS, LOG_INFO, "Host config file of %s has been changed", c->name);
447                         terminate_connection(c, c->edge);
448                 }
449         }
450
451         last_config_check = now.tv_sec;
452
453         return 0;
454 }
455
456 void retry(void) {
457         /* Reset the reconnection timers for all outgoing connections */
458         for list_each(outgoing_t, outgoing, &outgoing_list) {
459                 outgoing->timeout = 0;
460
461                 if(outgoing->ev.cb)
462                         timeout_set(&outgoing->ev, &(struct timeval) {
463                         0, 0
464                 });
465         }
466
467         /* Check for outgoing connections that are in progress, and reset their ping timers */
468         for list_each(connection_t, c, &connection_list) {
469                 if(c->outgoing && !c->node) {
470                         c->last_ping_time = 0;
471                 }
472         }
473
474         /* Kick the ping timeout handler */
475         timeout_set(&pingtimer, &(struct timeval) {
476                 0, 0
477         });
478 }
479
480 /*
481   this is where it all happens...
482 */
483 int main_loop(void) {
484         last_periodic_run_time = now;
485         timeout_add(&pingtimer, timeout_handler, &pingtimer, &(struct timeval) {
486                 pingtimeout, rand() % 100000
487         });
488         timeout_add(&periodictimer, periodic_handler, &periodictimer, &(struct timeval) {
489                 0, 0
490         });
491
492 #ifndef HAVE_MINGW
493         signal_t sighup = {0};
494         signal_t sigterm = {0};
495         signal_t sigquit = {0};
496         signal_t sigint = {0};
497         signal_t sigalrm = {0};
498
499         signal_add(&sighup, sighup_handler, &sighup, SIGHUP);
500         signal_add(&sigterm, sigterm_handler, &sigterm, SIGTERM);
501         signal_add(&sigquit, sigterm_handler, &sigquit, SIGQUIT);
502         signal_add(&sigint, sigterm_handler, &sigint, SIGINT);
503         signal_add(&sigalrm, sigalrm_handler, &sigalrm, SIGALRM);
504 #endif
505
506         if(!event_loop()) {
507                 logger(DEBUG_ALWAYS, LOG_ERR, "Error while waiting for input: %s", sockstrerror(sockerrno));
508                 return 1;
509         }
510
511 #ifndef HAVE_MINGW
512         signal_del(&sighup);
513         signal_del(&sigterm);
514         signal_del(&sigquit);
515         signal_del(&sigint);
516         signal_del(&sigalrm);
517 #endif
518
519         timeout_del(&periodictimer);
520         timeout_del(&pingtimer);
521
522         return 0;
523 }