/* * Copyright (c) 2013-2022, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * * See full license text in LICENSE file at top of project tree */ #ifndef ROUTER_CONTEXT_H__ #define ROUTER_CONTEXT_H__ #include #include #include #include #include #include #include "Identity.h" #include "RouterInfo.h" #include "Garlic.h" namespace i2p { namespace garlic { class RouterIncomingRatchetSession; } const char ROUTER_INFO[] = "router.info"; const char ROUTER_KEYS[] = "router.keys"; const char NTCP2_KEYS[] = "ntcp2.keys"; const char SSU2_KEYS[] = "ssu2.keys"; const int ROUTER_INFO_UPDATE_INTERVAL = 1800; // 30 minutes enum RouterStatus { eRouterStatusOK = 0, eRouterStatusTesting = 1, eRouterStatusFirewalled = 2, eRouterStatusError = 3, eRouterStatusUnknown = 4, eRouterStatusProxy = 5, eRouterStatusMesh = 6 }; enum RouterError { eRouterErrorNone = 0, eRouterErrorClockSkew = 1, eRouterErrorOffline = 2, eRouterErrorSymmetricNAT = 3 }; class RouterContext : public i2p::garlic::GarlicDestination { private: struct NTCP2PrivateKeys { uint8_t staticPublicKey[32]; uint8_t staticPrivateKey[32]; uint8_t iv[16]; }; struct SSU2PrivateKeys { uint8_t staticPublicKey[32]; uint8_t staticPrivateKey[32]; uint8_t intro[32]; }; public: RouterContext(); void Init(); const i2p::data::PrivateKeys &GetPrivateKeys() const { return m_Keys; }; i2p::data::LocalRouterInfo &GetRouterInfo() { return m_RouterInfo; }; std::shared_ptr GetSharedRouterInfo() { return std::shared_ptr(&m_RouterInfo, [](i2p::data::RouterInfo *) {}); } std::shared_ptr GetSharedDestination() { return std::shared_ptr(this, [](i2p::garlic::GarlicDestination *) {}); } const uint8_t *GetNTCP2StaticPublicKey() const { return m_NTCP2Keys ? m_NTCP2Keys->staticPublicKey : nullptr; }; const uint8_t *GetNTCP2StaticPrivateKey() const { return m_NTCP2Keys ? m_NTCP2Keys->staticPrivateKey : nullptr; }; const uint8_t *GetNTCP2IV() const { return m_NTCP2Keys ? m_NTCP2Keys->iv : nullptr; }; i2p::crypto::X25519Keys &GetNTCP2StaticKeys(); const uint8_t *GetSSU2StaticPublicKey() const { return m_SSU2Keys ? m_SSU2Keys->staticPublicKey : nullptr; }; const uint8_t *GetSSU2StaticPrivateKey() const { return m_SSU2Keys ? m_SSU2Keys->staticPrivateKey : nullptr; }; const uint8_t *GetSSU2IntroKey() const { return m_SSU2Keys ? m_SSU2Keys->intro : nullptr; }; i2p::crypto::X25519Keys &GetSSU2StaticKeys(); uint32_t GetUptime() const; // in seconds uint64_t GetLastUpdateTime() const { return m_LastUpdateTime; }; uint64_t GetBandwidthLimit() const { return m_BandwidthLimit; }; uint64_t GetTransitBandwidthLimit() const { return (m_BandwidthLimit * m_ShareRatio) / 100LL; }; RouterStatus GetStatus() const { return m_Status; }; void SetStatus(RouterStatus status); void SetStatusSSU2(RouterStatus status); RouterError GetError() const { return m_Error; }; void SetError(RouterError error) { m_Status = eRouterStatusError; m_Error = error; }; RouterStatus GetStatusV6() const { return m_StatusV6; }; void SetStatusV6(RouterStatus status); void SetStatusV6SSU2(RouterStatus status); RouterError GetErrorV6() const { return m_ErrorV6; }; void SetErrorV6(RouterError error) { m_StatusV6 = eRouterStatusError; m_ErrorV6 = error; }; int GetNetID() const { return m_NetID; }; void SetNetID(int netID) { m_NetID = netID; }; bool DecryptTunnelBuildRecord(const uint8_t *encrypted, uint8_t *data); bool DecryptTunnelShortRequestRecord(const uint8_t *encrypted, uint8_t *data); void UpdatePort(int port); // called from Daemon void UpdateAddress(const boost::asio::ip::address &host); // called from SSU or Daemon void PublishNTCP2Address(int port, bool publish, bool v4, bool v6, bool ygg); void UpdateNTCP2Address(bool enable); void PublishSSU2Address(int port, bool publish, bool v4, bool v6); void UpdateSSU2Address(bool enable); void RemoveNTCPAddress(bool v4only = true); // delete NTCP address for older routers. TODO: remove later void RemoveSSUAddress(); // delete SSU address for older routers bool AddIntroducer(const i2p::data::RouterInfo::Introducer &introducer); void RemoveIntroducer(const boost::asio::ip::udp::endpoint &e); bool AddSSU2Introducer(const i2p::data::RouterInfo::Introducer &introducer, bool v4); void RemoveSSU2Introducer(const i2p::data::IdentHash &h, bool v4); void ClearSSU2Introducers(bool v4); bool IsUnreachable() const; void SetUnreachable(bool v4, bool v6); void SetUnreachableSSU2(bool v4, bool v6); void SetReachable(bool v4, bool v6); bool IsFloodfill() const { return m_IsFloodfill; }; void SetFloodfill(bool floodfill); void SetFamily(const std::string &family); std::string GetFamily() const; void SetBandwidth(int limit); /* in kilobytes */ void SetBandwidth(char L); /* by letter */ void SetShareRatio(int percents); // 0 - 100 bool AcceptsTunnels() const { return m_AcceptsTunnels; }; void SetAcceptsTunnels(bool acceptsTunnels) { m_AcceptsTunnels = acceptsTunnels; }; bool SupportsV6() const { return m_RouterInfo.IsV6(); }; bool SupportsV4() const { return m_RouterInfo.IsV4(); }; bool SupportsMesh() const { return m_RouterInfo.IsMesh(); }; void SetSupportsV6(bool supportsV6); void SetSupportsV4(bool supportsV4); void SetSupportsMesh(bool supportsmesh, const boost::asio::ip::address_v6 &host); void SetMTU(int mtu, bool v4); i2p::crypto::NoiseSymmetricState &GetCurrentNoiseState() { return m_CurrentNoiseState; }; void UpdateNTCP2V6Address(const boost::asio::ip::address &host); // called from Daemon. TODO: remove void UpdateStats(); void UpdateTimestamp(uint64_t ts); // in seconds, called from NetDb before publishing void CleanupDestination(); // garlic destination // implements LocalDestination std::shared_ptr GetIdentity() const { return m_Keys.GetPublic(); }; bool Decrypt(const uint8_t *encrypted, uint8_t *data, i2p::data::CryptoKeyType preferredCrypto) const; void Sign(const uint8_t *buf, int len, uint8_t *signature) const { m_Keys.Sign(buf, len, signature); }; void SetLeaseSetUpdated() {}; // implements GarlicDestination std::shared_ptr GetLeaseSet() { return nullptr; }; std::shared_ptr GetTunnelPool() const; // override GarlicDestination void ProcessGarlicMessage(std::shared_ptr msg); void ProcessDeliveryStatusMessage(std::shared_ptr msg); protected: // implements GarlicDestination void HandleI2NPMessage(const uint8_t *buf, size_t len); bool HandleCloveI2NPMessage(I2NPMessageType typeID, const uint8_t *payload, size_t len, uint32_t msgID); private: void CreateNewRouter(); void NewRouterInfo(); void UpdateRouterInfo(); void NewNTCP2Keys(); void NewSSU2Keys(); bool IsSSU2Only() const; // SSU2 and no SSU bool Load(); void SaveKeys(); uint16_t SelectRandomPort() const; bool DecryptECIESTunnelBuildRecord(const uint8_t *encrypted, uint8_t *data, size_t clearTextSize); private: i2p::data::LocalRouterInfo m_RouterInfo; i2p::data::PrivateKeys m_Keys; std::shared_ptr m_Decryptor, m_TunnelDecryptor; std::shared_ptr m_ECIESSession; uint64_t m_LastUpdateTime; // in seconds bool m_AcceptsTunnels, m_IsFloodfill; std::chrono::time_point m_StartupTime; uint64_t m_BandwidthLimit; // allowed bandwidth int m_ShareRatio; RouterStatus m_Status, m_StatusV6; RouterError m_Error, m_ErrorV6; int m_NetID; std::mutex m_GarlicMutex; std::unique_ptr m_NTCP2Keys; std::unique_ptr m_SSU2Keys; std::unique_ptr m_NTCP2StaticKeys, m_SSU2StaticKeys; // for ECIESx25519 i2p::crypto::NoiseSymmetricState m_InitialNoiseState, m_CurrentNoiseState; }; extern RouterContext context; } #endif