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.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>
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;
723 conns.push_back (conn); 733 conns.push_back (conn);
724 conn->establish_connection (); 734 conn->establish_connection ();
725 } 735 }
726} 736}
727 737
728connection *vpn::find_router () 738bool vpn::can_direct (conf_node *src, conf_node *dst) const
729{ 739{
730 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{
731 connection *router = 0; 751 connection *router = 0;
732 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{
733 for (conns_vector::iterator i = conns.begin (); i != conns.end (); ++i) 808 for (conns_vector::iterator i = conns.begin (); i != conns.end (); ++i)
734 { 809 {
735 connection *c = *i; 810 connection *o = *i;
736 811
737 if (c->conf->routerprio > prio 812 if (!o->is_direct
738 && c->connectmode == conf_node::C_ALWAYS // so we don't drop the connection if in use 813 && o->si.valid ()
739 && c->ictx && c->octx 814 && c->si != o->si
740 && c->conf != THISNODE) // redundant, since ictx==octx==0 always on thisnode 815 && c == find_router_for (o))
741 {
742 prio = c->conf->routerprio;
743 router = c;
744 } 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 }
745 } 821 }
746
747 return router;
748} 822}
749 823
750void vpn::send_connect_request (int id) 824void vpn::send_connect_request (int id)
751{ 825{
752 connection *c = find_router (); 826 connection *c = find_router_for (conns[id]);
753 827
754 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);
755 c->send_connect_request (id); 832 c->send_connect_request (id);
833 }
756 else 834 else
757 // 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);
758 for (conns_vector::iterator i = conns.begin (); i != conns.end (); ++i)
759 if ((*i)->conf->routerprio && (*i)->conf != THISNODE)
760 (*i)->establish_connection ();
761} 836}
762 837
763void 838void
764connection::dump_status () 839connection::dump_status ()
765{ 840{
766 slog (L_NOTICE, _("node %s (id %d)"), conf->nodename, conf->id); 841 slog (L_NOTICE, _("node %s (id %d)"), conf->nodename, conf->id);
767 slog (L_NOTICE, _(" connectmode %d (%d) / sockaddr %s / minor %d"), 842 slog (L_NOTICE, _(" connectmode %d (%d) / sockaddr %s / minor %d"),
768 connectmode, conf->connectmode, (const char *)si, (int)prot_minor); 843 connectmode, conf->connectmode, (const char *)si, (int)prot_minor);
769 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"),
770 (long)ictx, (long)octx, (int)oseqno, (int)retry_cnt); 845 (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} 846}
774 847
775void 848void
776vpn::dump_status () 849vpn::dump_status ()
777{ 850{

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines