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.4 by pcg, Fri Apr 4 05:26:45 2003 UTC vs.
Revision 1.7 by pcg, Sun Apr 6 18:12:18 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
50///////////////////////////////////////////////////////////////////////////// 43/////////////////////////////////////////////////////////////////////////////
51 44
52const char *vpn::script_if_up () 45const char *vpn::script_if_up ()
53{ 46{
54 // the tunnel device mtu should be the physical mtu - overhead 47 // the tunnel device mtu should be the physical mtu - overhead
191 reconnect_all (); 184 reconnect_all ();
192 185
193 return 0; 186 return 0;
194} 187}
195 188
196void 189// send a vpn packet out to other hosts
190bool
191vpn::send_vpn_packet (vpn_packet *pkt, const sockinfo &si, int tos)
192{
193 switch (si.prot)
194 {
195 case PROT_IPv4:
196 return send_ipv4_packet (pkt, si, tos);
197
198 case PROT_UDPv4:
199 return send_udpv4_packet (pkt, si, tos);
200
201#if ENABLE_TCP
202 case PROT_TCPv4:
203 return send_tcpv4_packet (pkt, si, tos);
204#endif
205
206 default:
207 slog (L_CRIT, _("%s: FATAL: trying to send packet with unsupported protocol"), (const char *)si);
208 return false;
209 }
210}
211
212bool
197vpn::send_ipv4_packet (vpn_packet *pkt, const sockinfo &si, int tos) 213vpn::send_ipv4_packet (vpn_packet *pkt, const sockinfo &si, int tos)
198{ 214{
199 setsockopt (ipv4_fd, SOL_IP, IP_TOS, &tos, sizeof tos); 215 setsockopt (ipv4_fd, SOL_IP, IP_TOS, &tos, sizeof tos);
200 sendto (ipv4_fd, &((*pkt)[0]), pkt->len, 0, si.sav4 (), si.salenv4 ()); 216 sendto (ipv4_fd, &((*pkt)[0]), pkt->len, 0, si.sav4 (), si.salenv4 ());
201}
202 217
203void 218 return true;
219}
220
221bool
204vpn::send_udpv4_packet (vpn_packet *pkt, const sockinfo &si, int tos) 222vpn::send_udpv4_packet (vpn_packet *pkt, const sockinfo &si, int tos)
205{ 223{
206 setsockopt (udpv4_fd, SOL_IP, IP_TOS, &tos, sizeof tos); 224 setsockopt (udpv4_fd, SOL_IP, IP_TOS, &tos, sizeof tos);
207 sendto (udpv4_fd, &((*pkt)[0]), pkt->len, 0, si.sav4 (), si.salenv4 ()); 225 sendto (udpv4_fd, &((*pkt)[0]), pkt->len, 0, si.sav4 (), si.salenv4 ());
226
227 return true;
208} 228}
209 229
210void 230void
211vpn::recv_vpn_packet (vpn_packet *pkt, const sockinfo &rsi) 231vpn::recv_vpn_packet (vpn_packet *pkt, const sockinfo &rsi)
212{ 232{
219 if (src == 0 || src > conns.size () 239 if (src == 0 || src > conns.size ()
220 || dst > conns.size () 240 || dst > conns.size ()
221 || pkt->typ () >= vpn_packet::PT_MAX) 241 || pkt->typ () >= vpn_packet::PT_MAX)
222 slog (L_WARN, _("(%s): received corrupted packet type %d (src %d, dst %d)"), 242 slog (L_WARN, _("(%s): received corrupted packet type %d (src %d, dst %d)"),
223 (const char *)rsi, pkt->typ (), pkt->src (), pkt->dst ()); 243 (const char *)rsi, pkt->typ (), pkt->src (), pkt->dst ());
244 else if (dst > conns.size ())
245 slog (L_WARN, _("(%s): received corrupted packet type %d (src %d, dst %d)"),
246 (const char *)rsi, pkt->typ (), pkt->src (), pkt->dst ());
224 else 247 else
225 { 248 {
226 connection *c = conns[src - 1]; 249 connection *c = conns[src - 1];
227 250
228 if (dst == 0 && !THISNODE->routerprio) 251 if (dst == 0 && !THISNODE->routerprio)
229 slog (L_WARN, _("%s(%s): received broadcast, but we are no router"), 252 slog (L_WARN, _("%s(%s): received broadcast, but we are no router"),
230 c->conf->nodename, (const char *)rsi); 253 c->conf->nodename, (const char *)rsi);
231 else if (dst != 0 && dst != THISNODE->id) 254 else if (dst != 0 && dst != THISNODE->id)
232 // FORWARDING NEEDED ;) 255 {
256 if (THISNODE->routerprio)
257 // the tos setting gets lost here. who cares.
258 conns[dst - 1]->inject_vpn_packet (pkt);
259 else
233 slog (L_WARN, 260 slog (L_WARN,
234 _("received frame for node %d ('%s') from %s, but this is node %d ('%s')"), 261 _("%s(%s): forwarding request (=> %s), but we are no router"),
262 c->conf->nodename, (const char *)rsi,
235 dst, conns[dst - 1]->conf->nodename, 263 conns[dst - 1]->conf->nodename);
236 (const char *)rsi, 264 }
237 THISNODE->id, THISNODE->nodename);
238 else 265 else
239 c->recv_vpn_packet (pkt, rsi); 266 c->recv_vpn_packet (pkt, rsi);
240 } 267 }
241} 268}
242 269
248 vpn_packet *pkt = new vpn_packet; 275 vpn_packet *pkt = new vpn_packet;
249 struct sockaddr_in sa; 276 struct sockaddr_in sa;
250 socklen_t sa_len = sizeof (sa); 277 socklen_t sa_len = sizeof (sa);
251 int len; 278 int len;
252 279
253 len = recvfrom (w.p->fd, &((*pkt)[0]), MAXSIZE, 0, (sockaddr *)&sa, &sa_len); 280 len = recvfrom (w.fd, &((*pkt)[0]), MAXSIZE, 0, (sockaddr *)&sa, &sa_len);
254 281
255 sockinfo si(sa); 282 sockinfo si(sa, PROT_UDPv4);
256 283
257 if (len > 0) 284 if (len > 0)
258 { 285 {
259 pkt->len = len; 286 pkt->len = len;
260 287
261 recv_vpn_packet (pkt, si); 288 recv_vpn_packet (pkt, si);
262 } 289 }
263 else 290 else
264 { 291 {
265 // probably ECONNRESET or somesuch 292 // probably ECONNRESET or somesuch
266 slog (L_DEBUG, _("%s: %s"), (const char *)si, strerror (errno)); 293 slog (L_DEBUG, _("%s: fd %d, %s"), (const char *)si, w.fd, strerror (errno));
267 } 294 }
268 295
269 delete pkt; 296 delete pkt;
270 } 297 }
271 else if (revents & POLLHUP) 298 else if (revents & POLLHUP)
291 vpn_packet *pkt = new vpn_packet; 318 vpn_packet *pkt = new vpn_packet;
292 struct sockaddr_in sa; 319 struct sockaddr_in sa;
293 socklen_t sa_len = sizeof (sa); 320 socklen_t sa_len = sizeof (sa);
294 int len; 321 int len;
295 322
296 len = recvfrom (w.p->fd, &((*pkt)[0]), MAXSIZE, 0, (sockaddr *)&sa, &sa_len); 323 len = recvfrom (w.fd, &((*pkt)[0]), MAXSIZE, 0, (sockaddr *)&sa, &sa_len);
297 324
298 sockinfo si(sa, PROT_IPv4); 325 sockinfo si(sa, PROT_IPv4);
299 326
300 if (len > 0) 327 if (len > 0)
301 { 328 {
327 _("FATAL: unknown revents %08x in socket, terminating\n"), 354 _("FATAL: unknown revents %08x in socket, terminating\n"),
328 revents); 355 revents);
329 exit (1); 356 exit (1);
330 } 357 }
331} 358}
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
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 359
507void 360void
508vpn::tap_ev (io_watcher &w, short revents) 361vpn::tap_ev (io_watcher &w, short revents)
509{ 362{
510 if (revents & POLLIN) 363 if (revents & POLLIN)
644 } 497 }
645 498
646 return router; 499 return router;
647} 500}
648 501
649void vpn::connect_request (int id) 502void vpn::send_connect_request (int id)
650{ 503{
651 connection *c = find_router (); 504 connection *c = find_router ();
652 505
653 if (c) 506 if (c)
654 c->connect_request (id); 507 c->send_connect_request (id);
655 //else // does not work, because all others must connect to the same router 508 else
656 // // no router found, aggressively connect to all routers 509 // no router found, aggressively connect to all routers
657 // for (conns_vector::iterator i = conns.begin (); i != conns.end (); ++i) 510 for (conns_vector::iterator i = conns.begin (); i != conns.end (); ++i)
658 // if ((*i)->conf->routerprio) 511 if ((*i)->conf->routerprio)
659 // (*i)->establish_connection (); 512 (*i)->establish_connection ();
660} 513}
661 514
662void 515void
663connection::dump_status () 516connection::dump_status ()
664{ 517{

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines