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