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.39 by pcg, Sat Nov 10 05:14:22 2007 UTC vs.
Revision 1.47 by pcg, Thu Aug 7 17:54:27 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-2005 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>
46 56
47vpn network; // THE vpn (bad design...) 57vpn network; // THE vpn (bad design...)
48 58
49///////////////////////////////////////////////////////////////////////////// 59/////////////////////////////////////////////////////////////////////////////
50 60
61static void inline
62set_tos (int fd, int &tos_prev, int tos)
63{
64#if defined(SOL_IP) && defined(IP_TOS)
65 if (tos_prev == tos)
66 return;
67
68 tos_prev = tos;
69 setsockopt (fd, SOL_IP, IP_TOS, &tos, sizeof tos);
70#endif
71}
72
51void 73void
52vpn::script_init_env () 74vpn::script_init_env ()
53{ 75{
54 // the tunnel device mtu should be the physical mtu - overhead 76 // the tunnel device mtu should be the physical mtu - overhead
55 // the tricky part is rounding to the cipher key blocksize 77 // the tricky part is rounding to the cipher key blocksize
75 snprintf (ext, 16, "_%d", (*c)->conf->id); 97 snprintf (ext, 16, "_%d", (*c)->conf->id);
76 (*c)->script_init_env (ext); 98 (*c)->script_init_env (ext);
77 } 99 }
78} 100}
79 101
102inline const char *
80const char *vpn::script_if_init () 103vpn::script_if_init ()
81{ 104{
82 script_init_env (); 105 script_init_env ();
83 106
84 return tap->if_up (); 107 return tap->if_up ();
85} 108}
86 109
110inline const char *
87const char *vpn::script_if_up () 111vpn::script_if_up ()
88{ 112{
89 script_init_env (); 113 script_init_env ();
90 114
91 char *filename; 115 char *filename;
92 asprintf (&filename, 116 asprintf (&filename,
98} 122}
99 123
100int 124int
101vpn::setup () 125vpn::setup ()
102{ 126{
127 ipv4_tos = -1;
103 ipv4_fd = -1; 128 ipv4_fd = -1;
104 129
105 if (THISNODE->protocols & PROT_IPv4 && ::conf.ip_proto) 130 if (THISNODE->protocols & PROT_IPv4 && ::conf.ip_proto)
106 { 131 {
107 ipv4_fd = socket (PF_INET, SOCK_RAW, ::conf.ip_proto); 132 ipv4_fd = socket (PF_INET, SOCK_RAW, ::conf.ip_proto);
108 133
131 } 156 }
132 157
133 ipv4_ev_watcher.start (ipv4_fd, EV_READ); 158 ipv4_ev_watcher.start (ipv4_fd, EV_READ);
134 } 159 }
135 160
161 udpv4_tos = -1;
136 udpv4_fd = -1; 162 udpv4_fd = -1;
137 163
138 if (THISNODE->protocols & PROT_UDPv4 && THISNODE->udp_port) 164 if (THISNODE->protocols & PROT_UDPv4 && THISNODE->udp_port)
139 { 165 {
140 udpv4_fd = socket (PF_INET, SOCK_DGRAM, IPPROTO_UDP); 166 udpv4_fd = socket (PF_INET, SOCK_DGRAM, IPPROTO_UDP);
141 167
170 } 196 }
171 197
172 udpv4_ev_watcher.start (udpv4_fd, EV_READ); 198 udpv4_ev_watcher.start (udpv4_fd, EV_READ);
173 } 199 }
174 200
201 icmpv4_tos = -1;
175 icmpv4_fd = -1; 202 icmpv4_fd = -1;
176 203
177#if ENABLE_ICMP 204#if ENABLE_ICMP
178 if (THISNODE->protocols & PROT_ICMPv4) 205 if (THISNODE->protocols & PROT_ICMPv4)
179 { 206 {
180 icmpv4_fd = socket (PF_INET, SOCK_RAW, IPPROTO_ICMP); 207 icmpv4_fd = socket (PF_INET, SOCK_RAW, IPPROTO_ICMP);
252 } 279 }
253 280
254 tcpv4_ev_watcher.start (tcpv4_fd, EV_READ); 281 tcpv4_ev_watcher.start (tcpv4_fd, EV_READ);
255 } 282 }
256#endif 283#endif
284
285 dnsv4_tos = -1;
286 dnsv4_fd = -1;
257 287
258#if ENABLE_DNS 288#if ENABLE_DNS
259 if (THISNODE->protocols & PROT_DNSv4) 289 if (THISNODE->protocols & PROT_DNSv4)
260 { 290 {
261 dns_forwarder.set (::conf.dns_forw_host, ::conf.dns_forw_port, PROT_DNSv4); 291 dns_forwarder.set (::conf.dns_forw_host, ::conf.dns_forw_port, PROT_DNSv4);
311 exit (EXIT_FAILURE); 341 exit (EXIT_FAILURE);
312 } 342 }
313 343
314 fcntl (tap->fd, F_SETFD, FD_CLOEXEC); 344 fcntl (tap->fd, F_SETFD, FD_CLOEXEC);
315 345
346 run_script_cb cb;
347 cb.set<vpn, &vpn::script_if_init> (this);
348
316 if (tap->if_up () && 349 if (tap->if_up () &&
317 !run_script (run_script_cb (this, &vpn::script_if_init), true)) 350 !run_script (cb, true))
318 { 351 {
319 slog (L_ERR, _("interface initialization command '%s' failed, exiting."), 352 slog (L_ERR, _("interface initialization command '%s' failed, exiting."),
320 tap->if_up ()); 353 tap->if_up ());
321 exit (EXIT_FAILURE); 354 exit (EXIT_FAILURE);
322 } 355 }
323 356
324 if (!run_script (run_script_cb (this, &vpn::script_if_up), true)) 357 cb.set<vpn, &vpn::script_if_up> (this);
358 if (!run_script (cb, true))
325 { 359 {
326 slog (L_ERR, _("if-up command execution failed, exiting.")); 360 slog (L_ERR, _("if-up command execution failed, exiting."));
327 exit (EXIT_FAILURE); 361 exit (EXIT_FAILURE);
328 } 362 }
329 363
333} 367}
334 368
335bool 369bool
336vpn::send_ipv4_packet (vpn_packet *pkt, const sockinfo &si, int tos) 370vpn::send_ipv4_packet (vpn_packet *pkt, const sockinfo &si, int tos)
337{ 371{
338#if defined(SOL_IP) && defined(IP_TOS) 372 set_tos (ipv4_fd, ipv4_tos, tos);
339 setsockopt (ipv4_fd, SOL_IP, IP_TOS, &tos, sizeof tos);
340#endif
341 sendto (ipv4_fd, &((*pkt)[0]), pkt->len, 0, si.sav4 (), si.salenv4 ()); 373 sendto (ipv4_fd, &((*pkt)[0]), pkt->len, 0, si.sav4 (), si.salenv4 ());
342 374
343 return true; 375 return true;
344} 376}
345 377
368 400
369#if ENABLE_ICMP 401#if ENABLE_ICMP
370bool 402bool
371vpn::send_icmpv4_packet (vpn_packet *pkt, const sockinfo &si, int tos) 403vpn::send_icmpv4_packet (vpn_packet *pkt, const sockinfo &si, int tos)
372{ 404{
373#if defined(SOL_IP) && defined(IP_TOS)
374 setsockopt (icmpv4_fd, SOL_IP, IP_TOS, &tos, sizeof tos);
375#endif
376
377 pkt->unshift_hdr (4); 405 pkt->unshift_hdr (4);
378 406
379 icmp_header *hdr = (icmp_header *)&((*pkt)[0]); 407 icmp_header *hdr = (icmp_header *)&((*pkt)[0]);
380 hdr->type = ::conf.icmp_type; 408 hdr->type = ::conf.icmp_type;
381 hdr->code = 255; 409 hdr->code = 255;
382 hdr->checksum = 0; 410 hdr->checksum = 0;
383 hdr->checksum = ipv4_checksum ((u16 *)hdr, pkt->len); 411 hdr->checksum = ipv4_checksum ((u16 *)hdr, pkt->len);
384 412
413 set_tos (icmpv4_fd, icmpv4_tos, tos);
385 sendto (icmpv4_fd, &((*pkt)[0]), pkt->len, 0, si.sav4 (), si.salenv4 ()); 414 sendto (icmpv4_fd, &((*pkt)[0]), pkt->len, 0, si.sav4 (), si.salenv4 ());
386 415
387 return true; 416 return true;
388} 417}
389#endif 418#endif
390 419
391bool 420bool
392vpn::send_udpv4_packet (vpn_packet *pkt, const sockinfo &si, int tos) 421vpn::send_udpv4_packet (vpn_packet *pkt, const sockinfo &si, int tos)
393{ 422{
394#if defined(SOL_IP) && defined(IP_TOS) 423 set_tos (udpv4_fd, udpv4_tos, tos);
395 setsockopt (udpv4_fd, SOL_IP, IP_TOS, &tos, sizeof tos);
396#endif
397 sendto (udpv4_fd, &((*pkt)[0]), pkt->len, 0, si.sav4 (), si.salenv4 ()); 424 sendto (udpv4_fd, &((*pkt)[0]), pkt->len, 0, si.sav4 (), si.salenv4 ());
398 425
399 return true; 426 return true;
400} 427}
401 428
412 { 439 {
413 // broadcast, this is ugly, but due to the security policy 440 // broadcast, this is ugly, but due to the security policy
414 // we have to connect to all hosts... 441 // we have to connect to all hosts...
415 for (conns_vector::iterator c = conns.begin (); c != conns.end (); ++c) 442 for (conns_vector::iterator c = conns.begin (); c != conns.end (); ++c)
416 if ((*c)->conf != THISNODE) 443 if ((*c)->conf != THISNODE)
417 (*c)->inject_data_packet (pkt, true); 444 (*c)->inject_data_packet (pkt);
418 } 445 }
419} 446}
420 447
421void 448void
422vpn::recv_vpn_packet (vpn_packet *pkt, const sockinfo &rsi) 449vpn::recv_vpn_packet (vpn_packet *pkt, const sockinfo &rsi)
463{ 490{
464 switch (si.prot) 491 switch (si.prot)
465 { 492 {
466 case PROT_IPv4: 493 case PROT_IPv4:
467 return send_ipv4_packet (pkt, si, tos); 494 return send_ipv4_packet (pkt, si, tos);
495
468 case PROT_UDPv4: 496 case PROT_UDPv4:
469 return send_udpv4_packet (pkt, si, tos); 497 return send_udpv4_packet (pkt, si, tos);
498
470#if ENABLE_TCP 499#if ENABLE_TCP
471 case PROT_TCPv4: 500 case PROT_TCPv4:
472 return send_tcpv4_packet (pkt, si, tos); 501 return send_tcpv4_packet (pkt, si, tos);
473#endif 502#endif
474#if ENABLE_ICMP 503#if ENABLE_ICMP
477#endif 506#endif
478#if ENABLE_DNS 507#if ENABLE_DNS
479 case PROT_DNSv4: 508 case PROT_DNSv4:
480 return send_dnsv4_packet (pkt, si, tos); 509 return send_dnsv4_packet (pkt, si, tos);
481#endif 510#endif
482
483 default: 511 default:
484 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);
485 } 513 }
486 514
487 return false; 515 return false;
488} 516}
489 517
490void 518inline void
491vpn::ipv4_ev (ev::io &w, int revents) 519vpn::ipv4_ev (ev::io &w, int revents)
492{ 520{
493 if (revents & EV_READ) 521 if (revents & EV_READ)
494 { 522 {
495 vpn_packet *pkt = new vpn_packet; 523 vpn_packet *pkt = new vpn_packet;
526 exit (EXIT_FAILURE); 554 exit (EXIT_FAILURE);
527 } 555 }
528} 556}
529 557
530#if ENABLE_ICMP 558#if ENABLE_ICMP
531void 559inline void
532vpn::icmpv4_ev (ev::io &w, int revents) 560vpn::icmpv4_ev (ev::io &w, int revents)
533{ 561{
534 if (revents & EV_READ) 562 if (revents & EV_READ)
535 { 563 {
536 vpn_packet *pkt = new vpn_packet; 564 vpn_packet *pkt = new vpn_packet;
574 exit (EXIT_FAILURE); 602 exit (EXIT_FAILURE);
575 } 603 }
576} 604}
577#endif 605#endif
578 606
579void 607inline void
580vpn::udpv4_ev (ev::io &w, int revents) 608vpn::udpv4_ev (ev::io &w, int revents)
581{ 609{
582 if (revents & EV_READ) 610 if (revents & EV_READ)
583 { 611 {
584 vpn_packet *pkt = new vpn_packet; 612 vpn_packet *pkt = new vpn_packet;
611 revents); 639 revents);
612 exit (EXIT_FAILURE); 640 exit (EXIT_FAILURE);
613 } 641 }
614} 642}
615 643
616void 644inline void
617vpn::tap_ev (ev::io &w, int revents) 645vpn::tap_ev (ev::io &w, int revents)
618{ 646{
619 if (revents & EV_READ) 647 if (revents & EV_READ)
620 { 648 {
621 /* process data */ 649 /* process data */
653 } 681 }
654 else 682 else
655 abort (); 683 abort ();
656} 684}
657 685
658void 686inline void
659vpn::event_cb (ev::timer &w, int) 687vpn::event_cb (ev::timer &w, int)
660{ 688{
661 if (events) 689 if (events)
662 { 690 {
663 if (events & EVENT_SHUTDOWN) 691 if (events & EVENT_SHUTDOWN)
755} 783}
756 784
757void 785void
758vpn::dump_status () 786vpn::dump_status ()
759{ 787{
760 slog (L_NOTICE, _("BEGIN status dump (%ld)"), (long)ev::ev_now ()); 788 slog (L_NOTICE, _("BEGIN status dump (%ld)"), (long)ev_now ());
761 789
762 for (conns_vector::iterator c = conns.begin (); c != conns.end (); ++c) 790 for (conns_vector::iterator c = conns.begin (); c != conns.end (); ++c)
763 (*c)->dump_status (); 791 (*c)->dump_status ();
764 792
765 slog (L_NOTICE, _("END status dump")); 793 slog (L_NOTICE, _("END status dump"));
766} 794}
767 795
768vpn::vpn (void) 796vpn::vpn (void)
797{
769: event (this, &vpn::event_cb) 798 event .set<vpn, &vpn::event_cb > (this);
770, udpv4_ev_watcher (this, &vpn::udpv4_ev) 799 udpv4_ev_watcher .set<vpn, &vpn::udpv4_ev > (this);
771, ipv4_ev_watcher (this, &vpn::ipv4_ev) 800 ipv4_ev_watcher .set<vpn, &vpn::ipv4_ev > (this);
772#if ENABLE_TCP 801#if ENABLE_TCP
773, tcpv4_ev_watcher (this, &vpn::tcpv4_ev) 802 tcpv4_ev_watcher .set<vpn, &vpn::tcpv4_ev > (this);
774#endif 803#endif
775#if ENABLE_ICMP 804#if ENABLE_ICMP
776, icmpv4_ev_watcher(this, &vpn::icmpv4_ev) 805 icmpv4_ev_watcher.set<vpn, &vpn::icmpv4_ev> (this);
777#endif 806#endif
778#if ENABLE_DNS 807#if ENABLE_DNS
779, dnsv4_ev_watcher (this, &vpn::dnsv4_ev) 808 dnsv4_ev_watcher .set<vpn, &vpn::dnsv4_ev > (this);
780#endif 809#endif
781, tap_ev_watcher (this, &vpn::tap_ev) 810 tap_ev_watcher .set<vpn, &vpn::tap_ev > (this);
782{
783} 811}
784 812
785vpn::~vpn () 813vpn::~vpn ()
786{ 814{
787} 815}

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines