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

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines