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