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.54 by pcg, Mon Mar 23 15:22:00 2009 UTC vs.
Revision 1.71 by root, Thu Oct 6 03:25:54 2022 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-2008 Marc Lehmann <gvpe@schmorp.de> 3 Copyright (C) 2003-2008,2010,2011,2013 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 it 7 GVPE is free software; you can redistribute it and/or modify it
8 under the terms of the GNU General Public License as published by the 8 under the terms of the GNU General Public License as published by the
38#include <cstdlib> 38#include <cstdlib>
39 39
40#include <sys/types.h> 40#include <sys/types.h>
41#include <sys/socket.h> 41#include <sys/socket.h>
42#include <sys/wait.h> 42#include <sys/wait.h>
43#include <sys/stat.h>
43#include <errno.h> 44#include <errno.h>
44#include <time.h> 45#include <time.h>
45#include <unistd.h> 46#include <unistd.h>
46#include <fcntl.h> 47#include <fcntl.h>
47#include <sys/socket.h> 48#include <sys/socket.h>
52 53
53#include "connection.h" 54#include "connection.h"
54#include "util.h" 55#include "util.h"
55#include "vpn.h" 56#include "vpn.h"
56 57
58using namespace std;
59
57vpn network; // THE vpn (bad design...) 60vpn network; // THE vpn (bad design...)
61
62/////////////////////////////////////////////////////////////////////////////
63
64// hopefully temporary workaround for rare buffer full conditions
65// if it happens, usually instantly retrying or retrying ~5ms later
66// is good enough with current network technologies/kernels
67
68static ssize_t
69xsendto (int fd, const void *buf, size_t len, int flags,
70 const struct sockaddr *sa, socklen_t salen)
71{
72 ssize_t res;
73
74 for (int retry = 0; retry <= 13; ++retry) // ~100ms
75 {
76 res = sendto (fd, buf, len, flags, sa, salen);
77
78 if (res >= 0 || errno != ENOBUFS)
79 break;
80
81 struct timespec ts = { 0, 1000 * retry };
82 nanosleep (&ts, 0);
83 }
84
85 return res;
86}
58 87
59///////////////////////////////////////////////////////////////////////////// 88/////////////////////////////////////////////////////////////////////////////
60 89
61static void inline 90static void inline
62set_tos (int fd, int &tos_prev, int tos) 91set_tos (int fd, int &tos_prev, int tos)
75{ 104{
76 // the tunnel device mtu should be the physical mtu - overhead 105 // the tunnel device mtu should be the physical mtu - overhead
77 // the tricky part is rounding to the cipher key blocksize 106 // the tricky part is rounding to the cipher key blocksize
78 int mtu = conf.mtu - ETH_OVERHEAD - VPE_OVERHEAD - MAX_OVERHEAD; 107 int mtu = conf.mtu - ETH_OVERHEAD - VPE_OVERHEAD - MAX_OVERHEAD;
79 mtu += ETH_OVERHEAD - 6 - 6; // now we have the data portion 108 mtu += ETH_OVERHEAD - 6 - 6; // now we have the data portion
80 mtu -= mtu % EVP_CIPHER_block_size (CIPHER); // round 109 mtu -= mtu % BLOCK_SIZE (CIPHER); // round
81 mtu -= ETH_OVERHEAD - 6 - 6; // and get interface mtu again 110 mtu -= ETH_OVERHEAD - 6 - 6; // and get interface mtu again
82 111
83 char *env; 112 char *env;
84 asprintf (&env, "CONFBASE=%s", confbase); putenv (env); 113 asprintf (&env, "CONFBASE=%s", confbase); putenv (env);
85 asprintf (&env, "IFNAME=%s", tap->interface ()); putenv (env); 114 asprintf (&env, "IFNAME=%s", tap->interface ()); putenv (env);
110inline const char * 139inline const char *
111vpn::script_if_up () 140vpn::script_if_up ()
112{ 141{
113 script_init_env (); 142 script_init_env ();
114 143
115 char *filename; 144 return conf.config_filename (::conf.script_if_up, "if-up");
116 asprintf (&filename,
117 "%s/%s",
118 confbase,
119 ::conf.script_if_up ? ::conf.script_if_up : "if-up");
120
121 return filename;
122} 145}
123 146
124int 147int
125vpn::setup_socket (u8 prot, int family, int type, int proto) 148vpn::setup_socket (u8 prot, int family, int type, int proto)
126{ 149{
135 fcntl (fd, F_SETFL, O_NONBLOCK); 158 fcntl (fd, F_SETFL, O_NONBLOCK);
136 fcntl (fd, F_SETFD, FD_CLOEXEC); 159 fcntl (fd, F_SETFD, FD_CLOEXEC);
137 160
138#ifdef SO_MARK 161#ifdef SO_MARK
139 if (::conf.nfmark) 162 if (::conf.nfmark)
140 setsockopt (ipv4_fd, SOL_SOCKET, SO_MARK, &::conf.nfmark, sizeof ::conf.nfmark); 163 if (setsockopt (fd, SOL_SOCKET, SO_MARK, &::conf.nfmark, sizeof ::conf.nfmark))
164 slog (L_WARN, _("unable to set nfmark on %s socket: %s"), strprotocol (prot), strerror (errno));
141#endif 165#endif
142 166
143 return fd; 167 return fd;
144} 168}
145 169
231 icmpv4_fd = setup_socket (PROT_ICMPv4, PF_INET, SOCK_RAW, IPPROTO_ICMP); 255 icmpv4_fd = setup_socket (PROT_ICMPv4, PF_INET, SOCK_RAW, IPPROTO_ICMP);
232 256
233 if (icmpv4_fd < 0) 257 if (icmpv4_fd < 0)
234 return -1; 258 return -1;
235 259
260// no clue where trhis is actually defined
261#if !defined(ICMP_FILTER) && defined(__linux)
262 #define ICMP_FILTER 1
263#endif
264
236#ifdef ICMP_FILTER 265#ifdef ICMP_FILTER
237 { 266 {
238 icmp_filter oval; 267 uint32_t oval;
239 oval.data = 0xffffffff; 268 oval = 0;
240 if (::conf.icmp_type < 32) 269 if (::conf.icmp_type < 32)
241 oval.data &= ~(1 << ::conf.icmp_type); 270 oval |= 1 << ::conf.icmp_type;
271 oval = ~oval;
242 272
243 setsockopt (icmpv4_fd, SOL_RAW, ICMP_FILTER, &oval, sizeof oval); 273 setsockopt (icmpv4_fd, SOL_RAW, ICMP_FILTER, &oval, sizeof oval);
244 } 274 }
245#endif 275#endif
246 276
391 421
392 return 0; 422 return 0;
393} 423}
394 424
395bool 425bool
426vpn::drop_privileges ()
427{
428 if (::conf.change_root)
429 {
430 if (!strcmp (::conf.change_root, "/"))
431 {
432 char dir [L_tmpnam];
433 if (!tmpnam (dir))
434 {
435 slog (L_CRIT, _("unable to create anonymous root path."));
436 return false;
437 }
438
439 if (mkdir (dir, 0700))
440 {
441 slog (L_CRIT, _("unable to create anonymous root directory."));
442 return false;
443 }
444
445 if (chdir (dir))
446 {
447 slog (L_CRIT, _("unable to change to anonymous root directory."));
448 return false;
449 }
450
451 if (rmdir (dir))
452 slog (L_ERR, _("unable to remove anonymous root directory, continuing."));
453 }
454 else
455 {
456 if (chdir (::conf.change_root))
457 {
458 slog (L_CRIT, _("%s: unable to change to specified root directory."), ::conf.change_root);
459 return false;
460 }
461 }
462
463 if (chroot ("."))
464 {
465 slog (L_CRIT, _("unable to set new root directory."));
466 return false;
467 }
468
469 if (chdir ("/"))
470 {
471 slog (L_CRIT, _("unable to set cwd to new root directory."));
472 return false;
473 }
474 }
475
476 if (::conf.change_gid)
477 if (setgid (::conf.change_gid))
478 {
479 slog (L_CRIT, _("unable to change group id to %d."), ::conf.change_gid);
480 return false;
481 }
482
483 if (::conf.change_uid)
484 if (setuid (::conf.change_uid))
485 {
486 slog (L_CRIT, _("unable to change user id to %d."), ::conf.change_uid);
487 return false;
488 }
489
490 return true;
491}
492
493bool
396vpn::send_ipv4_packet (vpn_packet *pkt, const sockinfo &si, int tos) 494vpn::send_ipv4_packet (vpn_packet *pkt, const sockinfo &si, int tos)
397{ 495{
398 set_tos (ipv4_fd, ipv4_tos, tos); 496 set_tos (ipv4_fd, ipv4_tos, tos);
399 sendto (ipv4_fd, &((*pkt)[0]), pkt->len, 0, si.sav4 (), si.salenv4 ()); 497 xsendto (ipv4_fd, &((*pkt)[0]), pkt->len, 0, si.sav4 (), si.salenv4 ());
400 498
401 return true; 499 return true;
402} 500}
403 501
404static u16 502static u16
435 hdr->code = 255; 533 hdr->code = 255;
436 hdr->checksum = 0; 534 hdr->checksum = 0;
437 hdr->checksum = ipv4_checksum ((u16 *)hdr, pkt->len); 535 hdr->checksum = ipv4_checksum ((u16 *)hdr, pkt->len);
438 536
439 set_tos (icmpv4_fd, icmpv4_tos, tos); 537 set_tos (icmpv4_fd, icmpv4_tos, tos);
440 sendto (icmpv4_fd, &((*pkt)[0]), pkt->len, 0, si.sav4 (), si.salenv4 ()); 538 xsendto (icmpv4_fd, &((*pkt)[0]), pkt->len, 0, si.sav4 (), si.salenv4 ());
441 539
442 return true; 540 return true;
443} 541}
444#endif 542#endif
445 543
446bool 544bool
447vpn::send_udpv4_packet (vpn_packet *pkt, const sockinfo &si, int tos) 545vpn::send_udpv4_packet (vpn_packet *pkt, const sockinfo &si, int tos)
448{ 546{
449 set_tos (udpv4_fd, udpv4_tos, tos); 547 set_tos (udpv4_fd, udpv4_tos, tos);
450 sendto (udpv4_fd, &((*pkt)[0]), pkt->len, 0, si.sav4 (), si.salenv4 ()); 548 xsendto (udpv4_fd, &((*pkt)[0]), pkt->len, 0, si.sav4 (), si.salenv4 ());
451 549
452 return true; 550 return true;
453} 551}
454 552
455void 553void
481 (const char *)rsi, pkt->typ (), pkt->src (), pkt->dst (), pkt->len); 579 (const char *)rsi, pkt->typ (), pkt->src (), pkt->dst (), pkt->len);
482 580
483 if (src == 0 || src > conns.size () 581 if (src == 0 || src > conns.size ()
484 || dst > conns.size () 582 || dst > conns.size ()
485 || pkt->typ () >= vpn_packet::PT_MAX) 583 || pkt->typ () >= vpn_packet::PT_MAX)
486 slog (L_WARN, _("(%s): received corrupted packet type %d (src %d, dst %d)."),
487 (const char *)rsi, pkt->typ (), pkt->src (), pkt->dst ());
488 else if (dst > conns.size ())
489 slog (L_WARN, _("(%s): received corrupted packet type %d (src %d, dst %d)."), 584 slog (L_WARN, _("(%s): received corrupted packet type %d (src %d, dst %d)."),
490 (const char *)rsi, pkt->typ (), pkt->src (), pkt->dst ()); 585 (const char *)rsi, pkt->typ (), pkt->src (), pkt->dst ());
491 else 586 else
492 { 587 {
493 connection *c = conns[src - 1]; 588 connection *c = conns[src - 1];
515vpn::send_vpn_packet (vpn_packet *pkt, const sockinfo &si, int tos) 610vpn::send_vpn_packet (vpn_packet *pkt, const sockinfo &si, int tos)
516{ 611{
517 switch (si.prot) 612 switch (si.prot)
518 { 613 {
519 case PROT_IPv4: 614 case PROT_IPv4:
520 return send_ipv4_packet (pkt, si, tos); 615 return send_ipv4_packet (pkt, si, tos);
521 616
522 case PROT_UDPv4: 617 case PROT_UDPv4:
523 return send_udpv4_packet (pkt, si, tos); 618 return send_udpv4_packet (pkt, si, tos);
524 619
525#if ENABLE_TCP 620#if ENABLE_TCP
526 case PROT_TCPv4: 621 case PROT_TCPv4:
527 return send_tcpv4_packet (pkt, si, tos); 622 return send_tcpv4_packet (pkt, si, tos);
528#endif 623#endif
529#if ENABLE_ICMP 624#if ENABLE_ICMP
530 case PROT_ICMPv4: 625 case PROT_ICMPv4:
531 return send_icmpv4_packet (pkt, si, tos); 626 return send_icmpv4_packet (pkt, si, tos);
532#endif 627#endif
533#if ENABLE_DNS 628#if ENABLE_DNS
534 case PROT_DNSv4: 629 case PROT_DNSv4:
535 return send_dnsv4_packet (pkt, si, tos); 630 return send_dnsv4_packet (pkt, si, tos);
536#endif 631#endif
537 default: 632 default:
538 slog (L_CRIT, _("%s: FATAL: trying to send packet with unsupported protocol."), (const char *)si); 633 slog (L_CRIT, _("%s: FATAL: trying to send packet with unsupported protocol."), (const char *)si);
539 } 634 }
540 635
558 if (len > 0) 653 if (len > 0)
559 { 654 {
560 pkt->len = len; 655 pkt->len = len;
561 656
562 // raw sockets deliver the ipv4 header, but don't expect it on sends 657 // raw sockets deliver the ipv4 header, but don't expect it on sends
563 pkt->skip_hdr (IP_OVERHEAD); 658 pkt->skip_hdr (pkt->ipv4_hdr_len ());
564 659
565 recv_vpn_packet (pkt, si); 660 recv_vpn_packet (pkt, si);
566 } 661 }
567 else 662 else
568 { 663 {
605 if (hdr->type == ::conf.icmp_type 700 if (hdr->type == ::conf.icmp_type
606 && hdr->code == 255) 701 && hdr->code == 255)
607 { 702 {
608 // raw sockets deliver the ipv4, but don't expect it on sends 703 // raw sockets deliver the ipv4, but don't expect it on sends
609 // this is slow, but... 704 // this is slow, but...
610 pkt->skip_hdr (ICMP_OVERHEAD); 705 pkt->skip_hdr (pkt->ipv4_hdr_len () + (ICMP_OVERHEAD - IP_OVERHEAD));
611 706
612 recv_vpn_packet (pkt, si); 707 recv_vpn_packet (pkt, si);
613 } 708 }
614 } 709 }
615 else 710 else
757 852
758 for (conns_vector::iterator c = conns.begin (); c != conns.end (); ++c) 853 for (conns_vector::iterator c = conns.begin (); c != conns.end (); ++c)
759 (*c)->establish_connection (); 854 (*c)->establish_connection ();
760} 855}
761 856
857bool
762bool vpn::can_direct (conf_node *src, conf_node *dst) const 858vpn::can_direct (conf_node *src, conf_node *dst) const
763{ 859{
764 return src != dst 860 return src != dst
765 && src->may_direct (dst) 861 && src->may_direct (dst)
766 && dst->may_direct (src) 862 && dst->may_direct (src)
767 && (((src->protocols & dst->protocols) && src->connectmode == conf_node::C_ALWAYS) 863 && (((src->protocols & dst->protocols) && src->connectmode == conf_node::C_ALWAYS)
768 || (src->protocols & dst->connectable_protocols ())); 864 || (src->protocols & dst->connectable_protocols ()));
769} 865}
770 866
771// only works for indirect and routed connections: find a router 867// only works for indirect and routed connections: find a router
772// from THISNODE to dst 868// from THISNODE to dst
869connection *
773connection *vpn::find_router_for (const connection *dst) 870vpn::find_router_for (const connection *dst)
774{ 871{
775 connection *router = 0; 872 connection *router = 0;
776 873
777 // first try to find a router with a direct connection, route there 874 // first try to find a router with a direct connection, route there
778 // regardless of any other considerations. 875 // regardless of any other considerations.
817 } 914 }
818 915
819 return router; 916 return router;
820} 917}
821 918
919void
822void vpn::connection_established (connection *c) 920vpn::connection_established (connection *c)
823{ 921{
824 for (conns_vector::iterator i = conns.begin (); i != conns.end (); ++i) 922 for (conns_vector::iterator i = conns.begin (); i != conns.end (); ++i)
825 { 923 {
826 connection *o = *i; 924 connection *o = *i;
827 925
828 if (!o->is_direct
829 && o->si.valid () 926 if (o->si.valid ()
830 && c->si != o->si 927 && c->si != o->si
831 && c == find_router_for (o)) 928 && c == find_router_for (o)
929 && !can_direct (THISNODE, o->conf))
832 { 930 {
833 slog (L_DEBUG, _("%s: can now route packets via %s, re-keying connection."), 931 slog (L_DEBUG, _("%s: can now route packets via %s, re-keying connection."),
834 o->conf->nodename, c->conf->nodename); 932 o->conf->nodename, c->conf->nodename);
835 o->rekey (); 933 o->rekey ();
836 } 934 }
837 } 935 }
838} 936}
839 937
938void
840void vpn::send_connect_request (connection *c) 939vpn::send_connect_request (connection *c)
841{ 940{
842 connection *r = find_router_for (c); 941 connection *r = find_router_for (c);
843 942
844 if (r) 943 if (r)
845 { 944 {

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines