From f40e4c0c8455ff9897a088e000e20db25b2ff1a4 Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Wed, 14 Nov 2018 07:23:08 -0500 Subject: [PATCH] more exit stuff --- docs/proto_v0.txt | 35 +++++----- include/llarp/exit/context.hpp | 7 ++ include/llarp/exit/endpoint.hpp | 22 +++++- include/llarp/handlers/exit.hpp | 25 +++++-- include/llarp/handlers/tun.hpp | 52 ++++++++++---- include/llarp/messages/exit.hpp | 40 +++++++++++ include/llarp/path.hpp | 26 +++++++ include/llarp/routing/handler.hpp | 4 ++ include/llarp/service/address.hpp | 5 ++ include/llarp/service/endpoint.hpp | 3 +- llarp/crypto_libsodium.cpp | 2 +- llarp/dns_dotlokilookup.cpp | 3 +- llarp/exit/context.cpp | 28 ++++++++ llarp/exit/endpoint.cpp | 36 ++++++++++ llarp/exit/grant_exit.cpp | 26 +++++-- llarp/exit/update_exit.cpp | 107 +++++++++++++++++++++++++++-- llarp/handlers/exit.cpp | 65 ++++++++++++++++-- llarp/handlers/tun.cpp | 43 +++++++----- llarp/path.cpp | 18 +++++ llarp/service/context.cpp | 2 +- llarp/service/endpoint.cpp | 5 +- llarp/transit_hop.cpp | 57 ++++++++++++--- 22 files changed, 517 insertions(+), 94 deletions(-) diff --git a/docs/proto_v0.txt b/docs/proto_v0.txt index 802e2c4ea..b9f54bb3e 100644 --- a/docs/proto_v0.txt +++ b/docs/proto_v0.txt @@ -553,8 +553,7 @@ ip address used for exit traffic. A: "G", S: uint64_sequence_number, T: transaction_id_uint64, - V: 0, - Z: "<64 bytes signature using router identity signing key>" + V: 0 } any TITM recieved on the same path will be forwarded out to the internet if @@ -572,8 +571,7 @@ was denied. R: [list, of, rejected, traffic, policies], S: uint64_sequence_number, T: transaction_id_uint64, - V: 0, - Z: "<64 bytes signature signed by router's signing key>" + V: 0 } @@ -761,25 +759,13 @@ should use the new path that this message came from. { A: "U", - R: "<16 bytes previous rx path id>", + P: "<16 bytes previous tx path id>", S: uint64_sequence_number, - T: "<16 bytes previous tx path id>", - U: uint64_unique_id, + T: uint64_txid, V: 0, Z: "<64 bytes signature using previously provided signing key>" } -update exit verify message (EXVM) - -sent in reply to a UXPM to verify that the path handover was accepted - -{ - A: "V", - U: uint64_unique_id, - V: 0, - Z: "<64 bytes signature from router's signing key>" -} - close exit path message (CXPM) client sends a CXPM when the exit is no longer needed. @@ -792,6 +778,19 @@ client sends a CXPM when the exit is no longer needed. Z: "<64 bytes signagure using previously provided signing key>" } +update exit verify message (EXVM) + +sent in reply to a UXPM to verify that the path handover was accepted +sent in reply to a CXPM to verify that the exit was closed + +{ + A: "V", + S: uint64_sequence_number, + T: uint64_txid, + V: 0 +} + + DHT message holder message: wrapper message for sending many dht messages down a path. diff --git a/include/llarp/exit/context.hpp b/include/llarp/exit/context.hpp index cd524716f..feef6e069 100644 --- a/include/llarp/exit/context.hpp +++ b/include/llarp/exit/context.hpp @@ -24,6 +24,13 @@ namespace llarp bool AddExitEndpoint(const std::string &name, const Config_t &config); + bool + ObtainNewExit(const llarp::PubKey &remote, const llarp::PathID_t &path, + bool permitInternet); + + llarp::exit::Endpoint * + FindEndpointForPath(const llarp::PathID_t &path) const; + private: llarp_router *m_Router; std::unordered_map< std::string, diff --git a/include/llarp/exit/endpoint.hpp b/include/llarp/exit/endpoint.hpp index 0b29dd08a..2830ebc10 100644 --- a/include/llarp/exit/endpoint.hpp +++ b/include/llarp/exit/endpoint.hpp @@ -19,7 +19,7 @@ namespace llarp struct Endpoint { Endpoint(const llarp::PubKey& remoteIdent, - const llarp::PathID_t& beginPath, + const llarp::PathID_t& beginPath, bool rewriteIP, llarp::handlers::ExitEndpoint* parent); ~Endpoint(); @@ -33,20 +33,36 @@ namespace llarp SendInboundTraffic(llarp_buffer_t buff); /// send traffic to service node / internet - /// does ip rewrite + /// does ip rewrite here bool SendOutboundTraffic(llarp_buffer_t buf); - void + /// update local path id and cascade information to parent + /// return true if success + bool UpdateLocalPath(const llarp::PathID_t& nextPath); llarp::path::IHopHandler* GetCurrentPath() const; + const llarp::PubKey& + PubKey() const + { + return m_remoteSignKey; + } + + const llarp::PathID_t& + LocalPath() const + { + return m_CurrentPath; + } + private: llarp::handlers::ExitEndpoint* m_Parent; llarp::PubKey m_remoteSignKey; llarp::PathID_t m_CurrentPath; + llarp::huint32_t m_IP; + bool m_RewriteSource; }; } // namespace exit } // namespace llarp diff --git a/include/llarp/handlers/exit.hpp b/include/llarp/handlers/exit.hpp index 42bd79451..2d9c917f8 100644 --- a/include/llarp/handlers/exit.hpp +++ b/include/llarp/handlers/exit.hpp @@ -23,21 +23,34 @@ namespace llarp virtual std::string Name() const override; + bool + AllocateNewExit(const llarp::PubKey& pk, const llarp::PathID_t& path, + bool permitInternet); + + llarp::exit::Endpoint* + FindEndpointByPath(const llarp::PathID_t& path); + + bool + UpdateEndpointPath(const llarp::PubKey& remote, + const llarp::PathID_t& next); + + void + DelEndpointInfo(const llarp::PathID_t& path, const huint32_t& ip, + const llarp::PubKey& pk); + protected: void FlushSend(); private: - std::string m_Name; - + bool m_PermitExit; + std::unordered_map< llarp::PathID_t, llarp::PubKey, + llarp::PathID_t::Hash > + m_Paths; std::unordered_multimap< llarp::PubKey, llarp::exit::Endpoint, llarp::PubKey::Hash > m_ActiveExits; - - std::unordered_map< llarp::huint32_t, llarp::PubKey, - llarp::huint32_t::Hash > - m_AddrsToPubKey; }; } // namespace handlers } // namespace llarp diff --git a/include/llarp/handlers/tun.hpp b/include/llarp/handlers/tun.hpp index aefbbc7ca..1a6a893d4 100644 --- a/include/llarp/handlers/tun.hpp +++ b/include/llarp/handlers/tun.hpp @@ -51,6 +51,17 @@ namespace llarp bool ProcessDataMessage(service::ProtocolMessage* msg); + /// queue outbound packet to the world + bool + QueueOutboundTraffic(llarp::net::IPv4Packet&& pkt); + + /// get the local interface's address + huint32_t + GetIfAddr() const; + + bool + HasLocalIP(const huint32_t& ip) const; + #ifndef WIN32 /// overrides Endpoint bool @@ -80,19 +91,32 @@ namespace llarp static void handleTickTun(void* u); - /// get a service address for ip address - service::Address - ObtainAddrForIP(huint32_t ip); + /// get a key for ip address + template < typename Addr > + Addr + ObtainAddrForIP(huint32_t ip) + { + auto itr = m_IPToAddr.find(ip); + if(itr == m_IPToAddr.end()) + { + // not found + Addr addr; + addr.Zero(); + return addr; + } + // found + return itr->second.data(); + } bool - HasAddress(const service::Address& remote) const + HasAddress(const byte_t* addr) const { - return m_AddrToIP.find(remote) != m_AddrToIP.end(); + return m_AddrToIP.find(addr) != m_AddrToIP.end(); } - /// get ip address for service address unconditionally + /// get ip address for key unconditionally huint32_t - ObtainIPForAddr(const service::Address& addr); + ObtainIPForAddr(const byte_t* addr); protected: typedef llarp::util::CoDelQueue< @@ -119,6 +143,14 @@ namespace llarp virtual void FlushSend(); + /// maps ip to key (host byte order) + std::unordered_map< huint32_t, AlignedBuffer< 32 >, huint32_t::Hash > + m_IPToAddr; + /// maps key to ip (host byte order) + std::unordered_map< AlignedBuffer< 32 >, huint32_t, + AlignedBuffer< 32 >::Hash > + m_AddrToIP; + private: #ifndef WIN32 /// handles setup, given value true on success and false on failure to set @@ -131,12 +163,6 @@ namespace llarp /// for netns) struct dotLokiLookup dll; - /// maps ip to service address (host byte order) - std::unordered_map< huint32_t, service::Address, huint32_t::Hash > - m_IPToAddr; - /// maps service address to ip (host byte order) - std::unordered_map< service::Address, huint32_t, service::Address::Hash > - m_AddrToIP; /// maps ip address to timestamp last active std::unordered_map< huint32_t, llarp_time_t, huint32_t::Hash > m_IPActivity; diff --git a/include/llarp/messages/exit.hpp b/include/llarp/messages/exit.hpp index e2dc4c76d..b7a062403 100644 --- a/include/llarp/messages/exit.hpp +++ b/include/llarp/messages/exit.hpp @@ -49,6 +49,7 @@ namespace llarp struct GrantExitMessage final : public IMessage { + uint64_t T; GrantExitMessage() : IMessage() { } @@ -69,6 +70,10 @@ namespace llarp struct RejectExitMessage final : public IMessage { + uint64_t B; + std::vector< llarp::exit::Policy > R; + uint64_t T; + RejectExitMessage() : IMessage() { } @@ -87,8 +92,34 @@ namespace llarp HandleMessage(IMessageHandler* h, llarp_router* r) const override; }; + struct UpdateExitVerifyMessage final : public IMessage + { + uint64_t T; + + UpdateExitVerifyMessage() : IMessage() + { + } + + ~UpdateExitVerifyMessage() + { + } + + bool + BEncode(llarp_buffer_t* buf) const override; + + bool + DecodeKey(llarp_buffer_t key, llarp_buffer_t* buf) override; + + bool + HandleMessage(IMessageHandler* h, llarp_router* r) const override; + }; + struct UpdateExitMessage final : public IMessage { + llarp::PathID_t P; + uint64_t T; + llarp::Signature Z; + UpdateExitMessage() : IMessage() { } @@ -97,6 +128,15 @@ namespace llarp { } + UpdateExitMessage& + operator=(const UpdateExitMessage& other); + + bool + Sign(llarp_crypto* c, const llarp::SecretKey& sk); + + bool + Verify(llarp_crypto* c, const llarp::PubKey& pk) const; + bool BEncode(llarp_buffer_t* buf) const override; diff --git a/include/llarp/path.hpp b/include/llarp/path.hpp index a02447ddb..f9ba44eb1 100644 --- a/include/llarp/path.hpp +++ b/include/llarp/path.hpp @@ -191,6 +191,10 @@ namespace llarp HandleObtainExitMessage(const llarp::routing::ObtainExitMessage* msg, llarp_router* r); + bool + HandleUpdateExitVerifyMessage( + const llarp::routing::UpdateExitVerifyMessage* msg, llarp_router* r); + bool HandleTransferTrafficMessage( const llarp::routing::TransferTrafficMessage* msg, llarp_router* r); @@ -268,6 +272,8 @@ namespace llarp typedef std::vector< PathHopConfig > HopList; typedef std::function< bool(Path*, const service::ProtocolFrame*) > DataHandlerFunc; + typedef std::function< bool(Path*) > ExitUpdatedFunc; + typedef std::function< bool(Path*) > ExitClosedFunc; HopList hops; @@ -283,6 +289,18 @@ namespace llarp void SetBuildResultHook(BuildResultHookFunc func); + void + SetCloseExitFunc(ExitClosedFunc handler) + { + m_ExitClosed = handler; + } + + void + SetUpdateExitFunc(ExitUpdatedFunc handler) + { + m_ExitUpdated = handler; + } + void SetDataHandler(DataHandlerFunc func) { @@ -323,6 +341,10 @@ namespace llarp HandleObtainExitMessage(const llarp::routing::ObtainExitMessage* msg, llarp_router* r); + bool + HandleUpdateExitVerifyMessage( + const llarp::routing::UpdateExitVerifyMessage* msg, llarp_router* r); + bool HandleTransferTrafficMessage( const llarp::routing::TransferTrafficMessage* msg, llarp_router* r); @@ -412,9 +434,13 @@ namespace llarp DataHandlerFunc m_DataHandler; DropHandlerFunc m_DropHandler; CheckForDeadFunc m_CheckForDead; + ExitUpdatedFunc m_ExitUpdated; + ExitClosedFunc m_ExitClosed; llarp_time_t m_LastRecvMessage = 0; llarp_time_t m_LastLatencyTestTime = 0; uint64_t m_LastLatencyTestID = 0; + uint64_t m_UpdateExitTX = 0; + uint64_t m_CloseExitTX = 0; }; enum PathBuildStatus diff --git a/include/llarp/routing/handler.hpp b/include/llarp/routing/handler.hpp index f0fe96046..bf17615f0 100644 --- a/include/llarp/routing/handler.hpp +++ b/include/llarp/routing/handler.hpp @@ -39,6 +39,10 @@ namespace llarp HandleUpdateExitMessage(const UpdateExitMessage *msg, llarp_router *r) = 0; + virtual bool + HandleUpdateExitVerifyMessage(const UpdateExitVerifyMessage *msg, + llarp_router *r) = 0; + virtual bool HandleCloseExitMessage(const CloseExitMessage *msg, llarp_router *r) = 0; diff --git a/include/llarp/service/address.hpp b/include/llarp/service/address.hpp index c0bac6613..376be2498 100644 --- a/include/llarp/service/address.hpp +++ b/include/llarp/service/address.hpp @@ -22,6 +22,11 @@ namespace llarp Zero(); } + Address(const byte_t* buf) + { + memcpy(b, buf, 32); + } + Address(const Address& other) { memcpy(b, other.b, 32); diff --git a/include/llarp/service/endpoint.hpp b/include/llarp/service/endpoint.hpp index 3eb411e37..2cce05a93 100644 --- a/include/llarp/service/endpoint.hpp +++ b/include/llarp/service/endpoint.hpp @@ -159,8 +159,7 @@ namespace llarp HandlePathBuilt(path::Path* path); bool - SendToOrQueue(const Address& remote, llarp_buffer_t payload, - ProtocolType t); + SendToOrQueue(const byte_t* addr, llarp_buffer_t payload, ProtocolType t); struct PendingBuffer { diff --git a/llarp/crypto_libsodium.cpp b/llarp/crypto_libsodium.cpp index ef4fa841c..56012836d 100644 --- a/llarp/crypto_libsodium.cpp +++ b/llarp/crypto_libsodium.cpp @@ -178,7 +178,7 @@ namespace llarp void llarp_crypto_init(struct llarp_crypto *c) { - assert(sodium_init() == 0); + assert(sodium_init() != -1); char *avx2 = getenv("AVX2_FORCE_DISABLE"); if(avx2 && std::string(avx2) == "1") ntru_init(1); diff --git a/llarp/dns_dotlokilookup.cpp b/llarp/dns_dotlokilookup.cpp index e4df50eeb..f01adb05f 100644 --- a/llarp/dns_dotlokilookup.cpp +++ b/llarp/dns_dotlokilookup.cpp @@ -255,7 +255,8 @@ ReverseHandlerIter(struct llarp::service::Context::endpoint_iter *endpointCfg) if(inRange) { llarp::service::Address addr = - tunEndpoint->ObtainAddrForIP(searchIPv4_fixed); + tunEndpoint->ObtainAddrForIP< llarp::service::Address >( + searchIPv4_fixed); if(addr.IsZero()) { write404_dnss_response(context->from, diff --git a/llarp/exit/context.cpp b/llarp/exit/context.cpp index bce44afba..1ef86d1c4 100644 --- a/llarp/exit/context.cpp +++ b/llarp/exit/context.cpp @@ -22,6 +22,34 @@ namespace llarp } } + llarp::exit::Endpoint* + Context::FindEndpointForPath(const llarp::PathID_t& path) const + { + auto itr = m_Exits.begin(); + while(itr != m_Exits.end()) + { + auto ep = itr->second->FindEndpointByPath(path); + if(ep) + return ep; + ++itr; + } + return nullptr; + } + + bool + Context::ObtainNewExit(const llarp::PubKey& pk, const llarp::PathID_t& path, + bool permitInternet) + { + auto itr = m_Exits.begin(); + while(itr != m_Exits.end()) + { + if(itr->second->AllocateNewExit(pk, path, permitInternet)) + return true; + ++itr; + } + return false; + } + bool Context::AddExitEndpoint(const std::string& name, const Config_t& conf) { diff --git a/llarp/exit/endpoint.cpp b/llarp/exit/endpoint.cpp index 1d0ca2358..f6cda28ee 100644 --- a/llarp/exit/endpoint.cpp +++ b/llarp/exit/endpoint.cpp @@ -5,8 +5,29 @@ namespace llarp { namespace exit { + Endpoint::Endpoint(const llarp::PubKey& remoteIdent, + const llarp::PathID_t& beginPath, bool rewriteIP, + llarp::handlers::ExitEndpoint* parent) + : m_Parent(parent) + , m_remoteSignKey(remoteIdent) + , m_CurrentPath(beginPath) + , m_IP(parent->ObtainIPForAddr(remoteIdent)) + , m_RewriteSource(rewriteIP) + { + } + Endpoint::~Endpoint() { + m_Parent->DelEndpointInfo(m_CurrentPath, m_IP, m_remoteSignKey); + } + + bool + Endpoint::UpdateLocalPath(const llarp::PathID_t& nextPath) + { + if(!m_Parent->UpdateEndpointPath(m_remoteSignKey, nextPath)) + return false; + m_CurrentPath = nextPath; + return true; } bool @@ -21,6 +42,21 @@ namespace llarp return true; } + bool + Endpoint::SendOutboundTraffic(llarp_buffer_t buf) + { + llarp::net::IPv4Packet pkt; + if(!pkt.Load(buf)) + return false; + huint32_t dst; + if(m_RewriteSource) + dst = m_Parent->GetIfAddr(); + else + dst = pkt.dst(); + pkt.UpdateIPv4PacketOnDst(m_IP, dst); + return m_Parent->QueueOutboundTraffic(std::move(pkt)); + } + bool Endpoint::SendInboundTraffic(llarp_buffer_t buf) { diff --git a/llarp/exit/grant_exit.cpp b/llarp/exit/grant_exit.cpp index 4049426a9..398247d85 100644 --- a/llarp/exit/grant_exit.cpp +++ b/llarp/exit/grant_exit.cpp @@ -8,18 +8,30 @@ namespace llarp bool GrantExitMessage::BEncode(llarp_buffer_t* buf) const { - (void)buf; - // TODO: implement me - return false; + if(!bencode_start_dict(buf)) + return false; + if(!BEncodeWriteDictMsgType(buf, "A", "G")) + return false; + if(!BEncodeWriteDictInt("S", S, buf)) + return false; + if(!BEncodeWriteDictInt("T", T, buf)) + return false; + if(!BEncodeWriteDictInt("V", version, buf)) + return false; + return bencode_end(buf); } bool GrantExitMessage::DecodeKey(llarp_buffer_t k, llarp_buffer_t* buf) { - (void)k; - (void)buf; - // TODO: implement me - return false; + bool read = false; + if(!BEncodeMaybeReadDictInt("S", S, read, k, buf)) + return false; + if(!BEncodeMaybeReadDictInt("T", T, read, k, buf)) + return false; + if(!BEncodeMaybeReadDictInt("V", version, read, k, buf)) + return false; + return read; } bool diff --git a/llarp/exit/update_exit.cpp b/llarp/exit/update_exit.cpp index fc95352a3..f69ccc3c9 100644 --- a/llarp/exit/update_exit.cpp +++ b/llarp/exit/update_exit.cpp @@ -8,18 +8,75 @@ namespace llarp bool UpdateExitMessage::BEncode(llarp_buffer_t* buf) const { - (void)buf; - // TODO: implement me - return false; + if(!bencode_start_dict(buf)) + return false; + if(!BEncodeWriteDictMsgType(buf, "A", "V")) + return false; + if(!BEncodeWriteDictEntry("P", P, buf)) + return false; + if(!BEncodeWriteDictInt("S", S, buf)) + return false; + if(!BEncodeWriteDictInt("T", T, buf)) + return false; + if(!BEncodeWriteDictInt("V", version, buf)) + return false; + if(!BEncodeWriteDictEntry("Z", Z, buf)) + return false; + return bencode_end(buf); } bool UpdateExitMessage::DecodeKey(llarp_buffer_t k, llarp_buffer_t* buf) { - (void)k; - (void)buf; - // TODO: implement me - return false; + bool read = false; + if(!BEncodeMaybeReadDictInt("S", S, read, k, buf)) + return false; + if(!BEncodeMaybeReadDictInt("T", T, read, k, buf)) + return false; + if(!BEncodeMaybeReadDictInt("V", version, read, k, buf)) + return false; + if(!BEncodeMaybeReadDictEntry("P", P, read, k, buf)) + return false; + if(!BEncodeMaybeReadDictEntry("Z", Z, read, k, buf)) + return false; + return read; + } + + bool + UpdateExitMessage::Verify(llarp_crypto* c, const llarp::PubKey& pk) const + + { + byte_t tmp[128] = {0}; + auto buf = llarp::StackBuffer< decltype(tmp) >(tmp); + UpdateExitMessage copy; + copy = *this; + copy.Z.Zero(); + if(!copy.BEncode(&buf)) + return false; + buf.sz = buf.cur - buf.base; + return c->verify(pk, buf, Z); + } + + UpdateExitMessage& + UpdateExitMessage::operator=(const UpdateExitMessage& other) + { + P = other.P; + S = other.S; + T = other.T; + version = other.version; + Z = other.Z; + return *this; + } + + bool + UpdateExitMessage::Sign(llarp_crypto* c, const llarp::SecretKey& sk) + { + byte_t tmp[128] = {0}; + auto buf = llarp::StackBuffer< decltype(tmp) >(tmp); + if(!BEncode(&buf)) + return false; + buf.sz = buf.cur - buf.base; + return c->sign(Z, sk, buf); } bool @@ -28,5 +85,41 @@ namespace llarp return h->HandleUpdateExitMessage(this, r); } + bool + UpdateExitVerifyMessage::BEncode(llarp_buffer_t* buf) const + { + if(!bencode_start_dict(buf)) + return false; + if(!BEncodeWriteDictMsgType(buf, "A", "V")) + return false; + if(!BEncodeWriteDictInt("S", S, buf)) + return false; + if(!BEncodeWriteDictInt("T", T, buf)) + return false; + if(!BEncodeWriteDictInt("V", version, buf)) + return false; + return bencode_end(buf); + } + + bool + UpdateExitVerifyMessage::DecodeKey(llarp_buffer_t k, llarp_buffer_t* buf) + { + bool read = false; + if(!BEncodeMaybeReadDictInt("S", S, read, k, buf)) + return false; + if(!BEncodeMaybeReadDictInt("T", T, read, k, buf)) + return false; + if(!BEncodeMaybeReadDictInt("V", version, read, k, buf)) + return false; + return read; + } + + bool + UpdateExitVerifyMessage::HandleMessage(IMessageHandler* h, + llarp_router* r) const + { + return h->HandleUpdateExitVerifyMessage(this, r); + } + } // namespace routing } // namespace llarp \ No newline at end of file diff --git a/llarp/handlers/exit.cpp b/llarp/handlers/exit.cpp index d7cb2f332..000218c98 100644 --- a/llarp/handlers/exit.cpp +++ b/llarp/handlers/exit.cpp @@ -1,4 +1,5 @@ #include +#include "../str.hpp" namespace llarp { @@ -13,11 +14,46 @@ namespace llarp { } + llarp::exit::Endpoint * + ExitEndpoint::FindEndpointByPath(const llarp::PathID_t &path) + { + llarp::exit::Endpoint *endpoint = nullptr; + llarp::PubKey pk; + { + auto itr = m_Paths.find(path); + if(itr == m_Paths.end()) + return nullptr; + pk = itr->second; + } + { + auto itr = m_ActiveExits.find(pk); + if(itr != m_ActiveExits.end()) + { + if(itr->second.PubKey() == pk) + endpoint = &itr->second; + } + } + return endpoint; + } + + bool + ExitEndpoint::UpdateEndpointPath(const llarp::PubKey &remote, + const llarp::PathID_t &next) + { + // check if already mapped + auto itr = m_Paths.find(next); + if(itr != m_Paths.end()) + return false; + m_Paths.insert(std::make_pair(next, remote)); + return true; + } + bool ExitEndpoint::SetOption(const std::string &k, const std::string &v) { if(k == "exit") { + m_PermitExit = IsTrueValue(v.c_str()); // TODO: implement me return true; } @@ -36,19 +72,29 @@ namespace llarp return TunEndpoint::SetOption(k, v); } + bool + ExitEndpoint::AllocateNewExit(const llarp::PubKey &pk, + const llarp::PathID_t &path, + bool permitInternet) + { + m_ActiveExits.insert(std::make_pair( + pk, llarp::exit::Endpoint(pk, path, !permitInternet, this))); + return true; + } + void ExitEndpoint::FlushSend() { m_UserToNetworkPktQueue.Process([&](net::IPv4Packet &pkt) { // find pubkey for addr - auto itr = m_AddrsToPubKey.find(pkt.dst()); - if(itr == m_AddrsToPubKey.end()) + if(!HasLocalIP(pkt.dst())) { llarp::LogWarn(Name(), " has no endpoint for ", pkt.dst()); return true; } - pkt.UpdateIPv4PacketOnSrc(); - auto range = m_ActiveExits.equal_range(itr->second); + llarp::PubKey pk = ObtainAddrForIP< llarp::PubKey >(pkt.dst()); + pkt.UpdateIPv4PacketOnDst(pkt.src(), {0}); + auto range = m_ActiveExits.equal_range(pk); auto exit_itr = range.first; while(exit_itr != range.second) { @@ -57,7 +103,7 @@ namespace llarp ++exit_itr; } // dropped - llarp::LogWarn(Name(), " dropped traffic to ", itr->second); + llarp::LogWarn(Name(), " dropped traffic to ", pk); return true; }); } @@ -68,6 +114,15 @@ namespace llarp return m_Name; } + void + ExitEndpoint::DelEndpointInfo(const llarp::PathID_t &path, + const huint32_t &ip, const llarp::PubKey &pk) + { + m_Paths.erase(path); + m_IPToAddr.erase(ip); + m_AddrToIP.erase(pk); + } + void ExitEndpoint::Tick(llarp_time_t now) { diff --git a/llarp/handlers/tun.cpp b/llarp/handlers/tun.cpp index 3713ad0b3..f54f7b84f 100644 --- a/llarp/handlers/tun.cpp +++ b/llarp/handlers/tun.cpp @@ -141,6 +141,20 @@ namespace llarp return Endpoint::SetOption(k, v); } + bool + TunEndpoint::HasLocalIP(const huint32_t &ip) const + { + return m_IPToAddr.find(ip) != m_IPToAddr.end(); + } + + bool + TunEndpoint::QueueOutboundTraffic(llarp::net::IPv4Packet &&pkt) + { + return m_NetworkToUserPktQueue.EmplaceIf( + [](llarp::net::IPv4Packet &) -> bool { return true; }, + std::move(pkt)); + } + bool TunEndpoint::MapAddress(const service::Address &addr, huint32_t ip) { @@ -148,13 +162,14 @@ namespace llarp if(itr != m_IPToAddr.end()) { // XXX is calling inet_ntoa safe in this context? it's MP-unsafe - llarp::LogWarn(ip, " already mapped to ", itr->second.ToString()); + llarp::LogWarn(ip, " already mapped to ", + service::Address(itr->second).ToString()); return false; } llarp::LogInfo(Name() + " map ", addr.ToString(), " to ", ip); - m_IPToAddr.insert(std::make_pair(ip, addr)); - m_AddrToIP.insert(std::make_pair(addr, ip)); + m_IPToAddr.insert(std::make_pair(ip, addr.data())); + m_AddrToIP.insert(std::make_pair(addr.data(), ip)); MarkIPActiveForever(ip); return true; } @@ -331,7 +346,8 @@ namespace llarp // this includes clearing IP addresses, recalculating checksums, etc pkt.UpdateIPv4PacketOnSrc(); - if(!SendToOrQueue(itr->second, pkt.Buffer(), service::eProtocolTraffic)) + if(!SendToOrQueue(itr->second.data(), pkt.Buffer(), + service::eProtocolTraffic)) { llarp::LogWarn(Name(), " did not flush packets"); } @@ -343,7 +359,7 @@ namespace llarp TunEndpoint::ProcessDataMessage(service::ProtocolMessage *msg) { // llarp::LogInfo("got packet from ", msg->sender.Addr()); - auto themIP = ObtainIPForAddr(msg->sender.Addr()); + auto themIP = ObtainIPForAddr(msg->sender.Addr().data()); // llarp::LogInfo("themIP ", themIP); auto usIP = m_OurIP; auto buf = llarp::Buffer(msg->payload); @@ -376,23 +392,14 @@ namespace llarp return true; } - service::Address - TunEndpoint::ObtainAddrForIP(huint32_t ip) + huint32_t + TunEndpoint::GetIfAddr() const { - auto itr = m_IPToAddr.find(ip); - if(itr == m_IPToAddr.end()) - { - // not found - service::Address addr; - llarp::LogWarn(ip, " not found in tun map. Sending ", addr.ToString()); - return addr; - } - // found - return itr->second; + return m_OurIP; } huint32_t - TunEndpoint::ObtainIPForAddr(const service::Address &addr) + TunEndpoint::ObtainIPForAddr(const byte_t *addr) { llarp_time_t now = Now(); huint32_t nextIP = {0}; diff --git a/llarp/path.cpp b/llarp/path.cpp index 1666de95c..46ec6e443 100644 --- a/llarp/path.cpp +++ b/llarp/path.cpp @@ -530,6 +530,24 @@ namespace llarp return true; } + bool + Path::HandleUpdateExitVerifyMessage( + const llarp::routing::UpdateExitVerifyMessage* msg, llarp_router* r) + { + (void)r; + if(m_UpdateExitTX && msg->T == m_UpdateExitTX) + { + if(m_ExitUpdated) + return m_ExitUpdated(this); + } + if(m_CloseExitTX && msg->T == m_CloseExitTX) + { + if(m_ExitClosed) + return m_ExitClosed(this); + } + return false; + } + bool Path::SendRoutingMessage(const llarp::routing::IMessage* msg, llarp_router* r) diff --git a/llarp/service/context.cpp b/llarp/service/context.cpp index d7ae6347f..e0faf8e65 100644 --- a/llarp/service/context.cpp +++ b/llarp/service/context.cpp @@ -151,7 +151,7 @@ namespace llarp llarp::LogError("No tunnel endpoint found"); return zero; } - return tunEndpoint->ObtainIPForAddr(addr); + return tunEndpoint->ObtainIPForAddr(addr.data()); } bool diff --git a/llarp/service/endpoint.cpp b/llarp/service/endpoint.cpp index 037fa7f84..10ab0242d 100644 --- a/llarp/service/endpoint.cpp +++ b/llarp/service/endpoint.cpp @@ -1040,11 +1040,14 @@ namespace llarp } bool - Endpoint::SendToOrQueue(const Address& remote, llarp_buffer_t data, + Endpoint::SendToOrQueue(const byte_t* addr, llarp_buffer_t data, ProtocolType t) { + service::Address remote(addr); + // inbound converstation auto now = Now(); + { auto itr = m_AddressToService.find(remote); if(itr != m_AddressToService.end()) diff --git a/llarp/transit_hop.cpp b/llarp/transit_hop.cpp index ba875e17a..b6ad8619e 100644 --- a/llarp/transit_hop.cpp +++ b/llarp/transit_hop.cpp @@ -153,10 +153,20 @@ namespace llarp TransitHop::HandleObtainExitMessage( const llarp::routing::ObtainExitMessage* msg, llarp_router* r) { - // TODO: implement me - (void)msg; - (void)r; - return false; + if(msg->Verify(&r->crypto) + && r->exitContext.ObtainNewExit(msg->I, info.txID, msg->E != 0)) + { + llarp::routing::GrantExitMessage grant; + grant.S = NextSeqNo(); + grant.T = msg->T; + return SendRoutingMessage(&grant, r); + } + // TODO: exponential backoff + // TODO: rejected policies + llarp::routing::RejectExitMessage reject; + reject.S = NextSeqNo(); + reject.T = msg->T; + return SendRoutingMessage(&reject, r); } bool @@ -170,15 +180,38 @@ namespace llarp } bool - TransitHop::HandleUpdateExitMessage( - const llarp::routing::UpdateExitMessage* msg, llarp_router* r) + TransitHop::HandleUpdateExitVerifyMessage( + const llarp::routing::UpdateExitVerifyMessage* msg, llarp_router* r) { - // TODO: implement me (void)msg; (void)r; + llarp::LogError("unwarranted exit verify on ", info); return false; } + bool + TransitHop::HandleUpdateExitMessage( + const llarp::routing::UpdateExitMessage* msg, llarp_router* r) + { + auto ep = r->exitContext.FindEndpointForPath(msg->P); + if(ep) + { + if(msg->Verify(&r->crypto, ep->PubKey())) + { + if(ep->UpdateLocalPath(info.txID)) + { + llarp::routing::UpdateExitVerifyMessage reply; + reply.T = msg->T; + reply.S = NextSeqNo(); + return SendRoutingMessage(&reply, r); + } + } + } + // on fail tell message was discarded + llarp::routing::DataDiscardMessage discard(info.txID, msg->S); + return SendRoutingMessage(&discard, r); + } + bool TransitHop::HandleRejectExitMessage( const llarp::routing::RejectExitMessage* msg, llarp_router* r) @@ -203,10 +236,12 @@ namespace llarp TransitHop::HandleTransferTrafficMessage( const llarp::routing::TransferTrafficMessage* msg, llarp_router* r) { - // TODO: implement me - (void)msg; - (void)r; - return false; + auto endpoint = r->exitContext.FindEndpointForPath(info.txID); + if(endpoint == nullptr) + return false; + if(!msg->Verify(&r->crypto, endpoint->PubKey())) + return false; + return endpoint->SendOutboundTraffic(llarp::ConstBuffer(msg->X)); } bool