ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/gvpe/src/vpn.C
(Generate patch)

Comparing gvpe/src/vpn.C (file contents):
Revision 1.44 by pcg, Tue Dec 4 17:17:20 2007 UTC vs.
Revision 1.49 by pcg, Sun Aug 10 01:34:36 2008 UTC

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
102inline const char *
92const char *vpn::script_if_init () 103vpn::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
110inline const char *
99const char *vpn::script_if_up () 111vpn::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,
137 149
138 sockinfo si (THISNODE, PROT_IPv4); 150 sockinfo si (THISNODE, PROT_IPv4);
139 151
140 if (bind (ipv4_fd, si.sav4 (), si.salenv4 ())) 152 if (bind (ipv4_fd, si.sav4 (), si.salenv4 ()))
141 { 153 {
142 slog (L_ERR, _("can't bind ipv4 socket on %s: %s"), (const char *)si, strerror (errno)); 154 slog (L_ERR, _("can't bind ipv4 socket on %s: %s, exiting."), (const char *)si, strerror (errno));
143 exit (EXIT_FAILURE); 155 exit (EXIT_FAILURE);
144 } 156 }
145 157
146 ipv4_ev_watcher.start (ipv4_fd, EV_READ); 158 ipv4_ev_watcher.start (ipv4_fd, EV_READ);
147 } 159 }
177 189
178 sockinfo si (THISNODE, PROT_UDPv4); 190 sockinfo si (THISNODE, PROT_UDPv4);
179 191
180 if (bind (udpv4_fd, si.sav4 (), si.salenv4 ())) 192 if (bind (udpv4_fd, si.sav4 (), si.salenv4 ()))
181 { 193 {
182 slog (L_ERR, _("can't bind udpv4 on %s: %s"), (const char *)si, strerror (errno)); 194 slog (L_ERR, _("can't bind udpv4 on %s: %s, exiting."), (const char *)si, strerror (errno));
183 exit (EXIT_FAILURE); 195 exit (EXIT_FAILURE);
184 } 196 }
185 197
186 udpv4_ev_watcher.start (udpv4_fd, EV_READ); 198 udpv4_ev_watcher.start (udpv4_fd, EV_READ);
187 } 199 }
223 235
224 sockinfo si (THISNODE, PROT_ICMPv4); 236 sockinfo si (THISNODE, PROT_ICMPv4);
225 237
226 if (bind (icmpv4_fd, si.sav4 (), si.salenv4 ())) 238 if (bind (icmpv4_fd, si.sav4 (), si.salenv4 ()))
227 { 239 {
228 slog (L_ERR, _("can't bind icmpv4 on %s: %s"), (const char *)si, strerror (errno)); 240 slog (L_ERR, _("can't bind icmpv4 on %s: %s, exiting."), (const char *)si, strerror (errno));
229 exit (EXIT_FAILURE); 241 exit (EXIT_FAILURE);
230 } 242 }
231 243
232 icmpv4_ev_watcher.start (icmpv4_fd, EV_READ); 244 icmpv4_ev_watcher.start (icmpv4_fd, EV_READ);
233 } 245 }
254 266
255 sockinfo si (THISNODE, PROT_TCPv4); 267 sockinfo si (THISNODE, PROT_TCPv4);
256 268
257 if (bind (tcpv4_fd, si.sav4 (), si.salenv4 ())) 269 if (bind (tcpv4_fd, si.sav4 (), si.salenv4 ()))
258 { 270 {
259 slog (L_ERR, _("can't bind tcpv4 on %s: %s"), (const char *)si, strerror (errno)); 271 slog (L_ERR, _("can't bind tcpv4 on %s: %s, exiting."), (const char *)si, strerror (errno));
260 exit (EXIT_FAILURE); 272 exit (EXIT_FAILURE);
261 } 273 }
262 274
263 if (listen (tcpv4_fd, 5)) 275 if (listen (tcpv4_fd, 5))
264 { 276 {
265 slog (L_ERR, _("can't listen tcpv4 on %s: %s"), (const char *)si, strerror (errno)); 277 slog (L_ERR, _("can't listen tcpv4 on %s: %s, exiting."), (const char *)si, strerror (errno));
266 exit (EXIT_FAILURE); 278 exit (EXIT_FAILURE);
267 } 279 }
268 280
269 tcpv4_ev_watcher.start (tcpv4_fd, EV_READ); 281 tcpv4_ev_watcher.start (tcpv4_fd, EV_READ);
270 } 282 }
306 THISNODE->dns_hostname ? THISNODE->dns_port : 0, 318 THISNODE->dns_hostname ? THISNODE->dns_port : 0,
307 PROT_DNSv4); 319 PROT_DNSv4);
308 320
309 if (bind (dnsv4_fd, si.sav4 (), si.salenv4 ())) 321 if (bind (dnsv4_fd, si.sav4 (), si.salenv4 ()))
310 { 322 {
311 slog (L_ERR, _("can't bind dnsv4 on %s: %s"), (const char *)si, strerror (errno)); 323 slog (L_ERR, _("can't bind dnsv4 on %s: %s, exiting."), (const char *)si, strerror (errno));
312 exit (EXIT_FAILURE); 324 exit (EXIT_FAILURE);
313 } 325 }
314 326
315 dnsv4_ev_watcher.start (dnsv4_fd, EV_READ); 327 dnsv4_ev_watcher.start (dnsv4_fd, EV_READ);
316 } 328 }
323 ///////////////////////////////////////////////////////////////////////////// 335 /////////////////////////////////////////////////////////////////////////////
324 336
325 tap = new tap_device (); 337 tap = new tap_device ();
326 if (!tap) //D this, of course, never catches 338 if (!tap) //D this, of course, never catches
327 { 339 {
328 slog (L_ERR, _("cannot create network interface '%s'"), conf.ifname); 340 slog (L_ERR, _("cannot create network interface '%s', exiting."), conf.ifname);
329 exit (EXIT_FAILURE); 341 exit (EXIT_FAILURE);
330 } 342 }
331 343
332 fcntl (tap->fd, F_SETFD, FD_CLOEXEC); 344 fcntl (tap->fd, F_SETFD, FD_CLOEXEC);
333 345
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
436void 448void
437vpn::recv_vpn_packet (vpn_packet *pkt, const sockinfo &rsi) 449vpn::recv_vpn_packet (vpn_packet *pkt, const sockinfo &rsi)
438{ 450{
439 unsigned int src = pkt->src (); 451 unsigned int src = pkt->src ();
440 unsigned int dst = pkt->dst (); 452 unsigned int dst = pkt->dst ();
441 453
442 slog (L_NOISE, _("<<?/%s received possible vpn packet type %d from %d to %d, length %d"), 454 slog (L_NOISE, _("<<?/%s received possible vpn packet type %d from %d to %d, length %d."),
443 (const char *)rsi, pkt->typ (), pkt->src (), pkt->dst (), pkt->len); 455 (const char *)rsi, pkt->typ (), pkt->src (), pkt->dst (), pkt->len);
444 456
445 if (src == 0 || src > conns.size () 457 if (src == 0 || src > conns.size ()
446 || dst > conns.size () 458 || dst > conns.size ()
447 || pkt->typ () >= vpn_packet::PT_MAX) 459 || pkt->typ () >= vpn_packet::PT_MAX)
448 slog (L_WARN, _("(%s): received corrupted packet type %d (src %d, dst %d)"), 460 slog (L_WARN, _("(%s): received corrupted packet type %d (src %d, dst %d)."),
449 (const char *)rsi, pkt->typ (), pkt->src (), pkt->dst ()); 461 (const char *)rsi, pkt->typ (), pkt->src (), pkt->dst ());
450 else if (dst > conns.size ()) 462 else if (dst > conns.size ())
451 slog (L_WARN, _("(%s): received corrupted packet type %d (src %d, dst %d)"), 463 slog (L_WARN, _("(%s): received corrupted packet type %d (src %d, dst %d)."),
452 (const char *)rsi, pkt->typ (), pkt->src (), pkt->dst ()); 464 (const char *)rsi, pkt->typ (), pkt->src (), pkt->dst ());
453 else 465 else
454 { 466 {
455 connection *c = conns[src - 1]; 467 connection *c = conns[src - 1];
456 468
457 if (dst == 0) 469 if (dst == 0)
458 slog (L_WARN, _("%s(%s): received broadcast (protocol violation)"), 470 slog (L_WARN, _("%s(%s): received broadcast (protocol violation)."),
459 c->conf->nodename, (const char *)rsi); 471 c->conf->nodename, (const char *)rsi);
460 else if (dst != THISNODE->id) 472 else if (dst != THISNODE->id)
461 { 473 {
462 if (THISNODE->routerprio) 474 if (THISNODE->routerprio)
463 // the tos setting gets lost here. who cares. 475 // the tos setting gets lost here. who cares.
464 conns[dst - 1]->inject_vpn_packet (pkt); 476 conns[dst - 1]->inject_vpn_packet (pkt);
465 else 477 else
466 slog (L_WARN, 478 slog (L_WARN,
467 _("%s(%s): forwarding request (=> %s), but we are no router"), 479 _("%s(%s): request to forward packet to %s, but we are no router (config mismatch?)."),
468 c->conf->nodename, (const char *)rsi, 480 c->conf->nodename, (const char *)rsi,
469 conns[dst - 1]->conf->nodename); 481 conns[dst - 1]->conf->nodename);
470 } 482 }
471 else 483 else
472 c->recv_vpn_packet (pkt, rsi); 484 c->recv_vpn_packet (pkt, rsi);
495#if ENABLE_DNS 507#if ENABLE_DNS
496 case PROT_DNSv4: 508 case PROT_DNSv4:
497 return send_dnsv4_packet (pkt, si, tos); 509 return send_dnsv4_packet (pkt, si, tos);
498#endif 510#endif
499 default: 511 default:
500 slog (L_CRIT, _("%s: FATAL: trying to send packet with unsupported protocol"), (const char *)si); 512 slog (L_CRIT, _("%s: FATAL: trying to send packet with unsupported protocol."), (const char *)si);
501 } 513 }
502 514
503 return false; 515 return false;
504} 516}
505 517
506void 518inline void
507vpn::ipv4_ev (ev::io &w, int revents) 519vpn::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;
527 recv_vpn_packet (pkt, si); 539 recv_vpn_packet (pkt, si);
528 } 540 }
529 else 541 else
530 { 542 {
531 // probably ECONNRESET or somesuch 543 // probably ECONNRESET or somesuch
532 slog (L_DEBUG, _("%s: %s"), (const char *)si, strerror (errno)); 544 slog (L_DEBUG, _("%s: %s."), (const char *)si, strerror (errno));
533 } 545 }
534 546
535 delete pkt; 547 delete pkt;
536 } 548 }
537 else 549 else
538 { 550 {
539 slog (L_ERR, 551 slog (L_ERR,
540 _("FATAL: unknown revents %08x in socket, terminating\n"), 552 _("FATAL: unknown revents %08x in socket, exiting.\n"),
541 revents); 553 revents);
542 exit (EXIT_FAILURE); 554 exit (EXIT_FAILURE);
543 } 555 }
544} 556}
545 557
546#if ENABLE_ICMP 558#if ENABLE_ICMP
547void 559inline void
548vpn::icmpv4_ev (ev::io &w, int revents) 560vpn::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;
575 } 587 }
576 } 588 }
577 else 589 else
578 { 590 {
579 // probably ECONNRESET or somesuch 591 // probably ECONNRESET or somesuch
580 slog (L_DEBUG, _("%s: %s"), (const char *)si, strerror (errno)); 592 slog (L_DEBUG, _("%s: %s."), (const char *)si, strerror (errno));
581 } 593 }
582 594
583 delete pkt; 595 delete pkt;
584 } 596 }
585 else 597 else
586 { 598 {
587 slog (L_ERR, 599 slog (L_ERR,
588 _("FATAL: unknown revents %08x in socket, terminating\n"), 600 _("FATAL: unknown revents %08x in socket, exiting.\n"),
589 revents); 601 revents);
590 exit (EXIT_FAILURE); 602 exit (EXIT_FAILURE);
591 } 603 }
592} 604}
593#endif 605#endif
594 606
595void 607inline void
596vpn::udpv4_ev (ev::io &w, int revents) 608vpn::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;
613 recv_vpn_packet (pkt, si); 625 recv_vpn_packet (pkt, si);
614 } 626 }
615 else 627 else
616 { 628 {
617 // probably ECONNRESET or somesuch 629 // probably ECONNRESET or somesuch
618 slog (L_DEBUG, _("%s: fd %d, %s"), (const char *)si, w.fd, strerror (errno)); 630 slog (L_DEBUG, _("%s: fd %d, %s."), (const char *)si, w.fd, strerror (errno));
619 } 631 }
620 632
621 delete pkt; 633 delete pkt;
622 } 634 }
623 else 635 else
624 { 636 {
625 slog (L_ERR, 637 slog (L_ERR,
626 _("FATAL: unknown revents %08x in socket, terminating\n"), 638 _("FATAL: unknown revents %08x in socket, exiting.\n"),
627 revents); 639 revents);
628 exit (EXIT_FAILURE); 640 exit (EXIT_FAILURE);
629 } 641 }
630} 642}
631 643
632void 644inline void
633vpn::tap_ev (ev::io &w, int revents) 645vpn::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
674void 686inline void
675vpn::event_cb (ev::timer &w, int) 687vpn::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)
680 { 692 {
681 slog (L_INFO, _("preparing shutdown...")); 693 slog (L_INFO, _("preparing shutdown..."));
682 694
683 shutdown_all (); 695 shutdown_all ();
684 remove_pid (conf.pidfilename); 696 remove_pid (conf.pidfilename);
685 slog (L_INFO, _("terminating")); 697 slog (L_INFO, _("exiting."));
686 exit (EXIT_SUCCESS); 698 exit (EXIT_SUCCESS);
687 } 699 }
688 700
689 if (events & EVENT_RECONNECT) 701 if (events & EVENT_RECONNECT)
690 { 702 {
691 slog (L_INFO, _("forced reconnect")); 703 slog (L_INFO, _("forced reconnect."));
692 704
693 reconnect_all (); 705 reconnect_all ();
694 } 706 }
695 707
696 events = 0; 708 events = 0;
721 conns.push_back (conn); 733 conns.push_back (conn);
722 conn->establish_connection (); 734 conn->establish_connection ();
723 } 735 }
724} 736}
725 737
726connection *vpn::find_router () 738bool vpn::can_direct (conf_node *src, conf_node *dst) const
727{ 739{
728 u32 prio = 1; 740 return src != dst
741 && src->may_direct (dst)
742 && dst->may_direct (src)
743 && (((src->protocols & dst->protocols) && src->connectmode == conf_node::C_ALWAYS)
744 || (src->protocols & dst->connectable_protocols ()));
745}
746
747// only works for indirect and routed connections: find a router
748// from THISNODE to dst
749connection *vpn::find_router_for (const connection *dst)
750{
729 connection *router = 0; 751 connection *router = 0;
730 752
753 // first try to find a router with a direct connection
754 {
755 u32 prio = 1;
756
757 for (conns_vector::iterator i = conns.begin (); i != conns.end (); ++i)
758 {
759 connection *c = *i;
760
761 if (c->conf->routerprio > prio
762 && c->conf != THISNODE
763 && c != dst
764 && can_direct (c->conf, dst->conf))
765 {
766 if (c->ictx && c->octx)
767 {
768 prio = c->conf->routerprio;
769 router = c;
770 }
771 else
772 c->establish_connection ();
773 }
774 }
775 }
776
777 if (router)
778 return router;
779
780 // second try find the router with the highest priority higher than ours
781 {
782 u32 prio = 1;
783
784 for (conns_vector::iterator i = conns.begin (); i != conns.end (); ++i)
785 {
786 connection *c = *i;
787
788 if (c->conf->routerprio > prio
789 && c->conf->routerprio > THISNODE->routerprio
790 && c != dst
791 && c->conf != THISNODE)
792 {
793 if (c->ictx && c->octx)
794 {
795 prio = c->conf->routerprio;
796 router = c;
797 }
798 else
799 c->establish_connection ();
800 }
801 }
802 }
803 return router;
804}
805
806void vpn::connection_established (connection *c)
807{
731 for (conns_vector::iterator i = conns.begin (); i != conns.end (); ++i) 808 for (conns_vector::iterator i = conns.begin (); i != conns.end (); ++i)
732 { 809 {
733 connection *c = *i; 810 connection *o = *i;
734 811
735 if (c->conf->routerprio > prio 812 if (!o->is_direct
736 && c->connectmode == conf_node::C_ALWAYS // so we don't drop the connection if in use 813 && o->si.valid ()
737 && c->ictx && c->octx 814 && c->si != o->si
738 && c->conf != THISNODE) // redundant, since ictx==octx==0 always on thisnode 815 && c == find_router_for (o))
739 {
740 prio = c->conf->routerprio;
741 router = c;
742 } 816 {
817 slog (L_DEBUG, _("%s: can now route packets via %s, re-keying connection."),
818 o->conf->nodename, c->conf->nodename);
819 o->rekey ();
820 }
743 } 821 }
744
745 return router;
746} 822}
747 823
748void vpn::send_connect_request (int id) 824void vpn::send_connect_request (int id)
749{ 825{
750 connection *c = find_router (); 826 connection *c = find_router_for (conns[id]);
751 827
752 if (c) 828 if (c)
829 {
830 slog (L_TRACE, _("%s: no way to connect, sending mediated connection request via %s."),
831 conns[id]->conf->nodename, c->conf->nodename);
753 c->send_connect_request (id); 832 c->send_connect_request (id);
833 }
754 else 834 else
755 // no router found, aggressively connect to all routers 835 slog (L_DEBUG, _("%s: no way to connect and no router found: unable to connect."), conns[id]->conf->nodename);
756 for (conns_vector::iterator i = conns.begin (); i != conns.end (); ++i)
757 if ((*i)->conf->routerprio && (*i)->conf != THISNODE)
758 (*i)->establish_connection ();
759} 836}
760 837
761void 838void
762connection::dump_status () 839connection::dump_status ()
763{ 840{
764 slog (L_NOTICE, _("node %s (id %d)"), conf->nodename, conf->id); 841 slog (L_NOTICE, _("node %s (id %d)"), conf->nodename, conf->id);
765 slog (L_NOTICE, _(" connectmode %d (%d) / sockaddr %s / minor %d"), 842 slog (L_NOTICE, _(" connectmode %d (%d) / sockaddr %s / minor %d"),
766 connectmode, conf->connectmode, (const char *)si, (int)prot_minor); 843 connectmode, conf->connectmode, (const char *)si, (int)prot_minor);
767 slog (L_NOTICE, _(" ictx/octx %08lx/%08lx / oseqno %d / retry_cnt %d"), 844 slog (L_NOTICE, _(" ictx/octx %08lx/%08lx / oseqno %d / retry_cnt %d"),
768 (long)ictx, (long)octx, (int)oseqno, (int)retry_cnt); 845 (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} 846}
772 847
773void 848void
774vpn::dump_status () 849vpn::dump_status ()
775{ 850{

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines