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.45 by pcg, Thu Dec 6 00:35:29 2007 UTC vs.
Revision 1.53 by pcg, Fri Aug 15 17:50:10 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>
112} 122}
113 123
114int 124int
115vpn::setup () 125vpn::setup ()
116{ 126{
127 int success = 0;
128
117 ipv4_tos = -1; 129 ipv4_tos = -1;
118 ipv4_fd = -1; 130 ipv4_fd = -1;
119 131
120 if (THISNODE->protocols & PROT_IPv4 && ::conf.ip_proto) 132 if (THISNODE->protocols & PROT_IPv4 && ::conf.ip_proto)
121 { 133 {
139 151
140 sockinfo si (THISNODE, PROT_IPv4); 152 sockinfo si (THISNODE, PROT_IPv4);
141 153
142 if (bind (ipv4_fd, si.sav4 (), si.salenv4 ())) 154 if (bind (ipv4_fd, si.sav4 (), si.salenv4 ()))
143 { 155 {
144 slog (L_ERR, _("can't bind ipv4 socket on %s: %s"), (const char *)si, strerror (errno)); 156 slog (L_ERR, _("can't bind ipv4 socket on %s: %s, exiting."), (const char *)si, strerror (errno));
145 exit (EXIT_FAILURE); 157 exit (EXIT_FAILURE);
146 } 158 }
147 159
148 ipv4_ev_watcher.start (ipv4_fd, EV_READ); 160 ipv4_ev_watcher.start (ipv4_fd, EV_READ);
161 ++success;
149 } 162 }
163 else
164 THISNODE->protocols &= ~PROT_IPv4;
150 165
151 udpv4_tos = -1; 166 udpv4_tos = -1;
152 udpv4_fd = -1; 167 udpv4_fd = -1;
153 168
154 if (THISNODE->protocols & PROT_UDPv4 && THISNODE->udp_port) 169 if (THISNODE->protocols & PROT_UDPv4 && THISNODE->udp_port)
179 194
180 sockinfo si (THISNODE, PROT_UDPv4); 195 sockinfo si (THISNODE, PROT_UDPv4);
181 196
182 if (bind (udpv4_fd, si.sav4 (), si.salenv4 ())) 197 if (bind (udpv4_fd, si.sav4 (), si.salenv4 ()))
183 { 198 {
184 slog (L_ERR, _("can't bind udpv4 on %s: %s"), (const char *)si, strerror (errno)); 199 slog (L_ERR, _("can't bind udpv4 on %s: %s, exiting."), (const char *)si, strerror (errno));
185 exit (EXIT_FAILURE); 200 exit (EXIT_FAILURE);
186 } 201 }
187 202
188 udpv4_ev_watcher.start (udpv4_fd, EV_READ); 203 udpv4_ev_watcher.start (udpv4_fd, EV_READ);
204 ++success;
189 } 205 }
206 else
207 THISNODE->protocols &= ~PROT_UDPv4;
190 208
191 icmpv4_tos = -1; 209 icmpv4_tos = -1;
192 icmpv4_fd = -1; 210 icmpv4_fd = -1;
193 211
194#if ENABLE_ICMP 212#if ENABLE_ICMP
225 243
226 sockinfo si (THISNODE, PROT_ICMPv4); 244 sockinfo si (THISNODE, PROT_ICMPv4);
227 245
228 if (bind (icmpv4_fd, si.sav4 (), si.salenv4 ())) 246 if (bind (icmpv4_fd, si.sav4 (), si.salenv4 ()))
229 { 247 {
230 slog (L_ERR, _("can't bind icmpv4 on %s: %s"), (const char *)si, strerror (errno)); 248 slog (L_ERR, _("can't bind icmpv4 on %s: %s, exiting."), (const char *)si, strerror (errno));
231 exit (EXIT_FAILURE); 249 exit (EXIT_FAILURE);
232 } 250 }
233 251
234 icmpv4_ev_watcher.start (icmpv4_fd, EV_READ); 252 icmpv4_ev_watcher.start (icmpv4_fd, EV_READ);
253 ++success;
235 } 254 }
236#endif 255#endif
237 256
238 tcpv4_fd = -1; 257 tcpv4_fd = -1;
239 258
256 275
257 sockinfo si (THISNODE, PROT_TCPv4); 276 sockinfo si (THISNODE, PROT_TCPv4);
258 277
259 if (bind (tcpv4_fd, si.sav4 (), si.salenv4 ())) 278 if (bind (tcpv4_fd, si.sav4 (), si.salenv4 ()))
260 { 279 {
261 slog (L_ERR, _("can't bind tcpv4 on %s: %s"), (const char *)si, strerror (errno)); 280 slog (L_ERR, _("can't bind tcpv4 on %s: %s, exiting."), (const char *)si, strerror (errno));
262 exit (EXIT_FAILURE); 281 exit (EXIT_FAILURE);
263 } 282 }
264 283
265 if (listen (tcpv4_fd, 5)) 284 if (listen (tcpv4_fd, 5))
266 { 285 {
267 slog (L_ERR, _("can't listen tcpv4 on %s: %s"), (const char *)si, strerror (errno)); 286 slog (L_ERR, _("can't listen tcpv4 on %s: %s, exiting."), (const char *)si, strerror (errno));
268 exit (EXIT_FAILURE); 287 exit (EXIT_FAILURE);
269 } 288 }
270 289
271 tcpv4_ev_watcher.start (tcpv4_fd, EV_READ); 290 tcpv4_ev_watcher.start (tcpv4_fd, EV_READ);
291 ++success;
272 } 292 }
293 else
294 THISNODE->protocols &= ~PROT_TCPv4;
273#endif 295#endif
274 296
275 dnsv4_tos = -1; 297 dnsv4_tos = -1;
276 dnsv4_fd = -1; 298 dnsv4_fd = -1;
277 299
308 THISNODE->dns_hostname ? THISNODE->dns_port : 0, 330 THISNODE->dns_hostname ? THISNODE->dns_port : 0,
309 PROT_DNSv4); 331 PROT_DNSv4);
310 332
311 if (bind (dnsv4_fd, si.sav4 (), si.salenv4 ())) 333 if (bind (dnsv4_fd, si.sav4 (), si.salenv4 ()))
312 { 334 {
313 slog (L_ERR, _("can't bind dnsv4 on %s: %s"), (const char *)si, strerror (errno)); 335 slog (L_ERR, _("can't bind dnsv4 on %s: %s, exiting."), (const char *)si, strerror (errno));
314 exit (EXIT_FAILURE); 336 exit (EXIT_FAILURE);
315 } 337 }
316 338
317 dnsv4_ev_watcher.start (dnsv4_fd, EV_READ); 339 dnsv4_ev_watcher.start (dnsv4_fd, EV_READ);
340 ++success;
318 } 341 }
319#endif 342#endif
320 343
321 ///////////////////////////////////////////////////////////////////////////// 344 /////////////////////////////////////////////////////////////////////////////
345
346 if (!success)
347 {
348 slog (L_ERR, _("no protocols enabled, exiting."));
349 exit (EXIT_FAILURE);
350 }
322 351
323 reconnect_all (); 352 reconnect_all ();
324 353
325 ///////////////////////////////////////////////////////////////////////////// 354 /////////////////////////////////////////////////////////////////////////////
326 355
327 tap = new tap_device (); 356 tap = new tap_device ();
328 if (!tap) //D this, of course, never catches 357 if (!tap) //D this, of course, never catches
329 { 358 {
330 slog (L_ERR, _("cannot create network interface '%s'"), conf.ifname); 359 slog (L_ERR, _("cannot create network interface '%s', exiting."), conf.ifname);
331 exit (EXIT_FAILURE); 360 exit (EXIT_FAILURE);
332 } 361 }
333 362
334 fcntl (tap->fd, F_SETFD, FD_CLOEXEC); 363 fcntl (tap->fd, F_SETFD, FD_CLOEXEC);
335 364
429 { 458 {
430 // broadcast, this is ugly, but due to the security policy 459 // broadcast, this is ugly, but due to the security policy
431 // we have to connect to all hosts... 460 // we have to connect to all hosts...
432 for (conns_vector::iterator c = conns.begin (); c != conns.end (); ++c) 461 for (conns_vector::iterator c = conns.begin (); c != conns.end (); ++c)
433 if ((*c)->conf != THISNODE) 462 if ((*c)->conf != THISNODE)
434 (*c)->inject_data_packet (pkt, true); 463 (*c)->inject_data_packet (pkt);
435 } 464 }
436} 465}
437 466
438void 467void
439vpn::recv_vpn_packet (vpn_packet *pkt, const sockinfo &rsi) 468vpn::recv_vpn_packet (vpn_packet *pkt, const sockinfo &rsi)
440{ 469{
441 unsigned int src = pkt->src (); 470 unsigned int src = pkt->src ();
442 unsigned int dst = pkt->dst (); 471 unsigned int dst = pkt->dst ();
443 472
444 slog (L_NOISE, _("<<?/%s received possible vpn packet type %d from %d to %d, length %d"), 473 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); 474 (const char *)rsi, pkt->typ (), pkt->src (), pkt->dst (), pkt->len);
446 475
447 if (src == 0 || src > conns.size () 476 if (src == 0 || src > conns.size ()
448 || dst > conns.size () 477 || dst > conns.size ()
449 || pkt->typ () >= vpn_packet::PT_MAX) 478 || pkt->typ () >= vpn_packet::PT_MAX)
450 slog (L_WARN, _("(%s): received corrupted packet type %d (src %d, dst %d)"), 479 slog (L_WARN, _("(%s): received corrupted packet type %d (src %d, dst %d)."),
451 (const char *)rsi, pkt->typ (), pkt->src (), pkt->dst ()); 480 (const char *)rsi, pkt->typ (), pkt->src (), pkt->dst ());
452 else if (dst > conns.size ()) 481 else if (dst > conns.size ())
453 slog (L_WARN, _("(%s): received corrupted packet type %d (src %d, dst %d)"), 482 slog (L_WARN, _("(%s): received corrupted packet type %d (src %d, dst %d)."),
454 (const char *)rsi, pkt->typ (), pkt->src (), pkt->dst ()); 483 (const char *)rsi, pkt->typ (), pkt->src (), pkt->dst ());
455 else 484 else
456 { 485 {
457 connection *c = conns[src - 1]; 486 connection *c = conns[src - 1];
458 487
459 if (dst == 0) 488 if (dst == 0)
460 slog (L_WARN, _("%s(%s): received broadcast (protocol violation)"), 489 slog (L_WARN, _("%s(%s): received broadcast (protocol violation)."),
461 c->conf->nodename, (const char *)rsi); 490 c->conf->nodename, (const char *)rsi);
462 else if (dst != THISNODE->id) 491 else if (dst != THISNODE->id)
463 { 492 {
464 if (THISNODE->routerprio) 493 if (THISNODE->routerprio)
465 // the tos setting gets lost here. who cares. 494 // the tos setting gets lost here. who cares.
466 conns[dst - 1]->inject_vpn_packet (pkt); 495 conns[dst - 1]->inject_vpn_packet (pkt);
467 else 496 else
468 slog (L_WARN, 497 slog (L_WARN,
469 _("%s(%s): forwarding request (=> %s), but we are no router"), 498 _("%s(%s): request to forward packet to %s, but we are no router (config mismatch?)."),
470 c->conf->nodename, (const char *)rsi, 499 c->conf->nodename, (const char *)rsi,
471 conns[dst - 1]->conf->nodename); 500 conns[dst - 1]->conf->nodename);
472 } 501 }
473 else 502 else
474 c->recv_vpn_packet (pkt, rsi); 503 c->recv_vpn_packet (pkt, rsi);
497#if ENABLE_DNS 526#if ENABLE_DNS
498 case PROT_DNSv4: 527 case PROT_DNSv4:
499 return send_dnsv4_packet (pkt, si, tos); 528 return send_dnsv4_packet (pkt, si, tos);
500#endif 529#endif
501 default: 530 default:
502 slog (L_CRIT, _("%s: FATAL: trying to send packet with unsupported protocol"), (const char *)si); 531 slog (L_CRIT, _("%s: FATAL: trying to send packet with unsupported protocol."), (const char *)si);
503 } 532 }
504 533
505 return false; 534 return false;
506} 535}
507 536
529 recv_vpn_packet (pkt, si); 558 recv_vpn_packet (pkt, si);
530 } 559 }
531 else 560 else
532 { 561 {
533 // probably ECONNRESET or somesuch 562 // probably ECONNRESET or somesuch
534 slog (L_DEBUG, _("%s: %s"), (const char *)si, strerror (errno)); 563 slog (L_DEBUG, _("%s: %s."), (const char *)si, strerror (errno));
535 } 564 }
536 565
537 delete pkt; 566 delete pkt;
538 } 567 }
539 else 568 else
540 { 569 {
541 slog (L_ERR, 570 slog (L_ERR,
542 _("FATAL: unknown revents %08x in socket, terminating\n"), 571 _("FATAL: unknown revents %08x in socket, exiting.\n"),
543 revents); 572 revents);
544 exit (EXIT_FAILURE); 573 exit (EXIT_FAILURE);
545 } 574 }
546} 575}
547 576
577 } 606 }
578 } 607 }
579 else 608 else
580 { 609 {
581 // probably ECONNRESET or somesuch 610 // probably ECONNRESET or somesuch
582 slog (L_DEBUG, _("%s: %s"), (const char *)si, strerror (errno)); 611 slog (L_DEBUG, _("%s: %s."), (const char *)si, strerror (errno));
583 } 612 }
584 613
585 delete pkt; 614 delete pkt;
586 } 615 }
587 else 616 else
588 { 617 {
589 slog (L_ERR, 618 slog (L_ERR,
590 _("FATAL: unknown revents %08x in socket, terminating\n"), 619 _("FATAL: unknown revents %08x in socket, exiting.\n"),
591 revents); 620 revents);
592 exit (EXIT_FAILURE); 621 exit (EXIT_FAILURE);
593 } 622 }
594} 623}
595#endif 624#endif
615 recv_vpn_packet (pkt, si); 644 recv_vpn_packet (pkt, si);
616 } 645 }
617 else 646 else
618 { 647 {
619 // probably ECONNRESET or somesuch 648 // probably ECONNRESET or somesuch
620 slog (L_DEBUG, _("%s: fd %d, %s"), (const char *)si, w.fd, strerror (errno)); 649 slog (L_DEBUG, _("%s: fd %d, %s."), (const char *)si, w.fd, strerror (errno));
621 } 650 }
622 651
623 delete pkt; 652 delete pkt;
624 } 653 }
625 else 654 else
626 { 655 {
627 slog (L_ERR, 656 slog (L_ERR,
628 _("FATAL: unknown revents %08x in socket, terminating\n"), 657 _("FATAL: unknown revents %08x in socket, exiting.\n"),
629 revents); 658 revents);
630 exit (EXIT_FAILURE); 659 exit (EXIT_FAILURE);
631 } 660 }
632} 661}
633 662
682 { 711 {
683 slog (L_INFO, _("preparing shutdown...")); 712 slog (L_INFO, _("preparing shutdown..."));
684 713
685 shutdown_all (); 714 shutdown_all ();
686 remove_pid (conf.pidfilename); 715 remove_pid (conf.pidfilename);
687 slog (L_INFO, _("terminating")); 716 slog (L_INFO, _("exiting."));
688 exit (EXIT_SUCCESS); 717 exit (EXIT_SUCCESS);
689 } 718 }
690 719
691 if (events & EVENT_RECONNECT) 720 if (events & EVENT_RECONNECT)
692 { 721 {
693 slog (L_INFO, _("forced reconnect")); 722 slog (L_INFO, _("forced reconnect."));
694 723
695 reconnect_all (); 724 reconnect_all ();
696 } 725 }
697 726
698 events = 0; 727 events = 0;
714 743
715 conns.clear (); 744 conns.clear ();
716 745
717 connection_init (); 746 connection_init ();
718 747
719 for (configuration::node_vector::iterator i = conf.nodes.begin (); 748 for (configuration::node_vector::iterator i = conf.nodes.begin (); i != conf.nodes.end (); ++i)
720 i != conf.nodes.end (); ++i) 749 conns.push_back (new connection (this, *i));
721 { 750
722 connection *conn = new connection (this, *i); 751 for (conns_vector::iterator c = conns.begin (); c != conns.end (); ++c)
723 conns.push_back (conn);
724 conn->establish_connection (); 752 (*c)->establish_connection ();
725 }
726} 753}
727 754
728connection *vpn::find_router () 755bool vpn::can_direct (conf_node *src, conf_node *dst) const
729{ 756{
730 u32 prio = 1; 757 return src != dst
758 && src->may_direct (dst)
759 && dst->may_direct (src)
760 && (((src->protocols & dst->protocols) && src->connectmode == conf_node::C_ALWAYS)
761 || (src->protocols & dst->connectable_protocols ()));
762}
763
764// only works for indirect and routed connections: find a router
765// from THISNODE to dst
766connection *vpn::find_router_for (const connection *dst)
767{
731 connection *router = 0; 768 connection *router = 0;
732 769
770 // first try to find a router with a direct connection, route there
771 // regardless of any other considerations.
772 {
773 u32 prio = 1;
774
775 for (conns_vector::iterator i = conns.begin (); i != conns.end (); ++i)
776 {
777 connection *c = *i;
778
779 if (c->conf->routerprio > prio
780 && c->conf != THISNODE
781 && can_direct (c->conf, dst->conf)
782 && c->ictx && c->octx)
783 {
784 prio = c->conf->routerprio;
785 router = c;
786 }
787 }
788 }
789
790 if (router)
791 return router;
792
793 // second try find the router with the highest priority, higher than ours
794 {
795 u32 prio = THISNODE->routerprio ? THISNODE->routerprio : 1;
796
797 for (conns_vector::iterator i = conns.begin (); i != conns.end (); ++i)
798 {
799 connection *c = *i;
800
801 if (c->conf->routerprio > prio
802 && c != dst
803 && c->conf != THISNODE
804 && c->ictx && c->octx)
805 {
806 prio = c->conf->routerprio;
807 router = c;
808 }
809 }
810 }
811
812 return router;
813}
814
815void vpn::connection_established (connection *c)
816{
733 for (conns_vector::iterator i = conns.begin (); i != conns.end (); ++i) 817 for (conns_vector::iterator i = conns.begin (); i != conns.end (); ++i)
734 { 818 {
735 connection *c = *i; 819 connection *o = *i;
736 820
737 if (c->conf->routerprio > prio 821 if (!o->is_direct
738 && c->connectmode == conf_node::C_ALWAYS // so we don't drop the connection if in use 822 && o->si.valid ()
739 && c->ictx && c->octx 823 && c->si != o->si
740 && c->conf != THISNODE) // redundant, since ictx==octx==0 always on thisnode 824 && c == find_router_for (o))
741 {
742 prio = c->conf->routerprio;
743 router = c;
744 } 825 {
826 slog (L_DEBUG, _("%s: can now route packets via %s, re-keying connection."),
827 o->conf->nodename, c->conf->nodename);
828 o->rekey ();
829 }
745 } 830 }
746
747 return router;
748} 831}
749 832
750void vpn::send_connect_request (int id) 833void vpn::send_connect_request (connection *c)
751{ 834{
752 connection *c = find_router (); 835 connection *r = find_router_for (c);
753 836
754 if (c) 837 if (r)
838 {
839 slog (L_TRACE, _("%s: no address known, sending mediated connection request via %s."),
840 c->conf->nodename, r->conf->nodename);
755 c->send_connect_request (id); 841 r->send_connect_request (c->conf->id);
842 }
756 else 843 else
757 // no router found, aggressively connect to all routers 844 slog (L_DEBUG, _("%s: no way to connect and no router found: unable to connect at this time."),
758 for (conns_vector::iterator i = conns.begin (); i != conns.end (); ++i) 845 c->conf->nodename);
759 if ((*i)->conf->routerprio && (*i)->conf != THISNODE)
760 (*i)->establish_connection ();
761} 846}
762 847
763void 848void
764connection::dump_status () 849connection::dump_status ()
765{ 850{
766 slog (L_NOTICE, _("node %s (id %d)"), conf->nodename, conf->id); 851 slog (L_NOTICE, _("node %s (id %d)"), conf->nodename, conf->id);
767 slog (L_NOTICE, _(" connectmode %d (%d) / sockaddr %s / minor %d"), 852 slog (L_NOTICE, _(" connectmode %d (%d) / sockaddr %s / minor %d"),
768 connectmode, conf->connectmode, (const char *)si, (int)prot_minor); 853 connectmode, conf->connectmode, (const char *)si, (int)prot_minor);
769 slog (L_NOTICE, _(" ictx/octx %08lx/%08lx / oseqno %d / retry_cnt %d"), 854 slog (L_NOTICE, _(" ictx/octx %08lx/%08lx / oseqno %d / retry_cnt %d"),
770 (long)ictx, (long)octx, (int)oseqno, (int)retry_cnt); 855 (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} 856}
774 857
775void 858void
776vpn::dump_status () 859vpn::dump_status ()
777{ 860{

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines