--- gvpe/src/connection.C 2013/09/20 11:57:03 1.107 +++ gvpe/src/connection.C 2013/10/11 04:07:24 1.108 @@ -703,7 +703,7 @@ slog (L_INFO, _("%s(%s): connection established (%s), protocol version %d.%d."), conf->nodename, (const char *)rsi, - is_direct ? "direct" : "forwarded", + vpn->can_direct (THISNODE, conf) ? "direct" : "forwarded", PROTOCOL_MAJOR, prot_minor); if (::conf.script_node_up) @@ -725,22 +725,21 @@ ev::tstamp rekey_interval = ::conf.rekey + (conf->id > THISNODE->id ? 10 : 0); rekey.start (rekey_interval, rekey_interval); + hmac_error = 0.; + keepalive.start (::conf.keepalive); // send queued packets - if (ictx && octx) + while (tap_packet *p = (tap_packet *)data_queue.get ()) { - while (tap_packet *p = (tap_packet *)data_queue.get ()) - { - if (p->len) send_data_packet (p); - delete p; - } + if (p->len) send_data_packet (p); + delete p; + } - while (vpn_packet *p = (vpn_packet *)vpn_queue.get ()) - { - if (p->len) send_vpn_packet (p, si, IPTOS_RELIABILITY); - delete p; - } + while (vpn_packet *p = (vpn_packet *)vpn_queue.get ()) + { + if (p->len) send_vpn_packet (p, si, IPTOS_RELIABILITY); + delete p; } vpn->connection_established (this); @@ -758,8 +757,6 @@ } si.set (conf, protocol); - - is_direct = si.valid (); } // ensure sockinfo is valid, forward if necessary @@ -788,7 +785,7 @@ connection::send_vpn_packet (vpn_packet *pkt, const sockinfo &si, int tos) { if (!vpn->send_vpn_packet (pkt, si, tos)) - reset_connection (); + reset_connection ("packet send error"); } void @@ -874,7 +871,7 @@ // and stop trying. should probably be handled by a per-connection expire handler. if (connectmode == conf_node::C_ONDEMAND && vpn_queue.empty () && data_queue.empty ()) { - reset_connection (); + reset_connection ("no demand"); return; } @@ -925,12 +922,12 @@ } void -connection::reset_connection () +connection::reset_connection (const char *reason) { if (ictx && octx) { - slog (L_INFO, _("%s(%s): connection lost"), - conf->nodename, (const char *)si); + slog (L_INFO, _("%s(%s): connection lost (%s)"), + conf->nodename, (const char *)si, reason); if (::conf.script_node_down) { @@ -964,14 +961,14 @@ if (ictx && octx) send_reset (si); - reset_connection (); + reset_connection ("shutdown"); } // poor-man's rekeying inline void connection::rekey_cb (ev::timer &w, int revents) { - reset_connection (); + reset_connection ("rekeying"); establish_connection (); } @@ -1068,14 +1065,18 @@ break; case vpn_packet::PT_RESET: - { - reset_connection (); + slog (L_TRACE, "%s >> PT_RESET", conf->nodename); - config_packet *p = (config_packet *) pkt; + if (ictx && octx) + { + reset_connection ("remote reset"); + + config_packet *p = (config_packet *) pkt; + + if (p->chk_config (conf, rsi) && connectmode == conf_node::C_ALWAYS) + establish_connection (); + } - if (p->chk_config (conf, rsi) && connectmode == conf_node::C_ALWAYS) - establish_connection (); - } break; case vpn_packet::PT_AUTH_REQ: @@ -1100,7 +1101,12 @@ PROTOCOL_MINOR, conf->nodename, p->prot_minor); if (p->initiate) - send_auth_request (rsi, false); + { + send_auth_request (rsi, false); + + if (ictx && octx) + reset_connection ("reconnect"); + } auth_data auth; @@ -1172,15 +1178,34 @@ vpndata_packet *p = (vpndata_packet *)pkt; if (!p->hmac_chk (ictx)) - slog (L_ERR, _("%s(%s): hmac authentication error, received invalid packet\n" - "could be an attack, or just corruption or a synchronization error."), - conf->nodename, (const char *)rsi); + { + // rekeying often creates temporary hmac auth floods + // we assume they don't take longer than a few seconds normally, + // and suppress messages and resets during that time. + //TODO: should be done per source address + if (!hmac_error) + { + hmac_error = ev_now () + 3; + break; + } + else if (hmac_error >= ev_now ()) + break; // silently suppress + else + { + slog (L_ERR, _("%s(%s): hmac authentication error, received invalid packet\n" + "could be an attack, or just corruption or a synchronization error."), + conf->nodename, (const char *)rsi); + // reset + } + } else { u32 seqno; tap_packet *d = p->unpack (this, seqno); int seqclass = iseqno.seqno_classify (seqno); + hmac_error = 0; + if (seqclass == 0) // ok { vpn->tap->send (d); @@ -1316,7 +1341,7 @@ w.start (when); else if (when < -15) { - reset_connection (); + reset_connection ("keepalive overdue"); establish_connection (); } else if (conf->connectmode != conf_node::C_ONDEMAND @@ -1330,7 +1355,7 @@ // should delete octx, though, or something like that ;) w.start (when + 10); else - reset_connection (); + reset_connection ("keepalive timeout"); } void @@ -1440,7 +1465,7 @@ if (connectmode != conf_node::C_ALWAYS && connectmode != conf_node::C_DISABLED) vpn_queue.put (new net_packet); - reset_connection (); + reset_connection ("startup"); } connection::~connection ()