ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/gvpe/src/vpn.C
Revision: 1.61
Committed: Fri Sep 16 18:08:03 2011 UTC (12 years, 8 months ago) by root
Content type: text/plain
Branch: MAIN
Changes since 1.60: +0 -3 lines
Log Message:
ugh

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     else
490     {
491     connection *c = conns[src - 1];
492    
493 pcg 1.13 if (dst == 0)
494 pcg 1.49 slog (L_WARN, _("%s(%s): received broadcast (protocol violation)."),
495 pcg 1.1 c->conf->nodename, (const char *)rsi);
496 pcg 1.18 else if (dst != THISNODE->id)
497 pcg 1.6 {
498     if (THISNODE->routerprio)
499     // the tos setting gets lost here. who cares.
500     conns[dst - 1]->inject_vpn_packet (pkt);
501     else
502     slog (L_WARN,
503 pcg 1.49 _("%s(%s): request to forward packet to %s, but we are no router (config mismatch?)."),
504 pcg 1.6 c->conf->nodename, (const char *)rsi,
505     conns[dst - 1]->conf->nodename);
506     }
507 pcg 1.1 else
508     c->recv_vpn_packet (pkt, rsi);
509     }
510     }
511    
512 pcg 1.31 bool
513     vpn::send_vpn_packet (vpn_packet *pkt, const sockinfo &si, int tos)
514     {
515     switch (si.prot)
516     {
517     case PROT_IPv4:
518     return send_ipv4_packet (pkt, si, tos);
519 pcg 1.41
520 pcg 1.31 case PROT_UDPv4:
521     return send_udpv4_packet (pkt, si, tos);
522 pcg 1.41
523 root 1.57 #if ENABLE_TCP
524 pcg 1.31 case PROT_TCPv4:
525     return send_tcpv4_packet (pkt, si, tos);
526     #endif
527     #if ENABLE_ICMP
528     case PROT_ICMPv4:
529     return send_icmpv4_packet (pkt, si, tos);
530     #endif
531     #if ENABLE_DNS
532     case PROT_DNSv4:
533     return send_dnsv4_packet (pkt, si, tos);
534     #endif
535     default:
536 pcg 1.49 slog (L_CRIT, _("%s: FATAL: trying to send packet with unsupported protocol."), (const char *)si);
537 pcg 1.31 }
538    
539     return false;
540     }
541    
542 pcg 1.45 inline void
543 pcg 1.39 vpn::ipv4_ev (ev::io &w, int revents)
544 pcg 1.1 {
545 pcg 1.39 if (revents & EV_READ)
546 pcg 1.1 {
547     vpn_packet *pkt = new vpn_packet;
548     struct sockaddr_in sa;
549     socklen_t sa_len = sizeof (sa);
550     int len;
551    
552 pcg 1.5 len = recvfrom (w.fd, &((*pkt)[0]), MAXSIZE, 0, (sockaddr *)&sa, &sa_len);
553 pcg 1.1
554 pcg 1.9 sockinfo si(sa, PROT_IPv4);
555 pcg 1.1
556     if (len > 0)
557     {
558     pkt->len = len;
559    
560 pcg 1.30 // raw sockets deliver the ipv4 header, but don't expect it on sends
561 root 1.60 pkt->skip_hdr (pkt->ipv4_hdr_len ());
562 pcg 1.9
563 pcg 1.1 recv_vpn_packet (pkt, si);
564     }
565     else
566     {
567     // probably ECONNRESET or somesuch
568 pcg 1.49 slog (L_DEBUG, _("%s: %s."), (const char *)si, strerror (errno));
569 pcg 1.1 }
570    
571     delete pkt;
572     }
573     else
574     {
575     slog (L_ERR,
576 pcg 1.49 _("FATAL: unknown revents %08x in socket, exiting.\n"),
577 pcg 1.30 revents);
578 pcg 1.23 exit (EXIT_FAILURE);
579 pcg 1.1 }
580     }
581    
582 pcg 1.13 #if ENABLE_ICMP
583 pcg 1.45 inline void
584 pcg 1.39 vpn::icmpv4_ev (ev::io &w, int revents)
585 pcg 1.1 {
586 pcg 1.39 if (revents & EV_READ)
587 pcg 1.1 {
588     vpn_packet *pkt = new vpn_packet;
589     struct sockaddr_in sa;
590     socklen_t sa_len = sizeof (sa);
591     int len;
592    
593 pcg 1.5 len = recvfrom (w.fd, &((*pkt)[0]), MAXSIZE, 0, (sockaddr *)&sa, &sa_len);
594 pcg 1.1
595 pcg 1.9 sockinfo si(sa, PROT_ICMPv4);
596 pcg 1.1
597     if (len > 0)
598     {
599     pkt->len = len;
600    
601 pcg 1.14 icmp_header *hdr = (icmp_header *)&((*pkt)[IP_OVERHEAD]);
602 pcg 1.9
603     if (hdr->type == ::conf.icmp_type
604     && hdr->code == 255)
605     {
606     // raw sockets deliver the ipv4, but don't expect it on sends
607     // this is slow, but...
608 root 1.60 pkt->skip_hdr (pkt->ipv4_hdr_len () + (ICMP_OVERHEAD - IP_OVERHEAD));
609 pcg 1.9
610     recv_vpn_packet (pkt, si);
611     }
612     }
613     else
614     {
615     // probably ECONNRESET or somesuch
616 pcg 1.49 slog (L_DEBUG, _("%s: %s."), (const char *)si, strerror (errno));
617 pcg 1.9 }
618    
619     delete pkt;
620     }
621     else
622     {
623     slog (L_ERR,
624 pcg 1.49 _("FATAL: unknown revents %08x in socket, exiting.\n"),
625 pcg 1.9 revents);
626 pcg 1.23 exit (EXIT_FAILURE);
627 pcg 1.9 }
628     }
629 pcg 1.13 #endif
630 pcg 1.9
631 pcg 1.45 inline void
632 pcg 1.39 vpn::udpv4_ev (ev::io &w, int revents)
633 pcg 1.9 {
634 pcg 1.39 if (revents & EV_READ)
635 pcg 1.9 {
636     vpn_packet *pkt = new vpn_packet;
637     struct sockaddr_in sa;
638     socklen_t sa_len = sizeof (sa);
639     int len;
640    
641     len = recvfrom (w.fd, &((*pkt)[0]), MAXSIZE, 0, (sockaddr *)&sa, &sa_len);
642    
643     sockinfo si(sa, PROT_UDPv4);
644    
645     if (len > 0)
646     {
647     pkt->len = len;
648 pcg 1.1
649     recv_vpn_packet (pkt, si);
650     }
651     else
652     {
653     // probably ECONNRESET or somesuch
654 pcg 1.49 slog (L_DEBUG, _("%s: fd %d, %s."), (const char *)si, w.fd, strerror (errno));
655 pcg 1.1 }
656    
657     delete pkt;
658     }
659     else
660     {
661     slog (L_ERR,
662 pcg 1.49 _("FATAL: unknown revents %08x in socket, exiting.\n"),
663 pcg 1.1 revents);
664 pcg 1.23 exit (EXIT_FAILURE);
665 pcg 1.1 }
666     }
667 pcg 1.2
668 pcg 1.45 inline void
669 pcg 1.39 vpn::tap_ev (ev::io &w, int revents)
670 pcg 1.1 {
671 pcg 1.39 if (revents & EV_READ)
672 pcg 1.1 {
673     /* process data */
674     tap_packet *pkt;
675    
676     pkt = tap->recv ();
677    
678 pcg 1.17 if (!pkt)
679     return;
680 pcg 1.1
681 pcg 1.17 if (pkt->len > 14)
682 pcg 1.1 {
683 pcg 1.17 int dst = mac2id (pkt->dst);
684     int src = mac2id (pkt->src);
685 pcg 1.1
686 pcg 1.17 if (src != THISNODE->id)
687     {
688 pcg 1.30 slog (L_ERR, _("FATAL: tap packet not originating on current node received (if-up script not working properly?), exiting."));
689 pcg 1.23 exit (EXIT_FAILURE);
690 pcg 1.17 }
691 pcg 1.1
692 pcg 1.17 if (dst == THISNODE->id)
693 pcg 1.1 {
694 pcg 1.17 slog (L_ERR, _("FATAL: tap packet destined for current node received, exiting."));
695 pcg 1.23 exit (EXIT_FAILURE);
696 pcg 1.1 }
697 pcg 1.17
698     if (dst > conns.size ())
699     slog (L_ERR, _("tap packet for unknown node %d received, ignoring."), dst);
700 pcg 1.1 else
701 pcg 1.18 inject_data_packet (pkt, dst);
702 pcg 1.1 }
703    
704     delete pkt;
705     }
706     else
707     abort ();
708     }
709    
710 pcg 1.45 inline void
711 pcg 1.39 vpn::event_cb (ev::timer &w, int)
712 pcg 1.1 {
713     if (events)
714     {
715     if (events & EVENT_SHUTDOWN)
716     {
717     slog (L_INFO, _("preparing shutdown..."));
718    
719     shutdown_all ();
720 pcg 1.24 remove_pid (conf.pidfilename);
721 pcg 1.49 slog (L_INFO, _("exiting."));
722 pcg 1.23 exit (EXIT_SUCCESS);
723 pcg 1.1 }
724    
725     if (events & EVENT_RECONNECT)
726     {
727 pcg 1.49 slog (L_INFO, _("forced reconnect."));
728 pcg 1.1
729     reconnect_all ();
730     }
731    
732     events = 0;
733     }
734     }
735    
736     void
737     vpn::shutdown_all ()
738     {
739     for (conns_vector::iterator c = conns.begin (); c != conns.end (); ++c)
740     (*c)->shutdown ();
741     }
742    
743     void
744     vpn::reconnect_all ()
745     {
746     for (conns_vector::iterator c = conns.begin (); c != conns.end (); ++c)
747     delete *c;
748    
749     conns.clear ();
750    
751     connection_init ();
752    
753 pcg 1.50 for (configuration::node_vector::iterator i = conf.nodes.begin (); i != conf.nodes.end (); ++i)
754     conns.push_back (new connection (this, *i));
755    
756     for (conns_vector::iterator c = conns.begin (); c != conns.end (); ++c)
757     (*c)->establish_connection ();
758 pcg 1.1 }
759    
760 root 1.56 bool
761     vpn::can_direct (conf_node *src, conf_node *dst) const
762 pcg 1.49 {
763     return src != dst
764     && src->may_direct (dst)
765     && dst->may_direct (src)
766     && (((src->protocols & dst->protocols) && src->connectmode == conf_node::C_ALWAYS)
767     || (src->protocols & dst->connectable_protocols ()));
768     }
769    
770     // only works for indirect and routed connections: find a router
771     // from THISNODE to dst
772 root 1.56 connection *
773     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 root 1.56 void
823     vpn::connection_established (connection *c)
824 pcg 1.49 {
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 root 1.56 void
842     vpn::send_connect_request (connection *c)
843 pcg 1.1 {
844 pcg 1.50 connection *r = find_router_for (c);
845 pcg 1.1
846 pcg 1.50 if (r)
847 pcg 1.49 {
848 pcg 1.53 slog (L_TRACE, _("%s: no address known, sending mediated connection request via %s."),
849 pcg 1.50 c->conf->nodename, r->conf->nodename);
850     r->send_connect_request (c->conf->id);
851 pcg 1.49 }
852 pcg 1.7 else
853 pcg 1.53 slog (L_DEBUG, _("%s: no way to connect and no router found: unable to connect at this time."),
854 pcg 1.50 c->conf->nodename);
855 pcg 1.1 }
856    
857     void
858     connection::dump_status ()
859     {
860     slog (L_NOTICE, _("node %s (id %d)"), conf->nodename, conf->id);
861     slog (L_NOTICE, _(" connectmode %d (%d) / sockaddr %s / minor %d"),
862     connectmode, conf->connectmode, (const char *)si, (int)prot_minor);
863     slog (L_NOTICE, _(" ictx/octx %08lx/%08lx / oseqno %d / retry_cnt %d"),
864     (long)ictx, (long)octx, (int)oseqno, (int)retry_cnt);
865     }
866    
867     void
868     vpn::dump_status ()
869     {
870 pcg 1.40 slog (L_NOTICE, _("BEGIN status dump (%ld)"), (long)ev_now ());
871 pcg 1.1
872     for (conns_vector::iterator c = conns.begin (); c != conns.end (); ++c)
873     (*c)->dump_status ();
874    
875     slog (L_NOTICE, _("END status dump"));
876     }
877    
878     vpn::vpn (void)
879 pcg 1.44 {
880     event .set<vpn, &vpn::event_cb > (this);
881     udpv4_ev_watcher .set<vpn, &vpn::udpv4_ev > (this);
882     ipv4_ev_watcher .set<vpn, &vpn::ipv4_ev > (this);
883 pcg 1.2 #if ENABLE_TCP
884 pcg 1.44 tcpv4_ev_watcher .set<vpn, &vpn::tcpv4_ev > (this);
885 pcg 1.9 #endif
886     #if ENABLE_ICMP
887 pcg 1.44 icmpv4_ev_watcher.set<vpn, &vpn::icmpv4_ev> (this);
888 pcg 1.24 #endif
889     #if ENABLE_DNS
890 pcg 1.44 dnsv4_ev_watcher .set<vpn, &vpn::dnsv4_ev > (this);
891 pcg 1.2 #endif
892 pcg 1.44 tap_ev_watcher .set<vpn, &vpn::tap_ev > (this);
893 pcg 1.1 }
894    
895     vpn::~vpn ()
896     {
897     }
898