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.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-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
124 149
125 sockinfo si (THISNODE, PROT_IPv4); 150 sockinfo si (THISNODE, PROT_IPv4);
126 151
127 if (bind (ipv4_fd, si.sav4 (), si.salenv4 ())) 152 if (bind (ipv4_fd, si.sav4 (), si.salenv4 ()))
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, exiting."), (const char *)si, strerror (errno));
130 exit (EXIT_FAILURE); 155 exit (EXIT_FAILURE);
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
163 189
164 sockinfo si (THISNODE, PROT_UDPv4); 190 sockinfo si (THISNODE, PROT_UDPv4);
165 191
166 if (bind (udpv4_fd, si.sav4 (), si.salenv4 ())) 192 if (bind (udpv4_fd, si.sav4 (), si.salenv4 ()))
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, exiting."), (const char *)si, strerror (errno));
169 exit (EXIT_FAILURE); 195 exit (EXIT_FAILURE);
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);
208 235
209 sockinfo si (THISNODE, PROT_ICMPv4); 236 sockinfo si (THISNODE, PROT_ICMPv4);
210 237
211 if (bind (icmpv4_fd, si.sav4 (), si.salenv4 ())) 238 if (bind (icmpv4_fd, si.sav4 (), si.salenv4 ()))
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, exiting."), (const char *)si, strerror (errno));
214 exit (EXIT_FAILURE); 241 exit (EXIT_FAILURE);
215 } 242 }
216 243
217 icmpv4_ev_watcher.start (icmpv4_fd, EV_READ); 244 icmpv4_ev_watcher.start (icmpv4_fd, EV_READ);
218 } 245 }
239 266
240 sockinfo si (THISNODE, PROT_TCPv4); 267 sockinfo si (THISNODE, PROT_TCPv4);
241 268
242 if (bind (tcpv4_fd, si.sav4 (), si.salenv4 ())) 269 if (bind (tcpv4_fd, si.sav4 (), si.salenv4 ()))
243 { 270 {
244 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));
245 exit (EXIT_FAILURE); 272 exit (EXIT_FAILURE);
246 } 273 }
247 274
248 if (listen (tcpv4_fd, 5)) 275 if (listen (tcpv4_fd, 5))
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, exiting."), (const char *)si, strerror (errno));
251 exit (EXIT_FAILURE); 278 exit (EXIT_FAILURE);
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);
288 THISNODE->dns_hostname ? THISNODE->dns_port : 0, 318 THISNODE->dns_hostname ? THISNODE->dns_port : 0,
289 PROT_DNSv4); 319 PROT_DNSv4);
290 320
291 if (bind (dnsv4_fd, si.sav4 (), si.salenv4 ())) 321 if (bind (dnsv4_fd, si.sav4 (), si.salenv4 ()))
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, exiting."), (const char *)si, strerror (errno));
294 exit (EXIT_FAILURE); 324 exit (EXIT_FAILURE);
295 } 325 }
296 326
297 dnsv4_ev_watcher.start (dnsv4_fd, EV_READ); 327 dnsv4_ev_watcher.start (dnsv4_fd, EV_READ);
298 } 328 }
305 ///////////////////////////////////////////////////////////////////////////// 335 /////////////////////////////////////////////////////////////////////////////
306 336
307 tap = new tap_device (); 337 tap = new tap_device ();
308 if (!tap) //D this, of course, never catches 338 if (!tap) //D this, of course, never catches
309 { 339 {
310 slog (L_ERR, _("cannot create network interface '%s'"), conf.ifname); 340 slog (L_ERR, _("cannot create network interface '%s', exiting."), conf.ifname);
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)
423{ 450{
424 unsigned int src = pkt->src (); 451 unsigned int src = pkt->src ();
425 unsigned int dst = pkt->dst (); 452 unsigned int dst = pkt->dst ();
426 453
427 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."),
428 (const char *)rsi, pkt->typ (), pkt->src (), pkt->dst (), pkt->len); 455 (const char *)rsi, pkt->typ (), pkt->src (), pkt->dst (), pkt->len);
429 456
430 if (src == 0 || src > conns.size () 457 if (src == 0 || src > conns.size ()
431 || dst > conns.size () 458 || dst > conns.size ()
432 || pkt->typ () >= vpn_packet::PT_MAX) 459 || pkt->typ () >= vpn_packet::PT_MAX)
433 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)."),
434 (const char *)rsi, pkt->typ (), pkt->src (), pkt->dst ()); 461 (const char *)rsi, pkt->typ (), pkt->src (), pkt->dst ());
435 else if (dst > conns.size ()) 462 else if (dst > conns.size ())
436 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)."),
437 (const char *)rsi, pkt->typ (), pkt->src (), pkt->dst ()); 464 (const char *)rsi, pkt->typ (), pkt->src (), pkt->dst ());
438 else 465 else
439 { 466 {
440 connection *c = conns[src - 1]; 467 connection *c = conns[src - 1];
441 468
442 if (dst == 0) 469 if (dst == 0)
443 slog (L_WARN, _("%s(%s): received broadcast (protocol violation)"), 470 slog (L_WARN, _("%s(%s): received broadcast (protocol violation)."),
444 c->conf->nodename, (const char *)rsi); 471 c->conf->nodename, (const char *)rsi);
445 else if (dst != THISNODE->id) 472 else if (dst != THISNODE->id)
446 { 473 {
447 if (THISNODE->routerprio) 474 if (THISNODE->routerprio)
448 // the tos setting gets lost here. who cares. 475 // the tos setting gets lost here. who cares.
449 conns[dst - 1]->inject_vpn_packet (pkt); 476 conns[dst - 1]->inject_vpn_packet (pkt);
450 else 477 else
451 slog (L_WARN, 478 slog (L_WARN,
452 _("%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?)."),
453 c->conf->nodename, (const char *)rsi, 480 c->conf->nodename, (const char *)rsi,
454 conns[dst - 1]->conf->nodename); 481 conns[dst - 1]->conf->nodename);
455 } 482 }
456 else 483 else
457 c->recv_vpn_packet (pkt, rsi); 484 c->recv_vpn_packet (pkt, 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;
511 recv_vpn_packet (pkt, si); 539 recv_vpn_packet (pkt, si);
512 } 540 }
513 else 541 else
514 { 542 {
515 // probably ECONNRESET or somesuch 543 // probably ECONNRESET or somesuch
516 slog (L_DEBUG, _("%s: %s"), (const char *)si, strerror (errno)); 544 slog (L_DEBUG, _("%s: %s."), (const char *)si, strerror (errno));
517 } 545 }
518 546
519 delete pkt; 547 delete pkt;
520 } 548 }
521 else 549 else
522 { 550 {
523 slog (L_ERR, 551 slog (L_ERR,
524 _("FATAL: unknown revents %08x in socket, terminating\n"), 552 _("FATAL: unknown revents %08x in socket, exiting.\n"),
525 revents); 553 revents);
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;
559 } 587 }
560 } 588 }
561 else 589 else
562 { 590 {
563 // probably ECONNRESET or somesuch 591 // probably ECONNRESET or somesuch
564 slog (L_DEBUG, _("%s: %s"), (const char *)si, strerror (errno)); 592 slog (L_DEBUG, _("%s: %s."), (const char *)si, strerror (errno));
565 } 593 }
566 594
567 delete pkt; 595 delete pkt;
568 } 596 }
569 else 597 else
570 { 598 {
571 slog (L_ERR, 599 slog (L_ERR,
572 _("FATAL: unknown revents %08x in socket, terminating\n"), 600 _("FATAL: unknown revents %08x in socket, exiting.\n"),
573 revents); 601 revents);
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;
597 recv_vpn_packet (pkt, si); 625 recv_vpn_packet (pkt, si);
598 } 626 }
599 else 627 else
600 { 628 {
601 // probably ECONNRESET or somesuch 629 // probably ECONNRESET or somesuch
602 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));
603 } 631 }
604 632
605 delete pkt; 633 delete pkt;
606 } 634 }
607 else 635 else
608 { 636 {
609 slog (L_ERR, 637 slog (L_ERR,
610 _("FATAL: unknown revents %08x in socket, terminating\n"), 638 _("FATAL: unknown revents %08x in socket, exiting.\n"),
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)
664 { 692 {
665 slog (L_INFO, _("preparing shutdown...")); 693 slog (L_INFO, _("preparing shutdown..."));
666 694
667 shutdown_all (); 695 shutdown_all ();
668 remove_pid (conf.pidfilename); 696 remove_pid (conf.pidfilename);
669 slog (L_INFO, _("terminating")); 697 slog (L_INFO, _("exiting."));
670 exit (EXIT_SUCCESS); 698 exit (EXIT_SUCCESS);
671 } 699 }
672 700
673 if (events & EVENT_RECONNECT) 701 if (events & EVENT_RECONNECT)
674 { 702 {
675 slog (L_INFO, _("forced reconnect")); 703 slog (L_INFO, _("forced reconnect."));
676 704
677 reconnect_all (); 705 reconnect_all ();
678 } 706 }
679 707
680 events = 0; 708 events = 0;
705 conns.push_back (conn); 733 conns.push_back (conn);
706 conn->establish_connection (); 734 conn->establish_connection ();
707 } 735 }
708} 736}
709 737
710connection *vpn::find_router () 738bool vpn::can_direct (conf_node *src, conf_node *dst) const
711{ 739{
712 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{
713 connection *router = 0; 751 connection *router = 0;
714 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{
715 for (conns_vector::iterator i = conns.begin (); i != conns.end (); ++i) 808 for (conns_vector::iterator i = conns.begin (); i != conns.end (); ++i)
716 { 809 {
717 connection *c = *i; 810 connection *o = *i;
718 811
719 if (c->conf->routerprio > prio 812 if (!o->is_direct
720 && c->connectmode == conf_node::C_ALWAYS // so we don't drop the connection if in use 813 && o->si.valid ()
721 && c->ictx && c->octx 814 && c->si != o->si
722 && c->conf != THISNODE) // redundant, since ictx==octx==0 always on thisnode 815 && c == find_router_for (o))
723 {
724 prio = c->conf->routerprio;
725 router = c;
726 } 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 }
727 } 821 }
728
729 return router;
730} 822}
731 823
732void vpn::send_connect_request (int id) 824void vpn::send_connect_request (int id)
733{ 825{
734 connection *c = find_router (); 826 connection *c = find_router_for (conns[id]);
735 827
736 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);
737 c->send_connect_request (id); 832 c->send_connect_request (id);
833 }
738 else 834 else
739 // 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);
740 for (conns_vector::iterator i = conns.begin (); i != conns.end (); ++i)
741 if ((*i)->conf->routerprio && (*i)->conf != THISNODE)
742 (*i)->establish_connection ();
743} 836}
744 837
745void 838void
746connection::dump_status () 839connection::dump_status ()
747{ 840{
748 slog (L_NOTICE, _("node %s (id %d)"), conf->nodename, conf->id); 841 slog (L_NOTICE, _("node %s (id %d)"), conf->nodename, conf->id);
749 slog (L_NOTICE, _(" connectmode %d (%d) / sockaddr %s / minor %d"), 842 slog (L_NOTICE, _(" connectmode %d (%d) / sockaddr %s / minor %d"),
750 connectmode, conf->connectmode, (const char *)si, (int)prot_minor); 843 connectmode, conf->connectmode, (const char *)si, (int)prot_minor);
751 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"),
752 (long)ictx, (long)octx, (int)oseqno, (int)retry_cnt); 845 (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} 846}
756 847
757void 848void
758vpn::dump_status () 849vpn::dump_status ()
759{ 850{
760 slog (L_NOTICE, _("BEGIN status dump (%ld)"), (long)ev::ev_now ()); 851 slog (L_NOTICE, _("BEGIN status dump (%ld)"), (long)ev_now ());
761 852
762 for (conns_vector::iterator c = conns.begin (); c != conns.end (); ++c) 853 for (conns_vector::iterator c = conns.begin (); c != conns.end (); ++c)
763 (*c)->dump_status (); 854 (*c)->dump_status ();
764 855
765 slog (L_NOTICE, _("END status dump")); 856 slog (L_NOTICE, _("END status dump"));
766} 857}
767 858
768vpn::vpn (void) 859vpn::vpn (void)
860{
769: event (this, &vpn::event_cb) 861 event .set<vpn, &vpn::event_cb > (this);
770, udpv4_ev_watcher (this, &vpn::udpv4_ev) 862 udpv4_ev_watcher .set<vpn, &vpn::udpv4_ev > (this);
771, ipv4_ev_watcher (this, &vpn::ipv4_ev) 863 ipv4_ev_watcher .set<vpn, &vpn::ipv4_ev > (this);
772#if ENABLE_TCP 864#if ENABLE_TCP
773, tcpv4_ev_watcher (this, &vpn::tcpv4_ev) 865 tcpv4_ev_watcher .set<vpn, &vpn::tcpv4_ev > (this);
774#endif 866#endif
775#if ENABLE_ICMP 867#if ENABLE_ICMP
776, icmpv4_ev_watcher(this, &vpn::icmpv4_ev) 868 icmpv4_ev_watcher.set<vpn, &vpn::icmpv4_ev> (this);
777#endif 869#endif
778#if ENABLE_DNS 870#if ENABLE_DNS
779, dnsv4_ev_watcher (this, &vpn::dnsv4_ev) 871 dnsv4_ev_watcher .set<vpn, &vpn::dnsv4_ev > (this);
780#endif 872#endif
781, tap_ev_watcher (this, &vpn::tap_ev) 873 tap_ev_watcher .set<vpn, &vpn::tap_ev > (this);
782{
783} 874}
784 875
785vpn::~vpn () 876vpn::~vpn ()
786{ 877{
787} 878}

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines