--- gvpe/src/connection.C 2003/04/02 05:15:00 1.3 +++ gvpe/src/connection.C 2003/04/06 04:31:51 1.9 @@ -87,7 +87,7 @@ struct rsa_cache : list { - void cleaner_cb (tstamp &ts); time_watcher cleaner; + void cleaner_cb (time_watcher &w); time_watcher cleaner; bool find (const rsaid &id, rsachallenge &chg) { @@ -131,13 +131,13 @@ } rsa_cache; -void rsa_cache::cleaner_cb (tstamp &ts) +void rsa_cache::cleaner_cb (time_watcher &w) { if (empty ()) - ts = TSTAMP_CANCEL; + w.at = TSTAMP_CANCEL; else { - ts = NOW + RSA_TTL; + w.at = NOW + RSA_TTL; for (iterator i = begin (); i != end (); ) if (i->expire <= NOW) @@ -199,9 +199,9 @@ // but low on resources. struct net_rate_limiter : list { - static const double ALPHA = 1. - 1. / 90.; // allow bursts - static const double CUTOFF = 20.; // one event every CUTOFF seconds - static const double EXPIRE = CUTOFF * 30.; // expire entries after this time + static const double ALPHA = 1. - 1. / 180.; // allow bursts + static const double CUTOFF = 10.; // one event every CUTOFF seconds + static const double EXPIRE = CUTOFF * 30.; // expire entries after this time bool can (const sockinfo &si) { return can((u32)si.host); } bool can (u32 host); @@ -287,9 +287,9 @@ return !memcmp (hmac, hmac_digest, HMACLENGTH); } -void vpn_packet::set_hdr (ptype type, unsigned int dst) +void vpn_packet::set_hdr (ptype type_, unsigned int dst) { - this->type = type; + type = type_; int src = THISNODE->id; @@ -548,9 +548,37 @@ ///////////////////////////////////////////////////////////////////////////// void -connection::reset_dstaddr () +connection::reset_si () { - si.set (conf); + protocol = best_protocol (THISNODE->protocols & conf->protocols); + + // mask out protocols we cannot establish + if (!conf->udp_port) protocol &= ~PROT_UDPv4; + if (!conf->tcp_port) protocol &= ~PROT_TCPv4; + + si.set (conf, protocol); +} + +// ensure sockinfo is valid, forward if necessary +const sockinfo & +connection::forward_si (const sockinfo &si) const +{ + if (!si.valid ()) + { + connection *r = vpn->find_router (); + + if (r) + { + slog (L_DEBUG, _("%s: no common protocol, trying indirectly through %s"), + conf->nodename, r->conf->nodename); + return r->si; + } + else + slog (L_DEBUG, _("%s: node unreachable, no common protocol"), + conf->nodename); + } + + return si; } void @@ -559,7 +587,7 @@ ping_packet *pkt = new ping_packet; pkt->setup (conf->id, pong ? ping_packet::PT_PONG : ping_packet::PT_PING); - send_vpn_packet (pkt, si, IPTOS_LOWDELAY); + vpn->send_vpn_packet (pkt, si, IPTOS_LOWDELAY); delete pkt; } @@ -572,7 +600,7 @@ config_packet *pkt = new config_packet; pkt->setup (vpn_packet::PT_RESET, conf->id); - send_vpn_packet (pkt, si, IPTOS_MINCOST); + vpn->send_vpn_packet (pkt, si, IPTOS_MINCOST); delete pkt; } @@ -583,31 +611,20 @@ { auth_req_packet *pkt = new auth_req_packet (conf->id, initiate, THISNODE->protocols); - protocol = best_protocol (THISNODE->protocols & conf->protocols); - - // mask out protocols we cannot establish - if (!conf->udp_port) protocol &= ~PROT_UDPv4; - if (!conf->tcp_port) protocol &= ~PROT_TCPv4; - - if (protocol) - { - rsachallenge chg; + rsachallenge chg; - rsa_cache.gen (pkt->id, chg); + rsa_cache.gen (pkt->id, chg); - if (0 > RSA_public_encrypt (sizeof chg, - (unsigned char *)&chg, (unsigned char *)&pkt->encr, - conf->rsa_key, RSA_PKCS1_OAEP_PADDING)) - fatal ("RSA_public_encrypt error"); + if (0 > RSA_public_encrypt (sizeof chg, + (unsigned char *)&chg, (unsigned char *)&pkt->encr, + conf->rsa_key, RSA_PKCS1_OAEP_PADDING)) + fatal ("RSA_public_encrypt error"); - slog (L_TRACE, ">>%d PT_AUTH_REQ [%s]", conf->id, (const char *)si); + slog (L_TRACE, ">>%d PT_AUTH_REQ [%s]", conf->id, (const char *)si); - send_vpn_packet (pkt, si, IPTOS_RELIABILITY); // rsa is very very costly + vpn->send_vpn_packet (pkt, si, IPTOS_RELIABILITY | IPTOS_LOWDELAY); // rsa is very very costly - delete pkt; - } - else - ; // silently fail + delete pkt; } void @@ -623,7 +640,7 @@ slog (L_TRACE, ">>%d PT_AUTH_RES [%s]", conf->id, (const char *)si); - send_vpn_packet (pkt, si, IPTOS_RELIABILITY); // rsa is very very costly + vpn->send_vpn_packet (pkt, si, IPTOS_RELIABILITY); // rsa is very very costly delete pkt; } @@ -637,40 +654,43 @@ connect_info_packet *r = new connect_info_packet (conf->id, rid, rsi, rprotocols); r->hmac_set (octx); - send_vpn_packet (r, si); + vpn->send_vpn_packet (r, si); delete r; } void -connection::establish_connection_cb (tstamp &ts) +connection::establish_connection_cb (time_watcher &w) { if (ictx || conf == THISNODE || connectmode == conf_node::C_NEVER || connectmode == conf_node::C_DISABLED) - ts = TSTAMP_CANCEL; - else if (ts <= NOW) + w.at = TSTAMP_CANCEL; + else if (w.at <= NOW) { double retry_int = double (retry_cnt & 3 ? (retry_cnt & 3) : 1 << (retry_cnt >> 2)) * 0.6; if (retry_int < 3600 * 8) retry_cnt++; - ts = NOW + retry_int; + w.at = NOW + retry_int; - if (conf->hostname) + reset_si (); + + if (si.prot && !si.host) + vpn->connect_request (conf->id); + else { - reset_dstaddr (); - if (si.host && auth_rate_limiter.can (si)) - { - if (retry_cnt < 4) - send_auth_request (si, true); - else - send_ping (si, 0); - } + const sockinfo &dsi = forward_si (si); + + if (dsi.valid () && auth_rate_limiter.can (dsi)) + { + if (retry_cnt < 4) + send_auth_request (dsi, true); + else + send_ping (dsi, 0); + } } - else - vpn->connect_request (conf->id); } } @@ -709,9 +729,9 @@ } void -connection::rekey_cb (tstamp &ts) +connection::rekey_cb (time_watcher &w) { - ts = TSTAMP_CANCEL; + w.at = TSTAMP_CANCEL; reset_connection (); establish_connection (); @@ -729,7 +749,7 @@ tos = (*pkt)[15] & IPTOS_TOS_MASK; p->setup (this, broadcast ? 0 : conf->id, &((*pkt)[6 + 6]), pkt->len - 6 - 6, ++oseqno); // skip 2 macs - send_vpn_packet (p, si, tos); + vpn->send_vpn_packet (p, si, tos); delete p; @@ -751,6 +771,14 @@ } } +void connection::inject_vpn_packet (vpn_packet *pkt, int tos) +{ + if (ictx && octx) + vpn->send_vpn_packet (pkt, si, tos); + else + establish_connection (); +} + void connection::recv_vpn_packet (vpn_packet *pkt, const sockinfo &rsi) { @@ -822,7 +850,7 @@ else { retry_cnt = 0; - establish_connection.set (NOW + 8); //? ;) + establish_connection.start (NOW + 8); //? ;) keepalive.reset (); rekey.reset (); @@ -887,9 +915,10 @@ iseqno.reset (ntohl (*(u32 *)&chg[CHG_SEQNO]) & 0x7fffffff); // at least 2**31 sequence numbers are valid si = rsi; + protocol = rsi.prot; - rekey.set (NOW + ::conf.rekey); - keepalive.set (NOW + ::conf.keepalive); + rekey.start (NOW + ::conf.rekey); + keepalive.start (NOW + ::conf.keepalive); // send queued packets while (tap_packet *p = queue.get ()) @@ -900,9 +929,8 @@ connectmode = conf->connectmode; - slog (L_INFO, _("%s(%s): %s connection established, protocol version %d.%d"), + slog (L_INFO, _("%s(%s): connection established, protocol version %d.%d"), conf->nodename, (const char *)rsi, - strprotocol (protocol), p->prot_major, p->prot_minor); if (::conf.script_node_up) @@ -978,8 +1006,8 @@ connect_req_packet *p = (connect_req_packet *) pkt; assert (p->id > 0 && p->id <= vpn->conns.size ()); // hmac-auth does not mean we accept anything - conf->protocols = p->protocols; connection *c = vpn->conns[p->id - 1]; + conf->protocols = p->protocols; slog (L_TRACE, "<<%d PT_CONNECT_REQ(%d) [%d]\n", conf->id, p->id, c->ictx && c->octx); @@ -1001,13 +1029,20 @@ connect_info_packet *p = (connect_info_packet *) pkt; assert (p->id > 0 && p->id <= vpn->conns.size ()); // hmac-auth does not mean we accept anything - conf->protocols = p->protocols; + connection *c = vpn->conns[p->id - 1]; + c->conf->protocols = p->protocols; + protocol = best_protocol (c->conf->protocols & THISNODE->protocols & p->si.supported_protocols (c->conf)); + p->si.upgrade_protocol (protocol, c->conf); + slog (L_TRACE, "<<%d PT_CONNECT_INFO(%d,%s) (%d)", conf->id, p->id, (const char *)p->si, !c->ictx && !c->octx); - c->send_auth_request (p->si, true); + const sockinfo &dsi = forward_si (p->si); + + if (dsi.valid ()) + c->send_auth_request (dsi, true); } break; @@ -1018,7 +1053,7 @@ } } -void connection::keepalive_cb (tstamp &ts) +void connection::keepalive_cb (time_watcher &w) { if (NOW >= last_activity + ::conf.keepalive + 30) { @@ -1026,12 +1061,12 @@ establish_connection (); } else if (NOW < last_activity + ::conf.keepalive) - ts = last_activity + ::conf.keepalive; + w.at = last_activity + ::conf.keepalive; else if (conf->connectmode != conf_node::C_ONDEMAND || THISNODE->connectmode != conf_node::C_ONDEMAND) { send_ping (si); - ts = NOW + 5; + w.at = NOW + 5; } else reset_connection (); @@ -1043,7 +1078,7 @@ slog (L_TRACE, ">>%d PT_CONNECT_REQ(%d)", conf->id, id); p->hmac_set (octx); - send_vpn_packet (p, si); + vpn->send_vpn_packet (p, si); delete p; } @@ -1077,26 +1112,6 @@ return ::conf.script_node_up ? ::conf.script_node_down : "node-down"; } -// send a vpn packet out to other hosts -void -connection::send_vpn_packet (vpn_packet *pkt, const sockinfo &si, int tos) -{ - switch (protocol) - { - case PROT_IPv4: - vpn->send_ipv4_packet (pkt, si, tos); - break; - - case PROT_UDPv4: - vpn->send_udpv4_packet (pkt, si, tos); - break; - - case PROT_TCPv4: - vpn->send_tcpv4_packet (pkt, si, tos); - break; - } -} - connection::connection(struct vpn *vpn_) : vpn(vpn_) , rekey (this, &connection::rekey_cb)