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.2 by pcg, Wed Apr 2 05:15:00 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
87 udpv4_fd = socket (PF_INET, SOCK_DGRAM, IPPROTO_UDP); 80 udpv4_fd = socket (PF_INET, SOCK_DGRAM, IPPROTO_UDP);
88 81
89 if (udpv4_fd < 0) 82 if (udpv4_fd < 0)
90 return -1; 83 return -1;
91 84
85 // standard daemon practise...
86 {
87 int oval = 1;
88 setsockopt (udpv4_fd, SOL_SOCKET, SO_REUSEADDR, &oval, sizeof oval);
89 }
90
92 sockinfo si (THISNODE, PROT_UDPv4); 91 sockinfo si (THISNODE, PROT_UDPv4);
93 92
94 if (bind (udpv4_fd, si.sav4 (), si.salenv4 ())) 93 if (bind (udpv4_fd, si.sav4 (), si.salenv4 ()))
95 { 94 {
96 slog (L_ERR, _("can't bind udpv4 on %s: %s"), (const char *)si, strerror (errno)); 95 slog (L_ERR, _("can't bind udpv4 on %s: %s"), (const char *)si, strerror (errno));
105 int oval = IP_PMTUDISC_DONT; 104 int oval = IP_PMTUDISC_DONT;
106 setsockopt (udpv4_fd, SOL_IP, IP_MTU_DISCOVER, &oval, sizeof oval); 105 setsockopt (udpv4_fd, SOL_IP, IP_MTU_DISCOVER, &oval, sizeof oval);
107 } 106 }
108#endif 107#endif
109 108
110 // standard daemon practise...
111 {
112 int oval = 1;
113 setsockopt (udpv4_fd, SOL_SOCKET, SO_REUSEADDR, &oval, sizeof oval);
114 }
115
116 udpv4_ev_watcher.start (udpv4_fd, POLLIN); 109 udpv4_ev_watcher.start (udpv4_fd, POLLIN);
117 } 110 }
118 111
119 ipv4_fd = -1; 112 ipv4_fd = -1;
120 if (THISNODE->protocols & PROT_IPv4) 113 if (THISNODE->protocols & PROT_IPv4)
151 tcpv4_fd = socket (PF_INET, SOCK_STREAM, IPPROTO_TCP); 144 tcpv4_fd = socket (PF_INET, SOCK_STREAM, IPPROTO_TCP);
152 145
153 if (tcpv4_fd < 0) 146 if (tcpv4_fd < 0)
154 return -1; 147 return -1;
155 148
156 sockinfo si (THISNODE, PROT_TCPv4);
157
158 if (bind (tcpv4_fd, si.sav4 (), si.salenv4 ()))
159 {
160 slog (L_ERR, _("can't bind tcpv4 on %s: %s"), (const char *)si, strerror (errno));
161 exit (1);
162 }
163
164 if (listen (tcpv4_fd, 5))
165 {
166 slog (L_ERR, _("can't listen tcpv4 on %s: %s"), (const char *)si, strerror (errno));
167 exit (1);
168 }
169
170 // standard daemon practise... 149 // standard daemon practise...
171 { 150 {
172 int oval = 1; 151 int oval = 1;
173 setsockopt (tcpv4_fd, SOL_SOCKET, SO_REUSEADDR, &oval, sizeof oval); 152 setsockopt (tcpv4_fd, SOL_SOCKET, SO_REUSEADDR, &oval, sizeof oval);
174 } 153 }
175 154
155 sockinfo si (THISNODE, PROT_TCPv4);
156
157 if (bind (tcpv4_fd, si.sav4 (), si.salenv4 ()))
158 {
159 slog (L_ERR, _("can't bind tcpv4 on %s: %s"), (const char *)si, strerror (errno));
160 exit (1);
161 }
162
163 if (listen (tcpv4_fd, 5))
164 {
165 slog (L_ERR, _("can't listen tcpv4 on %s: %s"), (const char *)si, strerror (errno));
166 exit (1);
167 }
168
176 tcpv4_accept_watcher.start (tcpv4_fd, POLLIN); 169 tcpv4_ev_watcher.start (tcpv4_fd, POLLIN);
177 } 170 }
178#endif 171#endif
179 172
180 tap = new tap_device (); 173 tap = new tap_device ();
181 if (!tap) //D this, of course, never catches 174 if (!tap) //D this, of course, never catches
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
243void 270void
244vpn::udpv4_ev (int fd, short revents) 271vpn::udpv4_ev (io_watcher &w, short revents)
245{ 272{
246 if (revents & (POLLIN | POLLERR)) 273 if (revents & (POLLIN | POLLERR))
247 { 274 {
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 (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)
282 exit (1); 309 exit (1);
283 } 310 }
284} 311}
285 312
286void 313void
287vpn::ipv4_ev (int fd, short revents) 314vpn::ipv4_ev (io_watcher &w, short revents)
288{ 315{
289 if (revents & (POLLIN | POLLERR)) 316 if (revents & (POLLIN | POLLERR))
290 { 317 {
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 (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 {
328 revents); 355 revents);
329 exit (1); 356 exit (1);
330 } 357 }
331} 358}
332 359
333#if ENABLE_TCP
334
335struct tcp_info {
336 int fd;
337 bool ok;
338 io_watcher r;
339
340 tcp_info (vpn *v)
341 : r(v, &vpn::tcpv4_ev)
342 {
343 fd = -1;
344 }
345
346 ~tcp_info () { close (fd); }
347};
348
349typedef map<sockinfo, tcp_info *> tcp_si_map;
350typedef map<int, tcp_info *> tcp_fd_map; // unneecssary if iom would be cooler
351static tcp_si_map tcp_si;
352static tcp_fd_map tcp_fd;
353
354void 360void
355vpn::send_tcpv4_packet (vpn_packet *pkt, const sockinfo &si, int tos)
356{
357 tcp_si_map::iterator info = tcp_si.find (si);
358
359 if (info == tcp_si.end ())
360 {
361 // woaw, the first lost packet ;)
362 tcp_info *i = new tcp_info (this);
363
364 i->ok = false;
365 i->fd = socket (PF_INET, SOCK_STREAM, IPPROTO_TCP);
366
367 if (i->fd >= 0)
368 {
369 fcntl (i->fd, F_SETFL, O_NONBLOCK);
370
371 if (connect (i->fd, si.sav4 (), si.salenv4 ()) >= 0
372 || errno == EINPROGRESS)
373 {
374 tcp_si.insert (tcp_si_map::value_type (si, i));
375 tcp_fd.insert (tcp_fd_map::value_type (i->fd, i));
376 return;
377 }
378
379 delete i;
380 }
381 }
382 else
383 {
384 tcp_info *i = info->second;
385
386 if (i->ok)
387 {
388 setsockopt (i->fd, SOL_IP, IP_TOS, &tos, sizeof tos);
389
390 if (write (i->fd, (void *)pkt, pkt->len + sizeof (u32)) != pkt->len + sizeof (u32))
391 {
392 // error, close socket, forget it and retry immediately
393 tcp_si.erase (info);
394 tcp_fd.erase (i->fd);
395 delete i;
396
397 // tail recursion is... better than goto(?)
398 send_tcpv4_packet (pkt, si, tos);
399 }
400 }
401 }
402
403#if 0
404 setsockopt (udpv4_fd, SOL_IP, IP_TOS, &tos, sizeof tos);
405 sendto (udpv4_fd, &((*pkt)[0]), pkt->len, 0, si.sav4 (), si.salenv4 ());
406#endif
407}
408
409void
410vpn::tcpv4_accept (int fd, short revents)
411{
412 if (revents & (POLLIN | POLLERR))
413 {
414 struct sockaddr_in sa;
415 socklen_t sa_len = sizeof (sa);
416 int len;
417
418 fd = accept (fd, (sockaddr *)&sa, &sa_len);
419
420 if (fd >= 0)
421 {
422 fcntl (fd, F_SETFL, O_NONBLOCK);
423
424 sockinfo si(sa, PROT_TCPv4);
425 tcp_info *i = new tcp_info (this);
426
427 i->fd = fd;
428 i->ok = true;
429 i->r.start (fd, POLLIN);
430
431 tcp_si.insert (tcp_si_map::value_type (si, i));
432 tcp_fd.insert (tcp_fd_map::value_type (fd, i));
433 }
434 }
435}
436
437void
438vpn::tcpv4_ev (int fd, short revents)
439{
440 if (revents & (POLLIN | POLLERR))
441 {
442 tcp_fd_map::iterator info = tcp_fd.find (fd);
443
444 if (info != tcp_fd.end ())
445 {
446 tcp_info *i = info->second;
447
448 if (!i->ok) // not yet established
449 {
450 i->ok = true;
451 fcntl (i->fd, F_SETFL, 0);
452 }
453
454 u32 len;
455
456 if (sizeof (len) == read (fd, &len, sizeof (len)))
457 {
458 slog (L_ERR, "%d bytes received\n", len);
459 }
460
461 //tcp_si.erase (i);
462 tcp_fd.erase (fd);
463 delete i;
464 }
465 }
466}
467
468#endif
469
470void
471vpn::tap_ev (int fd, short revents) 361vpn::tap_ev (io_watcher &w, short revents)
472{ 362{
473 if (revents & POLLIN) 363 if (revents & POLLIN)
474 { 364 {
475 /* process data */ 365 /* process data */
476 tap_packet *pkt; 366 tap_packet *pkt;
526 else 416 else
527 abort (); 417 abort ();
528} 418}
529 419
530void 420void
531vpn::event_cb (tstamp &ts) 421vpn::event_cb (time_watcher &w)
532{ 422{
533 if (events) 423 if (events)
534 { 424 {
535 if (events & EVENT_SHUTDOWN) 425 if (events & EVENT_SHUTDOWN)
536 { 426 {
553 } 443 }
554 444
555 events = 0; 445 events = 0;
556 } 446 }
557 447
558 ts = TSTAMP_CANCEL; 448 w.at = TSTAMP_CANCEL;
559} 449}
560 450
561void 451void
562vpn::shutdown_all () 452vpn::shutdown_all ()
563{ 453{
607 } 497 }
608 498
609 return router; 499 return router;
610} 500}
611 501
612void vpn::connect_request (int id) 502void vpn::send_connect_request (int id)
613{ 503{
614 connection *c = find_router (); 504 connection *c = find_router ();
615 505
616 if (c) 506 if (c)
617 c->connect_request (id); 507 c->send_connect_request (id);
618 //else // does not work, because all others must connect to the same router 508 else
619 // // no router found, aggressively connect to all routers 509 // no router found, aggressively connect to all routers
620 // for (conns_vector::iterator i = conns.begin (); i != conns.end (); ++i) 510 for (conns_vector::iterator i = conns.begin (); i != conns.end (); ++i)
621 // if ((*i)->conf->routerprio) 511 if ((*i)->conf->routerprio)
622 // (*i)->establish_connection (); 512 (*i)->establish_connection ();
623} 513}
624 514
625void 515void
626connection::dump_status () 516connection::dump_status ()
627{ 517{
649: event(this, &vpn::event_cb) 539: event(this, &vpn::event_cb)
650, udpv4_ev_watcher(this, &vpn::udpv4_ev) 540, udpv4_ev_watcher(this, &vpn::udpv4_ev)
651, ipv4_ev_watcher (this, &vpn::ipv4_ev) 541, ipv4_ev_watcher (this, &vpn::ipv4_ev)
652, tap_ev_watcher (this, &vpn::tap_ev) 542, tap_ev_watcher (this, &vpn::tap_ev)
653#if ENABLE_TCP 543#if ENABLE_TCP
654, tcpv4_accept_watcher(this, &vpn::tcpv4_accept) 544, tcpv4_ev_watcher(this, &vpn::tcpv4_ev)
655#endif 545#endif
656{ 546{
657} 547}
658 548
659vpn::~vpn () 549vpn::~vpn ()

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines