Add syslog wrapper
[tinc] / src / net.c
1 /*
2     net.c -- most of the network code
3     Copyright (C) 1998-2002 Ivo Timmermans <itimmermans@bigfoot.com>,
4                   2000-2002 Guus Sliepen <guus@sliepen.warande.net>
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: net.c,v 1.37 2002/04/09 15:26:00 zarq Exp $
21 */
22
23 #include "config.h"
24
25 #include <errno.h>
26 #include <fcntl.h>
27 #include <netdb.h>
28 #include <netinet/in.h>
29 #ifdef HAVE_LINUX
30  #include <netinet/ip.h>
31  #include <netinet/tcp.h>
32 #endif
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <string.h>
36 #include <signal.h>
37 #include <sys/time.h>
38 #include <sys/types.h>
39 #include <syslog.h>
40 #include <unistd.h>
41 #include <sys/ioctl.h>
42 /* SunOS really wants sys/socket.h BEFORE net/if.h,
43    and FreeBSD wants these lines below the rest. */
44 #include <arpa/inet.h>
45 #include <sys/socket.h>
46 #include <net/if.h>
47
48 #include <openssl/rand.h>
49
50 #include <utils.h>
51 #include <xalloc.h>
52 #include <avl_tree.h>
53 #include <list.h>
54
55 #include "conf.h"
56 #include "connection.h"
57 #include "meta.h"
58 #include "net.h"
59 #include "netutl.h"
60 #include "process.h"
61 #include "protocol.h"
62 #include "subnet.h"
63 #include "graph.h"
64 #include "process.h"
65 #include "route.h"
66 #include "device.h"
67 #include "event.h"
68
69 #include "system.h"
70
71 int do_purge = 0;
72 int sighup = 0;
73 int sigalrm = 0;
74
75 time_t now = 0;
76
77 /* Purge edges and subnets of unreachable nodes. Use carefully. */
78
79 void purge(void)
80 {
81   avl_node_t *nnode, *nnext, *enode, *enext, *snode, *snext, *cnode;
82   node_t *n;
83   edge_t *e;
84   subnet_t *s;
85   connection_t *c;
86 cp
87   if(debug_lvl >= DEBUG_PROTOCOL)
88     syslog(LOG_DEBUG, _("Purging unreachable nodes"));
89
90   for(nnode = node_tree->head; nnode; nnode = nnext)
91   {
92     nnext = nnode->next;
93     n = (node_t *)nnode->data;
94
95     if(!n->status.reachable)
96     {
97       if(debug_lvl >= DEBUG_SCARY_THINGS)
98         syslog(LOG_DEBUG, _("Purging node %s (%s)"), n->name, n->hostname);
99
100       for(snode = n->subnet_tree->head; snode; snode = snext)
101       {
102         snext = snode->next;
103         s = (subnet_t *)snode->data;
104
105         for(cnode = connection_tree->head; cnode; cnode = cnode->next)
106         {
107           c = (connection_t *)cnode->data;
108           if(c->status.active)
109             send_del_subnet(c, s);
110         }
111
112         subnet_del(n, s);
113       }
114
115       for(enode = n->edge_tree->head; enode; enode = enext)
116       {
117         enext = enode->next;
118         e = (edge_t *)enode->data;
119
120         for(cnode = connection_tree->head; cnode; cnode = cnode->next)
121         {
122           c = (connection_t *)cnode->data;
123           if(c->status.active)
124             send_del_edge(c, e);
125         }
126
127         edge_del(e);
128       }
129
130       node_del(n);
131     }
132   }
133 cp
134 }
135
136 /*
137   put all file descriptors in an fd_set array
138   While we're at it, purge stuff that needs to be removed.
139 */
140 void build_fdset(fd_set *fs)
141 {
142   avl_node_t *node, *next;
143   connection_t *c;
144   int i;
145 cp
146   FD_ZERO(fs);
147
148   for(node = connection_tree->head; node; node = next)
149     {
150       next = node->next;
151       c = (connection_t *)node->data;
152
153       if(c->status.remove)
154         connection_del(c);
155       else
156         FD_SET(c->socket, fs);
157     }
158
159   if(!connection_tree->head)
160     purge();
161
162   for(i = 0; i < listen_sockets; i++)
163     {
164       FD_SET(listen_socket[i].tcp, fs);
165       FD_SET(listen_socket[i].udp, fs);
166     }
167
168   FD_SET(device_fd, fs);
169 cp
170 }
171
172 /*
173   Terminate a connection:
174   - Close the socket
175   - Remove associated edge and tell other connections about it if report = 1
176   - Check if we need to retry making an outgoing connection
177   - Deactivate the host
178 */
179 void terminate_connection(connection_t *c, int report)
180 {
181   avl_node_t *node;
182   connection_t *other;
183 cp
184   if(c->status.remove)
185     return;
186
187   if(debug_lvl >= DEBUG_CONNECTIONS)
188     syslog(LOG_NOTICE, _("Closing connection with %s (%s)"),
189            c->name, c->hostname);
190
191   c->status.remove = 1;
192   c->status.active = 0;
193
194   if(c->node)
195     c->node->connection = NULL;
196
197   if(c->socket)
198     close(c->socket);
199
200   if(c->edge)
201     {
202       if(report)
203         {
204           for(node = connection_tree->head; node; node = node->next)
205             {
206               other = (connection_t *)node->data;
207               if(other->status.active && other != c)
208                 send_del_edge(other, c->edge);
209             }
210         }
211
212       edge_del(c->edge);
213
214       /* Run MST and SSSP algorithms */
215
216       graph();
217     }
218
219   /* Check if this was our outgoing connection */
220
221   if(c->outgoing)
222     {
223       retry_outgoing(c->outgoing);
224       c->outgoing = NULL;
225     }
226 cp
227 }
228
229 /*
230   Check if the other end is active.
231   If we have sent packets, but didn't receive any,
232   then possibly the other end is dead. We send a
233   PING request over the meta connection. If the other
234   end does not reply in time, we consider them dead
235   and close the connection.
236 */
237 void check_dead_connections(void)
238 {
239   avl_node_t *node, *next;
240   connection_t *c;
241 cp
242   for(node = connection_tree->head; node; node = next)
243     {
244       next = node->next;
245       c = (connection_t *)node->data;
246       if(c->last_ping_time + pingtimeout < now)
247         {
248           if(c->status.active)
249             {
250               if(c->status.pinged)
251                 {
252                   if(debug_lvl >= DEBUG_PROTOCOL)
253                     syslog(LOG_INFO, _("%s (%s) didn't respond to PING"),
254                            c->name, c->hostname);
255                   c->status.timeout = 1;
256                   terminate_connection(c, 1);
257                 }
258               else
259                 {
260                   send_ping(c);
261                 }
262             }
263           else
264             {
265               if(debug_lvl >= DEBUG_CONNECTIONS)
266                 syslog(LOG_WARNING, _("Timeout from %s (%s) during authentication"),
267                        c->name, c->hostname);
268               terminate_connection(c, 0);
269             }
270         }
271     }
272 cp
273 }
274
275 /*
276   check all connections to see if anything
277   happened on their sockets
278 */
279 void check_network_activity(fd_set *f)
280 {
281   connection_t *c;
282   avl_node_t *node;
283   int result, i;
284   int len = sizeof(result);
285   vpn_packet_t packet;
286 cp
287   if(FD_ISSET(device_fd, f))
288     {
289       if(!read_packet(&packet))
290         route_outgoing(&packet);
291     }
292
293   for(node = connection_tree->head; node; node = node->next)
294     {
295       c = (connection_t *)node->data;
296
297       if(c->status.remove)
298         continue;
299
300       if(FD_ISSET(c->socket, f))
301         {
302           if(c->status.connecting)
303             {
304               c->status.connecting = 0;
305               getsockopt(c->socket, SOL_SOCKET, SO_ERROR, &result, &len);
306               if(!result)
307                 finish_connecting(c);
308               else
309                 {
310                   if(debug_lvl >= DEBUG_CONNECTIONS)
311                     syslog(LOG_DEBUG, _("Error while connecting to %s (%s): %s"), c->name, c->hostname, strerror(result));
312                   close(c->socket);
313                   do_outgoing_connection(c);
314                   continue;
315                 }
316             }
317           if(receive_meta(c) < 0)
318             {
319               terminate_connection(c, c->status.active);
320               continue;
321             }
322         }
323     }
324
325   for(i = 0; i < listen_sockets; i++)
326     {
327       if(FD_ISSET(listen_socket[i].udp, f))
328         handle_incoming_vpn_data(listen_socket[i].udp);
329       if(FD_ISSET(listen_socket[i].tcp, f))
330         handle_new_meta_connection(listen_socket[i].tcp);
331     }
332 cp
333 }
334
335 /*
336   this is where it all happens...
337 */
338 void main_loop(void)
339 {
340   fd_set fset;
341   struct timeval tv;
342   int r;
343   time_t last_ping_check;
344   event_t *event;
345 cp
346   last_ping_check = now;
347
348   srand(now);
349
350   for(;;)
351     {
352       now = time(NULL);
353
354       tv.tv_sec = 1 + (rand() & 7); /* Approx. 5 seconds, randomized to prevent global synchronisation effects */
355       tv.tv_usec = 0;
356
357       build_fdset(&fset);
358
359       if((r = select(FD_SETSIZE, &fset, NULL, NULL, &tv)) < 0)
360         {
361           if(errno != EINTR && errno != EAGAIN)
362             {
363               syslog(LOG_ERR, _("Error while waiting for input: %s"), strerror(errno));
364               cp_trace();
365               dump_connections();
366               return;
367             }
368
369           continue;
370         }
371
372       check_network_activity(&fset);
373
374       if(do_purge)
375         {
376           purge();
377           do_purge = 0;
378         }
379
380       /* Let's check if everybody is still alive */
381
382       if(last_ping_check + pingtimeout < now)
383         {
384           check_dead_connections();
385           last_ping_check = now;
386
387           if(routing_mode== RMODE_SWITCH)
388             age_mac();
389
390           age_past_requests();
391
392           /* Should we regenerate our key? */
393
394           if(keyexpires < now)
395             {
396               if(debug_lvl >= DEBUG_STATUS)
397                 syslog(LOG_INFO, _("Regenerating symmetric key"));
398
399               RAND_pseudo_bytes(myself->key, myself->keylength);
400               send_key_changed(myself->connection, myself);
401               keyexpires = now + keylifetime;
402             }
403         }
404
405
406       while((event = get_expired_event()))
407         {
408           event->handler(event->data);
409           free(event);
410         }
411
412       if(sigalrm)
413         {
414           syslog(LOG_INFO, _("Flushing event queue"));
415
416           while(event_tree->head)
417             {
418               event = (event_t *)event_tree->head->data;
419               event->handler(event->data);
420               event_del(event);
421             }
422           sigalrm = 0;
423         }
424
425       if(sighup)
426         {
427           sighup = 0;
428           close_network_connections();
429           exit_configuration(&config_tree);
430
431           syslog(LOG_INFO, _("Rereading configuration file and restarting in 5 seconds..."));
432           sleep(5);
433
434           init_configuration(&config_tree);
435
436           if(read_server_config())
437             {
438               syslog(LOG_ERR, _("Unable to reread configuration file, exitting."));
439               exit(1);
440             }
441
442           if(setup_network_connections())
443             return;
444
445           continue;
446         }
447     }
448 cp
449 }