ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/gvpe/src/vpn.C
Revision: 1.65
Committed: Tue Jul 16 16:44:37 2013 UTC (10 years, 10 months ago) by root
Content type: text/plain
Branch: MAIN
Changes since 1.64: +2 -2 lines
Log Message:
3.x

File Contents

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