Logging: consistent capitalization and typo fixes

This commit is contained in:
dr|z3d 2021-09-12 19:42:24 +00:00
parent a5968a484b
commit 950234cd66
25 changed files with 792 additions and 792 deletions

View file

@ -32,7 +32,7 @@ void SubscribeToEvents()
Result = pNetworkListManager->IsConnectedToInternet(&IsConnect); Result = pNetworkListManager->IsConnectedToInternet(&IsConnect);
if (SUCCEEDED(Result)) { if (SUCCEEDED(Result)) {
i2p::transport::transports.SetOnline (true); i2p::transport::transports.SetOnline (true);
LogPrint(eLogInfo, "NetState: current state: ", IsConnect == VARIANT_TRUE ? "connected" : "disconnected"); LogPrint(eLogInfo, "NetState: Current state: ", IsConnect == VARIANT_TRUE ? "connected" : "disconnected");
} }
Result = pNetworkListManager->QueryInterface(IID_IConnectionPointContainer, (void **)&pCPContainer); Result = pNetworkListManager->QueryInterface(IID_IConnectionPointContainer, (void **)&pCPContainer);
@ -79,7 +79,7 @@ void UnSubscribeFromEvents()
} }
catch (std::exception& ex) catch (std::exception& ex)
{ {
LogPrint (eLogError, "NetState: received exception: ", ex.what ()); LogPrint (eLogError, "NetState: Received exception: ", ex.what ());
} }
} }

View file

@ -118,26 +118,26 @@ namespace util
i2p::log::Logger().SetLogLevel(loglevel); i2p::log::Logger().SetLogLevel(loglevel);
if (logstream) { if (logstream) {
LogPrint(eLogInfo, "Log: will send messages to std::ostream"); LogPrint(eLogInfo, "Log: Sending messages to std::ostream");
i2p::log::Logger().SendTo (logstream); i2p::log::Logger().SendTo (logstream);
} else if (logs == "file") { } else if (logs == "file") {
if (logfile == "") if (logfile == "")
logfile = i2p::fs::DataDirPath("i2pd.log"); logfile = i2p::fs::DataDirPath("i2pd.log");
LogPrint(eLogInfo, "Log: will send messages to ", logfile); LogPrint(eLogInfo, "Log: Sending messages to ", logfile);
i2p::log::Logger().SendTo (logfile); i2p::log::Logger().SendTo (logfile);
#ifndef _WIN32 #ifndef _WIN32
} else if (logs == "syslog") { } else if (logs == "syslog") {
LogPrint(eLogInfo, "Log: will send messages to syslog"); LogPrint(eLogInfo, "Log: Sending messages to syslog");
i2p::log::Logger().SendTo("i2pd", LOG_DAEMON); i2p::log::Logger().SendTo("i2pd", LOG_DAEMON);
#endif #endif
} else { } else {
// use stdout -- default // use stdout -- default
} }
LogPrint(eLogNone, "i2pd v", VERSION, " starting"); LogPrint(eLogNone, "i2pd v", VERSION, " starting...");
LogPrint(eLogDebug, "FS: main config file: ", config); LogPrint(eLogDebug, "FS: Main config file: ", config);
LogPrint(eLogDebug, "FS: data directory: ", datadir); LogPrint(eLogDebug, "FS: Data directory: ", datadir);
LogPrint(eLogDebug, "FS: certificates directory: ", certsdir); LogPrint(eLogDebug, "FS: Certificates directory: ", certsdir);
bool precomputation; i2p::config::GetOption("precomputation.elgamal", precomputation); bool precomputation; i2p::config::GetOption("precomputation.elgamal", precomputation);
bool aesni; i2p::config::GetOption("cpuext.aesni", aesni); bool aesni; i2p::config::GetOption("cpuext.aesni", aesni);
@ -204,7 +204,7 @@ namespace util
uint16_t port; i2p::config::GetOption("port", port); uint16_t port; i2p::config::GetOption("port", port);
if (!i2p::config::IsDefault("port")) if (!i2p::config::IsDefault("port"))
{ {
LogPrint(eLogInfo, "Daemon: accepting incoming connections at port ", port); LogPrint(eLogInfo, "Daemon: Accepting incoming connections at port ", port);
i2p::context.UpdatePort (port); i2p::context.UpdatePort (port);
} }
i2p::context.SetSupportsV6 (ipv6); i2p::context.SetSupportsV6 (ipv6);
@ -252,7 +252,7 @@ namespace util
bool isFloodfill; i2p::config::GetOption("floodfill", isFloodfill); bool isFloodfill; i2p::config::GetOption("floodfill", isFloodfill);
if (isFloodfill) { if (isFloodfill) {
LogPrint(eLogInfo, "Daemon: router will be floodfill"); LogPrint(eLogInfo, "Daemon: Router configured as floodfill");
i2p::context.SetFloodfill (true); i2p::context.SetFloodfill (true);
} }
else else
@ -267,7 +267,7 @@ namespace util
if (bandwidth[0] >= 'K' && bandwidth[0] <= 'X') if (bandwidth[0] >= 'K' && bandwidth[0] <= 'X')
{ {
i2p::context.SetBandwidth (bandwidth[0]); i2p::context.SetBandwidth (bandwidth[0]);
LogPrint(eLogInfo, "Daemon: bandwidth set to ", i2p::context.GetBandwidthLimit (), "KBps"); LogPrint(eLogInfo, "Daemon: Bandwidth set to ", i2p::context.GetBandwidthLimit (), "KBps");
} }
else else
{ {
@ -275,23 +275,23 @@ namespace util
if (value > 0) if (value > 0)
{ {
i2p::context.SetBandwidth (value); i2p::context.SetBandwidth (value);
LogPrint(eLogInfo, "Daemon: bandwidth set to ", i2p::context.GetBandwidthLimit (), " KBps"); LogPrint(eLogInfo, "Daemon: Bandwidth set to ", i2p::context.GetBandwidthLimit (), " KBps");
} }
else else
{ {
LogPrint(eLogInfo, "Daemon: unexpected bandwidth ", bandwidth, ". Set to 'low'"); LogPrint(eLogInfo, "Daemon: Unexpected bandwidth ", bandwidth, ". Set to 'low'");
i2p::context.SetBandwidth (i2p::data::CAPS_FLAG_LOW_BANDWIDTH2); i2p::context.SetBandwidth (i2p::data::CAPS_FLAG_LOW_BANDWIDTH2);
} }
} }
} }
else if (isFloodfill) else if (isFloodfill)
{ {
LogPrint(eLogInfo, "Daemon: floodfill bandwidth set to 'extra'"); LogPrint(eLogInfo, "Daemon: Floodfill bandwidth set to 'extra'");
i2p::context.SetBandwidth (i2p::data::CAPS_FLAG_EXTRA_BANDWIDTH2); i2p::context.SetBandwidth (i2p::data::CAPS_FLAG_EXTRA_BANDWIDTH2);
} }
else else
{ {
LogPrint(eLogInfo, "Daemon: bandwidth set to 'low'"); LogPrint(eLogInfo, "Daemon: Bandwidth set to 'low'");
i2p::context.SetBandwidth (i2p::data::CAPS_FLAG_LOW_BANDWIDTH2); i2p::context.SetBandwidth (i2p::data::CAPS_FLAG_LOW_BANDWIDTH2);
} }
@ -301,12 +301,12 @@ namespace util
std::string family; i2p::config::GetOption("family", family); std::string family; i2p::config::GetOption("family", family);
i2p::context.SetFamily (family); i2p::context.SetFamily (family);
if (family.length () > 0) if (family.length () > 0)
LogPrint(eLogInfo, "Daemon: family set to ", family); LogPrint(eLogInfo, "Daemon: Router family set to ", family);
bool trust; i2p::config::GetOption("trust.enabled", trust); bool trust; i2p::config::GetOption("trust.enabled", trust);
if (trust) if (trust)
{ {
LogPrint(eLogInfo, "Daemon: explicit trust enabled"); LogPrint(eLogInfo, "Daemon: Explicit trust enabled");
std::string fam; i2p::config::GetOption("trust.family", fam); std::string fam; i2p::config::GetOption("trust.family", fam);
std::string routers; i2p::config::GetOption("trust.routers", routers); std::string routers; i2p::config::GetOption("trust.routers", routers);
bool restricted = false; bool restricted = false;
@ -336,18 +336,18 @@ namespace util
pos = comma + 1; pos = comma + 1;
} }
while (comma != std::string::npos); while (comma != std::string::npos);
LogPrint(eLogInfo, "Daemon: setting restricted routes to use ", idents.size(), " trusted routers"); LogPrint(eLogInfo, "Daemon: Setting restricted routes to use ", idents.size(), " trusted routers");
i2p::transport::transports.RestrictRoutesToRouters(idents); i2p::transport::transports.RestrictRoutesToRouters(idents);
restricted = idents.size() > 0; restricted = idents.size() > 0;
} }
if(!restricted) if(!restricted)
LogPrint(eLogError, "Daemon: no trusted routers of families specified"); LogPrint(eLogError, "Daemon: No trusted routers of families specified");
} }
bool hidden; i2p::config::GetOption("trust.hidden", hidden); bool hidden; i2p::config::GetOption("trust.hidden", hidden);
if (hidden) if (hidden)
{ {
LogPrint(eLogInfo, "Daemon: using hidden mode"); LogPrint(eLogInfo, "Daemon: Hidden mode enabled");
i2p::data::netdb.SetHidden(true); i2p::data::netdb.SetHidden(true);
} }
@ -360,7 +360,7 @@ namespace util
bool Daemon_Singleton::start() bool Daemon_Singleton::start()
{ {
i2p::log::Logger().Start(); i2p::log::Logger().Start();
LogPrint(eLogInfo, "Daemon: starting NetDB"); LogPrint(eLogInfo, "Daemon: Starting NetDB");
i2p::data::netdb.Start(); i2p::data::netdb.Start();
bool upnp; i2p::config::GetOption("upnp.enabled", upnp); bool upnp; i2p::config::GetOption("upnp.enabled", upnp);
@ -379,9 +379,9 @@ namespace util
bool ntcp2; i2p::config::GetOption("ntcp2.enabled", ntcp2); bool ntcp2; i2p::config::GetOption("ntcp2.enabled", ntcp2);
bool ssu; i2p::config::GetOption("ssu", ssu); bool ssu; i2p::config::GetOption("ssu", ssu);
bool checkInReserved; i2p::config::GetOption("reservedrange", checkInReserved); bool checkInReserved; i2p::config::GetOption("reservedrange", checkInReserved);
LogPrint(eLogInfo, "Daemon: starting Transports"); LogPrint(eLogInfo, "Daemon: Starting Transports");
if(!ssu) LogPrint(eLogInfo, "Daemon: ssu disabled"); if(!ssu) LogPrint(eLogInfo, "Daemon: SSU disabled");
if(!ntcp2) LogPrint(eLogInfo, "Daemon: ntcp2 disabled"); if(!ntcp2) LogPrint(eLogInfo, "Daemon: NTCP2 disabled");
i2p::transport::transports.SetCheckReserved(checkInReserved); i2p::transport::transports.SetCheckReserved(checkInReserved);
i2p::transport::transports.Start(ntcp2, ssu); i2p::transport::transports.Start(ntcp2, ssu);
@ -389,7 +389,7 @@ namespace util
LogPrint(eLogInfo, "Daemon: Transports started"); LogPrint(eLogInfo, "Daemon: Transports started");
else else
{ {
LogPrint(eLogError, "Daemon: failed to start Transports"); LogPrint(eLogError, "Daemon: Failed to start Transports");
/** shut down netdb right away */ /** shut down netdb right away */
i2p::transport::transports.Stop(); i2p::transport::transports.Stop();
i2p::data::netdb.Stop(); i2p::data::netdb.Stop();
@ -400,7 +400,7 @@ namespace util
if (http) { if (http) {
std::string httpAddr; i2p::config::GetOption("http.address", httpAddr); std::string httpAddr; i2p::config::GetOption("http.address", httpAddr);
uint16_t httpPort; i2p::config::GetOption("http.port", httpPort); uint16_t httpPort; i2p::config::GetOption("http.port", httpPort);
LogPrint(eLogInfo, "Daemon: starting webconsole at ", httpAddr, ":", httpPort); LogPrint(eLogInfo, "Daemon: Starting Webconsole at ", httpAddr, ":", httpPort);
try try
{ {
d.httpServer = std::unique_ptr<i2p::http::HTTPServer>(new i2p::http::HTTPServer(httpAddr, httpPort)); d.httpServer = std::unique_ptr<i2p::http::HTTPServer>(new i2p::http::HTTPServer(httpAddr, httpPort));
@ -408,16 +408,16 @@ namespace util
} }
catch (std::exception& ex) catch (std::exception& ex)
{ {
LogPrint (eLogError, "Daemon: failed to start webconsole: ", ex.what ()); LogPrint (eLogError, "Daemon: Failed to start Webconsole: ", ex.what ());
ThrowFatal ("Unable to start webconsole at ", httpAddr, ":", httpPort, ": ", ex.what ()); ThrowFatal ("Unable to start webconsole at ", httpAddr, ":", httpPort, ": ", ex.what ());
} }
} }
LogPrint(eLogInfo, "Daemon: starting Tunnels"); LogPrint(eLogInfo, "Daemon: Starting Tunnels");
i2p::tunnel::tunnels.Start(); i2p::tunnel::tunnels.Start();
LogPrint(eLogInfo, "Daemon: starting Client"); LogPrint(eLogInfo, "Daemon: Starting Client");
i2p::client::context.Start (); i2p::client::context.Start ();
// I2P Control Protocol // I2P Control Protocol
@ -425,7 +425,7 @@ namespace util
if (i2pcontrol) { if (i2pcontrol) {
std::string i2pcpAddr; i2p::config::GetOption("i2pcontrol.address", i2pcpAddr); std::string i2pcpAddr; i2p::config::GetOption("i2pcontrol.address", i2pcpAddr);
uint16_t i2pcpPort; i2p::config::GetOption("i2pcontrol.port", i2pcpPort); uint16_t i2pcpPort; i2p::config::GetOption("i2pcontrol.port", i2pcpPort);
LogPrint(eLogInfo, "Daemon: starting I2PControl at ", i2pcpAddr, ":", i2pcpPort); LogPrint(eLogInfo, "Daemon: Starting I2PControl at ", i2pcpAddr, ":", i2pcpPort);
try try
{ {
d.m_I2PControlService = std::unique_ptr<i2p::client::I2PControlService>(new i2p::client::I2PControlService (i2pcpAddr, i2pcpPort)); d.m_I2PControlService = std::unique_ptr<i2p::client::I2PControlService>(new i2p::client::I2PControlService (i2pcpAddr, i2pcpPort));
@ -433,7 +433,7 @@ namespace util
} }
catch (std::exception& ex) catch (std::exception& ex)
{ {
LogPrint (eLogError, "Daemon: failed to start I2PControl: ", ex.what ()); LogPrint (eLogError, "Daemon: Failed to start I2PControl: ", ex.what ());
ThrowFatal ("Unable to start I2PControl service at ", i2pcpAddr, ":", i2pcpPort, ": ", ex.what ()); ThrowFatal ("Unable to start I2PControl service at ", i2pcpAddr, ":", i2pcpPort, ": ", ex.what ());
} }
} }
@ -442,10 +442,10 @@ namespace util
bool Daemon_Singleton::stop() bool Daemon_Singleton::stop()
{ {
LogPrint(eLogInfo, "Daemon: shutting down"); LogPrint(eLogInfo, "Daemon: Shutting down");
LogPrint(eLogInfo, "Daemon: stopping Client"); LogPrint(eLogInfo, "Daemon: Stopping Client");
i2p::client::context.Stop(); i2p::client::context.Stop();
LogPrint(eLogInfo, "Daemon: stopping Tunnels"); LogPrint(eLogInfo, "Daemon: Stopping Tunnels");
i2p::tunnel::tunnels.Stop(); i2p::tunnel::tunnels.Stop();
if (d.UPnP) if (d.UPnP)
@ -460,18 +460,18 @@ namespace util
d.m_NTPSync = nullptr; d.m_NTPSync = nullptr;
} }
LogPrint(eLogInfo, "Daemon: stopping Transports"); LogPrint(eLogInfo, "Daemon: Stopping Transports");
i2p::transport::transports.Stop(); i2p::transport::transports.Stop();
LogPrint(eLogInfo, "Daemon: stopping NetDB"); LogPrint(eLogInfo, "Daemon: Stopping NetDB");
i2p::data::netdb.Stop(); i2p::data::netdb.Stop();
if (d.httpServer) { if (d.httpServer) {
LogPrint(eLogInfo, "Daemon: stopping HTTP Server"); LogPrint(eLogInfo, "Daemon: Stopping HTTP Server");
d.httpServer->Stop(); d.httpServer->Stop();
d.httpServer = nullptr; d.httpServer = nullptr;
} }
if (d.m_I2PControlService) if (d.m_I2PControlService)
{ {
LogPrint(eLogInfo, "Daemon: stopping I2PControl"); LogPrint(eLogInfo, "Daemon: Stopping I2PControl");
d.m_I2PControlService->Stop (); d.m_I2PControlService->Stop ();
d.m_I2PControlService = nullptr; d.m_I2PControlService = nullptr;
} }

View file

@ -48,10 +48,10 @@ namespace client
if (i2pcp_key.at(0) != '/') if (i2pcp_key.at(0) != '/')
i2pcp_key = i2p::fs::DataDirPath(i2pcp_key); i2pcp_key = i2p::fs::DataDirPath(i2pcp_key);
if (!i2p::fs::Exists (i2pcp_crt) || !i2p::fs::Exists (i2pcp_key)) { if (!i2p::fs::Exists (i2pcp_crt) || !i2p::fs::Exists (i2pcp_key)) {
LogPrint (eLogInfo, "I2PControl: creating new certificate for control connection"); LogPrint (eLogInfo, "I2PControl: Creating new certificate for control connection");
CreateCertificate (i2pcp_crt.c_str(), i2pcp_key.c_str()); CreateCertificate (i2pcp_crt.c_str(), i2pcp_key.c_str());
} else { } else {
LogPrint(eLogDebug, "I2PControl: using cert from ", i2pcp_crt); LogPrint(eLogDebug, "I2PControl: Using cert from ", i2pcp_crt);
} }
m_SSLContext.set_options (boost::asio::ssl::context::default_workarounds | boost::asio::ssl::context::no_sslv2 | boost::asio::ssl::context::single_dh_use); m_SSLContext.set_options (boost::asio::ssl::context::default_workarounds | boost::asio::ssl::context::no_sslv2 | boost::asio::ssl::context::single_dh_use);
m_SSLContext.use_certificate_file (i2pcp_crt, boost::asio::ssl::context::pem); m_SSLContext.use_certificate_file (i2pcp_crt, boost::asio::ssl::context::pem);
@ -142,7 +142,7 @@ namespace client
try { try {
m_Service.run (); m_Service.run ();
} catch (std::exception& ex) { } catch (std::exception& ex) {
LogPrint (eLogError, "I2PControl: runtime exception: ", ex.what ()); LogPrint (eLogError, "I2PControl: Runtime exception: ", ex.what ());
} }
} }
} }
@ -160,10 +160,10 @@ namespace client
Accept (); Accept ();
if (ecode) { if (ecode) {
LogPrint (eLogError, "I2PControl: accept error: ", ecode.message ()); LogPrint (eLogError, "I2PControl: Accept error: ", ecode.message ());
return; return;
} }
LogPrint (eLogDebug, "I2PControl: new request from ", socket->lowest_layer ().remote_endpoint ()); LogPrint (eLogDebug, "I2PControl: New request from ", socket->lowest_layer ().remote_endpoint ());
Handshake (socket); Handshake (socket);
} }
@ -176,7 +176,7 @@ namespace client
void I2PControlService::HandleHandshake (const boost::system::error_code& ecode, std::shared_ptr<ssl_socket> socket) void I2PControlService::HandleHandshake (const boost::system::error_code& ecode, std::shared_ptr<ssl_socket> socket)
{ {
if (ecode) { if (ecode) {
LogPrint (eLogError, "I2PControl: handshake error: ", ecode.message ()); LogPrint (eLogError, "I2PControl: Handshake error: ", ecode.message ());
return; return;
} }
//std::this_thread::sleep_for (std::chrono::milliseconds(5)); //std::this_thread::sleep_for (std::chrono::milliseconds(5));
@ -202,7 +202,7 @@ namespace client
{ {
if (ecode) if (ecode)
{ {
LogPrint (eLogError, "I2PControl: read error: ", ecode.message ()); LogPrint (eLogError, "I2PControl: Read error: ", ecode.message ());
return; return;
} }
else else
@ -225,7 +225,7 @@ namespace client
} }
if (ss.eof ()) if (ss.eof ())
{ {
LogPrint (eLogError, "I2PControl: malformed request, HTTP header expected"); LogPrint (eLogError, "I2PControl: Malformed request, HTTP header expected");
return; // TODO: return; // TODO:
} }
std::streamoff rem = contentLength + ss.tellg () - bytes_transferred; // more bytes to read std::streamoff rem = contentLength + ss.tellg () - bytes_transferred; // more bytes to read
@ -250,7 +250,7 @@ namespace client
} }
else else
{ {
LogPrint (eLogWarning, "I2PControl: unknown method ", method); LogPrint (eLogWarning, "I2PControl: Unknown method ", method);
response << "{\"id\":null,\"error\":"; response << "{\"id\":null,\"error\":";
response << "{\"code\":-32601,\"message\":\"Method not found\"},"; response << "{\"code\":-32601,\"message\":\"Method not found\"},";
response << "\"jsonrpc\":\"2.0\"}"; response << "\"jsonrpc\":\"2.0\"}";
@ -259,7 +259,7 @@ namespace client
} }
catch (std::exception& ex) catch (std::exception& ex)
{ {
LogPrint (eLogError, "I2PControl: exception when handle request: ", ex.what ()); LogPrint (eLogError, "I2PControl: Exception when handle request: ", ex.what ());
std::ostringstream response; std::ostringstream response;
response << "{\"id\":null,\"error\":"; response << "{\"id\":null,\"error\":";
response << "{\"code\":-32700,\"message\":\"" << ex.what () << "\"},"; response << "{\"code\":-32700,\"message\":\"" << ex.what () << "\"},";
@ -268,7 +268,7 @@ namespace client
} }
catch (...) catch (...)
{ {
LogPrint (eLogError, "I2PControl: handle request unknown exception"); LogPrint (eLogError, "I2PControl: Handle request unknown exception");
} }
} }
} }
@ -329,7 +329,7 @@ namespace client
std::shared_ptr<ssl_socket> socket, std::shared_ptr<I2PControlBuffer> buf) std::shared_ptr<ssl_socket> socket, std::shared_ptr<I2PControlBuffer> buf)
{ {
if (ecode) { if (ecode) {
LogPrint (eLogError, "I2PControl: write error: ", ecode.message ()); LogPrint (eLogError, "I2PControl: Write error: ", ecode.message ());
} }
} }
@ -379,7 +379,7 @@ namespace client
void I2PControlService::PasswordHandler (const std::string& value) void I2PControlService::PasswordHandler (const std::string& value)
{ {
LogPrint (eLogWarning, "I2PControl: new password=", value, ", to make it persistent you should update your config!"); LogPrint (eLogWarning, "I2PControl: New password=", value, ", to make it persistent you should update your config!");
m_Password = value; m_Password = value;
m_Tokens.clear (); m_Tokens.clear ();
} }
@ -395,8 +395,8 @@ namespace client
auto it1 = m_RouterInfoHandlers.find (it->first); auto it1 = m_RouterInfoHandlers.find (it->first);
if (it1 != m_RouterInfoHandlers.end ()) if (it1 != m_RouterInfoHandlers.end ())
{ {
if (!first) results << ","; if (!first) results << ",";
else first = false; else first = false;
(this->*(it1->second))(results); (this->*(it1->second))(results);
} }
else else
@ -577,25 +577,25 @@ namespace client
// save cert // save cert
if ((f = fopen (crt_path, "wb")) != NULL) { if ((f = fopen (crt_path, "wb")) != NULL) {
LogPrint (eLogInfo, "I2PControl: saving new cert to ", crt_path); LogPrint (eLogInfo, "I2PControl: Saving new cert to ", crt_path);
PEM_write_X509 (f, x509); PEM_write_X509 (f, x509);
fclose (f); fclose (f);
} else { } else {
LogPrint (eLogError, "I2PControl: can't write cert: ", strerror(errno)); LogPrint (eLogError, "I2PControl: Can't write cert: ", strerror(errno));
} }
// save key // save key
if ((f = fopen (key_path, "wb")) != NULL) { if ((f = fopen (key_path, "wb")) != NULL) {
LogPrint (eLogInfo, "I2PControl: saving cert key to ", key_path); LogPrint (eLogInfo, "I2PControl: Saving cert key to ", key_path);
PEM_write_PrivateKey (f, pkey, NULL, NULL, 0, NULL, NULL); PEM_write_PrivateKey (f, pkey, NULL, NULL, 0, NULL, NULL);
fclose (f); fclose (f);
} else { } else {
LogPrint (eLogError, "I2PControl: can't write key: ", strerror(errno)); LogPrint (eLogError, "I2PControl: Can't write key: ", strerror(errno));
} }
X509_free (x509); X509_free (x509);
} else { } else {
LogPrint (eLogError, "I2PControl: can't create RSA key for certificate"); LogPrint (eLogError, "I2PControl: Can't create RSA key for certificate");
} }
EVP_PKEY_free (pkey); EVP_PKEY_free (pkey);
} }

View file

@ -29,7 +29,7 @@ namespace transport
{ {
if (m_IsRunning) if (m_IsRunning)
{ {
LogPrint(eLogInfo, "UPnP: stopping"); LogPrint(eLogInfo, "UPnP: Stopping");
m_IsRunning = false; m_IsRunning = false;
m_Timer.cancel (); m_Timer.cancel ();
m_Service.stop (); m_Service.stop ();
@ -46,7 +46,7 @@ namespace transport
void UPnP::Start() void UPnP::Start()
{ {
m_IsRunning = true; m_IsRunning = true;
LogPrint(eLogInfo, "UPnP: starting"); LogPrint(eLogInfo, "UPnP: Starting");
m_Service.post (std::bind (&UPnP::Discover, this)); m_Service.post (std::bind (&UPnP::Discover, this));
std::unique_lock<std::mutex> l(m_StartedMutex); std::unique_lock<std::mutex> l(m_StartedMutex);
m_Thread.reset (new std::thread (std::bind (&UPnP::Run, this))); m_Thread.reset (new std::thread (std::bind (&UPnP::Run, this)));
@ -72,7 +72,7 @@ namespace transport
} }
catch (std::exception& ex) catch (std::exception& ex)
{ {
LogPrint (eLogError, "UPnP: runtime exception: ", ex.what ()); LogPrint (eLogError, "UPnP: Runtime exception: ", ex.what ());
PortMapping (); PortMapping ();
} }
} }
@ -106,7 +106,7 @@ namespace transport
if (isError) if (isError)
{ {
LogPrint (eLogError, "UPnP: unable to discover Internet Gateway Devices: error ", err); LogPrint (eLogError, "UPnP: Unable to discover Internet Gateway Devices: error ", err);
return; return;
} }
@ -117,22 +117,22 @@ namespace transport
err = UPNP_GetExternalIPAddress (m_upnpUrls.controlURL, m_upnpData.first.servicetype, m_externalIPAddress); err = UPNP_GetExternalIPAddress (m_upnpUrls.controlURL, m_upnpData.first.servicetype, m_externalIPAddress);
if(err != UPNPCOMMAND_SUCCESS) if(err != UPNPCOMMAND_SUCCESS)
{ {
LogPrint (eLogError, "UPnP: unable to get external address: error ", err); LogPrint (eLogError, "UPnP: Unable to get external address: error ", err);
return; return;
} }
else else
{ {
LogPrint (eLogError, "UPnP: found Internet Gateway Device ", m_upnpUrls.controlURL); LogPrint (eLogError, "UPnP: Found Internet Gateway Device ", m_upnpUrls.controlURL);
if (!m_externalIPAddress[0]) if (!m_externalIPAddress[0])
{ {
LogPrint (eLogError, "UPnP: found Internet Gateway Device doesn't know our external address"); LogPrint (eLogError, "UPnP: Found Internet Gateway Device doesn't know our external address");
return; return;
} }
} }
} }
else else
{ {
LogPrint (eLogError, "UPnP: unable to find valid Internet Gateway Device: error ", err); LogPrint (eLogError, "UPnP: Unable to find valid Internet Gateway Device: error ", err);
return; return;
} }
@ -183,7 +183,7 @@ namespace transport
err = CheckMapping (strPort.c_str (), strType.c_str ()); err = CheckMapping (strPort.c_str (), strType.c_str ());
if (err != UPNPCOMMAND_SUCCESS) // if mapping not found if (err != UPNPCOMMAND_SUCCESS) // if mapping not found
{ {
LogPrint (eLogDebug, "UPnP: possibly port ", strPort, " is not forwarded: return code ", err); LogPrint (eLogDebug, "UPnP: Port ", strPort, " is possibly not forwarded: return code ", err);
#if ((MINIUPNPC_API_VERSION >= 8) || defined (UPNPDISCOVER_SUCCESS)) #if ((MINIUPNPC_API_VERSION >= 8) || defined (UPNPDISCOVER_SUCCESS))
err = UPNP_AddPortMapping (m_upnpUrls.controlURL, m_upnpData.first.servicetype, strPort.c_str (), strPort.c_str (), m_NetworkAddr, strDesc.c_str (), strType.c_str (), NULL, NULL); err = UPNP_AddPortMapping (m_upnpUrls.controlURL, m_upnpData.first.servicetype, strPort.c_str (), strPort.c_str (), m_NetworkAddr, strDesc.c_str (), strType.c_str (), NULL, NULL);
@ -192,18 +192,18 @@ namespace transport
#endif #endif
if (err != UPNPCOMMAND_SUCCESS) if (err != UPNPCOMMAND_SUCCESS)
{ {
LogPrint (eLogError, "UPnP: port forwarding to ", m_NetworkAddr, ":", strPort, " failed: return code ", err); LogPrint (eLogError, "UPnP: Port forwarding to ", m_NetworkAddr, ":", strPort, " failed: return code ", err);
return; return;
} }
else else
{ {
LogPrint (eLogInfo, "UPnP: port successfully forwarded (", m_externalIPAddress ,":", strPort, " type ", strType, " -> ", m_NetworkAddr ,":", strPort ,")"); LogPrint (eLogInfo, "UPnP: Port successfully forwarded (", m_externalIPAddress ,":", strPort, " type ", strType, " -> ", m_NetworkAddr ,":", strPort ,")");
return; return;
} }
} }
else else
{ {
LogPrint (eLogDebug, "UPnP: external forward from ", m_NetworkAddr, ":", strPort, " exists on current Internet Gateway Device"); LogPrint (eLogDebug, "UPnP: External forward from ", m_NetworkAddr, ":", strPort, " exists on current Internet Gateway Device");
return; return;
} }
} }
@ -225,7 +225,7 @@ namespace transport
} }
std::string strType (GetProto (address)), strPort (std::to_string (address->port)); std::string strType (GetProto (address)), strPort (std::to_string (address->port));
int err = UPNPCOMMAND_SUCCESS; int err = UPNPCOMMAND_SUCCESS;
err = CheckMapping (strPort.c_str (), strType.c_str ()); err = CheckMapping (strPort.c_str (), strType.c_str ());
if (err == UPNPCOMMAND_SUCCESS) if (err == UPNPCOMMAND_SUCCESS)
{ {

View file

@ -42,7 +42,7 @@ void handle_signal(int sig)
{ {
i2p::context.SetAcceptsTunnels (false); i2p::context.SetAcceptsTunnels (false);
Daemon.gracefulShutdownInterval = 10*60; // 10 minutes Daemon.gracefulShutdownInterval = 10*60; // 10 minutes
LogPrint(eLogInfo, "Graceful shutdown after ", Daemon.gracefulShutdownInterval, " seconds"); LogPrint(eLogInfo, "Graceful shutdown in ", Daemon.gracefulShutdownInterval, " seconds");
} }
else else
Daemon.running = 0; Daemon.running = 0;
@ -72,7 +72,7 @@ namespace i2p
if (pid < 0) // error if (pid < 0) // error
{ {
LogPrint(eLogError, "Daemon: could not fork: ", strerror(errno)); LogPrint(eLogError, "Daemon: Could not fork: ", strerror(errno));
return false; return false;
} }
@ -81,13 +81,13 @@ namespace i2p
int sid = setsid(); int sid = setsid();
if (sid < 0) if (sid < 0)
{ {
LogPrint(eLogError, "Daemon: could not create process group."); LogPrint(eLogError, "Daemon: Could not create process group.");
return false; return false;
} }
std::string d = i2p::fs::GetDataDir(); std::string d = i2p::fs::GetDataDir();
if (chdir(d.c_str()) != 0) if (chdir(d.c_str()) != 0)
{ {
LogPrint(eLogError, "Daemon: could not chdir: ", strerror(errno)); LogPrint(eLogError, "Daemon: Could not chdir: ", strerror(errno));
return false; return false;
} }
@ -102,14 +102,14 @@ namespace i2p
uint16_t nfiles; i2p::config::GetOption("limits.openfiles", nfiles); uint16_t nfiles; i2p::config::GetOption("limits.openfiles", nfiles);
getrlimit(RLIMIT_NOFILE, &limit); getrlimit(RLIMIT_NOFILE, &limit);
if (nfiles == 0) { if (nfiles == 0) {
LogPrint(eLogInfo, "Daemon: using system limit in ", limit.rlim_cur, " max open files"); LogPrint(eLogInfo, "Daemon: Using system limit in ", limit.rlim_cur, " max open files");
} else if (nfiles <= limit.rlim_max) { } else if (nfiles <= limit.rlim_max) {
limit.rlim_cur = nfiles; limit.rlim_cur = nfiles;
if (setrlimit(RLIMIT_NOFILE, &limit) == 0) { if (setrlimit(RLIMIT_NOFILE, &limit) == 0) {
LogPrint(eLogInfo, "Daemon: set max number of open files to ", LogPrint(eLogInfo, "Daemon: Set max number of open files to ",
nfiles, " (system limit is ", limit.rlim_max, ")"); nfiles, " (system limit is ", limit.rlim_max, ")");
} else { } else {
LogPrint(eLogError, "Daemon: can't set max number of open files: ", strerror(errno)); LogPrint(eLogError, "Daemon: Can't set max number of open files: ", strerror(errno));
} }
} else { } else {
LogPrint(eLogError, "Daemon: limits.openfiles exceeds system limit: ", limit.rlim_max); LogPrint(eLogError, "Daemon: limits.openfiles exceeds system limit: ", limit.rlim_max);
@ -122,11 +122,11 @@ namespace i2p
if (cfsize <= limit.rlim_max) { if (cfsize <= limit.rlim_max) {
limit.rlim_cur = cfsize; limit.rlim_cur = cfsize;
if (setrlimit(RLIMIT_CORE, &limit) != 0) { if (setrlimit(RLIMIT_CORE, &limit) != 0) {
LogPrint(eLogError, "Daemon: can't set max size of coredump: ", strerror(errno)); LogPrint(eLogError, "Daemon: Can't set max size of coredump: ", strerror(errno));
} else if (cfsize == 0) { } else if (cfsize == 0) {
LogPrint(eLogInfo, "Daemon: coredumps disabled"); LogPrint(eLogInfo, "Daemon: coredumps disabled");
} else { } else {
LogPrint(eLogInfo, "Daemon: set max size of core files to ", cfsize / 1024, "Kb"); LogPrint(eLogInfo, "Daemon: Set max size of core files to ", cfsize / 1024, "Kb");
} }
} else { } else {
LogPrint(eLogError, "Daemon: limits.coresize exceeds system limit: ", limit.rlim_max); LogPrint(eLogError, "Daemon: limits.coresize exceeds system limit: ", limit.rlim_max);
@ -143,14 +143,14 @@ namespace i2p
pidFH = open(pidfile.c_str(), O_RDWR | O_CREAT, 0600); pidFH = open(pidfile.c_str(), O_RDWR | O_CREAT, 0600);
if (pidFH < 0) if (pidFH < 0)
{ {
LogPrint(eLogError, "Daemon: could not create pid file ", pidfile, ": ", strerror(errno)); LogPrint(eLogError, "Daemon: Could not create pid file ", pidfile, ": ", strerror(errno));
return false; return false;
} }
#ifndef ANDROID #ifndef ANDROID
if (lockf(pidFH, F_TLOCK, 0) != 0) if (lockf(pidFH, F_TLOCK, 0) != 0)
{ {
LogPrint(eLogError, "Daemon: could not lock pid file ", pidfile, ": ", strerror(errno)); LogPrint(eLogError, "Daemon: Could not lock pid file ", pidfile, ": ", strerror(errno));
return false; return false;
} }
#endif #endif
@ -159,7 +159,7 @@ namespace i2p
ftruncate(pidFH, 0); ftruncate(pidFH, 0);
if (write(pidFH, pid, strlen(pid)) < 0) if (write(pidFH, pid, strlen(pid)) < 0)
{ {
LogPrint(eLogError, "Daemon: could not write pidfile: ", strerror(errno)); LogPrint(eLogError, "Daemon: Could not write pidfile: ", strerror(errno));
return false; return false;
} }
} }

View file

@ -122,7 +122,7 @@ namespace data
break; break;
} }
default: default:
LogPrint (eLogError, "Blinding: signature type ", (int)sigType, " is not ECDSA"); LogPrint (eLogError, "Blinding: Signature type ", (int)sigType, " is not ECDSA");
} }
if (group) if (group)
{ {
@ -156,7 +156,7 @@ namespace data
size_t l = i2p::data::Base32ToByteStream (b33.c_str (), b33.length (), addr, 40); size_t l = i2p::data::Base32ToByteStream (b33.c_str (), b33.length (), addr, 40);
if (l < 32) if (l < 32)
{ {
LogPrint (eLogError, "Blinding: malformed b33 ", b33); LogPrint (eLogError, "Blinding: Malformed b33 ", b33);
return; return;
} }
uint32_t checksum = crc32 (0, addr + 3, l - 3); uint32_t checksum = crc32 (0, addr + 3, l - 3);
@ -186,10 +186,10 @@ namespace data
memcpy (m_PublicKey.data (), addr + offset, len); memcpy (m_PublicKey.data (), addr + offset, len);
} }
else else
LogPrint (eLogError, "Blinding: public key in b33 address is too short for signature type ", (int)m_SigType); LogPrint (eLogError, "Blinding: Public key in b33 address is too short for signature type ", (int)m_SigType);
} }
else else
LogPrint (eLogError, "Blinding: unknown signature type ", (int)m_SigType, " in b33"); LogPrint (eLogError, "Blinding: Unknown signature type ", (int)m_SigType, " in b33");
} }
std::string BlindedPublicKey::ToB33 () const std::string BlindedPublicKey::ToB33 () const
@ -256,7 +256,7 @@ namespace data
publicKeyLength = i2p::crypto::EDDSA25519_PUBLIC_KEY_LENGTH; publicKeyLength = i2p::crypto::EDDSA25519_PUBLIC_KEY_LENGTH;
break; break;
default: default:
LogPrint (eLogError, "Blinding: can't blind signature type ", (int)m_SigType); LogPrint (eLogError, "Blinding: Can't blind signature type ", (int)m_SigType);
} }
return publicKeyLength; return publicKeyLength;
} }
@ -272,21 +272,21 @@ namespace data
case i2p::data::SIGNING_KEY_TYPE_ECDSA_SHA384_P384: case i2p::data::SIGNING_KEY_TYPE_ECDSA_SHA384_P384:
case i2p::data::SIGNING_KEY_TYPE_ECDSA_SHA512_P521: case i2p::data::SIGNING_KEY_TYPE_ECDSA_SHA512_P521:
publicKeyLength = BlindECDSA (m_SigType, priv, seed, BlindEncodedPrivateKeyECDSA, blindedPriv, blindedPub); publicKeyLength = BlindECDSA (m_SigType, priv, seed, BlindEncodedPrivateKeyECDSA, blindedPriv, blindedPub);
break; break;
case i2p::data::SIGNING_KEY_TYPE_REDDSA_SHA512_ED25519: case i2p::data::SIGNING_KEY_TYPE_REDDSA_SHA512_ED25519:
i2p::crypto::GetEd25519 ()->BlindPrivateKey (priv, seed, blindedPriv, blindedPub); i2p::crypto::GetEd25519 ()->BlindPrivateKey (priv, seed, blindedPriv, blindedPub);
publicKeyLength = i2p::crypto::EDDSA25519_PUBLIC_KEY_LENGTH; publicKeyLength = i2p::crypto::EDDSA25519_PUBLIC_KEY_LENGTH;
break; break;
case i2p::data::SIGNING_KEY_TYPE_EDDSA_SHA512_ED25519: case i2p::data::SIGNING_KEY_TYPE_EDDSA_SHA512_ED25519:
{ {
uint8_t exp[64]; uint8_t exp[64];
i2p::crypto::Ed25519::ExpandPrivateKey (priv, exp); i2p::crypto::Ed25519::ExpandPrivateKey (priv, exp);
i2p::crypto::GetEd25519 ()->BlindPrivateKey (exp, seed, blindedPriv, blindedPub); i2p::crypto::GetEd25519 ()->BlindPrivateKey (exp, seed, blindedPriv, blindedPub);
publicKeyLength = i2p::crypto::EDDSA25519_PUBLIC_KEY_LENGTH; publicKeyLength = i2p::crypto::EDDSA25519_PUBLIC_KEY_LENGTH;
break; break;
} }
default: default:
LogPrint (eLogError, "Blinding: can't blind signature type ", (int)m_SigType); LogPrint (eLogError, "Blinding: Can't blind signature type ", (int)m_SigType);
} }
return publicKeyLength; return publicKeyLength;
} }
@ -324,7 +324,7 @@ namespace data
SHA256_Final ((uint8_t *)hash, &ctx); SHA256_Final ((uint8_t *)hash, &ctx);
} }
else else
LogPrint (eLogError, "Blinding: blinded key type ", (int)m_BlindedSigType, " is not supported"); LogPrint (eLogError, "Blinding: Blinded key type ", (int)m_BlindedSigType, " is not supported");
return hash; return hash;
} }

View file

@ -56,7 +56,7 @@ namespace client
it = params->find (I2CP_PARAM_TAGS_TO_SEND); it = params->find (I2CP_PARAM_TAGS_TO_SEND);
if (it != params->end ()) if (it != params->end ())
numTags = std::stoi(it->second); numTags = std::stoi(it->second);
LogPrint (eLogInfo, "Destination: parameters for tunnel set to: ", inQty, " inbound (", inLen, " hops), ", outQty, " outbound (", outLen, " hops), ", numTags, " tags"); LogPrint (eLogInfo, "Destination: Parameters for tunnel set to: ", inQty, " inbound (", inLen, " hops), ", outQty, " outbound (", outLen, " hops), ", numTags, " tags");
it = params->find (I2CP_PARAM_RATCHET_INBOUND_TAGS); it = params->find (I2CP_PARAM_RATCHET_INBOUND_TAGS);
if (it != params->end ()) if (it != params->end ())
SetNumRatchetInboundTags (std::stoi(it->second)); SetNumRatchetInboundTags (std::stoi(it->second));
@ -89,7 +89,7 @@ namespace client
bool dontpublish = false; bool dontpublish = false;
i2p::config::GetOption (it->second, dontpublish); i2p::config::GetOption (it->second, dontpublish);
m_IsPublic = !dontpublish; m_IsPublic = !dontpublish;
} }
it = params->find (I2CP_PARAM_LEASESET_TYPE); it = params->find (I2CP_PARAM_LEASESET_TYPE);
if (it != params->end ()) if (it != params->end ())
m_LeaseSetType = std::stoi(it->second); m_LeaseSetType = std::stoi(it->second);
@ -112,7 +112,7 @@ namespace client
m_LeaseSetPrivKey.reset (new i2p::data::Tag<32>()); m_LeaseSetPrivKey.reset (new i2p::data::Tag<32>());
if (m_LeaseSetPrivKey->FromBase64 (it->second) != 32) if (m_LeaseSetPrivKey->FromBase64 (it->second) != 32)
{ {
LogPrint(eLogError, "Destination: invalid value i2cp.leaseSetPrivKey ", it->second); LogPrint(eLogError, "Destination: Invalid value i2cp.leaseSetPrivKey ", it->second);
m_LeaseSetPrivKey.reset (nullptr); m_LeaseSetPrivKey.reset (nullptr);
} }
} }
@ -120,7 +120,7 @@ namespace client
} }
catch (std::exception & ex) catch (std::exception & ex)
{ {
LogPrint(eLogError, "Destination: unable to parse parameters for destination: ", ex.what()); LogPrint(eLogError, "Destination: Unable to parse parameters for destination: ", ex.what());
} }
SetNumTags (numTags); SetNumTags (numTags);
m_Pool = i2p::tunnel::tunnels.CreateTunnelPool (inLen, outLen, inQty, outQty); m_Pool = i2p::tunnel::tunnels.CreateTunnelPool (inLen, outLen, inQty, outQty);
@ -136,7 +136,7 @@ namespace client
auto minlatency = std::stoi(itr->second); auto minlatency = std::stoi(itr->second);
if ( minlatency > 0 && maxlatency > 0 ) { if ( minlatency > 0 && maxlatency > 0 ) {
// set tunnel pool latency // set tunnel pool latency
LogPrint(eLogInfo, "Destination: requiring tunnel latency [", minlatency, "ms, ", maxlatency, "ms]"); LogPrint(eLogInfo, "Destination: Requiring tunnel latency [", minlatency, "ms, ", maxlatency, "ms]");
m_Pool->RequireLatency(minlatency, maxlatency); m_Pool->RequireLatency(minlatency, maxlatency);
} }
} }
@ -251,7 +251,7 @@ namespace client
} }
else else
{ {
LogPrint (eLogWarning, "Destination: remote LeaseSet expired"); LogPrint (eLogWarning, "Destination: Remote LeaseSet expired");
std::lock_guard<std::mutex> lock(m_RemoteLeaseSetsMutex); std::lock_guard<std::mutex> lock(m_RemoteLeaseSetsMutex);
m_RemoteLeaseSets.erase (ident); m_RemoteLeaseSets.erase (ident);
return nullptr; return nullptr;
@ -367,8 +367,8 @@ namespace client
HandleDatabaseSearchReplyMessage (payload, len); HandleDatabaseSearchReplyMessage (payload, len);
break; break;
case eI2NPShortTunnelBuildReply: // might come as garlic encrypted case eI2NPShortTunnelBuildReply: // might come as garlic encrypted
i2p::HandleI2NPMessage (CreateI2NPMessage (typeID, payload, len, msgID)); i2p::HandleI2NPMessage (CreateI2NPMessage (typeID, payload, len, msgID));
break; break;
default: default:
LogPrint (eLogWarning, "Destination: Unexpected I2NP message type ", typeID); LogPrint (eLogWarning, "Destination: Unexpected I2NP message type ", typeID);
return false; return false;
@ -395,7 +395,7 @@ namespace client
LogPrint (eLogDebug, "Destination: Remote LeaseSet"); LogPrint (eLogDebug, "Destination: Remote LeaseSet");
std::lock_guard<std::mutex> lock(m_RemoteLeaseSetsMutex); std::lock_guard<std::mutex> lock(m_RemoteLeaseSetsMutex);
auto it = m_RemoteLeaseSets.find (key); auto it = m_RemoteLeaseSets.find (key);
if (it != m_RemoteLeaseSets.end () && if (it != m_RemoteLeaseSets.end () &&
it->second->GetStoreType () == buf[DATABASE_STORE_TYPE_OFFSET]) // update only if same type it->second->GetStoreType () == buf[DATABASE_STORE_TYPE_OFFSET]) // update only if same type
{ {
leaseSet = it->second; leaseSet = it->second;
@ -487,7 +487,7 @@ namespace client
i2p::data::IdentHash peerHash (buf + 33 + i*32); i2p::data::IdentHash peerHash (buf + 33 + i*32);
if (!request->excluded.count (peerHash) && !i2p::data::netdb.FindRouter (peerHash)) if (!request->excluded.count (peerHash) && !i2p::data::netdb.FindRouter (peerHash))
{ {
LogPrint (eLogInfo, "Destination: Found new floodfill, request it"); LogPrint (eLogInfo, "Destination: Found new floodfill, request it");
i2p::data::netdb.RequestDestination (peerHash, nullptr, false); // through exploratory i2p::data::netdb.RequestDestination (peerHash, nullptr, false); // through exploratory
} }
} }
@ -767,11 +767,11 @@ namespace client
uint8_t replyKey[32], replyTag[32]; uint8_t replyKey[32], replyTag[32];
RAND_bytes (replyKey, 32); // random session key RAND_bytes (replyKey, 32); // random session key
RAND_bytes (replyTag, isECIES ? 8 : 32); // random session tag RAND_bytes (replyTag, isECIES ? 8 : 32); // random session tag
if (isECIES) if (isECIES)
AddECIESx25519Key (replyKey, replyTag); AddECIESx25519Key (replyKey, replyTag);
else else
AddSessionKey (replyKey, replyTag); AddSessionKey (replyKey, replyTag);
auto msg = WrapMessageForRouter (nextFloodfill, CreateLeaseSetDatabaseLookupMsg (dest, auto msg = WrapMessageForRouter (nextFloodfill, CreateLeaseSetDatabaseLookupMsg (dest,
request->excluded, request->replyTunnel, replyKey, replyTag, isECIES)); request->excluded, request->replyTunnel, replyKey, replyTag, isECIES));
request->outboundTunnel->SendTunnelDataMsg ( request->outboundTunnel->SendTunnelDataMsg (
{ {
@ -866,8 +866,8 @@ namespace client
ClientDestination::ClientDestination (boost::asio::io_service& service, const i2p::data::PrivateKeys& keys, ClientDestination::ClientDestination (boost::asio::io_service& service, const i2p::data::PrivateKeys& keys,
bool isPublic, const std::map<std::string, std::string> * params): bool isPublic, const std::map<std::string, std::string> * params):
LeaseSetDestination (service, isPublic, params), LeaseSetDestination (service, isPublic, params),
m_Keys (keys), m_StreamingAckDelay (DEFAULT_INITIAL_ACK_DELAY), m_Keys (keys), m_StreamingAckDelay (DEFAULT_INITIAL_ACK_DELAY),
m_IsStreamingAnswerPings (DEFAULT_ANSWER_PINGS), m_IsStreamingAnswerPings (DEFAULT_ANSWER_PINGS),
m_DatagramDestination (nullptr), m_RefCounter (0), m_DatagramDestination (nullptr), m_RefCounter (0),
m_ReadyChecker(service) m_ReadyChecker(service)
@ -916,11 +916,11 @@ namespace client
encryptionKey->GenerateKeys (); encryptionKey->GenerateKeys ();
encryptionKey->CreateDecryptor (); encryptionKey->CreateDecryptor ();
if (it == i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD) if (it == i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD)
{ {
m_ECIESx25519EncryptionKey.reset (encryptionKey); m_ECIESx25519EncryptionKey.reset (encryptionKey);
if (GetLeaseSetType () == i2p::data::NETDB_STORE_TYPE_LEASESET) if (GetLeaseSetType () == i2p::data::NETDB_STORE_TYPE_LEASESET)
SetLeaseSetType (i2p::data::NETDB_STORE_TYPE_STANDARD_LEASESET2); // Rathets must use LeaseSet2 SetLeaseSetType (i2p::data::NETDB_STORE_TYPE_STANDARD_LEASESET2); // Rathets must use LeaseSet2
} }
else else
m_StandardEncryptionKey.reset (encryptionKey); m_StandardEncryptionKey.reset (encryptionKey);
} }
@ -939,7 +939,7 @@ namespace client
it = params->find (I2CP_PARAM_STREAMING_ANSWER_PINGS); it = params->find (I2CP_PARAM_STREAMING_ANSWER_PINGS);
if (it != params->end ()) if (it != params->end ())
i2p::config::GetOption (it->second, m_IsStreamingAnswerPings); i2p::config::GetOption (it->second, m_IsStreamingAnswerPings);
if (GetLeaseSetType () == i2p::data::NETDB_STORE_TYPE_ENCRYPTED_LEASESET2) if (GetLeaseSetType () == i2p::data::NETDB_STORE_TYPE_ENCRYPTED_LEASESET2)
{ {
// authentication for encrypted LeaseSet // authentication for encrypted LeaseSet
@ -966,7 +966,7 @@ namespace client
} }
catch (std::exception & ex) catch (std::exception & ex)
{ {
LogPrint(eLogError, "Destination: unable to parse parameters for destination: ", ex.what()); LogPrint(eLogError, "Destination: Unable to parse parameters for destination: ", ex.what());
} }
} }
@ -1050,7 +1050,7 @@ namespace client
{ {
if (!streamRequestComplete) if (!streamRequestComplete)
{ {
LogPrint (eLogError, "Destination: request callback is not specified in CreateStream"); LogPrint (eLogError, "Destination: Request callback is not specified in CreateStream");
return; return;
} }
auto leaseSet = FindLeaseSet (dest); auto leaseSet = FindLeaseSet (dest);
@ -1074,7 +1074,7 @@ namespace client
{ {
if (!streamRequestComplete) if (!streamRequestComplete)
{ {
LogPrint (eLogError, "Destination: request callback is not specified in CreateStream"); LogPrint (eLogError, "Destination: Request callback is not specified in CreateStream");
return; return;
} }
auto s = GetSharedFromThis (); auto s = GetSharedFromThis ();
@ -1153,18 +1153,18 @@ namespace client
auto ret = it->second; auto ret = it->second;
m_StreamingDestinationsByPorts.erase (it); m_StreamingDestinationsByPorts.erase (it);
return ret; return ret;
} }
} }
return nullptr; return nullptr;
} }
i2p::datagram::DatagramDestination * ClientDestination::CreateDatagramDestination (bool gzip) i2p::datagram::DatagramDestination * ClientDestination::CreateDatagramDestination (bool gzip)
{ {
if (m_DatagramDestination == nullptr) if (m_DatagramDestination == nullptr)
m_DatagramDestination = new i2p::datagram::DatagramDestination (GetSharedFromThis (), gzip); m_DatagramDestination = new i2p::datagram::DatagramDestination (GetSharedFromThis (), gzip);
return m_DatagramDestination; return m_DatagramDestination;
} }
std::vector<std::shared_ptr<const i2p::stream::Stream> > ClientDestination::GetAllStreams () const std::vector<std::shared_ptr<const i2p::stream::Stream> > ClientDestination::GetAllStreams () const
{ {
std::vector<std::shared_ptr<const i2p::stream::Stream> > ret; std::vector<std::shared_ptr<const i2p::stream::Stream> > ret;
@ -1253,7 +1253,7 @@ namespace client
if (m_StandardEncryptionKey && m_StandardEncryptionKey->decryptor) if (m_StandardEncryptionKey && m_StandardEncryptionKey->decryptor)
return m_StandardEncryptionKey->decryptor->Decrypt (encrypted, data); return m_StandardEncryptionKey->decryptor->Decrypt (encrypted, data);
else else
LogPrint (eLogError, "Destinations: decryptor is not set"); LogPrint (eLogError, "Destinations: Decryptor is not set");
return false; return false;
} }

View file

@ -90,24 +90,24 @@ namespace garlic
} }
void RatchetTagSet::DeleteSymmKey (int index) void RatchetTagSet::DeleteSymmKey (int index)
{ {
m_ItermediateSymmKeys.erase (index); m_ItermediateSymmKeys.erase (index);
} }
void ReceiveRatchetTagSet::Expire () void ReceiveRatchetTagSet::Expire ()
{ {
if (!m_ExpirationTimestamp) if (!m_ExpirationTimestamp)
m_ExpirationTimestamp = i2p::util::GetSecondsSinceEpoch () + ECIESX25519_PREVIOUS_TAGSET_EXPIRATION_TIMEOUT; m_ExpirationTimestamp = i2p::util::GetSecondsSinceEpoch () + ECIESX25519_PREVIOUS_TAGSET_EXPIRATION_TIMEOUT;
} }
bool ReceiveRatchetTagSet::IsExpired (uint64_t ts) const bool ReceiveRatchetTagSet::IsExpired (uint64_t ts) const
{ {
return m_ExpirationTimestamp && ts > m_ExpirationTimestamp; return m_ExpirationTimestamp && ts > m_ExpirationTimestamp;
} }
bool ReceiveRatchetTagSet::IsIndexExpired (int index) const bool ReceiveRatchetTagSet::IsIndexExpired (int index) const
{ {
return index < m_TrimBehindIndex; return index < m_TrimBehindIndex;
} }
bool ReceiveRatchetTagSet::HandleNextMessage (uint8_t * buf, size_t len, int index) bool ReceiveRatchetTagSet::HandleNextMessage (uint8_t * buf, size_t len, int index)
@ -115,21 +115,21 @@ namespace garlic
auto session = GetSession (); auto session = GetSession ();
if (!session) return false; if (!session) return false;
return session->HandleNextMessage (buf, len, shared_from_this (), index); return session->HandleNextMessage (buf, len, shared_from_this (), index);
} }
SymmetricKeyTagSet::SymmetricKeyTagSet (GarlicDestination * destination, const uint8_t * key): SymmetricKeyTagSet::SymmetricKeyTagSet (GarlicDestination * destination, const uint8_t * key):
ReceiveRatchetTagSet (nullptr), m_Destination (destination) ReceiveRatchetTagSet (nullptr), m_Destination (destination)
{ {
memcpy (m_Key, key, 32); memcpy (m_Key, key, 32);
Expire (); Expire ();
} }
bool SymmetricKeyTagSet::HandleNextMessage (uint8_t * buf, size_t len, int index) bool SymmetricKeyTagSet::HandleNextMessage (uint8_t * buf, size_t len, int index)
{ {
if (len < 24) return false; if (len < 24) return false;
uint8_t nonce[12]; uint8_t nonce[12];
memset (nonce, 0, 12); // n = 0 memset (nonce, 0, 12); // n = 0
size_t offset = 8; // first 8 bytes is reply tag used as AD size_t offset = 8; // first 8 bytes is reply tag used as AD
len -= 16; // poly1305 len -= 16; // poly1305
if (!i2p::crypto::AEADChaCha20Poly1305 (buf + offset, len - offset, buf, 8, m_Key, nonce, buf + offset, len - offset, false)) // decrypt if (!i2p::crypto::AEADChaCha20Poly1305 (buf + offset, len - offset, buf, 8, m_Key, nonce, buf + offset, len - offset, false)) // decrypt
{ {
@ -137,33 +137,33 @@ namespace garlic
return false; return false;
} }
// we assume 1 I2NP block with delivery type local // we assume 1 I2NP block with delivery type local
if (offset + 3 > len) if (offset + 3 > len)
{ {
LogPrint (eLogWarning, "Garlic: Symmetric key tagset is too short ", len); LogPrint (eLogWarning, "Garlic: Symmetric key tagset is too short ", len);
return false; return false;
} }
if (buf[offset] != eECIESx25519BlkGalicClove) if (buf[offset] != eECIESx25519BlkGalicClove)
{ {
LogPrint (eLogWarning, "Garlic: Symmetric key tagset unexpected block ", (int)buf[offset]); LogPrint (eLogWarning, "Garlic: Symmetric key tagset unexpected block ", (int)buf[offset]);
return false; return false;
} }
offset++; offset++;
auto size = bufbe16toh (buf + offset); auto size = bufbe16toh (buf + offset);
offset += 2; offset += 2;
if (offset + size > len) if (offset + size > len)
{ {
LogPrint (eLogWarning, "Garlic: Symmetric key tagset block is too long ", size); LogPrint (eLogWarning, "Garlic: Symmetric key tagset block is too long ", size);
return false; return false;
} }
if (m_Destination) if (m_Destination)
m_Destination->HandleECIESx25519GarlicClove (buf + offset, size); m_Destination->HandleECIESx25519GarlicClove (buf + offset, size);
return true; return true;
} }
ECIESX25519AEADRatchetSession::ECIESX25519AEADRatchetSession (GarlicDestination * owner, bool attachLeaseSetNS): ECIESX25519AEADRatchetSession::ECIESX25519AEADRatchetSession (GarlicDestination * owner, bool attachLeaseSetNS):
GarlicRoutingSession (owner, true) GarlicRoutingSession (owner, true)
{ {
if (!attachLeaseSetNS) SetLeaseSetUpdateStatus (eLeaseSetUpToDate); if (!attachLeaseSetNS) SetLeaseSetUpdateStatus (eLeaseSetUpToDate);
RAND_bytes (m_PaddingSizes, 32); m_NextPaddingSize = 0; RAND_bytes (m_PaddingSizes, 32); m_NextPaddingSize = 0;
} }
@ -181,11 +181,11 @@ namespace garlic
{ {
bool ineligible = false; bool ineligible = false;
while (!ineligible) while (!ineligible)
{ {
m_EphemeralKeys = i2p::transport::transports.GetNextX25519KeysPair (); m_EphemeralKeys = i2p::transport::transports.GetNextX25519KeysPair ();
ineligible = m_EphemeralKeys->IsElligatorIneligible (); ineligible = m_EphemeralKeys->IsElligatorIneligible ();
if (!ineligible) // we haven't tried it yet if (!ineligible) // we haven't tried it yet
{ {
if (i2p::crypto::GetElligator ()->Encode (m_EphemeralKeys->GetPublicKey (), buf)) if (i2p::crypto::GetElligator ()->Encode (m_EphemeralKeys->GetPublicKey (), buf))
return true; // success return true; // success
// otherwise return back // otherwise return back
@ -194,7 +194,7 @@ namespace garlic
} }
else else
i2p::transport::transports.ReuseX25519KeysPair (m_EphemeralKeys); i2p::transport::transports.ReuseX25519KeysPair (m_EphemeralKeys);
} }
// we still didn't find elligator eligible pair // we still didn't find elligator eligible pair
for (int i = 0; i < 25; i++) for (int i = 0; i < 25; i++)
{ {
@ -208,7 +208,7 @@ namespace garlic
// let NTCP2 use it // let NTCP2 use it
m_EphemeralKeys->SetElligatorIneligible (); m_EphemeralKeys->SetElligatorIneligible ();
i2p::transport::transports.ReuseX25519KeysPair (m_EphemeralKeys); i2p::transport::transports.ReuseX25519KeysPair (m_EphemeralKeys);
} }
} }
LogPrint (eLogError, "Garlic: Can't generate elligator eligible x25519 keys"); LogPrint (eLogError, "Garlic: Can't generate elligator eligible x25519 keys");
return false; return false;
@ -229,7 +229,7 @@ namespace garlic
// we are Bob // we are Bob
// KDF1 // KDF1
i2p::crypto::InitNoiseIKState (GetNoiseState (), GetOwner ()->GetEncryptionPublicKey (i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD)); // bpk i2p::crypto::InitNoiseIKState (GetNoiseState (), GetOwner ()->GetEncryptionPublicKey (i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD)); // bpk
if (!i2p::crypto::GetElligator ()->Decode (buf, m_Aepk)) if (!i2p::crypto::GetElligator ()->Decode (buf, m_Aepk))
{ {
LogPrint (eLogError, "Garlic: Can't decode elligator"); LogPrint (eLogError, "Garlic: Can't decode elligator");
@ -243,7 +243,7 @@ namespace garlic
{ {
LogPrint (eLogWarning, "Garlic: Incorrect Alice ephemeral key"); LogPrint (eLogWarning, "Garlic: Incorrect Alice ephemeral key");
return false; return false;
} }
MixKey (sharedSecret); MixKey (sharedSecret);
// decrypt flags/static // decrypt flags/static
@ -267,7 +267,7 @@ namespace garlic
{ {
LogPrint (eLogWarning, "Garlic: Incorrect Alice static key"); LogPrint (eLogWarning, "Garlic: Incorrect Alice static key");
return false; return false;
} }
MixKey (sharedSecret); MixKey (sharedSecret);
} }
else // all zeros flags else // all zeros flags
@ -280,13 +280,13 @@ namespace garlic
LogPrint (eLogWarning, "Garlic: Payload section AEAD verification failed"); LogPrint (eLogWarning, "Garlic: Payload section AEAD verification failed");
return false; return false;
} }
m_State = eSessionStateNewSessionReceived; m_State = eSessionStateNewSessionReceived;
if (isStatic) if (isStatic)
{ {
MixHash (buf, len); // h = SHA256(h || ciphertext) MixHash (buf, len); // h = SHA256(h || ciphertext)
GetOwner ()->AddECIESx25519Session (m_RemoteStaticKey, shared_from_this ()); GetOwner ()->AddECIESx25519Session (m_RemoteStaticKey, shared_from_this ());
} }
HandlePayload (payload.data (), len - 16, nullptr, 0); HandlePayload (payload.data (), len - 16, nullptr, 0);
return true; return true;
@ -381,7 +381,7 @@ namespace garlic
newTagset->NextSessionTagRatchet (); newTagset->NextSessionTagRatchet ();
m_SendTagset = newTagset; m_SendTagset = newTagset;
m_SendForwardKey = false; m_SendForwardKey = false;
LogPrint (eLogDebug, "Garlic: next send tagset ", newTagset->GetTagSetID (), " created"); LogPrint (eLogDebug, "Garlic: Next send tagset ", newTagset->GetTagSetID (), " created");
} }
else else
LogPrint (eLogDebug, "Garlic: Unexpected next key ", keyID); LogPrint (eLogDebug, "Garlic: Unexpected next key ", keyID);
@ -424,7 +424,7 @@ namespace garlic
GenerateMoreReceiveTags (newTagset, (GetOwner () && GetOwner ()->GetNumRatchetInboundTags () > 0) ? GenerateMoreReceiveTags (newTagset, (GetOwner () && GetOwner ()->GetNumRatchetInboundTags () > 0) ?
GetOwner ()->GetNumRatchetInboundTags () : ECIESX25519_MAX_NUM_GENERATED_TAGS); GetOwner ()->GetNumRatchetInboundTags () : ECIESX25519_MAX_NUM_GENERATED_TAGS);
receiveTagset->Expire (); receiveTagset->Expire ();
LogPrint (eLogDebug, "Garlic: next receive tagset ", tagsetID, " created"); LogPrint (eLogDebug, "Garlic: Next receive tagset ", tagsetID, " created");
} }
} }
@ -446,7 +446,7 @@ namespace garlic
m_NextSendRatchet->key = i2p::transport::transports.GetNextX25519KeysPair (); m_NextSendRatchet->key = i2p::transport::transports.GetNextX25519KeysPair ();
m_SendForwardKey = true; m_SendForwardKey = true;
LogPrint (eLogDebug, "Garlic: new send ratchet ", m_NextSendRatchet->newKey ? "new" : "old", " key ", m_NextSendRatchet->keyID, " created"); LogPrint (eLogDebug, "Garlic: New send ratchet ", m_NextSendRatchet->newKey ? "new" : "old", " key ", m_NextSendRatchet->keyID, " created");
} }
bool ECIESX25519AEADRatchetSession::NewOutgoingSessionMessage (const uint8_t * payload, size_t len, uint8_t * out, size_t outLen, bool isStatic) bool ECIESX25519AEADRatchetSession::NewOutgoingSessionMessage (const uint8_t * payload, size_t len, uint8_t * out, size_t outLen, bool isStatic)
@ -468,7 +468,7 @@ namespace garlic
{ {
LogPrint (eLogWarning, "Garlic: Incorrect Bob static key"); LogPrint (eLogWarning, "Garlic: Incorrect Bob static key");
return false; return false;
} }
MixKey (sharedSecret); MixKey (sharedSecret);
// encrypt flags/static key section // encrypt flags/static key section
uint8_t nonce[12]; uint8_t nonce[12];
@ -478,7 +478,7 @@ namespace garlic
fs = GetOwner ()->GetEncryptionPublicKey (i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD); fs = GetOwner ()->GetEncryptionPublicKey (i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD);
else else
{ {
memset (out + offset, 0, 32); // all zeros flags section memset (out + offset, 0, 32); // all zeros flags section
fs = out + offset; fs = out + offset;
} }
if (!i2p::crypto::AEADChaCha20Poly1305 (fs, 32, m_H, 32, m_CK + 32, nonce, out + offset, 48, true)) // encrypt if (!i2p::crypto::AEADChaCha20Poly1305 (fs, 32, m_H, 32, m_CK + 32, nonce, out + offset, 48, true)) // encrypt
@ -486,14 +486,14 @@ namespace garlic
LogPrint (eLogWarning, "Garlic: Flags/static section AEAD encryption failed "); LogPrint (eLogWarning, "Garlic: Flags/static section AEAD encryption failed ");
return false; return false;
} }
MixHash (out + offset, 48); // h = SHA256(h || ciphertext) MixHash (out + offset, 48); // h = SHA256(h || ciphertext)
offset += 48; offset += 48;
// KDF2 // KDF2
if (isStatic) if (isStatic)
{ {
GetOwner ()->Decrypt (m_RemoteStaticKey, sharedSecret, i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD); // x25519 (ask, bpk) GetOwner ()->Decrypt (m_RemoteStaticKey, sharedSecret, i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD); // x25519 (ask, bpk)
MixKey (sharedSecret); MixKey (sharedSecret);
} }
else else
CreateNonce (1, nonce); CreateNonce (1, nonce);
@ -503,10 +503,10 @@ namespace garlic
LogPrint (eLogWarning, "Garlic: Payload section AEAD encryption failed"); LogPrint (eLogWarning, "Garlic: Payload section AEAD encryption failed");
return false; return false;
} }
m_State = eSessionStateNewSessionSent; m_State = eSessionStateNewSessionSent;
if (isStatic) if (isStatic)
{ {
MixHash (out + offset, len + 16); // h = SHA256(h || ciphertext) MixHash (out + offset, len + 16); // h = SHA256(h || ciphertext)
if (GetOwner ()) if (GetOwner ())
{ {
@ -514,11 +514,11 @@ namespace garlic
InitNewSessionTagset (tagsetNsr); InitNewSessionTagset (tagsetNsr);
tagsetNsr->Expire (); // let non-replied session expire tagsetNsr->Expire (); // let non-replied session expire
GenerateMoreReceiveTags (tagsetNsr, ECIESX25519_NSR_NUM_GENERATED_TAGS); GenerateMoreReceiveTags (tagsetNsr, ECIESX25519_NSR_NUM_GENERATED_TAGS);
} }
} }
return true; return true;
} }
bool ECIESX25519AEADRatchetSession::NewSessionReplyMessage (const uint8_t * payload, size_t len, uint8_t * out, size_t outLen) bool ECIESX25519AEADRatchetSession::NewSessionReplyMessage (const uint8_t * payload, size_t len, uint8_t * out, size_t outLen)
{ {
// we are Bob // we are Bob
@ -545,13 +545,13 @@ namespace garlic
{ {
LogPrint (eLogWarning, "Garlic: Incorrect Alice ephemeral key"); LogPrint (eLogWarning, "Garlic: Incorrect Alice ephemeral key");
return false; return false;
} }
MixKey (sharedSecret); MixKey (sharedSecret);
if (!m_EphemeralKeys->Agree (m_RemoteStaticKey, sharedSecret)) // sharedSecret = x25519(besk, apk) if (!m_EphemeralKeys->Agree (m_RemoteStaticKey, sharedSecret)) // sharedSecret = x25519(besk, apk)
{ {
LogPrint (eLogWarning, "Garlic: Incorrect Alice static key"); LogPrint (eLogWarning, "Garlic: Incorrect Alice static key");
return false; return false;
} }
MixKey (sharedSecret); MixKey (sharedSecret);
uint8_t nonce[12]; uint8_t nonce[12];
CreateNonce (0, nonce); CreateNonce (0, nonce);
@ -584,10 +584,10 @@ namespace garlic
} }
m_State = eSessionStateNewSessionReplySent; m_State = eSessionStateNewSessionReplySent;
m_SessionCreatedTimestamp = i2p::util::GetSecondsSinceEpoch (); m_SessionCreatedTimestamp = i2p::util::GetSecondsSinceEpoch ();
return true; return true;
} }
bool ECIESX25519AEADRatchetSession::NextNewSessionReplyMessage (const uint8_t * payload, size_t len, uint8_t * out, size_t outLen) bool ECIESX25519AEADRatchetSession::NextNewSessionReplyMessage (const uint8_t * payload, size_t len, uint8_t * out, size_t outLen)
{ {
// we are Bob and sent NSR already // we are Bob and sent NSR already
@ -618,7 +618,7 @@ namespace garlic
bool ECIESX25519AEADRatchetSession::HandleNewOutgoingSessionReply (uint8_t * buf, size_t len) bool ECIESX25519AEADRatchetSession::HandleNewOutgoingSessionReply (uint8_t * buf, size_t len)
{ {
// we are Alice // we are Alice
LogPrint (eLogDebug, "Garlic: reply received"); LogPrint (eLogDebug, "Garlic: Reply received");
const uint8_t * tag = buf; const uint8_t * tag = buf;
buf += 8; len -= 8; // tag buf += 8; len -= 8; // tag
uint8_t bepk[32]; // Bob's ephemeral key uint8_t bepk[32]; // Bob's ephemeral key
@ -637,7 +637,7 @@ namespace garlic
{ {
LogPrint (eLogWarning, "Garlic: Incorrect Bob ephemeral key"); LogPrint (eLogWarning, "Garlic: Incorrect Bob ephemeral key");
return false; return false;
} }
MixKey (sharedSecret); MixKey (sharedSecret);
GetOwner ()->Decrypt (bepk, sharedSecret, i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD); // x25519 (ask, bepk) GetOwner ()->Decrypt (bepk, sharedSecret, i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD); // x25519 (ask, bepk)
MixKey (sharedSecret); MixKey (sharedSecret);
@ -700,11 +700,11 @@ namespace garlic
uint64_t tag = m_SendTagset->GetNextSessionTag (); uint64_t tag = m_SendTagset->GetNextSessionTag ();
if (!tag) if (!tag)
{ {
LogPrint (eLogError, "Garlic: can't create new ECIES-X25519-AEAD-Ratchet tag for send tagset"); LogPrint (eLogError, "Garlic: Can't create new ECIES-X25519-AEAD-Ratchet tag for send tagset");
if (GetOwner ()) if (GetOwner ())
GetOwner ()->RemoveECIESx25519Session (m_RemoteStaticKey); GetOwner ()->RemoveECIESx25519Session (m_RemoteStaticKey);
return false; return false;
} }
memcpy (out, &tag, 8); memcpy (out, &tag, 8);
// ad = The session tag, 8 bytes // ad = The session tag, 8 bytes
// ciphertext = ENCRYPT(k, n, payload, ad) // ciphertext = ENCRYPT(k, n, payload, ad)
@ -736,7 +736,7 @@ namespace garlic
} }
HandlePayload (payload, len - 16, receiveTagset, index); HandlePayload (payload, len - 16, receiveTagset, index);
if (GetOwner ()) if (GetOwner ())
{ {
int moreTags = 0; int moreTags = 0;
if (GetOwner ()->GetNumRatchetInboundTags () > 0) // override in settings? if (GetOwner ()->GetNumRatchetInboundTags () > 0) // override in settings?
{ {
@ -745,17 +745,17 @@ namespace garlic
index -= GetOwner ()->GetNumRatchetInboundTags (); // trim behind index -= GetOwner ()->GetNumRatchetInboundTags (); // trim behind
} }
else else
{ {
moreTags = ECIESX25519_MIN_NUM_GENERATED_TAGS + (index >> 2); // N/4 moreTags = ECIESX25519_MIN_NUM_GENERATED_TAGS + (index >> 2); // N/4
if (moreTags > ECIESX25519_MAX_NUM_GENERATED_TAGS) moreTags = ECIESX25519_MAX_NUM_GENERATED_TAGS; if (moreTags > ECIESX25519_MAX_NUM_GENERATED_TAGS) moreTags = ECIESX25519_MAX_NUM_GENERATED_TAGS;
moreTags -= (receiveTagset->GetNextIndex () - index); moreTags -= (receiveTagset->GetNextIndex () - index);
index -= ECIESX25519_MAX_NUM_GENERATED_TAGS; // trim behind index -= ECIESX25519_MAX_NUM_GENERATED_TAGS; // trim behind
} }
if (moreTags > 0) if (moreTags > 0)
GenerateMoreReceiveTags (receiveTagset, moreTags); GenerateMoreReceiveTags (receiveTagset, moreTags);
if (index > 0) if (index > 0)
receiveTagset->SetTrimBehind (index); receiveTagset->SetTrimBehind (index);
} }
return true; return true;
} }
@ -774,13 +774,13 @@ namespace garlic
#endif #endif
case eSessionStateEstablished: case eSessionStateEstablished:
if (receiveTagset->IsNS ()) if (receiveTagset->IsNS ())
{ {
// our of sequence NSR // our of sequence NSR
LogPrint (eLogDebug, "Garlic: check for out of order NSR with index ", index); LogPrint (eLogDebug, "Garlic: check for out of order NSR with index ", index);
if (receiveTagset->GetNextIndex () - index < ECIESX25519_NSR_NUM_GENERATED_TAGS/2) if (receiveTagset->GetNextIndex () - index < ECIESX25519_NSR_NUM_GENERATED_TAGS/2)
GenerateMoreReceiveTags (receiveTagset, ECIESX25519_NSR_NUM_GENERATED_TAGS); GenerateMoreReceiveTags (receiveTagset, ECIESX25519_NSR_NUM_GENERATED_TAGS);
return HandleNewOutgoingSessionReply (buf, len); return HandleNewOutgoingSessionReply (buf, len);
} }
else else
return HandleExistingSessionMessage (buf, len, receiveTagset, index); return HandleExistingSessionMessage (buf, len, receiveTagset, index);
case eSessionStateNew: case eSessionStateNew:
@ -792,7 +792,7 @@ namespace garlic
} }
return true; return true;
} }
std::shared_ptr<I2NPMessage> ECIESX25519AEADRatchetSession::WrapSingleMessage (std::shared_ptr<const I2NPMessage> msg) std::shared_ptr<I2NPMessage> ECIESX25519AEADRatchetSession::WrapSingleMessage (std::shared_ptr<const I2NPMessage> msg)
{ {
uint8_t * payload = GetOwner ()->GetPayloadBuffer (); uint8_t * payload = GetOwner ()->GetPayloadBuffer ();
@ -829,7 +829,7 @@ namespace garlic
if (!NewOutgoingSessionMessage (payload, len, buf, m->maxLen, false)) if (!NewOutgoingSessionMessage (payload, len, buf, m->maxLen, false))
return nullptr; return nullptr;
len += 96; len += 96;
break; break;
default: default:
return nullptr; return nullptr;
} }
@ -844,18 +844,18 @@ namespace garlic
{ {
m_State = eSessionStateOneTime; m_State = eSessionStateOneTime;
return WrapSingleMessage (msg); return WrapSingleMessage (msg);
} }
size_t ECIESX25519AEADRatchetSession::CreatePayload (std::shared_ptr<const I2NPMessage> msg, bool first, uint8_t * payload) size_t ECIESX25519AEADRatchetSession::CreatePayload (std::shared_ptr<const I2NPMessage> msg, bool first, uint8_t * payload)
{ {
uint64_t ts = i2p::util::GetMillisecondsSinceEpoch (); uint64_t ts = i2p::util::GetMillisecondsSinceEpoch ();
size_t payloadLen = 0; size_t payloadLen = 0;
if (first) payloadLen += 7;// datatime if (first) payloadLen += 7;// datatime
if (msg) if (msg)
{ {
payloadLen += msg->GetPayloadLength () + 13; payloadLen += msg->GetPayloadLength () + 13;
if (m_Destination) payloadLen += 32; if (m_Destination) payloadLen += 32;
} }
if (GetLeaseSetUpdateStatus () == eLeaseSetSubmitted && ts > GetLeaseSetSubmissionTime () + LEASET_CONFIRMATION_TIMEOUT) if (GetLeaseSetUpdateStatus () == eLeaseSetSubmitted && ts > GetLeaseSetSubmissionTime () + LEASET_CONFIRMATION_TIMEOUT)
{ {
// resubmit non-confirmed LeaseSet // resubmit non-confirmed LeaseSet
@ -896,9 +896,9 @@ namespace garlic
paddingSize = m_PaddingSizes[m_NextPaddingSize++] & 0x0F; // 0 - 15 paddingSize = m_PaddingSizes[m_NextPaddingSize++] & 0x0F; // 0 - 15
if (m_NextPaddingSize >= 32) if (m_NextPaddingSize >= 32)
{ {
RAND_bytes (m_PaddingSizes, 32); RAND_bytes (m_PaddingSizes, 32);
m_NextPaddingSize = 0; m_NextPaddingSize = 0;
} }
if (delta > 3) if (delta > 3)
{ {
delta -= 3; delta -= 3;
@ -912,9 +912,9 @@ namespace garlic
{ {
if (payloadLen > I2NP_MAX_MESSAGE_SIZE) if (payloadLen > I2NP_MAX_MESSAGE_SIZE)
{ {
LogPrint (eLogError, "Garlic: payload length ", payloadLen, " is too long"); LogPrint (eLogError, "Garlic: Payload length ", payloadLen, " is too long");
return 0; return 0;
} }
m_LastSentTimestamp = ts; m_LastSentTimestamp = ts;
size_t offset = 0; size_t offset = 0;
// DateTime // DateTime
@ -993,7 +993,7 @@ namespace garlic
htobe16buf (payload + offset, paddingSize); offset += 2; htobe16buf (payload + offset, paddingSize); offset += 2;
memset (payload + offset, 0, paddingSize); offset += paddingSize; memset (payload + offset, 0, paddingSize); offset += paddingSize;
} }
} }
return payloadLen; return payloadLen;
} }
@ -1050,17 +1050,17 @@ namespace garlic
void ECIESX25519AEADRatchetSession::GenerateMoreReceiveTags (std::shared_ptr<ReceiveRatchetTagSet> receiveTagset, int numTags) void ECIESX25519AEADRatchetSession::GenerateMoreReceiveTags (std::shared_ptr<ReceiveRatchetTagSet> receiveTagset, int numTags)
{ {
if (GetOwner ()) if (GetOwner ())
{ {
for (int i = 0; i < numTags; i++) for (int i = 0; i < numTags; i++)
{ {
auto tag = GetOwner ()->AddECIESx25519SessionNextTag (receiveTagset); auto tag = GetOwner ()->AddECIESx25519SessionNextTag (receiveTagset);
if (!tag) if (!tag)
{ {
LogPrint (eLogError, "Garlic: can't create new ECIES-X25519-AEAD-Ratchet tag for receive tagset"); LogPrint (eLogError, "Garlic: can't create new ECIES-X25519-AEAD-Ratchet tag for receive tagset");
break; break;
} }
} }
} }
} }
bool ECIESX25519AEADRatchetSession::CheckExpired (uint64_t ts) bool ECIESX25519AEADRatchetSession::CheckExpired (uint64_t ts)
@ -1073,9 +1073,9 @@ namespace garlic
RouterIncomingRatchetSession::RouterIncomingRatchetSession (const i2p::crypto::NoiseSymmetricState& initState): RouterIncomingRatchetSession::RouterIncomingRatchetSession (const i2p::crypto::NoiseSymmetricState& initState):
ECIESX25519AEADRatchetSession (&i2p::context, false) ECIESX25519AEADRatchetSession (&i2p::context, false)
{ {
SetLeaseSetUpdateStatus (eLeaseSetDoNotSend); SetLeaseSetUpdateStatus (eLeaseSetDoNotSend);
SetNoiseState (initState); SetNoiseState (initState);
} }
bool RouterIncomingRatchetSession::HandleNextMessage (const uint8_t * buf, size_t len) bool RouterIncomingRatchetSession::HandleNextMessage (const uint8_t * buf, size_t len)
{ {
@ -1088,12 +1088,12 @@ namespace garlic
{ {
LogPrint (eLogWarning, "Garlic: Incorrect N ephemeral public key"); LogPrint (eLogWarning, "Garlic: Incorrect N ephemeral public key");
return false; return false;
} }
m_CurrentNoiseState.MixKey (sharedSecret); m_CurrentNoiseState.MixKey (sharedSecret);
buf += 32; len -= 32; buf += 32; len -= 32;
uint8_t nonce[12]; uint8_t nonce[12];
CreateNonce (0, nonce); CreateNonce (0, nonce);
std::vector<uint8_t> payload (len - 16); std::vector<uint8_t> payload (len - 16);
if (!i2p::crypto::AEADChaCha20Poly1305 (buf, len - 16, m_CurrentNoiseState.m_H, 32, if (!i2p::crypto::AEADChaCha20Poly1305 (buf, len - 16, m_CurrentNoiseState.m_H, 32,
m_CurrentNoiseState.m_CK + 32, nonce, payload.data (), len - 16, false)) // decrypt m_CurrentNoiseState.m_CK + 32, nonce, payload.data (), len - 16, false)) // decrypt
{ {
@ -1102,20 +1102,20 @@ namespace garlic
} }
HandlePayload (payload.data (), len - 16, nullptr, 0); HandlePayload (payload.data (), len - 16, nullptr, 0);
return true; return true;
} }
static size_t CreateGarlicPayload (std::shared_ptr<const I2NPMessage> msg, uint8_t * payload, static size_t CreateGarlicPayload (std::shared_ptr<const I2NPMessage> msg, uint8_t * payload,
bool datetime, size_t optimalSize) bool datetime, size_t optimalSize)
{ {
size_t len = 0; size_t len = 0;
if (datetime) if (datetime)
{ {
// DateTime // DateTime
payload[0] = eECIESx25519BlkDateTime; payload[0] = eECIESx25519BlkDateTime;
htobe16buf (payload + 1, 4); htobe16buf (payload + 1, 4);
htobe32buf (payload + 3, i2p::util::GetSecondsSinceEpoch ()); htobe32buf (payload + 3, i2p::util::GetSecondsSinceEpoch ());
len = 7; len = 7;
} }
// I2NP // I2NP
payload += len; payload += len;
uint16_t cloveSize = msg->GetPayloadLength () + 10; uint16_t cloveSize = msg->GetPayloadLength () + 10;
@ -1139,14 +1139,14 @@ namespace garlic
delta -= 3; delta -= 3;
if (paddingSize > delta) paddingSize %= delta; if (paddingSize > delta) paddingSize %= delta;
} }
payload[0] = eECIESx25519BlkPadding; payload[0] = eECIESx25519BlkPadding;
htobe16buf (payload + 1, paddingSize); htobe16buf (payload + 1, paddingSize);
if (paddingSize) memset (payload + 3, 0, paddingSize); if (paddingSize) memset (payload + 3, 0, paddingSize);
len += paddingSize + 3; len += paddingSize + 3;
} }
return len; return len;
} }
std::shared_ptr<I2NPMessage> WrapECIESX25519Message (std::shared_ptr<const I2NPMessage> msg, const uint8_t * key, uint64_t tag) std::shared_ptr<I2NPMessage> WrapECIESX25519Message (std::shared_ptr<const I2NPMessage> msg, const uint8_t * key, uint64_t tag)
{ {
auto m = NewI2NPMessage (); auto m = NewI2NPMessage ();
@ -1188,8 +1188,8 @@ namespace garlic
{ {
LogPrint (eLogWarning, "Garlic: Incorrect Bob static key"); LogPrint (eLogWarning, "Garlic: Incorrect Bob static key");
return nullptr; return nullptr;
} }
noiseState.MixKey (sharedSecret); noiseState.MixKey (sharedSecret);
auto payload = buf + offset; auto payload = buf + offset;
size_t len = CreateGarlicPayload (msg, payload, true, 900); // 1003 - 32 eph key - 16 Poly1305 hash - 16 I2NP header - 4 garlic length - 35 router tunnel delivery size_t len = CreateGarlicPayload (msg, payload, true, 900); // 1003 - 32 eph key - 16 Poly1305 hash - 16 I2NP header - 4 garlic length - 35 router tunnel delivery
uint8_t nonce[12]; uint8_t nonce[12];
@ -1205,6 +1205,6 @@ namespace garlic
m->len += offset + 4; m->len += offset + 4;
m->FillI2NPMessageHeader (eI2NPGarlic); m->FillI2NPMessageHeader (eI2NPGarlic);
return m; return m;
} }
} }
} }

View file

@ -452,7 +452,7 @@ namespace garlic
{ {
it.second->Terminate (); it.second->Terminate ();
it.second->SetOwner (nullptr); it.second->SetOwner (nullptr);
} }
m_ECIESx25519Sessions.clear (); m_ECIESx25519Sessions.clear ();
m_ECIESx25519Tags.clear (); m_ECIESx25519Tags.clear ();
} }
@ -470,14 +470,14 @@ namespace garlic
uint64_t t; uint64_t t;
memcpy (&t, tag, 8); memcpy (&t, tag, 8);
AddECIESx25519Key (key, t); AddECIESx25519Key (key, t);
} }
void GarlicDestination::AddECIESx25519Key (const uint8_t * key, uint64_t tag) void GarlicDestination::AddECIESx25519Key (const uint8_t * key, uint64_t tag)
{ {
auto tagset = std::make_shared<SymmetricKeyTagSet>(this, key); auto tagset = std::make_shared<SymmetricKeyTagSet>(this, key);
m_ECIESx25519Tags.emplace (tag, ECIESX25519AEADRatchetIndexTagset{0, tagset}); m_ECIESx25519Tags.emplace (tag, ECIESX25519AEADRatchetIndexTagset{0, tagset});
} }
bool GarlicDestination::SubmitSessionKey (const uint8_t * key, const uint8_t * tag) bool GarlicDestination::SubmitSessionKey (const uint8_t * key, const uint8_t * tag)
{ {
AddSessionKey (key, tag); AddSessionKey (key, tag);
@ -498,10 +498,10 @@ namespace garlic
bool found = false; bool found = false;
if (SupportsEncryptionType (i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD)) if (SupportsEncryptionType (i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD))
// try ECIESx25519 tag // try ECIESx25519 tag
found = HandleECIESx25519TagMessage (buf, length); found = HandleECIESx25519TagMessage (buf, length);
if (!found) if (!found)
{ {
auto it = !mod ? m_Tags.find (SessionTag(buf)) : m_Tags.end (); // AES block is multiple of 16 auto it = !mod ? m_Tags.find (SessionTag(buf)) : m_Tags.end (); // AES block is multiple of 16
// AES tag might be used even if encryption type is not ElGamal/AES // AES tag might be used even if encryption type is not ElGamal/AES
if (it != m_Tags.end ()) // try AES tag if (it != m_Tags.end ()) // try AES tag
@ -542,7 +542,7 @@ namespace garlic
auto session = std::make_shared<ECIESX25519AEADRatchetSession> (this, false); // incoming auto session = std::make_shared<ECIESX25519AEADRatchetSession> (this, false); // incoming
if (!session->HandleNextMessage (buf, length, nullptr, 0)) if (!session->HandleNextMessage (buf, length, nullptr, 0))
{ {
// try to gererate more tags for last tagset // try to gererate more tags for last tagset
if (m_LastTagset && (m_LastTagset->GetNextIndex () - m_LastTagset->GetTrimBehind () < 3*ECIESX25519_MAX_NUM_GENERATED_TAGS)) if (m_LastTagset && (m_LastTagset->GetNextIndex () - m_LastTagset->GetTrimBehind () < 3*ECIESX25519_MAX_NUM_GENERATED_TAGS))
{ {
uint64_t missingTag; memcpy (&missingTag, buf, 8); uint64_t missingTag; memcpy (&missingTag, buf, 8);
@ -555,24 +555,24 @@ namespace garlic
{ {
LogPrint (eLogError, "Garlic: can't create new ECIES-X25519-AEAD-Ratchet tag for last tagset"); LogPrint (eLogError, "Garlic: can't create new ECIES-X25519-AEAD-Ratchet tag for last tagset");
break; break;
} }
if (nextTag == missingTag) if (nextTag == missingTag)
{ {
LogPrint (eLogDebug, "Garlic: Missing ECIES-X25519-AEAD-Ratchet tag was generated"); LogPrint (eLogDebug, "Garlic: Missing ECIES-X25519-AEAD-Ratchet tag was generated");
if (m_LastTagset->HandleNextMessage (buf, length, m_ECIESx25519Tags[nextTag].index)) if (m_LastTagset->HandleNextMessage (buf, length, m_ECIESx25519Tags[nextTag].index))
found = true; found = true;
break; break;
} }
} }
if (!found) m_LastTagset = nullptr; if (!found) m_LastTagset = nullptr;
} }
if (!found) if (!found)
LogPrint (eLogError, "Garlic: can't handle ECIES-X25519-AEAD-Ratchet message"); LogPrint (eLogError, "Garlic: can't handle ECIES-X25519-AEAD-Ratchet message");
} }
} }
else else
LogPrint (eLogError, "Garlic: Failed to decrypt message"); LogPrint (eLogError, "Garlic: Failed to decrypt message");
} }
} }
} }
@ -585,14 +585,14 @@ namespace garlic
{ {
if (it->second.tagset->HandleNextMessage (buf, len, it->second.index)) if (it->second.tagset->HandleNextMessage (buf, len, it->second.index))
m_LastTagset = it->second.tagset; m_LastTagset = it->second.tagset;
else else
LogPrint (eLogError, "Garlic: can't handle ECIES-X25519-AEAD-Ratchet message"); LogPrint (eLogError, "Garlic: Can't handle ECIES-X25519-AEAD-Ratchet message");
m_ECIESx25519Tags.erase (it); m_ECIESx25519Tags.erase (it);
return true; return true;
} }
return false; return false;
} }
void GarlicDestination::HandleAESBlock (uint8_t * buf, size_t len, std::shared_ptr<AESDecryption> decryption, void GarlicDestination::HandleAESBlock (uint8_t * buf, size_t len, std::shared_ptr<AESDecryption> decryption,
std::shared_ptr<i2p::tunnel::InboundTunnel> from) std::shared_ptr<i2p::tunnel::InboundTunnel> from)
{ {
@ -629,7 +629,7 @@ namespace garlic
SHA256 (buf, payloadSize, digest); SHA256 (buf, payloadSize, digest);
if (memcmp (payloadHash, digest, 32)) // payload hash doesn't match if (memcmp (payloadHash, digest, 32)) // payload hash doesn't match
{ {
LogPrint (eLogError, "Garlic: wrong payload hash"); LogPrint (eLogError, "Garlic: Wrong payload hash");
return; return;
} }
HandleGarlicPayload (buf, payloadSize, from); HandleGarlicPayload (buf, payloadSize, from);
@ -639,7 +639,7 @@ namespace garlic
{ {
if (len < 1) if (len < 1)
{ {
LogPrint (eLogError, "Garlic: payload is too short"); LogPrint (eLogError, "Garlic: Payload is too short");
return; return;
} }
int numCloves = buf[0]; int numCloves = buf[0];
@ -654,7 +654,7 @@ namespace garlic
if (flag & 0x80) // encrypted? if (flag & 0x80) // encrypted?
{ {
// TODO: implement // TODO: implement
LogPrint (eLogWarning, "Garlic: clove encrypted"); LogPrint (eLogWarning, "Garlic: Clove encrypted");
buf += 32; buf += 32;
} }
ptrdiff_t offset = buf - buf1; ptrdiff_t offset = buf - buf1;
@ -662,35 +662,35 @@ namespace garlic
switch (deliveryType) switch (deliveryType)
{ {
case eGarlicDeliveryTypeLocal: case eGarlicDeliveryTypeLocal:
LogPrint (eLogDebug, "Garlic: type local"); LogPrint (eLogDebug, "Garlic: Type local");
if (offset > (int)len) if (offset > (int)len)
{ {
LogPrint (eLogError, "Garlic: message is too short"); LogPrint (eLogError, "Garlic: Message is too short");
break; break;
} }
HandleI2NPMessage (buf, len - offset); HandleI2NPMessage (buf, len - offset);
break; break;
case eGarlicDeliveryTypeDestination: case eGarlicDeliveryTypeDestination:
LogPrint (eLogDebug, "Garlic: type destination"); LogPrint (eLogDebug, "Garlic: Type destination");
buf += 32; // destination. check it later or for multiple destinations buf += 32; // destination. check it later or for multiple destinations
offset = buf - buf1; offset = buf - buf1;
if (offset > (int)len) if (offset > (int)len)
{ {
LogPrint (eLogError, "Garlic: message is too short"); LogPrint (eLogError, "Garlic: Message is too short");
break; break;
} }
HandleI2NPMessage (buf, len - offset); HandleI2NPMessage (buf, len - offset);
break; break;
case eGarlicDeliveryTypeTunnel: case eGarlicDeliveryTypeTunnel:
{ {
LogPrint (eLogDebug, "Garlic: type tunnel"); LogPrint (eLogDebug, "Garlic: Type tunnel");
// gwHash and gwTunnel sequence is reverted // gwHash and gwTunnel sequence is reverted
uint8_t * gwHash = buf; uint8_t * gwHash = buf;
buf += 32; buf += 32;
offset = buf - buf1; offset = buf - buf1;
if (offset + 4 > (int)len) if (offset + 4 > (int)len)
{ {
LogPrint (eLogError, "Garlic: message is too short"); LogPrint (eLogError, "Garlic: Message is too short");
break; break;
} }
uint32_t gwTunnel = bufbe32toh (buf); uint32_t gwTunnel = bufbe32toh (buf);
@ -721,22 +721,22 @@ namespace garlic
{ {
if (offset > (int)len) if (offset > (int)len)
{ {
LogPrint (eLogError, "Garlic: message is too short"); LogPrint (eLogError, "Garlic: Message is too short");
break; break;
} }
i2p::transport::transports.SendMessage (ident, i2p::transport::transports.SendMessage (ident,
CreateI2NPMessage (buf, GetI2NPMessageLength (buf, len - offset))); CreateI2NPMessage (buf, GetI2NPMessageLength (buf, len - offset)));
} }
else else
LogPrint (eLogWarning, "Garlic: type router for inbound tunnels not supported"); LogPrint (eLogWarning, "Garlic: Type router for inbound tunnels not supported");
break; break;
} }
default: default:
LogPrint (eLogWarning, "Garlic: unknown delivery type ", (int)deliveryType); LogPrint (eLogWarning, "Garlic: Unknown delivery type ", (int)deliveryType);
} }
if (offset > (int)len) if (offset > (int)len)
{ {
LogPrint (eLogError, "Garlic: message is too short"); LogPrint (eLogError, "Garlic: Message is too short");
break; break;
} }
buf += GetI2NPMessageLength (buf, len - offset); // I2NP buf += GetI2NPMessageLength (buf, len - offset); // I2NP
@ -746,7 +746,7 @@ namespace garlic
offset = buf - buf1; offset = buf - buf1;
if (offset > (int)len) if (offset > (int)len)
{ {
LogPrint (eLogError, "Garlic: clove is too long"); LogPrint (eLogError, "Garlic: Clove is too long");
break; break;
} }
len -= offset; len -= offset;
@ -759,10 +759,10 @@ namespace garlic
if (router->GetEncryptionType () == i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD) if (router->GetEncryptionType () == i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD)
return WrapECIESX25519MessageForRouter (msg, router->GetIdentity ()->GetEncryptionPublicKey ()); return WrapECIESX25519MessageForRouter (msg, router->GetIdentity ()->GetEncryptionPublicKey ());
else else
{ {
auto session = GetRoutingSession (router, false); auto session = GetRoutingSession (router, false);
return session->WrapSingleMessage (msg); return session->WrapSingleMessage (msg);
} }
} }
std::shared_ptr<GarlicRoutingSession> GarlicDestination::GetRoutingSession ( std::shared_ptr<GarlicRoutingSession> GarlicDestination::GetRoutingSession (
@ -776,14 +776,14 @@ namespace garlic
destination->Encrypt (nullptr, staticKey); // we are supposed to get static key destination->Encrypt (nullptr, staticKey); // we are supposed to get static key
auto it = m_ECIESx25519Sessions.find (staticKey); auto it = m_ECIESx25519Sessions.find (staticKey);
if (it != m_ECIESx25519Sessions.end ()) if (it != m_ECIESx25519Sessions.end ())
{ {
session = it->second; session = it->second;
if (session->IsInactive (i2p::util::GetSecondsSinceEpoch ())) if (session->IsInactive (i2p::util::GetSecondsSinceEpoch ()))
{ {
LogPrint (eLogDebug, "Garlic: session restarted"); LogPrint (eLogDebug, "Garlic: Session restarted");
session = nullptr; session = nullptr;
} }
} }
if (!session) if (!session)
{ {
session = std::make_shared<ECIESX25519AEADRatchetSession> (this, true); session = std::make_shared<ECIESX25519AEADRatchetSession> (this, true);
@ -879,18 +879,18 @@ namespace garlic
it->second.tagset->DeleteSymmKey (it->second.index); it->second.tagset->DeleteSymmKey (it->second.index);
it = m_ECIESx25519Tags.erase (it); it = m_ECIESx25519Tags.erase (it);
numExpiredTags++; numExpiredTags++;
} }
else else
{ {
auto session = it->second.tagset->GetSession (); auto session = it->second.tagset->GetSession ();
if (!session || session->IsTerminated()) if (!session || session->IsTerminated())
{ {
it = m_ECIESx25519Tags.erase (it); it = m_ECIESx25519Tags.erase (it);
numExpiredTags++; numExpiredTags++;
} }
else else
++it; ++it;
} }
} }
if (numExpiredTags > 0) if (numExpiredTags > 0)
LogPrint (eLogDebug, "Garlic: ", numExpiredTags, " ECIESx25519 tags expired for ", GetIdentHash().ToBase64 ()); LogPrint (eLogDebug, "Garlic: ", numExpiredTags, " ECIESx25519 tags expired for ", GetIdentHash().ToBase64 ());
@ -1030,7 +1030,7 @@ namespace garlic
switch (deliveryType) switch (deliveryType)
{ {
case eGarlicDeliveryTypeDestination: case eGarlicDeliveryTypeDestination:
LogPrint (eLogDebug, "Garlic: type destination"); LogPrint (eLogDebug, "Garlic: Type destination");
buf += 32; // TODO: check destination buf += 32; // TODO: check destination
#if (__cplusplus >= 201703L) // C++ 17 or higher #if (__cplusplus >= 201703L) // C++ 17 or higher
[[fallthrough]]; [[fallthrough]];
@ -1038,7 +1038,7 @@ namespace garlic
// no break here // no break here
case eGarlicDeliveryTypeLocal: case eGarlicDeliveryTypeLocal:
{ {
LogPrint (eLogDebug, "Garlic: type local"); LogPrint (eLogDebug, "Garlic: Type local");
I2NPMessageType typeID = (I2NPMessageType)(buf[0]); buf++; // typeid I2NPMessageType typeID = (I2NPMessageType)(buf[0]); buf++; // typeid
int32_t msgID = bufbe32toh (buf); buf += 4; // msgID int32_t msgID = bufbe32toh (buf); buf += 4; // msgID
buf += 4; // expiration buf += 4; // expiration
@ -1046,19 +1046,19 @@ namespace garlic
if (offset <= (int)len) if (offset <= (int)len)
HandleCloveI2NPMessage (typeID, buf, len - offset, msgID); HandleCloveI2NPMessage (typeID, buf, len - offset, msgID);
else else
LogPrint (eLogError, "Garlic: clove is too long"); LogPrint (eLogError, "Garlic: Clove is too long");
break; break;
} }
case eGarlicDeliveryTypeTunnel: case eGarlicDeliveryTypeTunnel:
{ {
LogPrint (eLogDebug, "Garlic: type tunnel"); LogPrint (eLogDebug, "Garlic: Type tunnel");
// gwHash and gwTunnel sequence is reverted // gwHash and gwTunnel sequence is reverted
const uint8_t * gwHash = buf; const uint8_t * gwHash = buf;
buf += 32; buf += 32;
ptrdiff_t offset = buf - buf1; ptrdiff_t offset = buf - buf1;
if (offset + 13 > (int)len) if (offset + 13 > (int)len)
{ {
LogPrint (eLogError, "Garlic: message is too short"); LogPrint (eLogError, "Garlic: Message is too short");
break; break;
} }
uint32_t gwTunnel = bufbe32toh (buf); buf += 4; uint32_t gwTunnel = bufbe32toh (buf); buf += 4;
@ -1079,7 +1079,7 @@ namespace garlic
break; break;
} }
default: default:
LogPrint (eLogWarning, "Garlic: unexpected delivery type ", (int)deliveryType); LogPrint (eLogWarning, "Garlic: Unexpected delivery type ", (int)deliveryType);
} }
} }
@ -1099,10 +1099,10 @@ namespace garlic
if (it != m_ECIESx25519Sessions.end ()) if (it != m_ECIESx25519Sessions.end ())
{ {
if (it->second->CanBeRestarted (i2p::util::GetSecondsSinceEpoch ())) if (it->second->CanBeRestarted (i2p::util::GetSecondsSinceEpoch ()))
{ {
it->second->Terminate (); // detach it->second->Terminate (); // detach
m_ECIESx25519Sessions.erase (it); m_ECIESx25519Sessions.erase (it);
} }
else else
{ {
LogPrint (eLogInfo, "Garlic: ECIESx25519 session with static key ", staticKeyTag.ToBase64 (), " already exists"); LogPrint (eLogInfo, "Garlic: ECIESx25519 session with static key ", staticKeyTag.ToBase64 (), " already exists");
@ -1127,6 +1127,6 @@ namespace garlic
if (!m_PayloadBuffer) if (!m_PayloadBuffer)
m_PayloadBuffer = new uint8_t[I2NP_MAX_MESSAGE_SIZE]; m_PayloadBuffer = new uint8_t[I2NP_MAX_MESSAGE_SIZE];
return m_PayloadBuffer; return m_PayloadBuffer;
} }
} }
} }

View file

@ -40,7 +40,7 @@ namespace i2p
{ {
I2NPMessage * msg = nullptr; I2NPMessage * msg = nullptr;
if (endpoint) if (endpoint)
{ {
// should fit two tunnel message + tunnel gateway header, enough for one garlic encrypted streaming packet // should fit two tunnel message + tunnel gateway header, enough for one garlic encrypted streaming packet
msg = new I2NPMessageBuffer<2*i2p::tunnel::TUNNEL_DATA_MSG_SIZE + I2NP_HEADER_SIZE + TUNNEL_GATEWAY_HEADER_SIZE + 28>(); // reserved for alignment and NTCP 16 + 6 + 6 msg = new I2NPMessageBuffer<2*i2p::tunnel::TUNNEL_DATA_MSG_SIZE + I2NP_HEADER_SIZE + TUNNEL_GATEWAY_HEADER_SIZE + 28>(); // reserved for alignment and NTCP 16 + 6 + 6
msg->Align (6); msg->Align (6);
@ -50,7 +50,7 @@ namespace i2p
{ {
msg = new I2NPMessageBuffer<i2p::tunnel::TUNNEL_DATA_MSG_SIZE + I2NP_HEADER_SIZE + 34>(); // reserved for alignment and NTCP 16 + 6 + 12 msg = new I2NPMessageBuffer<i2p::tunnel::TUNNEL_DATA_MSG_SIZE + I2NP_HEADER_SIZE + 34>(); // reserved for alignment and NTCP 16 + 6 + 12
msg->Align (12); msg->Align (12);
} }
return std::shared_ptr<I2NPMessage>(msg); return std::shared_ptr<I2NPMessage>(msg);
} }
@ -88,7 +88,7 @@ namespace i2p
{ {
auto msg = NewI2NPMessage (len); auto msg = NewI2NPMessage (len);
if (msg->Concat (buf, len) < len) if (msg->Concat (buf, len) < len)
LogPrint (eLogError, "I2NP: message length ", len, " exceeds max length ", msg->maxLen); LogPrint (eLogError, "I2NP: Message length ", len, " exceeds max length ", msg->maxLen);
msg->FillI2NPMessageHeader (msgType, replyMsgID); msg->FillI2NPMessageHeader (msgType, replyMsgID);
return msg; return msg;
} }
@ -103,7 +103,7 @@ namespace i2p
msg->from = from; msg->from = from;
} }
else else
LogPrint (eLogError, "I2NP: message length ", len, " exceeds max length"); LogPrint (eLogError, "I2NP: Message length ", len, " exceeds max length");
return msg; return msg;
} }
@ -183,7 +183,7 @@ namespace i2p
std::shared_ptr<I2NPMessage> CreateLeaseSetDatabaseLookupMsg (const i2p::data::IdentHash& dest, std::shared_ptr<I2NPMessage> CreateLeaseSetDatabaseLookupMsg (const i2p::data::IdentHash& dest,
const std::set<i2p::data::IdentHash>& excludedFloodfills, const std::set<i2p::data::IdentHash>& excludedFloodfills,
std::shared_ptr<const i2p::tunnel::InboundTunnel> replyTunnel, const uint8_t * replyKey, std::shared_ptr<const i2p::tunnel::InboundTunnel> replyTunnel, const uint8_t * replyKey,
const uint8_t * replyTag, bool replyECIES) const uint8_t * replyTag, bool replyECIES)
{ {
int cnt = excludedFloodfills.size (); int cnt = excludedFloodfills.size ();
@ -222,12 +222,12 @@ namespace i2p
{ {
memcpy (buf + 33, replyTag, 8); // 8 bytes tag memcpy (buf + 33, replyTag, 8); // 8 bytes tag
buf += 41; buf += 41;
} }
else else
{ {
memcpy (buf + 33, replyTag, 32); // 32 bytes tag memcpy (buf + 33, replyTag, 32); // 32 bytes tag
buf += 65; buf += 65;
} }
m->len += (buf - m->GetPayload ()); m->len += (buf - m->GetPayload ());
m->FillI2NPMessageHeader (eI2NPDatabaseLookup); m->FillI2NPMessageHeader (eI2NPDatabaseLookup);
@ -256,7 +256,7 @@ namespace i2p
return m; return m;
} }
std::shared_ptr<I2NPMessage> CreateDatabaseStoreMsg (std::shared_ptr<const i2p::data::RouterInfo> router, std::shared_ptr<I2NPMessage> CreateDatabaseStoreMsg (std::shared_ptr<const i2p::data::RouterInfo> router,
uint32_t replyToken, std::shared_ptr<const i2p::tunnel::InboundTunnel> replyTunnel) uint32_t replyToken, std::shared_ptr<const i2p::tunnel::InboundTunnel> replyTunnel)
{ {
if (!router) // we send own RouterInfo if (!router) // we send own RouterInfo
@ -267,7 +267,7 @@ namespace i2p
LogPrint (eLogError, "I2NP: Invalid RouterInfo buffer for DatabaseStore"); LogPrint (eLogError, "I2NP: Invalid RouterInfo buffer for DatabaseStore");
return nullptr; return nullptr;
} }
auto m = NewI2NPShortMessage (); auto m = NewI2NPShortMessage ();
uint8_t * payload = m->GetPayload (); uint8_t * payload = m->GetPayload ();
@ -285,12 +285,12 @@ namespace i2p
buf += 32; // reply tunnel gateway buf += 32; // reply tunnel gateway
} }
else else
{ {
memset (buf, 0, 4); // zero tunnelID means direct reply memset (buf, 0, 4); // zero tunnelID means direct reply
buf += 4; buf += 4;
memcpy (buf, context.GetIdentHash (), 32); memcpy (buf, context.GetIdentHash (), 32);
buf += 32; buf += 32;
} }
} }
uint8_t * sizePtr = buf; uint8_t * sizePtr = buf;
@ -303,7 +303,7 @@ namespace i2p
{ {
i2p::data::GzipDeflator deflator; i2p::data::GzipDeflator deflator;
size = deflator.Deflate (router->GetBuffer (), router->GetBufferLen (), buf, m->maxLen -m->len); size = deflator.Deflate (router->GetBuffer (), router->GetBufferLen (), buf, m->maxLen -m->len);
} }
if (size) if (size)
{ {
htobe16buf (sizePtr, size); // size htobe16buf (sizePtr, size); // size
@ -560,8 +560,8 @@ namespace i2p
{ {
LogPrint (eLogDebug, "I2NP: Short request record ", i, " is ours"); LogPrint (eLogDebug, "I2NP: Short request record ", i, " is ours");
uint8_t clearText[SHORT_REQUEST_RECORD_CLEAR_TEXT_SIZE]; uint8_t clearText[SHORT_REQUEST_RECORD_CLEAR_TEXT_SIZE];
if (!i2p::context.DecryptTunnelShortRequestRecord (record + SHORT_REQUEST_RECORD_ENCRYPTED_OFFSET, clearText)) if (!i2p::context.DecryptTunnelShortRequestRecord (record + SHORT_REQUEST_RECORD_ENCRYPTED_OFFSET, clearText))
{ {
LogPrint (eLogWarning, "I2NP: Can't decrypt short request record ", i); LogPrint (eLogWarning, "I2NP: Can't decrypt short request record ", i);
return; return;
} }
@ -569,19 +569,19 @@ namespace i2p
{ {
LogPrint (eLogWarning, "I2NP: Unknown layer encryption type ", clearText[SHORT_REQUEST_RECORD_LAYER_ENCRYPTION_TYPE], " in short request record"); LogPrint (eLogWarning, "I2NP: Unknown layer encryption type ", clearText[SHORT_REQUEST_RECORD_LAYER_ENCRYPTION_TYPE], " in short request record");
return; return;
} }
auto& noiseState = i2p::context.GetCurrentNoiseState (); auto& noiseState = i2p::context.GetCurrentNoiseState ();
uint8_t replyKey[32], layerKey[32], ivKey[32]; uint8_t replyKey[32], layerKey[32], ivKey[32];
i2p::crypto::HKDF (noiseState.m_CK, nullptr, 0, "SMTunnelReplyKey", noiseState.m_CK); i2p::crypto::HKDF (noiseState.m_CK, nullptr, 0, "SMTunnelReplyKey", noiseState.m_CK);
memcpy (replyKey, noiseState.m_CK + 32, 32); memcpy (replyKey, noiseState.m_CK + 32, 32);
i2p::crypto::HKDF (noiseState.m_CK, nullptr, 0, "SMTunnelLayerKey", noiseState.m_CK); i2p::crypto::HKDF (noiseState.m_CK, nullptr, 0, "SMTunnelLayerKey", noiseState.m_CK);
memcpy (layerKey, noiseState.m_CK + 32, 32); memcpy (layerKey, noiseState.m_CK + 32, 32);
bool isEndpoint = clearText[SHORT_REQUEST_RECORD_FLAG_OFFSET] & TUNNEL_BUILD_RECORD_ENDPOINT_FLAG; bool isEndpoint = clearText[SHORT_REQUEST_RECORD_FLAG_OFFSET] & TUNNEL_BUILD_RECORD_ENDPOINT_FLAG;
if (isEndpoint) if (isEndpoint)
{ {
i2p::crypto::HKDF (noiseState.m_CK, nullptr, 0, "TunnelLayerIVKey", noiseState.m_CK); i2p::crypto::HKDF (noiseState.m_CK, nullptr, 0, "TunnelLayerIVKey", noiseState.m_CK);
memcpy (ivKey, noiseState.m_CK + 32, 32); memcpy (ivKey, noiseState.m_CK + 32, 32);
} }
else else
memcpy (ivKey, noiseState.m_CK , 32); memcpy (ivKey, noiseState.m_CK , 32);
@ -593,7 +593,7 @@ namespace i2p
i2p::transport::transports.IsTransitBandwidthExceeded ()) i2p::transport::transports.IsTransitBandwidthExceeded ())
retCode = 30; retCode = 30;
if (!retCode) if (!retCode)
{ {
// create new transit tunnel // create new transit tunnel
auto transitTunnel = i2p::tunnel::CreateTransitTunnel ( auto transitTunnel = i2p::tunnel::CreateTransitTunnel (
bufbe32toh (clearText + SHORT_REQUEST_RECORD_RECEIVE_TUNNEL_OFFSET), bufbe32toh (clearText + SHORT_REQUEST_RECORD_RECEIVE_TUNNEL_OFFSET),
@ -604,46 +604,46 @@ namespace i2p
clearText[SHORT_REQUEST_RECORD_FLAG_OFFSET] & TUNNEL_BUILD_RECORD_ENDPOINT_FLAG); clearText[SHORT_REQUEST_RECORD_FLAG_OFFSET] & TUNNEL_BUILD_RECORD_ENDPOINT_FLAG);
i2p::tunnel::tunnels.AddTransitTunnel (transitTunnel); i2p::tunnel::tunnels.AddTransitTunnel (transitTunnel);
} }
// encrypt reply // encrypt reply
uint8_t nonce[12]; uint8_t nonce[12];
memset (nonce, 0, 12); memset (nonce, 0, 12);
uint8_t * reply = buf + 1; uint8_t * reply = buf + 1;
for (int j = 0; j < num; j++) for (int j = 0; j < num; j++)
{ {
nonce[4] = j; // nonce is record # nonce[4] = j; // nonce is record #
if (j == i) if (j == i)
{ {
memset (reply + SHORT_RESPONSE_RECORD_OPTIONS_OFFSET, 0, 2); // no options memset (reply + SHORT_RESPONSE_RECORD_OPTIONS_OFFSET, 0, 2); // no options
reply[SHORT_RESPONSE_RECORD_RET_OFFSET] = retCode; reply[SHORT_RESPONSE_RECORD_RET_OFFSET] = retCode;
if (!i2p::crypto::AEADChaCha20Poly1305 (reply, SHORT_TUNNEL_BUILD_RECORD_SIZE - 16, if (!i2p::crypto::AEADChaCha20Poly1305 (reply, SHORT_TUNNEL_BUILD_RECORD_SIZE - 16,
noiseState.m_H, 32, replyKey, nonce, reply, SHORT_TUNNEL_BUILD_RECORD_SIZE, true)) // encrypt noiseState.m_H, 32, replyKey, nonce, reply, SHORT_TUNNEL_BUILD_RECORD_SIZE, true)) // encrypt
{ {
LogPrint (eLogWarning, "I2NP: Short reply AEAD encryption failed"); LogPrint (eLogWarning, "I2NP: Short reply AEAD encryption failed");
return; return;
} }
} }
else else
i2p::crypto::ChaCha20 (reply, SHORT_TUNNEL_BUILD_RECORD_SIZE, replyKey, nonce, reply); i2p::crypto::ChaCha20 (reply, SHORT_TUNNEL_BUILD_RECORD_SIZE, replyKey, nonce, reply);
reply += SHORT_TUNNEL_BUILD_RECORD_SIZE; reply += SHORT_TUNNEL_BUILD_RECORD_SIZE;
} }
// send reply // send reply
if (isEndpoint) if (isEndpoint)
{ {
auto replyMsg = NewI2NPShortMessage (); auto replyMsg = NewI2NPShortMessage ();
replyMsg->Concat (buf, len); replyMsg->Concat (buf, len);
replyMsg->FillI2NPMessageHeader (eI2NPShortTunnelBuildReply, bufbe32toh (clearText + SHORT_REQUEST_RECORD_SEND_MSG_ID_OFFSET)); replyMsg->FillI2NPMessageHeader (eI2NPShortTunnelBuildReply, bufbe32toh (clearText + SHORT_REQUEST_RECORD_SEND_MSG_ID_OFFSET));
if (memcmp ((const uint8_t *)i2p::context.GetIdentHash (), if (memcmp ((const uint8_t *)i2p::context.GetIdentHash (),
clearText + SHORT_REQUEST_RECORD_NEXT_IDENT_OFFSET, 32)) // reply IBGW is not local? clearText + SHORT_REQUEST_RECORD_NEXT_IDENT_OFFSET, 32)) // reply IBGW is not local?
{ {
i2p::crypto::HKDF (noiseState.m_CK, nullptr, 0, "RGarlicKeyAndTag", noiseState.m_CK); i2p::crypto::HKDF (noiseState.m_CK, nullptr, 0, "RGarlicKeyAndTag", noiseState.m_CK);
uint64_t tag; uint64_t tag;
memcpy (&tag, noiseState.m_CK, 8); memcpy (&tag, noiseState.m_CK, 8);
// we send it to reply tunnel // we send it to reply tunnel
transports.SendMessage (clearText + SHORT_REQUEST_RECORD_NEXT_IDENT_OFFSET, transports.SendMessage (clearText + SHORT_REQUEST_RECORD_NEXT_IDENT_OFFSET,
CreateTunnelGatewayMsg (bufbe32toh (clearText + SHORT_REQUEST_RECORD_NEXT_TUNNEL_OFFSET), CreateTunnelGatewayMsg (bufbe32toh (clearText + SHORT_REQUEST_RECORD_NEXT_TUNNEL_OFFSET),
i2p::garlic::WrapECIESX25519Message (replyMsg, noiseState.m_CK + 32, tag))); i2p::garlic::WrapECIESX25519Message (replyMsg, noiseState.m_CK + 32, tag)));
} }
else else
{ {
// IBGW is local // IBGW is local
@ -653,18 +653,18 @@ namespace i2p
tunnel->SendTunnelDataMsg (replyMsg); tunnel->SendTunnelDataMsg (replyMsg);
else else
LogPrint (eLogWarning, "I2NP: Tunnel ", tunnelID, " not found for short tunnel build reply"); LogPrint (eLogWarning, "I2NP: Tunnel ", tunnelID, " not found for short tunnel build reply");
} }
} }
else else
transports.SendMessage (clearText + SHORT_REQUEST_RECORD_NEXT_IDENT_OFFSET, transports.SendMessage (clearText + SHORT_REQUEST_RECORD_NEXT_IDENT_OFFSET,
CreateI2NPMessage (eI2NPShortTunnelBuild, buf, len, CreateI2NPMessage (eI2NPShortTunnelBuild, buf, len,
bufbe32toh (clearText + SHORT_REQUEST_RECORD_SEND_MSG_ID_OFFSET))); bufbe32toh (clearText + SHORT_REQUEST_RECORD_SEND_MSG_ID_OFFSET)));
return; return;
} }
record += SHORT_TUNNEL_BUILD_RECORD_SIZE; record += SHORT_TUNNEL_BUILD_RECORD_SIZE;
} }
} }
std::shared_ptr<I2NPMessage> CreateTunnelDataMsg (const uint8_t * buf) std::shared_ptr<I2NPMessage> CreateTunnelDataMsg (const uint8_t * buf)
{ {
auto msg = NewI2NPTunnelMessage (false); auto msg = NewI2NPTunnelMessage (false);
@ -698,7 +698,7 @@ namespace i2p
htobe16buf (payload + TUNNEL_GATEWAY_HEADER_LENGTH_OFFSET, len); htobe16buf (payload + TUNNEL_GATEWAY_HEADER_LENGTH_OFFSET, len);
msg->len += TUNNEL_GATEWAY_HEADER_SIZE; msg->len += TUNNEL_GATEWAY_HEADER_SIZE;
if (msg->Concat (buf, len) < len) if (msg->Concat (buf, len) < len)
LogPrint (eLogError, "I2NP: tunnel gateway buffer overflow ", msg->maxLen); LogPrint (eLogError, "I2NP: Tunnel gateway buffer overflow ", msg->maxLen);
msg->FillI2NPMessageHeader (eI2NPTunnelGateway); msg->FillI2NPMessageHeader (eI2NPTunnelGateway);
return msg; return msg;
} }
@ -729,7 +729,7 @@ namespace i2p
msg->offset += gatewayMsgOffset; msg->offset += gatewayMsgOffset;
msg->len += gatewayMsgOffset; msg->len += gatewayMsgOffset;
if (msg->Concat (buf, len) < len) if (msg->Concat (buf, len) < len)
LogPrint (eLogError, "I2NP: tunnel gateway buffer overflow ", msg->maxLen); LogPrint (eLogError, "I2NP: Tunnel gateway buffer overflow ", msg->maxLen);
msg->FillI2NPMessageHeader (msgType, replyMsgID); // create content message msg->FillI2NPMessageHeader (msgType, replyMsgID); // create content message
len = msg->GetLength (); len = msg->GetLength ();
msg->offset -= gatewayMsgOffset; msg->offset -= gatewayMsgOffset;
@ -744,13 +744,13 @@ namespace i2p
{ {
if (len < I2NP_HEADER_SIZE_OFFSET + 2) if (len < I2NP_HEADER_SIZE_OFFSET + 2)
{ {
LogPrint (eLogError, "I2NP: message length ", len, " is smaller than header"); LogPrint (eLogError, "I2NP: Message length ", len, " is smaller than header");
return len; return len;
} }
auto l = bufbe16toh (msg + I2NP_HEADER_SIZE_OFFSET) + I2NP_HEADER_SIZE; auto l = bufbe16toh (msg + I2NP_HEADER_SIZE_OFFSET) + I2NP_HEADER_SIZE;
if (l > len) if (l > len)
{ {
LogPrint (eLogError, "I2NP: message length ", l, " exceeds buffer length ", len); LogPrint (eLogError, "I2NP: Message length ", l, " exceeds buffer length ", len);
l = len; l = len;
} }
return l; return l;
@ -760,18 +760,18 @@ namespace i2p
{ {
if (len < I2NP_HEADER_SIZE) if (len < I2NP_HEADER_SIZE)
{ {
LogPrint (eLogError, "I2NP: message length ", len, " is smaller than header"); LogPrint (eLogError, "I2NP: Message length ", len, " is smaller than header");
return; return;
} }
uint8_t typeID = msg[I2NP_HEADER_TYPEID_OFFSET]; uint8_t typeID = msg[I2NP_HEADER_TYPEID_OFFSET];
uint32_t msgID = bufbe32toh (msg + I2NP_HEADER_MSGID_OFFSET); uint32_t msgID = bufbe32toh (msg + I2NP_HEADER_MSGID_OFFSET);
LogPrint (eLogDebug, "I2NP: msg received len=", len,", type=", (int)typeID, ", msgID=", (unsigned int)msgID); LogPrint (eLogDebug, "I2NP: Message received len=", len,", type=", (int)typeID, ", msgID=", (unsigned int)msgID);
uint8_t * buf = msg + I2NP_HEADER_SIZE; uint8_t * buf = msg + I2NP_HEADER_SIZE;
auto size = bufbe16toh (msg + I2NP_HEADER_SIZE_OFFSET); auto size = bufbe16toh (msg + I2NP_HEADER_SIZE_OFFSET);
len -= I2NP_HEADER_SIZE; len -= I2NP_HEADER_SIZE;
if (size > len) if (size > len)
{ {
LogPrint (eLogError, "I2NP: payload size ", size, " exceeds buffer length ", len); LogPrint (eLogError, "I2NP: Payload size ", size, " exceeds buffer length ", len);
size = len; size = len;
} }
switch (typeID) switch (typeID)
@ -781,13 +781,13 @@ namespace i2p
break; break;
case eI2NPShortTunnelBuild: case eI2NPShortTunnelBuild:
HandleShortTunnelBuildMsg (msgID, buf, size); HandleShortTunnelBuildMsg (msgID, buf, size);
break; break;
case eI2NPVariableTunnelBuildReply: case eI2NPVariableTunnelBuildReply:
HandleTunnelBuildReplyMsg (msgID, buf, size, false); HandleTunnelBuildReplyMsg (msgID, buf, size, false);
break; break;
case eI2NPShortTunnelBuildReply: case eI2NPShortTunnelBuildReply:
HandleTunnelBuildReplyMsg (msgID, buf, size, true); HandleTunnelBuildReplyMsg (msgID, buf, size, true);
break; break;
case eI2NPTunnelBuild: case eI2NPTunnelBuild:
HandleTunnelBuildMsg (buf, size); HandleTunnelBuildMsg (buf, size);
break; break;
@ -844,8 +844,8 @@ namespace i2p
case eI2NPVariableTunnelBuildReply: case eI2NPVariableTunnelBuildReply:
case eI2NPTunnelBuild: case eI2NPTunnelBuild:
case eI2NPTunnelBuildReply: case eI2NPTunnelBuildReply:
case eI2NPShortTunnelBuild: case eI2NPShortTunnelBuild:
case eI2NPShortTunnelBuildReply: case eI2NPShortTunnelBuildReply:
// forward to tunnel thread // forward to tunnel thread
i2p::tunnel::tunnels.PostTunnelData (msg); i2p::tunnel::tunnels.PostTunnelData (msg);
break; break;

View file

@ -52,9 +52,9 @@ namespace data
{ {
memcpy (m_StandardIdentity.publicKey, publicKey, 32); memcpy (m_StandardIdentity.publicKey, publicKey, 32);
RAND_bytes (m_StandardIdentity.publicKey + 32, 224); RAND_bytes (m_StandardIdentity.publicKey + 32, 224);
} }
else else
memcpy (m_StandardIdentity.publicKey, publicKey, 256); memcpy (m_StandardIdentity.publicKey, publicKey, 256);
if (type != SIGNING_KEY_TYPE_DSA_SHA1) if (type != SIGNING_KEY_TYPE_DSA_SHA1)
{ {
size_t excessLen = 0; size_t excessLen = 0;
@ -214,7 +214,7 @@ namespace data
{ {
if (len < DEFAULT_IDENTITY_SIZE) if (len < DEFAULT_IDENTITY_SIZE)
{ {
LogPrint (eLogError, "Identity: buffer length ", len, " is too small"); LogPrint (eLogError, "Identity: Buffer length ", len, " is too small");
return 0; return 0;
} }
memcpy (&m_StandardIdentity, buf, DEFAULT_IDENTITY_SIZE); memcpy (&m_StandardIdentity, buf, DEFAULT_IDENTITY_SIZE);
@ -479,7 +479,7 @@ namespace data
size_t ret = m_Public->FromBuffer (buf, len); size_t ret = m_Public->FromBuffer (buf, len);
auto cryptoKeyLen = GetPrivateKeyLen (); auto cryptoKeyLen = GetPrivateKeyLen ();
if (!ret || ret + cryptoKeyLen > len) return 0; // overflow if (!ret || ret + cryptoKeyLen > len) return 0; // overflow
memcpy (m_PrivateKey, buf + ret, cryptoKeyLen); memcpy (m_PrivateKey, buf + ret, cryptoKeyLen);
ret += cryptoKeyLen; ret += cryptoKeyLen;
size_t signingPrivateKeySize = m_Public->GetSigningPrivateKeyLen (); size_t signingPrivateKeySize = m_Public->GetSigningPrivateKeyLen ();
if(signingPrivateKeySize + ret > len || signingPrivateKeySize > 128) return 0; // overflow if(signingPrivateKeySize + ret > len || signingPrivateKeySize > 128) return 0; // overflow
@ -653,9 +653,9 @@ namespace data
size_t PrivateKeys::GetPrivateKeyLen () const size_t PrivateKeys::GetPrivateKeyLen () const
{ {
// private key length always 256, but type 4 // private key length always 256, but type 4
return (m_Public->GetCryptoKeyType () == CRYPTO_KEY_TYPE_ECIES_X25519_AEAD) ? 32 : 256; return (m_Public->GetCryptoKeyType () == CRYPTO_KEY_TYPE_ECIES_X25519_AEAD) ? 32 : 256;
} }
uint8_t * PrivateKeys::GetPadding() uint8_t * PrivateKeys::GetPadding()
{ {
if(m_Public->GetSigningKeyType () == SIGNING_KEY_TYPE_EDDSA_SHA512_ED25519) if(m_Public->GetSigningKeyType () == SIGNING_KEY_TYPE_EDDSA_SHA512_ED25519)
@ -680,7 +680,7 @@ namespace data
break; break;
case CRYPTO_KEY_TYPE_ECIES_X25519_AEAD: case CRYPTO_KEY_TYPE_ECIES_X25519_AEAD:
return std::make_shared<i2p::crypto::ECIESX25519AEADRatchetDecryptor>(key); return std::make_shared<i2p::crypto::ECIESX25519AEADRatchetDecryptor>(key);
break; break;
case CRYPTO_KEY_TYPE_ECIES_P256_SHA256_AES256CBC: case CRYPTO_KEY_TYPE_ECIES_P256_SHA256_AES256CBC:
case CRYPTO_KEY_TYPE_ECIES_P256_SHA256_AES256CBC_TEST: case CRYPTO_KEY_TYPE_ECIES_P256_SHA256_AES256CBC_TEST:
return std::make_shared<i2p::crypto::ECIESP256Decryptor>(key); return std::make_shared<i2p::crypto::ECIESP256Decryptor>(key);

View file

@ -77,23 +77,23 @@ namespace data
LogPrint (eLogError, "LeaseSet: ", size, " exceeds buffer size ", m_BufferLen); LogPrint (eLogError, "LeaseSet: ", size, " exceeds buffer size ", m_BufferLen);
m_IsValid = false; m_IsValid = false;
return; return;
} }
uint8_t num = m_Buffer[size]; uint8_t num = m_Buffer[size];
size++; // num size++; // num
LogPrint (eLogDebug, "LeaseSet: read num=", (int)num); LogPrint (eLogDebug, "LeaseSet: read num=", (int)num);
if (!num || num > MAX_NUM_LEASES) if (!num || num > MAX_NUM_LEASES)
{ {
LogPrint (eLogError, "LeaseSet: incorrect number of leases", (int)num); LogPrint (eLogError, "LeaseSet: Incorrect number of leases", (int)num);
m_IsValid = false; m_IsValid = false;
return; return;
} }
if (size + num*LEASE_SIZE > m_BufferLen) if (size + num*LEASE_SIZE > m_BufferLen)
{ {
LogPrint (eLogError, "LeaseSet: ", size, " exceeds buffer size ", m_BufferLen); LogPrint (eLogError, "LeaseSet: ", size, " exceeds buffer size ", m_BufferLen);
m_IsValid = false; m_IsValid = false;
return; return;
} }
UpdateLeasesBegin (); UpdateLeasesBegin ();
// process leases // process leases
m_ExpirationTime = 0; m_ExpirationTime = 0;
@ -112,7 +112,7 @@ namespace data
} }
if (!m_ExpirationTime) if (!m_ExpirationTime)
{ {
LogPrint (eLogWarning, "LeaseSet: all leases are expired. Dropped"); LogPrint (eLogWarning, "LeaseSet: All leases have expired, dropping");
m_IsValid = false; m_IsValid = false;
return; return;
} }
@ -121,16 +121,16 @@ namespace data
// verify // verify
if (verifySignature) if (verifySignature)
{ {
auto signedSize = leases - m_Buffer; auto signedSize = leases - m_Buffer;
if (signedSize + m_Identity->GetSignatureLen () > m_BufferLen) if (signedSize + m_Identity->GetSignatureLen () > m_BufferLen)
{ {
LogPrint (eLogError, "LeaseSet: Signature exceeds buffer size ", m_BufferLen); LogPrint (eLogError, "LeaseSet: Signature exceeds buffer size ", m_BufferLen);
m_IsValid = false; m_IsValid = false;
} }
else if (!m_Identity->Verify (m_Buffer, signedSize, leases)) else if (!m_Identity->Verify (m_Buffer, signedSize, leases))
{ {
LogPrint (eLogWarning, "LeaseSet: verification failed"); LogPrint (eLogWarning, "LeaseSet: Verification failed");
m_IsValid = false; m_IsValid = false;
} }
} }
@ -274,7 +274,7 @@ namespace data
{ {
if (len <= m_BufferLen) m_BufferLen = len; if (len <= m_BufferLen) m_BufferLen = len;
else else
LogPrint (eLogError, "LeaseSet2: actual buffer size ", len , " exceeds full buffer size ", m_BufferLen); LogPrint (eLogError, "LeaseSet2: Actual buffer size ", len , " exceeds full buffer size ", m_BufferLen);
} }
LeaseSet2::LeaseSet2 (uint8_t storeType, const uint8_t * buf, size_t len, bool storeLeases, CryptoKeyType preferredCrypto): LeaseSet2::LeaseSet2 (uint8_t storeType, const uint8_t * buf, size_t len, bool storeLeases, CryptoKeyType preferredCrypto):
@ -331,7 +331,7 @@ namespace data
m_TransientVerifier = ProcessOfflineSignature (identity, buf, len, offset); m_TransientVerifier = ProcessOfflineSignature (identity, buf, len, offset);
if (!m_TransientVerifier) if (!m_TransientVerifier)
{ {
LogPrint (eLogError, "LeaseSet2: offline signature failed"); LogPrint (eLogError, "LeaseSet2: Offline signature failed");
return; return;
} }
} }
@ -378,7 +378,7 @@ namespace data
bool verified = verifier->Verify (buf - 1, signatureOffset + 1, buf + signatureOffset); bool verified = verifier->Verify (buf - 1, signatureOffset + 1, buf + signatureOffset);
const_cast<uint8_t *>(buf)[-1] = c; const_cast<uint8_t *>(buf)[-1] = c;
if (!verified) if (!verified)
LogPrint (eLogWarning, "LeaseSet2: verification failed"); LogPrint (eLogWarning, "LeaseSet2: Verification failed");
return verified; return verified;
} }
@ -489,7 +489,7 @@ namespace data
m_TransientVerifier = ProcessOfflineSignature (blindedVerifier, buf, len, offset); m_TransientVerifier = ProcessOfflineSignature (blindedVerifier, buf, len, offset);
if (!m_TransientVerifier) if (!m_TransientVerifier)
{ {
LogPrint (eLogError, "LeaseSet2: offline signature failed"); LogPrint (eLogError, "LeaseSet2: Offline signature failed");
return; return;
} }
} }
@ -515,7 +515,7 @@ namespace data
key->GetBlindedKey (date, blinded.data ()); key->GetBlindedKey (date, blinded.data ());
if (memcmp (blindedPublicKey, blinded.data (), blindedKeyLen)) if (memcmp (blindedPublicKey, blinded.data (), blindedKeyLen))
{ {
LogPrint (eLogError, "LeaseSet2: blinded public key doesn't match"); LogPrint (eLogError, "LeaseSet2: Blinded public key doesn't match");
return; return;
} }
} }
@ -569,7 +569,7 @@ namespace data
ReadFromBuffer (innerPlainText.data () + 1, lenInnerPlaintext - 1); ReadFromBuffer (innerPlainText.data () + 1, lenInnerPlaintext - 1);
} }
else else
LogPrint (eLogError, "LeaseSet2: unexpected LeaseSet type ", (int)innerPlainText[0], " inside encrypted LeaseSet"); LogPrint (eLogError, "LeaseSet2: Unexpected LeaseSet type ", (int)innerPlainText[0], " inside encrypted LeaseSet");
} }
else else
{ {
@ -653,7 +653,7 @@ namespace data
LogPrint (eLogError, "LeaseSet2: Can't calculate authCookie: psk_i is not provided"); LogPrint (eLogError, "LeaseSet2: Can't calculate authCookie: psk_i is not provided");
} }
else else
LogPrint (eLogError, "LeaseSet2: unknown client auth type ", (int)flag); LogPrint (eLogError, "LeaseSet2: Unknown client auth type ", (int)flag);
} }
return offset - 1; return offset - 1;
} }
@ -768,7 +768,7 @@ namespace data
size_t size = ident.GetFullLen (); size_t size = ident.GetFullLen ();
if (size > sz) if (size > sz)
{ {
LogPrint (eLogError, "LeaseSet: identity length ", size, " exceeds buffer size ", sz); LogPrint (eLogError, "LeaseSet: Identity length ", size, " exceeds buffer size ", sz);
return false; return false;
} }
// encryption key // encryption key
@ -779,7 +779,7 @@ namespace data
++size; ++size;
if (!numLeases || numLeases > MAX_NUM_LEASES) if (!numLeases || numLeases > MAX_NUM_LEASES)
{ {
LogPrint (eLogError, "LeaseSet: incorrect number of leases", (int)numLeases); LogPrint (eLogError, "LeaseSet: Incorrect number of leases", (int)numLeases);
return false; return false;
} }
const uint8_t * leases = ptr + size; const uint8_t * leases = ptr + size;
@ -863,17 +863,17 @@ namespace data
} }
// update expiration // update expiration
if (expirationTime) if (expirationTime)
{ {
SetExpirationTime (expirationTime*1000LL); SetExpirationTime (expirationTime*1000LL);
auto expires = (int)expirationTime - timestamp; auto expires = (int)expirationTime - timestamp;
htobe16buf (expiresBuf, expires > 0 ? expires : 0); htobe16buf (expiresBuf, expires > 0 ? expires : 0);
} }
else else
{ {
// no tunnels or withdraw // no tunnels or withdraw
SetExpirationTime (timestamp*1000LL); SetExpirationTime (timestamp*1000LL);
memset (expiresBuf, 0, 2); // expires immeditely memset (expiresBuf, 0, 2); // expires immeditely
} }
// sign // sign
keys.Sign (m_Buffer, offset, m_Buffer + offset); // LS + leading store type keys.Sign (m_Buffer, offset, m_Buffer + offset); // LS + leading store type
} }
@ -979,7 +979,7 @@ namespace data
m_StoreHash = blindedKey->GetStoreHash (); m_StoreHash = blindedKey->GetStoreHash ();
} }
else else
LogPrint (eLogError, "LeaseSet2: couldn't extract inner layer"); LogPrint (eLogError, "LeaseSet2: Couldn't extract inner layer");
} }
void LocalEncryptedLeaseSet2::CreateClientAuthData (const uint8_t * subcredential, int authType, std::shared_ptr<std::vector<AuthPublicKey> > authKeys, const uint8_t * authCookie, uint8_t * authData) const void LocalEncryptedLeaseSet2::CreateClientAuthData (const uint8_t * subcredential, int authType, std::shared_ptr<std::vector<AuthPublicKey> > authKeys, const uint8_t * authCookie, uint8_t * authData) const

View file

@ -129,10 +129,10 @@ namespace log {
else if (level == "info") { m_MinLevel = eLogInfo; } else if (level == "info") { m_MinLevel = eLogInfo; }
else if (level == "debug") { m_MinLevel = eLogDebug; } else if (level == "debug") { m_MinLevel = eLogDebug; }
else { else {
LogPrint(eLogError, "Log: unknown loglevel: ", level); LogPrint(eLogError, "Log: Unknown loglevel: ", level);
return; return;
} }
LogPrint(eLogInfo, "Log: min messages level set to ", level); LogPrint(eLogInfo, "Log: Logging level set to ", level);
} }
const char * Log::TimeAsString(std::time_t t) { const char * Log::TimeAsString(std::time_t t) {
@ -212,7 +212,7 @@ namespace log {
m_LogStream = os; m_LogStream = os;
return; return;
} }
LogPrint(eLogError, "Log: can't open file ", path); LogPrint(eLogError, "Log: Can't open file ", path);
} }
void Log::SendTo (std::shared_ptr<std::ostream> os) { void Log::SendTo (std::shared_ptr<std::ostream> os) {

View file

@ -377,7 +377,7 @@ namespace transport
transports.PeerDisconnected (shared_from_this ()); transports.PeerDisconnected (shared_from_this ());
m_Server.RemoveNTCP2Session (shared_from_this ()); m_Server.RemoveNTCP2Session (shared_from_this ());
m_SendQueue.clear (); m_SendQueue.clear ();
LogPrint (eLogDebug, "NTCP2: session terminated"); LogPrint (eLogDebug, "NTCP2: Session terminated");
} }
} }
@ -435,7 +435,7 @@ namespace transport
(void) bytes_transferred; (void) bytes_transferred;
if (ecode) if (ecode)
{ {
LogPrint (eLogWarning, "NTCP2: couldn't send SessionRequest message: ", ecode.message ()); LogPrint (eLogWarning, "NTCP2: Couldn't send SessionRequest message: ", ecode.message ());
Terminate (); Terminate ();
} }
else else
@ -566,7 +566,7 @@ namespace transport
(void) bytes_transferred; (void) bytes_transferred;
if (ecode) if (ecode)
{ {
LogPrint (eLogWarning, "NTCP2: couldn't send SessionConfirmed message: ", ecode.message ()); LogPrint (eLogWarning, "NTCP2: Couldn't send SessionConfirmed message: ", ecode.message ());
Terminate (); Terminate ();
} }
else else
@ -593,7 +593,7 @@ namespace transport
(void) bytes_transferred; (void) bytes_transferred;
if (ecode) if (ecode)
{ {
LogPrint (eLogWarning, "NTCP2: couldn't send SessionCreated message: ", ecode.message ()); LogPrint (eLogWarning, "NTCP2: Couldn't send SessionCreated message: ", ecode.message ());
Terminate (); Terminate ();
} }
else else
@ -636,7 +636,7 @@ namespace transport
// process RI // process RI
if (buf[0] != eNTCP2BlkRouterInfo) if (buf[0] != eNTCP2BlkRouterInfo)
{ {
LogPrint (eLogWarning, "NTCP2: unexpected block ", (int)buf[0], " in SessionConfirmed"); LogPrint (eLogWarning, "NTCP2: Unexpected block ", (int)buf[0], " in SessionConfirmed");
Terminate (); Terminate ();
return; return;
} }
@ -741,7 +741,7 @@ namespace transport
if (ecode) if (ecode)
{ {
if (ecode != boost::asio::error::operation_aborted) if (ecode != boost::asio::error::operation_aborted)
LogPrint (eLogWarning, "NTCP2: receive length read error: ", ecode.message ()); LogPrint (eLogWarning, "NTCP2: Receive length read error: ", ecode.message ());
Terminate (); Terminate ();
} }
else else
@ -756,7 +756,7 @@ namespace transport
#endif #endif
// m_NextReceivedLen comes from the network in BigEndian // m_NextReceivedLen comes from the network in BigEndian
m_NextReceivedLen = be16toh (m_NextReceivedLen) ^ le16toh (m_ReceiveIV.key); m_NextReceivedLen = be16toh (m_NextReceivedLen) ^ le16toh (m_ReceiveIV.key);
LogPrint (eLogDebug, "NTCP2: received length ", m_NextReceivedLen); LogPrint (eLogDebug, "NTCP2: Received length ", m_NextReceivedLen);
if (m_NextReceivedLen >= 16) if (m_NextReceivedLen >= 16)
{ {
if (m_NextReceivedBuffer) delete[] m_NextReceivedBuffer; if (m_NextReceivedBuffer) delete[] m_NextReceivedBuffer;
@ -774,7 +774,7 @@ namespace transport
} }
else else
{ {
LogPrint (eLogError, "NTCP2: received length ", m_NextReceivedLen, " is too short"); LogPrint (eLogError, "NTCP2: Received length ", m_NextReceivedLen, " is too short");
Terminate (); Terminate ();
} }
} }
@ -796,7 +796,7 @@ namespace transport
if (ecode) if (ecode)
{ {
if (ecode != boost::asio::error::operation_aborted) if (ecode != boost::asio::error::operation_aborted)
LogPrint (eLogWarning, "NTCP2: receive read error: ", ecode.message ()); LogPrint (eLogWarning, "NTCP2: Receive read error: ", ecode.message ());
Terminate (); Terminate ();
} }
else else
@ -808,7 +808,7 @@ namespace transport
CreateNonce (m_ReceiveSequenceNumber, nonce); m_ReceiveSequenceNumber++; CreateNonce (m_ReceiveSequenceNumber, nonce); m_ReceiveSequenceNumber++;
if (i2p::crypto::AEADChaCha20Poly1305 (m_NextReceivedBuffer, m_NextReceivedLen-16, nullptr, 0, m_ReceiveKey, nonce, m_NextReceivedBuffer, m_NextReceivedLen, false)) if (i2p::crypto::AEADChaCha20Poly1305 (m_NextReceivedBuffer, m_NextReceivedLen-16, nullptr, 0, m_ReceiveKey, nonce, m_NextReceivedBuffer, m_NextReceivedLen, false))
{ {
LogPrint (eLogDebug, "NTCP2: received message decrypted"); LogPrint (eLogDebug, "NTCP2: Received message decrypted");
ProcessNextFrame (m_NextReceivedBuffer, m_NextReceivedLen-16); ProcessNextFrame (m_NextReceivedBuffer, m_NextReceivedLen-16);
delete[] m_NextReceivedBuffer; m_NextReceivedBuffer = nullptr; // we don't need received buffer anymore delete[] m_NextReceivedBuffer; m_NextReceivedBuffer = nullptr; // we don't need received buffer anymore
ReceiveLength (); ReceiveLength ();
@ -869,14 +869,14 @@ namespace transport
case eNTCP2BlkTermination: case eNTCP2BlkTermination:
if (size >= 9) if (size >= 9)
{ {
LogPrint (eLogDebug, "NTCP2: termination. reason=", (int)(frame[offset + 8])); LogPrint (eLogDebug, "NTCP2: Termination. reason=", (int)(frame[offset + 8]));
Terminate (); Terminate ();
} }
else else
LogPrint (eLogWarning, "NTCP2: Unexpected termination block size ", size); LogPrint (eLogWarning, "NTCP2: Unexpected termination block size ", size);
break; break;
case eNTCP2BlkPadding: case eNTCP2BlkPadding:
LogPrint (eLogDebug, "NTCP2: padding"); LogPrint (eLogDebug, "NTCP2: Padding");
break; break;
default: default:
LogPrint (eLogWarning, "NTCP2: Unknown block type ", (int)blk); LogPrint (eLogWarning, "NTCP2: Unknown block type ", (int)blk);
@ -898,7 +898,7 @@ namespace transport
#endif #endif
// length must be in BigEndian // length must be in BigEndian
htobe16buf (lengthBuf, frameLen ^ le16toh (m_SendIV.key)); htobe16buf (lengthBuf, frameLen ^ le16toh (m_SendIV.key));
LogPrint (eLogDebug, "NTCP2: sent length ", frameLen); LogPrint (eLogDebug, "NTCP2: Sent length ", frameLen);
} }
void NTCP2Session::SendI2NPMsgs (std::vector<std::shared_ptr<I2NPMessage> >& msgs) void NTCP2Session::SendI2NPMsgs (std::vector<std::shared_ptr<I2NPMessage> >& msgs)
@ -1059,15 +1059,15 @@ namespace transport
size_t paddingSize = (msgLen*NTCP2_MAX_PADDING_RATIO)/100; size_t paddingSize = (msgLen*NTCP2_MAX_PADDING_RATIO)/100;
if (msgLen + paddingSize + 3 > NTCP2_UNENCRYPTED_FRAME_MAX_SIZE) paddingSize = NTCP2_UNENCRYPTED_FRAME_MAX_SIZE - msgLen -3; if (msgLen + paddingSize + 3 > NTCP2_UNENCRYPTED_FRAME_MAX_SIZE) paddingSize = NTCP2_UNENCRYPTED_FRAME_MAX_SIZE - msgLen -3;
if (paddingSize > len) paddingSize = len; if (paddingSize > len) paddingSize = len;
if (paddingSize) if (paddingSize)
{ {
if (m_NextPaddingSize >= 16) if (m_NextPaddingSize >= 16)
{ {
RAND_bytes ((uint8_t *)m_PaddingSizes, sizeof (m_PaddingSizes)); RAND_bytes ((uint8_t *)m_PaddingSizes, sizeof (m_PaddingSizes));
m_NextPaddingSize = 0; m_NextPaddingSize = 0;
} }
paddingSize = m_PaddingSizes[m_NextPaddingSize++] % paddingSize; paddingSize = m_PaddingSizes[m_NextPaddingSize++] % paddingSize;
} }
buf[0] = eNTCP2BlkPadding; // blk buf[0] = eNTCP2BlkPadding; // blk
htobe16buf (buf + 1, paddingSize); // size htobe16buf (buf + 1, paddingSize); // size
memset (buf + 3, 0, paddingSize); memset (buf + 3, 0, paddingSize);
@ -1126,7 +1126,7 @@ namespace transport
SendQueue (); SendQueue ();
else if (m_SendQueue.size () > NTCP2_MAX_OUTGOING_QUEUE_SIZE) else if (m_SendQueue.size () > NTCP2_MAX_OUTGOING_QUEUE_SIZE)
{ {
LogPrint (eLogWarning, "NTCP2: outgoing messages queue size to ", LogPrint (eLogWarning, "NTCP2: Outgoing messages queue size to ",
GetIdentHashBase64(), " exceeds ", NTCP2_MAX_OUTGOING_QUEUE_SIZE); GetIdentHashBase64(), " exceeds ", NTCP2_MAX_OUTGOING_QUEUE_SIZE);
Terminate (); Terminate ();
} }
@ -1232,7 +1232,7 @@ namespace transport
} }
catch ( std::exception & ex ) catch ( std::exception & ex )
{ {
LogPrint(eLogError, "NTCP2: failed to bind to v6 port ", address->port, ": ", ex.what()); LogPrint(eLogError, "NTCP2: Failed to bind to v6 port ", address->port, ": ", ex.what());
ThrowFatal ("Unable to start IPv6 NTCP2 transport at port ", address->port, ": ", ex.what ()); ThrowFatal ("Unable to start IPv6 NTCP2 transport at port ", address->port, ": ", ex.what ());
continue; continue;
} }
@ -1273,7 +1273,7 @@ namespace transport
auto it = m_NTCP2Sessions.find (ident); auto it = m_NTCP2Sessions.find (ident);
if (it != m_NTCP2Sessions.end ()) if (it != m_NTCP2Sessions.end ())
{ {
LogPrint (eLogWarning, "NTCP2: session to ", ident.ToBase64 (), " already exists"); LogPrint (eLogWarning, "NTCP2: Session to ", ident.ToBase64 (), " already exists");
if (incoming) if (incoming)
// replace by new session // replace by new session
it->second->Terminate (); it->second->Terminate ();
@ -1342,7 +1342,7 @@ namespace transport
boost::system::error_code ec; boost::system::error_code ec;
conn->GetSocket ().bind (*localAddress, ec); conn->GetSocket ().bind (*localAddress, ec);
if (ec) if (ec)
LogPrint (eLogError, "NTCP2: can't bind to ", localAddress->address ().to_string (), ": ", ec.message ()); LogPrint (eLogError, "NTCP2: Can't bind to ", localAddress->address ().to_string (), ": ", ec.message ());
} }
conn->GetSocket ().async_connect (conn->GetRemoteEndpoint (), std::bind (&NTCP2Server::HandleConnect, this, std::placeholders::_1, conn, timer)); conn->GetSocket ().async_connect (conn->GetRemoteEndpoint (), std::bind (&NTCP2Server::HandleConnect, this, std::placeholders::_1, conn, timer));
} }
@ -1509,7 +1509,7 @@ namespace transport
{ {
if (ecode) if (ecode)
{ {
LogPrint(eLogWarning, "NTCP2: failed to connect to proxy ", ecode.message()); LogPrint(eLogWarning, "NTCP2: Failed to connect to proxy ", ecode.message());
timer->cancel(); timer->cancel();
conn->Terminate(); conn->Terminate();
return; return;
@ -1526,7 +1526,7 @@ namespace transport
(void) transferred; (void) transferred;
if(ec) if(ec)
{ {
LogPrint(eLogWarning, "NTCP2: socks5 write error ", ec.message()); LogPrint(eLogWarning, "NTCP2: SOCKS5 write error ", ec.message());
} }
}); });
auto readbuff = std::make_shared<std::vector<uint8_t> >(2); auto readbuff = std::make_shared<std::vector<uint8_t> >(2);
@ -1535,7 +1535,7 @@ namespace transport
{ {
if(ec) if(ec)
{ {
LogPrint(eLogError, "NTCP2: socks5 read error ", ec.message()); LogPrint(eLogError, "NTCP2: SOCKS5 read error ", ec.message());
timer->cancel(); timer->cancel();
conn->Terminate(); conn->Terminate();
return; return;
@ -1549,14 +1549,14 @@ namespace transport
} }
else if ((*readbuff)[1] == 0xff) else if ((*readbuff)[1] == 0xff)
{ {
LogPrint(eLogError, "NTCP2: socks5 proxy rejected authentication"); LogPrint(eLogError, "NTCP2: SOCKS5 proxy rejected authentication");
timer->cancel(); timer->cancel();
conn->Terminate(); conn->Terminate();
return; return;
} }
LogPrint(eLogError, "NTCP2:", (int)(*readbuff)[1]); LogPrint(eLogError, "NTCP2:", (int)(*readbuff)[1]);
} }
LogPrint(eLogError, "NTCP2: socks5 server gave invalid response"); LogPrint(eLogError, "NTCP2: SOCKS5 server gave invalid response");
timer->cancel(); timer->cancel();
conn->Terminate(); conn->Terminate();
}); });
@ -1584,7 +1584,7 @@ namespace transport
{ {
(void) transferred; (void) transferred;
if(ec) if(ec)
LogPrint(eLogError, "NTCP2: http proxy write error ", ec.message()); LogPrint(eLogError, "NTCP2: HTTP proxy write error ", ec.message());
}); });
boost::asio::streambuf * readbuff = new boost::asio::streambuf; boost::asio::streambuf * readbuff = new boost::asio::streambuf;
@ -1593,7 +1593,7 @@ namespace transport
{ {
if(ec) if(ec)
{ {
LogPrint(eLogError, "NTCP2: http proxy read error ", ec.message()); LogPrint(eLogError, "NTCP2: HTTP proxy read error ", ec.message());
timer->cancel(); timer->cancel();
conn->Terminate(); conn->Terminate();
} }
@ -1611,10 +1611,10 @@ namespace transport
return; return;
} }
else else
LogPrint(eLogError, "NTCP2: http proxy rejected request ", res.code); LogPrint(eLogError, "NTCP2: HTTP proxy rejected request ", res.code);
} }
else else
LogPrint(eLogError, "NTCP2: http proxy gave malformed response"); LogPrint(eLogError, "NTCP2: HTTP proxy gave malformed response");
timer->cancel(); timer->cancel();
conn->Terminate(); conn->Terminate();
delete readbuff; delete readbuff;
@ -1623,7 +1623,7 @@ namespace transport
break; break;
} }
default: default:
LogPrint(eLogError, "NTCP2: unknown proxy type, invalid state"); LogPrint(eLogError, "NTCP2: Unknown proxy type, invalid state");
} }
} }
@ -1664,7 +1664,7 @@ namespace transport
{ {
if(ec) if(ec)
{ {
LogPrint(eLogError, "NTCP2: failed to write handshake to socks proxy ", ec.message()); LogPrint(eLogError, "NTCP2: Failed to write handshake to socks proxy ", ec.message());
return; return;
} }
}); });
@ -1674,7 +1674,7 @@ namespace transport
{ {
if(e) if(e)
{ {
LogPrint(eLogError, "NTCP2: socks proxy read error ", e.message()); LogPrint(eLogError, "NTCP2: SOCKS proxy read error ", e.message());
} }
else if(transferred == sz) else if(transferred == sz)
{ {

View file

@ -73,7 +73,7 @@ namespace data
m_RouterInfos.emplace (i2p::context.GetIdentHash (), i2p::context.GetSharedRouterInfo ()); m_RouterInfos.emplace (i2p::context.GetIdentHash (), i2p::context.GetSharedRouterInfo ());
if (i2p::context.IsFloodfill ()) if (i2p::context.IsFloodfill ())
m_Floodfills.push_back (i2p::context.GetSharedRouterInfo ()); m_Floodfills.push_back (i2p::context.GetSharedRouterInfo ());
i2p::config::GetOption("persist.profiles", m_PersistProfiles); i2p::config::GetOption("persist.profiles", m_PersistProfiles);
m_IsRunning = true; m_IsRunning = true;
@ -118,7 +118,7 @@ namespace data
int numMsgs = 0; int numMsgs = 0;
while (msg) while (msg)
{ {
LogPrint(eLogDebug, "NetDb: got request with type ", (int) msg->GetTypeID ()); LogPrint(eLogDebug, "NetDb: Got request with type ", (int) msg->GetTypeID ());
switch (msg->GetTypeID ()) switch (msg->GetTypeID ())
{ {
case eI2NPDatabaseStore: case eI2NPDatabaseStore:
@ -138,7 +138,7 @@ namespace data
HandleNTCP2RouterInfoMsg (msg); HandleNTCP2RouterInfoMsg (msg);
break; break;
default: // WTF? default: // WTF?
LogPrint (eLogError, "NetDb: unexpected message type ", (int) msg->GetTypeID ()); LogPrint (eLogError, "NetDb: Unexpected message type ", (int) msg->GetTypeID ());
//i2p::HandleI2NPMessage (msg); //i2p::HandleI2NPMessage (msg);
} }
if (numMsgs > 100) break; if (numMsgs > 100) break;
@ -148,7 +148,7 @@ namespace data
} }
if (!m_IsRunning) break; if (!m_IsRunning) break;
if (!i2p::transport::transports.IsOnline ()) continue; // don't manage netdb when offline if (!i2p::transport::transports.IsOnline ()) continue; // don't manage netdb when offline
uint64_t ts = i2p::util::GetSecondsSinceEpoch (); uint64_t ts = i2p::util::GetSecondsSinceEpoch ();
if (ts - lastManageRequest >= 15) // manage requests every 15 seconds if (ts - lastManageRequest >= 15) // manage requests every 15 seconds
{ {
@ -170,8 +170,8 @@ namespace data
lastDestinationCleanup = ts; lastDestinationCleanup = ts;
} }
// publish // publish
if (!m_HiddenMode && i2p::transport::transports.IsOnline ()) if (!m_HiddenMode && i2p::transport::transports.IsOnline ())
{ {
bool publish = false; bool publish = false;
if (m_PublishReplyToken) if (m_PublishReplyToken)
@ -179,15 +179,15 @@ namespace data
// next publishing attempt // next publishing attempt
if (ts - lastPublish >= NETDB_PUBLISH_CONFIRMATION_TIMEOUT) publish = true; if (ts - lastPublish >= NETDB_PUBLISH_CONFIRMATION_TIMEOUT) publish = true;
} }
else if (i2p::context.GetLastUpdateTime () > lastPublish || else if (i2p::context.GetLastUpdateTime () > lastPublish ||
ts - lastPublish >= NETDB_PUBLISH_INTERVAL) ts - lastPublish >= NETDB_PUBLISH_INTERVAL)
{ {
// new publish // new publish
m_PublishExcluded.clear (); m_PublishExcluded.clear ();
if (i2p::context.IsFloodfill ()) if (i2p::context.IsFloodfill ())
m_PublishExcluded.insert (i2p::context.GetIdentHash ()); // do publish to ourselves m_PublishExcluded.insert (i2p::context.GetIdentHash ()); // do publish to ourselves
publish = true; publish = true;
} }
if (publish) // update timestamp and publish if (publish) // update timestamp and publish
{ {
i2p::context.UpdateTimestamp (ts); i2p::context.UpdateTimestamp (ts);
@ -216,7 +216,7 @@ namespace data
} }
catch (std::exception& ex) catch (std::exception& ex)
{ {
LogPrint (eLogError, "NetDb: runtime exception: ", ex.what ()); LogPrint (eLogError, "NetDb: Runtime exception: ", ex.what ());
} }
} }
} }
@ -290,7 +290,7 @@ namespace data
if (inserted) if (inserted)
{ {
LogPrint (eLogInfo, "NetDb: RouterInfo added: ", ident.ToBase64()); LogPrint (eLogInfo, "NetDb: RouterInfo added: ", ident.ToBase64());
if (r->IsFloodfill () && r->IsEligibleFloodfill ()) if (r->IsFloodfill () && r->IsEligibleFloodfill ())
{ {
std::unique_lock<std::mutex> l(m_FloodfillsMutex); std::unique_lock<std::mutex> l(m_FloodfillsMutex);
m_Floodfills.push_back (r); m_Floodfills.push_back (r);
@ -343,7 +343,7 @@ namespace data
updated = true; updated = true;
} }
else else
LogPrint (eLogError, "NetDb: new LeaseSet validation failed: ", ident.ToBase32()); LogPrint (eLogError, "NetDb: New LeaseSet validation failed: ", ident.ToBase32());
} }
return updated; return updated;
} }
@ -373,7 +373,7 @@ namespace data
} }
} }
else else
LogPrint (eLogError, "NetDb: new LeaseSet2 validation failed: ", ident.ToBase32()); LogPrint (eLogError, "NetDb: New LeaseSet2 validation failed: ", ident.ToBase32());
return false; return false;
} }
@ -430,7 +430,7 @@ namespace data
int riLen = ri->GetBufferLen(); int riLen = ri->GetBufferLen();
if(!i2p::data::netdb.AddRouterInfo(riData, riLen)) { if(!i2p::data::netdb.AddRouterInfo(riData, riLen)) {
// bad router info // bad router info
LogPrint(eLogError, "NetDb: bad router info"); LogPrint(eLogError, "NetDb: Bad RouterInfo");
return; return;
} }
m_FloodfillBootstrap = ri; m_FloodfillBootstrap = ri;
@ -445,7 +445,7 @@ namespace data
void NetDb::ReseedFromFloodfill(const RouterInfo & ri, int numRouters, int numFloodfills) void NetDb::ReseedFromFloodfill(const RouterInfo & ri, int numRouters, int numFloodfills)
{ {
LogPrint(eLogInfo, "NetDB: reseeding from floodfill ", ri.GetIdentHashBase64()); LogPrint(eLogInfo, "NetDB: Reseeding from floodfill ", ri.GetIdentHashBase64());
std::vector<std::shared_ptr<i2p::I2NPMessage> > requests; std::vector<std::shared_ptr<i2p::I2NPMessage> > requests;
i2p::data::IdentHash ourIdent = i2p::context.GetIdentHash(); i2p::data::IdentHash ourIdent = i2p::context.GetIdentHash();
@ -476,14 +476,14 @@ namespace data
{ {
auto r = std::make_shared<RouterInfo>(path); auto r = std::make_shared<RouterInfo>(path);
if (r->GetRouterIdentity () && !r->IsUnreachable () && r->HasValidAddresses ()) if (r->GetRouterIdentity () && !r->IsUnreachable () && r->HasValidAddresses ())
{ {
r->DeleteBuffer (); r->DeleteBuffer ();
r->ClearProperties (); // properties are not used for regular routers r->ClearProperties (); // properties are not used for regular routers
if (m_RouterInfos.emplace (r->GetIdentHash (), r).second) if (m_RouterInfos.emplace (r->GetIdentHash (), r).second)
{ {
if (r->IsFloodfill () && r->IsEligibleFloodfill ()) if (r->IsFloodfill () && r->IsEligibleFloodfill ())
m_Floodfills.push_back (r); m_Floodfills.push_back (r);
} }
} }
else else
{ {
@ -591,7 +591,7 @@ namespace data
expirationTimeout = i2p::context.IsFloodfill () ? NETDB_FLOODFILL_EXPIRATION_TIMEOUT*1000LL : expirationTimeout = i2p::context.IsFloodfill () ? NETDB_FLOODFILL_EXPIRATION_TIMEOUT*1000LL :
NETDB_MIN_EXPIRATION_TIMEOUT*1000LL + (NETDB_MAX_EXPIRATION_TIMEOUT - NETDB_MIN_EXPIRATION_TIMEOUT)*1000LL*NETDB_MIN_ROUTERS/total; NETDB_MIN_EXPIRATION_TIMEOUT*1000LL + (NETDB_MAX_EXPIRATION_TIMEOUT - NETDB_MIN_EXPIRATION_TIMEOUT)*1000LL*NETDB_MIN_ROUTERS/total;
auto own = i2p::context.GetSharedRouterInfo (); auto own = i2p::context.GetSharedRouterInfo ();
for (auto& it: m_RouterInfos) for (auto& it: m_RouterInfos)
{ {
if (it.second == own) continue; // skip own if (it.second == own) continue; // skip own
@ -609,7 +609,7 @@ namespace data
// make router reachable back if too few routers or floodfills // make router reachable back if too few routers or floodfills
if (it.second->IsUnreachable () && (total - deletedCount < NETDB_MIN_ROUTERS || if (it.second->IsUnreachable () && (total - deletedCount < NETDB_MIN_ROUTERS ||
(it.second->IsFloodfill () && totalFloodfills - deletedFloodfillsCount < NETDB_MIN_FLOODFILLS))) (it.second->IsFloodfill () && totalFloodfills - deletedFloodfillsCount < NETDB_MIN_FLOODFILLS)))
it.second->SetUnreachable (false); it.second->SetUnreachable (false);
// find & mark expired routers // find & mark expired routers
if (!it.second->IsReachable () && it.second->IsSSU (false)) if (!it.second->IsReachable () && it.second->IsSSU (false))
{ {
@ -626,15 +626,15 @@ namespace data
// delete RI file // delete RI file
m_Storage.Remove(ident); m_Storage.Remove(ident);
deletedCount++; deletedCount++;
if (total - deletedCount < NETDB_MIN_ROUTERS) checkForExpiration = false; if (total - deletedCount < NETDB_MIN_ROUTERS) checkForExpiration = false;
} }
} // m_RouterInfos iteration } // m_RouterInfos iteration
if (updatedCount > 0) if (updatedCount > 0)
LogPrint (eLogInfo, "NetDb: saved ", updatedCount, " new/updated routers"); LogPrint (eLogInfo, "NetDb: Saved ", updatedCount, " new/updated routers");
if (deletedCount > 0) if (deletedCount > 0)
{ {
LogPrint (eLogInfo, "NetDb: deleting ", deletedCount, " unreachable routers"); LogPrint (eLogInfo, "NetDb: Deleting ", deletedCount, " unreachable routers");
// clean up RouterInfos table // clean up RouterInfos table
{ {
std::unique_lock<std::mutex> l(m_RouterInfosMutex); std::unique_lock<std::mutex> l(m_RouterInfosMutex);
@ -666,7 +666,7 @@ namespace data
auto dest = m_Requests.CreateRequest (destination, false, requestComplete); // non-exploratory auto dest = m_Requests.CreateRequest (destination, false, requestComplete); // non-exploratory
if (!dest) if (!dest)
{ {
LogPrint (eLogWarning, "NetDb: destination ", destination.ToBase64(), " is requested already"); LogPrint (eLogWarning, "NetDb: Destination ", destination.ToBase64(), " has already been requested");
return; return;
} }
@ -674,7 +674,7 @@ namespace data
if (floodfill) if (floodfill)
{ {
if (direct && !floodfill->IsReachableFrom (i2p::context.GetRouterInfo ()) && if (direct && !floodfill->IsReachableFrom (i2p::context.GetRouterInfo ()) &&
!i2p::transport::transports.IsConnected (floodfill->GetIdentHash ())) !i2p::transport::transports.IsConnected (floodfill->GetIdentHash ()))
direct = false; // floodfill can't be reached directly direct = false; // floodfill can't be reached directly
if (direct) if (direct)
transports.SendMessage (floodfill->GetIdentHash (), dest->CreateRequestMessage (floodfill->GetIdentHash ())); transports.SendMessage (floodfill->GetIdentHash (), dest->CreateRequestMessage (floodfill->GetIdentHash ()));
@ -688,10 +688,10 @@ namespace data
else else
{ {
LogPrint (eLogError, "NetDb: ", destination.ToBase64(), " destination requested, but no tunnels found"); LogPrint (eLogError, "NetDb: ", destination.ToBase64(), " destination requested, but no tunnels found");
m_Requests.RequestComplete (destination, nullptr); m_Requests.RequestComplete (destination, nullptr);
} }
} }
} }
else else
{ {
LogPrint (eLogError, "NetDb: ", destination.ToBase64(), " destination requested, but no floodfills found"); LogPrint (eLogError, "NetDb: ", destination.ToBase64(), " destination requested, but no floodfills found");
@ -705,10 +705,10 @@ namespace data
auto dest = m_Requests.CreateRequest (destination, exploritory, requestComplete); // non-exploratory auto dest = m_Requests.CreateRequest (destination, exploritory, requestComplete); // non-exploratory
if (!dest) if (!dest)
{ {
LogPrint (eLogWarning, "NetDb: destination ", destination.ToBase64(), " is requested already"); LogPrint (eLogWarning, "NetDb: Destination ", destination.ToBase64(), " is requested already");
return; return;
} }
LogPrint(eLogInfo, "NetDb: destination ", destination.ToBase64(), " being requested directly from ", from.ToBase64()); LogPrint(eLogInfo, "NetDb: Destination ", destination.ToBase64(), " being requested directly from ", from.ToBase64());
// direct // direct
transports.SendMessage (from, dest->CreateRequestMessage (nullptr, nullptr)); transports.SendMessage (from, dest->CreateRequestMessage (nullptr, nullptr));
} }
@ -732,7 +732,7 @@ namespace data
IdentHash ident (buf + DATABASE_STORE_KEY_OFFSET); IdentHash ident (buf + DATABASE_STORE_KEY_OFFSET);
if (ident.IsZero ()) if (ident.IsZero ())
{ {
LogPrint (eLogDebug, "NetDb: database store with zero ident, dropped"); LogPrint (eLogDebug, "NetDb: Database store with zero ident, dropped");
return; return;
} }
uint32_t replyToken = bufbe32toh (buf + DATABASE_STORE_REPLY_TOKEN_OFFSET); uint32_t replyToken = bufbe32toh (buf + DATABASE_STORE_REPLY_TOKEN_OFFSET);
@ -751,14 +751,14 @@ namespace data
if (outbound) if (outbound)
outbound->SendTunnelDataMsg (buf + offset, tunnelID, deliveryStatus); outbound->SendTunnelDataMsg (buf + offset, tunnelID, deliveryStatus);
else else
LogPrint (eLogWarning, "NetDb: no outbound tunnels for DatabaseStore reply found"); LogPrint (eLogWarning, "NetDb: No outbound tunnels for DatabaseStore reply found");
} }
offset += 32; offset += 32;
} }
// we must send reply back before this check // we must send reply back before this check
if (ident == i2p::context.GetIdentHash ()) if (ident == i2p::context.GetIdentHash ())
{ {
LogPrint (eLogDebug, "NetDb: database store with own RouterInfo received, dropped"); LogPrint (eLogDebug, "NetDb: Database store with own RouterInfo received, dropped");
return; return;
} }
size_t payloadOffset = offset; size_t payloadOffset = offset;
@ -771,24 +771,24 @@ namespace data
{ {
if (storeType == NETDB_STORE_TYPE_LEASESET) // 1 if (storeType == NETDB_STORE_TYPE_LEASESET) // 1
{ {
LogPrint (eLogDebug, "NetDb: store request: LeaseSet for ", ident.ToBase32()); LogPrint (eLogDebug, "NetDb: Store request: LeaseSet for ", ident.ToBase32());
updated = AddLeaseSet (ident, buf + offset, len - offset); updated = AddLeaseSet (ident, buf + offset, len - offset);
} }
else // all others are considered as LeaseSet2 else // all others are considered as LeaseSet2
{ {
LogPrint (eLogDebug, "NetDb: store request: LeaseSet2 of type ", storeType, " for ", ident.ToBase32()); LogPrint (eLogDebug, "NetDb: Store request: LeaseSet2 of type ", storeType, " for ", ident.ToBase32());
updated = AddLeaseSet2 (ident, buf + offset, len - offset, storeType); updated = AddLeaseSet2 (ident, buf + offset, len - offset, storeType);
} }
} }
} }
else // RouterInfo else // RouterInfo
{ {
LogPrint (eLogDebug, "NetDb: store request: RouterInfo"); LogPrint (eLogDebug, "NetDb: Store request: RouterInfo");
size_t size = bufbe16toh (buf + offset); size_t size = bufbe16toh (buf + offset);
offset += 2; offset += 2;
if (size > MAX_RI_BUFFER_SIZE || size > len - offset) if (size > MAX_RI_BUFFER_SIZE || size > len - offset)
{ {
LogPrint (eLogError, "NetDb: invalid RouterInfo length ", (int)size); LogPrint (eLogError, "NetDb: Invalid RouterInfo length ", (int)size);
return; return;
} }
uint8_t uncompressed[MAX_RI_BUFFER_SIZE]; uint8_t uncompressed[MAX_RI_BUFFER_SIZE];
@ -797,7 +797,7 @@ namespace data
updated = AddRouterInfo (ident, uncompressed, uncompressedSize); updated = AddRouterInfo (ident, uncompressed, uncompressedSize);
else else
{ {
LogPrint (eLogInfo, "NetDb: decompression failed ", uncompressedSize); LogPrint (eLogInfo, "NetDb: Decompression failed ", uncompressedSize);
return; return;
} }
} }
@ -872,7 +872,7 @@ namespace data
m_Requests.RequestComplete (ident, nullptr); m_Requests.RequestComplete (ident, nullptr);
} }
else if(!m_FloodfillBootstrap) else if(!m_FloodfillBootstrap)
LogPrint (eLogWarning, "NetDb: requested destination for ", key, " not found"); LogPrint (eLogWarning, "NetDb: Requested destination for ", key, " not found");
// try responses // try responses
for (int i = 0; i < num; i++) for (int i = 0; i < num; i++)
@ -887,7 +887,7 @@ namespace data
if (!r || i2p::util::GetMillisecondsSinceEpoch () > r->GetTimestamp () + 3600*1000LL) if (!r || i2p::util::GetMillisecondsSinceEpoch () > r->GetTimestamp () + 3600*1000LL)
{ {
// router with ident not found or too old (1 hour) // router with ident not found or too old (1 hour)
LogPrint (eLogDebug, "NetDb: found new/outdated router. Requesting RouterInfo ..."); LogPrint (eLogDebug, "NetDb: Found new/outdated router. Requesting RouterInfo ...");
if(m_FloodfillBootstrap) if(m_FloodfillBootstrap)
RequestDestinationFrom(router, m_FloodfillBootstrap->GetIdentHash(), true); RequestDestinationFrom(router, m_FloodfillBootstrap->GetIdentHash(), true);
else else
@ -928,14 +928,14 @@ namespace data
excluded += 2; excluded += 2;
if (numExcluded > 512) if (numExcluded > 512)
{ {
LogPrint (eLogWarning, "NetDb: number of excluded peers", numExcluded, " exceeds 512"); LogPrint (eLogWarning, "NetDb: Number of excluded peers", numExcluded, " exceeds 512");
return; return;
} }
std::shared_ptr<I2NPMessage> replyMsg; std::shared_ptr<I2NPMessage> replyMsg;
if (lookupType == DATABASE_LOOKUP_TYPE_EXPLORATORY_LOOKUP) if (lookupType == DATABASE_LOOKUP_TYPE_EXPLORATORY_LOOKUP)
{ {
LogPrint (eLogInfo, "NetDb: exploratory close to ", key, " ", numExcluded, " excluded"); LogPrint (eLogInfo, "NetDb: Exploratory close to ", key, " ", numExcluded, " excluded");
std::set<IdentHash> excludedRouters; std::set<IdentHash> excludedRouters;
for (int i = 0; i < numExcluded; i++) for (int i = 0; i < numExcluded; i++)
{ {
@ -962,7 +962,7 @@ namespace data
auto router = FindRouter (ident); auto router = FindRouter (ident);
if (router) if (router)
{ {
LogPrint (eLogDebug, "NetDb: requested RouterInfo ", key, " found"); LogPrint (eLogDebug, "NetDb: Requested RouterInfo ", key, " found");
router->LoadBuffer (); router->LoadBuffer ();
if (router->GetBuffer ()) if (router->GetBuffer ())
replyMsg = CreateDatabaseStoreMsg (router); replyMsg = CreateDatabaseStoreMsg (router);
@ -976,11 +976,11 @@ namespace data
if (!leaseSet) if (!leaseSet)
{ {
// no lease set found // no lease set found
LogPrint(eLogDebug, "NetDb: requested LeaseSet not found for ", ident.ToBase32()); LogPrint(eLogDebug, "NetDb: Requested LeaseSet not found for ", ident.ToBase32());
} }
else if (!leaseSet->IsExpired ()) // we don't send back our LeaseSets else if (!leaseSet->IsExpired ()) // we don't send back our LeaseSets
{ {
LogPrint (eLogDebug, "NetDb: requested LeaseSet ", key, " found"); LogPrint (eLogDebug, "NetDb: Requested LeaseSet ", key, " found");
replyMsg = CreateDatabaseStoreMsg (ident, leaseSet); replyMsg = CreateDatabaseStoreMsg (ident, leaseSet);
} }
} }
@ -1050,8 +1050,8 @@ namespace data
m_PublishExcluded.clear (); m_PublishExcluded.clear ();
m_PublishReplyToken = 0; m_PublishReplyToken = 0;
} }
} }
void NetDb::Explore (int numDestinations) void NetDb::Explore (int numDestinations)
{ {
// new requests // new requests
@ -1062,14 +1062,14 @@ namespace data
uint8_t randomHash[32]; uint8_t randomHash[32];
std::vector<i2p::tunnel::TunnelMessageBlock> msgs; std::vector<i2p::tunnel::TunnelMessageBlock> msgs;
LogPrint (eLogInfo, "NetDb: exploring new ", numDestinations, " routers ..."); LogPrint (eLogInfo, "NetDb: Exploring new ", numDestinations, " routers ...");
for (int i = 0; i < numDestinations; i++) for (int i = 0; i < numDestinations; i++)
{ {
RAND_bytes (randomHash, 32); RAND_bytes (randomHash, 32);
auto dest = m_Requests.CreateRequest (randomHash, true); // exploratory auto dest = m_Requests.CreateRequest (randomHash, true); // exploratory
if (!dest) if (!dest)
{ {
LogPrint (eLogWarning, "NetDb: exploratory destination is requested already"); LogPrint (eLogWarning, "NetDb: Exploratory destination is requested already");
return; return;
} }
auto floodfill = GetClosestFloodfill (randomHash, dest->GetExcludedPeers ()); auto floodfill = GetClosestFloodfill (randomHash, dest->GetExcludedPeers ());
@ -1111,7 +1111,7 @@ namespace data
LogPrint (eLogError, "NetDb: Couldn't publish our RouterInfo to ", NETDB_MAX_PUBLISH_EXCLUDED_FLOODFILLS, " closest routers. Try again"); LogPrint (eLogError, "NetDb: Couldn't publish our RouterInfo to ", NETDB_MAX_PUBLISH_EXCLUDED_FLOODFILLS, " closest routers. Try again");
m_PublishExcluded.clear (); m_PublishExcluded.clear ();
} }
auto floodfill = GetClosestFloodfill (i2p::context.GetIdentHash (), m_PublishExcluded); auto floodfill = GetClosestFloodfill (i2p::context.GetIdentHash (), m_PublishExcluded);
if (floodfill) if (floodfill)
{ {
@ -1121,19 +1121,19 @@ namespace data
m_PublishExcluded.insert (floodfill->GetIdentHash ()); m_PublishExcluded.insert (floodfill->GetIdentHash ());
m_PublishReplyToken = replyToken; m_PublishReplyToken = replyToken;
if (floodfill->IsReachableFrom (i2p::context.GetRouterInfo ()) || // are we able to connect? if (floodfill->IsReachableFrom (i2p::context.GetRouterInfo ()) || // are we able to connect?
i2p::transport::transports.IsConnected (floodfill->GetIdentHash ())) // already connected ? i2p::transport::transports.IsConnected (floodfill->GetIdentHash ())) // already connected ?
// send directly // send directly
transports.SendMessage (floodfill->GetIdentHash (), CreateDatabaseStoreMsg (i2p::context.GetSharedRouterInfo (), replyToken)); transports.SendMessage (floodfill->GetIdentHash (), CreateDatabaseStoreMsg (i2p::context.GetSharedRouterInfo (), replyToken));
else else
{ {
// otherwise through exploratory // otherwise through exploratory
auto exploratoryPool = i2p::tunnel::tunnels.GetExploratoryPool (); auto exploratoryPool = i2p::tunnel::tunnels.GetExploratoryPool ();
auto outbound = exploratoryPool ? exploratoryPool->GetNextOutboundTunnel () : nullptr; auto outbound = exploratoryPool ? exploratoryPool->GetNextOutboundTunnel () : nullptr;
auto inbound = exploratoryPool ? exploratoryPool->GetNextInboundTunnel () : nullptr; auto inbound = exploratoryPool ? exploratoryPool->GetNextInboundTunnel () : nullptr;
if (inbound && outbound) if (inbound && outbound)
outbound->SendTunnelDataMsg (floodfill->GetIdentHash (), 0, outbound->SendTunnelDataMsg (floodfill->GetIdentHash (), 0,
CreateDatabaseStoreMsg (i2p::context.GetSharedRouterInfo (), replyToken, inbound)); CreateDatabaseStoreMsg (i2p::context.GetSharedRouterInfo (), replyToken, inbound));
} }
} }
} }
@ -1215,7 +1215,7 @@ namespace data
return !router->IsHidden () && router != compatibleWith && return !router->IsHidden () && router != compatibleWith &&
(reverse ? compatibleWith->IsReachableFrom (*router) : (reverse ? compatibleWith->IsReachableFrom (*router) :
router->IsReachableFrom (*compatibleWith)) && router->IsReachableFrom (*compatibleWith)) &&
(router->GetCaps () & RouterInfo::eHighBandwidth) && (router->GetCaps () & RouterInfo::eHighBandwidth) &&
router->GetVersion () >= NETDB_MIN_HIGHBANDWIDTH_VERSION && router->GetVersion () >= NETDB_MIN_HIGHBANDWIDTH_VERSION &&
router->IsECIES (); router->IsECIES ();
}); });
@ -1237,12 +1237,12 @@ namespace data
return it->second; return it->second;
// try some routers around // try some routers around
auto it1 = m_RouterInfos.begin (); auto it1 = m_RouterInfos.begin ();
if (inds[0]) if (inds[0])
{ {
// before // before
inds[1] %= inds[0]; inds[1] %= inds[0];
std::advance (it1, (inds[1] + inds[0])/2); std::advance (it1, (inds[1] + inds[0])/2);
} }
else else
it1 = it; it1 = it;
auto it2 = it; auto it2 = it;
@ -1253,7 +1253,7 @@ namespace data
std::advance (it2, inds[2]); std::advance (it2, inds[2]);
} }
// it1 - from, it2 - to // it1 - from, it2 - to
it = it1; it = it1;
while (it != it2 && it != m_RouterInfos.end ()) while (it != it2 && it != m_RouterInfos.end ())
{ {
if (!it->second->IsUnreachable () && filter (it->second)) if (!it->second->IsUnreachable () && filter (it->second))

View file

@ -73,7 +73,7 @@ namespace data
if (!i2p::fs::Exists(path)) if (!i2p::fs::Exists(path))
{ {
LogPrint(eLogWarning, "Profiling: no profile yet for ", ident); LogPrint(eLogWarning, "Profiling: No profile yet for ", ident);
return; return;
} }
@ -194,7 +194,7 @@ namespace data
continue; continue;
} }
if (((now - st.st_mtime) / 3600) >= PEER_PROFILE_EXPIRATION_TIMEOUT) { if (((now - st.st_mtime) / 3600) >= PEER_PROFILE_EXPIRATION_TIMEOUT) {
LogPrint(eLogDebug, "Profiling: removing expired peer profile: ", path); LogPrint(eLogDebug, "Profiling: Removing expired peer profile: ", path);
i2p::fs::Remove(path); i2p::fs::Remove(path);
} }
} }

View file

@ -60,19 +60,19 @@ namespace data
num = ProcessSU3File (su3FileName.c_str ()); num = ProcessSU3File (su3FileName.c_str ());
} }
if (num == 0) if (num == 0)
LogPrint (eLogWarning, "Reseed: failed to reseed from ", su3FileName); LogPrint (eLogWarning, "Reseed: Failed to reseed from ", su3FileName);
} }
else if (zipFileName.length() > 0) // bootstrap from ZIP file else if (zipFileName.length() > 0) // bootstrap from ZIP file
{ {
int num = ProcessZIPFile (zipFileName.c_str ()); int num = ProcessZIPFile (zipFileName.c_str ());
if (num == 0) if (num == 0)
LogPrint (eLogWarning, "Reseed: failed to reseed from ", zipFileName); LogPrint (eLogWarning, "Reseed: Failed to reseed from ", zipFileName);
} }
else // bootstrap from reseed servers else // bootstrap from reseed servers
{ {
int num = ReseedFromServers (); int num = ReseedFromServers ();
if (num == 0) if (num == 0)
LogPrint (eLogWarning, "Reseed: failed to reseed from servers"); LogPrint (eLogWarning, "Reseed: Failed to reseed from servers");
} }
} }
@ -84,15 +84,15 @@ namespace data
{ {
bool ipv6; i2p::config::GetOption("ipv6", ipv6); bool ipv6; i2p::config::GetOption("ipv6", ipv6);
bool ipv4; i2p::config::GetOption("ipv4", ipv4); bool ipv4; i2p::config::GetOption("ipv4", ipv4);
std::vector<std::string> httpsReseedHostList; std::vector<std::string> httpsReseedHostList;
if (ipv4 || ipv6) if (ipv4 || ipv6)
{ {
std::string reseedURLs; i2p::config::GetOption("reseed.urls", reseedURLs); std::string reseedURLs; i2p::config::GetOption("reseed.urls", reseedURLs);
if (!reseedURLs.empty ()) if (!reseedURLs.empty ())
boost::split(httpsReseedHostList, reseedURLs, boost::is_any_of(","), boost::token_compress_on); boost::split(httpsReseedHostList, reseedURLs, boost::is_any_of(","), boost::token_compress_on);
} }
std::vector<std::string> yggReseedHostList; std::vector<std::string> yggReseedHostList;
if (!i2p::util::net::GetYggdrasilAddress ().is_unspecified ()) if (!i2p::util::net::GetYggdrasilAddress ().is_unspecified ())
{ {
@ -100,7 +100,7 @@ namespace data
std::string yggReseedURLs; i2p::config::GetOption("reseed.yggurls", yggReseedURLs); std::string yggReseedURLs; i2p::config::GetOption("reseed.yggurls", yggReseedURLs);
if (!yggReseedURLs.empty ()) if (!yggReseedURLs.empty ())
boost::split(yggReseedHostList, yggReseedURLs, boost::is_any_of(","), boost::token_compress_on); boost::split(yggReseedHostList, yggReseedURLs, boost::is_any_of(","), boost::token_compress_on);
} }
if (httpsReseedHostList.empty () && yggReseedHostList.empty()) if (httpsReseedHostList.empty () && yggReseedHostList.empty())
{ {
@ -113,14 +113,14 @@ namespace data
{ {
auto ind = rand () % (httpsReseedHostList.size () + yggReseedHostList.size ()); auto ind = rand () % (httpsReseedHostList.size () + yggReseedHostList.size ());
bool isHttps = ind < httpsReseedHostList.size (); bool isHttps = ind < httpsReseedHostList.size ();
std::string reseedUrl = isHttps ? httpsReseedHostList[ind] : std::string reseedUrl = isHttps ? httpsReseedHostList[ind] :
yggReseedHostList[ind - httpsReseedHostList.size ()]; yggReseedHostList[ind - httpsReseedHostList.size ()];
reseedUrl += "i2pseeds.su3"; reseedUrl += "i2pseeds.su3";
auto num = ReseedFromSU3Url (reseedUrl, isHttps); auto num = ReseedFromSU3Url (reseedUrl, isHttps);
if (num > 0) return num; // success if (num > 0) return num; // success
reseedRetries++; reseedRetries++;
} }
LogPrint (eLogWarning, "Reseed: failed to reseed from servers after 10 attempts"); LogPrint (eLogWarning, "Reseed: Failed to reseed from servers after 10 attempts");
return 0; return 0;
} }
@ -509,7 +509,7 @@ namespace data
for (const std::string & file : files) { for (const std::string & file : files) {
if (file.compare(file.size() - 4, 4, ".crt") != 0) { if (file.compare(file.size() - 4, 4, ".crt") != 0) {
LogPrint(eLogWarning, "Reseed: ignoring file ", file); LogPrint(eLogWarning, "Reseed: Ignoring file ", file);
continue; continue;
} }
LoadCertificate (file); LoadCertificate (file);
@ -533,17 +533,17 @@ namespace data
} }
// check for valid proxy url schema // check for valid proxy url schema
if (proxyUrl.schema != "http" && proxyUrl.schema != "socks") { if (proxyUrl.schema != "http" && proxyUrl.schema != "socks") {
LogPrint(eLogError, "Reseed: bad proxy url: ", proxy); LogPrint(eLogError, "Reseed: Bad proxy URL: ", proxy);
return ""; return "";
} }
} else { } else {
LogPrint(eLogError, "Reseed: bad proxy url: ", proxy); LogPrint(eLogError, "Reseed: Bad proxy URL: ", proxy);
return ""; return "";
} }
} }
i2p::http::URL url; i2p::http::URL url;
if (!url.parse(address)) { if (!url.parse(address)) {
LogPrint(eLogError, "Reseed: failed to parse url: ", address); LogPrint(eLogError, "Reseed: Failed to parse URL: ", address);
return ""; return "";
} }
url.schema = "https"; url.schema = "https";
@ -680,30 +680,30 @@ namespace data
auto it = boost::asio::ip::tcp::resolver(service).resolve ( auto it = boost::asio::ip::tcp::resolver(service).resolve (
boost::asio::ip::tcp::resolver::query (url.host, std::to_string(url.port)), ecode); boost::asio::ip::tcp::resolver::query (url.host, std::to_string(url.port)), ecode);
if (!ecode) if (!ecode)
{ {
bool connected = false; bool connected = false;
boost::asio::ip::tcp::resolver::iterator end; boost::asio::ip::tcp::resolver::iterator end;
while (it != end) while (it != end)
{ {
boost::asio::ip::tcp::endpoint ep = *it; boost::asio::ip::tcp::endpoint ep = *it;
if ((ep.address ().is_v4 () && i2p::context.SupportsV4 ()) || if ((ep.address ().is_v4 () && i2p::context.SupportsV4 ()) ||
(ep.address ().is_v6 () && i2p::context.SupportsV6 ())) (ep.address ().is_v6 () && i2p::context.SupportsV6 ()))
{ {
s.lowest_layer().connect (ep, ecode); s.lowest_layer().connect (ep, ecode);
if (!ecode) if (!ecode)
{ {
connected = true; connected = true;
break; break;
} }
} }
it++; it++;
} }
if (!connected) if (!connected)
{ {
LogPrint(eLogError, "Reseed: Failed to connect to ", url.host); LogPrint(eLogError, "Reseed: Failed to connect to ", url.host);
return ""; return "";
} }
} }
} }
if (!ecode) if (!ecode)
{ {
@ -743,40 +743,40 @@ namespace data
i2p::http::HTTPRes res; i2p::http::HTTPRes res;
int len = res.parse(data); int len = res.parse(data);
if (len <= 0) { if (len <= 0) {
LogPrint(eLogWarning, "Reseed: incomplete/broken response from ", uri); LogPrint(eLogWarning, "Reseed: Incomplete/broken response from ", uri);
return ""; return "";
} }
if (res.code != 200) { if (res.code != 200) {
LogPrint(eLogError, "Reseed: failed to reseed from ", uri, ", http code ", res.code); LogPrint(eLogError, "Reseed: Failed to reseed from ", uri, ", http code ", res.code);
return ""; return "";
} }
data.erase(0, len); /* drop http headers from response */ data.erase(0, len); /* drop http headers from response */
LogPrint(eLogDebug, "Reseed: got ", data.length(), " bytes of data from ", uri); LogPrint(eLogDebug, "Reseed: Got ", data.length(), " bytes of data from ", uri);
if (res.is_chunked()) { if (res.is_chunked()) {
std::stringstream in(data), out; std::stringstream in(data), out;
if (!i2p::http::MergeChunkedResponse(in, out)) { if (!i2p::http::MergeChunkedResponse(in, out)) {
LogPrint(eLogWarning, "Reseed: failed to merge chunked response from ", uri); LogPrint(eLogWarning, "Reseed: Failed to merge chunked response from ", uri);
return ""; return "";
} }
LogPrint(eLogDebug, "Reseed: got ", data.length(), "(", out.tellg(), ") bytes of data from ", uri); LogPrint(eLogDebug, "Reseed: Got ", data.length(), "(", out.tellg(), ") bytes of data from ", uri);
data = out.str(); data = out.str();
} }
return data; return data;
} }
std::string Reseeder::YggdrasilRequest (const std::string& address) std::string Reseeder::YggdrasilRequest (const std::string& address)
{ {
i2p::http::URL url; i2p::http::URL url;
if (!url.parse(address)) if (!url.parse(address))
{ {
LogPrint(eLogError, "Reseed: failed to parse url: ", address); LogPrint(eLogError, "Reseed: Failed to parse URL: ", address);
return ""; return "";
} }
url.schema = "http"; url.schema = "http";
if (!url.port) url.port = 80; if (!url.port) url.port = 80;
boost::system::error_code ecode; boost::system::error_code ecode;
boost::asio::io_service service; boost::asio::io_service service;
boost::asio::ip::tcp::socket s(service, boost::asio::ip::tcp::v6()); boost::asio::ip::tcp::socket s(service, boost::asio::ip::tcp::v6());
if (url.host.length () < 2) return ""; // assume [] if (url.host.length () < 2) return ""; // assume []
@ -789,9 +789,9 @@ namespace data
return ReseedRequest (s, url.to_string()); return ReseedRequest (s, url.to_string());
} }
else else
LogPrint (eLogError, "Reseed: Couldn't connect to yggdrasil ", url.host, ": ", ecode.message ()); LogPrint (eLogError, "Reseed: Couldn't connect to yggdrasil ", url.host, ": ", ecode.message ());
return ""; return "";
} }
} }
} }

View file

@ -205,10 +205,10 @@ namespace data
char transportStyle[6]; char transportStyle[6];
ReadString (transportStyle, 6, s); ReadString (transportStyle, 6, s);
if (!strncmp (transportStyle, "NTCP", 4)) // NTCP or NTCP2 if (!strncmp (transportStyle, "NTCP", 4)) // NTCP or NTCP2
{ {
address->transportStyle = eTransportNTCP; address->transportStyle = eTransportNTCP;
address->ntcp2.reset (new NTCP2Ext ()); address->ntcp2.reset (new NTCP2Ext ());
} }
else if (!strcmp (transportStyle, "SSU")) else if (!strcmp (transportStyle, "SSU"))
{ {
address->transportStyle = eTransportSSU; address->transportStyle = eTransportSSU;
@ -302,39 +302,39 @@ namespace data
if (address->transportStyle == eTransportNTCP) if (address->transportStyle == eTransportNTCP)
{ {
if (isStaticKey) if (isStaticKey)
{ {
if (isHost) if (isHost)
{ {
if (address->host.is_v6 ()) if (address->host.is_v6 ())
supportedTransports |= (i2p::util::net::IsYggdrasilAddress (address->host) ? eNTCP2V6Mesh : eNTCP2V6); supportedTransports |= (i2p::util::net::IsYggdrasilAddress (address->host) ? eNTCP2V6Mesh : eNTCP2V6);
else else
supportedTransports |= eNTCP2V4; supportedTransports |= eNTCP2V4;
m_ReachableTransports |= supportedTransports; m_ReachableTransports |= supportedTransports;
} }
else if (!address->published) else if (!address->published)
{ {
if (address->caps) if (address->caps)
{ {
if (address->caps & AddressCaps::eV4) supportedTransports |= eNTCP2V4; if (address->caps & AddressCaps::eV4) supportedTransports |= eNTCP2V4;
if (address->caps & AddressCaps::eV6) supportedTransports |= eNTCP2V6; if (address->caps & AddressCaps::eV6) supportedTransports |= eNTCP2V6;
} }
else else
supportedTransports |= eNTCP2V4; // most likely, since we don't have host supportedTransports |= eNTCP2V4; // most likely, since we don't have host
} }
} }
} }
else if (address->transportStyle == eTransportSSU) else if (address->transportStyle == eTransportSSU)
{ {
if (isIntroKey) if (isIntroKey)
{ {
if (isHost) if (isHost)
supportedTransports |= address->host.is_v4 () ? eSSUV4 : eSSUV6; supportedTransports |= address->host.is_v4 () ? eSSUV4 : eSSUV6;
else if (address->caps & AddressCaps::eV6) else if (address->caps & AddressCaps::eV6)
{ {
supportedTransports |= eSSUV6; supportedTransports |= eSSUV6;
if (address->caps & AddressCaps::eV4) supportedTransports |= eSSUV4; // in additional to v6 if (address->caps & AddressCaps::eV4) supportedTransports |= eSSUV4; // in additional to v6
} }
else else
supportedTransports |= eSSUV4; // in case if host or 6 caps is not preasented, we assume 4 supportedTransports |= eSSUV4; // in case if host or 6 caps is not preasented, we assume 4
if (address->ssu && !address->ssu->introducers.empty ()) if (address->ssu && !address->ssu->introducers.empty ())
{ {
@ -344,24 +344,24 @@ namespace data
for (auto& it: address->ssu->introducers) for (auto& it: address->ssu->introducers)
{ {
if (!it.iExp) it.iExp = m_Timestamp/1000 + NETDB_INTRODUCEE_EXPIRATION_TIMEOUT; if (!it.iExp) it.iExp = m_Timestamp/1000 + NETDB_INTRODUCEE_EXPIRATION_TIMEOUT;
if (ts <= it.iExp && it.iPort > 0 && if (ts <= it.iExp && it.iPort > 0 &&
((it.iHost.is_v4 () && address->IsV4 ()) || (it.iHost.is_v6 () && address->IsV6 ()))) ((it.iHost.is_v4 () && address->IsV4 ()) || (it.iHost.is_v6 () && address->IsV6 ())))
numValid++; numValid++;
else else
it.iPort = 0; it.iPort = 0;
} }
if (numValid) if (numValid)
m_ReachableTransports |= supportedTransports; m_ReachableTransports |= supportedTransports;
else else
address->ssu->introducers.resize (0); address->ssu->introducers.resize (0);
} }
else if (isHost && address->port) else if (isHost && address->port)
{ {
address->published = true; address->published = true;
m_ReachableTransports |= supportedTransports; m_ReachableTransports |= supportedTransports;
} }
} }
} }
if (supportedTransports) if (supportedTransports)
{ {
addresses->push_back(address); addresses->push_back(address);
@ -486,10 +486,10 @@ namespace data
{ {
case CAPS_FLAG_V4: case CAPS_FLAG_V4:
caps |= AddressCaps::eV4; caps |= AddressCaps::eV4;
break; break;
case CAPS_FLAG_V6: case CAPS_FLAG_V6:
caps |= AddressCaps::eV6; caps |= AddressCaps::eV6;
break; break;
case CAPS_FLAG_SSU_TESTING: case CAPS_FLAG_SSU_TESTING:
caps |= AddressCaps::eSSUTesting; caps |= AddressCaps::eSSUTesting;
break; break;
@ -502,7 +502,7 @@ namespace data
} }
return caps; return caps;
} }
void RouterInfo::UpdateCapsProperty () void RouterInfo::UpdateCapsProperty ()
{ {
std::string caps; std::string caps;
@ -553,7 +553,7 @@ namespace data
if (address.transportStyle == eTransportNTCP) if (address.transportStyle == eTransportNTCP)
{ {
if (address.IsNTCP2 ()) if (address.IsNTCP2 ())
{ {
WriteString ("NTCP2", s); WriteString ("NTCP2", s);
if (address.IsPublishedNTCP2 () && !address.host.is_unspecified () && address.port) if (address.IsPublishedNTCP2 () && !address.host.is_unspecified () && address.port)
isPublished = true; isPublished = true;
@ -567,45 +567,45 @@ namespace data
if (caps.empty ()) caps += CAPS_FLAG_V4; if (caps.empty ()) caps += CAPS_FLAG_V4;
WriteString (caps, properties); WriteString (caps, properties);
properties << ';'; properties << ';';
} }
} }
else else
continue; // don't write NTCP address continue; // don't write NTCP address
} }
else if (address.transportStyle == eTransportSSU) else if (address.transportStyle == eTransportSSU)
{ {
WriteString ("SSU", s); WriteString ("SSU", s);
// caps // caps
WriteString ("caps", properties); WriteString ("caps", properties);
properties << '='; properties << '=';
std::string caps; std::string caps;
if (address.IsPeerTesting ()) caps += CAPS_FLAG_SSU_TESTING; if (address.IsPeerTesting ()) caps += CAPS_FLAG_SSU_TESTING;
if (address.host.is_v4 ()) if (address.host.is_v4 ())
{ {
if (address.published) if (address.published)
{ {
isPublished = true; isPublished = true;
if (address.IsIntroducer ()) caps += CAPS_FLAG_SSU_INTRODUCER; if (address.IsIntroducer ()) caps += CAPS_FLAG_SSU_INTRODUCER;
} }
else else
caps += CAPS_FLAG_V4; caps += CAPS_FLAG_V4;
} }
else if (address.host.is_v6 ()) else if (address.host.is_v6 ())
{ {
if (address.published) if (address.published)
{ {
isPublished = true; isPublished = true;
if (address.IsIntroducer ()) caps += CAPS_FLAG_SSU_INTRODUCER; if (address.IsIntroducer ()) caps += CAPS_FLAG_SSU_INTRODUCER;
} }
else else
caps += CAPS_FLAG_V6; caps += CAPS_FLAG_V6;
} }
else else
{ {
if (address.IsV4 ()) caps += CAPS_FLAG_V4; if (address.IsV4 ()) caps += CAPS_FLAG_V4;
if (address.IsV6 ()) caps += CAPS_FLAG_V6; if (address.IsV6 ()) caps += CAPS_FLAG_V6;
if (caps.empty ()) caps += CAPS_FLAG_V4; if (caps.empty ()) caps += CAPS_FLAG_V4;
} }
WriteString (caps, properties); WriteString (caps, properties);
properties << ';'; properties << ';';
} }
@ -809,7 +809,7 @@ namespace data
} }
else else
{ {
LogPrint (eLogWarning, "RouterInfo: string length ", (int)l, " exceeds buffer size ", len); LogPrint (eLogWarning, "RouterInfo: String length ", (int)l, " exceeds buffer size ", len);
s.seekg (l, std::ios::cur); // skip s.seekg (l, std::ios::cur); // skip
str[0] = 0; str[0] = 0;
} }
@ -845,13 +845,13 @@ namespace data
m_Addresses->push_back(std::move(addr)); m_Addresses->push_back(std::move(addr));
} }
void RouterInfo::AddNTCP2Address (const uint8_t * staticKey, const uint8_t * iv, void RouterInfo::AddNTCP2Address (const uint8_t * staticKey, const uint8_t * iv,
const boost::asio::ip::address& host, int port, uint8_t caps) const boost::asio::ip::address& host, int port, uint8_t caps)
{ {
auto addr = std::make_shared<Address>(); auto addr = std::make_shared<Address>();
addr->host = host; addr->host = host;
addr->port = port; addr->port = port;
addr->transportStyle = eTransportNTCP; addr->transportStyle = eTransportNTCP;
addr->caps = caps; addr->caps = caps;
addr->date = 0; addr->date = 0;
addr->ntcp2.reset (new NTCP2Ext ()); addr->ntcp2.reset (new NTCP2Ext ());
@ -862,12 +862,12 @@ namespace data
{ {
m_SupportedTransports |= eNTCP2V4; m_SupportedTransports |= eNTCP2V4;
if (addr->published) m_ReachableTransports |= eNTCP2V4; if (addr->published) m_ReachableTransports |= eNTCP2V4;
} }
if (addr->IsV6 ()) if (addr->IsV6 ())
{ {
m_SupportedTransports |= eNTCP2V6; m_SupportedTransports |= eNTCP2V6;
if (addr->published) m_ReachableTransports |= eNTCP2V6; if (addr->published) m_ReachableTransports |= eNTCP2V6;
} }
m_Addresses->push_back(std::move(addr)); m_Addresses->push_back(std::move(addr));
} }
@ -875,7 +875,7 @@ namespace data
{ {
for (auto& addr : *m_Addresses) for (auto& addr : *m_Addresses)
{ {
if (addr->transportStyle == eTransportSSU && if (addr->transportStyle == eTransportSSU &&
((addr->IsV4 () && introducer.iHost.is_v4 ()) || (addr->IsV6 () && introducer.iHost.is_v6 ()))) ((addr->IsV4 () && introducer.iHost.is_v4 ()) || (addr->IsV6 () && introducer.iHost.is_v6 ())))
{ {
for (auto& intro: addr->ssu->introducers) for (auto& intro: addr->ssu->introducers)
@ -892,7 +892,7 @@ namespace data
{ {
for (auto& addr: *m_Addresses) for (auto& addr: *m_Addresses)
{ {
if (addr->transportStyle == eTransportSSU && if (addr->transportStyle == eTransportSSU &&
((addr->IsV4 () && e.address ().is_v4 ()) || (addr->IsV6 () && e.address ().is_v6 ()))) ((addr->IsV4 () && e.address ().is_v4 ()) || (addr->IsV6 () && e.address ().is_v6 ())))
{ {
for (auto it = addr->ssu->introducers.begin (); it != addr->ssu->introducers.end (); ++it) for (auto it = addr->ssu->introducers.begin (); it != addr->ssu->introducers.end (); ++it)
@ -963,8 +963,8 @@ namespace data
bool RouterInfo::IsNTCP2V6 () const bool RouterInfo::IsNTCP2V6 () const
{ {
return m_SupportedTransports & eNTCP2V6; return m_SupportedTransports & eNTCP2V6;
} }
bool RouterInfo::IsV6 () const bool RouterInfo::IsV6 () const
{ {
return m_SupportedTransports & (eSSUV6 | eNTCP2V6); return m_SupportedTransports & (eSSUV6 | eNTCP2V6);
@ -978,28 +978,28 @@ namespace data
bool RouterInfo::IsMesh () const bool RouterInfo::IsMesh () const
{ {
return m_SupportedTransports & eNTCP2V6Mesh; return m_SupportedTransports & eNTCP2V6Mesh;
} }
void RouterInfo::EnableV6 () void RouterInfo::EnableV6 ()
{ {
if (!IsV6 ()) if (!IsV6 ())
{ {
uint8_t addressCaps = AddressCaps::eV6; uint8_t addressCaps = AddressCaps::eV6;
if (IsV4 ()) addressCaps |= AddressCaps::eV4; if (IsV4 ()) addressCaps |= AddressCaps::eV4;
SetUnreachableAddressesTransportCaps (addressCaps); SetUnreachableAddressesTransportCaps (addressCaps);
UpdateSupportedTransports (); UpdateSupportedTransports ();
} }
} }
void RouterInfo::EnableV4 () void RouterInfo::EnableV4 ()
{ {
if (!IsV4 ()) if (!IsV4 ())
{ {
uint8_t addressCaps = AddressCaps::eV4; uint8_t addressCaps = AddressCaps::eV4;
if (IsV6 ()) addressCaps |= AddressCaps::eV6; if (IsV6 ()) addressCaps |= AddressCaps::eV6;
SetUnreachableAddressesTransportCaps (addressCaps); SetUnreachableAddressesTransportCaps (addressCaps);
UpdateSupportedTransports (); UpdateSupportedTransports ();
} }
} }
@ -1011,15 +1011,15 @@ namespace data
{ {
auto addr = *it; auto addr = *it;
if (addr->IsV6 ()) if (addr->IsV6 ())
{ {
if (addr->IsV4 ()) if (addr->IsV4 ())
{ {
addr->caps &= ~AddressCaps::eV6; addr->caps &= ~AddressCaps::eV6;
++it; ++it;
} }
else else
it = m_Addresses->erase (it); it = m_Addresses->erase (it);
} }
else else
++it; ++it;
} }
@ -1035,15 +1035,15 @@ namespace data
{ {
auto addr = *it; auto addr = *it;
if (addr->IsV4 ()) if (addr->IsV4 ())
{ {
if (addr->IsV6 ()) if (addr->IsV6 ())
{ {
addr->caps &= ~AddressCaps::eV4; addr->caps &= ~AddressCaps::eV4;
++it; ++it;
} }
else else
it = m_Addresses->erase (it); it = m_Addresses->erase (it);
} }
else else
++it; ++it;
} }
@ -1054,14 +1054,14 @@ namespace data
void RouterInfo::EnableMesh () void RouterInfo::EnableMesh ()
{ {
if (!IsMesh ()) if (!IsMesh ())
{ {
m_SupportedTransports |= eNTCP2V6Mesh; m_SupportedTransports |= eNTCP2V6Mesh;
m_ReachableTransports |= eNTCP2V6Mesh; m_ReachableTransports |= eNTCP2V6Mesh;
} }
} }
void RouterInfo::DisableMesh () void RouterInfo::DisableMesh ()
{ {
if (IsMesh ()) if (IsMesh ())
{ {
m_SupportedTransports &= ~eNTCP2V6Mesh; m_SupportedTransports &= ~eNTCP2V6Mesh;
@ -1074,8 +1074,8 @@ namespace data
else else
++it; ++it;
} }
} }
} }
std::shared_ptr<const RouterInfo::Address> RouterInfo::GetSSUAddress (bool v4only) const std::shared_ptr<const RouterInfo::Address> RouterInfo::GetSSUAddress (bool v4only) const
{ {
@ -1115,7 +1115,7 @@ namespace data
if (!key) return nullptr; if (!key) return nullptr;
return GetAddress ( return GetAddress (
[key](std::shared_ptr<const RouterInfo::Address> address)->bool [key](std::shared_ptr<const RouterInfo::Address> address)->bool
{ {
return address->IsNTCP2 () && !memcmp (address->ntcp2->staticKey, key, 32); return address->IsNTCP2 () && !memcmp (address->ntcp2->staticKey, key, 32);
}); });
} }
@ -1128,16 +1128,16 @@ namespace data
return address->IsPublishedNTCP2 () && address->host.is_v4 (); return address->IsPublishedNTCP2 () && address->host.is_v4 ();
}); });
} }
std::shared_ptr<const RouterInfo::Address> RouterInfo::GetPublishedNTCP2V6Address () const std::shared_ptr<const RouterInfo::Address> RouterInfo::GetPublishedNTCP2V6Address () const
{ {
return GetAddress ( return GetAddress (
[](std::shared_ptr<const RouterInfo::Address> address)->bool [](std::shared_ptr<const RouterInfo::Address> address)->bool
{ {
return address->IsPublishedNTCP2 () && address->host.is_v6 () && return address->IsPublishedNTCP2 () && address->host.is_v6 () &&
!i2p::util::net::IsYggdrasilAddress (address->host); !i2p::util::net::IsYggdrasilAddress (address->host);
}); });
} }
std::shared_ptr<const RouterInfo::Address> RouterInfo::GetYggdrasilAddress () const std::shared_ptr<const RouterInfo::Address> RouterInfo::GetYggdrasilAddress () const
{ {
@ -1146,8 +1146,8 @@ namespace data
{ {
return address->IsPublishedNTCP2 () && i2p::util::net::IsYggdrasilAddress (address->host); return address->IsPublishedNTCP2 () && i2p::util::net::IsYggdrasilAddress (address->host);
}); });
} }
std::shared_ptr<RouterProfile> RouterInfo::GetProfile () const std::shared_ptr<RouterProfile> RouterInfo::GetProfile () const
{ {
if (!m_Profile) if (!m_Profile)
@ -1162,34 +1162,34 @@ namespace data
encryptor->Encrypt (data, encrypted); encryptor->Encrypt (data, encrypted);
} }
bool RouterInfo::IsEligibleFloodfill () const bool RouterInfo::IsEligibleFloodfill () const
{ {
// floodfill must be reachable by ipv4, >= 0.9.38 and not DSA // floodfill must be reachable by ipv4, >= 0.9.38 and not DSA
return IsReachableBy (eNTCP2V4 | eSSUV4) && m_Version >= NETDB_MIN_FLOODFILL_VERSION && return IsReachableBy (eNTCP2V4 | eSSUV4) && m_Version >= NETDB_MIN_FLOODFILL_VERSION &&
GetIdentity ()->GetSigningKeyType () != SIGNING_KEY_TYPE_DSA_SHA1; GetIdentity ()->GetSigningKeyType () != SIGNING_KEY_TYPE_DSA_SHA1;
} }
bool RouterInfo::IsPeerTesting (bool v4) const bool RouterInfo::IsPeerTesting (bool v4) const
{ {
if (!(m_SupportedTransports & (v4 ? eSSUV4 : eSSUV6))) return false; if (!(m_SupportedTransports & (v4 ? eSSUV4 : eSSUV6))) return false;
return (bool)GetAddress ( return (bool)GetAddress (
[v4](std::shared_ptr<const RouterInfo::Address> address)->bool [v4](std::shared_ptr<const RouterInfo::Address> address)->bool
{ {
return (address->transportStyle == eTransportSSU) && address->IsPeerTesting () && return (address->transportStyle == eTransportSSU) && address->IsPeerTesting () &&
((v4 && address->IsV4 ()) || (!v4 && address->IsV6 ())) && address->IsReachableSSU (); ((v4 && address->IsV4 ()) || (!v4 && address->IsV6 ())) && address->IsReachableSSU ();
}); });
} }
bool RouterInfo::IsIntroducer (bool v4) const bool RouterInfo::IsIntroducer (bool v4) const
{ {
if (!(m_SupportedTransports & (v4 ? eSSUV4 : eSSUV6))) return false; if (!(m_SupportedTransports & (v4 ? eSSUV4 : eSSUV6))) return false;
return (bool)GetAddress ( return (bool)GetAddress (
[v4](std::shared_ptr<const RouterInfo::Address> address)->bool [v4](std::shared_ptr<const RouterInfo::Address> address)->bool
{ {
return (address->transportStyle == eTransportSSU) && address->IsIntroducer () && return (address->transportStyle == eTransportSSU) && address->IsIntroducer () &&
((v4 && address->IsV4 ()) || (!v4 && address->IsV6 ())) && !address->host.is_unspecified (); ((v4 && address->IsV4 ()) || (!v4 && address->IsV6 ())) && !address->host.is_unspecified ();
}); });
} }
void RouterInfo::SetUnreachableAddressesTransportCaps (uint8_t transports) void RouterInfo::SetUnreachableAddressesTransportCaps (uint8_t transports)
{ {
@ -1214,7 +1214,7 @@ namespace data
if (addr->transportStyle == eTransportNTCP) if (addr->transportStyle == eTransportNTCP)
{ {
if (addr->IsV4 ()) transports |= eNTCP2V4; if (addr->IsV4 ()) transports |= eNTCP2V4;
if (addr->IsV6 ()) if (addr->IsV6 ())
transports |= (i2p::util::net::IsYggdrasilAddress (addr->host) ? eNTCP2V6Mesh : eNTCP2V6); transports |= (i2p::util::net::IsYggdrasilAddress (addr->host) ? eNTCP2V6Mesh : eNTCP2V6);
if (addr->IsPublishedNTCP2 ()) if (addr->IsPublishedNTCP2 ())
m_ReachableTransports |= transports; m_ReachableTransports |= transports;
@ -1225,9 +1225,9 @@ namespace data
if (addr->IsV6 ()) transports |= eSSUV6; if (addr->IsV6 ()) transports |= eSSUV6;
if (addr->IsReachableSSU ()) if (addr->IsReachableSSU ())
m_ReachableTransports |= transports; m_ReachableTransports |= transports;
} }
m_SupportedTransports |= transports; m_SupportedTransports |= transports;
} }
} }
} }
} }

View file

@ -53,7 +53,7 @@ namespace transport
} }
catch ( std::exception & ex ) catch ( std::exception & ex )
{ {
LogPrint (eLogError, "SSU: failed to bind to v4 port ", m_Endpoint.port(), ": ", ex.what()); LogPrint (eLogError, "SSU: Failed to bind to v4 port ", m_Endpoint.port(), ": ", ex.what());
ThrowFatal ("Unable to start IPv4 SSU transport at port ", m_Endpoint.port(), ": ", ex.what ()); ThrowFatal ("Unable to start IPv4 SSU transport at port ", m_Endpoint.port(), ": ", ex.what ());
} }
} }
@ -83,7 +83,7 @@ namespace transport
} }
catch ( std::exception & ex ) catch ( std::exception & ex )
{ {
LogPrint (eLogError, "SSU: failed to bind to v6 port ", m_EndpointV6.port(), ": ", ex.what()); LogPrint (eLogError, "SSU: Failed to bind to v6 port ", m_EndpointV6.port(), ": ", ex.what());
ThrowFatal ("Unable to start IPv6 SSU transport at port ", m_Endpoint.port(), ": ", ex.what ()); ThrowFatal ("Unable to start IPv6 SSU transport at port ", m_Endpoint.port(), ": ", ex.what ());
} }
} }
@ -156,7 +156,7 @@ namespace transport
} }
catch (std::exception& ex) catch (std::exception& ex)
{ {
LogPrint (eLogError, "SSU: server runtime exception: ", ex.what ()); LogPrint (eLogError, "SSU: Server runtime exception: ", ex.what ());
} }
} }
} }
@ -173,7 +173,7 @@ namespace transport
} }
catch (std::exception& ex) catch (std::exception& ex)
{ {
LogPrint (eLogError, "SSU: receivers runtime exception: ", ex.what ()); LogPrint (eLogError, "SSU: Receivers runtime exception: ", ex.what ());
if (m_IsRunning) if (m_IsRunning)
{ {
// restart socket // restart socket
@ -249,7 +249,7 @@ namespace transport
if (ec) if (ec)
{ {
LogPrint (eLogError, "SSU: send exception: ", ec.message (), " while trying to send data to ", to.address (), ":", to.port (), " (length: ", len, ")"); LogPrint (eLogError, "SSU: Send exception: ", ec.message (), " while trying to send data to ", to.address (), ":", to.port (), " (length: ", len, ")");
} }
} }
@ -318,7 +318,7 @@ namespace transport
delete packet; delete packet;
if (ecode != boost::asio::error::operation_aborted) if (ecode != boost::asio::error::operation_aborted)
{ {
LogPrint (eLogError, "SSU: receive error: code ", ecode.value(), ": ", ecode.message ()); LogPrint (eLogError, "SSU: Receive error: code ", ecode.value(), ": ", ecode.message ());
m_Socket.close (); m_Socket.close ();
OpenSocket (); OpenSocket ();
Receive (); Receive ();
@ -409,7 +409,7 @@ namespace transport
session = std::make_shared<SSUSession> (*this, packet->from); session = std::make_shared<SSUSession> (*this, packet->from);
session->WaitForConnect (); session->WaitForConnect ();
(*sessions)[packet->from] = session; (*sessions)[packet->from] = session;
LogPrint (eLogDebug, "SSU: new session from ", packet->from.address ().to_string (), ":", packet->from.port (), " created"); LogPrint (eLogDebug, "SSU: New session from ", packet->from.address ().to_string (), ":", packet->from.port (), " created");
} }
} }
if (session) if (session)
@ -548,7 +548,7 @@ namespace transport
} }
if (!introducer) if (!introducer)
{ {
LogPrint (eLogWarning, "SSU: Can't connect to unreachable router and no compatibe non-expired introducers presented"); LogPrint (eLogWarning, "SSU: Can't connect to unreachable router, no compatible introducers");
return; return;
} }
@ -797,7 +797,7 @@ namespace transport
if (sessions.empty () && !introducers.empty ()) if (sessions.empty () && !introducers.empty ())
{ {
// bump creation time for previous introducers if no new sessions found // bump creation time for previous introducers if no new sessions found
LogPrint (eLogDebug, "SSU: no new introducers found. Trying to reuse existing"); LogPrint (eLogDebug, "SSU: No new introducers found. Trying to reuse existing");
for (const auto& it : introducers) for (const auto& it : introducers)
{ {
auto session = FindSession (it); auto session = FindSession (it);
@ -847,7 +847,7 @@ namespace transport
} }
else else
{ {
LogPrint (eLogDebug, "SSU: can't find more introducers"); LogPrint (eLogDebug, "SSU: Can't find more introducers");
break; break;
} }
} }
@ -945,10 +945,10 @@ namespace transport
{ {
auto session = it.second; auto session = it.second;
if (it.first != session->GetRemoteEndpoint ()) if (it.first != session->GetRemoteEndpoint ())
LogPrint (eLogWarning, "SSU: remote endpoint ", session->GetRemoteEndpoint (), " doesn't match key ", it.first, " adjusted"); LogPrint (eLogWarning, "SSU: Remote endpoint ", session->GetRemoteEndpoint (), " doesn't match key ", it.first, " adjusted");
m_Service.post ([session] m_Service.post ([session]
{ {
LogPrint (eLogWarning, "SSU: no activity with ", session->GetRemoteEndpoint (), " for ", session->GetTerminationTimeout (), " seconds"); LogPrint (eLogWarning, "SSU: No activity with ", session->GetRemoteEndpoint (), " for ", session->GetTerminationTimeout (), " seconds");
session->Failed (); session->Failed ();
}); });
} }
@ -973,10 +973,10 @@ namespace transport
{ {
auto session = it.second; auto session = it.second;
if (it.first != session->GetRemoteEndpoint ()) if (it.first != session->GetRemoteEndpoint ())
LogPrint (eLogWarning, "SSU: remote endpoint ", session->GetRemoteEndpoint (), " doesn't match key ", it.first); LogPrint (eLogWarning, "SSU: Remote endpoint ", session->GetRemoteEndpoint (), " doesn't match key ", it.first);
m_Service.post ([session] m_Service.post ([session]
{ {
LogPrint (eLogWarning, "SSU: no activity with ", session->GetRemoteEndpoint (), " for ", session->GetTerminationTimeout (), " seconds"); LogPrint (eLogWarning, "SSU: No activity with ", session->GetRemoteEndpoint (), " for ", session->GetTerminationTimeout (), " seconds");
session->Failed (); session->Failed ();
}); });
} }

View file

@ -177,12 +177,12 @@ namespace transport
ProcessSessionConfirmed (buf, len); // buf with header ProcessSessionConfirmed (buf, len); // buf with header
break; break;
case PAYLOAD_TYPE_PEER_TEST: case PAYLOAD_TYPE_PEER_TEST:
LogPrint (eLogDebug, "SSU: peer test received"); LogPrint (eLogDebug, "SSU: Peer test received");
ProcessPeerTest (buf + headerSize, len - headerSize, senderEndpoint); ProcessPeerTest (buf + headerSize, len - headerSize, senderEndpoint);
break; break;
case PAYLOAD_TYPE_SESSION_DESTROYED: case PAYLOAD_TYPE_SESSION_DESTROYED:
{ {
LogPrint (eLogDebug, "SSU: session destroy received"); LogPrint (eLogDebug, "SSU: Session destroy received");
m_Server.DeleteSession (shared_from_this ()); m_Server.DeleteSession (shared_from_this ());
break; break;
} }
@ -192,11 +192,11 @@ namespace transport
m_Server.DeleteSession (shared_from_this ()); m_Server.DeleteSession (shared_from_this ());
break; break;
case PAYLOAD_TYPE_RELAY_REQUEST: case PAYLOAD_TYPE_RELAY_REQUEST:
LogPrint (eLogDebug, "SSU: relay request received"); LogPrint (eLogDebug, "SSU: Relay request received");
ProcessRelayRequest (buf + headerSize, len - headerSize, senderEndpoint); ProcessRelayRequest (buf + headerSize, len - headerSize, senderEndpoint);
break; break;
case PAYLOAD_TYPE_RELAY_INTRO: case PAYLOAD_TYPE_RELAY_INTRO:
LogPrint (eLogDebug, "SSU: relay intro received"); LogPrint (eLogDebug, "SSU: Relay intro received");
ProcessRelayIntro (buf + headerSize, len - headerSize); ProcessRelayIntro (buf + headerSize, len - headerSize);
break; break;
default: default:
@ -206,7 +206,7 @@ namespace transport
void SSUSession::ProcessSessionRequest (const uint8_t * buf, size_t len) void SSUSession::ProcessSessionRequest (const uint8_t * buf, size_t len)
{ {
LogPrint (eLogDebug, "SSU message: session request"); LogPrint (eLogDebug, "SSU: Session request");
bool sendRelayTag = true; bool sendRelayTag = true;
auto headerSize = sizeof (SSUHeader); auto headerSize = sizeof (SSUHeader);
if (((SSUHeader *)buf)->IsExtendedOptions ()) if (((SSUHeader *)buf)->IsExtendedOptions ())
@ -222,7 +222,7 @@ namespace transport
} }
if (headerSize >= len) if (headerSize >= len)
{ {
LogPrint (eLogError, "Session request header size ", headerSize, " exceeds packet length ", len); LogPrint (eLogError, "SSU: Session request header size ", headerSize, " exceeds packet length ", len);
return; return;
} }
if (!m_DHKeysPair) if (!m_DHKeysPair)
@ -230,7 +230,7 @@ namespace transport
auto pair = std::make_shared<i2p::crypto::DHKeys> (); auto pair = std::make_shared<i2p::crypto::DHKeys> ();
pair->GenerateKeys (); pair->GenerateKeys ();
m_DHKeysPair = pair; m_DHKeysPair = pair;
} }
CreateAESandMacKey (buf + headerSize); CreateAESandMacKey (buf + headerSize);
SendSessionCreated (buf + headerSize, sendRelayTag); SendSessionCreated (buf + headerSize, sendRelayTag);
} }
@ -243,13 +243,13 @@ namespace transport
return; return;
} }
LogPrint (eLogDebug, "SSU message: session created"); LogPrint (eLogDebug, "SSU: Session created");
m_ConnectTimer.cancel (); // connect timer m_ConnectTimer.cancel (); // connect timer
SignedData s; // x,y, our IP, our port, remote IP, remote port, relayTag, signed on time SignedData s; // x,y, our IP, our port, remote IP, remote port, relayTag, signed on time
auto headerSize = GetSSUHeaderSize (buf); auto headerSize = GetSSUHeaderSize (buf);
if (headerSize >= len) if (headerSize >= len)
{ {
LogPrint (eLogError, "Session created header size ", headerSize, " exceeds packet length ", len); LogPrint (eLogError, "SSU: Session created header size ", headerSize, " exceeds packet length ", len);
return; return;
} }
uint8_t * payload = buf + headerSize; uint8_t * payload = buf + headerSize;
@ -259,7 +259,7 @@ namespace transport
s.Insert (y, 256); // y s.Insert (y, 256); // y
payload += 256; payload += 256;
boost::asio::ip::address ourIP; boost::asio::ip::address ourIP;
uint16_t ourPort = 0; uint16_t ourPort = 0;
auto addressAndPortLen = ExtractIPAddressAndPort (payload, len, ourIP, ourPort); auto addressAndPortLen = ExtractIPAddressAndPort (payload, len, ourIP, ourPort);
if (!addressAndPortLen) return; if (!addressAndPortLen) return;
uint8_t * ourAddressAndPort = payload + 1; uint8_t * ourAddressAndPort = payload + 1;
@ -280,7 +280,7 @@ namespace transport
uint32_t signedOnTime = bufbe32toh(payload); uint32_t signedOnTime = bufbe32toh(payload);
if (signedOnTime < ts - SSU_CLOCK_SKEW || signedOnTime > ts + SSU_CLOCK_SKEW) if (signedOnTime < ts - SSU_CLOCK_SKEW || signedOnTime > ts + SSU_CLOCK_SKEW)
{ {
LogPrint (eLogError, "SSU: clock skew detected ", (int)ts - signedOnTime, ". Check your clock"); LogPrint (eLogError, "SSU: Clock skew detected ", (int)ts - signedOnTime, ". Check your clock!");
i2p::context.SetError (eRouterErrorClockSkew); i2p::context.SetError (eRouterErrorClockSkew);
} }
} }
@ -297,19 +297,19 @@ namespace transport
{ {
LogPrint (eLogInfo, "SSU: Our external address is ", ourIP.to_string (), ":", ourPort); LogPrint (eLogInfo, "SSU: Our external address is ", ourIP.to_string (), ":", ourPort);
if (!i2p::util::net::IsInReservedRange (ourIP)) if (!i2p::util::net::IsInReservedRange (ourIP))
{ {
i2p::context.UpdateAddress (ourIP); i2p::context.UpdateAddress (ourIP);
SendSessionConfirmed (y, ourAddressAndPort, addressAndPortLen); SendSessionConfirmed (y, ourAddressAndPort, addressAndPortLen);
} }
else else
{ {
LogPrint (eLogError, "SSU: Wrong external address ", ourIP.to_string ()); LogPrint (eLogError, "SSU: Wrong external address ", ourIP.to_string ());
Failed (); Failed ();
} }
} }
else else
{ {
LogPrint (eLogError, "SSU: message 'created' signature verification failed"); LogPrint (eLogError, "SSU: Message 'created' signature verification failed");
Failed (); Failed ();
} }
} }
@ -317,7 +317,7 @@ namespace transport
void SSUSession::ProcessSessionConfirmed (const uint8_t * buf, size_t len) void SSUSession::ProcessSessionConfirmed (const uint8_t * buf, size_t len)
{ {
LogPrint (eLogDebug, "SSU: Session confirmed received"); LogPrint (eLogDebug, "SSU: Session confirmed received");
m_ConnectTimer.cancel (); m_ConnectTimer.cancel ();
auto headerSize = GetSSUHeaderSize (buf); auto headerSize = GetSSUHeaderSize (buf);
if (headerSize >= len) if (headerSize >= len)
{ {
@ -331,7 +331,7 @@ namespace transport
{ {
LogPrint (eLogError, "SSU: Session confirmed identity size ", identitySize, " exceeds packet length ", len); LogPrint (eLogError, "SSU: Session confirmed identity size ", identitySize, " exceeds packet length ", len);
return; return;
} }
payload += 2; // size of identity fragment payload += 2; // size of identity fragment
auto identity = std::make_shared<i2p::data::IdentityEx> (payload, identitySize); auto identity = std::make_shared<i2p::data::IdentityEx> (payload, identitySize);
auto existing = i2p::data::netdb.FindRouter (identity->GetIdentHash ()); // check if exists already auto existing = i2p::data::netdb.FindRouter (identity->GetIdentHash ()); // check if exists already
@ -342,7 +342,7 @@ namespace transport
uint32_t signedOnTime = bufbe32toh(payload); uint32_t signedOnTime = bufbe32toh(payload);
if (signedOnTime < ts - SSU_CLOCK_SKEW || signedOnTime > ts + SSU_CLOCK_SKEW) if (signedOnTime < ts - SSU_CLOCK_SKEW || signedOnTime > ts + SSU_CLOCK_SKEW)
{ {
LogPrint (eLogError, "SSU message 'confirmed' time difference ", (int)ts - signedOnTime, " exceeds clock skew"); LogPrint (eLogError, "SSU: 'Confirmed' time difference ", (int)ts - signedOnTime, " exceeds clock skew");
Failed (); Failed ();
return; return;
} }
@ -357,7 +357,7 @@ namespace transport
{ {
LogPrint (eLogError, "SSU: Session confirmed message is too short ", len); LogPrint (eLogError, "SSU: Session confirmed message is too short ", len);
return; return;
} }
// verify signature // verify signature
if (m_SignedData && m_SignedData->Verify (m_RemoteIdentity, payload)) if (m_SignedData && m_SignedData->Verify (m_RemoteIdentity, payload))
{ {
@ -366,7 +366,7 @@ namespace transport
} }
else else
{ {
LogPrint (eLogError, "SSU message 'confirmed' signature verification failed"); LogPrint (eLogError, "SSU: 'Confirmed' signature verification failed");
Failed (); Failed ();
} }
} }
@ -599,19 +599,19 @@ namespace transport
uint8_t * payload = buf + sizeof (SSUHeader); uint8_t * payload = buf + sizeof (SSUHeader);
// Charlie // Charlie
if (isV4) if (isV4)
{ {
*payload = 4; *payload = 4;
payload++; // size payload++; // size
memcpy (payload, to.address ().to_v4 ().to_bytes ().data (), 4); // Charlie's IP V4 memcpy (payload, to.address ().to_v4 ().to_bytes ().data (), 4); // Charlie's IP V4
payload += 4; // address payload += 4; // address
} }
else else
{ {
*payload = 16; *payload = 16;
payload++; // size payload++; // size
memcpy (payload, to.address ().to_v6 ().to_bytes ().data (), 16); // Alice's IP V6 memcpy (payload, to.address ().to_v6 ().to_bytes ().data (), 16); // Alice's IP V6
payload += 16; // address payload += 16; // address
} }
htobe16buf (payload, to.port ()); // Charlie's port htobe16buf (payload, to.port ()); // Charlie's port
payload += 2; // port payload += 2; // port
// Alice // Alice
@ -647,7 +647,7 @@ namespace transport
FillHeaderAndEncrypt (PAYLOAD_TYPE_RELAY_RESPONSE, buf, isV4 ? 64 : 80, introKey, iv, introKey); FillHeaderAndEncrypt (PAYLOAD_TYPE_RELAY_RESPONSE, buf, isV4 ? 64 : 80, introKey, iv, introKey);
m_Server.Send (buf, isV4 ? 64 : 80, from); m_Server.Send (buf, isV4 ? 64 : 80, from);
} }
LogPrint (eLogDebug, "SSU: relay response sent"); LogPrint (eLogDebug, "SSU: Relay response sent");
} }
void SSUSession::SendRelayIntro (std::shared_ptr<SSUSession> session, const boost::asio::ip::udp::endpoint& from) void SSUSession::SendRelayIntro (std::shared_ptr<SSUSession> session, const boost::asio::ip::udp::endpoint& from)
@ -683,12 +683,12 @@ namespace transport
RAND_bytes (iv, 16); // random iv RAND_bytes (iv, 16); // random iv
FillHeaderAndEncrypt (PAYLOAD_TYPE_RELAY_INTRO, buf, isV4 ? 48 : 64, session->m_SessionKey, iv, session->m_MacKey); FillHeaderAndEncrypt (PAYLOAD_TYPE_RELAY_INTRO, buf, isV4 ? 48 : 64, session->m_SessionKey, iv, session->m_MacKey);
m_Server.Send (buf, isV4 ? 48 : 64, session->m_RemoteEndpoint); m_Server.Send (buf, isV4 ? 48 : 64, session->m_RemoteEndpoint);
LogPrint (eLogDebug, "SSU: relay intro sent"); LogPrint (eLogDebug, "SSU: Relay intro sent");
} }
void SSUSession::ProcessRelayResponse (const uint8_t * buf, size_t len) void SSUSession::ProcessRelayResponse (const uint8_t * buf, size_t len)
{ {
LogPrint (eLogDebug, "SSU message: Relay response received"); LogPrint (eLogDebug, "SSU: Relay response received");
boost::asio::ip::address remoteIP; boost::asio::ip::address remoteIP;
uint16_t remotePort = 0; uint16_t remotePort = 0;
auto remoteSize = ExtractIPAddressAndPort (buf, len, remoteIP, remotePort); auto remoteSize = ExtractIPAddressAndPort (buf, len, remoteIP, remotePort);
@ -705,15 +705,15 @@ namespace transport
else else
LogPrint (eLogWarning, "SSU: Wrong external address ", ourIP.to_string ()); LogPrint (eLogWarning, "SSU: Wrong external address ", ourIP.to_string ());
if (ourIP.is_v4 ()) if (ourIP.is_v4 ())
{ {
if (ourPort != m_Server.GetPort ()) if (ourPort != m_Server.GetPort ())
{ {
if (i2p::context.GetStatus () == eRouterStatusTesting) if (i2p::context.GetStatus () == eRouterStatusTesting)
i2p::context.SetError (eRouterErrorSymmetricNAT); i2p::context.SetError (eRouterErrorSymmetricNAT);
} }
else if (i2p::context.GetStatus () == eRouterStatusError && i2p::context.GetError () == eRouterErrorSymmetricNAT) else if (i2p::context.GetStatus () == eRouterStatusError && i2p::context.GetError () == eRouterErrorSymmetricNAT)
i2p::context.SetStatus (eRouterStatusTesting); i2p::context.SetStatus (eRouterStatusTesting);
} }
uint32_t nonce = bufbe32toh (buf); uint32_t nonce = bufbe32toh (buf);
buf += 4; // nonce buf += 4; // nonce
auto it = m_RelayRequests.find (nonce); auto it = m_RelayRequests.find (nonce);
@ -727,7 +727,7 @@ namespace transport
// now we do // now we do
LogPrint (eLogInfo, "SSU: RelayReponse connecting to endpoint ", remoteEndpoint); LogPrint (eLogInfo, "SSU: RelayReponse connecting to endpoint ", remoteEndpoint);
if ((remoteIP.is_v4 () && i2p::context.GetStatus () == eRouterStatusFirewalled) || if ((remoteIP.is_v4 () && i2p::context.GetStatus () == eRouterStatusFirewalled) ||
(remoteIP.is_v6 () && i2p::context.GetStatusV6 () == eRouterStatusFirewalled)) (remoteIP.is_v6 () && i2p::context.GetStatusV6 () == eRouterStatusFirewalled))
m_Server.Send (buf, 0, remoteEndpoint); // send HolePunch m_Server.Send (buf, 0, remoteEndpoint); // send HolePunch
// we assume that HolePunch has been sent by this time and our SessionRequest will go through // we assume that HolePunch has been sent by this time and our SessionRequest will go through
m_Server.CreateDirectSession (it->second, remoteEndpoint, false); m_Server.CreateDirectSession (it->second, remoteEndpoint, false);
@ -803,7 +803,7 @@ namespace transport
htobe16buf (out + len + 16, (netid == I2PD_NET_ID) ? encryptedLen : encryptedLen ^ ((netid - 2) << 8)); htobe16buf (out + len + 16, (netid == I2PD_NET_ID) ? encryptedLen : encryptedLen ^ ((netid - 2) << 8));
i2p::crypto::HMACMD5Digest (encrypted, encryptedLen + 18, m_MacKey, header->mac); i2p::crypto::HMACMD5Digest (encrypted, encryptedLen + 18, m_MacKey, header->mac);
} }
void SSUSession::Decrypt (uint8_t * buf, size_t len, const i2p::crypto::AESKey& aesKey) void SSUSession::Decrypt (uint8_t * buf, size_t len, const i2p::crypto::AESKey& aesKey)
{ {
if (len < sizeof (SSUHeader)) if (len < sizeof (SSUHeader))
@ -872,7 +872,7 @@ namespace transport
if (!IsOutgoing ()) // incoming session if (!IsOutgoing ()) // incoming session
ScheduleConnectTimer (); ScheduleConnectTimer ();
else else
LogPrint (eLogError, "SSU: wait for connect for outgoing session"); LogPrint (eLogError, "SSU: Wait for connect for outgoing session");
} }
void SSUSession::ScheduleConnectTimer () void SSUSession::ScheduleConnectTimer ()
@ -888,7 +888,7 @@ namespace transport
if (!ecode) if (!ecode)
{ {
// timeout expired // timeout expired
LogPrint (eLogWarning, "SSU: session with ", m_RemoteEndpoint, " was not established after ", SSU_CONNECT_TIMEOUT, " seconds"); LogPrint (eLogWarning, "SSU: Session with ", m_RemoteEndpoint, " was not established after ", SSU_CONNECT_TIMEOUT, " seconds");
Failed (); Failed ();
} }
} }
@ -1023,29 +1023,29 @@ namespace transport
{ {
if (m_Server.GetPeerTestSession (nonce) == shared_from_this ()) // Alice-Bob if (m_Server.GetPeerTestSession (nonce) == shared_from_this ()) // Alice-Bob
{ {
LogPrint (eLogDebug, "SSU: peer test from Bob. We are Alice"); LogPrint (eLogDebug, "SSU: Peer test from Bob. We are Alice");
if (IsV6 ()) if (IsV6 ())
{ {
if (i2p::context.GetStatusV6 () == eRouterStatusTesting) if (i2p::context.GetStatusV6 () == eRouterStatusTesting)
{ {
i2p::context.SetStatusV6 (eRouterStatusFirewalled); i2p::context.SetStatusV6 (eRouterStatusFirewalled);
m_Server.RescheduleIntroducersUpdateTimerV6 (); m_Server.RescheduleIntroducersUpdateTimerV6 ();
} }
} }
else if (i2p::context.GetStatus () == eRouterStatusTesting) // still not OK else if (i2p::context.GetStatus () == eRouterStatusTesting) // still not OK
{ {
i2p::context.SetStatus (eRouterStatusFirewalled); i2p::context.SetStatus (eRouterStatusFirewalled);
m_Server.RescheduleIntroducersUpdateTimer (); m_Server.RescheduleIntroducersUpdateTimer ();
} }
} }
else else
{ {
LogPrint (eLogDebug, "SSU: first peer test from Charlie. We are Alice"); LogPrint (eLogDebug, "SSU: First peer test from Charlie. We are Alice");
if (m_State == eSessionStateEstablished) if (m_State == eSessionStateEstablished)
LogPrint (eLogWarning, "SSU: first peer test from Charlie through established session. We are Alice"); LogPrint (eLogWarning, "SSU: First peer test from Charlie through established session. We are Alice");
if (IsV6 ()) if (IsV6 ())
i2p::context.SetStatusV6 (eRouterStatusOK); i2p::context.SetStatusV6 (eRouterStatusOK);
else else
i2p::context.SetStatus (eRouterStatusOK); i2p::context.SetStatus (eRouterStatusOK);
m_Server.UpdatePeerTest (nonce, ePeerTestParticipantAlice2); m_Server.UpdatePeerTest (nonce, ePeerTestParticipantAlice2);
SendPeerTest (nonce, senderEndpoint.address (), senderEndpoint.port (), introKey, true, false); // to Charlie SendPeerTest (nonce, senderEndpoint.address (), senderEndpoint.port (), introKey, true, false); // to Charlie
@ -1055,14 +1055,14 @@ namespace transport
case ePeerTestParticipantAlice2: case ePeerTestParticipantAlice2:
{ {
if (m_Server.GetPeerTestSession (nonce) == shared_from_this ()) // Alice-Bob if (m_Server.GetPeerTestSession (nonce) == shared_from_this ()) // Alice-Bob
LogPrint (eLogDebug, "SSU: peer test from Bob. We are Alice"); LogPrint (eLogDebug, "SSU: Peer test from Bob. We are Alice");
else else
{ {
// peer test successive // peer test successive
LogPrint (eLogDebug, "SSU: second peer test from Charlie. We are Alice"); LogPrint (eLogDebug, "SSU: Second peer test from Charlie. We are Alice");
if (IsV6 ()) if (IsV6 ())
i2p::context.SetStatusV6 (eRouterStatusOK); i2p::context.SetStatusV6 (eRouterStatusOK);
else else
i2p::context.SetStatus (eRouterStatusOK); i2p::context.SetStatus (eRouterStatusOK);
m_Server.RemovePeerTest (nonce); m_Server.RemovePeerTest (nonce);
} }
@ -1070,19 +1070,19 @@ namespace transport
} }
case ePeerTestParticipantBob: case ePeerTestParticipantBob:
{ {
LogPrint (eLogDebug, "SSU: peer test from Charlie. We are Bob"); LogPrint (eLogDebug, "SSU: Peer test from Charlie. We are Bob");
auto session = m_Server.GetPeerTestSession (nonce); // session with Alice from PeerTest auto session = m_Server.GetPeerTestSession (nonce); // session with Alice from PeerTest
if (session && session->m_State == eSessionStateEstablished) if (session && session->m_State == eSessionStateEstablished)
{ {
const auto& ep = session->GetRemoteEndpoint (); // Alice's endpoint as known to Bob const auto& ep = session->GetRemoteEndpoint (); // Alice's endpoint as known to Bob
session->SendPeerTest (nonce, ep.address (), ep.port (), introKey, false, true); // send back to Alice session->SendPeerTest (nonce, ep.address (), ep.port (), introKey, false, true); // send back to Alice
} }
m_Server.RemovePeerTest (nonce); // nonce has been used m_Server.RemovePeerTest (nonce); // nonce has been used
break; break;
} }
case ePeerTestParticipantCharlie: case ePeerTestParticipantCharlie:
{ {
LogPrint (eLogDebug, "SSU: peer test from Alice. We are Charlie"); LogPrint (eLogDebug, "SSU: Peer test from Alice. We are Charlie");
SendPeerTest (nonce, senderEndpoint.address (), senderEndpoint.port (), introKey); // to Alice with her actual address SendPeerTest (nonce, senderEndpoint.address (), senderEndpoint.port (), introKey); // to Alice with her actual address
m_Server.RemovePeerTest (nonce); // nonce has been used m_Server.RemovePeerTest (nonce); // nonce has been used
break; break;
@ -1095,17 +1095,17 @@ namespace transport
// new test // new test
if (port) if (port)
{ {
LogPrint (eLogDebug, "SSU: peer test from Bob. We are Charlie"); LogPrint (eLogDebug, "SSU: Peer test from Bob. We are Charlie");
Send (PAYLOAD_TYPE_PEER_TEST, buf, len); // back to Bob Send (PAYLOAD_TYPE_PEER_TEST, buf, len); // back to Bob
if (!addr.is_unspecified () && !i2p::util::net::IsInReservedRange(addr)) if (!addr.is_unspecified () && !i2p::util::net::IsInReservedRange(addr))
{ {
m_Server.NewPeerTest (nonce, ePeerTestParticipantCharlie); m_Server.NewPeerTest (nonce, ePeerTestParticipantCharlie);
SendPeerTest (nonce, addr, port, introKey); // to Alice with her address received from Bob SendPeerTest (nonce, addr, port, introKey); // to Alice with her address received from Bob
} }
} }
else else
{ {
LogPrint (eLogDebug, "SSU: peer test from Alice. We are Bob"); LogPrint (eLogDebug, "SSU: Peer test from Alice. We are Bob");
auto session = senderEndpoint.address ().is_v4 () ? m_Server.GetRandomEstablishedV4Session (shared_from_this ()) : m_Server.GetRandomEstablishedV6Session (shared_from_this ()); // Charlie auto session = senderEndpoint.address ().is_v4 () ? m_Server.GetRandomEstablishedV4Session (shared_from_this ()) : m_Server.GetRandomEstablishedV6Session (shared_from_this ()); // Charlie
if (session) if (session)
{ {
@ -1115,7 +1115,7 @@ namespace transport
} }
} }
else else
LogPrint (eLogError, "SSU: unexpected peer test"); LogPrint (eLogError, "SSU: Unexpected peer test");
} }
} }
} }
@ -1188,7 +1188,7 @@ namespace transport
void SSUSession::SendPeerTest () void SSUSession::SendPeerTest ()
{ {
// we are Alice // we are Alice
LogPrint (eLogDebug, "SSU: sending peer test"); LogPrint (eLogDebug, "SSU: Initiating peer test");
auto address = IsV6 () ? i2p::context.GetRouterInfo ().GetSSUV6Address () : i2p::context.GetRouterInfo ().GetSSUAddress (true); auto address = IsV6 () ? i2p::context.GetRouterInfo ().GetSSUV6Address () : i2p::context.GetRouterInfo ().GetSSUAddress (true);
if (!address) if (!address)
{ {
@ -1233,9 +1233,9 @@ namespace transport
} }
catch (std::exception& ex) catch (std::exception& ex)
{ {
LogPrint (eLogWarning, "SSU: exception while sending session destoroyed: ", ex.what ()); LogPrint (eLogWarning, "SSU: Exception while sending session destroyed: ", ex.what ());
} }
LogPrint (eLogDebug, "SSU: session destroyed sent"); LogPrint (eLogDebug, "SSU: Session destroyed sent");
} }
} }
@ -1247,7 +1247,7 @@ namespace transport
if (paddingSize > 0) msgSize += (16 - paddingSize); if (paddingSize > 0) msgSize += (16 - paddingSize);
if (msgSize > SSU_MTU_V4) if (msgSize > SSU_MTU_V4)
{ {
LogPrint (eLogWarning, "SSU: payload size ", msgSize, " exceeds MTU"); LogPrint (eLogWarning, "SSU: Payload size ", msgSize, " exceeds MTU");
return; return;
} }
memcpy (buf + sizeof (SSUHeader), payload, len); memcpy (buf + sizeof (SSUHeader), payload, len);
@ -1268,12 +1268,12 @@ namespace transport
if (!len) return 0; if (!len) return 0;
uint8_t size = *buf; uint8_t size = *buf;
size_t s = 1 + size + 2; // size + address + port size_t s = 1 + size + 2; // size + address + port
if (len < s) if (len < s)
{ {
LogPrint (eLogWarning, "SSU: Address is too short ", len); LogPrint (eLogWarning, "SSU: Address is too short ", len);
port = 0; port = 0;
return len; return len;
} }
buf++; // size buf++; // size
if (size == 4) if (size == 4)
{ {
@ -1286,12 +1286,12 @@ namespace transport
boost::asio::ip::address_v6::bytes_type bytes; boost::asio::ip::address_v6::bytes_type bytes;
memcpy (bytes.data (), buf, 16); memcpy (bytes.data (), buf, 16);
ip = boost::asio::ip::address_v6 (bytes); ip = boost::asio::ip::address_v6 (bytes);
} }
else else
LogPrint (eLogWarning, "SSU: Address size ", size, " is not supported"); LogPrint (eLogWarning, "SSU: Address size ", size, " is not supported");
buf += size; buf += size;
port = bufbe16toh (buf); port = bufbe16toh (buf);
return s; return s;
} }
} }
} }

View file

@ -128,7 +128,7 @@ namespace transport
m_Queue.push (pair); m_Queue.push (pair);
} }
else else
LogPrint(eLogError, "Transports: return null DHKeys"); LogPrint(eLogError, "Transports: Return null DHKeys");
} }
Transports transports; Transports transports;
@ -192,10 +192,10 @@ namespace transport
i2p::context.SetStatus (eRouterStatusProxy); i2p::context.SetStatus (eRouterStatusProxy);
} }
else else
LogPrint(eLogError, "Transports: unsupported NTCP2 proxy URL ", ntcp2proxy); LogPrint(eLogError, "Transports: Unsupported NTCP2 proxy URL ", ntcp2proxy);
} }
else else
LogPrint(eLogError, "Transports: invalid NTCP2 proxy url ", ntcp2proxy); LogPrint(eLogError, "Transports: invalid NTCP2 proxy URL ", ntcp2proxy);
} }
else else
m_NTCP2Server = new NTCP2Server (); m_NTCP2Server = new NTCP2Server ();
@ -204,7 +204,7 @@ namespace transport
// create SSU server // create SSU server
int ssuPort = 0; int ssuPort = 0;
if (enableSSU) if (enableSSU)
{ {
auto& addresses = context.GetRouterInfo ().GetAddresses (); auto& addresses = context.GetRouterInfo ().GetAddresses ();
for (const auto& address: addresses) for (const auto& address: addresses)
{ {
@ -216,39 +216,39 @@ namespace transport
break; break;
} }
} }
} }
// bind to interfaces // bind to interfaces
bool ipv4; i2p::config::GetOption("ipv4", ipv4); bool ipv4; i2p::config::GetOption("ipv4", ipv4);
if (ipv4) if (ipv4)
{ {
std::string address; i2p::config::GetOption("address4", address); std::string address; i2p::config::GetOption("address4", address);
if (!address.empty ()) if (!address.empty ())
{ {
boost::system::error_code ec; boost::system::error_code ec;
auto addr = boost::asio::ip::address::from_string (address, ec); auto addr = boost::asio::ip::address::from_string (address, ec);
if (!ec) if (!ec)
{ {
if (m_NTCP2Server) m_NTCP2Server->SetLocalAddress (addr); if (m_NTCP2Server) m_NTCP2Server->SetLocalAddress (addr);
if (m_SSUServer) m_SSUServer->SetLocalAddress (addr); if (m_SSUServer) m_SSUServer->SetLocalAddress (addr);
} }
} }
} }
bool ipv6; i2p::config::GetOption("ipv6", ipv6); bool ipv6; i2p::config::GetOption("ipv6", ipv6);
if (ipv6) if (ipv6)
{ {
std::string address; i2p::config::GetOption("address6", address); std::string address; i2p::config::GetOption("address6", address);
if (!address.empty ()) if (!address.empty ())
{ {
boost::system::error_code ec; boost::system::error_code ec;
auto addr = boost::asio::ip::address::from_string (address, ec); auto addr = boost::asio::ip::address::from_string (address, ec);
if (!ec) if (!ec)
{ {
if (m_NTCP2Server) m_NTCP2Server->SetLocalAddress (addr); if (m_NTCP2Server) m_NTCP2Server->SetLocalAddress (addr);
if (m_SSUServer) m_SSUServer->SetLocalAddress (addr); if (m_SSUServer) m_SSUServer->SetLocalAddress (addr);
} }
} }
} }
bool ygg; i2p::config::GetOption("meshnets.yggdrasil", ygg); bool ygg; i2p::config::GetOption("meshnets.yggdrasil", ygg);
@ -256,12 +256,12 @@ namespace transport
{ {
std::string address; i2p::config::GetOption("meshnets.yggaddress", address); std::string address; i2p::config::GetOption("meshnets.yggaddress", address);
if (!address.empty ()) if (!address.empty ())
{ {
boost::system::error_code ec; boost::system::error_code ec;
auto addr = boost::asio::ip::address::from_string (address, ec); auto addr = boost::asio::ip::address::from_string (address, ec);
if (!ec && m_NTCP2Server && i2p::util::net::IsYggdrasilAddress (addr)) if (!ec && m_NTCP2Server && i2p::util::net::IsYggdrasilAddress (addr))
m_NTCP2Server->SetLocalAddress (addr); m_NTCP2Server->SetLocalAddress (addr);
} }
} }
// start servers // start servers
@ -269,11 +269,11 @@ namespace transport
if (m_SSUServer) if (m_SSUServer)
{ {
LogPrint (eLogInfo, "Transports: Start listening UDP port ", ssuPort); LogPrint (eLogInfo, "Transports: Start listening UDP port ", ssuPort);
try try
{ {
m_SSUServer->Start (); m_SSUServer->Start ();
} }
catch (std::exception& ex ) catch (std::exception& ex )
{ {
LogPrint(eLogError, "Transports: Failed to bind to UDP port", ssuPort); LogPrint(eLogError, "Transports: Failed to bind to UDP port", ssuPort);
m_SSUServer->Stop (); m_SSUServer->Stop ();
@ -281,8 +281,8 @@ namespace transport
m_SSUServer = nullptr; m_SSUServer = nullptr;
} }
if (m_SSUServer) DetectExternalIP (); if (m_SSUServer) DetectExternalIP ();
} }
m_PeerCleanupTimer->expires_from_now (boost::posix_time::seconds(5*SESSION_CREATION_TIMEOUT)); m_PeerCleanupTimer->expires_from_now (boost::posix_time::seconds(5*SESSION_CREATION_TIMEOUT));
m_PeerCleanupTimer->async_wait (std::bind (&Transports::HandlePeerCleanupTimer, this, std::placeholders::_1)); m_PeerCleanupTimer->async_wait (std::bind (&Transports::HandlePeerCleanupTimer, this, std::placeholders::_1));
@ -335,7 +335,7 @@ namespace transport
} }
catch (std::exception& ex) catch (std::exception& ex)
{ {
LogPrint (eLogError, "Transports: runtime exception: ", ex.what ()); LogPrint (eLogError, "Transports: Runtime exception: ", ex.what ());
} }
} }
} }
@ -426,7 +426,7 @@ namespace transport
} }
else else
{ {
LogPrint (eLogWarning, "Transports: delayed messages queue size to ", LogPrint (eLogWarning, "Transports: Delayed messages queue size to ",
ident.ToBase64 (), " exceeds ", MAX_NUM_DELAYED_MESSAGES); ident.ToBase64 (), " exceeds ", MAX_NUM_DELAYED_MESSAGES);
std::unique_lock<std::mutex> l(m_PeersMutex); std::unique_lock<std::mutex> l(m_PeersMutex);
m_Peers.erase (it); m_Peers.erase (it);
@ -448,23 +448,23 @@ namespace transport
if (!peer.numAttempts) // NTCP2 ipv6 if (!peer.numAttempts) // NTCP2 ipv6
{ {
if (context.GetRouterInfo ().IsNTCP2V6 () && peer.router->IsReachableBy (RouterInfo::eNTCP2V6)) if (context.GetRouterInfo ().IsNTCP2V6 () && peer.router->IsReachableBy (RouterInfo::eNTCP2V6))
{ {
address = peer.router->GetPublishedNTCP2V6Address (); address = peer.router->GetPublishedNTCP2V6Address ();
if (address && m_CheckReserved && i2p::util::net::IsInReservedRange(address->host)) if (address && m_CheckReserved && i2p::util::net::IsInReservedRange(address->host))
address = nullptr; address = nullptr;
} }
peer.numAttempts++; peer.numAttempts++;
} }
if (!address && peer.numAttempts == 1) // NTCP2 ipv4 if (!address && peer.numAttempts == 1) // NTCP2 ipv4
{ {
if (context.GetRouterInfo ().IsNTCP2 (true) && peer.router->IsReachableBy (RouterInfo::eNTCP2V4)) if (context.GetRouterInfo ().IsNTCP2 (true) && peer.router->IsReachableBy (RouterInfo::eNTCP2V4))
{ {
address = peer.router->GetPublishedNTCP2V4Address (); address = peer.router->GetPublishedNTCP2V4Address ();
if (address && m_CheckReserved && i2p::util::net::IsInReservedRange(address->host)) if (address && m_CheckReserved && i2p::util::net::IsInReservedRange(address->host))
address = nullptr; address = nullptr;
} }
peer.numAttempts++; peer.numAttempts++;
} }
if (address) if (address)
{ {
auto s = std::make_shared<NTCP2Session> (*m_NTCP2Server, peer.router, address); auto s = std::make_shared<NTCP2Session> (*m_NTCP2Server, peer.router, address);
@ -478,10 +478,10 @@ namespace transport
else else
peer.numAttempts = 2; // switch to SSU peer.numAttempts = 2; // switch to SSU
} }
if (peer.numAttempts == 2 || peer.numAttempts == 3) // SSU if (peer.numAttempts == 2 || peer.numAttempts == 3) // SSU
{ {
if (m_SSUServer) if (m_SSUServer)
{ {
std::shared_ptr<const RouterInfo::Address> address; std::shared_ptr<const RouterInfo::Address> address;
if (peer.numAttempts == 2) // SSU ipv6 if (peer.numAttempts == 2) // SSU ipv6
{ {
@ -507,7 +507,7 @@ namespace transport
{ {
if (m_SSUServer->CreateSession (peer.router, address)) if (m_SSUServer->CreateSession (peer.router, address))
return true; return true;
} }
} }
else else
peer.numAttempts += 2; // switch to Mesh peer.numAttempts += 2; // switch to Mesh
@ -523,10 +523,10 @@ namespace transport
auto s = std::make_shared<NTCP2Session> (*m_NTCP2Server, peer.router, address); auto s = std::make_shared<NTCP2Session> (*m_NTCP2Server, peer.router, address);
m_NTCP2Server->Connect (s); m_NTCP2Server->Connect (s);
return true; return true;
} }
} }
} }
LogPrint (eLogInfo, "Transports: No compatble NTCP2 or SSU addresses available"); LogPrint (eLogInfo, "Transports: No compatible NTCP2 or SSU addresses available");
i2p::data::netdb.SetUnreachable (ident, true); // we are here because all connection attempts failed i2p::data::netdb.SetUnreachable (ident, true); // we are here because all connection attempts failed
peer.Done (); peer.Done ();
std::unique_lock<std::mutex> l(m_PeersMutex); std::unique_lock<std::mutex> l(m_PeersMutex);
@ -591,7 +591,7 @@ namespace transport
bool statusChanged = false; bool statusChanged = false;
for (int i = 0; i < 5; i++) for (int i = 0; i < 5; i++)
{ {
auto router = i2p::data::netdb.GetRandomPeerTestRouter (true, excluded); // v4 auto router = i2p::data::netdb.GetRandomPeerTestRouter (true, excluded); // v4
if (router) if (router)
{ {
auto addr = router->GetSSUAddress (true); // ipv4 auto addr = router->GetSSUAddress (true); // ipv4
@ -602,8 +602,8 @@ namespace transport
statusChanged = true; statusChanged = true;
i2p::context.SetStatus (eRouterStatusTesting); // first time only i2p::context.SetStatus (eRouterStatusTesting); // first time only
} }
m_SSUServer->CreateSession (router, addr, true); // peer test v4 m_SSUServer->CreateSession (router, addr, true); // peer test v4
} }
excluded.insert (router->GetIdentHash ()); excluded.insert (router->GetIdentHash ());
} }
} }
@ -622,20 +622,20 @@ namespace transport
{ {
auto addr = router->GetSSUV6Address (); auto addr = router->GetSSUV6Address ();
if (addr && !i2p::util::net::IsInReservedRange(addr->host)) if (addr && !i2p::util::net::IsInReservedRange(addr->host))
{ {
if (!statusChanged) if (!statusChanged)
{ {
statusChanged = true; statusChanged = true;
i2p::context.SetStatusV6 (eRouterStatusTesting); // first time only i2p::context.SetStatusV6 (eRouterStatusTesting); // first time only
} }
m_SSUServer->CreateSession (router, addr, true); // peer test v6 m_SSUServer->CreateSession (router, addr, true); // peer test v6
} }
excluded.insert (router->GetIdentHash ()); excluded.insert (router->GetIdentHash ());
} }
} }
if (!statusChanged) if (!statusChanged)
LogPrint (eLogWarning, "Transports: Can't find routers for peer test ipv6"); LogPrint (eLogWarning, "Transports: Can't find routers for peer test ipv6");
} }
} }
std::shared_ptr<i2p::crypto::X25519Keys> Transports::GetNextX25519KeysPair () std::shared_ptr<i2p::crypto::X25519Keys> Transports::GetNextX25519KeysPair ()
@ -680,7 +680,7 @@ namespace transport
{ {
if(RoutesRestricted() && ! IsRestrictedPeer(ident)) { if(RoutesRestricted() && ! IsRestrictedPeer(ident)) {
// not trusted // not trusted
LogPrint(eLogWarning, "Transports: closing untrusted inbound connection from ", ident.ToBase64()); LogPrint(eLogWarning, "Transports: Closing untrusted inbound connection from ", ident.ToBase64());
session->Done(); session->Done();
return; return;
} }
@ -780,7 +780,7 @@ namespace transport
std::advance (it, rand () % m_Peers.size ()); std::advance (it, rand () % m_Peers.size ());
if (it == m_Peers.end () || it->second.router) return nullptr; // not connected if (it == m_Peers.end () || it->second.router) return nullptr; // not connected
ident = it->first; ident = it->first;
} }
return i2p::data::netdb.FindRouter (ident); return i2p::data::netdb.FindRouter (ident);
} }
void Transports::RestrictRoutesToFamilies(std::set<std::string> families) void Transports::RestrictRoutesToFamilies(std::set<std::string> families)

View file

@ -40,7 +40,7 @@ namespace tunnel
SHA256(fragment, TUNNEL_DATA_MSG_SIZE -(fragment - msg->GetPayload ()) + 16, hash); // payload + iv SHA256(fragment, TUNNEL_DATA_MSG_SIZE -(fragment - msg->GetPayload ()) + 16, hash); // payload + iv
if (memcmp (hash, decrypted, 4)) if (memcmp (hash, decrypted, 4))
{ {
LogPrint (eLogError, "TunnelMessage: checksum verification failed"); LogPrint (eLogError, "TunnelMessage: Checksum verification failed");
return; return;
} }
// process fragments // process fragments
@ -57,7 +57,7 @@ namespace tunnel
// first fragment // first fragment
if (m_CurrentMsgID) if (m_CurrentMsgID)
AddIncompleteCurrentMessage (); // we have got a new message while previous is not complete AddIncompleteCurrentMessage (); // we have got a new message while previous is not complete
m_CurrentMessage.deliveryType = (TunnelDeliveryType)((flag >> 5) & 0x03); m_CurrentMessage.deliveryType = (TunnelDeliveryType)((flag >> 5) & 0x03);
switch (m_CurrentMessage.deliveryType) switch (m_CurrentMessage.deliveryType)
{ {
@ -108,8 +108,8 @@ namespace tunnel
{ {
HandleFollowOnFragment (msgID, isLastFragment, fragmentNum, fragment, size); // another HandleFollowOnFragment (msgID, isLastFragment, fragmentNum, fragment, size); // another
m_CurrentMsgID = 0; m_CurrentMessage.data = nullptr; m_CurrentMsgID = 0; m_CurrentMessage.data = nullptr;
} }
} }
else else
{ {
// new message // new message
@ -118,7 +118,7 @@ namespace tunnel
// check message size // check message size
if (msg->len > msg->maxLen) if (msg->len > msg->maxLen)
{ {
LogPrint (eLogError, "TunnelMessage: fragment is too long ", (int)size); LogPrint (eLogError, "TunnelMessage: Fragment is too long ", (int)size);
m_CurrentMsgID = 0; m_CurrentMessage.data = nullptr; m_CurrentMsgID = 0; m_CurrentMessage.data = nullptr;
return; return;
} }
@ -131,35 +131,35 @@ namespace tunnel
} }
else else
m_CurrentMessage.data = msg; m_CurrentMessage.data = msg;
if (isLastFragment) if (isLastFragment)
{ {
// single message // single message
HandleNextMessage (m_CurrentMessage); HandleNextMessage (m_CurrentMessage);
m_CurrentMsgID = 0; m_CurrentMessage.data = nullptr; m_CurrentMsgID = 0; m_CurrentMessage.data = nullptr;
} }
else if (msgID) else if (msgID)
{ {
// first fragment of a new message // first fragment of a new message
m_CurrentMessage.nextFragmentNum = 1; m_CurrentMessage.nextFragmentNum = 1;
m_CurrentMessage.receiveTime = i2p::util::GetMillisecondsSinceEpoch (); m_CurrentMessage.receiveTime = i2p::util::GetMillisecondsSinceEpoch ();
HandleOutOfSequenceFragments (msgID, m_CurrentMessage); HandleOutOfSequenceFragments (msgID, m_CurrentMessage);
} }
else else
{ {
LogPrint (eLogError, "TunnelMessage: Message is fragmented, but msgID is not presented"); LogPrint (eLogError, "TunnelMessage: Message is fragmented, but msgID is not presented");
m_CurrentMsgID = 0; m_CurrentMessage.data = nullptr; m_CurrentMsgID = 0; m_CurrentMessage.data = nullptr;
} }
} }
fragment += size; fragment += size;
} }
} }
else else
LogPrint (eLogError, "TunnelMessage: zero not found"); LogPrint (eLogError, "TunnelMessage: Zero not found");
} }
void TunnelEndpoint::HandleFollowOnFragment (uint32_t msgID, bool isLastFragment, void TunnelEndpoint::HandleFollowOnFragment (uint32_t msgID, bool isLastFragment,
uint8_t fragmentNum, const uint8_t * fragment, size_t size) uint8_t fragmentNum, const uint8_t * fragment, size_t size)
{ {
auto it = m_IncompleteMessages.find (msgID); auto it = m_IncompleteMessages.find (msgID);
@ -213,15 +213,15 @@ namespace tunnel
msg.data = newMsg; msg.data = newMsg;
} }
if (msg.data->Concat (fragment, size) < size) // concatenate fragment if (msg.data->Concat (fragment, size) < size) // concatenate fragment
{ {
LogPrint (eLogError, "TunnelMessage: I2NP buffer overflow ", msg.data->maxLen); LogPrint (eLogError, "TunnelMessage: I2NP buffer overflow ", msg.data->maxLen);
return false; return false;
} }
} }
else else
return false; return false;
return true; return true;
} }
void TunnelEndpoint::HandleCurrenMessageFollowOnFragment (const uint8_t * fragment, size_t size, bool isLastFragment) void TunnelEndpoint::HandleCurrenMessageFollowOnFragment (const uint8_t * fragment, size_t size, bool isLastFragment)
{ {
@ -244,7 +244,7 @@ namespace tunnel
LogPrint (eLogError, "TunnelMessage: Fragment ", m_CurrentMessage.nextFragmentNum, " of message ", m_CurrentMsgID, " exceeds max I2NP message size, message dropped"); LogPrint (eLogError, "TunnelMessage: Fragment ", m_CurrentMessage.nextFragmentNum, " of message ", m_CurrentMsgID, " exceeds max I2NP message size, message dropped");
m_CurrentMsgID = 0; m_CurrentMessage.data = nullptr; m_CurrentMsgID = 0; m_CurrentMessage.data = nullptr;
} }
} }
void TunnelEndpoint::AddIncompleteCurrentMessage () void TunnelEndpoint::AddIncompleteCurrentMessage ()
{ {
@ -255,16 +255,16 @@ namespace tunnel
LogPrint (eLogError, "TunnelMessage: Incomplete message ", m_CurrentMsgID, " already exists"); LogPrint (eLogError, "TunnelMessage: Incomplete message ", m_CurrentMsgID, " already exists");
m_CurrentMessage.data = nullptr; m_CurrentMessage.data = nullptr;
m_CurrentMsgID = 0; m_CurrentMsgID = 0;
} }
} }
void TunnelEndpoint::AddOutOfSequenceFragment (uint32_t msgID, uint8_t fragmentNum, void TunnelEndpoint::AddOutOfSequenceFragment (uint32_t msgID, uint8_t fragmentNum,
bool isLastFragment, const uint8_t * fragment, size_t size) bool isLastFragment, const uint8_t * fragment, size_t size)
{ {
std::unique_ptr<Fragment> f(new Fragment (isLastFragment, i2p::util::GetMillisecondsSinceEpoch (), size)); std::unique_ptr<Fragment> f(new Fragment (isLastFragment, i2p::util::GetMillisecondsSinceEpoch (), size));
memcpy (f->data.data (), fragment, size); memcpy (f->data.data (), fragment, size);
if (!m_OutOfSequenceFragments.emplace ((uint64_t)msgID << 32 | fragmentNum, std::move (f)).second) if (!m_OutOfSequenceFragments.emplace ((uint64_t)msgID << 32 | fragmentNum, std::move (f)).second)
LogPrint (eLogInfo, "TunnelMessage: duplicate out-of-sequence fragment ", fragmentNum, " of message ", msgID); LogPrint (eLogInfo, "TunnelMessage: Duplicate out-of-sequence fragment ", fragmentNum, " of message ", msgID);
} }
void TunnelEndpoint::HandleOutOfSequenceFragments (uint32_t msgID, TunnelMessageBlockEx& msg) void TunnelEndpoint::HandleOutOfSequenceFragments (uint32_t msgID, TunnelMessageBlockEx& msg)
@ -276,10 +276,10 @@ namespace tunnel
HandleNextMessage (msg); HandleNextMessage (msg);
if (&msg == &m_CurrentMessage) if (&msg == &m_CurrentMessage)
{ {
m_CurrentMsgID = 0; m_CurrentMsgID = 0;
m_CurrentMessage.data = nullptr; m_CurrentMessage.data = nullptr;
} }
else else
m_IncompleteMessages.erase (msgID); m_IncompleteMessages.erase (msgID);
LogPrint (eLogDebug, "TunnelMessage: All fragments of message ", msgID, " found"); LogPrint (eLogDebug, "TunnelMessage: All fragments of message ", msgID, " found");
break; break;
@ -318,11 +318,11 @@ namespace tunnel
{ {
if (!m_IsInbound && msg.data->IsExpired ()) if (!m_IsInbound && msg.data->IsExpired ())
{ {
LogPrint (eLogInfo, "TunnelMessage: message expired"); LogPrint (eLogInfo, "TunnelMessage: Message expired");
return; return;
} }
uint8_t typeID = msg.data->GetTypeID (); uint8_t typeID = msg.data->GetTypeID ();
LogPrint (eLogDebug, "TunnelMessage: handle fragment of ", msg.data->GetLength (), " bytes, msg type ", (int)typeID); LogPrint (eLogDebug, "TunnelMessage: Handle fragment of ", msg.data->GetLength (), " bytes, msg type ", (int)typeID);
// catch RI or reply with new list of routers // catch RI or reply with new list of routers
if ((IsRouterInfoMsg (msg.data) || typeID == eI2NPDatabaseSearchReply) && if ((IsRouterInfoMsg (msg.data) || typeID == eI2NPDatabaseSearchReply) &&
!m_IsInbound && msg.deliveryType != eDeliveryTypeLocal) !m_IsInbound && msg.deliveryType != eDeliveryTypeLocal)

View file

@ -27,28 +27,28 @@ namespace tunnel
void Path::Add (std::shared_ptr<const i2p::data::RouterInfo> r) void Path::Add (std::shared_ptr<const i2p::data::RouterInfo> r)
{ {
if (r) if (r)
{ {
peers.push_back (r->GetRouterIdentity ()); peers.push_back (r->GetRouterIdentity ());
if (r->GetVersion () < i2p::data::NETDB_MIN_SHORT_TUNNEL_BUILD_VERSION || if (r->GetVersion () < i2p::data::NETDB_MIN_SHORT_TUNNEL_BUILD_VERSION ||
r->GetRouterIdentity ()->GetCryptoKeyType () != i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD) r->GetRouterIdentity ()->GetCryptoKeyType () != i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD)
isShort = false; isShort = false;
} }
} }
void Path::Reverse () void Path::Reverse ()
{ {
std::reverse (peers.begin (), peers.end ()); std::reverse (peers.begin (), peers.end ());
} }
TunnelPool::TunnelPool (int numInboundHops, int numOutboundHops, int numInboundTunnels, int numOutboundTunnels): TunnelPool::TunnelPool (int numInboundHops, int numOutboundHops, int numInboundTunnels, int numOutboundTunnels):
m_NumInboundHops (numInboundHops), m_NumOutboundHops (numOutboundHops), m_NumInboundHops (numInboundHops), m_NumOutboundHops (numOutboundHops),
m_NumInboundTunnels (numInboundTunnels), m_NumOutboundTunnels (numOutboundTunnels), m_NumInboundTunnels (numInboundTunnels), m_NumOutboundTunnels (numOutboundTunnels),
m_IsActive (true), m_CustomPeerSelector(nullptr) m_IsActive (true), m_CustomPeerSelector(nullptr)
{ {
if (m_NumInboundTunnels > TUNNEL_POOL_MAX_INBOUND_TUNNELS_QUANTITY) if (m_NumInboundTunnels > TUNNEL_POOL_MAX_INBOUND_TUNNELS_QUANTITY)
m_NumInboundTunnels = TUNNEL_POOL_MAX_INBOUND_TUNNELS_QUANTITY; m_NumInboundTunnels = TUNNEL_POOL_MAX_INBOUND_TUNNELS_QUANTITY;
if (m_NumOutboundTunnels > TUNNEL_POOL_MAX_OUTBOUND_TUNNELS_QUANTITY) if (m_NumOutboundTunnels > TUNNEL_POOL_MAX_OUTBOUND_TUNNELS_QUANTITY)
m_NumOutboundTunnels = TUNNEL_POOL_MAX_OUTBOUND_TUNNELS_QUANTITY; m_NumOutboundTunnels = TUNNEL_POOL_MAX_OUTBOUND_TUNNELS_QUANTITY;
m_NextManageTime = i2p::util::GetSecondsSinceEpoch () + rand () % TUNNEL_POOL_MANAGE_INTERVAL; m_NextManageTime = i2p::util::GetSecondsSinceEpoch () + rand () % TUNNEL_POOL_MANAGE_INTERVAL;
} }
@ -179,10 +179,10 @@ namespace tunnel
if (it->IsSlow () && !slowTunnel) if (it->IsSlow () && !slowTunnel)
slowTunnel = it; slowTunnel = it;
else else
{ {
v.push_back (it); v.push_back (it);
i++; i++;
} }
} }
} }
if (slowTunnel && (int)v.size () < (num/2+1)) if (slowTunnel && (int)v.size () < (num/2+1))
@ -213,8 +213,8 @@ namespace tunnel
{ {
if (it->IsEstablished () && it != excluded) if (it->IsEstablished () && it != excluded)
{ {
if (it->IsSlow () || (HasLatencyRequirement() && it->LatencyIsKnown() && if (it->IsSlow () || (HasLatencyRequirement() && it->LatencyIsKnown() &&
!it->LatencyFitsRange(m_MinLatency, m_MaxLatency))) !it->LatencyFitsRange(m_MinLatency, m_MaxLatency)))
{ {
i++; skipped = true; i++; skipped = true;
continue; continue;
@ -224,7 +224,7 @@ namespace tunnel
} }
if (i > ind && tunnel) break; if (i > ind && tunnel) break;
} }
if (!tunnel && skipped) if (!tunnel && skipped)
{ {
ind = rand () % (tunnels.size ()/2 + 1), i = 0; ind = rand () % (tunnels.size ()/2 + 1), i = 0;
for (const auto& it: tunnels) for (const auto& it: tunnels)
@ -281,12 +281,12 @@ namespace tunnel
if (!num && !m_OutboundTunnels.empty () && m_NumOutboundHops > 0) if (!num && !m_OutboundTunnels.empty () && m_NumOutboundHops > 0)
{ {
for (auto it: m_OutboundTunnels) for (auto it: m_OutboundTunnels)
{ {
CreatePairedInboundTunnel (it); CreatePairedInboundTunnel (it);
num++; num++;
if (num >= m_NumInboundTunnels) break; if (num >= m_NumInboundTunnels) break;
} }
} }
for (int i = num; i < m_NumInboundTunnels; i++) for (int i = num; i < m_NumInboundTunnels; i++)
CreateInboundTunnel (); CreateInboundTunnel ();
@ -304,7 +304,7 @@ namespace tunnel
for (auto& it: tests) for (auto& it: tests)
{ {
LogPrint (eLogWarning, "Tunnels: test of tunnel ", it.first, " failed"); LogPrint (eLogWarning, "Tunnels: Test of tunnel ", it.first, " failed");
// if test failed again with another tunnel we consider it failed // if test failed again with another tunnel we consider it failed
if (it.second.first) if (it.second.first)
{ {
@ -368,19 +368,19 @@ namespace tunnel
void TunnelPool::ManageTunnels (uint64_t ts) void TunnelPool::ManageTunnels (uint64_t ts)
{ {
if (ts > m_NextManageTime) if (ts > m_NextManageTime)
{ {
CreateTunnels (); CreateTunnels ();
TestTunnels (); TestTunnels ();
m_NextManageTime = ts + TUNNEL_POOL_MANAGE_INTERVAL + (rand () % TUNNEL_POOL_MANAGE_INTERVAL)/2; m_NextManageTime = ts + TUNNEL_POOL_MANAGE_INTERVAL + (rand () % TUNNEL_POOL_MANAGE_INTERVAL)/2;
} }
} }
void TunnelPool::ProcessGarlicMessage (std::shared_ptr<I2NPMessage> msg) void TunnelPool::ProcessGarlicMessage (std::shared_ptr<I2NPMessage> msg)
{ {
if (m_LocalDestination) if (m_LocalDestination)
m_LocalDestination->ProcessGarlicMessage (msg); m_LocalDestination->ProcessGarlicMessage (msg);
else else
LogPrint (eLogWarning, "Tunnels: local destination doesn't exist, dropped"); LogPrint (eLogWarning, "Tunnels: Local destination doesn't exist, dropped");
} }
void TunnelPool::ProcessDeliveryStatus (std::shared_ptr<I2NPMessage> msg) void TunnelPool::ProcessDeliveryStatus (std::shared_ptr<I2NPMessage> msg)
@ -405,23 +405,23 @@ namespace tunnel
if (found) if (found)
{ {
uint64_t dlt = i2p::util::GetMillisecondsSinceEpoch () - timestamp; uint64_t dlt = i2p::util::GetMillisecondsSinceEpoch () - timestamp;
LogPrint (eLogDebug, "Tunnels: test of ", msgID, " successful. ", dlt, " milliseconds"); LogPrint (eLogDebug, "Tunnels: Test of ", msgID, " successful. ", dlt, " milliseconds");
uint64_t latency = dlt / 2; uint64_t latency = dlt / 2;
// restore from test failed state if any // restore from test failed state if any
if (test.first) if (test.first)
{ {
if (test.first->GetState () == eTunnelStateTestFailed) if (test.first->GetState () == eTunnelStateTestFailed)
test.first->SetState (eTunnelStateEstablished); test.first->SetState (eTunnelStateEstablished);
// update latency // update latency
test.first->AddLatencySample(latency); test.first->AddLatencySample(latency);
} }
if (test.second) if (test.second)
{ {
if (test.second->GetState () == eTunnelStateTestFailed) if (test.second->GetState () == eTunnelStateTestFailed)
test.second->SetState (eTunnelStateEstablished); test.second->SetState (eTunnelStateEstablished);
// update latency // update latency
test.second->AddLatencySample(latency); test.second->AddLatencySample(latency);
} }
} }
else else
{ {
@ -435,8 +435,8 @@ namespace tunnel
bool TunnelPool::IsExploratory () const bool TunnelPool::IsExploratory () const
{ {
return i2p::tunnel::tunnels.GetExploratoryPool () == shared_from_this (); return i2p::tunnel::tunnels.GetExploratoryPool () == shared_from_this ();
} }
std::shared_ptr<const i2p::data::RouterInfo> TunnelPool::SelectNextHop (std::shared_ptr<const i2p::data::RouterInfo> prevHop, bool reverse) const std::shared_ptr<const i2p::data::RouterInfo> TunnelPool::SelectNextHop (std::shared_ptr<const i2p::data::RouterInfo> prevHop, bool reverse) const
{ {
auto hop = IsExploratory () ? i2p::data::netdb.GetRandomRouter (prevHop, reverse): auto hop = IsExploratory () ? i2p::data::netdb.GetRandomRouter (prevHop, reverse):
@ -464,7 +464,7 @@ namespace tunnel
(inbound && i2p::transport::transports.GetNumPeers () > 25)) (inbound && i2p::transport::transports.GetNumPeers () > 25))
{ {
auto r = i2p::transport::transports.GetRandomPeer (); auto r = i2p::transport::transports.GetRandomPeer ();
if (r && r->IsECIES () && !r->GetProfile ()->IsBad () && if (r && r->IsECIES () && !r->GetProfile ()->IsBad () &&
(numHops > 1 || (r->IsV4 () && (!inbound || r->IsReachable ())))) // first inbound must be reachable (numHops > 1 || (r->IsV4 () && (!inbound || r->IsReachable ())))) // first inbound must be reachable
{ {
prevHop = r; prevHop = r;
@ -477,11 +477,11 @@ namespace tunnel
{ {
auto hop = nextHop (prevHop, inbound); auto hop = nextHop (prevHop, inbound);
if (!hop && !i) // if no suitable peer found for first hop, try already connected if (!hop && !i) // if no suitable peer found for first hop, try already connected
{ {
LogPrint (eLogInfo, "Tunnels: Can't select first hop for a tunnel. Trying already connected"); LogPrint (eLogInfo, "Tunnels: No suitable peer found for first hop, trying existing connections");
hop = i2p::transport::transports.GetRandomPeer (); hop = i2p::transport::transports.GetRandomPeer ();
if (hop && !hop->IsECIES ()) hop = nullptr; if (hop && !hop->IsECIES ()) hop = nullptr;
} }
if (!hop) if (!hop)
{ {
LogPrint (eLogError, "Tunnels: Can't select next hop for ", prevHop->GetIdentHashBase64 ()); LogPrint (eLogError, "Tunnels: Can't select next hop for ", prevHop->GetIdentHashBase64 ());
@ -492,7 +492,7 @@ namespace tunnel
{ {
auto hop1 = nextHop (prevHop, true); auto hop1 = nextHop (prevHop, true);
if (hop1) hop = hop1; if (hop1) hop = hop1;
} }
prevHop = hop; prevHop = hop;
path.Add (hop); path.Add (hop);
} }
@ -519,21 +519,21 @@ namespace tunnel
{ {
int numHops = isInbound ? m_NumInboundHops : m_NumOutboundHops; int numHops = isInbound ? m_NumInboundHops : m_NumOutboundHops;
if (numHops > (int)m_ExplicitPeers->size ()) numHops = m_ExplicitPeers->size (); if (numHops > (int)m_ExplicitPeers->size ()) numHops = m_ExplicitPeers->size ();
if (!numHops) return false; if (!numHops) return false;
for (int i = 0; i < numHops; i++) for (int i = 0; i < numHops; i++)
{ {
auto& ident = (*m_ExplicitPeers)[i]; auto& ident = (*m_ExplicitPeers)[i];
auto r = i2p::data::netdb.FindRouter (ident); auto r = i2p::data::netdb.FindRouter (ident);
if (r) if (r)
{ {
if (r->IsECIES ()) if (r->IsECIES ())
path.Add (r); path.Add (r);
else else
{ {
LogPrint (eLogError, "Tunnels: ElGamal router ", ident.ToBase64 (), " is not supported"); LogPrint (eLogError, "Tunnels: ElGamal router ", ident.ToBase64 (), " is not supported");
return false; return false;
} }
} }
else else
{ {
LogPrint (eLogInfo, "Tunnels: Can't find router for ", ident.ToBase64 ()); LogPrint (eLogInfo, "Tunnels: Can't find router for ", ident.ToBase64 ());
@ -614,8 +614,8 @@ namespace tunnel
// TODO: implement it better // TODO: implement it better
tunnel = tunnels.CreateOutboundTunnel (config, inboundTunnel->GetTunnelPool ()); tunnel = tunnels.CreateOutboundTunnel (config, inboundTunnel->GetTunnelPool ());
tunnel->SetTunnelPool (shared_from_this ()); tunnel->SetTunnelPool (shared_from_this ());
} }
else else
tunnel = tunnels.CreateOutboundTunnel (config, shared_from_this ()); tunnel = tunnels.CreateOutboundTunnel (config, shared_from_this ());
if (tunnel && tunnel->IsEstablished ()) // zero hops if (tunnel && tunnel->IsEstablished ()) // zero hops
TunnelCreated (tunnel); TunnelCreated (tunnel);
@ -660,7 +660,7 @@ namespace tunnel
{ {
LogPrint (eLogDebug, "Tunnels: Creating paired inbound tunnel..."); LogPrint (eLogDebug, "Tunnels: Creating paired inbound tunnel...");
auto tunnel = tunnels.CreateInboundTunnel ( auto tunnel = tunnels.CreateInboundTunnel (
m_NumOutboundHops > 0 ? std::make_shared<TunnelConfig>(outboundTunnel->GetInvertedPeers ()) : nullptr, m_NumOutboundHops > 0 ? std::make_shared<TunnelConfig>(outboundTunnel->GetInvertedPeers ()) : nullptr,
shared_from_this (), outboundTunnel); shared_from_this (), outboundTunnel);
if (tunnel->IsEstablished ()) // zero hops if (tunnel->IsEstablished ()) // zero hops
TunnelCreated (tunnel); TunnelCreated (tunnel);

View file

@ -60,22 +60,22 @@ namespace api
else else
i2p::log::Logger().SendTo (i2p::fs::DataDirPath (i2p::fs::GetAppName () + ".log")); i2p::log::Logger().SendTo (i2p::fs::DataDirPath (i2p::fs::GetAppName () + ".log"));
i2p::log::Logger().Start (); i2p::log::Logger().Start ();
LogPrint(eLogInfo, "API: starting NetDB"); LogPrint(eLogInfo, "API: Starting NetDB");
i2p::data::netdb.Start(); i2p::data::netdb.Start();
LogPrint(eLogInfo, "API: starting Transports"); LogPrint(eLogInfo, "API: Starting Transports");
i2p::transport::transports.Start(); i2p::transport::transports.Start();
LogPrint(eLogInfo, "API: starting Tunnels"); LogPrint(eLogInfo, "API: Starting Tunnels");
i2p::tunnel::tunnels.Start(); i2p::tunnel::tunnels.Start();
} }
void StopI2P () void StopI2P ()
{ {
LogPrint(eLogInfo, "API: shutting down"); LogPrint(eLogInfo, "API: Shutting down");
LogPrint(eLogInfo, "API: stopping Tunnels"); LogPrint(eLogInfo, "API: Stopping Tunnels");
i2p::tunnel::tunnels.Stop(); i2p::tunnel::tunnels.Stop();
LogPrint(eLogInfo, "API: stopping Transports"); LogPrint(eLogInfo, "API: Stopping Transports");
i2p::transport::transports.Stop(); i2p::transport::transports.Stop();
LogPrint(eLogInfo, "API: stopping NetDB"); LogPrint(eLogInfo, "API: Stopping NetDB");
i2p::data::netdb.Stop(); i2p::data::netdb.Stop();
i2p::log::Logger().Stop (); i2p::log::Logger().Stop ();
} }

View file

@ -377,7 +377,7 @@ namespace net
const boost::asio::ip::address GetInterfaceAddress (const std::string & ifname, bool ipv6) const boost::asio::ip::address GetInterfaceAddress (const std::string & ifname, bool ipv6)
{ {
#ifdef _WIN32 #ifdef _WIN32
LogPrint(eLogError, "NetIface: cannot get address by interface name, not implemented on WIN32"); LogPrint(eLogError, "NetIface: Cannot get address by interface name, not implemented on WIN32");
if(ipv6) if(ipv6)
return boost::asio::ip::address::from_string("::1"); return boost::asio::ip::address::from_string("::1");
else else
@ -413,10 +413,10 @@ namespace net
if(ipv6) if(ipv6)
{ {
fallback = "::1"; fallback = "::1";
LogPrint(eLogWarning, "NetIface: cannot find ipv6 address for interface ", ifname); LogPrint(eLogWarning, "NetIface: Can't find ipv6 address for interface ", ifname);
} else { } else {
fallback = "127.0.0.1"; fallback = "127.0.0.1";
LogPrint(eLogWarning, "NetIface: cannot find ipv4 address for interface ", ifname); LogPrint(eLogWarning, "NetIface: Can't find ipv4 address for interface ", ifname);
} }
return boost::asio::ip::address::from_string(fallback); return boost::asio::ip::address::from_string(fallback);
#endif #endif
@ -425,14 +425,14 @@ namespace net
static bool IsYggdrasilAddress (const uint8_t addr[16]) static bool IsYggdrasilAddress (const uint8_t addr[16])
{ {
return addr[0] == 0x02 || addr[0] == 0x03; return addr[0] == 0x02 || addr[0] == 0x03;
} }
bool IsYggdrasilAddress (const boost::asio::ip::address& addr) bool IsYggdrasilAddress (const boost::asio::ip::address& addr)
{ {
if (!addr.is_v6 ()) return false; if (!addr.is_v6 ()) return false;
return IsYggdrasilAddress (addr.to_v6 ().to_bytes ().data ()); return IsYggdrasilAddress (addr.to_v6 ().to_bytes ().data ());
} }
boost::asio::ip::address_v6 GetYggdrasilAddress () boost::asio::ip::address_v6 GetYggdrasilAddress ()
{ {
#if defined(_WIN32) #if defined(_WIN32)
@ -479,7 +479,7 @@ namespace net
} }
pCurrAddresses = pCurrAddresses->Next; pCurrAddresses = pCurrAddresses->Next;
} }
LogPrint(eLogWarning, "NetIface: interface with yggdrasil network address not found"); LogPrint(eLogWarning, "NetIface: Interface with yggdrasil network address not found");
FREE(pAddresses); FREE(pAddresses);
return boost::asio::ip::address_v6 (); return boost::asio::ip::address_v6 ();
#else #else
@ -504,7 +504,7 @@ namespace net
cur = cur->ifa_next; cur = cur->ifa_next;
} }
} }
LogPrint(eLogWarning, "NetIface: interface with yggdrasil network address not found"); LogPrint(eLogWarning, "NetIface: Interface with yggdrasil network address not found");
if(addrs) freeifaddrs(addrs); if(addrs) freeifaddrs(addrs);
return boost::asio::ip::address_v6 (); return boost::asio::ip::address_v6 ();
#endif #endif
@ -517,11 +517,11 @@ namespace net
GetMTUWindows(addr, 0); GetMTUWindows(addr, 0);
#else #else
GetMTUUnix(addr, 0); GetMTUUnix(addr, 0);
#endif #endif
return mtu > 0; return mtu > 0;
} }
bool IsInReservedRange (const boost::asio::ip::address& host) bool IsInReservedRange (const boost::asio::ip::address& host)
{ {
// https://en.wikipedia.org/wiki/Reserved_IP_addresses // https://en.wikipedia.org/wiki/Reserved_IP_addresses
if (host.is_unspecified ()) return false; if (host.is_unspecified ()) return false;