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