mirror of https://github.com/oxen-io/lokinet
Merge branch 'master' of https://github.com/neuroscr/loki-network
commit
da6621519d
@ -1,74 +1,76 @@
|
||||
{
|
||||
"editor.formatOnSave": true,
|
||||
"files.associations": {
|
||||
"array": "cpp",
|
||||
"limits": "cpp",
|
||||
"cctype": "cpp",
|
||||
"clocale": "cpp",
|
||||
"cmath": "cpp",
|
||||
"cstdarg": "cpp",
|
||||
"cstddef": "cpp",
|
||||
"cstdio": "cpp",
|
||||
"cstdlib": "cpp",
|
||||
"cstring": "cpp",
|
||||
"ctime": "cpp",
|
||||
"cwchar": "cpp",
|
||||
"cwctype": "cpp",
|
||||
"atomic": "cpp",
|
||||
"*.tcc": "cpp",
|
||||
"bitset": "cpp",
|
||||
"chrono": "cpp",
|
||||
"codecvt": "cpp",
|
||||
"condition_variable": "cpp",
|
||||
"cstdint": "cpp",
|
||||
"deque": "cpp",
|
||||
"list": "cpp",
|
||||
"unordered_map": "cpp",
|
||||
"unordered_set": "cpp",
|
||||
"exception": "cpp",
|
||||
"filesystem": "cpp",
|
||||
"string_view": "cpp",
|
||||
"fstream": "cpp",
|
||||
"functional": "cpp",
|
||||
"initializer_list": "cpp",
|
||||
"iomanip": "cpp",
|
||||
"iosfwd": "cpp",
|
||||
"iostream": "cpp",
|
||||
"istream": "cpp",
|
||||
"memory": "cpp",
|
||||
"mutex": "cpp",
|
||||
"optional": "cpp",
|
||||
"ostream": "cpp",
|
||||
"ratio": "cpp",
|
||||
"sstream": "cpp",
|
||||
"stdexcept": "cpp",
|
||||
"streambuf": "cpp",
|
||||
"system_error": "cpp",
|
||||
"thread": "cpp",
|
||||
"cinttypes": "cpp",
|
||||
"type_traits": "cpp",
|
||||
"tuple": "cpp",
|
||||
"typeindex": "cpp",
|
||||
"typeinfo": "cpp",
|
||||
"utility": "cpp",
|
||||
"__config": "cpp",
|
||||
"__nullptr": "cpp",
|
||||
"algorithm": "cpp",
|
||||
"io": "cpp",
|
||||
"strstream": "cpp",
|
||||
"numeric": "cpp",
|
||||
"valarray": "cpp",
|
||||
"*.ipp": "cpp",
|
||||
"csignal": "cpp",
|
||||
"future": "cpp",
|
||||
"map": "cpp",
|
||||
"vector": "cpp",
|
||||
"new": "cpp",
|
||||
"shared_mutex": "cpp",
|
||||
"complex": "cpp",
|
||||
"variant": "cpp",
|
||||
"any": "cpp",
|
||||
"tuntap.h": "c",
|
||||
"hashtable": "cpp"
|
||||
}
|
||||
"editor.formatOnSave": true,
|
||||
"files.associations": {
|
||||
"array": "cpp",
|
||||
"limits": "cpp",
|
||||
"cctype": "cpp",
|
||||
"clocale": "cpp",
|
||||
"cmath": "cpp",
|
||||
"cstdarg": "cpp",
|
||||
"cstddef": "cpp",
|
||||
"cstdio": "cpp",
|
||||
"cstdlib": "cpp",
|
||||
"cstring": "cpp",
|
||||
"ctime": "cpp",
|
||||
"cwchar": "cpp",
|
||||
"cwctype": "cpp",
|
||||
"atomic": "cpp",
|
||||
"*.tcc": "cpp",
|
||||
"bitset": "cpp",
|
||||
"chrono": "cpp",
|
||||
"codecvt": "cpp",
|
||||
"condition_variable": "cpp",
|
||||
"cstdint": "cpp",
|
||||
"deque": "cpp",
|
||||
"list": "cpp",
|
||||
"unordered_map": "cpp",
|
||||
"unordered_set": "cpp",
|
||||
"exception": "cpp",
|
||||
"filesystem": "cpp",
|
||||
"string_view": "cpp",
|
||||
"fstream": "cpp",
|
||||
"functional": "cpp",
|
||||
"initializer_list": "cpp",
|
||||
"iomanip": "cpp",
|
||||
"iosfwd": "cpp",
|
||||
"iostream": "cpp",
|
||||
"istream": "cpp",
|
||||
"memory": "cpp",
|
||||
"mutex": "cpp",
|
||||
"optional": "cpp",
|
||||
"ostream": "cpp",
|
||||
"ratio": "cpp",
|
||||
"sstream": "cpp",
|
||||
"stdexcept": "cpp",
|
||||
"streambuf": "cpp",
|
||||
"system_error": "cpp",
|
||||
"thread": "cpp",
|
||||
"cinttypes": "cpp",
|
||||
"type_traits": "cpp",
|
||||
"tuple": "cpp",
|
||||
"typeindex": "cpp",
|
||||
"typeinfo": "cpp",
|
||||
"utility": "cpp",
|
||||
"__config": "cpp",
|
||||
"__nullptr": "cpp",
|
||||
"algorithm": "cpp",
|
||||
"io": "cpp",
|
||||
"strstream": "cpp",
|
||||
"numeric": "cpp",
|
||||
"valarray": "cpp",
|
||||
"*.ipp": "cpp",
|
||||
"csignal": "cpp",
|
||||
"future": "cpp",
|
||||
"map": "cpp",
|
||||
"vector": "cpp",
|
||||
"new": "cpp",
|
||||
"shared_mutex": "cpp",
|
||||
"complex": "cpp",
|
||||
"variant": "cpp",
|
||||
"any": "cpp",
|
||||
"tuntap.h": "c",
|
||||
"hashtable": "cpp",
|
||||
"__mutex_base": "cpp",
|
||||
"iterator": "cpp"
|
||||
}
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
#ifndef LLARP_COMMON_H
|
||||
#define LLARP_COMMON_H
|
||||
#ifndef LLARP_COMMON_HPP
|
||||
#define LLARP_COMMON_HPP
|
||||
#ifdef __STRICT_ANSI__
|
||||
#define INLINE __inline__
|
||||
#else
|
@ -1,5 +1,5 @@
|
||||
#ifndef LLARP_ENDIAN_H
|
||||
#define LLARP_ENDIAN_H
|
||||
#ifndef LLARP_ENDIAN_HPP
|
||||
#define LLARP_ENDIAN_HPP
|
||||
|
||||
// adapted from libi2pd
|
||||
|
@ -0,0 +1,6 @@
|
||||
#ifndef LLARP_EXIT_HPP
|
||||
#define LLARP_EXIT_HPP
|
||||
#include <llarp/exit/context.hpp>
|
||||
#include <llarp/exit/policy.hpp>
|
||||
#include <llarp/exit/session.hpp>
|
||||
#endif
|
@ -0,0 +1,54 @@
|
||||
#ifndef LLARP_EXIT_CONTEXT_HPP
|
||||
#define LLARP_EXIT_CONTEXT_HPP
|
||||
#include <llarp/exit/policy.hpp>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <llarp/handlers/exit.hpp>
|
||||
#include <llarp/router.h>
|
||||
|
||||
namespace llarp
|
||||
{
|
||||
namespace exit
|
||||
{
|
||||
/// owner of all the exit endpoints
|
||||
struct Context
|
||||
{
|
||||
using Config_t = std::unordered_multimap< std::string, std::string >;
|
||||
|
||||
Context(llarp_router *r);
|
||||
~Context();
|
||||
|
||||
void
|
||||
Tick(llarp_time_t now);
|
||||
|
||||
void
|
||||
ClearAllEndpoints();
|
||||
|
||||
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;
|
||||
|
||||
/// calculate (pk, tx, rx) for all exit traffic
|
||||
using TrafficStats =
|
||||
std::unordered_map< PubKey, std::pair< uint64_t, uint64_t >,
|
||||
PubKey::Hash >;
|
||||
|
||||
void
|
||||
CalculateExitTraffic(TrafficStats &stats);
|
||||
|
||||
private:
|
||||
llarp_router *m_Router;
|
||||
std::unordered_map< std::string,
|
||||
std::unique_ptr< llarp::handlers::ExitEndpoint > >
|
||||
m_Exits;
|
||||
};
|
||||
} // namespace exit
|
||||
} // namespace llarp
|
||||
|
||||
#endif
|
@ -0,0 +1,100 @@
|
||||
#ifndef LLARP_EXIT_ENDPOINT_HPP
|
||||
#define LLARP_EXIT_ENDPOINT_HPP
|
||||
#include <llarp/time.hpp>
|
||||
#include <llarp/crypto.hpp>
|
||||
#include <llarp/router.h>
|
||||
#include <llarp/path.hpp>
|
||||
|
||||
namespace llarp
|
||||
{
|
||||
namespace handlers
|
||||
{
|
||||
// forward declare
|
||||
struct ExitEndpoint;
|
||||
} // namespace handlers
|
||||
|
||||
namespace exit
|
||||
{
|
||||
/// persistant exit state for 1 identity on the exit node
|
||||
struct Endpoint
|
||||
{
|
||||
Endpoint(const llarp::PubKey& remoteIdent,
|
||||
const llarp::PathID_t& beginPath, bool rewriteDst, huint32_t ip,
|
||||
llarp::handlers::ExitEndpoint* parent);
|
||||
|
||||
~Endpoint();
|
||||
|
||||
/// close ourselves
|
||||
void
|
||||
Close();
|
||||
|
||||
/// return true if we are expired right now
|
||||
bool
|
||||
IsExpired(llarp_time_t now) const;
|
||||
|
||||
bool
|
||||
ExpiresSoon(llarp_time_t now, llarp_time_t dlt = 5000) const;
|
||||
|
||||
/// tick ourself, reset tx/rx rates
|
||||
void
|
||||
Tick(llarp_time_t now);
|
||||
|
||||
/// handle traffic from service node / internet
|
||||
bool
|
||||
SendInboundTraffic(llarp_buffer_t buff);
|
||||
|
||||
/// send traffic to service node / internet
|
||||
/// does ip rewrite here
|
||||
bool
|
||||
SendOutboundTraffic(llarp_buffer_t buf);
|
||||
|
||||
/// 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;
|
||||
}
|
||||
|
||||
uint64_t
|
||||
TxRate() const
|
||||
{
|
||||
return m_TxRate;
|
||||
}
|
||||
|
||||
uint64_t
|
||||
RxRate() const
|
||||
{
|
||||
return m_RxRate;
|
||||
}
|
||||
|
||||
huint32_t
|
||||
LocalIP() const
|
||||
{
|
||||
return m_IP;
|
||||
}
|
||||
|
||||
private:
|
||||
llarp::handlers::ExitEndpoint* m_Parent;
|
||||
llarp::PubKey m_remoteSignKey;
|
||||
llarp::PathID_t m_CurrentPath;
|
||||
llarp::huint32_t m_IP;
|
||||
uint64_t m_TxRate, m_RxRate;
|
||||
bool m_RewriteSource;
|
||||
};
|
||||
} // namespace exit
|
||||
} // namespace llarp
|
||||
|
||||
#endif
|
@ -0,0 +1,26 @@
|
||||
#ifndef LLARP_EXIT_POLICY_HPP
|
||||
#define LLARP_EXIT_POLICY_HPP
|
||||
#include <llarp/bencode.hpp>
|
||||
|
||||
namespace llarp
|
||||
{
|
||||
namespace exit
|
||||
{
|
||||
struct Policy final : public llarp::IBEncodeMessage
|
||||
{
|
||||
~Policy();
|
||||
|
||||
uint64_t proto;
|
||||
uint64_t port;
|
||||
uint64_t drop;
|
||||
|
||||
bool
|
||||
DecodeKey(llarp_buffer_t k, llarp_buffer_t* val) override;
|
||||
|
||||
bool
|
||||
BEncode(llarp_buffer_t* buf) const override;
|
||||
};
|
||||
} // namespace exit
|
||||
} // namespace llarp
|
||||
|
||||
#endif
|
@ -0,0 +1,53 @@
|
||||
#ifndef LLARP_EXIT_SESSION_HPP
|
||||
#define LLARP_EXIT_SESSION_HPP
|
||||
#include <llarp/pathbuilder.hpp>
|
||||
#include <llarp/ip.hpp>
|
||||
|
||||
namespace llarp
|
||||
{
|
||||
namespace exit
|
||||
{
|
||||
/// a persisiting exit session with an exit router
|
||||
struct BaseSession : public llarp::path::Builder
|
||||
{
|
||||
BaseSession(const llarp::RouterID& exitRouter,
|
||||
std::function< bool(llarp_buffer_t) > writepkt,
|
||||
llarp_router* r, size_t numpaths, size_t hoplen);
|
||||
|
||||
~BaseSession();
|
||||
|
||||
bool
|
||||
SelectHop(llarp_nodedb* db, const RouterContact& prev, RouterContact& cur,
|
||||
size_t hop, llarp::path::PathRole roles) override;
|
||||
|
||||
bool
|
||||
ShouldBuildMore(llarp_time_t now) const override;
|
||||
|
||||
void
|
||||
HandlePathBuilt(llarp::path::Path* p) override;
|
||||
|
||||
bool
|
||||
SendUpstreamTraffic(llarp::net::IPv4Packet pkt);
|
||||
|
||||
protected:
|
||||
llarp::RouterID m_ExitRouter;
|
||||
std::function< bool(llarp_buffer_t) > m_WritePacket;
|
||||
|
||||
bool
|
||||
HandleTrafficDrop(llarp::path::Path* p, const llarp::PathID_t& path,
|
||||
uint64_t s);
|
||||
|
||||
bool
|
||||
HandleGotExit(llarp::path::Path* p, llarp_time_t b);
|
||||
|
||||
bool
|
||||
HandleTraffic(llarp::path::Path* p, llarp_buffer_t buf);
|
||||
|
||||
private:
|
||||
llarp::SecretKey m_ExitIdentity;
|
||||
};
|
||||
|
||||
} // namespace exit
|
||||
} // namespace llarp
|
||||
|
||||
#endif
|
@ -0,0 +1,143 @@
|
||||
#ifndef LLARP_HANDLERS_EXIT_HPP
|
||||
#define LLARP_HANDLERS_EXIT_HPP
|
||||
|
||||
#include <llarp/handlers/tun.hpp>
|
||||
#include <llarp/exit/endpoint.hpp>
|
||||
#include <unordered_map>
|
||||
|
||||
namespace llarp
|
||||
{
|
||||
namespace handlers
|
||||
{
|
||||
struct ExitEndpoint
|
||||
{
|
||||
ExitEndpoint(const std::string& name, llarp_router* r);
|
||||
~ExitEndpoint();
|
||||
|
||||
void
|
||||
Tick(llarp_time_t now);
|
||||
|
||||
bool
|
||||
SetOption(const std::string& k, const std::string& v);
|
||||
|
||||
std::string
|
||||
Name() const;
|
||||
|
||||
bool
|
||||
AllocateNewExit(const llarp::PubKey pk, const llarp::PathID_t& path,
|
||||
bool permitInternet);
|
||||
|
||||
llarp::exit::Endpoint*
|
||||
FindEndpointByPath(const llarp::PathID_t& path);
|
||||
|
||||
llarp::exit::Endpoint*
|
||||
FindEndpointByIP(huint32_t ip);
|
||||
|
||||
bool
|
||||
UpdateEndpointPath(const llarp::PubKey& remote,
|
||||
const llarp::PathID_t& next);
|
||||
|
||||
/// handle ip packet from outside
|
||||
void
|
||||
OnInetPacket(llarp_buffer_t buf);
|
||||
|
||||
llarp_router*
|
||||
Router();
|
||||
|
||||
llarp_crypto*
|
||||
Crypto();
|
||||
|
||||
template < typename Stats >
|
||||
void
|
||||
CalculateTrafficStats(Stats& stats)
|
||||
{
|
||||
auto itr = m_ActiveExits.begin();
|
||||
while(itr != m_ActiveExits.end())
|
||||
{
|
||||
stats[itr->first].first += itr->second->TxRate();
|
||||
stats[itr->first].second += itr->second->RxRate();
|
||||
++itr;
|
||||
}
|
||||
}
|
||||
|
||||
/// DO NOT CALL ME
|
||||
void
|
||||
DelEndpointInfo(const llarp::PathID_t& path);
|
||||
|
||||
/// DO NOT CALL ME
|
||||
void
|
||||
RemoveExit(const llarp::exit::Endpoint* ep);
|
||||
|
||||
bool
|
||||
QueueOutboundTraffic(llarp_buffer_t buf);
|
||||
|
||||
/// sets up networking and starts traffic
|
||||
bool
|
||||
Start();
|
||||
|
||||
bool
|
||||
HasLocalMappedAddrFor(const llarp::PubKey& pk) const;
|
||||
|
||||
huint32_t
|
||||
GetIfAddr() const;
|
||||
|
||||
void
|
||||
FlushInbound();
|
||||
|
||||
private:
|
||||
huint32_t
|
||||
GetIPForIdent(const llarp::PubKey pk);
|
||||
|
||||
huint32_t
|
||||
AllocateNewAddress();
|
||||
|
||||
void
|
||||
MarkIPActive(llarp::huint32_t ip);
|
||||
|
||||
void
|
||||
KickIdentOffExit(const llarp::PubKey& pk);
|
||||
|
||||
llarp_router* m_Router;
|
||||
bool m_ShouldInitTun;
|
||||
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,
|
||||
std::unique_ptr< llarp::exit::Endpoint >,
|
||||
llarp::PubKey::Hash >
|
||||
m_ActiveExits;
|
||||
|
||||
using KeyMap_t = std::unordered_map< llarp::PubKey, llarp::huint32_t,
|
||||
llarp::PubKey::Hash >;
|
||||
|
||||
KeyMap_t m_KeyToIP;
|
||||
|
||||
std::unordered_map< llarp::huint32_t, llarp::PubKey,
|
||||
llarp::huint32_t::Hash >
|
||||
m_IPToKey;
|
||||
|
||||
huint32_t m_IfAddr;
|
||||
huint32_t m_HigestAddr;
|
||||
huint32_t m_NextAddr;
|
||||
|
||||
std::unordered_map< llarp::huint32_t, llarp_time_t,
|
||||
llarp::huint32_t::Hash >
|
||||
m_IPActivity;
|
||||
|
||||
llarp_tun_io m_Tun;
|
||||
|
||||
using Pkt_t = llarp::net::IPv4Packet;
|
||||
using PacketQueue_t =
|
||||
llarp::util::CoDelQueue< Pkt_t, Pkt_t::GetTime, Pkt_t::PutTime,
|
||||
Pkt_t::CompareOrder, Pkt_t::GetNow,
|
||||
llarp::util::DummyMutex,
|
||||
llarp::util::DummyLock, 5, 100, 1024 >;
|
||||
|
||||
/// internet to llarp packet queue
|
||||
PacketQueue_t m_InetToNetwork;
|
||||
};
|
||||
} // namespace handlers
|
||||
} // namespace llarp
|
||||
#endif
|
@ -1,8 +1,8 @@
|
||||
#ifndef LLARP_LOGIC_H
|
||||
#define LLARP_LOGIC_H
|
||||
#ifndef LLARP_LOGIC_HPP
|
||||
#define LLARP_LOGIC_HPP
|
||||
#include <llarp/mem.h>
|
||||
#include <llarp/threadpool.h>
|
||||
#include <llarp/timer.h>
|
||||
#include <llarp/timer.hpp>
|
||||
|
||||
struct llarp_logic
|
||||
{
|
@ -0,0 +1,225 @@
|
||||
#ifndef LLARP_MESSAGES_EXIT_HPP
|
||||
#define LLARP_MESSAGES_EXIT_HPP
|
||||
#include <llarp/routing/message.hpp>
|
||||
#include <llarp/exit/policy.hpp>
|
||||
#include <vector>
|
||||
#include <llarp/crypto.hpp>
|
||||
|
||||
namespace llarp
|
||||
{
|
||||
namespace routing
|
||||
{
|
||||
struct ObtainExitMessage final : public IMessage
|
||||
{
|
||||
std::vector< llarp::exit::Policy > B;
|
||||
uint64_t E;
|
||||
llarp::PubKey I;
|
||||
uint64_t T;
|
||||
std::vector< llarp::exit::Policy > W;
|
||||
llarp_time_t X;
|
||||
llarp::Signature Z;
|
||||
|
||||
ObtainExitMessage() : IMessage()
|
||||
{
|
||||
}
|
||||
|
||||
~ObtainExitMessage()
|
||||
{
|
||||
}
|
||||
|
||||
ObtainExitMessage&
|
||||
operator=(const ObtainExitMessage& other);
|
||||
|
||||
/// populates I and signs
|
||||
bool
|
||||
Sign(llarp_crypto* c, const llarp::SecretKey& sk);
|
||||
|
||||
bool
|
||||
Verify(llarp_crypto* c) const;
|
||||
|
||||
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 GrantExitMessage final : public IMessage
|
||||
{
|
||||
using Nonce_t = llarp::AlignedBuffer< 16 >;
|
||||
uint64_t T;
|
||||
Nonce_t Y;
|
||||
llarp::Signature Z;
|
||||
GrantExitMessage() : IMessage()
|
||||
{
|
||||
}
|
||||
|
||||
~GrantExitMessage()
|
||||
{
|
||||
}
|
||||
|
||||
GrantExitMessage&
|
||||
operator=(const GrantExitMessage& other);
|
||||
|
||||
bool
|
||||
BEncode(llarp_buffer_t* buf) const override;
|
||||
|
||||
bool
|
||||
Sign(llarp_crypto* c, const llarp::SecretKey& sk);
|
||||
|
||||
bool
|
||||
Verify(llarp_crypto* c, const llarp::PubKey& pk) const;
|
||||
|
||||
bool
|
||||
DecodeKey(llarp_buffer_t key, llarp_buffer_t* buf) override;
|
||||
|
||||
bool
|
||||
HandleMessage(IMessageHandler* h, llarp_router* r) const override;
|
||||
};
|
||||
|
||||
struct RejectExitMessage final : public IMessage
|
||||
{
|
||||
using Nonce_t = llarp::AlignedBuffer< 16 >;
|
||||
uint64_t B;
|
||||
std::vector< llarp::exit::Policy > R;
|
||||
uint64_t T;
|
||||
Nonce_t Y;
|
||||
llarp::Signature Z;
|
||||
|
||||
RejectExitMessage() : IMessage()
|
||||
{
|
||||
}
|
||||
|
||||
~RejectExitMessage()
|
||||
{
|
||||
}
|
||||
|
||||
RejectExitMessage&
|
||||
operator=(const RejectExitMessage& 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;
|
||||
|
||||
bool
|
||||
DecodeKey(llarp_buffer_t key, llarp_buffer_t* buf) override;
|
||||
|
||||
bool
|
||||
HandleMessage(IMessageHandler* h, llarp_router* r) const override;
|
||||
};
|
||||
|
||||
struct UpdateExitVerifyMessage final : public IMessage
|
||||
{
|
||||
using Nonce_t = llarp::AlignedBuffer< 16 >;
|
||||
uint64_t T;
|
||||
Nonce_t Y;
|
||||
llarp::Signature Z;
|
||||
|
||||
UpdateExitVerifyMessage() : IMessage()
|
||||
{
|
||||
}
|
||||
|
||||
~UpdateExitVerifyMessage()
|
||||
{
|
||||
}
|
||||
|
||||
UpdateExitVerifyMessage&
|
||||
operator=(const UpdateExitVerifyMessage& 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;
|
||||
|
||||
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
|
||||
{
|
||||
using Nonce_t = llarp::AlignedBuffer< 16 >;
|
||||
llarp::PathID_t P;
|
||||
uint64_t T;
|
||||
Nonce_t Y;
|
||||
llarp::Signature Z;
|
||||
|
||||
UpdateExitMessage() : IMessage()
|
||||
{
|
||||
}
|
||||
|
||||
~UpdateExitMessage()
|
||||
{
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
bool
|
||||
DecodeKey(llarp_buffer_t key, llarp_buffer_t* buf) override;
|
||||
|
||||
bool
|
||||
HandleMessage(IMessageHandler* h, llarp_router* r) const override;
|
||||
};
|
||||
|
||||
struct CloseExitMessage final : public IMessage
|
||||
{
|
||||
using Nonce_t = llarp::AlignedBuffer< 16 >;
|
||||
|
||||
Nonce_t Y;
|
||||
llarp::Signature Z;
|
||||
|
||||
CloseExitMessage() : IMessage()
|
||||
{
|
||||
}
|
||||
|
||||
~CloseExitMessage()
|
||||
{
|
||||
}
|
||||
|
||||
CloseExitMessage&
|
||||
operator=(const CloseExitMessage& other);
|
||||
|
||||
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;
|
||||
|
||||
bool
|
||||
Sign(llarp_crypto* c, const llarp::SecretKey& sk);
|
||||
|
||||
bool
|
||||
Verify(llarp_crypto* c, const llarp::PubKey& pk) const;
|
||||
};
|
||||
|
||||
} // namespace routing
|
||||
} // namespace llarp
|
||||
|
||||
#endif
|
@ -0,0 +1,44 @@
|
||||
#ifndef LLARP_MESSAGES_TRANSFER_TRAFFIC_HPP
|
||||
#define LLARP_MESSAGES_TRANSFER_TRAFFIC_HPP
|
||||
#include <llarp/routing/message.hpp>
|
||||
#include <llarp/crypto.hpp>
|
||||
#include <vector>
|
||||
|
||||
namespace llarp
|
||||
{
|
||||
namespace routing
|
||||
{
|
||||
constexpr size_t MaxExitMTU = 1500;
|
||||
struct TransferTrafficMessage final : public IMessage
|
||||
{
|
||||
using Nonce_t = AlignedBuffer< 16 >;
|
||||
|
||||
std::vector< byte_t > X;
|
||||
Nonce_t Y;
|
||||
llarp::Signature Z;
|
||||
|
||||
TransferTrafficMessage&
|
||||
operator=(const TransferTrafficMessage& other);
|
||||
|
||||
bool
|
||||
PutBuffer(llarp_buffer_t buf);
|
||||
|
||||
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;
|
||||
|
||||
bool
|
||||
DecodeKey(llarp_buffer_t k, llarp_buffer_t* val) override;
|
||||
|
||||
bool
|
||||
HandleMessage(IMessageHandler* h, llarp_router* r) const override;
|
||||
};
|
||||
} // namespace routing
|
||||
} // namespace llarp
|
||||
|
||||
#endif
|
@ -1,5 +1,5 @@
|
||||
#ifndef LLARP_PROTO_H
|
||||
#define LLARP_PROTO_H
|
||||
#ifndef LLARP_PROTO_HPP
|
||||
#define LLARP_PROTO_HPP
|
||||
|
||||
#ifndef LLARP_PROTO_VERSION
|
||||
#define LLARP_PROTO_VERSION (0)
|
@ -1,8 +0,0 @@
|
||||
#ifndef LLARP_TIME_H
|
||||
#define LLARP_TIME_H
|
||||
#include <llarp/types.h>
|
||||
|
||||
llarp_time_t
|
||||
llarp_time_now_ms();
|
||||
|
||||
#endif
|
@ -1,11 +1,16 @@
|
||||
#ifndef LLARP_TIME_HPP
|
||||
#define LLARP_TIME_HPP
|
||||
|
||||
#include <llarp/types.hpp>
|
||||
|
||||
#include <chrono>
|
||||
|
||||
namespace llarp
|
||||
{
|
||||
typedef std::chrono::system_clock Clock_t;
|
||||
}
|
||||
using Clock_t = std::chrono::system_clock;
|
||||
|
||||
llarp_time_t
|
||||
time_now_ms();
|
||||
} // namespace llarp
|
||||
|
||||
#endif
|
||||
|
@ -1,8 +1,9 @@
|
||||
#ifndef LLARP_TIMER_H
|
||||
#define LLARP_TIMER_H
|
||||
#include <llarp/common.h>
|
||||
#ifndef LLARP_TIMER_HPP
|
||||
#define LLARP_TIMER_HPP
|
||||
|
||||
#include <llarp/common.hpp>
|
||||
#include <llarp/threadpool.h>
|
||||
#include <llarp/time.h>
|
||||
#include <llarp/time.hpp>
|
||||
|
||||
/** called with userptr, original timeout, left */
|
||||
typedef void (*llarp_timer_handler_func)(void *, uint64_t, uint64_t);
|
@ -1,9 +0,0 @@
|
||||
#ifndef LLARP_TYPES_H
|
||||
#define LLARP_TYPES_H
|
||||
#include <stdint.h>
|
||||
|
||||
typedef uint8_t llarp_proto_version_t;
|
||||
typedef uint64_t llarp_time_t;
|
||||
typedef uint64_t llarp_seconds_t;
|
||||
|
||||
#endif
|
@ -0,0 +1,9 @@
|
||||
#ifndef LLARP_TYPES_H
|
||||
#define LLARP_TYPES_H
|
||||
#include <cstdint>
|
||||
|
||||
using llarp_proto_version_t = std::uint8_t;
|
||||
using llarp_time_t = std::uint64_t;
|
||||
using llarp_seconds_t = std::uint64_t;
|
||||
|
||||
#endif
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,85 @@
|
||||
#include <llarp/messages/exit.hpp>
|
||||
#include <llarp/routing/handler.hpp>
|
||||
|
||||
namespace llarp
|
||||
{
|
||||
namespace routing
|
||||
{
|
||||
bool
|
||||
CloseExitMessage::BEncode(llarp_buffer_t* buf) const
|
||||
{
|
||||
if(!bencode_start_dict(buf))
|
||||
return false;
|
||||
if(!BEncodeWriteDictMsgType(buf, "A", "C"))
|
||||
return false;
|
||||
if(!BEncodeWriteDictInt("S", S, buf))
|
||||
return false;
|
||||
if(!BEncodeWriteDictInt("V", version, buf))
|
||||
return false;
|
||||
if(!BEncodeWriteDictEntry("Y", Y, buf))
|
||||
return false;
|
||||
if(!BEncodeWriteDictEntry("Z", Z, buf))
|
||||
return false;
|
||||
return bencode_end(buf);
|
||||
}
|
||||
|
||||
bool
|
||||
CloseExitMessage::DecodeKey(llarp_buffer_t k, llarp_buffer_t* buf)
|
||||
{
|
||||
bool read = false;
|
||||
if(!BEncodeMaybeReadDictInt("S", S, read, k, buf))
|
||||
return false;
|
||||
if(!BEncodeMaybeReadDictInt("V", version, read, k, buf))
|
||||
return false;
|
||||
if(!BEncodeMaybeReadDictEntry("Y", Y, read, k, buf))
|
||||
return false;
|
||||
if(!BEncodeMaybeReadDictEntry("Z", Z, read, k, buf))
|
||||
return false;
|
||||
return read;
|
||||
}
|
||||
|
||||
bool
|
||||
CloseExitMessage::Verify(llarp_crypto* c, const llarp::PubKey& pk) const
|
||||
{
|
||||
byte_t tmp[512] = {0};
|
||||
auto buf = llarp::StackBuffer< decltype(tmp) >(tmp);
|
||||
CloseExitMessage copy;
|
||||
copy = *this;
|
||||
copy.Z.Zero();
|
||||
if(!copy.BEncode(&buf))
|
||||
return false;
|
||||
buf.sz = buf.cur - buf.base;
|
||||
return c->verify(pk, buf, Z);
|
||||
}
|
||||
|
||||
bool
|
||||
CloseExitMessage::Sign(llarp_crypto* c, const llarp::SecretKey& sk)
|
||||
{
|
||||
byte_t tmp[512] = {0};
|
||||
auto buf = llarp::StackBuffer< decltype(tmp) >(tmp);
|
||||
Z.Zero();
|
||||
Y.Randomize();
|
||||
if(!BEncode(&buf))
|
||||
return false;
|
||||
buf.sz = buf.cur - buf.base;
|
||||
return c->sign(Z, sk, buf);
|
||||
}
|
||||
|
||||
CloseExitMessage&
|
||||
CloseExitMessage::operator=(const CloseExitMessage& other)
|
||||
{
|
||||
S = other.S;
|
||||
version = other.version;
|
||||
Y = other.Y;
|
||||
Z = other.Z;
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool
|
||||
CloseExitMessage::HandleMessage(IMessageHandler* h, llarp_router* r) const
|
||||
{
|
||||
return h->HandleCloseExitMessage(this, r);
|
||||
}
|
||||
|
||||
} // namespace routing
|
||||
} // namespace llarp
|
@ -0,0 +1,97 @@
|
||||
#include <llarp/exit/context.hpp>
|
||||
|
||||
namespace llarp
|
||||
{
|
||||
namespace exit
|
||||
{
|
||||
Context::Context(llarp_router* r) : m_Router(r)
|
||||
{
|
||||
}
|
||||
Context::~Context()
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
Context::Tick(llarp_time_t now)
|
||||
{
|
||||
auto itr = m_Exits.begin();
|
||||
while(itr != m_Exits.end())
|
||||
{
|
||||
itr->second->Tick(now);
|
||||
++itr;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Context::CalculateExitTraffic(TrafficStats& stats)
|
||||
{
|
||||
auto itr = m_Exits.begin();
|
||||
while(itr != m_Exits.end())
|
||||
{
|
||||
itr->second->CalculateTrafficStats(stats);
|
||||
++itr;
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
// check for duplicate exit by name
|
||||
{
|
||||
auto itr = m_Exits.find(name);
|
||||
if(itr != m_Exits.end())
|
||||
{
|
||||
llarp::LogError("duplicate exit with name ", name);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
std::unique_ptr< llarp::handlers::ExitEndpoint > endpoint;
|
||||
// make new endpoint
|
||||
endpoint.reset(new llarp::handlers::ExitEndpoint(name, m_Router));
|
||||
// configure
|
||||
{
|
||||
auto itr = conf.begin();
|
||||
while(itr != conf.end())
|
||||
{
|
||||
if(!endpoint->SetOption(itr->first, itr->second))
|
||||
return false;
|
||||
++itr;
|
||||
}
|
||||
}
|
||||
// add endpoint
|
||||
if(!endpoint->Start())
|
||||
return false;
|
||||
m_Exits.emplace(name, std::move(endpoint));
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace exit
|
||||
} // namespace llarp
|
@ -0,0 +1,127 @@
|
||||
#include <llarp/exit/endpoint.hpp>
|
||||
#include "router.hpp"
|
||||
|
||||
namespace llarp
|
||||
{
|
||||
namespace exit
|
||||
{
|
||||
Endpoint::Endpoint(const llarp::PubKey& remoteIdent,
|
||||
const llarp::PathID_t& beginPath, bool rewriteIP,
|
||||
huint32_t ip, llarp::handlers::ExitEndpoint* parent)
|
||||
: m_Parent(parent)
|
||||
, m_remoteSignKey(remoteIdent)
|
||||
, m_CurrentPath(beginPath)
|
||||
, m_IP(ip)
|
||||
, m_RewriteSource(rewriteIP)
|
||||
{
|
||||
}
|
||||
|
||||
Endpoint::~Endpoint()
|
||||
{
|
||||
m_Parent->DelEndpointInfo(m_CurrentPath);
|
||||
}
|
||||
|
||||
void
|
||||
Endpoint::Close()
|
||||
{
|
||||
m_Parent->RemoveExit(this);
|
||||
}
|
||||
|
||||
bool
|
||||
Endpoint::UpdateLocalPath(const llarp::PathID_t& nextPath)
|
||||
{
|
||||
if(!m_Parent->UpdateEndpointPath(m_remoteSignKey, nextPath))
|
||||
return false;
|
||||
m_CurrentPath = nextPath;
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
Endpoint::Tick(llarp_time_t now)
|
||||
{
|
||||
(void)now;
|
||||
m_RxRate = 0;
|
||||
m_TxRate = 0;
|
||||
}
|
||||
|
||||
bool
|
||||
Endpoint::IsExpired(llarp_time_t now) const
|
||||
{
|
||||
auto path = GetCurrentPath();
|
||||
if(path)
|
||||
{
|
||||
return path->Expired(now);
|
||||
}
|
||||
// if we don't have an underlying path we are considered expired
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
Endpoint::ExpiresSoon(llarp_time_t now, llarp_time_t dlt) const
|
||||
{
|
||||
auto path = GetCurrentPath();
|
||||
if(path)
|
||||
return path->ExpiresSoon(now, dlt);
|
||||
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);
|
||||
if(!m_Parent->QueueOutboundTraffic(pkt.Buffer()))
|
||||
{
|
||||
llarp::LogError("failed to queue outbound traffic");
|
||||
return false;
|
||||
}
|
||||
m_TxRate += buf.sz;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
Endpoint::SendInboundTraffic(llarp_buffer_t buf)
|
||||
{
|
||||
auto path = GetCurrentPath();
|
||||
if(path)
|
||||
{
|
||||
llarp::net::IPv4Packet pkt;
|
||||
if(!pkt.Load(buf))
|
||||
return false;
|
||||
|
||||
huint32_t src;
|
||||
if(m_RewriteSource)
|
||||
src = m_Parent->GetIfAddr();
|
||||
else
|
||||
src = pkt.src();
|
||||
pkt.UpdateIPv4PacketOnDst(src, m_IP);
|
||||
|
||||
llarp::routing::TransferTrafficMessage msg;
|
||||
if(!msg.PutBuffer(pkt.Buffer()))
|
||||
return false;
|
||||
msg.S = path->NextSeqNo();
|
||||
if(!msg.Sign(m_Parent->Crypto(), m_Parent->Router()->identity))
|
||||
return false;
|
||||
if(!path->SendRoutingMessage(&msg, m_Parent->Router()))
|
||||
return false;
|
||||
m_RxRate += buf.sz;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
llarp::path::IHopHandler*
|
||||
Endpoint::GetCurrentPath() const
|
||||
{
|
||||
auto router = m_Parent->Router();
|
||||
return router->paths.GetByUpstream(router->pubkey(), m_CurrentPath);
|
||||
}
|
||||
} // namespace exit
|
||||
} // namespace llarp
|
@ -0,0 +1,90 @@
|
||||
#include <llarp/messages/exit.hpp>
|
||||
#include <llarp/routing/handler.hpp>
|
||||
|
||||
namespace llarp
|
||||
{
|
||||
namespace routing
|
||||
{
|
||||
bool
|
||||
GrantExitMessage::BEncode(llarp_buffer_t* buf) const
|
||||
{
|
||||
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;
|
||||
if(!BEncodeWriteDictEntry("Y", Y, buf))
|
||||
return false;
|
||||
if(!BEncodeWriteDictEntry("Z", Z, buf))
|
||||
return false;
|
||||
return bencode_end(buf);
|
||||
}
|
||||
|
||||
bool
|
||||
GrantExitMessage::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;
|
||||
if(!BEncodeMaybeReadDictEntry("Y", Y, read, k, buf))
|
||||
return false;
|
||||
if(!BEncodeMaybeReadDictEntry("Z", Z, read, k, buf))
|
||||
return false;
|
||||
return read;
|
||||
}
|
||||
|
||||
bool
|
||||
GrantExitMessage::Verify(llarp_crypto* c, const llarp::PubKey& pk) const
|
||||
{
|
||||
byte_t tmp[512] = {0};
|
||||
auto buf = llarp::StackBuffer< decltype(tmp) >(tmp);
|
||||
GrantExitMessage copy;
|
||||
copy = *this;
|
||||
copy.Z.Zero();
|
||||
if(!copy.BEncode(&buf))
|
||||
return false;
|
||||
buf.sz = buf.cur - buf.base;
|
||||
return c->verify(pk, buf, Z);
|
||||
}
|
||||
|
||||
bool
|
||||
GrantExitMessage::Sign(llarp_crypto* c, const llarp::SecretKey& sk)
|
||||
{
|
||||
byte_t tmp[512] = {0};
|
||||
auto buf = llarp::StackBuffer< decltype(tmp) >(tmp);
|
||||
Z.Zero();
|
||||
Y.Randomize();
|
||||
if(!BEncode(&buf))
|
||||
return false;
|
||||
buf.sz = buf.cur - buf.base;
|
||||
return c->sign(Z, sk, buf);
|
||||
}
|
||||
|
||||
GrantExitMessage&
|
||||
GrantExitMessage::operator=(const GrantExitMessage& other)
|
||||
{
|
||||
S = other.S;
|
||||
T = other.T;
|
||||
version = other.version;
|
||||
Y = other.Y;
|
||||
Z = other.Z;
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool
|
||||
GrantExitMessage::HandleMessage(IMessageHandler* h, llarp_router* r) const
|
||||
{
|
||||
return h->HandleGrantExitMessage(this, r);
|
||||
}
|
||||
|
||||
} // namespace routing
|
||||
} // namespace llarp
|
@ -0,0 +1,112 @@
|
||||
#include <llarp/messages/exit.hpp>
|
||||
#include <llarp/routing/handler.hpp>
|
||||
#include <llarp/link_layer.hpp>
|
||||
|
||||
namespace llarp
|
||||
{
|
||||
namespace routing
|
||||
{
|
||||
ObtainExitMessage&
|
||||
ObtainExitMessage::operator=(const ObtainExitMessage& other)
|
||||
{
|
||||
B = other.B;
|
||||
E = other.E;
|
||||
I = other.I;
|
||||
T = other.T;
|
||||
W = other.W;
|
||||
X = other.X;
|
||||
version = other.version;
|
||||
S = other.S;
|
||||
Z = other.Z;
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool
|
||||
ObtainExitMessage::Sign(llarp_crypto* c, const llarp::SecretKey& sk)
|
||||
{
|
||||
byte_t tmp[1024] = {0};
|
||||
auto buf = llarp::StackBuffer< decltype(tmp) >(tmp);
|
||||
I = llarp::seckey_topublic(sk);
|
||||
Z.Zero();
|
||||
if(!BEncode(&buf))
|
||||
return false;
|
||||
buf.sz = buf.cur - buf.base;
|
||||
return c->sign(Z, sk, buf);
|
||||
}
|
||||
|
||||
bool
|
||||
ObtainExitMessage::Verify(llarp_crypto* c) const
|
||||
{
|
||||
byte_t tmp[1024] = {0};
|
||||
auto buf = llarp::StackBuffer< decltype(tmp) >(tmp);
|
||||
ObtainExitMessage copy;
|
||||
copy = *this;
|
||||
copy.Z.Zero();
|
||||
if(!copy.BEncode(&buf))
|
||||
return false;
|
||||
// rewind buffer
|
||||
buf.sz = buf.cur - buf.base;
|
||||
return c->verify(I, buf, Z);
|
||||
}
|
||||
|
||||
bool
|
||||
ObtainExitMessage::BEncode(llarp_buffer_t* buf) const
|
||||
{
|
||||
if(!bencode_start_dict(buf))
|
||||
return false;
|
||||
if(!BEncodeWriteDictMsgType(buf, "A", "O"))
|
||||
return false;
|
||||
if(!BEncodeWriteDictArray("B", B, buf))
|
||||
return false;
|
||||
if(!BEncodeWriteDictInt("E", E, buf))
|
||||
return false;
|
||||
if(!BEncodeWriteDictEntry("I", I, 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(!BEncodeWriteDictArray("W", W, buf))
|
||||
return false;
|
||||
if(!BEncodeWriteDictInt("X", X, buf))
|
||||
return false;
|
||||
if(!BEncodeWriteDictEntry("Z", Z, buf))
|
||||
return false;
|
||||
return bencode_end(buf);
|
||||
}
|
||||
|
||||
bool
|
||||
ObtainExitMessage::DecodeKey(llarp_buffer_t k, llarp_buffer_t* buf)
|
||||
{
|
||||
bool read = false;
|
||||
if(!BEncodeMaybeReadDictList("B", B, read, k, buf))
|
||||
return false;
|
||||
if(!BEncodeMaybeReadDictInt("E", E, read, k, buf))
|
||||
return false;
|
||||
if(!BEncodeMaybeReadDictEntry("I", I, read, k, buf))
|
||||
return 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(!BEncodeMaybeReadDictList("W", W, read, k, buf))
|
||||
return false;
|
||||
if(!BEncodeMaybeReadDictInt("X", X, read, k, buf))
|
||||
return false;
|
||||
if(!BEncodeMaybeReadDictEntry("Z", Z, read, k, buf))
|
||||
return false;
|
||||
return read;
|
||||
}
|
||||
|
||||
bool
|
||||
ObtainExitMessage::HandleMessage(IMessageHandler* h, llarp_router* r) const
|
||||
{
|
||||
return h->HandleObtainExitMessage(this, r);
|
||||
}
|
||||
|
||||
} // namespace routing
|
||||
} // namespace llarp
|
@ -0,0 +1,43 @@
|
||||
#include <llarp/exit/policy.hpp>
|
||||
|
||||
namespace llarp
|
||||
{
|
||||
namespace exit
|
||||
{
|
||||
Policy::~Policy()
|
||||
{
|
||||
}
|
||||
|
||||
bool
|
||||
Policy::BEncode(llarp_buffer_t *buf) const
|
||||
{
|
||||
if(!bencode_start_dict(buf))
|
||||
return false;
|
||||
if(!BEncodeWriteDictInt("a", proto, buf))
|
||||
return false;
|
||||
if(!BEncodeWriteDictInt("b", port, buf))
|
||||
return false;
|
||||
if(!BEncodeWriteDictInt("d", drop, buf))
|
||||
return false;
|
||||
if(!BEncodeWriteDictInt("v", version, buf))
|
||||
return false;
|
||||
return bencode_end(buf);
|
||||
}
|
||||
|
||||
bool
|
||||
Policy::DecodeKey(llarp_buffer_t k, llarp_buffer_t *buf)
|
||||
{
|
||||
bool read = false;
|
||||
if(!BEncodeMaybeReadDictInt("a", proto, read, k, buf))
|
||||
return false;
|
||||
if(!BEncodeMaybeReadDictInt("b", port, read, k, buf))
|
||||
return false;
|
||||
if(!BEncodeMaybeReadDictInt("d", drop, read, k, buf))
|
||||
return false;
|
||||
if(!BEncodeMaybeReadDictInt("v", version, read, k, buf))
|
||||
return false;
|
||||
return read;
|
||||
}
|
||||
|
||||
} // namespace exit
|
||||
} // namespace llarp
|
@ -0,0 +1,100 @@
|
||||
#include <llarp/messages/exit.hpp>
|
||||
#include <llarp/routing/handler.hpp>
|
||||
|
||||
namespace llarp
|
||||
{
|
||||
namespace routing
|
||||
{
|
||||
bool
|
||||
RejectExitMessage::BEncode(llarp_buffer_t* buf) const
|
||||
{
|
||||
if(!bencode_start_dict(buf))
|
||||
return false;
|
||||
if(!BEncodeWriteDictMsgType(buf, "A", "J"))
|
||||
return false;
|
||||
if(!BEncodeWriteDictInt("B", B, buf))
|
||||
return false;
|
||||
if(!BEncodeWriteDictList("R", R, 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("Y", Y, buf))
|
||||
return false;
|
||||
if(!BEncodeWriteDictEntry("Z", Z, buf))
|
||||
return false;
|
||||
return bencode_end(buf);
|
||||
}
|
||||
|
||||
bool
|
||||
RejectExitMessage::DecodeKey(llarp_buffer_t k, llarp_buffer_t* buf)
|
||||
{
|
||||
bool read = false;
|
||||
if(!BEncodeMaybeReadDictInt("B", B, read, k, buf))
|
||||
return false;
|
||||
if(!BEncodeMaybeReadDictList("R", R, read, k, buf))
|
||||
return 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("Y", Y, read, k, buf))
|
||||
return false;
|
||||
if(!BEncodeMaybeReadDictEntry("Z", Z, read, k, buf))
|
||||
return false;
|
||||
return read;
|
||||
}
|
||||
|
||||
RejectExitMessage&
|
||||
RejectExitMessage::operator=(const RejectExitMessage& other)
|
||||
{
|
||||
B = other.B;
|
||||
R = other.R;
|
||||
S = other.S;
|
||||
T = other.T;
|
||||
version = other.version;
|
||||
Y = other.Y;
|
||||
Z = other.Z;
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool
|
||||
RejectExitMessage::Sign(llarp_crypto* c, const llarp::SecretKey& sk)
|
||||
{
|
||||
byte_t tmp[512] = {0};
|
||||
auto buf = llarp::StackBuffer< decltype(tmp) >(tmp);
|
||||
Z.Zero();
|
||||
Y.Randomize();
|
||||
if(!BEncode(&buf))
|
||||
return false;
|
||||
buf.sz = buf.cur - buf.base;
|
||||
return c->sign(Z, sk, buf);
|
||||
}
|
||||
|
||||
bool
|
||||
RejectExitMessage::Verify(llarp_crypto* c, const llarp::PubKey& pk) const
|
||||
{
|
||||
byte_t tmp[512] = {0};
|
||||
auto buf = llarp::StackBuffer< decltype(tmp) >(tmp);
|
||||
RejectExitMessage copy;
|
||||
copy = *this;
|
||||
copy.Z.Zero();
|
||||
if(!copy.BEncode(&buf))
|
||||
return false;
|
||||
buf.sz = buf.cur - buf.base;
|
||||
return c->verify(pk, buf, Z);
|
||||
}
|
||||
|
||||
bool
|
||||
RejectExitMessage::HandleMessage(IMessageHandler* h, llarp_router* r) const
|
||||
{
|
||||
return h->HandleRejectExitMessage(this, r);
|
||||
}
|
||||
|
||||
} // namespace routing
|
||||
} // namespace llarp
|
@ -0,0 +1,113 @@
|
||||
#include <llarp/exit/session.hpp>
|
||||
#include "router.hpp"
|
||||
|
||||
namespace llarp
|
||||
{
|
||||
namespace exit
|
||||
{
|
||||
BaseSession::BaseSession(const llarp::RouterID& router,
|
||||
std::function< bool(llarp_buffer_t) > writepkt,
|
||||
llarp_router* r, size_t numpaths, size_t hoplen)
|
||||
: llarp::path::Builder(r, r->dht, numpaths, hoplen)
|
||||
, m_ExitRouter(router)
|
||||
, m_WritePacket(writepkt)
|
||||
{
|
||||
r->crypto.identity_keygen(m_ExitIdentity);
|
||||
}
|
||||
|
||||
BaseSession::~BaseSession()
|
||||
{
|
||||
}
|
||||
|
||||
bool
|
||||
BaseSession::ShouldBuildMore(llarp_time_t now) const
|
||||
{
|
||||
return AvailablePaths(llarp::path::ePathRoleExit) == 0
|
||||
|| path::Builder::ShouldBuildMore(now);
|
||||
}
|
||||
|
||||
bool
|
||||
BaseSession::SelectHop(llarp_nodedb* db, const RouterContact& prev,
|
||||
RouterContact& cur, size_t hop,
|
||||
llarp::path::PathRole roles)
|
||||
{
|
||||
if(hop == numHops - 1)
|
||||
return llarp_nodedb_get_rc(db, m_ExitRouter, cur);
|
||||
else
|
||||
return path::Builder::SelectHop(db, prev, cur, hop, roles);
|
||||
}
|
||||
|
||||
void
|
||||
BaseSession::HandlePathBuilt(llarp::path::Path* p)
|
||||
{
|
||||
p->SetDropHandler(std::bind(&BaseSession::HandleTrafficDrop, this,
|
||||
std::placeholders::_1, std::placeholders::_2,
|
||||
std::placeholders::_3));
|
||||
p->SetExitTrafficHandler(std::bind(&BaseSession::HandleTraffic, this,
|
||||
std::placeholders::_1,
|
||||
std::placeholders::_2));
|
||||
p->AddObtainExitHandler(std::bind(&BaseSession::HandleGotExit, this,
|
||||
std::placeholders::_1,
|
||||
std::placeholders::_2));
|
||||
llarp::routing::ObtainExitMessage obtain;
|
||||
obtain.S = p->NextSeqNo();
|
||||
obtain.T = llarp_randint();
|
||||
obtain.X = 0;
|
||||
obtain.E = 1;
|
||||
if(!obtain.Sign(&router->crypto, m_ExitIdentity))
|
||||
{
|
||||
llarp::LogError("Failed to sign exit request");
|
||||
return;
|
||||
}
|
||||
if(p->SendExitRequest(&obtain, router))
|
||||
llarp::LogInfo("asking ", m_ExitRouter, " for exit");
|
||||
else
|
||||
llarp::LogError("faild to send exit request");
|
||||
}
|
||||
|
||||
bool
|
||||
BaseSession::HandleGotExit(llarp::path::Path* p, llarp_time_t b)
|
||||
{
|
||||
if(b == 0)
|
||||
{
|
||||
llarp::LogInfo("obtained an exit via ", p->Endpoint());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
BaseSession::HandleTraffic(llarp::path::Path* p, llarp_buffer_t pkt)
|
||||
{
|
||||
(void)p;
|
||||
if(m_WritePacket)
|
||||
return m_WritePacket(pkt);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
BaseSession::HandleTrafficDrop(llarp::path::Path* p, const PathID_t& path,
|
||||
uint64_t s)
|
||||
{
|
||||
(void)p;
|
||||
llarp::LogError("dropped traffic on exit ", m_ExitRouter, " S=", s,
|
||||
" P=", path);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
BaseSession::SendUpstreamTraffic(llarp::net::IPv4Packet pkt)
|
||||
{
|
||||
auto path = PickRandomEstablishedPath(llarp::path::ePathRoleExit);
|
||||
if(!path)
|
||||
return false;
|
||||
llarp::routing::TransferTrafficMessage transfer;
|
||||
transfer.S = path->NextSeqNo();
|
||||
transfer.X.resize(pkt.sz);
|
||||
memcpy(transfer.X.data(), pkt.buf, pkt.sz);
|
||||
if(!transfer.Sign(&router->crypto, m_ExitIdentity))
|
||||
return false;
|
||||
return path->SendRoutingMessage(&transfer, router);
|
||||
}
|
||||
|
||||
} // namespace exit
|
||||
} // namespace llarp
|
@ -0,0 +1,118 @@
|
||||
#include <llarp/messages/transfer_traffic.hpp>
|
||||
#include <llarp/routing/handler.hpp>
|
||||
|
||||
namespace llarp
|
||||
{
|
||||
namespace routing
|
||||
{
|
||||
bool
|
||||
TransferTrafficMessage::Sign(llarp_crypto* c, const llarp::SecretKey& k)
|
||||
{
|
||||
byte_t tmp[MaxExitMTU + 512] = {0};
|
||||
auto buf = llarp::StackBuffer< decltype(tmp) >(tmp);
|
||||
// zero out sig
|
||||
Z.Zero();
|
||||
// randomize nonce
|
||||
Y.Randomize();
|
||||
if(!BEncode(&buf))
|
||||
return false;
|
||||
// rewind buffer
|
||||
buf.sz = buf.cur - buf.base;
|
||||
return c->sign(Z, k, buf);
|
||||
}
|
||||
|
||||
TransferTrafficMessage&
|
||||
TransferTrafficMessage::operator=(const TransferTrafficMessage& other)
|
||||
{
|
||||
Z = other.Z;
|
||||
Y = other.Y;
|
||||
S = other.S;
|
||||
version = other.version;
|
||||
X = other.X;
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool
|
||||
TransferTrafficMessage::Verify(llarp_crypto* c,
|
||||
const llarp::PubKey& pk) const
|
||||
{
|
||||
byte_t tmp[MaxExitMTU + 512] = {0};
|
||||
auto buf = llarp::StackBuffer< decltype(tmp) >(tmp);
|
||||
// make copy
|
||||
TransferTrafficMessage copy;
|
||||
copy = *this;
|
||||
// zero copy's sig
|
||||
copy.Z.Zero();
|
||||
// encode
|
||||
if(!copy.BEncode(&buf))
|
||||
return false;
|
||||
// rewind buffer
|
||||
buf.sz = buf.cur - buf.base;
|
||||
// verify signature
|
||||
return c->verify(pk, buf, Z);
|
||||
}
|
||||
|
||||
bool
|
||||
TransferTrafficMessage::PutBuffer(llarp_buffer_t buf)
|
||||
{
|
||||
if(buf.sz > MaxExitMTU)
|
||||
return false;
|
||||
X.resize(buf.sz);
|
||||
memcpy(X.data(), buf.base, buf.sz);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
TransferTrafficMessage::BEncode(llarp_buffer_t* buf) const
|
||||
{
|
||||
if(!bencode_start_dict(buf))
|
||||
return false;
|
||||
if(!BEncodeWriteDictMsgType(buf, "A", "I"))
|
||||
return false;
|
||||
if(!BEncodeWriteDictInt("S", S, buf))
|
||||
return false;
|
||||
if(!BEncodeWriteDictInt("V", version, buf))
|
||||
return false;
|
||||
|
||||
if(!bencode_write_bytestring(buf, "X", 1))
|
||||
return false;
|
||||
if(!bencode_write_bytestring(buf, X.data(), X.size()))
|
||||
return false;
|
||||
if(!BEncodeWriteDictEntry("Y", Y, buf))
|
||||
return false;
|
||||
if(!BEncodeWriteDictEntry("Z", Z, buf))
|
||||
return false;
|
||||
return bencode_end(buf);
|
||||
}
|
||||
|
||||
bool
|
||||
TransferTrafficMessage::DecodeKey(llarp_buffer_t key, llarp_buffer_t* buf)
|
||||
{
|
||||
bool read = false;
|
||||
if(!BEncodeMaybeReadDictEntry("Z", Z, read, key, buf))
|
||||
return false;
|
||||
if(!BEncodeMaybeReadDictEntry("Y", Y, read, key, buf))
|
||||
return false;
|
||||
if(!BEncodeMaybeReadDictInt("S", S, read, key, buf))
|
||||
return false;
|
||||
if(!BEncodeMaybeReadDictInt("V", version, read, key, buf))
|
||||
return false;
|
||||
if(llarp_buffer_eq(key, "X"))
|
||||
{
|
||||
llarp_buffer_t strbuf;
|
||||
if(!bencode_read_string(buf, &strbuf))
|
||||
return false;
|
||||
return PutBuffer(strbuf);
|
||||
}
|
||||
return read;
|
||||
}
|
||||
|
||||
bool
|
||||
TransferTrafficMessage::HandleMessage(IMessageHandler* h,
|
||||
llarp_router* r) const
|
||||
{
|
||||
return h->HandleTransferTrafficMessage(this, r);
|
||||
}
|
||||
|
||||
} // namespace routing
|
||||
} // namespace llarp
|
@ -0,0 +1,127 @@
|
||||
#include <llarp/messages/exit.hpp>
|
||||
#include <llarp/routing/handler.hpp>
|
||||
|
||||
namespace llarp
|
||||
{
|
||||
namespace routing
|
||||
{
|
||||
bool
|
||||
UpdateExitMessage::BEncode(llarp_buffer_t* buf) const
|
||||
{
|
||||
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)
|
||||
{
|
||||
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[512] = {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;
|
||||
Y = other.Y;
|
||||
Z = other.Z;
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool
|
||||
UpdateExitMessage::Sign(llarp_crypto* c, const llarp::SecretKey& sk)
|
||||
{
|
||||
byte_t tmp[512] = {0};
|
||||
auto buf = llarp::StackBuffer< decltype(tmp) >(tmp);
|
||||
Y.Randomize();
|
||||
if(!BEncode(&buf))
|
||||
return false;
|
||||
buf.sz = buf.cur - buf.base;
|
||||
return c->sign(Z, sk, buf);
|
||||
}
|
||||
|
||||
bool
|
||||
UpdateExitMessage::HandleMessage(IMessageHandler* h, llarp_router* r) const
|
||||
{
|
||||
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
|
@ -0,0 +1,355 @@
|
||||
#include <llarp/handlers/exit.hpp>
|
||||
#include "../str.hpp"
|
||||
#include "../router.hpp"
|
||||
#include <llarp/net.hpp>
|
||||
#include <cassert>
|
||||
|
||||
namespace llarp
|
||||
{
|
||||
namespace handlers
|
||||
{
|
||||
static void
|
||||
ExitHandlerRecvPkt(llarp_tun_io *tun, const void *pkt, ssize_t sz)
|
||||
{
|
||||
static_cast< ExitEndpoint * >(tun->user)->OnInetPacket(
|
||||
llarp::InitBuffer(pkt, sz));
|
||||
}
|
||||
static void
|
||||
ExitHandlerFlushInbound(llarp_tun_io *tun)
|
||||
{
|
||||
static_cast< ExitEndpoint * >(tun->user)->FlushInbound();
|
||||
}
|
||||
|
||||
ExitEndpoint::ExitEndpoint(const std::string &name, llarp_router *r)
|
||||
: m_Router(r)
|
||||
, m_Name(name)
|
||||
, m_Tun{{0}, 0, {0}, 0, 0, 0, 0, 0, 0}
|
||||
, m_InetToNetwork(name + "_exit_rx", r->netloop, r->netloop)
|
||||
|
||||
{
|
||||
m_Tun.user = this;
|
||||
m_Tun.recvpkt = &ExitHandlerRecvPkt;
|
||||
m_Tun.tick = &ExitHandlerFlushInbound;
|
||||
m_ShouldInitTun = true;
|
||||
}
|
||||
|
||||
ExitEndpoint::~ExitEndpoint()
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
ExitEndpoint::FlushInbound()
|
||||
{
|
||||
auto now = Router()->Now();
|
||||
m_InetToNetwork.Process([&](Pkt_t &pkt) {
|
||||
llarp::PubKey pk;
|
||||
{
|
||||
auto itr = m_IPToKey.find(pkt.dst());
|
||||
if(itr == m_IPToKey.end())
|
||||
{
|
||||
// drop
|
||||
llarp::LogWarn(Name(), " dropping packet, has no session at ",
|
||||
pkt.dst());
|
||||
return;
|
||||
}
|
||||
pk = itr->second;
|
||||
}
|
||||
llarp::exit::Endpoint *ep = nullptr;
|
||||
auto range = m_ActiveExits.equal_range(pk);
|
||||
auto itr = range.first;
|
||||
uint64_t min = std::numeric_limits< uint64_t >::max();
|
||||
/// pick path with lowest rx rate
|
||||
while(itr != range.second)
|
||||
{
|
||||
if(ep == nullptr)
|
||||
ep = itr->second.get();
|
||||
else if(itr->second->RxRate() < min && !itr->second->ExpiresSoon(now))
|
||||
{
|
||||
min = ep->RxRate();
|
||||
ep = itr->second.get();
|
||||
}
|
||||
++itr;
|
||||
}
|
||||
if(ep)
|
||||
{
|
||||
if(!ep->SendInboundTraffic(pkt.Buffer()))
|
||||
{
|
||||
llarp::LogWarn(Name(), " dropped inbound traffic for session ", pk);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
bool
|
||||
ExitEndpoint::Start()
|
||||
{
|
||||
if(m_ShouldInitTun)
|
||||
return llarp_ev_add_tun(Router()->netloop, &m_Tun);
|
||||
return true;
|
||||
}
|
||||
|
||||
llarp_router *
|
||||
ExitEndpoint::Router()
|
||||
{
|
||||
return m_Router;
|
||||
}
|
||||
|
||||
llarp_crypto *
|
||||
ExitEndpoint::Crypto()
|
||||
{
|
||||
return &m_Router->crypto;
|
||||
}
|
||||
|
||||
huint32_t
|
||||
ExitEndpoint::GetIfAddr() const
|
||||
{
|
||||
return m_IfAddr;
|
||||
}
|
||||
|
||||
bool
|
||||
ExitEndpoint::HasLocalMappedAddrFor(const llarp::PubKey &pk) const
|
||||
{
|
||||
return m_KeyToIP.find(pk) != m_KeyToIP.end();
|
||||
}
|
||||
|
||||
huint32_t
|
||||
ExitEndpoint::GetIPForIdent(const llarp::PubKey pk)
|
||||
{
|
||||
huint32_t found = {0};
|
||||
if(!HasLocalMappedAddrFor(pk))
|
||||
{
|
||||
// allocate and map
|
||||
found.h = AllocateNewAddress().h;
|
||||
if(!m_KeyToIP.emplace(pk, found).second)
|
||||
{
|
||||
llarp::LogError(Name(), "failed to map ", pk, " to ", found);
|
||||
return found;
|
||||
}
|
||||
if(!m_IPToKey.emplace(found, pk).second)
|
||||
{
|
||||
llarp::LogError(Name(), "failed to map ", found, " to ", pk);
|
||||
return found;
|
||||
}
|
||||
if(HasLocalMappedAddrFor(pk))
|
||||
llarp::LogInfo(Name(), " mapping ", pk, " to ", found);
|
||||
else
|
||||
llarp::LogError(Name(), "failed to map ", pk, " to ", found);
|
||||
}
|
||||
else
|
||||
found.h = m_KeyToIP[pk].h;
|
||||
|
||||
MarkIPActive(found);
|
||||
m_KeyToIP.rehash(0);
|
||||
assert(HasLocalMappedAddrFor(pk));
|
||||
return found;
|
||||
}
|
||||
|
||||
huint32_t
|
||||
ExitEndpoint::AllocateNewAddress()
|
||||
{
|
||||
if(m_NextAddr < m_HigestAddr)
|
||||
return ++m_NextAddr;
|
||||
|
||||
// find oldest activity ip address
|
||||
huint32_t found = {0};
|
||||
llarp_time_t min = std::numeric_limits< llarp_time_t >::max();
|
||||
auto itr = m_IPActivity.begin();
|
||||
while(itr != m_IPActivity.end())
|
||||
{
|
||||
if(itr->second < min)
|
||||
{
|
||||
found.h = itr->first.h;
|
||||
min = itr->second;
|
||||
}
|
||||
++itr;
|
||||
}
|
||||
// kick old ident off exit
|
||||
// TODO: DoS
|
||||
llarp::PubKey pk = m_IPToKey[found];
|
||||
KickIdentOffExit(pk);
|
||||
|
||||
return found;
|
||||
}
|
||||
|
||||
bool
|
||||
ExitEndpoint::QueueOutboundTraffic(llarp_buffer_t buf)
|
||||
{
|
||||
return llarp_ev_tun_async_write(&m_Tun, buf.base, buf.sz);
|
||||
}
|
||||
|
||||
void
|
||||
ExitEndpoint::KickIdentOffExit(const llarp::PubKey &pk)
|
||||
{
|
||||
llarp::LogInfo(Name(), " kicking ", pk, " off exit");
|
||||
huint32_t ip = m_KeyToIP[pk];
|
||||
m_KeyToIP.erase(pk);
|
||||
m_IPToKey.erase(ip);
|
||||
auto range = m_ActiveExits.equal_range(pk);
|
||||
auto exit_itr = range.first;
|
||||
while(exit_itr != range.second)
|
||||
exit_itr = m_ActiveExits.erase(exit_itr);
|
||||
}
|
||||
|
||||
void
|
||||
ExitEndpoint::MarkIPActive(llarp::huint32_t ip)
|
||||
{
|
||||
m_IPActivity[ip] = Router()->Now();
|
||||
}
|
||||
|
||||
void
|
||||
ExitEndpoint::OnInetPacket(llarp_buffer_t buf)
|
||||
{
|
||||
m_InetToNetwork.EmplaceIf(
|
||||
[buf](Pkt_t &pkt) -> bool { return pkt.Load(buf); });
|
||||
}
|
||||
|
||||
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.get();
|
||||
}
|
||||
}
|
||||
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 == "type" && v == "null")
|
||||
{
|
||||
m_ShouldInitTun = false;
|
||||
return true;
|
||||
}
|
||||
if(k == "exit")
|
||||
{
|
||||
m_PermitExit = IsTrueValue(v.c_str());
|
||||
return true;
|
||||
}
|
||||
if(k == "ifaddr")
|
||||
{
|
||||
auto pos = v.find("/");
|
||||
if(pos == std::string::npos)
|
||||
{
|
||||
llarp::LogError(Name(), " ifaddr is not a cidr: ", v);
|
||||
return false;
|
||||
}
|
||||
std::string nmask_str = v.substr(1 + pos);
|
||||
std::string host_str = v.substr(0, pos);
|
||||
strncpy(m_Tun.ifaddr, host_str.c_str(), sizeof(m_Tun.ifaddr));
|
||||
m_Tun.netmask = std::atoi(nmask_str.c_str());
|
||||
|
||||
llarp::Addr ifaddr(host_str);
|
||||
m_IfAddr = ifaddr.xtohl();
|
||||
m_NextAddr = m_IfAddr;
|
||||
m_HigestAddr = m_IfAddr ^ (~llarp::netmask_ipv4_bits(m_Tun.netmask));
|
||||
llarp::LogInfo(Name(), " set ifaddr range to ", m_Tun.ifaddr, "/",
|
||||
m_Tun.netmask, " lo=", m_IfAddr, " hi=", m_HigestAddr);
|
||||
}
|
||||
if(k == "ifname")
|
||||
{
|
||||
strncpy(m_Tun.ifname, v.c_str(), sizeof(m_Tun.ifname));
|
||||
llarp::LogInfo(Name(), " set ifname to ", m_Tun.ifname);
|
||||
}
|
||||
if(k == "exit-whitelist")
|
||||
{
|
||||
// add exit policy whitelist rule
|
||||
// TODO: implement me
|
||||
return true;
|
||||
}
|
||||
if(k == "exit-blacklist")
|
||||
{
|
||||
// add exit policy blacklist rule
|
||||
// TODO: implement me
|
||||
return true;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
ExitEndpoint::AllocateNewExit(const llarp::PubKey pk,
|
||||
const llarp::PathID_t &path,
|
||||
bool wantInternet)
|
||||
{
|
||||
if(wantInternet && !m_PermitExit)
|
||||
return false;
|
||||
huint32_t ip = GetIPForIdent(pk);
|
||||
m_ActiveExits.insert(std::make_pair(
|
||||
pk, new llarp::exit::Endpoint(pk, path, !wantInternet, ip, this)));
|
||||
m_Paths[path] = pk;
|
||||
return HasLocalMappedAddrFor(pk);
|
||||
}
|
||||
|
||||
std::string
|
||||
ExitEndpoint::Name() const
|
||||
{
|
||||
return m_Name;
|
||||
}
|
||||
|
||||
void
|
||||
ExitEndpoint::DelEndpointInfo(const llarp::PathID_t &path)
|
||||
{
|
||||
m_Paths.erase(path);
|
||||
}
|
||||
|
||||
void
|
||||
ExitEndpoint::RemoveExit(const llarp::exit::Endpoint *ep)
|
||||
{
|
||||
auto range = m_ActiveExits.equal_range(ep->PubKey());
|
||||
auto itr = range.first;
|
||||
while(itr != range.second)
|
||||
{
|
||||
if(itr->second->LocalPath() == ep->LocalPath())
|
||||
{
|
||||
itr = m_ActiveExits.erase(itr);
|
||||
// now ep is gone af
|
||||
return;
|
||||
}
|
||||
++itr;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ExitEndpoint::Tick(llarp_time_t now)
|
||||
{
|
||||
auto itr = m_ActiveExits.begin();
|
||||
while(itr != m_ActiveExits.end())
|
||||
{
|
||||
if(itr->second->IsExpired(now))
|
||||
{
|
||||
itr = m_ActiveExits.erase(itr);
|
||||
}
|
||||
else
|
||||
{
|
||||
itr->second->Tick(now);
|
||||
++itr;
|
||||
}
|
||||
}
|
||||
}
|
||||
} // namespace handlers
|
||||
} // namespace llarp
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue