ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/gvpe/src/vpn.C
Revision: 1.53
Committed: Fri Aug 15 17:50:10 2008 UTC (15 years, 9 months ago) by pcg
Content type: text/plain
Branch: MAIN
CVS Tags: rel-2_2, rel-2_21, rel-2_22
Changes since 1.52: +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 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.52 // first try to find a router with a direct connection, route there
771     // regardless of any other considerations.
772 pcg 1.49 {
773     u32 prio = 1;
774    
775     for (conns_vector::iterator i = conns.begin (); i != conns.end (); ++i)
776     {
777     connection *c = *i;
778    
779     if (c->conf->routerprio > prio
780     && c->conf != THISNODE
781 pcg 1.52 && can_direct (c->conf, dst->conf)
782     && c->ictx && c->octx)
783 pcg 1.49 {
784 pcg 1.52 prio = c->conf->routerprio;
785     router = c;
786 pcg 1.49 }
787     }
788     }
789    
790     if (router)
791     return router;
792    
793 pcg 1.52 // second try find the router with the highest priority, higher than ours
794 pcg 1.49 {
795 pcg 1.52 u32 prio = THISNODE->routerprio ? THISNODE->routerprio : 1;
796 pcg 1.49
797     for (conns_vector::iterator i = conns.begin (); i != conns.end (); ++i)
798     {
799     connection *c = *i;
800    
801     if (c->conf->routerprio > prio
802     && c != dst
803 pcg 1.52 && c->conf != THISNODE
804     && c->ictx && c->octx)
805 pcg 1.49 {
806 pcg 1.52 prio = c->conf->routerprio;
807     router = c;
808 pcg 1.49 }
809     }
810     }
811 pcg 1.52
812 pcg 1.49 return router;
813     }
814    
815     void vpn::connection_established (connection *c)
816     {
817 pcg 1.1 for (conns_vector::iterator i = conns.begin (); i != conns.end (); ++i)
818     {
819 pcg 1.49 connection *o = *i;
820 pcg 1.1
821 pcg 1.49 if (!o->is_direct
822     && o->si.valid ()
823     && c->si != o->si
824     && c == find_router_for (o))
825     {
826     slog (L_DEBUG, _("%s: can now route packets via %s, re-keying connection."),
827     o->conf->nodename, c->conf->nodename);
828     o->rekey ();
829 pcg 1.1 }
830     }
831     }
832    
833 pcg 1.50 void vpn::send_connect_request (connection *c)
834 pcg 1.1 {
835 pcg 1.50 connection *r = find_router_for (c);
836 pcg 1.1
837 pcg 1.50 if (r)
838 pcg 1.49 {
839 pcg 1.53 slog (L_TRACE, _("%s: no address known, sending mediated connection request via %s."),
840 pcg 1.50 c->conf->nodename, r->conf->nodename);
841     r->send_connect_request (c->conf->id);
842 pcg 1.49 }
843 pcg 1.7 else
844 pcg 1.53 slog (L_DEBUG, _("%s: no way to connect and no router found: unable to connect at this time."),
845 pcg 1.50 c->conf->nodename);
846 pcg 1.1 }
847    
848     void
849     connection::dump_status ()
850     {
851     slog (L_NOTICE, _("node %s (id %d)"), conf->nodename, conf->id);
852     slog (L_NOTICE, _(" connectmode %d (%d) / sockaddr %s / minor %d"),
853     connectmode, conf->connectmode, (const char *)si, (int)prot_minor);
854     slog (L_NOTICE, _(" ictx/octx %08lx/%08lx / oseqno %d / retry_cnt %d"),
855     (long)ictx, (long)octx, (int)oseqno, (int)retry_cnt);
856     }
857    
858     void
859     vpn::dump_status ()
860     {
861 pcg 1.40 slog (L_NOTICE, _("BEGIN status dump (%ld)"), (long)ev_now ());
862 pcg 1.1
863     for (conns_vector::iterator c = conns.begin (); c != conns.end (); ++c)
864     (*c)->dump_status ();
865    
866     slog (L_NOTICE, _("END status dump"));
867     }
868    
869     vpn::vpn (void)
870 pcg 1.44 {
871     event .set<vpn, &vpn::event_cb > (this);
872     udpv4_ev_watcher .set<vpn, &vpn::udpv4_ev > (this);
873     ipv4_ev_watcher .set<vpn, &vpn::ipv4_ev > (this);
874 pcg 1.2 #if ENABLE_TCP
875 pcg 1.44 tcpv4_ev_watcher .set<vpn, &vpn::tcpv4_ev > (this);
876 pcg 1.9 #endif
877     #if ENABLE_ICMP
878 pcg 1.44 icmpv4_ev_watcher.set<vpn, &vpn::icmpv4_ev> (this);
879 pcg 1.24 #endif
880     #if ENABLE_DNS
881 pcg 1.44 dnsv4_ev_watcher .set<vpn, &vpn::dnsv4_ev > (this);
882 pcg 1.2 #endif
883 pcg 1.44 tap_ev_watcher .set<vpn, &vpn::tap_ev > (this);
884 pcg 1.1 }
885    
886     vpn::~vpn ()
887     {
888     }
889