Correctly add/remove outgoing connections when reloading configuration.
[tinc] / src / net.c
1 /*
2     net.c -- most of the network code
3     Copyright (C) 1998-2005 Ivo Timmermans,
4                   2000-2012 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 "utils.h"
26 #include "splay_tree.h"
27 #include "conf.h"
28 #include "connection.h"
29 #include "device.h"
30 #include "graph.h"
31 #include "logger.h"
32 #include "meta.h"
33 #include "net.h"
34 #include "netutl.h"
35 #include "process.h"
36 #include "protocol.h"
37 #include "subnet.h"
38 #include "xalloc.h"
39
40 int contradicting_add_edge = 0;
41 int contradicting_del_edge = 0;
42 static int sleeptime = 10;
43 time_t last_config_check = 0;
44
45 /* Purge edges and subnets of unreachable nodes. Use carefully. */
46
47 void purge(void) {
48         splay_node_t *nnode, *nnext, *enode, *enext, *snode, *snext;
49         node_t *n;
50         edge_t *e;
51         subnet_t *s;
52
53         logger(DEBUG_PROTOCOL, LOG_DEBUG, "Purging unreachable nodes");
54
55         /* Remove all edges and subnets owned by unreachable nodes. */
56
57         for(nnode = node_tree->head; nnode; nnode = nnext) {
58                 nnext = nnode->next;
59                 n = nnode->data;
60
61                 if(!n->status.reachable) {
62                         logger(DEBUG_SCARY_THINGS, LOG_DEBUG, "Purging node %s (%s)", n->name, n->hostname);
63
64                         for(snode = n->subnet_tree->head; snode; snode = snext) {
65                                 snext = snode->next;
66                                 s = snode->data;
67                                 send_del_subnet(everyone, s);
68                                 if(!strictsubnets)
69                                         subnet_del(n, s);
70                         }
71
72                         for(enode = n->edge_tree->head; enode; enode = enext) {
73                                 enext = enode->next;
74                                 e = enode->data;
75                                 if(!tunnelserver)
76                                         send_del_edge(everyone, e);
77                                 edge_del(e);
78                         }
79                 }
80         }
81
82         /* Check if anyone else claims to have an edge to an unreachable node. If not, delete node. */
83
84         for(nnode = node_tree->head; nnode; nnode = nnext) {
85                 nnext = nnode->next;
86                 n = nnode->data;
87
88                 if(!n->status.reachable) {
89                         for(enode = edge_weight_tree->head; enode; enode = enext) {
90                                 enext = enode->next;
91                                 e = enode->data;
92
93                                 if(e->to == n)
94                                         break;
95                         }
96
97                         if(!enode && (!strictsubnets || !n->subnet_tree->head))
98                                 /* in strictsubnets mode do not delete nodes with subnets */
99                                 node_del(n);
100                 }
101         }
102 }
103
104 /*
105   Terminate a connection:
106   - Close the socket
107   - Remove associated edge and tell other connections about it if report = true
108   - Check if we need to retry making an outgoing connection
109   - Deactivate the host
110 */
111 void terminate_connection(connection_t *c, bool report) {
112         logger(DEBUG_CONNECTIONS, LOG_NOTICE, "Closing connection with %s (%s)",
113                            c->name, c->hostname);
114
115         c->status.active = false;
116
117         if(c->node && c->node->connection == c)
118                 c->node->connection = NULL;
119
120         if(c->edge) {
121                 if(report && !tunnelserver)
122                         send_del_edge(everyone, c->edge);
123
124                 edge_del(c->edge);
125                 c->edge = NULL;
126
127                 /* Run MST and SSSP algorithms */
128
129                 graph();
130
131                 /* If the node is not reachable anymore but we remember it had an edge to us, clean it up */
132
133                 if(report && !c->node->status.reachable) {
134                         edge_t *e;
135                         e = lookup_edge(c->node, myself);
136                         if(e) {
137                                 if(!tunnelserver)
138                                         send_del_edge(everyone, e);
139                                 edge_del(e);
140                         }
141                 }
142         }
143
144         free_connection_partially(c);
145
146         /* Check if this was our outgoing connection */
147
148         if(c->outgoing) {
149                 do_outgoing_connection(c);
150         } else {
151                 connection_del(c);
152         }
153 }
154
155 /*
156   Check if the other end is active.
157   If we have sent packets, but didn't receive any,
158   then possibly the other end is dead. We send a
159   PING request over the meta connection. If the other
160   end does not reply in time, we consider them dead
161   and close the connection.
162 */
163 static void timeout_handler(int fd, short events, void *event) {
164         splay_node_t *node, *next;
165         connection_t *c;
166         time_t now = time(NULL);
167
168         for(node = connection_tree->head; node; node = next) {
169                 next = node->next;
170                 c = node->data;
171
172                 if(c->status.control)
173                         continue;
174
175                 if(c->last_ping_time + pingtimeout <= now) {
176                         if(c->status.active) {
177                                 if(c->status.pinged) {
178                                         logger(DEBUG_CONNECTIONS, LOG_INFO, "%s (%s) didn't respond to PING in %ld seconds",
179                                                            c->name, c->hostname, (long)now - c->last_ping_time);
180                                         terminate_connection(c, true);
181                                         continue;
182                                 } else if(c->last_ping_time + pinginterval <= now) {
183                                         send_ping(c);
184                                 }
185                         } else {
186                                 if(c->status.connecting) {
187                                         logger(DEBUG_CONNECTIONS, LOG_WARNING, "Timeout while connecting to %s (%s)", c->name, c->hostname);
188                                         c->status.connecting = false;
189                                         closesocket(c->socket);
190                                         do_outgoing_connection(c);
191                                 } else {
192                                         logger(DEBUG_CONNECTIONS, LOG_WARNING, "Timeout from %s (%s) during authentication", c->name, c->hostname);
193                                         terminate_connection(c, false);
194                                         continue;
195                                 }
196                         }
197                 }
198         }
199
200         if(contradicting_del_edge > 100 && contradicting_add_edge > 100) {
201                 logger(DEBUG_ALWAYS, LOG_WARNING, "Possible node with same Name as us! Sleeping %d seconds.", sleeptime);
202                 usleep(sleeptime * 1000000LL);
203                 sleeptime *= 2;
204                 if(sleeptime < 0)
205                         sleeptime = 3600;
206         } else {
207                 sleeptime /= 2;
208                 if(sleeptime < 10)
209                         sleeptime = 10;
210         }
211
212         contradicting_add_edge = 0;
213         contradicting_del_edge = 0;
214
215         event_add(event, &(struct timeval){pingtimeout, 0});
216 }
217
218 void handle_meta_connection_data(int fd, short events, void *data) {
219         connection_t *c = data;
220         int result;
221         socklen_t len = sizeof result;
222
223         if(c->status.connecting) {
224                 c->status.connecting = false;
225
226                 getsockopt(c->socket, SOL_SOCKET, SO_ERROR, &result, &len);
227
228                 if(!result)
229                         finish_connecting(c);
230                 else {
231                         logger(DEBUG_CONNECTIONS, LOG_DEBUG,
232                                            "Error while connecting to %s (%s): %s",
233                                            c->name, c->hostname, sockstrerror(result));
234                         closesocket(c->socket);
235                         do_outgoing_connection(c);
236                         return;
237                 }
238         }
239
240         if (!receive_meta(c)) {
241                 terminate_connection(c, c->status.active);
242                 return;
243         }
244 }
245
246 static void sigterm_handler(int signal, short events, void *data) {
247         logger(DEBUG_ALWAYS, LOG_NOTICE, "Got %s signal", strsignal(signal));
248         event_loopexit(NULL);
249 }
250
251 static void sighup_handler(int signal, short events, void *data) {
252         logger(DEBUG_ALWAYS, LOG_NOTICE, "Got %s signal", strsignal(signal));
253         reopenlogger();
254         reload_configuration();
255 }
256
257 static void sigalrm_handler(int signal, short events, void *data) {
258         logger(DEBUG_ALWAYS, LOG_NOTICE, "Got %s signal", strsignal(signal));
259         retry();
260 }
261
262 int reload_configuration(void) {
263         connection_t *c;
264         splay_node_t *node, *next;
265         char *fname;
266         struct stat s;
267
268         /* Reread our own configuration file */
269
270         exit_configuration(&config_tree);
271         init_configuration(&config_tree);
272
273         if(!read_server_config()) {
274                 logger(DEBUG_ALWAYS, LOG_ERR, "Unable to reread configuration file, exitting.");
275                 event_loopexit(NULL);
276                 return EINVAL;
277         }
278
279         read_config_options(config_tree, NULL);
280
281         xasprintf(&fname, "%s" SLASH "hosts" SLASH "%s", confbase, myself->name);
282         read_config_file(config_tree, fname);
283         free(fname);    
284
285         /* Parse some options that are allowed to be changed while tinc is running */
286
287         setup_myself_reloadable();
288
289         /* If StrictSubnet is set, expire deleted Subnets and read new ones in */
290
291         if(strictsubnets) {
292                 subnet_t *subnet;
293
294                 for(node = subnet_tree->head; node; node = node->next) {
295                         subnet = node->data;
296                         subnet->expires = 1;
297                 }
298
299                 load_all_subnets();
300
301                 for(node = subnet_tree->head; node; node = next) {
302                         next = node->next;
303                         subnet = node->data;
304                         if(subnet->expires == 1) {
305                                 send_del_subnet(everyone, subnet);
306                                 if(subnet->owner->status.reachable)
307                                         subnet_update(subnet->owner, subnet, false);
308                                 subnet_del(subnet->owner, subnet);
309                         } else if(subnet->expires == -1) {
310                                 subnet->expires = 0;
311                         } else {
312                                 send_add_subnet(everyone, subnet);
313                                 if(subnet->owner->status.reachable)
314                                         subnet_update(subnet->owner, subnet, true);
315                         }
316                 }
317         } else { /* Only read our own subnets back in */
318                 subnet_t *subnet, *s2;
319
320                 for(node = myself->subnet_tree->head; node; node = node->next) {
321                         subnet_t *subnet = node->data;
322                         logger(DEBUG_ALWAYS, LOG_DEBUG, "subnet %p expires %d", subnet, (int)subnet->expires);
323                         if(!subnet->expires)
324                                 subnet->expires = 1;
325                 }
326
327                 config_t *cfg = lookup_config(config_tree, "Subnet");
328
329                 while(cfg) {
330                         if(!get_config_subnet(cfg, &subnet))
331                                 continue;
332
333                         if((s2 = lookup_subnet(myself, subnet))) {
334                                 logger(DEBUG_ALWAYS, LOG_DEBUG, "read subnet that already exists: %p expires %d", s2, (int)s2->expires);
335                                 if(s2->expires == 1)
336                                         s2->expires = 0;
337
338                                 free_subnet(subnet);
339                         } else {
340                                 logger(DEBUG_ALWAYS, LOG_DEBUG, "read new subnet %p", subnet);
341                                 subnet_add(myself, subnet);
342                                 send_add_subnet(everyone, subnet);
343                                 subnet_update(myself, subnet, true);
344                         }
345
346                         cfg = lookup_config_next(config_tree, cfg);
347                 }
348
349                 for(node = myself->subnet_tree->head; node; node = next) {
350                         next = node->next;
351                         subnet_t *subnet = node->data;
352                         if(subnet->expires == 1) {
353                                 logger(DEBUG_ALWAYS, LOG_DEBUG, "removed subnet %p", subnet);
354                                 send_del_subnet(everyone, subnet);
355                                 subnet_update(myself, subnet, false);
356                                 subnet_del(myself, subnet);
357                         }
358                 }
359         }
360
361         /* Try to make outgoing connections */
362         
363         try_outgoing_connections();
364
365         /* Close connections to hosts that have a changed or deleted host config file */
366
367         for(node = connection_tree->head; node; node = next) {
368                 c = node->data;
369                 next = node->next;
370
371                 if(c->status.control)
372                         continue;
373
374                 xasprintf(&fname, "%s" SLASH "hosts" SLASH "%s", confbase, c->name);
375                 if(stat(fname, &s) || s.st_mtime > last_config_check) {
376                         fprintf(stderr, "ZOMG %ld > %ld\n", s.st_mtime, last_config_check);
377                         terminate_connection(c, c->status.active);
378                 }
379                 free(fname);
380         }
381
382         last_config_check = time(NULL);
383
384         return 0;
385 }
386
387 void retry(void) {
388         connection_t *c;
389         splay_node_t *node, *next;
390
391         for(node = connection_tree->head; node; node = next) {
392                 next = node->next;
393                 c = node->data;
394                 
395                 if(c->outgoing && !c->node) {
396                         if(timeout_initialized(&c->outgoing->ev))
397                                 event_del(&c->outgoing->ev);
398                         if(c->status.connecting)
399                                 close(c->socket);
400                         c->outgoing->timeout = 0;
401                         do_outgoing_connection(c);
402                 }
403         }
404 }
405
406 /*
407   this is where it all happens...
408 */
409 int main_loop(void) {
410         struct event timeout_event;
411
412         timeout_set(&timeout_event, timeout_handler, &timeout_event);
413         event_add(&timeout_event, &(struct timeval){pingtimeout, 0});
414
415 #ifndef HAVE_MINGW
416         struct event sighup_event;
417         struct event sigterm_event;
418         struct event sigquit_event;
419         struct event sigalrm_event;
420
421         signal_set(&sighup_event, SIGHUP, sighup_handler, NULL);
422         signal_add(&sighup_event, NULL);
423         signal_set(&sigterm_event, SIGTERM, sigterm_handler, NULL);
424         signal_add(&sigterm_event, NULL);
425         signal_set(&sigquit_event, SIGQUIT, sigterm_handler, NULL);
426         signal_add(&sigquit_event, NULL);
427         signal_set(&sigalrm_event, SIGALRM, sigalrm_handler, NULL);
428         signal_add(&sigalrm_event, NULL);
429 #endif
430
431         if(event_loop(0) < 0) {
432                 logger(DEBUG_ALWAYS, LOG_ERR, "Error while waiting for input: %s", strerror(errno));
433                 return 1;
434         }
435
436 #ifndef HAVE_MINGW
437         signal_del(&sighup_event);
438         signal_del(&sigterm_event);
439         signal_del(&sigquit_event);
440         signal_del(&sigalrm_event);
441 #endif
442
443         event_del(&timeout_event);
444
445         return 0;
446 }