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.37 by pcg, Tue Apr 19 03:47:32 2005 UTC vs.
Revision 1.48 by pcg, Sat Aug 9 18:30:55 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. 59 Temple Place, Suite 330, Boston, MA 02111-1307 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
128 { 153 {
129 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"), (const char *)si, strerror (errno));
130 exit (EXIT_FAILURE); 155 exit (EXIT_FAILURE);
131 } 156 }
132 157
133 ipv4_ev_watcher.start (ipv4_fd, EVENT_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
167 { 193 {
168 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"), (const char *)si, strerror (errno));
169 exit (EXIT_FAILURE); 195 exit (EXIT_FAILURE);
170 } 196 }
171 197
172 udpv4_ev_watcher.start (udpv4_fd, EVENT_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);
212 { 239 {
213 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"), (const char *)si, strerror (errno));
214 exit (EXIT_FAILURE); 241 exit (EXIT_FAILURE);
215 } 242 }
216 243
217 icmpv4_ev_watcher.start (icmpv4_fd, EVENT_READ); 244 icmpv4_ev_watcher.start (icmpv4_fd, EV_READ);
218 } 245 }
219#endif 246#endif
220 247
221 tcpv4_fd = -1; 248 tcpv4_fd = -1;
222 249
249 { 276 {
250 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"), (const char *)si, strerror (errno));
251 exit (EXIT_FAILURE); 278 exit (EXIT_FAILURE);
252 } 279 }
253 280
254 tcpv4_ev_watcher.start (tcpv4_fd, EVENT_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);
292 { 322 {
293 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"), (const char *)si, strerror (errno));
294 exit (EXIT_FAILURE); 324 exit (EXIT_FAILURE);
295 } 325 }
296 326
297 dnsv4_ev_watcher.start (dnsv4_fd, EVENT_READ); 327 dnsv4_ev_watcher.start (dnsv4_fd, EV_READ);
298 } 328 }
299#endif 329#endif
300 330
301 ///////////////////////////////////////////////////////////////////////////// 331 /////////////////////////////////////////////////////////////////////////////
302 332
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
330 tap_ev_watcher.start (tap->fd, EVENT_READ); 364 tap_ev_watcher.start (tap->fd, EV_READ);
331 365
332 return 0; 366 return 0;
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 (io_watcher &w, short revents) 519vpn::ipv4_ev (ev::io &w, int revents)
492{ 520{
493 if (revents & EVENT_READ) 521 if (revents & EV_READ)
494 { 522 {
495 vpn_packet *pkt = new vpn_packet; 523 vpn_packet *pkt = new vpn_packet;
496 struct sockaddr_in sa; 524 struct sockaddr_in sa;
497 socklen_t sa_len = sizeof (sa); 525 socklen_t sa_len = sizeof (sa);
498 int len; 526 int len;
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 (io_watcher &w, short revents) 560vpn::icmpv4_ev (ev::io &w, int revents)
533{ 561{
534 if (revents & EVENT_READ) 562 if (revents & EV_READ)
535 { 563 {
536 vpn_packet *pkt = new vpn_packet; 564 vpn_packet *pkt = new vpn_packet;
537 struct sockaddr_in sa; 565 struct sockaddr_in sa;
538 socklen_t sa_len = sizeof (sa); 566 socklen_t sa_len = sizeof (sa);
539 int len; 567 int len;
574 exit (EXIT_FAILURE); 602 exit (EXIT_FAILURE);
575 } 603 }
576} 604}
577#endif 605#endif
578 606
579void 607inline void
580vpn::udpv4_ev (io_watcher &w, short revents) 608vpn::udpv4_ev (ev::io &w, int revents)
581{ 609{
582 if (revents & EVENT_READ) 610 if (revents & EV_READ)
583 { 611 {
584 vpn_packet *pkt = new vpn_packet; 612 vpn_packet *pkt = new vpn_packet;
585 struct sockaddr_in sa; 613 struct sockaddr_in sa;
586 socklen_t sa_len = sizeof (sa); 614 socklen_t sa_len = sizeof (sa);
587 int len; 615 int len;
611 revents); 639 revents);
612 exit (EXIT_FAILURE); 640 exit (EXIT_FAILURE);
613 } 641 }
614} 642}
615 643
616void 644inline void
617vpn::tap_ev (io_watcher &w, short revents) 645vpn::tap_ev (ev::io &w, int revents)
618{ 646{
619 if (revents & EVENT_READ) 647 if (revents & EV_READ)
620 { 648 {
621 /* process data */ 649 /* process data */
622 tap_packet *pkt; 650 tap_packet *pkt;
623 651
624 pkt = tap->recv (); 652 pkt = tap->recv ();
653 } 681 }
654 else 682 else
655 abort (); 683 abort ();
656} 684}
657 685
658void 686inline void
659vpn::event_cb (time_watcher &w) 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)
664 { 692 {
748 slog (L_NOTICE, _("node %s (id %d)"), conf->nodename, conf->id); 776 slog (L_NOTICE, _("node %s (id %d)"), conf->nodename, conf->id);
749 slog (L_NOTICE, _(" connectmode %d (%d) / sockaddr %s / minor %d"), 777 slog (L_NOTICE, _(" connectmode %d (%d) / sockaddr %s / minor %d"),
750 connectmode, conf->connectmode, (const char *)si, (int)prot_minor); 778 connectmode, conf->connectmode, (const char *)si, (int)prot_minor);
751 slog (L_NOTICE, _(" ictx/octx %08lx/%08lx / oseqno %d / retry_cnt %d"), 779 slog (L_NOTICE, _(" ictx/octx %08lx/%08lx / oseqno %d / retry_cnt %d"),
752 (long)ictx, (long)octx, (int)oseqno, (int)retry_cnt); 780 (long)ictx, (long)octx, (int)oseqno, (int)retry_cnt);
753 slog (L_NOTICE, _(" establish_conn %ld / rekey %ld / keepalive %ld"),
754 (long)(establish_connection.at), (long)(rekey.at), (long)(keepalive.at));
755} 781}
756 782
757void 783void
758vpn::dump_status () 784vpn::dump_status ()
759{ 785{
760 slog (L_NOTICE, _("BEGIN status dump (%ld)"), (long)NOW); 786 slog (L_NOTICE, _("BEGIN status dump (%ld)"), (long)ev_now ());
761 787
762 for (conns_vector::iterator c = conns.begin (); c != conns.end (); ++c) 788 for (conns_vector::iterator c = conns.begin (); c != conns.end (); ++c)
763 (*c)->dump_status (); 789 (*c)->dump_status ();
764 790
765 slog (L_NOTICE, _("END status dump")); 791 slog (L_NOTICE, _("END status dump"));
766} 792}
767 793
768vpn::vpn (void) 794vpn::vpn (void)
795{
769: event (this, &vpn::event_cb) 796 event .set<vpn, &vpn::event_cb > (this);
770, udpv4_ev_watcher (this, &vpn::udpv4_ev) 797 udpv4_ev_watcher .set<vpn, &vpn::udpv4_ev > (this);
771, ipv4_ev_watcher (this, &vpn::ipv4_ev) 798 ipv4_ev_watcher .set<vpn, &vpn::ipv4_ev > (this);
772#if ENABLE_TCP 799#if ENABLE_TCP
773, tcpv4_ev_watcher (this, &vpn::tcpv4_ev) 800 tcpv4_ev_watcher .set<vpn, &vpn::tcpv4_ev > (this);
774#endif 801#endif
775#if ENABLE_ICMP 802#if ENABLE_ICMP
776, icmpv4_ev_watcher(this, &vpn::icmpv4_ev) 803 icmpv4_ev_watcher.set<vpn, &vpn::icmpv4_ev> (this);
777#endif 804#endif
778#if ENABLE_DNS 805#if ENABLE_DNS
779, dnsv4_ev_watcher (this, &vpn::dnsv4_ev) 806 dnsv4_ev_watcher .set<vpn, &vpn::dnsv4_ev > (this);
780#endif 807#endif
781, tap_ev_watcher (this, &vpn::tap_ev) 808 tap_ev_watcher .set<vpn, &vpn::tap_ev > (this);
782{
783} 809}
784 810
785vpn::~vpn () 811vpn::~vpn ()
786{ 812{
787} 813}

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines