ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/gvpe/src/vpn.C
Revision: 1.36
Committed: Fri Apr 8 16:48:16 2005 UTC (19 years, 1 month ago) by pcg
Content type: text/plain
Branch: MAIN
Changes since 1.35: +1 -1 lines
Log Message:
*** empty log message ***

File Contents

# User Rev Content
1 pcg 1.1 /*
2     vpn.C -- handle the protocol, encryption, handshaking etc.
3 pcg 1.28 Copyright (C) 2003-2005 Marc Lehmann <gvpe@schmorp.de>
4 pcg 1.1
5 pcg 1.28 This file is part of GVPE.
6    
7     GVPE is free software; you can redistribute it and/or modify
8 pcg 1.1 it under the terms of the GNU General Public License as published by
9     the Free Software Foundation; either version 2 of the License, or
10     (at your option) any later version.
11    
12     This program is distributed in the hope that it will be useful,
13     but WITHOUT ANY WARRANTY; without even the implied warranty of
14     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15     GNU General Public License for more details.
16    
17     You should have received a copy of the GNU General Public License
18 pcg 1.28 along with gvpe; if not, write to the Free Software
19 pcg 1.1 Foundation, Inc. 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20     */
21    
22     #include "config.h"
23    
24     #include <list>
25    
26 pcg 1.23 #include <cstdio>
27     #include <cstring>
28 pcg 1.1 #include <cstdlib>
29    
30     #include <sys/types.h>
31     #include <sys/socket.h>
32     #include <sys/wait.h>
33     #include <errno.h>
34     #include <time.h>
35     #include <unistd.h>
36 pcg 1.11 #include <fcntl.h>
37 pcg 1.14 #include <sys/socket.h>
38 pcg 1.15
39     #include "netcompat.h"
40 pcg 1.1
41     #include "pidfile.h"
42    
43     #include "connection.h"
44     #include "util.h"
45     #include "vpn.h"
46    
47 pcg 1.20 vpn network; // THE vpn (bad design...)
48    
49 pcg 1.1 /////////////////////////////////////////////////////////////////////////////
50    
51 pcg 1.33 void
52     vpn::script_init_env ()
53 pcg 1.1 {
54     // the tunnel device mtu should be the physical mtu - overhead
55     // the tricky part is rounding to the cipher key blocksize
56     int mtu = conf.mtu - ETH_OVERHEAD - VPE_OVERHEAD - MAX_OVERHEAD;
57     mtu += ETH_OVERHEAD - 6 - 6; // now we have the data portion
58     mtu -= mtu % EVP_CIPHER_block_size (CIPHER); // round
59     mtu -= ETH_OVERHEAD - 6 - 6; // and get interface mtu again
60    
61     char *env;
62 pcg 1.21 asprintf (&env, "CONFBASE=%s", confbase); putenv (env);
63     asprintf (&env, "IFNAME=%s", tap->interface ()); putenv (env);
64     asprintf (&env, "IFTYPE=%s", IFTYPE); putenv (env);
65     asprintf (&env, "IFSUBTYPE=%s", IFSUBTYPE); putenv (env);
66     asprintf (&env, "MTU=%d", mtu); putenv (env);
67 pcg 1.34 asprintf (&env, "NODES=%d", conns.size ()); putenv (env);
68     asprintf (&env, "NODEID=%d", THISNODE->id); putenv (env);
69    
70     conns [THISNODE->id - 1]->script_init_env ("");
71 pcg 1.33
72 pcg 1.34 for (conns_vector::iterator c = conns.begin (); c != conns.end (); ++c)
73     {
74     char ext[16];
75     snprintf (ext, 16, "_%d", (*c)->conf->id);
76     (*c)->script_init_env (ext);
77     }
78 pcg 1.33 }
79    
80     const char *vpn::script_if_init ()
81     {
82     script_init_env ();
83 pcg 1.1
84 pcg 1.33 return tap->if_up ();
85     }
86    
87     const char *vpn::script_if_up ()
88     {
89     script_init_env ();
90    
91     char *filename;
92     asprintf (&filename,
93     "%s/%s",
94     confbase,
95     ::conf.script_if_up ? ::conf.script_if_up : "if-up");
96    
97     return filename;
98 pcg 1.1 }
99    
100     int
101     vpn::setup ()
102     {
103 pcg 1.8 ipv4_fd = -1;
104 pcg 1.1
105 pcg 1.8 if (THISNODE->protocols & PROT_IPv4 && ::conf.ip_proto)
106 pcg 1.1 {
107 pcg 1.8 ipv4_fd = socket (PF_INET, SOCK_RAW, ::conf.ip_proto);
108 pcg 1.1
109 pcg 1.8 if (ipv4_fd < 0)
110 pcg 1.1 return -1;
111    
112 pcg 1.11 fcntl (ipv4_fd, F_SETFL, O_NONBLOCK);
113    
114 pcg 1.14 #if defined(SOL_IP) && defined(IP_MTU_DISCOVER)
115 pcg 1.1 // this I really consider a linux bug. I am neither connected
116     // nor do I fragment myself. Linux still sets DF and doesn't
117     // fragment for me sometimes.
118     {
119     int oval = IP_PMTUDISC_DONT;
120 pcg 1.8 setsockopt (ipv4_fd, SOL_IP, IP_MTU_DISCOVER, &oval, sizeof oval);
121 pcg 1.1 }
122     #endif
123    
124 pcg 1.9 sockinfo si (THISNODE, PROT_IPv4);
125    
126     if (bind (ipv4_fd, si.sav4 (), si.salenv4 ()))
127     {
128     slog (L_ERR, _("can't bind ipv4 socket on %s: %s"), (const char *)si, strerror (errno));
129 pcg 1.23 exit (EXIT_FAILURE);
130 pcg 1.9 }
131    
132 pcg 1.22 ipv4_ev_watcher.start (ipv4_fd, EVENT_READ);
133 pcg 1.1 }
134    
135 pcg 1.8 udpv4_fd = -1;
136    
137     if (THISNODE->protocols & PROT_UDPv4 && THISNODE->udp_port)
138 pcg 1.1 {
139 pcg 1.8 udpv4_fd = socket (PF_INET, SOCK_DGRAM, IPPROTO_UDP);
140 pcg 1.1
141 pcg 1.8 if (udpv4_fd < 0)
142 pcg 1.1 return -1;
143    
144 pcg 1.11 fcntl (udpv4_fd, F_SETFL, O_NONBLOCK);
145    
146 pcg 1.8 // standard daemon practise...
147     {
148     int oval = 1;
149     setsockopt (udpv4_fd, SOL_SOCKET, SO_REUSEADDR, &oval, sizeof oval);
150     }
151    
152 pcg 1.14 #if defined(SOL_IP) && defined(IP_MTU_DISCOVER)
153 pcg 1.9 // this I really consider a linux bug. I am neither connected
154     // nor do I fragment myself. Linux still sets DF and doesn't
155     // fragment for me sometimes.
156     {
157     int oval = IP_PMTUDISC_DONT;
158     setsockopt (udpv4_fd, SOL_IP, IP_MTU_DISCOVER, &oval, sizeof oval);
159     }
160     #endif
161    
162 pcg 1.8 sockinfo si (THISNODE, PROT_UDPv4);
163 pcg 1.2
164 pcg 1.8 if (bind (udpv4_fd, si.sav4 (), si.salenv4 ()))
165 pcg 1.1 {
166 pcg 1.8 slog (L_ERR, _("can't bind udpv4 on %s: %s"), (const char *)si, strerror (errno));
167 pcg 1.23 exit (EXIT_FAILURE);
168 pcg 1.1 }
169    
170 pcg 1.22 udpv4_ev_watcher.start (udpv4_fd, EVENT_READ);
171 pcg 1.9 }
172    
173     icmpv4_fd = -1;
174    
175     #if ENABLE_ICMP
176     if (THISNODE->protocols & PROT_ICMPv4)
177     {
178     icmpv4_fd = socket (PF_INET, SOCK_RAW, IPPROTO_ICMP);
179    
180     if (icmpv4_fd < 0)
181     return -1;
182    
183 pcg 1.11 fcntl (icmpv4_fd, F_SETFL, O_NONBLOCK);
184    
185 pcg 1.9 #ifdef ICMP_FILTER
186     {
187     icmp_filter oval;
188     oval.data = 0xffffffff;
189     if (::conf.icmp_type < 32)
190     oval.data &= ~(1 << ::conf.icmp_type);
191    
192     setsockopt (icmpv4_fd, SOL_RAW, ICMP_FILTER, &oval, sizeof oval);
193     }
194     #endif
195    
196 pcg 1.14 #if defined(SOL_IP) && defined(IP_MTU_DISCOVER)
197 pcg 1.1 // this I really consider a linux bug. I am neither connected
198     // nor do I fragment myself. Linux still sets DF and doesn't
199     // fragment for me sometimes.
200     {
201     int oval = IP_PMTUDISC_DONT;
202 pcg 1.36 setsockopt (icmpv4_fd, SOL_IP, IP_MTU_DISCOVER, &oval, sizeof oval);
203 pcg 1.1 }
204     #endif
205    
206 pcg 1.9 sockinfo si (THISNODE, PROT_ICMPv4);
207    
208     if (bind (icmpv4_fd, si.sav4 (), si.salenv4 ()))
209     {
210     slog (L_ERR, _("can't bind icmpv4 on %s: %s"), (const char *)si, strerror (errno));
211 pcg 1.23 exit (EXIT_FAILURE);
212 pcg 1.9 }
213    
214 pcg 1.22 icmpv4_ev_watcher.start (icmpv4_fd, EVENT_READ);
215 pcg 1.1 }
216 pcg 1.9 #endif
217 pcg 1.1
218 pcg 1.8 tcpv4_fd = -1;
219    
220 pcg 1.2 #if ENABLE_TCP
221 pcg 1.8 if (THISNODE->protocols & PROT_TCPv4 && THISNODE->tcp_port)
222 pcg 1.2 {
223     tcpv4_fd = socket (PF_INET, SOCK_STREAM, IPPROTO_TCP);
224    
225     if (tcpv4_fd < 0)
226     return -1;
227    
228 pcg 1.11 fcntl (tcpv4_fd, F_SETFL, O_NONBLOCK);
229    
230 pcg 1.3 // standard daemon practise...
231     {
232     int oval = 1;
233     setsockopt (tcpv4_fd, SOL_SOCKET, SO_REUSEADDR, &oval, sizeof oval);
234     }
235    
236 pcg 1.2 sockinfo si (THISNODE, PROT_TCPv4);
237    
238     if (bind (tcpv4_fd, si.sav4 (), si.salenv4 ()))
239     {
240     slog (L_ERR, _("can't bind tcpv4 on %s: %s"), (const char *)si, strerror (errno));
241 pcg 1.23 exit (EXIT_FAILURE);
242 pcg 1.2 }
243    
244     if (listen (tcpv4_fd, 5))
245     {
246     slog (L_ERR, _("can't listen tcpv4 on %s: %s"), (const char *)si, strerror (errno));
247 pcg 1.23 exit (EXIT_FAILURE);
248 pcg 1.2 }
249    
250 pcg 1.22 tcpv4_ev_watcher.start (tcpv4_fd, EVENT_READ);
251 pcg 1.2 }
252     #endif
253    
254 pcg 1.24 #if ENABLE_DNS
255     if (THISNODE->protocols & PROT_DNSv4)
256     {
257 pcg 1.29 dns_forwarder.set (::conf.dns_forw_host, ::conf.dns_forw_port, PROT_DNSv4);
258    
259 pcg 1.24 dnsv4_fd = socket (PF_INET, SOCK_DGRAM, IPPROTO_UDP);
260    
261     if (dnsv4_fd < 0)
262     return -1;
263    
264 pcg 1.35 # if defined(SOL_IP) && defined(IP_MTU_DISCOVER)
265 pcg 1.32 // this I really consider a linux bug. I am neither connected
266     // nor do I fragment myself. Linux still sets DF and doesn't
267     // fragment for me sometimes.
268     {
269     int oval = IP_PMTUDISC_DONT;
270 pcg 1.35 setsockopt (dnsv4_fd, SOL_IP, IP_MTU_DISCOVER, &oval, sizeof oval);
271 pcg 1.32 }
272 pcg 1.35 # endif
273 pcg 1.32
274 pcg 1.24 // standard daemon practise...
275     {
276     int oval = 1;
277 pcg 1.31 setsockopt (dnsv4_fd, SOL_SOCKET, SO_REUSEADDR, &oval, sizeof oval);
278 pcg 1.24 }
279    
280 pcg 1.31 sockinfo si (THISNODE->dns_hostname,
281     THISNODE->dns_hostname ? THISNODE->dns_port : 0,
282     PROT_DNSv4);
283 pcg 1.24
284     if (bind (dnsv4_fd, si.sav4 (), si.salenv4 ()))
285     {
286     slog (L_ERR, _("can't bind dnsv4 on %s: %s"), (const char *)si, strerror (errno));
287     exit (EXIT_FAILURE);
288     }
289    
290     dnsv4_ev_watcher.start (dnsv4_fd, EVENT_READ);
291     }
292     #endif
293    
294 pcg 1.34 /////////////////////////////////////////////////////////////////////////////
295    
296     reconnect_all ();
297    
298     /////////////////////////////////////////////////////////////////////////////
299    
300 pcg 1.1 tap = new tap_device ();
301     if (!tap) //D this, of course, never catches
302     {
303     slog (L_ERR, _("cannot create network interface '%s'"), conf.ifname);
304 pcg 1.23 exit (EXIT_FAILURE);
305 pcg 1.1 }
306    
307 pcg 1.33 if (tap->if_up () &&
308     !run_script (run_script_cb (this, &vpn::script_if_init), true))
309     {
310     slog (L_ERR, _("interface initialization command '%s' failed, exiting."),
311     tap->if_up ());
312     exit (EXIT_FAILURE);
313     }
314    
315     if (!run_script (run_script_cb (this, &vpn::script_if_up), true))
316     {
317     slog (L_ERR, _("if-up command execution failed, exiting."));
318     exit (EXIT_FAILURE);
319     }
320 pcg 1.1
321 pcg 1.22 tap_ev_watcher.start (tap->fd, EVENT_READ);
322 pcg 1.1
323     return 0;
324     }
325    
326 pcg 1.7 bool
327 pcg 1.1 vpn::send_ipv4_packet (vpn_packet *pkt, const sockinfo &si, int tos)
328     {
329 pcg 1.14 #if defined(SOL_IP) && defined(IP_TOS)
330 pcg 1.1 setsockopt (ipv4_fd, SOL_IP, IP_TOS, &tos, sizeof tos);
331 pcg 1.14 #endif
332 pcg 1.1 sendto (ipv4_fd, &((*pkt)[0]), pkt->len, 0, si.sav4 (), si.salenv4 ());
333 pcg 1.7
334     return true;
335 pcg 1.1 }
336    
337 pcg 1.9 static u16
338     ipv4_checksum (u16 *data, unsigned int len)
339     {
340     // use 32 bit accumulator and fold back carry bits at the end
341     u32 sum = 0;
342    
343     while (len > 1)
344     {
345     sum += *data++;
346     len -= 2;
347     }
348    
349     // odd byte left?
350     if (len)
351     sum += *(u8 *)data;
352    
353     // add back carry bits
354     sum = (sum >> 16) + (sum & 0xffff); // lo += hi
355     sum += (sum >> 16); // carry
356    
357     return ~sum;
358     }
359    
360 pcg 1.13 #if ENABLE_ICMP
361 pcg 1.9 bool
362     vpn::send_icmpv4_packet (vpn_packet *pkt, const sockinfo &si, int tos)
363     {
364 pcg 1.14 #if defined(SOL_IP) && defined(IP_TOS)
365 pcg 1.9 setsockopt (icmpv4_fd, SOL_IP, IP_TOS, &tos, sizeof tos);
366 pcg 1.14 #endif
367 pcg 1.9
368     pkt->unshift_hdr (4);
369    
370 pcg 1.14 icmp_header *hdr = (icmp_header *)&((*pkt)[0]);
371 pcg 1.9 hdr->type = ::conf.icmp_type;
372     hdr->code = 255;
373     hdr->checksum = 0;
374     hdr->checksum = ipv4_checksum ((u16 *)hdr, pkt->len);
375    
376     sendto (icmpv4_fd, &((*pkt)[0]), pkt->len, 0, si.sav4 (), si.salenv4 ());
377    
378     return true;
379     }
380 pcg 1.13 #endif
381 pcg 1.9
382 pcg 1.7 bool
383 pcg 1.1 vpn::send_udpv4_packet (vpn_packet *pkt, const sockinfo &si, int tos)
384     {
385 pcg 1.14 #if defined(SOL_IP) && defined(IP_TOS)
386 pcg 1.1 setsockopt (udpv4_fd, SOL_IP, IP_TOS, &tos, sizeof tos);
387 pcg 1.14 #endif
388 pcg 1.1 sendto (udpv4_fd, &((*pkt)[0]), pkt->len, 0, si.sav4 (), si.salenv4 ());
389 pcg 1.7
390     return true;
391 pcg 1.1 }
392    
393     void
394 pcg 1.18 vpn::inject_data_packet (tap_packet *pkt, int dst)
395     {
396     if (dst)
397     {
398     // unicast
399     if (dst != THISNODE->id)
400     conns[dst - 1]->inject_data_packet (pkt);
401     }
402     else
403     {
404     // broadcast, this is ugly, but due to the security policy
405     // we have to connect to all hosts...
406     for (conns_vector::iterator c = conns.begin (); c != conns.end (); ++c)
407     if ((*c)->conf != THISNODE)
408     (*c)->inject_data_packet (pkt, true);
409     }
410     }
411    
412     void
413 pcg 1.1 vpn::recv_vpn_packet (vpn_packet *pkt, const sockinfo &rsi)
414     {
415     unsigned int src = pkt->src ();
416     unsigned int dst = pkt->dst ();
417    
418     slog (L_NOISE, _("<<?/%s received possible vpn packet type %d from %d to %d, length %d"),
419     (const char *)rsi, pkt->typ (), pkt->src (), pkt->dst (), pkt->len);
420    
421     if (src == 0 || src > conns.size ()
422     || dst > conns.size ()
423     || pkt->typ () >= vpn_packet::PT_MAX)
424     slog (L_WARN, _("(%s): received corrupted packet type %d (src %d, dst %d)"),
425     (const char *)rsi, pkt->typ (), pkt->src (), pkt->dst ());
426 pcg 1.6 else if (dst > conns.size ())
427     slog (L_WARN, _("(%s): received corrupted packet type %d (src %d, dst %d)"),
428     (const char *)rsi, pkt->typ (), pkt->src (), pkt->dst ());
429 pcg 1.1 else
430     {
431     connection *c = conns[src - 1];
432    
433 pcg 1.13 if (dst == 0)
434     slog (L_WARN, _("%s(%s): received broadcast (protocol violation)"),
435 pcg 1.1 c->conf->nodename, (const char *)rsi);
436 pcg 1.18 else if (dst != THISNODE->id)
437 pcg 1.6 {
438     if (THISNODE->routerprio)
439     // the tos setting gets lost here. who cares.
440     conns[dst - 1]->inject_vpn_packet (pkt);
441     else
442     slog (L_WARN,
443     _("%s(%s): forwarding request (=> %s), but we are no router"),
444     c->conf->nodename, (const char *)rsi,
445     conns[dst - 1]->conf->nodename);
446     }
447 pcg 1.1 else
448     c->recv_vpn_packet (pkt, rsi);
449     }
450     }
451    
452 pcg 1.31 bool
453     vpn::send_vpn_packet (vpn_packet *pkt, const sockinfo &si, int tos)
454     {
455     switch (si.prot)
456     {
457     case PROT_IPv4:
458     return send_ipv4_packet (pkt, si, tos);
459     case PROT_UDPv4:
460     return send_udpv4_packet (pkt, si, tos);
461     #if ENABLE_TCP
462     case PROT_TCPv4:
463     return send_tcpv4_packet (pkt, si, tos);
464     #endif
465     #if ENABLE_ICMP
466     case PROT_ICMPv4:
467     return send_icmpv4_packet (pkt, si, tos);
468     #endif
469     #if ENABLE_DNS
470     case PROT_DNSv4:
471     return send_dnsv4_packet (pkt, si, tos);
472     #endif
473    
474     default:
475     slog (L_CRIT, _("%s: FATAL: trying to send packet with unsupported protocol"), (const char *)si);
476     }
477    
478     return false;
479     }
480    
481 pcg 1.1 void
482 pcg 1.9 vpn::ipv4_ev (io_watcher &w, short revents)
483 pcg 1.1 {
484 pcg 1.22 if (revents & EVENT_READ)
485 pcg 1.1 {
486     vpn_packet *pkt = new vpn_packet;
487     struct sockaddr_in sa;
488     socklen_t sa_len = sizeof (sa);
489     int len;
490    
491 pcg 1.5 len = recvfrom (w.fd, &((*pkt)[0]), MAXSIZE, 0, (sockaddr *)&sa, &sa_len);
492 pcg 1.1
493 pcg 1.9 sockinfo si(sa, PROT_IPv4);
494 pcg 1.1
495     if (len > 0)
496     {
497     pkt->len = len;
498    
499 pcg 1.30 // raw sockets deliver the ipv4 header, but don't expect it on sends
500 pcg 1.9 pkt->skip_hdr (IP_OVERHEAD);
501    
502 pcg 1.1 recv_vpn_packet (pkt, si);
503     }
504     else
505     {
506     // probably ECONNRESET or somesuch
507 pcg 1.9 slog (L_DEBUG, _("%s: %s"), (const char *)si, strerror (errno));
508 pcg 1.1 }
509    
510     delete pkt;
511     }
512     else
513     {
514     slog (L_ERR,
515 pcg 1.30 _("FATAL: unknown revents %08x in socket, terminating\n"),
516     revents);
517 pcg 1.23 exit (EXIT_FAILURE);
518 pcg 1.1 }
519     }
520    
521 pcg 1.13 #if ENABLE_ICMP
522 pcg 1.1 void
523 pcg 1.9 vpn::icmpv4_ev (io_watcher &w, short revents)
524 pcg 1.1 {
525 pcg 1.22 if (revents & EVENT_READ)
526 pcg 1.1 {
527     vpn_packet *pkt = new vpn_packet;
528     struct sockaddr_in sa;
529     socklen_t sa_len = sizeof (sa);
530     int len;
531    
532 pcg 1.5 len = recvfrom (w.fd, &((*pkt)[0]), MAXSIZE, 0, (sockaddr *)&sa, &sa_len);
533 pcg 1.1
534 pcg 1.9 sockinfo si(sa, PROT_ICMPv4);
535 pcg 1.1
536     if (len > 0)
537     {
538     pkt->len = len;
539    
540 pcg 1.14 icmp_header *hdr = (icmp_header *)&((*pkt)[IP_OVERHEAD]);
541 pcg 1.9
542     if (hdr->type == ::conf.icmp_type
543     && hdr->code == 255)
544     {
545     // raw sockets deliver the ipv4, but don't expect it on sends
546     // this is slow, but...
547     pkt->skip_hdr (ICMP_OVERHEAD);
548    
549     recv_vpn_packet (pkt, si);
550     }
551     }
552     else
553     {
554     // probably ECONNRESET or somesuch
555     slog (L_DEBUG, _("%s: %s"), (const char *)si, strerror (errno));
556     }
557    
558     delete pkt;
559     }
560     else
561     {
562     slog (L_ERR,
563     _("FATAL: unknown revents %08x in socket, terminating\n"),
564     revents);
565 pcg 1.23 exit (EXIT_FAILURE);
566 pcg 1.9 }
567     }
568 pcg 1.13 #endif
569 pcg 1.9
570     void
571     vpn::udpv4_ev (io_watcher &w, short revents)
572     {
573 pcg 1.22 if (revents & EVENT_READ)
574 pcg 1.9 {
575     vpn_packet *pkt = new vpn_packet;
576     struct sockaddr_in sa;
577     socklen_t sa_len = sizeof (sa);
578     int len;
579    
580     len = recvfrom (w.fd, &((*pkt)[0]), MAXSIZE, 0, (sockaddr *)&sa, &sa_len);
581    
582     sockinfo si(sa, PROT_UDPv4);
583    
584     if (len > 0)
585     {
586     pkt->len = len;
587 pcg 1.1
588     recv_vpn_packet (pkt, si);
589     }
590     else
591     {
592     // probably ECONNRESET or somesuch
593 pcg 1.9 slog (L_DEBUG, _("%s: fd %d, %s"), (const char *)si, w.fd, strerror (errno));
594 pcg 1.1 }
595    
596     delete pkt;
597     }
598     else
599     {
600     slog (L_ERR,
601     _("FATAL: unknown revents %08x in socket, terminating\n"),
602     revents);
603 pcg 1.23 exit (EXIT_FAILURE);
604 pcg 1.1 }
605     }
606 pcg 1.2
607     void
608 pcg 1.3 vpn::tap_ev (io_watcher &w, short revents)
609 pcg 1.1 {
610 pcg 1.22 if (revents & EVENT_READ)
611 pcg 1.1 {
612     /* process data */
613     tap_packet *pkt;
614    
615     pkt = tap->recv ();
616    
617 pcg 1.17 if (!pkt)
618     return;
619 pcg 1.1
620 pcg 1.17 if (pkt->len > 14)
621 pcg 1.1 {
622 pcg 1.17 int dst = mac2id (pkt->dst);
623     int src = mac2id (pkt->src);
624 pcg 1.1
625 pcg 1.17 if (src != THISNODE->id)
626     {
627 pcg 1.30 slog (L_ERR, _("FATAL: tap packet not originating on current node received (if-up script not working properly?), exiting."));
628 pcg 1.23 exit (EXIT_FAILURE);
629 pcg 1.17 }
630 pcg 1.1
631 pcg 1.17 if (dst == THISNODE->id)
632 pcg 1.1 {
633 pcg 1.17 slog (L_ERR, _("FATAL: tap packet destined for current node received, exiting."));
634 pcg 1.23 exit (EXIT_FAILURE);
635 pcg 1.1 }
636 pcg 1.17
637     if (dst > conns.size ())
638     slog (L_ERR, _("tap packet for unknown node %d received, ignoring."), dst);
639 pcg 1.1 else
640 pcg 1.18 inject_data_packet (pkt, dst);
641 pcg 1.1 }
642    
643     delete pkt;
644     }
645     else
646     abort ();
647     }
648    
649     void
650 pcg 1.3 vpn::event_cb (time_watcher &w)
651 pcg 1.1 {
652     if (events)
653     {
654     if (events & EVENT_SHUTDOWN)
655     {
656     slog (L_INFO, _("preparing shutdown..."));
657    
658     shutdown_all ();
659 pcg 1.24 remove_pid (conf.pidfilename);
660 pcg 1.1 slog (L_INFO, _("terminating"));
661 pcg 1.23 exit (EXIT_SUCCESS);
662 pcg 1.1 }
663    
664     if (events & EVENT_RECONNECT)
665     {
666     slog (L_INFO, _("forced reconnect"));
667    
668     reconnect_all ();
669     }
670    
671     events = 0;
672     }
673     }
674    
675     void
676     vpn::shutdown_all ()
677     {
678     for (conns_vector::iterator c = conns.begin (); c != conns.end (); ++c)
679     (*c)->shutdown ();
680     }
681    
682     void
683     vpn::reconnect_all ()
684     {
685     for (conns_vector::iterator c = conns.begin (); c != conns.end (); ++c)
686     delete *c;
687    
688     conns.clear ();
689    
690     connection_init ();
691    
692     for (configuration::node_vector::iterator i = conf.nodes.begin ();
693     i != conf.nodes.end (); ++i)
694     {
695 pcg 1.27 connection *conn = new connection (this, *i);
696 pcg 1.1 conns.push_back (conn);
697     conn->establish_connection ();
698     }
699     }
700    
701     connection *vpn::find_router ()
702     {
703 pcg 1.26 u32 prio = 1;
704 pcg 1.1 connection *router = 0;
705    
706     for (conns_vector::iterator i = conns.begin (); i != conns.end (); ++i)
707     {
708     connection *c = *i;
709    
710 pcg 1.13 if (c->conf->routerprio > prio
711 pcg 1.11 && c->connectmode == conf_node::C_ALWAYS // so we don't drop the connection if in use
712     && c->ictx && c->octx
713 pcg 1.13 && c->conf != THISNODE) // redundant, since ictx==octx==0 always on thisnode
714 pcg 1.1 {
715     prio = c->conf->routerprio;
716     router = c;
717     }
718     }
719    
720     return router;
721     }
722    
723 pcg 1.7 void vpn::send_connect_request (int id)
724 pcg 1.1 {
725     connection *c = find_router ();
726    
727     if (c)
728 pcg 1.7 c->send_connect_request (id);
729     else
730     // no router found, aggressively connect to all routers
731     for (conns_vector::iterator i = conns.begin (); i != conns.end (); ++i)
732 pcg 1.13 if ((*i)->conf->routerprio && (*i)->conf != THISNODE)
733 pcg 1.7 (*i)->establish_connection ();
734 pcg 1.1 }
735    
736     void
737     connection::dump_status ()
738     {
739     slog (L_NOTICE, _("node %s (id %d)"), conf->nodename, conf->id);
740     slog (L_NOTICE, _(" connectmode %d (%d) / sockaddr %s / minor %d"),
741     connectmode, conf->connectmode, (const char *)si, (int)prot_minor);
742     slog (L_NOTICE, _(" ictx/octx %08lx/%08lx / oseqno %d / retry_cnt %d"),
743     (long)ictx, (long)octx, (int)oseqno, (int)retry_cnt);
744     slog (L_NOTICE, _(" establish_conn %ld / rekey %ld / keepalive %ld"),
745     (long)(establish_connection.at), (long)(rekey.at), (long)(keepalive.at));
746     }
747    
748     void
749     vpn::dump_status ()
750     {
751     slog (L_NOTICE, _("BEGIN status dump (%ld)"), (long)NOW);
752    
753     for (conns_vector::iterator c = conns.begin (); c != conns.end (); ++c)
754     (*c)->dump_status ();
755    
756     slog (L_NOTICE, _("END status dump"));
757     }
758    
759     vpn::vpn (void)
760 pcg 1.9 : event (this, &vpn::event_cb)
761     , udpv4_ev_watcher (this, &vpn::udpv4_ev)
762     , ipv4_ev_watcher (this, &vpn::ipv4_ev)
763 pcg 1.2 #if ENABLE_TCP
764 pcg 1.9 , tcpv4_ev_watcher (this, &vpn::tcpv4_ev)
765     #endif
766     #if ENABLE_ICMP
767     , icmpv4_ev_watcher(this, &vpn::icmpv4_ev)
768 pcg 1.24 #endif
769     #if ENABLE_DNS
770     , dnsv4_ev_watcher (this, &vpn::dnsv4_ev)
771 pcg 1.2 #endif
772 pcg 1.9 , tap_ev_watcher (this, &vpn::tap_ev)
773 pcg 1.1 {
774     }
775    
776     vpn::~vpn ()
777     {
778     }
779