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.9 by pcg, Tue Apr 8 02:00:54 2003 UTC vs.
Revision 1.13 by pcg, Sun Apr 13 16:53:36 2003 UTC

29#include <sys/poll.h> 29#include <sys/poll.h>
30#include <sys/wait.h> 30#include <sys/wait.h>
31#include <errno.h> 31#include <errno.h>
32#include <time.h> 32#include <time.h>
33#include <unistd.h> 33#include <unistd.h>
34#include <fcntl.h>
34#include <arpa/inet.h> 35#include <arpa/inet.h>
35#include <netinet/in.h> 36#include <netinet/in.h>
36#include <netinet/icmp.h> 37#include <netinet/ip_icmp.h>
37 38
38#include "pidfile.h" 39#include "pidfile.h"
39 40
40#include "connection.h" 41#include "connection.h"
41#include "util.h" 42#include "util.h"
81 ipv4_fd = socket (PF_INET, SOCK_RAW, ::conf.ip_proto); 82 ipv4_fd = socket (PF_INET, SOCK_RAW, ::conf.ip_proto);
82 83
83 if (ipv4_fd < 0) 84 if (ipv4_fd < 0)
84 return -1; 85 return -1;
85 86
87 fcntl (ipv4_fd, F_SETFL, O_NONBLOCK);
88
86#ifdef IP_MTU_DISCOVER 89#ifdef IP_MTU_DISCOVER
87 // this I really consider a linux bug. I am neither connected 90 // this I really consider a linux bug. I am neither connected
88 // nor do I fragment myself. Linux still sets DF and doesn't 91 // nor do I fragment myself. Linux still sets DF and doesn't
89 // fragment for me sometimes. 92 // fragment for me sometimes.
90 { 93 {
111 udpv4_fd = socket (PF_INET, SOCK_DGRAM, IPPROTO_UDP); 114 udpv4_fd = socket (PF_INET, SOCK_DGRAM, IPPROTO_UDP);
112 115
113 if (udpv4_fd < 0) 116 if (udpv4_fd < 0)
114 return -1; 117 return -1;
115 118
119 fcntl (udpv4_fd, F_SETFL, O_NONBLOCK);
120
116 // standard daemon practise... 121 // standard daemon practise...
117 { 122 {
118 int oval = 1; 123 int oval = 1;
119 setsockopt (udpv4_fd, SOL_SOCKET, SO_REUSEADDR, &oval, sizeof oval); 124 setsockopt (udpv4_fd, SOL_SOCKET, SO_REUSEADDR, &oval, sizeof oval);
120 } 125 }
148 icmpv4_fd = socket (PF_INET, SOCK_RAW, IPPROTO_ICMP); 153 icmpv4_fd = socket (PF_INET, SOCK_RAW, IPPROTO_ICMP);
149 154
150 if (icmpv4_fd < 0) 155 if (icmpv4_fd < 0)
151 return -1; 156 return -1;
152 157
158 fcntl (icmpv4_fd, F_SETFL, O_NONBLOCK);
159
153#ifdef ICMP_FILTER 160#ifdef ICMP_FILTER
154 { 161 {
155 icmp_filter oval; 162 icmp_filter oval;
156 oval.data = 0xffffffff; 163 oval.data = 0xffffffff;
157 if (::conf.icmp_type < 32) 164 if (::conf.icmp_type < 32)
191 tcpv4_fd = socket (PF_INET, SOCK_STREAM, IPPROTO_TCP); 198 tcpv4_fd = socket (PF_INET, SOCK_STREAM, IPPROTO_TCP);
192 199
193 if (tcpv4_fd < 0) 200 if (tcpv4_fd < 0)
194 return -1; 201 return -1;
195 202
203 fcntl (tcpv4_fd, F_SETFL, O_NONBLOCK);
204
196 // standard daemon practise... 205 // standard daemon practise...
197 { 206 {
198 int oval = 1; 207 int oval = 1;
199 setsockopt (tcpv4_fd, SOL_SOCKET, SO_REUSEADDR, &oval, sizeof oval); 208 setsockopt (tcpv4_fd, SOL_SOCKET, SO_REUSEADDR, &oval, sizeof oval);
200 } 209 }
291 sum += (sum >> 16); // carry 300 sum += (sum >> 16); // carry
292 301
293 return ~sum; 302 return ~sum;
294} 303}
295 304
305#if ENABLE_ICMP
296bool 306bool
297vpn::send_icmpv4_packet (vpn_packet *pkt, const sockinfo &si, int tos) 307vpn::send_icmpv4_packet (vpn_packet *pkt, const sockinfo &si, int tos)
298{ 308{
299 setsockopt (icmpv4_fd, SOL_IP, IP_TOS, &tos, sizeof tos); 309 setsockopt (icmpv4_fd, SOL_IP, IP_TOS, &tos, sizeof tos);
300 310
308 318
309 sendto (icmpv4_fd, &((*pkt)[0]), pkt->len, 0, si.sav4 (), si.salenv4 ()); 319 sendto (icmpv4_fd, &((*pkt)[0]), pkt->len, 0, si.sav4 (), si.salenv4 ());
310 320
311 return true; 321 return true;
312} 322}
323#endif
313 324
314bool 325bool
315vpn::send_udpv4_packet (vpn_packet *pkt, const sockinfo &si, int tos) 326vpn::send_udpv4_packet (vpn_packet *pkt, const sockinfo &si, int tos)
316{ 327{
317 setsockopt (udpv4_fd, SOL_IP, IP_TOS, &tos, sizeof tos); 328 setsockopt (udpv4_fd, SOL_IP, IP_TOS, &tos, sizeof tos);
339 (const char *)rsi, pkt->typ (), pkt->src (), pkt->dst ()); 350 (const char *)rsi, pkt->typ (), pkt->src (), pkt->dst ());
340 else 351 else
341 { 352 {
342 connection *c = conns[src - 1]; 353 connection *c = conns[src - 1];
343 354
344 if (dst == 0 && !THISNODE->routerprio) 355 if (dst == 0)
345 slog (L_WARN, _("%s(%s): received broadcast, but we are no router"), 356 slog (L_WARN, _("%s(%s): received broadcast (protocol violation)"),
346 c->conf->nodename, (const char *)rsi); 357 c->conf->nodename, (const char *)rsi);
347 else if (dst != 0 && dst != THISNODE->id) 358 else if (dst != 0 && dst != THISNODE->id)
348 { 359 {
349 if (THISNODE->routerprio) 360 if (THISNODE->routerprio)
350 // the tos setting gets lost here. who cares. 361 // the tos setting gets lost here. who cares.
405 revents); 416 revents);
406 exit (1); 417 exit (1);
407 } 418 }
408} 419}
409 420
421#if ENABLE_ICMP
410void 422void
411vpn::icmpv4_ev (io_watcher &w, short revents) 423vpn::icmpv4_ev (io_watcher &w, short revents)
412{ 424{
413 if (revents & (POLLIN | POLLERR)) 425 if (revents & (POLLIN | POLLERR))
414 { 426 {
457 _("FATAL: unknown revents %08x in socket, terminating\n"), 469 _("FATAL: unknown revents %08x in socket, terminating\n"),
458 revents); 470 revents);
459 exit (1); 471 exit (1);
460 } 472 }
461} 473}
474#endif
462 475
463void 476void
464vpn::udpv4_ev (io_watcher &w, short revents) 477vpn::udpv4_ev (io_watcher &w, short revents)
465{ 478{
466 if (revents & (POLLIN | POLLERR)) 479 if (revents & (POLLIN | POLLERR))
538 if (dst != THISNODE->id) 551 if (dst != THISNODE->id)
539 conns[dst - 1]->inject_data_packet (pkt); 552 conns[dst - 1]->inject_data_packet (pkt);
540 } 553 }
541 else 554 else
542 { 555 {
543 // broadcast, first check router, then self, then english 556 // broadcast, this is ugly, but due to the security policy
544 connection *router = find_router (); 557 // we have to connect to all hosts...
545
546 if (router)
547 router->inject_data_packet (pkt, true);
548 else
549 for (conns_vector::iterator c = conns.begin (); c != conns.end (); ++c) 558 for (conns_vector::iterator c = conns.begin (); c != conns.end (); ++c)
550 if ((*c)->conf != THISNODE) 559 if ((*c)->conf != THISNODE)
551 (*c)->inject_data_packet (pkt); 560 (*c)->inject_data_packet (pkt);
552 } 561 }
553 } 562 }
554 563
555 delete pkt; 564 delete pkt;
556 } 565 }
623 } 632 }
624} 633}
625 634
626connection *vpn::find_router () 635connection *vpn::find_router ()
627{ 636{
628 u32 prio = 0; 637 u32 prio = 1;
629 connection *router = 0; 638 connection *router = 0;
630 639
631 for (conns_vector::iterator i = conns.begin (); i != conns.end (); ++i) 640 for (conns_vector::iterator i = conns.begin (); i != conns.end (); ++i)
632 { 641 {
633 connection *c = *i; 642 connection *c = *i;
634 643
635 if (c->conf->routerprio > prio 644 if (c->conf->routerprio > prio
636 && c->connectmode == conf_node::C_ALWAYS 645 && c->connectmode == conf_node::C_ALWAYS // so we don't drop the connection if in use
637 && c->conf != THISNODE
638 && c->ictx && c->octx) 646 && c->ictx && c->octx
647 && c->conf != THISNODE) // redundant, since ictx==octx==0 always on thisnode
639 { 648 {
640 prio = c->conf->routerprio; 649 prio = c->conf->routerprio;
641 router = c; 650 router = c;
642 } 651 }
643 } 652 }
652 if (c) 661 if (c)
653 c->send_connect_request (id); 662 c->send_connect_request (id);
654 else 663 else
655 // no router found, aggressively connect to all routers 664 // no router found, aggressively connect to all routers
656 for (conns_vector::iterator i = conns.begin (); i != conns.end (); ++i) 665 for (conns_vector::iterator i = conns.begin (); i != conns.end (); ++i)
657 if ((*i)->conf->routerprio) 666 if ((*i)->conf->routerprio && (*i)->conf != THISNODE)
658 (*i)->establish_connection (); 667 (*i)->establish_connection ();
659} 668}
660 669
661void 670void
662connection::dump_status () 671connection::dump_status ()

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines