K&R style braces
[tinc] / src / net.c
1 /*
2     net.c -- most of the network code
3     Copyright (C) 1998-2005 Ivo Timmermans,
4                   2000-2006 Guus Sliepen <guus@tinc-vpn.org>
5
6     This program is free software; you can redistribute it and/or modify
7     it under the terms of the GNU General Public License as published by
8     the Free Software Foundation; either version 2 of the License, or
9     (at your option) any later version.
10
11     This program is distributed in the hope that it will be useful,
12     but WITHOUT ANY WARRANTY; without even the implied warranty of
13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14     GNU General Public License for more details.
15
16     You should have received a copy of the GNU General Public License
17     along with this program; if not, write to the Free Software
18     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19
20     $Id$
21 */
22
23 #include "system.h"
24
25 #include <openssl/rand.h>
26
27 #include "utils.h"
28 #include "avl_tree.h"
29 #include "conf.h"
30 #include "connection.h"
31 #include "device.h"
32 #include "graph.h"
33 #include "logger.h"
34 #include "meta.h"
35 #include "net.h"
36 #include "netutl.h"
37 #include "process.h"
38 #include "protocol.h"
39 #include "subnet.h"
40 #include "xalloc.h"
41
42 /* Purge edges and subnets of unreachable nodes. Use carefully. */
43
44 static void purge(void) {
45         avl_node_t *nnode, *nnext, *enode, *enext, *snode, *snext;
46         node_t *n;
47         edge_t *e;
48         subnet_t *s;
49
50         cp();
51
52         ifdebug(PROTOCOL) logger(LOG_DEBUG, _("Purging unreachable nodes"));
53
54         /* Remove all edges and subnets owned by unreachable nodes. */
55
56         for(nnode = node_tree->head; nnode; nnode = nnext) {
57                 nnext = nnode->next;
58                 n = nnode->data;
59
60                 if(!n->status.reachable) {
61                         ifdebug(SCARY_THINGS) logger(LOG_DEBUG, _("Purging node %s (%s)"), n->name,
62                                            n->hostname);
63
64                         for(snode = n->subnet_tree->head; snode; snode = snext) {
65                                 snext = snode->next;
66                                 s = snode->data;
67                                 if(!tunnelserver)
68                                         send_del_subnet(broadcast, s);
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(broadcast, 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)
98                                 node_del(n);
99                 }
100         }
101 }
102
103 /*
104   put all file descriptors into events
105   While we're at it, purge stuf that needs to be removed.
106 */
107 static int build_fdset(void) {
108         avl_node_t *node, *next;
109         connection_t *c;
110         int i, max = 0;
111
112         cp();
113
114         for(node = connection_tree->head; node; node = next) {
115                 next = node->next;
116                 c = node->data;
117
118                 if(c->status.remove) {
119                         connection_del(c);
120                         if(!connection_tree->head)
121                                 purge();
122                 }
123         }
124
125         return 0;
126 }
127
128 /*
129   Terminate a connection:
130   - Close the socket
131   - Remove associated edge and tell other connections about it if report = true
132   - Check if we need to retry making an outgoing connection
133   - Deactivate the host
134 */
135 void terminate_connection(connection_t *c, bool report) {
136         cp();
137
138         if(c->status.remove)
139                 return;
140
141         ifdebug(CONNECTIONS) logger(LOG_NOTICE, _("Closing connection with %s (%s)"),
142                            c->name, c->hostname);
143
144         c->status.remove = true;
145         c->status.active = false;
146
147         if(c->node)
148                 c->node->connection = NULL;
149
150         if(c->socket)
151                 closesocket(c->socket);
152
153         event_del(&c->ev);
154
155         if(c->edge) {
156                 if(report && !tunnelserver)
157                         send_del_edge(broadcast, c->edge);
158
159                 edge_del(c->edge);
160
161                 /* Run MST and SSSP algorithms */
162
163                 graph();
164
165                 /* If the node is not reachable anymore but we remember it had an edge to us, clean it up */
166
167                 if(report && !c->node->status.reachable) {
168                         edge_t *e;
169                         e = lookup_edge(c->node, myself);
170                         if(e) {
171                                 if(!tunnelserver)
172                                         send_del_edge(broadcast, e);
173                                 edge_del(e);
174                         }
175                 }
176         }
177
178         /* Check if this was our outgoing connection */
179
180         if(c->outgoing) {
181                 retry_outgoing(c->outgoing);
182                 c->outgoing = NULL;
183         }
184
185         free(c->outbuf);
186         c->outbuf = NULL;
187         c->outbuflen = 0;
188         c->outbufsize = 0;
189         c->outbufstart = 0;
190 }
191
192 /*
193   Check if the other end is active.
194   If we have sent packets, but didn't receive any,
195   then possibly the other end is dead. We send a
196   PING request over the meta connection. If the other
197   end does not reply in time, we consider them dead
198   and close the connection.
199 */
200 static void timeout_handler(int fd, short events, void *event) {
201         avl_node_t *node, *next;
202         connection_t *c;
203         time_t now = time(NULL);
204
205         cp();
206
207         for(node = connection_tree->head; node; node = next) {
208                 next = node->next;
209                 c = node->data;
210
211                 if(c->last_ping_time + pingtimeout < now) {
212                         if(c->status.active) {
213                                 if(c->status.pinged) {
214                                         ifdebug(CONNECTIONS) logger(LOG_INFO, _("%s (%s) didn't respond to PING in %ld seconds"),
215                                                            c->name, c->hostname, now - c->last_ping_time);
216                                         c->status.timeout = true;
217                                         terminate_connection(c, true);
218                                 } else if(c->last_ping_time + pinginterval < now) {
219                                         send_ping(c);
220                                 }
221                         } else {
222                                 if(c->status.remove) {
223                                         logger(LOG_WARNING, _("Old connection_t for %s (%s) status %04x still lingering, deleting..."),
224                                                    c->name, c->hostname, c->status.value);
225                                         connection_del(c);
226                                         continue;
227                                 }
228                                 ifdebug(CONNECTIONS) logger(LOG_WARNING, _("Timeout from %s (%s) during authentication"),
229                                                    c->name, c->hostname);
230                                 if(c->status.connecting) {
231                                         c->status.connecting = false;
232                                         closesocket(c->socket);
233                                         do_outgoing_connection(c);
234                                 } else {
235                                         terminate_connection(c, false);
236                                 }
237                         }
238                 }
239         }
240
241         event_add(event, &(struct timeval){pingtimeout, 0});
242 }
243
244 void handle_meta_connection_data(int fd, short events, void *data) {
245         connection_t *c = data;
246         int result;
247         socklen_t len = sizeof(result);
248
249         if (c->status.remove)
250                 return;
251
252         if(c->status.connecting) {
253                 getsockopt(c->socket, SOL_SOCKET, SO_ERROR, &result, &len);
254
255                 if(!result)
256                         finish_connecting(c);
257                 else {
258                         ifdebug(CONNECTIONS) logger(LOG_DEBUG,
259                                            _("Error while connecting to %s (%s): %s"),
260                                            c->name, c->hostname, strerror(result));
261                         c->status.connecting = false;
262                         closesocket(c->socket);
263                         do_outgoing_connection(c);
264                         return;
265                 }
266         }
267
268         if (!receive_meta(c)) {
269                 terminate_connection(c, c->status.active);
270                 return;
271         }
272 }
273
274 static void sigterm_handler(int signal, short events, void *data) {
275         logger(LOG_NOTICE, _("Got %s signal"), strsignal(signal));
276         event_loopexit(NULL);
277 }
278
279 static void sigint_handler(int signal, short events, void *data) {
280         static int saved_debug_level = -1;
281
282         logger(LOG_NOTICE, _("Got %s signal"), strsignal(signal));
283
284         if(saved_debug_level != -1) {
285                 logger(LOG_NOTICE, _("Reverting to old debug level (%d)"),
286                         saved_debug_level);
287                 debug_level = saved_debug_level;
288                 saved_debug_level = -1;
289         } else {
290                 logger(LOG_NOTICE,
291                         _("Temporarily setting debug level to 5.  Kill me with SIGINT again to go back to level %d."),
292                         debug_level);
293                 saved_debug_level = debug_level;
294                 debug_level = 5;
295         }
296 }
297
298 static void sigusr1_handler(int signal, short events, void *data) {
299         logger(LOG_NOTICE, _("Got %s signal"), strsignal(signal));
300         dump_connections();
301 }
302
303 static void sigusr2_handler(int signal, short events, void *data) {
304         logger(LOG_NOTICE, _("Got %s signal"), strsignal(signal));
305         dump_device_stats();
306         dump_nodes();
307         dump_edges();
308         dump_subnets();
309 }
310
311 static void sigwinch_handler(int signal, short events, void *data) {
312         logger(LOG_NOTICE, _("Got %s signal"), strsignal(signal));
313         purge();
314 }
315
316 static void sighup_handler(int signal, short events, void *data) {
317         connection_t *c;
318         avl_node_t *node;
319         char *fname;
320         struct stat s;
321         static time_t last_config_check = 0;
322         
323         logger(LOG_NOTICE, _("Got %s signal"), strsignal(signal));
324
325         /* Reread our own configuration file */
326
327         exit_configuration(&config_tree);
328         init_configuration(&config_tree);
329
330         if(!read_server_config()) {
331                 logger(LOG_ERR, _("Unable to reread configuration file, exitting."));
332                 event_loopexit(NULL);
333                 return;
334         }
335
336         /* Close connections to hosts that have a changed or deleted host config file */
337         
338         for(node = connection_tree->head; node; node = node->next) {
339                 c = node->data;
340                 
341                 if(c->outgoing) {
342                         free(c->outgoing->name);
343                         if(c->outgoing->ai)
344                                 freeaddrinfo(c->outgoing->ai);
345                         free(c->outgoing);
346                         c->outgoing = NULL;
347                 }
348                 
349                 asprintf(&fname, "%s/hosts/%s", confbase, c->name);
350                 if(stat(fname, &s) || s.st_mtime > last_config_check)
351                         terminate_connection(c, c->status.active);
352                 free(fname);
353         }
354
355         last_config_check = time(NULL);
356
357         /* Try to make outgoing connections */
358         
359         try_outgoing_connections();
360 }
361
362 static void sigalrm_handler(int signal, short events, void *data) {
363         logger(LOG_NOTICE, _("Got %s signal"), strsignal(signal));
364
365         connection_t *c;
366         avl_node_t *node;
367
368         for(node = connection_tree->head; node; node = node->next) {
369                 c = node->data;
370                 
371                 if(c->outgoing && !c->node) {
372                         if(timeout_initialized(&c->outgoing->ev))
373                                 event_del(&c->outgoing->ev);
374                         if(c->status.connecting)
375                                 close(c->socket);
376                         c->outgoing->timeout = 0;
377                         do_outgoing_connection(c);
378                 }
379         }
380 }
381
382 /*
383   this is where it all happens...
384 */
385 int main_loop(void) {
386         struct timeval tv;
387         int r;
388         struct event timeout_event;
389         struct event sighup_event;
390         struct event sigint_event;
391         struct event sigterm_event;
392         struct event sigquit_event;
393         struct event sigusr1_event;
394         struct event sigusr2_event;
395         struct event sigwinch_event;
396         struct event sigalrm_event;
397
398         cp();
399
400         timeout_set(&timeout_event, timeout_handler, &timeout_event);
401         event_add(&timeout_event, &(struct timeval){pingtimeout, 0});
402         signal_set(&sighup_event, SIGHUP, sighup_handler, NULL);
403         signal_add(&sighup_event, NULL);
404         signal_set(&sigint_event, SIGINT, sigint_handler, NULL);
405         signal_add(&sigint_event, NULL);
406         signal_set(&sigterm_event, SIGTERM, sigterm_handler, NULL);
407         signal_add(&sigterm_event, NULL);
408         signal_set(&sigquit_event, SIGQUIT, sigterm_handler, NULL);
409         signal_add(&sigquit_event, NULL);
410         signal_set(&sigusr1_event, SIGUSR1, sigusr1_handler, NULL);
411         signal_add(&sigusr1_event, NULL);
412         signal_set(&sigusr2_event, SIGUSR2, sigusr2_handler, NULL);
413         signal_add(&sigusr2_event, NULL);
414         signal_set(&sigwinch_event, SIGWINCH, sigwinch_handler, NULL);
415         signal_add(&sigwinch_event, NULL);
416         signal_set(&sigalrm_event, SIGALRM, sigalrm_handler, NULL);
417         signal_add(&sigalrm_event, NULL);
418
419         if(event_loop(0) < 0) {
420                 logger(LOG_ERR, _("Error while waiting for input: %s"), strerror(errno));
421                 return 1;
422         }
423
424         signal_del(&sighup_event);
425         signal_del(&sigint_event);
426         signal_del(&sigterm_event);
427         signal_del(&sigquit_event);
428         signal_del(&sigusr1_event);
429         signal_del(&sigusr2_event);
430         signal_del(&sigwinch_event);
431         signal_del(&sigalrm_event);
432         event_del(&timeout_event);
433
434         return 0;
435 }