From 22a16da09ed649b2476271247382a1ac87810492 Mon Sep 17 00:00:00 2001 From: orignal Date: Wed, 20 Jul 2016 21:44:17 -0400 Subject: [PATCH 01/10] fixed android build --- Reseed.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/Reseed.cpp b/Reseed.cpp index 66609414..236531f9 100644 --- a/Reseed.cpp +++ b/Reseed.cpp @@ -15,6 +15,7 @@ #include "Identity.h" #include "NetDb.h" #include "HTTP.h" +#include "util.h" namespace i2p { From abcf030181acac231be8558423e2ed0b83b70649 Mon Sep 17 00:00:00 2001 From: orignal Date: Thu, 21 Jul 2016 14:02:13 -0400 Subject: [PATCH 02/10] more BOB error messages --- BOB.cpp | 60 ++++++++++++++++++++++++++++++++++++++++++++------------- BOB.h | 2 +- 2 files changed, 48 insertions(+), 14 deletions(-) diff --git a/BOB.cpp b/BOB.cpp index f983c67a..ae6e12ce 100644 --- a/BOB.cpp +++ b/BOB.cpp @@ -203,7 +203,7 @@ namespace client BOBCommandSession::BOBCommandSession (BOBCommandChannel& owner): m_Owner (owner), m_Socket (m_Owner.GetService ()), - m_ReceiveBufferOffset (0), m_IsOpen (true), m_IsQuiet (false), + m_ReceiveBufferOffset (0), m_IsOpen (true), m_IsQuiet (false), m_IsActive (false), m_InPort (0), m_OutPort (0), m_CurrentDestination (nullptr) { } @@ -354,6 +354,11 @@ namespace client void BOBCommandSession::StartCommandHandler (const char * operand, size_t len) { LogPrint (eLogDebug, "BOB: start ", m_Nickname); + if (m_IsActive) + { + SendReplyError ("tunnel is active"); + return; + } if (!m_CurrentDestination) { m_CurrentDestination = new BOBDestination (i2p::client::context.CreateNewLocalDestination (m_Keys, true, &m_Options)); @@ -364,19 +369,27 @@ namespace client if (m_OutPort && !m_Address.empty ()) m_CurrentDestination->CreateOutboundTunnel (m_Address, m_OutPort, m_IsQuiet); m_CurrentDestination->Start (); - SendReplyOK ("tunnel starting"); + SendReplyOK ("Tunnel starting"); + m_IsActive = true; } void BOBCommandSession::StopCommandHandler (const char * operand, size_t len) { + LogPrint (eLogDebug, "BOB: stop ", m_Nickname); + if (!m_IsActive) + { + SendReplyError ("tunnel is inactive"); + return; + } auto dest = m_Owner.FindDestination (m_Nickname); if (dest) { dest->StopTunnels (); - SendReplyOK ("tunnel stopping"); + SendReplyOK ("Tunnel stopping"); } else SendReplyError ("tunnel not found"); + m_IsActive = false; } void BOBCommandSession::SetNickCommandHandler (const char * operand, size_t len) @@ -384,7 +397,7 @@ namespace client LogPrint (eLogDebug, "BOB: setnick ", operand); m_Nickname = operand; std::string msg ("Nickname set to "); - msg += operand; + msg += m_Nickname; SendReplyOK (msg.c_str ()); } @@ -397,11 +410,11 @@ namespace client m_Keys = m_CurrentDestination->GetKeys (); m_Nickname = operand; std::string msg ("Nickname set to "); - msg += operand; + msg += m_Nickname; SendReplyOK (msg.c_str ()); } else - SendReplyError ("tunnel not found"); + SendReplyError ("no nickname has been set"); } void BOBCommandSession::NewkeysCommandHandler (const char * operand, size_t len) @@ -441,7 +454,10 @@ namespace client { LogPrint (eLogDebug, "BOB: outport ", operand); m_OutPort = boost::lexical_cast(operand); - SendReplyOK ("outbound port set"); + if (m_OutPort >= 0) + SendReplyOK ("outbound port set"); + else + SendReplyError ("port out of range"); } void BOBCommandSession::InhostCommandHandler (const char * operand, size_t len) @@ -455,14 +471,27 @@ namespace client { LogPrint (eLogDebug, "BOB: inport ", operand); m_InPort = boost::lexical_cast(operand); - SendReplyOK ("inbound port set"); + if (m_InPort >= 0) + SendReplyOK ("inbound port set"); + else + SendReplyError ("port out of range"); } void BOBCommandSession::QuietCommandHandler (const char * operand, size_t len) { LogPrint (eLogDebug, "BOB: quiet"); - m_IsQuiet = true; - SendReplyOK ("quiet"); + if (m_Nickname.length () > 0) + { + if (!m_IsActive) + { + m_IsQuiet = true; + SendReplyOK ("Quiet set"); + } + else + SendReplyError ("tunnel is active"); + } + else + SendReplyError ("no nickname has been set"); } void BOBCommandSession::LookupCommandHandler (const char * operand, size_t len) @@ -497,6 +526,7 @@ namespace client { LogPrint (eLogDebug, "BOB: clear"); m_Owner.DeleteDestination (m_Nickname); + m_Nickname = ""; SendReplyOK ("cleared"); } @@ -515,10 +545,14 @@ namespace client const char * value = strchr (operand, '='); if (value) { + std::string msg ("option "); *(const_cast(value)) = 0; m_Options[operand] = value + 1; + msg += operand; *(const_cast(value)) = '='; - SendReplyOK ("option"); + msg += " set to "; + msg += value; + SendReplyOK (msg.c_str ()); } else SendReplyError ("malformed"); @@ -527,10 +561,10 @@ namespace client void BOBCommandSession::StatusCommandHandler (const char * operand, size_t len) { LogPrint (eLogDebug, "BOB: status ", operand); - if (operand == m_Nickname) + if (m_Nickname == operand) { std::stringstream s; - s << "DATA"; s << " NICKNAME:"; s << operand; + s << "DATA"; s << " NICKNAME:"; s << m_Nickname; if (m_CurrentDestination->GetLocalDestination ()->IsReady ()) s << " STARTING:false RUNNING:true STOPPING:false"; else diff --git a/BOB.h b/BOB.h index d2118c5c..104073bd 100644 --- a/BOB.h +++ b/BOB.h @@ -188,7 +188,7 @@ namespace client boost::asio::ip::tcp::socket m_Socket; char m_ReceiveBuffer[BOB_COMMAND_BUFFER_SIZE + 1], m_SendBuffer[BOB_COMMAND_BUFFER_SIZE + 1]; size_t m_ReceiveBufferOffset; - bool m_IsOpen, m_IsQuiet; + bool m_IsOpen, m_IsQuiet, m_IsActive; std::string m_Nickname, m_Address; int m_InPort, m_OutPort; i2p::data::PrivateKeys m_Keys; From 3b9b827ebfadd14ee50856b2ee804600e2a0fb70 Mon Sep 17 00:00:00 2001 From: orignal Date: Thu, 21 Jul 2016 20:42:40 -0400 Subject: [PATCH 03/10] getnick doean't return error if was set before --- BOB.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/BOB.cpp b/BOB.cpp index ae6e12ce..aa11c7b8 100644 --- a/BOB.cpp +++ b/BOB.cpp @@ -409,10 +409,13 @@ namespace client { m_Keys = m_CurrentDestination->GetKeys (); m_Nickname = operand; + } + if (m_Nickname == operand) + { std::string msg ("Nickname set to "); msg += m_Nickname; SendReplyOK (msg.c_str ()); - } + } else SendReplyError ("no nickname has been set"); } From a4112ebed26a2bd1879c35c3c8252ffb16017fb9 Mon Sep 17 00:00:00 2001 From: orignal Date: Fri, 22 Jul 2016 10:16:57 -0400 Subject: [PATCH 04/10] add both v4 and v6 addresses --- RouterContext.cpp | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/RouterContext.cpp b/RouterContext.cpp index 737a92fc..0140c298 100644 --- a/RouterContext.cpp +++ b/RouterContext.cpp @@ -53,16 +53,25 @@ namespace i2p bool ipv6; i2p::config::GetOption("ipv6", ipv6); bool nat; i2p::config::GetOption("nat", nat); std::string ifname; i2p::config::GetOption("ifname", ifname); - std::string host = ipv6 ? "::" : "127.0.0.1"; - if (nat) { + if (ipv4) + { + std::string host = "127.0.0.1"; if (!i2p::config::IsDefault("host")) i2p::config::GetOption("host", host); - } else if (!ifname.empty()) { - /* bind to interface, we have no NAT so set external address too */ - host = i2p::util::net::GetInterfaceAddress(ifname, ipv6).to_string(); + else if (!nat && !ifname.empty()) + /* bind to interface, we have no NAT so set external address too */ + host = i2p::util::net::GetInterfaceAddress(ifname, false).to_string(); // v4 + routerInfo.AddSSUAddress (host.c_str(), port, routerInfo.GetIdentHash ()); + routerInfo.AddNTCPAddress (host.c_str(), port); + } + if (ipv6) + { + std::string host = "::"; + if (!ifname.empty()) + host = i2p::util::net::GetInterfaceAddress(ifname, true).to_string(); // v6 + routerInfo.AddSSUAddress (host.c_str(), port, routerInfo.GetIdentHash ()); + routerInfo.AddNTCPAddress (host.c_str(), port); } - routerInfo.AddSSUAddress (host.c_str(), port, routerInfo.GetIdentHash ()); - routerInfo.AddNTCPAddress (host.c_str(), port); routerInfo.SetCaps (i2p::data::RouterInfo::eReachable | i2p::data::RouterInfo::eSSUTesting | i2p::data::RouterInfo::eSSUIntroducer); // LR, BC routerInfo.SetProperty ("netId", std::to_string (I2PD_NET_ID)); From 6a1049bfb7d26fe58c32a5f1e12b3c58b67cc85e Mon Sep 17 00:00:00 2001 From: orignal Date: Fri, 22 Jul 2016 10:34:56 -0400 Subject: [PATCH 05/10] override address if v6 only --- RouterContext.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/RouterContext.cpp b/RouterContext.cpp index 0140c298..f2c2bc48 100644 --- a/RouterContext.cpp +++ b/RouterContext.cpp @@ -67,7 +67,9 @@ namespace i2p if (ipv6) { std::string host = "::"; - if (!ifname.empty()) + if (!i2p::config::IsDefault("host") && !ipv4) // override if v6 only + i2p::config::GetOption("host", host); + else if (!ifname.empty()) host = i2p::util::net::GetInterfaceAddress(ifname, true).to_string(); // v6 routerInfo.AddSSUAddress (host.c_str(), port, routerInfo.GetIdentHash ()); routerInfo.AddNTCPAddress (host.c_str(), port); From ba078f3ff571deacaa458f9ff54f1de711f0341f Mon Sep 17 00:00:00 2001 From: orignal Date: Fri, 22 Jul 2016 12:50:03 -0400 Subject: [PATCH 06/10] support peer test for ipv6 --- SSUSession.cpp | 55 +++++++++++++++++++++++++++++++++----------------- SSUSession.h | 2 +- 2 files changed, 38 insertions(+), 19 deletions(-) diff --git a/SSUSession.cpp b/SSUSession.cpp index 9c90ff88..ef8fc467 100644 --- a/SSUSession.cpp +++ b/SSUSession.cpp @@ -930,10 +930,10 @@ namespace transport { uint32_t nonce = bufbe32toh (buf); // 4 bytes uint8_t size = buf[4]; // 1 byte - uint32_t address = (size == 4) ? buf32toh(buf + 5) : 0; // big endian, size bytes + const uint8_t * address = buf + 5; // big endian, size bytes uint16_t port = buf16toh(buf + size + 5); // big endian, 2 bytes const uint8_t * introKey = buf + size + 7; - if (port && !address) + if (port && (size != 4) && (size != 16)) { LogPrint (eLogWarning, "SSU: Address of ", size, " bytes not supported"); return; @@ -954,8 +954,7 @@ namespace transport LogPrint (eLogDebug, "SSU: first peer test from Charlie. We are Alice"); i2p::context.SetStatus (eRouterStatusOK); m_Server.UpdatePeerTest (nonce, ePeerTestParticipantAlice2); - SendPeerTest (nonce, senderEndpoint.address ().to_v4 ().to_ulong (), - senderEndpoint.port (), introKey, true, false); // to Charlie + SendPeerTest (nonce, senderEndpoint.address (), senderEndpoint.port (), introKey, true, false); // to Charlie } break; } @@ -984,8 +983,7 @@ namespace transport case ePeerTestParticipantCharlie: { LogPrint (eLogDebug, "SSU: peer test from Alice. We are Charlie"); - SendPeerTest (nonce, senderEndpoint.address ().to_v4 ().to_ulong (), - 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 break; } @@ -1000,7 +998,20 @@ namespace transport LogPrint (eLogDebug, "SSU: peer test from Bob. We are Charlie"); m_Server.NewPeerTest (nonce, ePeerTestParticipantCharlie); Send (PAYLOAD_TYPE_PEER_TEST, buf, len); // back to Bob - SendPeerTest (nonce, be32toh (address), be16toh (port), introKey); // to Alice with her address received from Bob + boost::asio::ip::address addr; // Alice's address + if (size == 4) // v4 + { + boost::asio::ip::address_v4::bytes_type bytes; + memcpy (bytes.data (), address, 4); + addr = boost::asio::ip::address_v4 (bytes); + } + else // v6 + { + boost::asio::ip::address_v6::bytes_type bytes; + memcpy (bytes.data (), address, 6); + addr = boost::asio::ip::address_v6 (bytes); + } + SendPeerTest (nonce, addr, be16toh (port), introKey); // to Alice with her address received from Bob } else { @@ -1009,8 +1020,7 @@ namespace transport if (session) { m_Server.NewPeerTest (nonce, ePeerTestParticipantBob, shared_from_this ()); - session->SendPeerTest (nonce, senderEndpoint.address ().to_v4 ().to_ulong (), - senderEndpoint.port (), introKey, false); // to Charlie with Alice's actual address + session->SendPeerTest (nonce, senderEndpoint.address (), senderEndpoint.port (), introKey, false); // to Charlie with Alice's actual address } } } @@ -1020,7 +1030,7 @@ namespace transport } } - void SSUSession::SendPeerTest (uint32_t nonce, uint32_t address, uint16_t port, + void SSUSession::SendPeerTest (uint32_t nonce, const boost::asio::ip::address& address, uint16_t port, const uint8_t * introKey, bool toAddress, bool sendAddress) // toAddress is true for Alice<->Chalie communications only // sendAddress is false if message comes from Alice @@ -1031,12 +1041,21 @@ namespace transport htobe32buf (payload, nonce); payload += 4; // nonce // address and port - if (sendAddress && address) - { - *payload = 4; - payload++; // size - htobe32buf (payload, address); - payload += 4; // address + if (sendAddress) + { + if (address.is_v4 ()) + { + *payload = 4; + memcpy (payload + 1, address.to_v4 ().to_bytes ().data (), 4); // our IP V4 + } + else if (address.is_v6 ()) + { + *payload = 6; + memcpy (payload + 1, address.to_v6 ().to_bytes ().data (), 16); // our IP V6 + } + else + *payload = 0; + payload += (payload[0] + 1); } else { @@ -1064,7 +1083,7 @@ namespace transport { // encrypt message with specified intro key FillHeaderAndEncrypt (PAYLOAD_TYPE_PEER_TEST, buf, 80, introKey, iv, introKey); - boost::asio::ip::udp::endpoint e (boost::asio::ip::address_v4 (address), port); + boost::asio::ip::udp::endpoint e (address, port); m_Server.Send (buf, 80, e); } else @@ -1090,7 +1109,7 @@ namespace transport if (!nonce) nonce = 1; m_IsPeerTest = false; m_Server.NewPeerTest (nonce, ePeerTestParticipantAlice1); - SendPeerTest (nonce, 0, 0, address->key, false, false); // address and port always zero for Alice + SendPeerTest (nonce, boost::asio::ip::address(), 0, address->key, false, false); // address and port always zero for Alice } void SSUSession::SendKeepAlive () diff --git a/SSUSession.h b/SSUSession.h index cfe24f6c..c2f24ce3 100644 --- a/SSUSession.h +++ b/SSUSession.h @@ -118,7 +118,7 @@ namespace transport void ScheduleConnectTimer (); void HandleConnectTimer (const boost::system::error_code& ecode); void ProcessPeerTest (const uint8_t * buf, size_t len, const boost::asio::ip::udp::endpoint& senderEndpoint); - void SendPeerTest (uint32_t nonce, uint32_t address, uint16_t port, const uint8_t * introKey, bool toAddress = true, bool sendAddress = true); + void SendPeerTest (uint32_t nonce, const boost::asio::ip::address& address, uint16_t port, const uint8_t * introKey, bool toAddress = true, bool sendAddress = true); void ProcessData (uint8_t * buf, size_t len); void SendSesionDestroyed (); void Send (uint8_t type, const uint8_t * payload, size_t len); // with session key From 3d1a7f173c1dc136aa143debff41a909682d24ac Mon Sep 17 00:00:00 2001 From: orignal Date: Fri, 22 Jul 2016 13:08:41 -0400 Subject: [PATCH 07/10] select Charlie based on Alice's address type --- SSU.cpp | 27 +++++++++++++++++++++++++-- SSU.h | 5 ++++- SSUSession.cpp | 2 +- 3 files changed, 30 insertions(+), 4 deletions(-) diff --git a/SSU.cpp b/SSU.cpp index 4693a4f6..f4277a5a 100644 --- a/SSU.cpp +++ b/SSU.cpp @@ -459,8 +459,31 @@ namespace transport return GetRandomV4Session ( [excluded](std::shared_ptr session)->bool { - return session->GetState () == eSessionStateEstablished && !session->IsV6 () && - session != excluded; + return session->GetState () == eSessionStateEstablished && session != excluded; + } + ); + } + + template + std::shared_ptr SSUServer::GetRandomV6Session (Filter filter) // v6 only + { + std::vector > filteredSessions; + for (auto s :m_SessionsV6) + if (filter (s.second)) filteredSessions.push_back (s.second); + if (filteredSessions.size () > 0) + { + auto ind = rand () % filteredSessions.size (); + return filteredSessions[ind]; + } + return nullptr; + } + + std::shared_ptr SSUServer::GetRandomEstablishedV6Session (std::shared_ptr excluded) // v6 only + { + return GetRandomV6Session ( + [excluded](std::shared_ptr session)->bool + { + return session->GetState () == eSessionStateEstablished && session != excluded; } ); } diff --git a/SSU.h b/SSU.h index 0fdf0621..d779c025 100644 --- a/SSU.h +++ b/SSU.h @@ -48,6 +48,7 @@ namespace transport std::shared_ptr FindSession (std::shared_ptr router) const; std::shared_ptr FindSession (const boost::asio::ip::udp::endpoint& e) const; std::shared_ptr GetRandomEstablishedV4Session (std::shared_ptr excluded); + std::shared_ptr GetRandomEstablishedV6Session (std::shared_ptr excluded); void DeleteSession (std::shared_ptr session); void DeleteAllSessions (); @@ -79,7 +80,9 @@ namespace transport void CreateSessionThroughIntroducer (std::shared_ptr router, bool peerTest = false); template std::shared_ptr GetRandomV4Session (Filter filter); - + template + std::shared_ptr GetRandomV6Session (Filter filter); + std::set FindIntroducers (int maxNumIntroducers); void ScheduleIntroducersUpdateTimer (); void HandleIntroducersUpdateTimer (const boost::system::error_code& ecode); diff --git a/SSUSession.cpp b/SSUSession.cpp index ef8fc467..3aae06ba 100644 --- a/SSUSession.cpp +++ b/SSUSession.cpp @@ -1016,7 +1016,7 @@ namespace transport else { LogPrint (eLogDebug, "SSU: peer test from Alice. We are Bob"); - auto session = m_Server.GetRandomEstablishedV4Session (shared_from_this ()); // Charlie, TODO: implement v6 support + auto session = senderEndpoint.address ().is_v4 () ? m_Server.GetRandomEstablishedV4Session (shared_from_this ()) : m_Server.GetRandomEstablishedV6Session (shared_from_this ()); // Charlie if (session) { m_Server.NewPeerTest (nonce, ePeerTestParticipantBob, shared_from_this ()); From 8fb093b27265ab70d1fcc15da57ab319aa6a370e Mon Sep 17 00:00:00 2001 From: Mikal Villa Date: Sun, 24 Jul 2016 17:58:26 +0800 Subject: [PATCH 08/10] Reload client config on SIGHUP --- DaemonLinux.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/DaemonLinux.cpp b/DaemonLinux.cpp index 118fc5f5..f6664926 100644 --- a/DaemonLinux.cpp +++ b/DaemonLinux.cpp @@ -13,6 +13,7 @@ #include "FS.h" #include "Log.h" #include "RouterContext.h" +#include "ClientContext.h" void handle_signal(int sig) { @@ -21,6 +22,7 @@ void handle_signal(int sig) case SIGHUP: LogPrint(eLogInfo, "Daemon: Got SIGHUP, reopening log..."); i2p::log::Logger().Reopen (); + i2p::client::context.ReloadConfig(); break; case SIGINT: if (i2p::context.AcceptsTunnels () && !Daemon.gracefullShutdownInterval) From 11585327bf5e08eab1716803922f0d81725c74e7 Mon Sep 17 00:00:00 2001 From: orignal Date: Sun, 24 Jul 2016 09:24:20 -0400 Subject: [PATCH 09/10] correct status response --- BOB.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/BOB.cpp b/BOB.cpp index aa11c7b8..1ed03281 100644 --- a/BOB.cpp +++ b/BOB.cpp @@ -567,21 +567,21 @@ namespace client if (m_Nickname == operand) { std::stringstream s; - s << "DATA"; s << " NICKNAME:"; s << m_Nickname; + s << "DATA"; s << " NICKNAME: "; s << m_Nickname; if (m_CurrentDestination->GetLocalDestination ()->IsReady ()) - s << " STARTING:false RUNNING:true STOPPING:false"; + s << " STARTING: false RUNNING: true STOPPING: false"; else - s << " STARTING:true RUNNING:false STOPPING:false"; - s << " KEYS: true"; s << " QUIET:"; s << (m_IsQuiet ? "true":"false"); + s << " STARTING: true RUNNING: false STOPPING: false"; + s << " KEYS: true"; s << " QUIET: "; s << (m_IsQuiet ? "true":"false"); if (m_InPort) { - s << " INPORT:" << m_InPort; - s << " INHOST:" << (m_Address.length () > 0 ? m_Address : "127.0.0.1"); + s << " INPORT: " << m_InPort; + s << " INHOST: " << (m_Address.length () > 0 ? m_Address : "127.0.0.1"); } if (m_OutPort) { - s << " OUTPORT:" << m_OutPort; - s << " OUTHOST:" << (m_Address.length () > 0 ? m_Address : "127.0.0.1"); + s << " OUTPORT: " << m_OutPort; + s << " OUTHOST: " << (m_Address.length () > 0 ? m_Address : "127.0.0.1"); } SendReplyOK (s.str().c_str()); } From 061720bcf034ffee29d8f0492211223172fb2544 Mon Sep 17 00:00:00 2001 From: orignal Date: Sun, 24 Jul 2016 10:20:37 -0400 Subject: [PATCH 10/10] handle'\r\n' terminated address from Transmission --- BOB.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/BOB.cpp b/BOB.cpp index 1ed03281..caf766af 100644 --- a/BOB.cpp +++ b/BOB.cpp @@ -70,7 +70,7 @@ namespace client if (eol) { *eol = 0; - + if (eol != receiver->buffer && eol[-1] == '\r') eol[-1] = 0; // workaround for Transmission, it sends '\r\n' terminated address receiver->data = (uint8_t *)eol + 1; receiver->dataLen = receiver->bufferOffset - (eol - receiver->buffer + 1); i2p::data::IdentHash ident;