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.1 by pcg, Wed Apr 2 03:25:17 2003 UTC vs.
Revision 1.4 by pcg, Fri Apr 4 05:26:45 2003 UTC

38 38
39#include "connection.h" 39#include "connection.h"
40#include "util.h" 40#include "util.h"
41#include "vpn.h" 41#include "vpn.h"
42 42
43#if ENABLE_TCP
44# include <map>
45# include <unistd.h>
46# include <fcntl.h>
47# include <sys/poll.h>
48#endif
49
43///////////////////////////////////////////////////////////////////////////// 50/////////////////////////////////////////////////////////////////////////////
44 51
45const char *vpn::script_if_up (int) 52const char *vpn::script_if_up ()
46{ 53{
47 // the tunnel device mtu should be the physical mtu - overhead 54 // the tunnel device mtu should be the physical mtu - overhead
48 // the tricky part is rounding to the cipher key blocksize 55 // the tricky part is rounding to the cipher key blocksize
49 int mtu = conf.mtu - ETH_OVERHEAD - VPE_OVERHEAD - MAX_OVERHEAD; 56 int mtu = conf.mtu - ETH_OVERHEAD - VPE_OVERHEAD - MAX_OVERHEAD;
50 mtu += ETH_OVERHEAD - 6 - 6; // now we have the data portion 57 mtu += ETH_OVERHEAD - 6 - 6; // now we have the data portion
71} 78}
72 79
73int 80int
74vpn::setup () 81vpn::setup ()
75{ 82{
76 sockinfo si;
77
78 si.set (THISNODE);
79
80 udpv4_fd = -1; 83 udpv4_fd = -1;
81 84
82 if (THISNODE->protocols & PROT_UDPv4) 85 if (THISNODE->protocols & PROT_UDPv4)
83 { 86 {
84 udpv4_fd = socket (PF_INET, SOCK_DGRAM, IPPROTO_UDP); 87 udpv4_fd = socket (PF_INET, SOCK_DGRAM, IPPROTO_UDP);
85 88
86 if (udpv4_fd < 0) 89 if (udpv4_fd < 0)
87 return -1; 90 return -1;
88 91
92 // standard daemon practise...
93 {
94 int oval = 1;
95 setsockopt (udpv4_fd, SOL_SOCKET, SO_REUSEADDR, &oval, sizeof oval);
96 }
97
98 sockinfo si (THISNODE, PROT_UDPv4);
99
89 if (bind (udpv4_fd, si.sav4 (), si.salenv4 ())) 100 if (bind (udpv4_fd, si.sav4 (), si.salenv4 ()))
90 { 101 {
91 slog (L_ERR, _("can't bind udpv4 to %s: %s"), (const char *)si, strerror (errno)); 102 slog (L_ERR, _("can't bind udpv4 on %s: %s"), (const char *)si, strerror (errno));
92 exit (1); 103 exit (1);
93 } 104 }
94 105
95#ifdef IP_MTU_DISCOVER 106#ifdef IP_MTU_DISCOVER
96 // this I really consider a linux bug. I am neither connected 107 // this I really consider a linux bug. I am neither connected
100 int oval = IP_PMTUDISC_DONT; 111 int oval = IP_PMTUDISC_DONT;
101 setsockopt (udpv4_fd, SOL_IP, IP_MTU_DISCOVER, &oval, sizeof oval); 112 setsockopt (udpv4_fd, SOL_IP, IP_MTU_DISCOVER, &oval, sizeof oval);
102 } 113 }
103#endif 114#endif
104 115
105 // standard daemon practise...
106 {
107 int oval = 1;
108 setsockopt (udpv4_fd, SOL_SOCKET, SO_REUSEADDR, &oval, sizeof oval);
109 }
110
111 udpv4_ev_watcher.start (udpv4_fd, POLLIN); 116 udpv4_ev_watcher.start (udpv4_fd, POLLIN);
112 } 117 }
113 118
114 ipv4_fd = -1; 119 ipv4_fd = -1;
115 if (THISNODE->protocols & PROT_IPv4) 120 if (THISNODE->protocols & PROT_IPv4)
117 ipv4_fd = socket (PF_INET, SOCK_RAW, ::conf.ip_proto); 122 ipv4_fd = socket (PF_INET, SOCK_RAW, ::conf.ip_proto);
118 123
119 if (ipv4_fd < 0) 124 if (ipv4_fd < 0)
120 return -1; 125 return -1;
121 126
127 sockinfo si (THISNODE, PROT_IPv4);
128
122 if (bind (ipv4_fd, si.sav4 (), si.salenv4 ())) 129 if (bind (ipv4_fd, si.sav4 (), si.salenv4 ()))
123 { 130 {
124 slog (L_ERR, _("can't bind ipv4 socket to %s: %s"), (const char *)si, strerror (errno)); 131 slog (L_ERR, _("can't bind ipv4 socket on %s: %s"), (const char *)si, strerror (errno));
125 exit (1); 132 exit (1);
126 } 133 }
127 134
128#ifdef IP_MTU_DISCOVER 135#ifdef IP_MTU_DISCOVER
129 // this I really consider a linux bug. I am neither connected 136 // this I really consider a linux bug. I am neither connected
135 } 142 }
136#endif 143#endif
137 144
138 ipv4_ev_watcher.start (ipv4_fd, POLLIN); 145 ipv4_ev_watcher.start (ipv4_fd, POLLIN);
139 } 146 }
147
148#if ENABLE_TCP
149 if (THISNODE->protocols & PROT_TCPv4)
150 {
151 tcpv4_fd = socket (PF_INET, SOCK_STREAM, IPPROTO_TCP);
152
153 if (tcpv4_fd < 0)
154 return -1;
155
156 // standard daemon practise...
157 {
158 int oval = 1;
159 setsockopt (tcpv4_fd, SOL_SOCKET, SO_REUSEADDR, &oval, sizeof oval);
160 }
161
162 sockinfo si (THISNODE, PROT_TCPv4);
163
164 if (bind (tcpv4_fd, si.sav4 (), si.salenv4 ()))
165 {
166 slog (L_ERR, _("can't bind tcpv4 on %s: %s"), (const char *)si, strerror (errno));
167 exit (1);
168 }
169
170 if (listen (tcpv4_fd, 5))
171 {
172 slog (L_ERR, _("can't listen tcpv4 on %s: %s"), (const char *)si, strerror (errno));
173 exit (1);
174 }
175
176 tcpv4_ev_watcher.start (tcpv4_fd, POLLIN);
177 }
178#endif
140 179
141 tap = new tap_device (); 180 tap = new tap_device ();
142 if (!tap) //D this, of course, never catches 181 if (!tap) //D this, of course, never catches
143 { 182 {
144 slog (L_ERR, _("cannot create network interface '%s'"), conf.ifname); 183 slog (L_ERR, _("cannot create network interface '%s'"), conf.ifname);
200 c->recv_vpn_packet (pkt, rsi); 239 c->recv_vpn_packet (pkt, rsi);
201 } 240 }
202} 241}
203 242
204void 243void
205vpn::udpv4_ev (short revents) 244vpn::udpv4_ev (io_watcher &w, short revents)
206{ 245{
207 if (revents & (POLLIN | POLLERR)) 246 if (revents & (POLLIN | POLLERR))
208 { 247 {
209 vpn_packet *pkt = new vpn_packet; 248 vpn_packet *pkt = new vpn_packet;
210 struct sockaddr_in sa; 249 struct sockaddr_in sa;
211 socklen_t sa_len = sizeof (sa); 250 socklen_t sa_len = sizeof (sa);
212 int len; 251 int len;
213 252
214 len = recvfrom (udpv4_fd, &((*pkt)[0]), MAXSIZE, 0, (sockaddr *)&sa, &sa_len); 253 len = recvfrom (w.p->fd, &((*pkt)[0]), MAXSIZE, 0, (sockaddr *)&sa, &sa_len);
215 254
216 sockinfo si(sa); 255 sockinfo si(sa);
217 256
218 if (len > 0) 257 if (len > 0)
219 { 258 {
243 exit (1); 282 exit (1);
244 } 283 }
245} 284}
246 285
247void 286void
248vpn::ipv4_ev (short revents) 287vpn::ipv4_ev (io_watcher &w, short revents)
249{ 288{
250 if (revents & (POLLIN | POLLERR)) 289 if (revents & (POLLIN | POLLERR))
251 { 290 {
252 vpn_packet *pkt = new vpn_packet; 291 vpn_packet *pkt = new vpn_packet;
253 struct sockaddr_in sa; 292 struct sockaddr_in sa;
254 socklen_t sa_len = sizeof (sa); 293 socklen_t sa_len = sizeof (sa);
255 int len; 294 int len;
256 295
257 len = recvfrom (ipv4_fd, &((*pkt)[0]), MAXSIZE, 0, (sockaddr *)&sa, &sa_len); 296 len = recvfrom (w.p->fd, &((*pkt)[0]), MAXSIZE, 0, (sockaddr *)&sa, &sa_len);
258 297
259 sockinfo si(sa, PROT_IPv4); 298 sockinfo si(sa, PROT_IPv4);
260 299
261 if (len > 0) 300 if (len > 0)
262 { 301 {
289 revents); 328 revents);
290 exit (1); 329 exit (1);
291 } 330 }
292} 331}
293 332
333#if ENABLE_TCP
334
335struct tcp_connection;
336
337struct lt_sockinfo
338{
339 bool operator()(const sockinfo *a, const sockinfo *b) const
340 {
341 return *a < *b;
342 }
343};
344
345struct tcp_si_map : public map<const sockinfo *, tcp_connection *, lt_sockinfo> {
346 void cleaner_cb (time_watcher &w); time_watcher cleaner;
347
348 tcp_si_map ()
349 : cleaner(this, &tcp_si_map::cleaner_cb)
350 {
351 cleaner.start (0);
352 }
353} tcp_si;
354
355struct tcp_connection : io_watcher {
356 tstamp last_activity;
357 const sockinfo si;
358 vpn &v;
359 bool ok;
360
361 vpn_packet *r_pkt;
362 u32 r_len, r_ofs;
363
364 void tcpv4_ev (io_watcher &w, short revents);
365
366 operator tcp_si_map::value_type()
367 {
368 return tcp_si_map::value_type (&si, this);
369 }
370
371 tcp_connection (int fd, const sockinfo &si_, vpn &v_)
372 : v(v_), si(si_), io_watcher(this, &tcp_connection::tcpv4_ev)
373 {
374 last_activity = NOW;
375 ok = false;
376 r_pkt = 0;
377 start (fd, POLLOUT);
378 }
379
380 ~tcp_connection () { if (p) close (p->fd); }
381};
382
383void tcp_si_map::cleaner_cb (time_watcher &w)
384{
385 w.at = NOW + 600;
386 tstamp to = NOW - ::conf.keepalive - 30;
387
388 for (iterator i = begin (); i != end(); )
389 if (i->second->last_activity >= to)
390 ++i;
391 else
392 {
393 erase (i);
394 i = begin ();
395 }
396}
397
294void 398void
399vpn::send_tcpv4_packet (vpn_packet *pkt, const sockinfo &si, int tos)
400{
401 tcp_si_map::iterator info = tcp_si.find (&si);
402
403 if (info == tcp_si.end ())
404 {
405 // woaw, the first lost packet ;)
406 int fd = socket (PF_INET, SOCK_STREAM, IPPROTO_TCP);
407
408 if (fd >= 0)
409 {
410 fcntl (fd, F_SETFL, O_NONBLOCK);
411
412 if (connect (fd, si.sav4 (), si.salenv4 ()) >= 0
413 || errno == EINPROGRESS)
414 {
415 tcp_connection *i = new tcp_connection (fd, si, *this);
416
417 tcp_si.insert (*i);
418 }
419 else
420 close (fd);
421 }
422 }
423 else
424 {
425 tcp_connection *i = info->second;
426
427 i->last_activity = NOW;
428
429 if (i->ok)
430 {
431 setsockopt (i->p->fd, SOL_IP, IP_TOS, &tos, sizeof tos);
432
433 // we use none of the advantages of tcp
434 write (i->p->fd, (void *)pkt, pkt->len + sizeof (u32)) != pkt->len + sizeof (u32);
435 }
436 }
437
438#if 0
439 setsockopt (udpv4_fd, SOL_IP, IP_TOS, &tos, sizeof tos);
440 sendto (udpv4_fd, &((*pkt)[0]), pkt->len, 0, si.sav4 (), si.salenv4 ());
441#endif
442}
443
444void
445tcp_connection::tcpv4_ev (io_watcher &w, short revents)
446{
447 last_activity = NOW;
448
449 if (!ok) // just established?
450 {
451 ok = true;
452 set (POLLIN);
453 }
454
455 if (revents & (POLLIN | POLLERR))
456 {
457 u32 len;
458
459 if (sizeof (len) == read (p->fd, &len, sizeof (len)))
460 {
461 vpn_packet *pkt = new vpn_packet;
462
463 if (len == read (p->fd, &((*pkt)[0]), len))
464 {
465 pkt->len = len;
466
467 v.recv_vpn_packet (pkt, si);
468 return;
469 }
470
471 delete pkt;
472 }
473
474 tcp_si.erase (&si);
475
476 set (0);//D
477 }
478}
479
480void
481vpn::tcpv4_ev (io_watcher &w, short revents)
482{
483 if (revents & (POLLIN | POLLERR))
484 {
485 struct sockaddr_in sa;
486 socklen_t sa_len = sizeof (sa);
487 int len;
488
489 int fd = accept (w.p->fd, (sockaddr *)&sa, &sa_len);
490
491 if (fd >= 0)
492 {
493 fcntl (fd, F_SETFL, O_NONBLOCK);
494
495 sockinfo si(sa, PROT_TCPv4);
496 tcp_connection *i = new tcp_connection (fd, si, *this);
497
498 slog (L_DEBUG, _("accepted tcp connection from %s\n"), (const char *)si);//D
499
500 tcp_si.insert (*i);
501 }
502 }
503}
504
505#endif
506
507void
295vpn::tap_ev (short revents) 508vpn::tap_ev (io_watcher &w, short revents)
296{ 509{
297 if (revents & POLLIN) 510 if (revents & POLLIN)
298 { 511 {
299 /* process data */ 512 /* process data */
300 tap_packet *pkt; 513 tap_packet *pkt;
350 else 563 else
351 abort (); 564 abort ();
352} 565}
353 566
354void 567void
355vpn::event_cb (tstamp &ts) 568vpn::event_cb (time_watcher &w)
356{ 569{
357 if (events) 570 if (events)
358 { 571 {
359 if (events & EVENT_SHUTDOWN) 572 if (events & EVENT_SHUTDOWN)
360 { 573 {
377 } 590 }
378 591
379 events = 0; 592 events = 0;
380 } 593 }
381 594
382 ts = TSTAMP_CANCEL; 595 w.at = TSTAMP_CANCEL;
383} 596}
384 597
385void 598void
386vpn::shutdown_all () 599vpn::shutdown_all ()
387{ 600{
468 681
469 slog (L_NOTICE, _("END status dump")); 682 slog (L_NOTICE, _("END status dump"));
470} 683}
471 684
472vpn::vpn (void) 685vpn::vpn (void)
686: event(this, &vpn::event_cb)
473: udpv4_ev_watcher(this, &vpn::udpv4_ev) 687, udpv4_ev_watcher(this, &vpn::udpv4_ev)
474, ipv4_ev_watcher(this, &vpn::ipv4_ev) 688, ipv4_ev_watcher (this, &vpn::ipv4_ev)
475, tap_ev_watcher(this, &vpn::tap_ev) 689, tap_ev_watcher (this, &vpn::tap_ev)
476, event(this, &vpn::event_cb) 690#if ENABLE_TCP
691, tcpv4_ev_watcher(this, &vpn::tcpv4_ev)
692#endif
477{ 693{
478} 694}
479 695
480vpn::~vpn () 696vpn::~vpn ()
481{ 697{

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines