1 | /* |
1 | /* |
2 | vpn.C -- handle the protocol, encryption, handshaking etc. |
2 | vpn.C -- handle the protocol, encryption, handshaking etc. |
3 | Copyright (C) 2003-2007 Marc Lehmann <gvpe@schmorp.de> |
3 | Copyright (C) 2003-2008 Marc Lehmann <gvpe@schmorp.de> |
4 | |
4 | |
5 | This file is part of GVPE. |
5 | This file is part of GVPE. |
6 | |
6 | |
7 | GVPE is free software; you can redistribute it and/or modify |
7 | GVPE is free software; you can redistribute it and/or modify it |
8 | it under the terms of the GNU General Public License as published by |
8 | under the terms of the GNU General Public License as published by the |
9 | the Free Software Foundation; either version 2 of the License, or |
9 | Free Software Foundation; either version 3 of the License, or (at your |
10 | (at your option) any later version. |
10 | option) any later version. |
11 | |
11 | |
12 | This program is distributed in the hope that it will be useful, |
12 | This program is distributed in the hope that it will be useful, but |
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
13 | WITHOUT ANY WARRANTY; without even the implied warranty of |
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General |
15 | GNU General Public License for more details. |
15 | Public License for more details. |
16 | |
16 | |
17 | You should have received a copy of the GNU General Public License |
17 | You should have received a copy of the GNU General Public License along |
18 | along with gvpe; if not, write to the Free Software |
18 | with this program; if not, see <http://www.gnu.org/licenses/>. |
19 | Foundation, Inc. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
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. |
20 | */ |
30 | */ |
21 | |
31 | |
22 | #include "config.h" |
32 | #include "config.h" |
23 | |
33 | |
24 | #include <list> |
34 | #include <list> |
… | |
… | |
87 | snprintf (ext, 16, "_%d", (*c)->conf->id); |
97 | snprintf (ext, 16, "_%d", (*c)->conf->id); |
88 | (*c)->script_init_env (ext); |
98 | (*c)->script_init_env (ext); |
89 | } |
99 | } |
90 | } |
100 | } |
91 | |
101 | |
|
|
102 | inline const char * |
92 | const char *vpn::script_if_init () |
103 | vpn::script_if_init () |
93 | { |
104 | { |
94 | script_init_env (); |
105 | script_init_env (); |
95 | |
106 | |
96 | return tap->if_up (); |
107 | return tap->if_up (); |
97 | } |
108 | } |
98 | |
109 | |
|
|
110 | inline const char * |
99 | const char *vpn::script_if_up () |
111 | vpn::script_if_up () |
100 | { |
112 | { |
101 | script_init_env (); |
113 | script_init_env (); |
102 | |
114 | |
103 | char *filename; |
115 | char *filename; |
104 | asprintf (&filename, |
116 | asprintf (&filename, |
… | |
… | |
330 | } |
342 | } |
331 | |
343 | |
332 | fcntl (tap->fd, F_SETFD, FD_CLOEXEC); |
344 | fcntl (tap->fd, F_SETFD, FD_CLOEXEC); |
333 | |
345 | |
334 | run_script_cb cb; |
346 | run_script_cb cb; |
|
|
347 | cb.set<vpn, &vpn::script_if_init> (this); |
335 | |
348 | |
336 | callback_set (cb, this, vpn, script_if_init); |
|
|
337 | if (tap->if_up () && |
349 | if (tap->if_up () && |
338 | !run_script (cb, true)) |
350 | !run_script (cb, true)) |
339 | { |
351 | { |
340 | slog (L_ERR, _("interface initialization command '%s' failed, exiting."), |
352 | slog (L_ERR, _("interface initialization command '%s' failed, exiting."), |
341 | tap->if_up ()); |
353 | tap->if_up ()); |
342 | exit (EXIT_FAILURE); |
354 | exit (EXIT_FAILURE); |
343 | } |
355 | } |
344 | |
356 | |
345 | callback_set (cb, this, vpn, script_if_up); |
357 | cb.set<vpn, &vpn::script_if_up> (this); |
346 | if (!run_script (cb, true)) |
358 | if (!run_script (cb, true)) |
347 | { |
359 | { |
348 | slog (L_ERR, _("if-up command execution failed, exiting.")); |
360 | slog (L_ERR, _("if-up command execution failed, exiting.")); |
349 | exit (EXIT_FAILURE); |
361 | exit (EXIT_FAILURE); |
350 | } |
362 | } |
… | |
… | |
427 | { |
439 | { |
428 | // broadcast, this is ugly, but due to the security policy |
440 | // broadcast, this is ugly, but due to the security policy |
429 | // we have to connect to all hosts... |
441 | // we have to connect to all hosts... |
430 | for (conns_vector::iterator c = conns.begin (); c != conns.end (); ++c) |
442 | for (conns_vector::iterator c = conns.begin (); c != conns.end (); ++c) |
431 | if ((*c)->conf != THISNODE) |
443 | if ((*c)->conf != THISNODE) |
432 | (*c)->inject_data_packet (pkt, true); |
444 | (*c)->inject_data_packet (pkt); |
433 | } |
445 | } |
434 | } |
446 | } |
435 | |
447 | |
436 | void |
448 | void |
437 | vpn::recv_vpn_packet (vpn_packet *pkt, const sockinfo &rsi) |
449 | vpn::recv_vpn_packet (vpn_packet *pkt, const sockinfo &rsi) |
… | |
… | |
501 | } |
513 | } |
502 | |
514 | |
503 | return false; |
515 | return false; |
504 | } |
516 | } |
505 | |
517 | |
506 | void |
518 | inline void |
507 | vpn::ipv4_ev (ev::io &w, int revents) |
519 | vpn::ipv4_ev (ev::io &w, int revents) |
508 | { |
520 | { |
509 | if (revents & EV_READ) |
521 | if (revents & EV_READ) |
510 | { |
522 | { |
511 | vpn_packet *pkt = new vpn_packet; |
523 | vpn_packet *pkt = new vpn_packet; |
… | |
… | |
542 | exit (EXIT_FAILURE); |
554 | exit (EXIT_FAILURE); |
543 | } |
555 | } |
544 | } |
556 | } |
545 | |
557 | |
546 | #if ENABLE_ICMP |
558 | #if ENABLE_ICMP |
547 | void |
559 | inline void |
548 | vpn::icmpv4_ev (ev::io &w, int revents) |
560 | vpn::icmpv4_ev (ev::io &w, int revents) |
549 | { |
561 | { |
550 | if (revents & EV_READ) |
562 | if (revents & EV_READ) |
551 | { |
563 | { |
552 | vpn_packet *pkt = new vpn_packet; |
564 | vpn_packet *pkt = new vpn_packet; |
… | |
… | |
590 | exit (EXIT_FAILURE); |
602 | exit (EXIT_FAILURE); |
591 | } |
603 | } |
592 | } |
604 | } |
593 | #endif |
605 | #endif |
594 | |
606 | |
595 | void |
607 | inline void |
596 | vpn::udpv4_ev (ev::io &w, int revents) |
608 | vpn::udpv4_ev (ev::io &w, int revents) |
597 | { |
609 | { |
598 | if (revents & EV_READ) |
610 | if (revents & EV_READ) |
599 | { |
611 | { |
600 | vpn_packet *pkt = new vpn_packet; |
612 | vpn_packet *pkt = new vpn_packet; |
… | |
… | |
627 | revents); |
639 | revents); |
628 | exit (EXIT_FAILURE); |
640 | exit (EXIT_FAILURE); |
629 | } |
641 | } |
630 | } |
642 | } |
631 | |
643 | |
632 | void |
644 | inline void |
633 | vpn::tap_ev (ev::io &w, int revents) |
645 | vpn::tap_ev (ev::io &w, int revents) |
634 | { |
646 | { |
635 | if (revents & EV_READ) |
647 | if (revents & EV_READ) |
636 | { |
648 | { |
637 | /* process data */ |
649 | /* process data */ |
… | |
… | |
669 | } |
681 | } |
670 | else |
682 | else |
671 | abort (); |
683 | abort (); |
672 | } |
684 | } |
673 | |
685 | |
674 | void |
686 | inline void |
675 | vpn::event_cb (ev::timer &w, int) |
687 | vpn::event_cb (ev::timer &w, int) |
676 | { |
688 | { |
677 | if (events) |
689 | if (events) |
678 | { |
690 | { |
679 | if (events & EVENT_SHUTDOWN) |
691 | if (events & EVENT_SHUTDOWN) |
… | |
… | |
764 | slog (L_NOTICE, _("node %s (id %d)"), conf->nodename, conf->id); |
776 | slog (L_NOTICE, _("node %s (id %d)"), conf->nodename, conf->id); |
765 | slog (L_NOTICE, _(" connectmode %d (%d) / sockaddr %s / minor %d"), |
777 | slog (L_NOTICE, _(" connectmode %d (%d) / sockaddr %s / minor %d"), |
766 | connectmode, conf->connectmode, (const char *)si, (int)prot_minor); |
778 | connectmode, conf->connectmode, (const char *)si, (int)prot_minor); |
767 | slog (L_NOTICE, _(" ictx/octx %08lx/%08lx / oseqno %d / retry_cnt %d"), |
779 | slog (L_NOTICE, _(" ictx/octx %08lx/%08lx / oseqno %d / retry_cnt %d"), |
768 | (long)ictx, (long)octx, (int)oseqno, (int)retry_cnt); |
780 | (long)ictx, (long)octx, (int)oseqno, (int)retry_cnt); |
769 | slog (L_NOTICE, _(" establish_conn %ld / rekey %ld / keepalive %ld"), |
|
|
770 | (long)(establish_connection.at), (long)(rekey.at), (long)(keepalive.at)); |
|
|
771 | } |
781 | } |
772 | |
782 | |
773 | void |
783 | void |
774 | vpn::dump_status () |
784 | vpn::dump_status () |
775 | { |
785 | { |
… | |
… | |
780 | |
790 | |
781 | slog (L_NOTICE, _("END status dump")); |
791 | slog (L_NOTICE, _("END status dump")); |
782 | } |
792 | } |
783 | |
793 | |
784 | vpn::vpn (void) |
794 | vpn::vpn (void) |
|
|
795 | { |
785 | : event (this, &vpn::event_cb) |
796 | event .set<vpn, &vpn::event_cb > (this); |
786 | , udpv4_ev_watcher (this, &vpn::udpv4_ev) |
797 | udpv4_ev_watcher .set<vpn, &vpn::udpv4_ev > (this); |
787 | , ipv4_ev_watcher (this, &vpn::ipv4_ev) |
798 | ipv4_ev_watcher .set<vpn, &vpn::ipv4_ev > (this); |
788 | #if ENABLE_TCP |
799 | #if ENABLE_TCP |
789 | , tcpv4_ev_watcher (this, &vpn::tcpv4_ev) |
800 | tcpv4_ev_watcher .set<vpn, &vpn::tcpv4_ev > (this); |
790 | #endif |
801 | #endif |
791 | #if ENABLE_ICMP |
802 | #if ENABLE_ICMP |
792 | , icmpv4_ev_watcher(this, &vpn::icmpv4_ev) |
803 | icmpv4_ev_watcher.set<vpn, &vpn::icmpv4_ev> (this); |
793 | #endif |
804 | #endif |
794 | #if ENABLE_DNS |
805 | #if ENABLE_DNS |
795 | , dnsv4_ev_watcher (this, &vpn::dnsv4_ev) |
806 | dnsv4_ev_watcher .set<vpn, &vpn::dnsv4_ev > (this); |
796 | #endif |
807 | #endif |
797 | , tap_ev_watcher (this, &vpn::tap_ev) |
808 | tap_ev_watcher .set<vpn, &vpn::tap_ev > (this); |
798 | { |
|
|
799 | } |
809 | } |
800 | |
810 | |
801 | vpn::~vpn () |
811 | vpn::~vpn () |
802 | { |
812 | { |
803 | } |
813 | } |