ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/gvpe/src/protocol.C
(Generate patch)

Comparing gvpe/src/protocol.C (file contents):
Revision 1.15 by pcg, Sun Mar 23 14:49:16 2003 UTC vs.
Revision 1.16 by pcg, Tue Mar 25 18:11:58 2003 UTC

62 62
63static const rsachallenge & 63static const rsachallenge &
64challenge_bytes () 64challenge_bytes ()
65{ 65{
66 static rsachallenge challenge; 66 static rsachallenge challenge;
67 static double challenge_ttl; // time this challenge needs to be recreated 67 static tstamp challenge_ttl; // time this challenge needs to be recreated
68 68
69 if (NOW > challenge_ttl) 69 if (NOW > challenge_ttl)
70 { 70 {
71 RAND_bytes ((unsigned char *)&challenge, sizeof (challenge)); 71 RAND_bytes ((unsigned char *)&challenge, sizeof (challenge));
72 challenge_ttl = NOW + CHALLENGE_TTL; 72 challenge_ttl = NOW + CHALLENGE_TTL;
264{ 264{
265 for (i = QUEUEDEPTH; --i > 0; ) 265 for (i = QUEUEDEPTH; --i > 0; )
266 delete queue[i]; 266 delete queue[i];
267} 267}
268 268
269struct net_rateinfo {
270 u32 host;
271 double pcnt, diff;
272 tstamp last;
273};
274
269// only do action once every x seconds per host. 275// only do action once every x seconds per host whole allowing bursts.
270// currently this is quite a slow implementation, 276// this implementation ("splay list" ;) is inefficient,
271// but suffices for normal operation. 277// but low on resources.
272struct u32_rate_limiter : private map<u32, tstamp> 278struct net_rate_limiter : private list<net_rateinfo>
273 { 279{
274 tstamp every; 280 static const double ALPHA = 1. - 1. / 90.; // allow bursts
281 static const double CUTOFF = 20.; // one event every CUTOFF seconds
282 static const double EXPIRE = CUTOFF * 30.; // expire entries after this time
275 283
276 bool can (u32 host); 284 bool can (u32 host);
277
278 u32_rate_limiter (tstamp every = 1)
279 {
280 this->every = every;
281 }
282 };
283
284struct net_rate_limiter : u32_rate_limiter
285 {
286 bool can (SOCKADDR *sa) { return u32_rate_limiter::can((u32)sa->sin_addr.s_addr); } 285 bool can (SOCKADDR *sa) { return can((u32)sa->sin_addr.s_addr); }
287 bool can (sockinfo &si) { return u32_rate_limiter::can((u32)si.host); } 286 bool can (sockinfo &si) { return can((u32)si.host); }
287};
288 288
289 net_rate_limiter (tstamp every) : u32_rate_limiter (every) {} 289net_rate_limiter auth_rate_limiter, reset_rate_limiter;
290 };
291 290
292bool u32_rate_limiter::can (u32 host) 291bool net_rate_limiter::can (u32 host)
293{ 292{
294 iterator i; 293 iterator i;
295 294
296 for (i = begin (); i != end (); ) 295 for (i = begin (); i != end (); )
297 if (i->second <= NOW) 296 if (i->host == host)
298 { 297 break;
298 else if (i->last < NOW - EXPIRE)
299 erase (i); 299 i = erase (i);
300 i = begin ();
301 }
302 else 300 else
303 ++i; 301 i++;
304 302
305 i = find (host);
306
307 if (i != end ()) 303 if (i == end ())
308 return false; 304 {
305 net_rateinfo ri;
309 306
310 insert (value_type (host, NOW + every)); 307 ri.host = host;
308 ri.pcnt = 1.;
309 ri.diff = CUTOFF * (1. / (1. - ALPHA));
310 ri.last = NOW;
311 311
312 push_front (ri);
313
312 return true; 314 return true;
315 }
316 else
317 {
318 net_rateinfo ri (*i);
319 erase (i);
320
321 ri.pcnt = ri.pcnt * ALPHA;
322 ri.diff = ri.diff * ALPHA + (NOW - ri.last);
323
324 ri.last = NOW;
325
326 bool send = ri.diff / ri.pcnt > CUTOFF;
327
328 if (send)
329 ri.pcnt++;
330
331 //printf ("RATE %d %f,%f = %f > %f\n", !!send, ri.pcnt, ri.diff, ri.diff / ri.pcnt, CUTOFF);
332
333 push_front (ri);
334
335 return send;
336 }
313} 337}
314 338
315///////////////////////////////////////////////////////////////////////////// 339/////////////////////////////////////////////////////////////////////////////
316 340
317static void next_wakeup (time_t next) 341static void next_wakeup (time_t next)
665} 689}
666 690
667void 691void
668connection::send_reset (SOCKADDR *dsa) 692connection::send_reset (SOCKADDR *dsa)
669{ 693{
670 static net_rate_limiter limiter(1);
671
672 if (limiter.can (dsa) && connectmode != conf_node::C_DISABLED) 694 if (reset_rate_limiter.can (dsa) && connectmode != conf_node::C_DISABLED)
673 { 695 {
674 config_packet *pkt = new config_packet; 696 config_packet *pkt = new config_packet;
675 697
676 pkt->setup (vpn_packet::PT_RESET, conf->id); 698 pkt->setup (vpn_packet::PT_RESET, conf->id);
677 vpn->send_vpn_packet (pkt, dsa, IPTOS_MINCOST); 699 vpn->send_vpn_packet (pkt, dsa, IPTOS_MINCOST);
693} 715}
694 716
695void 717void
696connection::send_auth (auth_subtype subtype, SOCKADDR *sa, const rsachallenge *k) 718connection::send_auth (auth_subtype subtype, SOCKADDR *sa, const rsachallenge *k)
697{ 719{
698 static net_rate_limiter limiter(0.2);
699
700 if (subtype != AUTH_INIT || limiter.can (sa)) 720 if (subtype == AUTH_REPLY || auth_rate_limiter.can (sa))
701 { 721 {
702 if (!k) 722 if (!k)
703 k = gen_challenge (seqrand, sa); 723 k = gen_challenge (seqrand, sa);
704 724
705 auth_packet *pkt = new auth_packet (conf->id, subtype); 725 auth_packet *pkt = new auth_packet (conf->id, subtype);
732 { 752 {
733 reset_dstaddr (); 753 reset_dstaddr ();
734 if (sa.sin_addr.s_addr) 754 if (sa.sin_addr.s_addr)
735 if (retry_cnt < 4) 755 if (retry_cnt < 4)
736 send_auth (AUTH_INIT, &sa); 756 send_auth (AUTH_INIT, &sa);
737 else 757 else if (auth_rate_limiter.can (&sa))
738 send_ping (&sa, 0); 758 send_ping (&sa, 0);
739 } 759 }
740 else 760 else
741 vpn->connect_request (conf->id); 761 vpn->connect_request (conf->id);
742 } 762 }
829 conf->id, pkt->typ (), pkt->src (), pkt->dst ()); 849 conf->id, pkt->typ (), pkt->src (), pkt->dst ());
830 850
831 switch (pkt->typ ()) 851 switch (pkt->typ ())
832 { 852 {
833 case vpn_packet::PT_PING: 853 case vpn_packet::PT_PING:
834 send_ping (ssa, 1); // pong
835 break;
836
837 case vpn_packet::PT_PONG:
838 // we send pings instead of auth packets after some retries, 854 // we send pings instead of auth packets after some retries,
839 // so reset the retry counter and establish a conenction 855 // so reset the retry counter and establish a conenction
840 // when we receive a pong. 856 // when we receive a pong.
841 if (!ictx && !octx) 857 if (!ictx && !octx)
842 { 858 {
843 retry_cnt = 0; 859 retry_cnt = 0;
844 establish_connection.at = 0; 860 establish_connection.at = 0;
845 establish_connection (); 861 establish_connection ();
846 } 862 }
863 else
864 send_ping (ssa, 1); // pong
847 865
866 break;
867
868 case vpn_packet::PT_PONG:
848 break; 869 break;
849 870
850 case vpn_packet::PT_RESET: 871 case vpn_packet::PT_RESET:
851 { 872 {
852 reset_connection (); 873 reset_connection ();
882 903
883 if (!k) 904 if (!k)
884 { 905 {
885 slog (L_ERR, _("challenge from %s (%s) illegal or corrupted"), 906 slog (L_ERR, _("challenge from %s (%s) illegal or corrupted"),
886 conf->nodename, (const char *)sockinfo (ssa)); 907 conf->nodename, (const char *)sockinfo (ssa));
908 send_reset (ssa);
887 break; 909 break;
888 } 910 }
889 911
890 retry_cnt = 0; 912 retry_cnt = 0;
891 establish_connection.set (NOW + 8); //? ;) 913 establish_connection.set (NOW + 8); //? ;)
1444 } 1466 }
1445 1467
1446 ts = TSTAMP_CANCEL; 1468 ts = TSTAMP_CANCEL;
1447} 1469}
1448 1470
1471#include <sys/time.h>//D
1449vpn::vpn (void) 1472vpn::vpn (void)
1450: udp_ev_watcher (this, &vpn::udp_ev) 1473: udp_ev_watcher (this, &vpn::udp_ev)
1451, vpn_ev_watcher (this, &vpn::vpn_ev) 1474, vpn_ev_watcher (this, &vpn::vpn_ev)
1452, event (this, &vpn::event_cb) 1475, event (this, &vpn::event_cb)
1453{ 1476{

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines