Ryan Tharp 6 years ago
commit ab3493ba3d

@ -1,6 +1,6 @@
cmake_minimum_required(VERSION 2.8.10)
set(PROJECT_NAME llarpd)
set(PROJECT_NAME lokinet)
project(${PROJECT_NAME})
macro(add_cflags)
@ -34,6 +34,10 @@ else()
message(ERROR "The compiler ${CMAKE_CXX_COMPILER} has no C++11 or C++17 support. Please use a different C++ compiler.")
endif()
if(DEBIAN)
add_definitions(-DDEBIAN)
endif()
if(ANDROID)
set(THREAD_LIB "-pthread")
# finally removed pthread dependency for MSC++
@ -118,7 +122,7 @@ if(RELEASE_MOTTO)
add_definitions(-DLLARP_RELEASE_MOTTO="${RELEASE_MOTTO}")
endif()
set(EXE llarpd)
set(EXE lokinet)
set(EXE_SRC daemon/main.cpp)
if(SODIUM_INCLUDE_DIR)
@ -177,11 +181,13 @@ endif(UNIX)
if(TUNTAP)
set(LIBTUNTAP_SRC
${TT_ROOT}/tuntap.c
${TT_ROOT}/tuntap_log.c
${TT_ROOT}/tuntap_log.cpp
${LIBTUNTAP_IMPL})
if (UNIX)
${TT_ROOT}/tuntap-unix.c
set(LIBTUNTAP_SRC
${TT_ROOT}/tuntap-unix.c
${LIBTUNTAP_SRC})
endif()
${LIBTUNTAP_IMPL})
else()
set(LIBTUNTAP_SRC "")
endif()
@ -282,6 +288,7 @@ set(LIB_SRC
llarp/dht/got_router.cpp
llarp/dht/search_job.cpp
llarp/dht/publish_intro.cpp
llarp/handlers/tun.cpp
llarp/iwp/frame_header.cpp
llarp/iwp/frame_state.cpp
llarp/iwp/session.cpp

@ -18,7 +18,7 @@ SHADOW_CONFIG=$(REPO)/shadow.config.xml
SHADOW_PLUGIN=$(REPO)/libshadow-plugin-llarp.so
SHADOW_LOG=$(REPO)/shadow.log.txt
SHADOW_SRC ?= $(HOME)/git/shadow
SHADOW_SRC ?= $(HOME)/local/shadow
SHADOW_PARSE ?= python $(SHADOW_SRC)/src/tools/parse-shadow.py - -m 0 --packet-data
SHADOW_PLOT ?= python $(SHADOW_SRC)/src/tools/plot-shadow.py -d $(REPO) LokiNET -c $(SHADOW_CONFIG) -r 10000 -e '.*'
@ -26,7 +26,9 @@ TESTNET_ROOT=/tmp/lokinet_testnet_tmp
TESTNET_CONF=$(TESTNET_ROOT)/supervisor.conf
TESTNET_LOG=$(TESTNET_ROOT)/testnet.log
TESTNET_EXE=$(REPO)/lokinet
EXE = $(REPO)/lokinet
TESTNET_EXE=$(REPO)/lokinet-testnet
TESTNET_CLIENTS ?= 50
TESTNET_SERVERS ?= 50
TESTNET_DEBUG ?= 0
@ -40,10 +42,10 @@ clean:
rm -f *.a *.so
debug-configure:
cmake -GNinja -DCMAKE_BUILD_TYPE=Debug -DWITH_TESTS=ON -DCMAKE_C_COMPILER=$(CC) -DCMAKE_CXX_COMPILER=$(CXX)
cmake -GNinja -DCMAKE_BUILD_TYPE=Debug -DWITH_TESTS=ON -DCMAKE_C_COMPILER=$(CC) -DCMAKE_CXX_COMPILER=$(CXX) -DTUNTAP=ON
release-configure: clean
cmake -GNinja -DSTATIC_LINK=ON -DCMAKE_BUILD_TYPE=Release -DRELEASE_MOTTO="$(shell cat motto.txt)" -DCMAKE_C_COMPILER=$(CC) -DCMAKE_CXX_COMPILER=$(CXX)
cmake -GNinja -DSTATIC_LINK=ON -DCMAKE_BUILD_TYPE=Release -DRELEASE_MOTTO="$(shell cat motto.txt)" -DCMAKE_C_COMPILER=$(CC) -DCMAKE_CXX_COMPILER=$(CXX) -DTUNTAP=ON
debug: debug-configure
ninja
@ -82,21 +84,19 @@ testnet-clean: clean
rm -rf $(TESTNET_ROOT)
testnet-configure: testnet-clean
cmake -GNinja -DCMAKE_BUILD_TYPE=Debug -DCMAKE_C_COMPILER=$(CC) -DCMAKE_CXX_COMPILER=$(CXX)
cmake -GNinja -DCMAKE_BUILD_TYPE=Debug -DCMAKE_C_COMPILER=$(CC) -DCMAKE_CXX_COMPILER=$(CXX) -DTUNTAP=ON
testnet-build: testnet-configure
ninja
$(TESTNET_EXE): testnet-build
cp -f $(REPO)/llarpd $(TESTNET_EXE)
shared-configure: clean
cmake -GNinja -DCMAKE_BUILD_TYPE=Debug -DWITH_TESTS=ON -DCMAKE_C_COMPILER=$(CC) -DCMAKE_CXX_COMPILER=$(CXX) -DWITH_SHARED=ON
cmake -GNinja -DCMAKE_BUILD_TYPE=Debug -DWITH_TESTS=ON -DCMAKE_C_COMPILER=$(CC) -DCMAKE_CXX_COMPILER=$(CXX) -DWITH_SHARED=ON -DTUNTAP=ON
shared: shared-configure
ninja
testnet: $(TESTNET_EXE)
testnet:
cp $(EXE) $(TESTNET_EXE)
mkdir -p $(TESTNET_ROOT)
python3 contrib/testnet/genconf.py --bin=$(TESTNET_EXE) --svc=$(TESTNET_SERVERS) --clients=$(TESTNET_CLIENTS) --dir=$(TESTNET_ROOT) --out $(TESTNET_CONF)
LLARP_DEBUG=$(TESTNET_DEBUG) supervisord -n -d $(TESTNET_ROOT) -l $(TESTNET_LOG) -c $(TESTNET_CONF)
@ -107,12 +107,3 @@ test: debug-configure
format:
clang-format -i $$(find daemon llarp include | grep -E '\.[h,c](pp)?$$')
fuzz-configure: clean
cmake -GNinja -DCMAKE_BUILD_TYPE=Fuzz -DCMAKE_C_COMPILER=afl-gcc -DCMAKE_CXX_COMPILER=afl-g++
fuzz-build: fuzz-configure
ninja
fuzz: fuzz-build
$(EXE)

@ -13,7 +13,7 @@ def getSetting(s, name, fallback): return name in s and s[name] or fallback
shadowRoot = getSetting(os.environ, "SHADOW_ROOT",
os.path.join(os.environ['HOME'], '.shadow'))
libpath = 'libshadow-plugin-llarp.so'
libpath = 'libshadow-plugin-lokinet.so'
def nodeconf(conf, baseDir, name, ifname=None, port=None):

@ -39,5 +39,6 @@ main(int argc, char *argv[])
code = llarp_main_run(ctx);
llarp_main_free(ctx);
}
exit(code);
return code;
}

@ -557,6 +557,7 @@ ordered data message (variant 2)
D: "<N bytes encrypted HSD>",
N: "<32 bytes nonce for symettric cipher>",
S: sequence_number_uint64,
T: "<16 bytes converstation tag>",
V: 0,
Z: "<64 bytes signature using sender's signing key>"
}
@ -567,11 +568,12 @@ data sent anonymously over the network to a recipiant from a sender.
sent inside a HSFM encrypted with a shared secret.
{
A: protocol_number_uint,
D: "<N bytes payload>",
I: Introduction for reply,
S: SI of sender,
V: 0
a: protocol_number_uint,
d: "<N bytes payload>",
i: Introduction for reply,
s: SI of sender,
t: "<16 bytes converstation tag present only in message 0>",
v: 0
}
transfer data fragment message (TDFM)

@ -21,12 +21,8 @@ namespace llarp
{
if(randomize)
Randomize();
}
AlignedBuffer(const AlignedBuffer& other)
{
for(size_t idx = 0; idx < (sz / 8); ++idx)
l[idx] = other.l[idx];
else
Zero();
}
AlignedBuffer(const byte_t* data)
@ -68,6 +64,24 @@ namespace llarp
return memcmp(l, other.l, sz) < 0;
}
bool
operator>(const AlignedBuffer& other) const
{
return memcmp(l, other.l, sz) > 0;
}
bool
operator<=(const AlignedBuffer& other) const
{
return memcmp(l, other.l, sz) <= 0;
}
bool
operator>=(const AlignedBuffer& other) const
{
return memcmp(l, other.l, sz) >= 0;
}
AlignedBuffer
operator^(const AlignedBuffer& other) const
{
@ -110,7 +124,7 @@ namespace llarp
size_t idx = sz / 8;
while(idx)
{
if(l[idx--])
if(l[--idx])
return false;
}
return true;

@ -14,12 +14,13 @@ namespace llarp
return bencode_write_bytestring(buf, k, 1)
&& bencode_write_bytestring(buf, t, 1);
}
template < typename Obj_t >
bool
BEncodeWriteDictString(const char* k, const Obj_t& str, llarp_buffer_t* buf)
{
return bencode_write_bytestring(buf, k, 1)
&& bencode_write_bytestring(buf, str.c_str(), str.size());
&& bencode_write_bytestring(buf, str.data(), str.size());
}
template < typename Obj_t >
@ -149,11 +150,7 @@ namespace llarp
T item;
if(!item.BDecode(buf))
return false;
result.insert(item);
/*
if(!result.insert(item).second)
return false;
*/
return result.insert(item).second;
}
if(*buf->cur != 'e') // make sure we're at a list end
return false;

@ -61,10 +61,12 @@ typedef struct llarp_buffer_t
/// max size of buffer
size_t sz;
#ifdef __cplusplus
const byte_t operator[](size_t x)
{
return *(this->base + x);
}
#endif
} llarp_buffer_t;
/// how much room is left in buffer

@ -51,8 +51,7 @@ namespace llarp
};
template < typename T, typename GetTime, typename PutTime, typename Compare,
typename Mutex_t = std::mutex,
typename Lock_t = std::lock_guard< std::mutex >,
typename Mutex_t = util::Mutex, typename Lock_t = util::Lock,
llarp_time_t dropMs = 5, llarp_time_t initialIntervalMs = 100 >
struct CoDelQueue
{

@ -0,0 +1,30 @@
#ifndef LLARP_DEFAULTS_H
#define LLARP_DEFAULTS_H
#ifndef DEFAULT_RESOLVER_US
#define DEFAULT_RESOLVER_US "128.52.130.209"
#endif
#ifndef DEFAULT_RESOLVER_EU
#define DEFAULT_RESOLVER_EU "85.208.208.141"
#endif
#ifndef DEFAULT_RESOLVER_AU
#define DEFAULT_RESOLVER_AU "103.236.162.119"
#endif
#ifdef DEBIAN
#ifndef DEFAULT_LOKINET_USER
#define DEFAULT_LOKINET_USER "debian-lokinet"
#endif
#ifndef DEFAULT_LOKINET_GROUP
#define DEFAULT_LOKINET_GROUP "debian-lokinet"
#endif
#else
#ifndef DEFAULT_LOKINET_USER
#define DEFAULT_LOKINET_USER "lokinet"
#endif
#ifndef DEFAULT_LOKINET_GROUP
#define DEFAULT_LOKINET_GROUP "lokinet"
#endif
#endif
#endif

@ -19,8 +19,7 @@ namespace llarp
Bucket(const Key_t& us) : nodes(XorMetric(us)){};
bool
GetRandomNodeExcluding(Key_t& result,
const std::set< Key_t >& exclude) const
GetRandomNodeExcluding(Key_t& result, std::set< Key_t > exclude) const
{
std::vector< Key_t > candidates;
for(const auto& item : nodes)
@ -53,7 +52,7 @@ namespace llarp
bool
FindCloseExcluding(const Key_t& target, Key_t& result,
const std::set< Key_t >& exclude) const
std::set< Key_t > exclude) const
{
Key_t maxdist;
maxdist.Fill(0xff);
@ -61,8 +60,9 @@ namespace llarp
mindist.Fill(0xff);
for(const auto& item : nodes)
{
if(exclude.find(item.first) != exclude.end())
if(exclude.count(item.first))
continue;
auto curDist = item.first ^ target;
if(curDist < mindist)
{
@ -76,7 +76,7 @@ namespace llarp
void
PutNode(const Val_t& val)
{
nodes[val.ID] = val;
nodes.insert(std::make_pair(val.ID, val));
}
void

@ -6,6 +6,7 @@
#include <llarp/dht/bucket.hpp>
#include <llarp/dht/key.hpp>
#include <llarp/dht/message.hpp>
#include <llarp/dht/messages/findintro.hpp>
#include <llarp/dht/node.hpp>
#include <llarp/dht/search_job.hpp>
#include <llarp/service/IntroSet.hpp>
@ -42,8 +43,8 @@ namespace llarp
void
LookupIntroSet(const service::Address& addr, const Key_t& whoasked,
uint64_t whoaskedTX, const Key_t& askpeer,
bool interative = false, std::set< Key_t > excludes = {});
uint64_t whoaskedTX, const Key_t& askpeer, uint64_t R,
std::set< Key_t > excludes = {});
void
LookupTag(const service::Tag& tag, const Key_t& whoasked,
@ -60,7 +61,43 @@ namespace llarp
void
LookupIntroSetForPath(const service::Address& addr, uint64_t txid,
const llarp::PathID_t& path, const Key_t& askpeer);
const llarp::PathID_t& path, Key_t askpeer);
template < typename Job, typename Result >
void
TryLookupAgain(Job* j, Result r, uint64_t R)
{
const Key_t targetKey = j->target.ToKey();
Key_t askpeer;
std::set< Key_t > exclude = j->asked;
if(!nodes->FindCloseExcluding(targetKey, askpeer, exclude))
{
j->Exausted();
delete j;
return;
}
if((OurKey() ^ targetKey) < (askpeer ^ targetKey))
{
j->Exausted();
delete j;
return;
}
auto id = ++ids;
TXOwner ownerKey;
ownerKey.node = askpeer;
ownerKey.txid = id;
SearchJob job(j->whoasked, j->txid, r, [j]() { delete j; });
pendingTX[ownerKey] = job;
auto msg = new FindIntroMessage(id, j->target);
msg->R = R;
llarp::LogInfo("asking ", askpeer, " for ", j->target.ToString(),
" with txid=", id);
DHTSendTo(askpeer, msg);
j->asked.insert(std::move(askpeer));
}
void
DHTSendTo(const Key_t& peer, IMessage* msg);
void
LookupIntroSetRelayed(const Key_t& requester, uint64_t txid,

@ -28,7 +28,13 @@ namespace llarp
bool
operator<(const Key_t& other) const
{
return memcmp(data_l(), other.data_l(), 32) < 0;
return memcmp(data(), other.data(), 32) < 0;
}
bool
operator>(const Key_t& other) const
{
return memcmp(data(), other.data(), 32) > 0;
}
};
} // namespace dht

@ -10,8 +10,7 @@ namespace llarp
{
struct FindIntroMessage : public IMessage
{
uint64_t R = 0;
bool iterative = false;
uint64_t R = 0;
llarp::service::Address S;
llarp::service::Tag N;
uint64_t T = 0;
@ -28,7 +27,7 @@ namespace llarp
S.Zero();
}
FindIntroMessage(const llarp::service::Address& addr, uint64_t txid)
FindIntroMessage(uint64_t txid, const llarp::service::Address& addr)
: IMessage({}), S(addr), T(txid)
{
N.Zero();

@ -8,11 +8,13 @@ namespace llarp
{
struct GotRouterMessage : public IMessage
{
GotRouterMessage(const Key_t& from) : IMessage(from)
GotRouterMessage(const Key_t& from, bool tunneled)
: IMessage(from), relayed(tunneled)
{
}
GotRouterMessage(const Key_t& from, uint64_t id, const llarp_rc* result)
: IMessage(from), txid(id)
GotRouterMessage(const Key_t& from, uint64_t id, const llarp_rc* result,
bool tunneled)
: IMessage(from), txid(id), relayed(tunneled)
{
if(result)
{
@ -37,6 +39,7 @@ namespace llarp
std::vector< llarp_rc > R;
uint64_t txid = 0;
uint64_t version = 0;
bool relayed = false;
};
} // namespace dht
} // namespace llarp

@ -40,7 +40,8 @@ namespace llarp
ISNode(const llarp::service::IntroSet& other)
{
introset = other;
other.A.CalculateAddress(ID);
introset.A.CalculateAddress(ID);
llarp::LogInfo("make ISNode with topic ", introset.topic.ToString());
}
};
} // namespace dht

@ -18,9 +18,11 @@ namespace llarp
{
const static uint64_t JobTimeout = 30000;
typedef std::function< void(
typedef std::function< bool(
const std::vector< llarp::service::IntroSet >&) >
IntroSetHookFunc;
typedef std::function< void(void) > DoneFunc;
SearchJob();
/// for routers
SearchJob(const Key_t& requester, uint64_t requesterTX,
@ -29,15 +31,15 @@ namespace llarp
/// for introsets
SearchJob(const Key_t& requester, uint64_t requesterTX,
const Key_t& target, const std::set< Key_t >& excludes,
IntroSetHookFunc found);
IntroSetHookFunc found, DoneFunc done);
// for introsets via tag
SearchJob(const Key_t& requester, uint64_t requseterTX,
IntroSetHookFunc found);
IntroSetHookFunc found, DoneFunc done);
void
FoundRouter(const llarp_rc* router) const;
void
bool
FoundIntros(
const std::vector< llarp::service::IntroSet >& introset) const;
@ -50,6 +52,7 @@ namespace llarp
// only set if looking up router
llarp_router_lookup_job* job = nullptr;
IntroSetHookFunc foundIntroHook;
DoneFunc onDone;
llarp_time_t started;
Key_t requester;
uint64_t requesterTX;

@ -12,6 +12,7 @@ namespace llarp
struct Encrypted
{
Encrypted(Encrypted&&) = delete;
Encrypted(const Encrypted& other);
Encrypted();
Encrypted(const byte_t* buf, size_t sz);
Encrypted(size_t sz);

@ -1,18 +0,0 @@
#ifndef LLARP_ENDPOINT_HANDLER_HPP
#define LLARP_ENDPOINT_HANDLER_HPP
#include <llarp/buffer.h>
namespace llarp
{
// hidden service endpoint handler
struct IEndpointHandler
{
~IEndpointHandler(){};
virtual void
HandleMessage(llarp_buffer_t buf) = 0;
};
} // namespace llarp
#endif

@ -0,0 +1,15 @@
#ifndef LLARP_HANDLERS_TUN_HPP
#define LLARP_HANDLERS_TUN_HPP
#include <llarp/service/handler.hpp>
namespace llarp
{
namespace handlers
{
struct TunHandler : public service::IDataHandler
{
};
} // namespace handlers
} // namespace llarp
#endif

@ -1,7 +1,7 @@
#ifndef LLARP_IWP_H_
#define LLARP_IWP_H_
#ifndef LLARP_IWP_HPP
#define LLARP_IWP_HPP
#include <llarp/crypto.h>
#include "router.hpp"
#include <string>
struct llarp_iwp_args
{
@ -9,7 +9,7 @@ struct llarp_iwp_args
struct llarp_logic* logic;
struct llarp_threadpool* cryptoworker;
struct llarp_router* router;
const char* keyfile;
std::string keyfile;
};
#endif

@ -1,5 +1,5 @@
#pragma once
#include <llarp/iwp.h>
#include <llarp/iwp.hpp>
#include <llarp/threading.hpp>
#include "llarp/iwp/establish_job.hpp"
#include "router.hpp"
@ -10,12 +10,8 @@
struct llarp_link
{
/*
typedef std::mutex mtx_t;
typedef std::unique_lock< mtx_t > lock_t;
*/
typedef llarp::util::DummyMutex mtx_t;
typedef llarp::util::DummyLock lock_t;
typedef llarp::util::NullMutex mtx_t;
typedef llarp::util::NullLock lock_t;
llarp_router *router;
llarp_crypto *crypto;
@ -26,7 +22,7 @@ struct llarp_link
llarp_link *parent = nullptr;
llarp_udp_io udp;
llarp::Addr addr;
char keyfile[255];
std::string keyfile;
uint32_t timeout_job_id;
const char *

@ -125,10 +125,7 @@ struct llarp_link_session
llarp::util::CoDelQueue< iwp_async_frame *, FrameGetTime, FramePutTime,
FrameCompareTime >
outboundFrames;
/*
std::mutex m_EncryptedFramesMutex;
std::queue< iwp_async_frame > encryptedFrames;
*/
llarp::util::CoDelQueue< iwp_async_frame *, FrameGetTime, FramePutTime,
FrameCompareTime >
decryptedFrames;

@ -31,7 +31,7 @@ namespace llarp
std::string nodeName;
LogLevel minlevel = eLogInfo;
std::ostream& out;
std::mutex access;
llarp::util::Mutex access;
Logger() : Logger(std::cout, "unnamed")
{
#ifdef _WIN32
@ -80,19 +80,24 @@ namespace llarp
std::stringstream ss;
#ifdef ANDROID
int loglev = -1;
switch(lvl)
{
case eLogDebug:
ss << "[DBG] ";
loglev = ANDROID_LOG_DEBUG;
break;
case eLogInfo:
ss << "[NFO] ";
loglev = ANDROID_LOG_INFO;
break;
case eLogWarn:
ss << "[WRN] ";
loglev = ANDROID_LOG_WARN;
break;
case eLogError:
ss << "[ERR] ";
loglev = ANDROID_LOG_ERROR;
break;
}
#else
@ -127,7 +132,10 @@ namespace llarp
#else
{
std::unique_lock< std::mutex > lock(_glog.access);
__android_log_write(ANDROID_LOG_INFO, "LOKINET", ss.str().c_str());
tag = "LOKINET|" + tag;
__android_log_write(ANDROID_LOG_INFO, tag.c_str(), ss.str().c_str());
//__android_log_write(ANDROID_LOG_INFO, "LOKINET", ss.str().c_str());
llarp::util::Lock lock(_glog.access);
_glog.out << ss.str() << std::endl;
}
#endif

@ -21,6 +21,10 @@ llarp_init_single_process_logic(struct llarp_threadpool* tp);
void
llarp_logic_tick(struct llarp_logic* logic);
/// isolated tick
void
llarp_logic_tick_async(struct llarp_logic* logic);
void
llarp_free_logic(struct llarp_logic** logic);
@ -29,6 +33,7 @@ llarp_logic_queue_job(struct llarp_logic* logic, struct llarp_thread_job job);
uint32_t
llarp_logic_call_later(struct llarp_logic* logic, struct llarp_timeout_job job);
void
llarp_logic_cancel_call(struct llarp_logic* logic, uint32_t id);

@ -13,11 +13,16 @@ namespace llarp
struct PathTransferMessage : public IMessage
{
PathID_t P;
service::ProtocolFrame* T = nullptr;
uint64_t V = 0;
service::ProtocolFrame T;
uint64_t V = 0;
TunnelNonce Y;
PathTransferMessage();
PathTransferMessage(const service::ProtocolFrame& f, const PathID_t& p)
: P(p), T(f)
{
Y.Randomize();
}
~PathTransferMessage();
bool

@ -6,7 +6,6 @@
#include <llarp/aligned.hpp>
#include <llarp/crypto.hpp>
#include <llarp/dht.hpp>
#include <llarp/endpoint.hpp>
#include <llarp/messages/relay.hpp>
#include <llarp/messages/relay_commit.hpp>
#include <llarp/path_types.hpp>
@ -359,6 +358,9 @@ namespace llarp
PathSet*
GetLocalPathSet(const PathID_t& id);
routing::IMessageHandler*
GetHandler(const PathID_t& id);
bool
ForwardLRCM(const RouterID& nextHop,
std::deque< EncryptedFrame >& frames);
@ -377,12 +379,12 @@ namespace llarp
typedef std::multimap< PathID_t, TransitHop* > TransitHopsMap_t;
typedef std::pair< std::mutex, TransitHopsMap_t > SyncTransitMap_t;
typedef std::pair< util::Mutex, TransitHopsMap_t > SyncTransitMap_t;
// maps path id -> pathset owner of path
typedef std::map< PathID_t, PathSet* > OwnedPathsMap_t;
typedef std::pair< std::mutex, OwnedPathsMap_t > SyncOwnedPathsMap_t;
typedef std::pair< util::Mutex, OwnedPathsMap_t > SyncOwnedPathsMap_t;
llarp_threadpool*
Worker();

@ -24,6 +24,9 @@ struct llarp_pathbuilder_context : public llarp::path::PathSet
void
BuildOne();
void
ManualRebuild(size_t N);
virtual byte_t*
GetTunnelEncryptionSecretKey();
};

@ -78,6 +78,19 @@ namespace llarp
return false;
}
/// override me in subtype
virtual bool
HandleGotRouterMessage(const llarp::dht::GotRouterMessage* msg)
{
return false;
}
virtual routing::IMessageHandler*
GetDHTHandler()
{
return nullptr;
}
Path*
GetEstablishedPathClosestTo(const RouterID& router) const;
@ -87,6 +100,9 @@ namespace llarp
Path*
GetPathByRouter(const RouterID& router) const;
Path*
GetPathByID(const PathID_t& id) const;
bool
GetCurrentIntroductions(
std::set< llarp::service::Introduction >& intros) const;

@ -19,9 +19,6 @@ namespace llarp
bool
IsValid(llarp_shorthash_func hashfunc) const;
bool
BDecode(llarp_buffer_t* buf);
bool
DecodeKey(llarp_buffer_t k, llarp_buffer_t* val);

@ -10,14 +10,58 @@ namespace llarp
{
struct ServiceInfo : public llarp::IBEncodeMessage
{
private:
llarp::PubKey enckey;
llarp::PubKey signkey;
uint64_t version = 0;
VanityNonce vanity;
ServiceInfo();
public:
ServiceInfo() = default;
ServiceInfo(const ServiceInfo&& other)
{
enckey = std::move(other.enckey);
signkey = std::move(other.signkey);
version = std::move(other.version);
vanity = std::move(other.vanity);
m_CachedAddr = std::move(other.m_CachedAddr);
}
ServiceInfo(const ServiceInfo& other)
{
enckey = other.enckey;
signkey = other.signkey;
version = other.version;
vanity = other.vanity;
m_CachedAddr = other.m_CachedAddr;
}
void
RandomizeVanity()
{
vanity.Randomize();
}
bool
Verify(llarp_crypto* crypto, llarp_buffer_t payload,
const Signature& sig) const
{
return crypto->verify(signkey, payload, sig);
}
byte_t*
EncryptionPublicKey()
{
return enckey;
}
~ServiceInfo();
bool
Update(const byte_t* enc, const byte_t* sign)
{
enckey = enc;
signkey = sign;
return UpdateAddr();
}
bool
operator==(const ServiceInfo& other) const
@ -26,6 +70,12 @@ namespace llarp
&& version == other.version && vanity == other.vanity;
}
bool
operator!=(const ServiceInfo& other) const
{
return !(*this == other);
}
ServiceInfo&
operator=(const ServiceInfo& other)
{
@ -50,7 +100,7 @@ namespace llarp
<< " v=" << i.version << " x=" << i.vanity << "]";
}
/// compute .loki address
/// .loki address
std::string
Name() const;
@ -70,9 +120,9 @@ namespace llarp
bool
BDecode(llarp_buffer_t* buf)
{
if(!IBEncodeMessage::BDecode(buf))
return false;
return CalculateAddress(m_CachedAddr);
if(IBEncodeMessage::BDecode(buf))
return CalculateAddress(m_CachedAddr.data());
return false;
}
bool

@ -25,6 +25,29 @@ namespace llarp
llarp::PoW* W = nullptr;
llarp::Signature Z;
IntroSet() = default;
IntroSet(const IntroSet&& other)
{
A = std::move(other.A);
I = std::move(other.I);
version = std::move(other.version);
topic = std::move(other.topic);
W = std::move(other.W);
Z = std::move(other.Z);
}
IntroSet(const IntroSet& other)
{
A = other.A;
I = other.I;
version = other.version;
topic = other.topic;
if(other.W)
W = new llarp::PoW(*other.W);
Z = other.Z;
}
~IntroSet();
IntroSet&
@ -36,7 +59,8 @@ namespace llarp
topic = other.topic;
if(W)
delete W;
W = other.W;
if(other.W)
W = new llarp::PoW(*other.W);
Z = other.Z;
return *this;
}
@ -72,6 +96,23 @@ namespace llarp
return out << " V=" << i.version << " Z=" << i.Z;
}
bool
IsNewerThan(const IntroSet& other) const
{
return GetNewestIntro().expiresAt > other.GetNewestIntro().expiresAt;
}
Introduction
GetNewestIntro() const
{
Introduction i;
i.expiresAt = 0;
for(const auto& intro : I)
if(intro.expiresAt > i.expiresAt)
i = intro;
return i;
}
bool
HasExpiredIntros(llarp_time_t now) const;

@ -2,13 +2,14 @@
#define LLARP_SERVICE_ADDRESS_HPP
#include <llarp/aligned.hpp>
#include <llarp/dht/key.hpp>
#include <llarp/router_id.hpp>
#include <string>
namespace llarp
{
namespace service
{
struct Address : public llarp::AlignedBuffer< 32 >
struct Address
{
std::string
ToString() const;
@ -16,28 +17,152 @@ namespace llarp
bool
FromString(const std::string& str);
Address() : llarp::AlignedBuffer< 32 >()
Address()
{
Zero();
}
Address(const byte_t* data) : llarp::AlignedBuffer< 32 >(data)
Address(const Address& other)
{
memcpy(b, other.b, 32);
}
struct Hash
byte_t& operator[](size_t idx)
{
size_t
operator()(const Address& addr) const
return b[idx];
}
const byte_t& operator[](size_t idx) const
{
return b[idx];
}
bool
BEncode(llarp_buffer_t* buf) const
{
return bencode_write_bytestring(buf, b, 32);
}
bool
BDecode(llarp_buffer_t* buf)
{
llarp_buffer_t strbuf;
if(!bencode_read_string(buf, &strbuf))
return false;
if(strbuf.sz != 32)
{
size_t idx = 0;
memcpy(&idx, addr, sizeof(idx));
return idx;
llarp::LogErrorTag("Address::BDecode",
"bdecode buffer size missmatch ", strbuf.sz,
"!=32");
return false;
}
};
memcpy(b, strbuf.base, 32);
return true;
}
operator const dht::Key_t() const
size_t
size() const
{
return 32;
}
bool
IsZero() const
{
size_t sz = 4;
while(sz)
{
if(l[--sz])
return false;
}
return true;
}
void
Zero()
{
size_t sz = 4;
while(sz)
{
l[--sz] = 0;
}
}
bool
operator<(const Address& other) const
{
return memcmp(data(), other.data(), 32) < 0;
}
friend std::ostream&
operator<<(std::ostream& out, const Address& self)
{
return out << self.ToString();
}
bool
operator==(const Address& other) const
{
return memcmp(data(), other.data(), 32) == 0;
}
bool
operator!=(const Address& other) const
{
return !(*this == other);
}
Address&
operator=(const Address& other)
{
memcpy(data(), other.data(), 32);
return *this;
}
const dht::Key_t
ToKey() const
{
return dht::Key_t(data());
}
const RouterID
ToRouter() const
{
return RouterID(data());
}
const byte_t*
data() const
{
return b;
}
byte_t*
data()
{
return b;
}
const uint64_t*
data_l() const
{
return l;
}
struct Hash
{
size_t
operator()(const Address& buf) const
{
return *buf.data_l();
}
};
private:
union {
byte_t b[32];
uint64_t l[4];
};
};
} // namespace service

@ -3,13 +3,16 @@
#include <llarp/codel.hpp>
#include <llarp/pathbuilder.hpp>
#include <llarp/service/Identity.hpp>
#include <llarp/service/handler.hpp>
#include <llarp/service/protocol.hpp>
namespace llarp
{
namespace service
{
struct Endpoint : public llarp_pathbuilder_context, public ILookupHolder
struct Endpoint : public llarp_pathbuilder_context,
public ILookupHolder,
public IDataHandler
{
/// minimum interval for publishing introsets
static const llarp_time_t INTROSET_PUBLISH_INTERVAL =
@ -20,14 +23,22 @@ namespace llarp
Endpoint(const std::string& nickname, llarp_router* r);
~Endpoint();
void
SetHandler(IDataHandler* h);
bool
SetOption(const std::string& k, const std::string& v);
void
Tick(llarp_time_t now);
/// router's logic
llarp_logic*
RouterLogic();
/// endpoint's logic
llarp_logic*
Logic();
EndpointLogic();
llarp_crypto*
Crypto();
@ -56,6 +67,9 @@ namespace llarp
bool
HandleGotIntroMessage(const llarp::dht::GotIntroMessage* msg);
bool
HandleGotRouterMessage(const llarp::dht::GotRouterMessage* msg);
bool
HandleHiddenServiceFrame(const llarp::service::ProtocolFrame* msg);
@ -63,11 +77,26 @@ namespace llarp
bool
HasPathToService(const Address& remote) const;
/// return true if we have a pending job to build to a hidden service but
/// it's not done yet
bool
HasPendingPathToService(const Address& remote) const;
/// return false if we don't have a path to the service
/// return true if we did and we removed it
bool
ForgetPathToService(const Address& remote);
virtual void
HandleDataMessage(ProtocolMessage* msg)
{
// override me in subclass
}
/// ensure that we know a router, looks up if it doesn't
void
EnsureRouterIsKnown(const RouterID& router);
Identity*
GetIdentity()
{
@ -114,9 +143,6 @@ namespace llarp
bool
SelectHop(llarp_nodedb* db, llarp_rc* prev, llarp_rc* cur, size_t hop);
bool
HandleGotIntroMessage(const llarp::dht::GotIntroMessage* msg);
bool
HandleHiddenServiceFrame(const ProtocolFrame* frame);
@ -127,8 +153,11 @@ namespace llarp
Name() const;
private:
bool
OnIntroSetUpdate(const IntroSet* i);
void
AsyncEncrypt(llarp_buffer_t payload);
EncryptAndSendTo(llarp_buffer_t payload);
void
AsyncGenIntro(llarp_buffer_t payload);
@ -160,6 +189,29 @@ namespace llarp
return true;
}
void
PutSenderFor(const ConvoTag& tag, const ServiceInfo& info);
bool
GetCachedSessionKeyFor(const ConvoTag& remote,
SharedSecret& secret) const;
void
PutCachedSessionKeyFor(const ConvoTag& remote,
const SharedSecret& secret);
bool
GetSenderFor(const ConvoTag& remote, ServiceInfo& si) const;
void
PutIntroFor(const ConvoTag& remote, const Introduction& intro);
bool
GetIntroFor(const ConvoTag& remote, Introduction& intro) const;
bool
GetConvoTagsForService(const ServiceInfo& si,
std::set< ConvoTag >& tag) const;
void
PutNewOutboundContext(const IntroSet& introset);
@ -175,19 +227,44 @@ namespace llarp
void
PrefetchServicesByTag(const Tag& tag);
uint64_t
GetSeqNoForConvo(const ConvoTag& tag);
bool
IsolateNetwork();
private:
bool
OnOutboundLookup(const IntroSet* i); /* */
static bool
SetupIsolatedNetwork(void* user);
bool
DoNetworkIsolation();
uint64_t
GenTXID();
protected:
IDataHandler* m_DataHandler = nullptr;
Identity m_Identity;
private:
llarp_router* m_Router;
llarp_threadpool* m_IsolatedWorker = nullptr;
llarp_logic* m_IsolatedLogic = nullptr;
std::string m_Keyfile;
std::string m_Name;
Identity m_Identity;
std::string m_NetNS;
std::unordered_map< Address, OutboundContext*, Address::Hash >
m_RemoteSessions;
std::unordered_map< Address, PathEnsureHook, Address::Hash >
m_PendingServiceLookups;
std::unordered_map< RouterID, uint64_t, RouterID::Hash > m_PendingRouters;
uint64_t m_CurrentPublishTX = 0;
llarp_time_t m_LastPublish = 0;
llarp_time_t m_LastPublishAttempt = 0;
@ -201,6 +278,20 @@ namespace llarp
Tag m_Tag;
/// prefetch descriptors for these hidden service tags
std::set< Tag > m_PrefetchTags;
/// on initialize functions
std::list< std::function< bool(void) > > m_OnInit;
struct Session
{
SharedSecret sharedKey;
ServiceInfo remote;
Introduction intro;
llarp_time_t lastUsed = 0;
uint64_t seqno = 0;
};
/// sessions
std::unordered_map< ConvoTag, Session, ConvoTag::Hash > m_Sessions;
struct CachedTagResult : public IServiceLookup
{

@ -0,0 +1,44 @@
#ifndef LLARP_SERVICE_HANDLER_HPP
#define LLARP_SERVICE_HANDLER_HPP
#include <llarp/aligned.hpp>
#include <llarp/crypto.hpp>
#include <llarp/service/IntroSet.hpp>
namespace llarp
{
namespace service
{
typedef llarp::AlignedBuffer< 16 > ConvoTag;
struct ProtocolMessage;
struct IDataHandler
{
virtual void
HandleDataMessage(ProtocolMessage* msg) = 0;
virtual bool
GetCachedSessionKeyFor(const ConvoTag& remote,
SharedSecret& secret) const = 0;
virtual void
PutCachedSessionKeyFor(const ConvoTag& remote,
const SharedSecret& secret) = 0;
virtual void
PutSenderFor(const ConvoTag& remote, const ServiceInfo& si) = 0;
virtual bool
GetSenderFor(const ConvoTag& remote, ServiceInfo& si) const = 0;
virtual void
PutIntroFor(const ConvoTag& remote, const Introduction& intro) = 0;
virtual bool
GetIntroFor(const ConvoTag& remote, Introduction& intro) const = 0;
virtual bool
GetConvoTagsForService(const ServiceInfo& si,
std::set< ConvoTag >& tag) const = 0;
};
} // namespace service
} // namespace llarp
#endif

@ -7,6 +7,7 @@
#include <llarp/routing/message.hpp>
#include <llarp/service/Info.hpp>
#include <llarp/service/Intro.hpp>
#include <llarp/service/handler.hpp>
#include <vector>
namespace llarp
@ -15,30 +16,36 @@ namespace llarp
{
constexpr std::size_t MAX_PROTOCOL_MESSAGE_SIZE = 2048;
enum ProtocolType
{
eProtocolText = 0,
eProtocolTraffic = 1
};
typedef uint64_t ProtocolType;
constexpr ProtocolType eProtocolText = 0UL;
constexpr ProtocolType eProtocolTraffic = 1UL;
/// inner message
struct ProtocolMessage : public llarp::IBEncodeMessage
struct ProtocolMessage : public IBEncodeMessage
{
ProtocolMessage(const ConvoTag& tag);
ProtocolMessage();
~ProtocolMessage();
ProtocolType proto;
ProtocolType proto = eProtocolText;
llarp_time_t queued = 0;
std::vector< byte_t > payload;
Introduction introReply;
ServiceInfo sender;
IDataHandler* handler = nullptr;
ConvoTag tag;
bool
DecodeKey(llarp_buffer_t key, llarp_buffer_t* val);
bool
BEncode(llarp_buffer_t* buf) const;
void
PutBuffer(llarp_buffer_t payload);
static void
ProcessAsync(void* user);
};
/// outer message
@ -48,6 +55,10 @@ namespace llarp
llarp::PubKey H;
llarp::KeyExchangeNonce N;
llarp::Signature Z;
llarp::service::ConvoTag T;
ProtocolFrame();
ProtocolFrame(const ProtocolFrame& other);
~ProtocolFrame();
@ -55,6 +66,11 @@ namespace llarp
EncryptAndSign(llarp_crypto* c, const ProtocolMessage* msg,
byte_t* sharedkey, byte_t* signingkey);
bool
AsyncDecryptAndVerify(llarp_logic* logic, llarp_crypto* c,
llarp_threadpool* worker, byte_t* localSecret,
IDataHandler* handler) const;
bool
DecryptPayloadInto(llarp_crypto* c, byte_t* sharedkey,
ProtocolMessage* into) const;
@ -66,7 +82,7 @@ namespace llarp
BEncode(llarp_buffer_t* buf) const;
bool
Verify(llarp_crypto* c, byte_t* signingkey);
Verify(llarp_crypto* c, const ServiceInfo& from) const;
bool
HandleMessage(llarp::routing::IMessageHandler* h, llarp_router* r) const;

@ -13,7 +13,6 @@ namespace llarp
{
Tag() : llarp::AlignedBuffer< 16 >()
{
Zero();
}
Tag(const byte_t* d) : llarp::AlignedBuffer< 16 >(d)
@ -29,17 +28,33 @@ namespace llarp
#endif
}
llarp::dht::Key_t
Key() const
Tag&
operator=(const Tag& other)
{
llarp::dht::Key_t k;
crypto_generichash(k, 32, data(), 16, nullptr, 0);
return k;
memcpy(data(), other.data(), 16);
return *this;
}
Tag&
operator=(const std::string& str)
{
#ifndef MIN
#define MIN(X, Y) (((X) < (Y)) ? (X) : (Y))
memcpy(data(), str.data(), MIN(16UL, str.size()));
#undef MIN
#endif
return *this;
}
std::string
ToString() const;
bool
Empty() const
{
return ToString().empty();
}
struct Hash
{
std::size_t

@ -0,0 +1,20 @@
#ifndef LLARP_SERVICE_TUN_HPP
#define LLARP_SERVICE_TUN_HPP
#include <tuntap.h>
#include <llarp/service/endpoint.hpp>
namespace llarp
{
namespace service
{
struct TunEndpoint : public Endpoint
{
TunEndpoint(const std::string& ifname, llarp_router* r);
~TunEndpoint();
device* m_tunif;
};
} // namespace service
} // namespace llarp
#endif

@ -9,4 +9,113 @@
#include <condition_variable>
#include <thread>
#endif
#include <memory>
namespace llarp
{
namespace util
{
/// a mutex that does nothing
struct NullMutex
{
};
/// a lock that does nothing
struct NullLock
{
NullLock(NullMutex& mtx)
{
}
};
/// a condition variable that does nothing
struct NullCondition
{
void
wait(NullLock& l)
{
}
void
notify_one()
{
}
void
notify_all()
{
}
template < typename Interval >
void
wait_for(NullLock& l, Interval i)
{
std::this_thread::sleep_for(i);
}
};
#ifdef SHADOW_TESTNET
typedef NullMutex mtx_t;
typedef NullLock lock_t;
typedef NullCondition cond_t;
#else
typedef std::mutex mtx_t;
typedef std::unique_lock< std::mutex > lock_t;
typedef std::condition_variable cond_t;
#endif
struct Mutex
{
mtx_t impl;
};
/// aqcuire a lock on a mutex
struct Lock
{
Lock(Mutex& mtx) : impl(mtx.impl)
{
}
lock_t impl;
};
struct Condition
{
cond_t impl;
void
NotifyAll()
{
impl.notify_all();
}
void
NotifyOne()
{
impl.notify_one();
}
void
Wait(Lock& lock)
{
impl.wait(lock.impl);
}
template < typename Interval >
void
WaitFor(Lock& lock, Interval i)
{
impl.wait_for(lock.impl, i);
}
template < typename Pred >
void
WaitUntil(Lock& lock, Pred p)
{
impl.wait(lock.impl, p);
}
};
} // namespace util
} // namespace llarp
#endif

@ -10,6 +10,13 @@ llarp_init_threadpool(int workers, const char *name);
struct llarp_threadpool *
llarp_init_same_process_threadpool();
typedef bool (*setup_net_func)(void *);
/// for network isolation
struct llarp_threadpool *
llarp_init_isolated_net_threadpool(const char *name, setup_net_func setupNet,
void *context);
void
llarp_free_threadpool(struct llarp_threadpool **tp);

@ -38,8 +38,12 @@ llarp_timer_run(struct llarp_timer_context *t, struct llarp_threadpool *pool);
/// single threaded run timer, tick all timers
void
llarp_timer_tick_all(struct llarp_timer_context *t,
struct llarp_threadpool *pool);
llarp_timer_tick_all(struct llarp_timer_context *t);
/// tick all timers into a threadpool asynchronously
void
llarp_timer_tick_all_async(struct llarp_timer_context *t,
struct llarp_threadpool *pool);
void
llarp_free_timer(struct llarp_timer_context **t);

@ -0,0 +1,251 @@
/*
* Copyright (c) 2012 Tristan Le Guern <leguern AT medu DOT se>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* Copyright (c) 2016 Mahdi Mokhtari <mokhi64@gmail.com>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <sys/types.h>
#if defined Windows
#else /* Unix */
#include <sys/socket.h>
#endif
#if !defined Windows /* Unix :) */
#if defined Linux
#include <linux/if.h>
#else
#include <net/if.h>
#endif
#include <netinet/if_ether.h>
#include <netinet/in.h>
#endif
#include <stdint.h>
#ifndef LIBTUNTAP_H_
#define LIBTUNTAP_H_
/*
* Uniformize macros
* - ETHER_ADDR_LEN: Magic number from IEEE 802.3
* - IF_NAMESIZE: Length of interface external name
* - IF_DESCRSIZE: Length of interface description
* - TUNSDEBUG: ioctl flag to enable the debug mode of a tun device
* - TUNFD_INVALID_VALUE: Invalid value for tun_fd
*/
#if defined ETH_ALEN /* Linux */
#define ETHER_ADDR_LEN ETH_ALEN
#elif defined Windows
#define ETHER_ADDR_LEN 6
#endif
#if defined IFNAMSIZ && !defined IF_NAMESIZE
#define IF_NAMESIZE IFNAMSIZ /* Historical BSD name */
#elif !defined IF_NAMESIZE
#define IF_NAMESIZE 16
#endif
#define IF_DESCRSIZE 50 /* XXX: Tests needed on NetBSD and OpenBSD */
#if defined TUNSETDEBUG
#define TUNSDEBUG TUNSETDEBUG
#endif
#if defined Windows
#define TUNFD_INVALID_VALUE INVALID_HANDLE_VALUE
#else /* Unix */
#define TUNFD_INVALID_VALUE -1
#endif
/*
* Uniformize types
* - t_tun: tun device file descriptor
* - t_tun_in_addr: struct in_addr/IN_ADDR
* - t_tun_in6_addr: struct in6_addr/IN6_ADDR
*/
#if defined Windows
typedef HANDLE t_tun;
typedef IN_ADDR t_tun_in_addr;
typedef IN6_ADDR t_tun_in6_addr;
#else /* Unix */
typedef int t_tun;
typedef struct in_addr t_tun_in_addr;
typedef struct in6_addr t_tun_in6_addr;
#endif
/*
* Windows helpers
*/
#if defined Windows
#define snprintf(x, y, z, ...) _snprintf_s((x), (y), (y), (z), __VA_ARGS__);
#define strncat(x, y, z) strncat_s((x), _countof(x), (y), (z));
#define strdup(x) _strdup(x)
#endif
#define TUNTAP_ID_MAX 256
#define TUNTAP_ID_ANY 257
#define TUNTAP_MODE_ETHERNET 0x0001
#define TUNTAP_MODE_TUNNEL 0x0002
#define TUNTAP_MODE_PERSIST 0x0004
#define TUNTAP_LOG_NONE 0x0000
#define TUNTAP_LOG_DEBUG 0x0001
#define TUNTAP_LOG_INFO 0x0002
#define TUNTAP_LOG_NOTICE 0x0004
#define TUNTAP_LOG_WARN 0x0008
#define TUNTAP_LOG_ERR 0x0016
/* Versioning: 0xMMmm, with 'M' for major and 'm' for minor */
#define TUNTAP_VERSION_MAJOR 0
#define TUNTAP_VERSION_MINOR 3
#define TUNTAP_VERSION ((TUNTAP_VERSION_MAJOR << 8) | TUNTAP_VERSION_MINOR)
#define TUNTAP_GET_FD(x) (x)->tun_fd
/* Handle Windows symbols export */
#if defined Windows
#if defined(tuntap_EXPORTS) /* CMake generated goo */
#define TUNTAP_EXPORT __declspec(dllexport)
#else
#define TUNTAP_EXPORT __declspec(dllimport)
#endif
#else /* Unix */
#define TUNTAP_EXPORT extern
#endif
#ifdef __cplusplus
extern "C"
{
#endif
struct device
{
t_tun tun_fd;
int ctrl_sock;
int flags; /* ifr.ifr_flags on Unix */
unsigned char hwaddr[ETHER_ADDR_LEN];
char if_name[IF_NAMESIZE];
#if defined(FreeBSD)
int mode;
#endif
};
/* User definable log callback */
typedef void (*t_tuntap_log)(int, const char *);
TUNTAP_EXPORT t_tuntap_log tuntap_log;
/* Portable "public" functions */
TUNTAP_EXPORT struct device *
tuntap_init(void);
TUNTAP_EXPORT int
tuntap_version(void);
TUNTAP_EXPORT void
tuntap_destroy(struct device *);
TUNTAP_EXPORT void
tuntap_release(struct device *);
TUNTAP_EXPORT int
tuntap_start(struct device *, int, int);
TUNTAP_EXPORT char *
tuntap_get_ifname(struct device *);
TUNTAP_EXPORT int
tuntap_set_ifname(struct device *, const char *);
TUNTAP_EXPORT char *
tuntap_get_hwaddr(struct device *);
TUNTAP_EXPORT int
tuntap_set_hwaddr(struct device *, const char *);
TUNTAP_EXPORT int
tuntap_set_descr(struct device *, const char *);
TUNTAP_EXPORT int
tuntap_up(struct device *);
TUNTAP_EXPORT int
tuntap_down(struct device *);
TUNTAP_EXPORT int
tuntap_get_mtu(struct device *);
TUNTAP_EXPORT int
tuntap_set_mtu(struct device *, int);
/*
* It's impossible to set single IP for `tun` devices on FreeBSD .
* FreeBSD's `tun` interface needs 2 IP addresses.
* So a new (and backward compatible) version of tuntap_set_ip() is
* implemented.
*/
TUNTAP_EXPORT int
tuntap_set_ip(struct device *, ...);
// TUNTAP_EXPORT int tuntap_set_ip_old(struct device *, const char
// *, int);
/*TUNTAP_EXPORT int tuntap_set_ip_old(struct device *, const char
* *, int);*/
TUNTAP_EXPORT int
tuntap_read(struct device *, void *, size_t);
TUNTAP_EXPORT int
tuntap_write(struct device *, void *, size_t);
TUNTAP_EXPORT int
tuntap_get_readable(struct device *);
TUNTAP_EXPORT int
tuntap_set_nonblocking(struct device *dev, int);
TUNTAP_EXPORT int
tuntap_set_debug(struct device *dev, int);
/* Logging functions */
TUNTAP_EXPORT void
tuntap_log_set_cb(t_tuntap_log cb);
void
tuntap_log_default(int, const char *);
void
tuntap_log_hexdump(void *, size_t);
void
tuntap_log_chksum(void *, int);
/* OS specific functions */
int
tuntap_sys_start(struct device *, int, int);
void
tuntap_sys_destroy(struct device *);
int
tuntap_sys_set_hwaddr(struct device *, struct ether_addr *);
int
tuntap_sys_set_ipv4(struct device *, t_tun_in_addr *, uint32_t);
#if defined(FreeBSD)
int
tuntap_sys_set_ipv4_tap(struct device *, t_tun_in_addr *, uint32_t);
int
tuntap_sys_set_ipv4_tun(struct device *dev, t_tun_in_addr *s4,
t_tun_in_addr *s4dest, uint32_t bits);
#endif
int
tuntap_sys_set_ipv6(struct device *, t_tun_in6_addr *, uint32_t);
int
tuntap_sys_set_ifname(struct device *, const char *, size_t);
int
tuntap_sys_set_descr(struct device *, const char *, size_t);
#ifdef __cplusplus
}
#endif
#endif

@ -1,5 +1,6 @@
#include "config.hpp"
#include <llarp/config.h>
#include <llarp/defaults.h>
#include <llarp/net.hpp>
#include "fs.hpp"
#include "ini.hpp"
@ -34,6 +35,7 @@ namespace llarp
iwp_links = find_section(top, "bind", section_t{});
services = find_section(top, "services", section_t{});
dns = find_section(top, "dns", section_t{});
system = find_section(top, "system", section_t{});
return true;
}
return false;
@ -46,7 +48,7 @@ extern "C"
void
llarp_new_config(struct llarp_config **conf)
{
llarp_config *c = new llarp_config;
llarp_config *c = new llarp_config();
*conf = c;
}
@ -72,9 +74,10 @@ extern "C"
{
iter->conf = conf;
std::map< std::string, llarp::Config::section_t & > sections = {
{"network", conf->impl.network}, {"connect", conf->impl.connect},
{"bind", conf->impl.iwp_links}, {"netdb", conf->impl.netdb},
{"dns", conf->impl.dns}, {"services", conf->impl.services}};
{"network", conf->impl.network}, {"connect", conf->impl.connect},
{"system", conf->impl.system}, {"bind", conf->impl.iwp_links},
{"netdb", conf->impl.netdb}, {"dns", conf->impl.dns},
{"services", conf->impl.services}};
for(const auto item : conf->impl.router)
iter->visit(iter, "router", item.first.c_str(), item.second.c_str());
@ -103,16 +106,62 @@ extern "C"
llarp::LogError("failed to open ", fname, " for writing");
return false;
}
f << "# this configuration was auto generated with 'sane' defaults"
<< std::endl;
f << "# change these values as desired" << std::endl;
f << std::endl;
f << "# system settings for priviledges and such" << std::endl;
f << "[system]" << std::endl;
#ifdef _WIN32
f << "# ";
#endif
f << "user=" << DEFAULT_LOKINET_USER << std::endl;
#ifdef _WIN32
f << "# ";
#endif
f << "group=" << DEFAULT_LOKINET_GROUP << std::endl;
f << "# configuration for lokinet network interface" << std::endl;
f << "[network]" << std::endl;
f << "# interface name" << std::endl;
#ifdef _WIN32
// comment out ifname section for windows
f << "# ";
#endif
f << "ifname=lokitun0" << std::endl;
f << "# ip range for interface" << std::endl;
f << "addr=10.0.0.1/16" << std::endl;
f << std::endl;
f << "# dns provider configuration section" << std::endl;
f << "[dns]" << std::endl;
f << "# opennic us resolver" << std::endl;
f << "upstream=" << DEFAULT_RESOLVER_US << std::endl;
f << "# opennic eu resolver" << std::endl;
f << "upstream=" << DEFAULT_RESOLVER_EU << std::endl;
f << "# opennic au resolver" << std::endl;
f << "upstream=" << DEFAULT_RESOLVER_AU << std::endl;
f << "bind=127.3.2.1:53" << std::endl;
f << std::endl;
f << "[netdb]" << std::endl;
f << "dir=netdb" << std::endl;
f << std::endl;
f << "# publish network interfaces for handling inbound traffic"
<< std::endl;
f << "[bind]" << std::endl;
std::string ifname;
if(llarp::GetBestNetIF(ifname, AF_INET))
f << ifname << "=1090" << std::endl;
else
f << "# could not autodetect network interface" << std::endl
<< "# eth0=1090" << std::endl;
f << std::endl;
llarp::LogInfo("Generated new config ", fname);
return true;
}

@ -18,6 +18,7 @@ namespace llarp
section_t iwp_links;
section_t connect;
section_t services;
section_t system;
bool
Load(const char *fname);

@ -51,18 +51,52 @@ namespace llarp
struct PathLookupJob
{
Key_t whoasked;
service::Address target;
uint64_t txid;
PathID_t pathID;
llarp_router *m_router;
std::set< service::IntroSet > localIntroSets;
std::set< Key_t > asked;
int m_TriesLeft = 5;
uint64_t R = 0;
PathLookupJob(llarp_router *r, const PathID_t &localpath, uint64_t tx)
: txid(tx), pathID(localpath), m_router(r)
{
whoasked = r->dht->impl.OurKey();
}
void
TryAgain()
{
--m_TriesLeft;
auto &dht = m_router->dht->impl;
llarp::LogInfo("try lookup again");
dht.TryLookupAgain(
this,
std::bind(&PathLookupJob::OnResult, this, std::placeholders::_1),
R);
}
void
Exausted()
{
llarp::LogWarn("Exausted peers for lookup");
auto path =
m_router->paths.GetByUpstream(m_router->dht->impl.OurKey(), pathID);
if(path)
{
llarp::routing::DHTMessage msg;
msg.M.push_back(new llarp::dht::GotIntroMessage(
std::vector< service::IntroSet >(), txid));
path->SendRoutingMessage(&msg, m_router);
}
else
llarp::LogError("no path for lookup pathid=", pathID);
}
bool
OnResult(const std::vector< service::IntroSet > &results)
{
auto path =
@ -73,23 +107,35 @@ namespace llarp
{
localIntroSets.insert(introset);
}
llarp::routing::DHTMessage msg;
auto sz = localIntroSets.size();
std::vector< service::IntroSet > intros(sz);
for(const auto &i : localIntroSets)
if(sz || target.IsZero() || m_TriesLeft == 0)
{
intros[--sz] = i;
llarp::routing::DHTMessage msg;
std::vector< service::IntroSet > intros(sz);
for(const auto &i : localIntroSets)
{
intros[--sz] = i;
}
llarp::LogInfo("found ", sz, " introsets for txid=", txid);
msg.M.push_back(new llarp::dht::GotIntroMessage(intros, txid));
path->SendRoutingMessage(&msg, m_router);
}
else if(!target.IsZero())
{
if(m_TriesLeft)
{
TryAgain();
return false;
}
}
llarp::LogInfo("found ", sz, " introsets for txid=", txid);
msg.M.push_back(new llarp::dht::GotIntroMessage(intros, txid));
path->SendRoutingMessage(&msg, m_router);
}
else
{
llarp::LogWarn("no local path for reply on PathTagLookupJob pathid=",
pathID);
}
delete this;
return true;
}
};
@ -110,8 +156,10 @@ namespace llarp
TXOwner ownerKey;
ownerKey.node = peer;
ownerKey.txid = id;
SearchJob job(from, txid,
[](const std::vector< service::IntroSet > &) {});
SearchJob job(
from, txid,
[](const std::vector< service::IntroSet > &) -> bool { return true; },
[]() {});
pendingTX[ownerKey] = job;
auto msg = new llarp::DHTImmeidateMessage(peer);
msg->msgs.push_back(new PublishIntroMessage(introset, id, S, E));
@ -130,12 +178,14 @@ namespace llarp
j->localIntroSets = FindRandomIntroSetsWithTag(tag);
SearchJob job(
OurKey(), txid,
std::bind(&PathLookupJob::OnResult, j, std::placeholders::_1));
std::bind(&PathLookupJob::OnResult, j, std::placeholders::_1),
[j]() { delete j; });
pendingTX[ownerKey] = job;
auto msg = new llarp::DHTImmeidateMessage(askpeer);
auto dhtmsg = new FindIntroMessage(tag, id);
dhtmsg->R = 5;
j->R = 5;
msg->msgs.push_back(dhtmsg);
llarp::LogInfo("asking ", askpeer, " for tag ", tag.ToString(), " with ",
j->localIntroSets.size(), " local tags txid=", txid);
@ -144,22 +194,30 @@ namespace llarp
void
Context::LookupIntroSetForPath(const service::Address &addr, uint64_t txid,
const llarp::PathID_t &path,
const Key_t &askpeer)
const llarp::PathID_t &path, Key_t askpeer)
{
auto id = ++ids;
TXOwner ownerKey;
ownerKey.node = askpeer;
ownerKey.txid = id;
PathLookupJob *j = new PathLookupJob(router, path, txid);
j->target = addr;
j->R = 5;
j->asked.emplace(askpeer);
Key_t us = OurKey();
j->asked.emplace(us);
SearchJob job(
OurKey(), txid,
std::bind(&PathLookupJob::OnResult, j, std::placeholders::_1));
std::bind(&PathLookupJob::OnResult, j, std::placeholders::_1),
[j]() { delete j; });
pendingTX[ownerKey] = job;
auto msg = new llarp::DHTImmeidateMessage(askpeer);
auto dhtmsg = new FindIntroMessage(addr, id);
auto dhtmsg = new FindIntroMessage(id, addr);
dhtmsg->R = 5;
msg->msgs.push_back(dhtmsg);
llarp::LogInfo("asking ", askpeer, " for ", addr.ToString(),
" with txid=", id);
router->SendToOrQueue(askpeer, msg);
}
@ -169,8 +227,9 @@ namespace llarp
std::set< service::IntroSet > found;
auto &nodes = services->nodes;
if(nodes.size() == 0)
{
return found;
}
auto itr = nodes.begin();
// start at random middle point
auto start = llarp_randint() % nodes.size();
@ -209,7 +268,8 @@ namespace llarp
if(target == ourKey)
{
// we are the target, give them our RC
replies.push_back(new GotRouterMessage(requester, txid, &router->rc));
replies.push_back(
new GotRouterMessage(requester, txid, &router->rc, false));
return;
}
Key_t next;
@ -219,8 +279,8 @@ namespace llarp
if(next == target)
{
// we know it
replies.push_back(
new GotRouterMessage(requester, txid, nodes->nodes[target].rc));
replies.push_back(new GotRouterMessage(
requester, txid, nodes->nodes[target].rc, false));
}
else if(recursive) // are we doing a recursive lookup?
{
@ -230,7 +290,8 @@ namespace llarp
// so we won't ask neighboor recursively, tell them we don't have it
llarp::LogInfo("we aren't closer to ", target, " than ", next,
" so we end it here");
replies.push_back(new GotRouterMessage(requester, txid, nullptr));
replies.push_back(
new GotRouterMessage(requester, txid, nullptr, false));
}
else
{
@ -246,7 +307,8 @@ namespace llarp
llarp::LogInfo("we don't have ", target,
" and this was an iterative request so telling ",
requester, " that we don't have it");
replies.push_back(new GotRouterMessage(requester, txid, nullptr));
replies.push_back(
new GotRouterMessage(requester, txid, nullptr, false));
}
}
else
@ -255,7 +317,8 @@ namespace llarp
llarp::LogInfo("we don't have ", target,
" and have no closer peers so telling ", requester,
" that we don't have it");
replies.push_back(new GotRouterMessage(requester, txid, nullptr));
replies.push_back(
new GotRouterMessage(requester, txid, nullptr, false));
}
}
@ -330,47 +393,100 @@ namespace llarp
{1000, this, &handle_cleaner_timer});
}
void
Context::DHTSendTo(const Key_t &peer, IMessage *msg)
{
auto m = new llarp::DHTImmeidateMessage(peer);
m->msgs.push_back(msg);
router->SendToOrQueue(peer, m);
}
bool
Context::RelayRequestForPath(const llarp::PathID_t &id, const IMessage *msg)
{
llarp::routing::DHTMessage reply;
if(!msg->HandleMessage(router->dht, reply.M))
return false;
auto path = router->paths.GetByUpstream(router->pubkey(), id);
return path && path->SendRoutingMessage(&reply, router);
if(reply.M.size())
{
auto path = router->paths.GetByUpstream(router->pubkey(), id);
return path && path->SendRoutingMessage(&reply, router);
}
return true;
}
/// handles replying with a GIM for a lookup
struct IntroSetInformJob
{
service::Address target;
uint64_t R = 0;
int m_TriesLeft = 5;
std::set< service::IntroSet > localIntroSets;
Key_t replyNode;
std::set< Key_t > asked;
Key_t whoasked;
uint64_t txid;
llarp_router *m_Router;
IntroSetInformJob(llarp_router *r, const Key_t &replyTo, uint64_t id)
: replyNode(replyTo), txid(id), m_Router(r)
: whoasked(replyTo), txid(id), m_Router(r)
{
}
void
Exausted()
{
auto msg = new llarp::DHTImmeidateMessage(whoasked);
msg->msgs.push_back(new GotIntroMessage({}, txid));
m_Router->SendToOrQueue(whoasked, msg);
}
void
TryAgain()
{
--m_TriesLeft;
llarp::LogInfo("try lookup again");
auto &dht = m_Router->dht->impl;
dht.TryLookupAgain(this,
std::bind(&IntroSetInformJob::OnResult, this,
std::placeholders::_1),
R);
}
bool
OnResult(const std::vector< llarp::service::IntroSet > &results)
{
for(const auto &introset : results)
{
localIntroSets.insert(introset);
localIntroSets.insert(std::move(introset));
}
if(replyNode != m_Router->dht->impl.OurKey())
if(whoasked != m_Router->dht->impl.OurKey())
{
std::vector< service::IntroSet > reply;
for(const auto &introset : localIntroSets)
size_t sz = localIntroSets.size();
if(sz || target.IsZero() || m_TriesLeft == 0)
{
reply.push_back(introset);
std::vector< service::IntroSet > reply;
for(const auto &introset : localIntroSets)
{
reply.push_back(std::move(introset));
}
localIntroSets.clear();
auto msg = new llarp::DHTImmeidateMessage(whoasked);
msg->msgs.push_back(new GotIntroMessage(reply, txid));
m_Router->SendToOrQueue(whoasked, msg);
}
else if(!target.IsZero())
{
if(m_TriesLeft)
{
TryAgain();
return false;
}
}
auto msg = new llarp::DHTImmeidateMessage(replyNode);
msg->msgs.push_back(new GotIntroMessage(reply, txid));
m_Router->SendToOrQueue(replyNode, msg);
}
delete this;
else
{
llarp::LogWarn("we asked for something without a path?");
}
return true;
}
};
@ -389,7 +505,8 @@ namespace llarp
j->localIntroSets = include;
SearchJob job(
whoasked, txid,
std::bind(&IntroSetInformJob::OnResult, j, std::placeholders::_1));
std::bind(&IntroSetInformJob::OnResult, j, std::placeholders::_1),
[j]() { delete j; });
pendingTX[ownerKey] = job;
auto msg = new llarp::DHTImmeidateMessage(askpeer);
@ -401,7 +518,7 @@ namespace llarp
void
Context::LookupIntroSet(const service::Address &addr, const Key_t &whoasked,
uint64_t txid, const Key_t &askpeer, bool iterative,
uint64_t txid, const Key_t &askpeer, uint64_t R,
std::set< Key_t > excludes)
{
auto id = ++ids;
@ -412,14 +529,22 @@ namespace llarp
ownerKey.node = askpeer;
ownerKey.txid = id;
IntroSetInformJob *j = new IntroSetInformJob(router, whoasked, txid);
j->target = addr;
for(const auto &item : excludes)
j->asked.emplace(item);
j->R = R;
SearchJob job(
whoasked, txid, addr, excludes,
std::bind(&IntroSetInformJob::OnResult, j, std::placeholders::_1));
whoasked, txid, addr.ToKey(), {},
std::bind(&IntroSetInformJob::OnResult, j, std::placeholders::_1),
[j]() { delete j; });
pendingTX[ownerKey] = job;
auto msg = new llarp::DHTImmeidateMessage(askpeer);
auto dhtmsg = new FindIntroMessage(addr, id);
auto dhtmsg = new FindIntroMessage(id, addr);
dhtmsg->R = R;
msg->msgs.push_back(dhtmsg);
llarp::LogInfo("asking ", askpeer, " for ", addr.ToString(),
" on request of ", whoasked);
router->SendToOrQueue(askpeer, msg);
}

@ -35,7 +35,8 @@ namespace llarp
// bad msg size?
if(strbuf.sz != 1)
return false;
llarp::LogInfo("Handle DHT message ", *strbuf.base);
llarp::LogInfo("Handle DHT message ", *strbuf.base,
" relayed=", dec->relayed);
switch(*strbuf.base)
{
case 'F':
@ -48,15 +49,7 @@ namespace llarp
dec->msg = new FindRouterMessage(dec->From);
break;
case 'S':
if(dec->relayed)
{
llarp::LogWarn(
"GotRouterMessage found when parsing relayed DHT "
"message");
return false;
}
else
dec->msg = new GotRouterMessage(dec->From);
dec->msg = new GotRouterMessage(dec->From, dec->relayed);
break;
case 'I':
dec->msg = new PublishIntroMessage();

@ -27,15 +27,7 @@ namespace llarp
bool
FindIntroMessage::DecodeKey(llarp_buffer_t k, llarp_buffer_t* val)
{
uint64_t i = 0;
bool read = false;
if(!BEncodeMaybeReadDictInt("I", i, read, k, val))
return false;
if(read)
{
iterative = i != 0;
return true;
}
bool read = false;
if(!BEncodeMaybeReadDictEntry("N", N, read, k, val))
return false;
@ -65,12 +57,8 @@ namespace llarp
// message id
if(!BEncodeWriteDictMsgType(buf, "A", "F"))
return false;
// iterative
if(!BEncodeWriteDictInt("I", iterative ? 1 : 0, buf))
return false;
if(N.IsZero())
if(N.Empty())
{
return false;
// r5n counter
if(!BEncodeWriteDictInt("R", R, buf))
return false;
@ -107,36 +95,53 @@ namespace llarp
return false;
}
auto& dht = ctx->impl;
if((!relayed) && dht.FindPendingTX(From, T))
{
llarp::LogWarn("duplicate FIM from ", From, " txid=", T);
return false;
}
Key_t peer;
std::set< Key_t > exclude = {dht.OurKey(), From};
if(N.IsZero())
if(N.Empty())
{
llarp::LogInfo("lookup ", S.ToString());
const auto introset = dht.GetIntroSetByServiceAddress(S);
if(introset)
{
llarp::LogInfo("introset found locally");
service::IntroSet i = *introset;
replies.push_back(new GotIntroMessage({i}, T));
}
else
{
if(iterative)
if(R == 0)
{
// we are iterative and don't have it, reply with a direct reply
// we don't have it, reply with a direct reply
llarp::LogInfo("dont have intro set and no recursion");
replies.push_back(new GotIntroMessage({}, T));
}
else
{
const auto& us = dht.OurKey();
auto target = S.ToKey();
// we are recursive
if(dht.nodes->FindCloseExcluding(S, peer, exclude))
if(dht.nodes->FindCloseExcluding(target, peer, exclude))
{
if(relayed)
dht.LookupIntroSetForPath(S, T, pathID, peer);
else if((peer ^ dht.OurKey())
> (peer
^ From)) // peer is closer than us, recursive search
dht.LookupIntroSet(S, From, T, peer);
else // we are closer than peer so do iterative search
dht.LookupIntroSet(S, From, T, peer, true);
else
{
if((us ^ target) < (peer ^ target))
{
// we are not closer than our peer to the target so don't
// revurse
replies.push_back(new GotIntroMessage({}, T));
}
else if(R >= 1)
dht.LookupIntroSet(S, From, T, peer, R - 1, exclude);
else
dht.LookupIntroSet(S, From, T, peer, 0, exclude);
}
}
else
{
@ -163,7 +168,7 @@ namespace llarp
else
{
auto introsets = dht.FindRandomIntroSetsWithTag(N);
if(iterative || R == 0)
if(R == 0)
{
std::vector< service::IntroSet > reply;
for(const auto& introset : introsets)

@ -45,8 +45,8 @@ namespace llarp
{
if(llarp_rc_verify_sig(&self->router->crypto, &job->result))
{
reply.M.push_back(
new GotRouterMessage(job->target, self->txid, &job->result));
reply.M.push_back(new GotRouterMessage(job->target, self->txid,
&job->result, false));
}
llarp_rc_free(&job->result);
llarp_rc_clear(&job->result);
@ -54,7 +54,7 @@ namespace llarp
else
{
reply.M.push_back(
new GotRouterMessage(job->target, self->txid, nullptr));
new GotRouterMessage(job->target, self->txid, nullptr, false));
}
self->SendReply(&reply);
// TODO: is this okay?
@ -74,7 +74,8 @@ namespace llarp
auto path = dht.router->paths.GetByUpstream(K, pathID);
if(path)
{
replies.push_back(new GotRouterMessage(K, txid, &dht.router->rc));
replies.push_back(
new GotRouterMessage(K, txid, &dht.router->rc, false));
return true;
}
return false;

@ -39,8 +39,11 @@ namespace llarp
auto pending = dht.FindPendingTX(From, T);
if(pending)
{
pending->FoundIntros(I);
dht.RemovePendingLookup(From, T);
if(pending->FoundIntros(I))
{
dht.RemovePendingLookup(From, T);
llarp::LogInfo("removed pending tx from ", From, " txid=", T);
}
return true;
}
else

@ -61,7 +61,15 @@ namespace llarp
GotRouterMessage::HandleMessage(llarp_dht_context *ctx,
std::vector< IMessage * > &replies) const
{
auto &dht = ctx->impl;
auto &dht = ctx->impl;
if(relayed)
{
auto pathset = ctx->impl.router->paths.GetLocalPathSet(pathID);
if(pathset)
{
return pathset->HandleGotRouterMessage(this);
}
}
SearchJob *pending = dht.FindPendingTX(From, txid);
if(pending)
{
@ -71,7 +79,7 @@ namespace llarp
if(pending->requester != dht.OurKey())
{
replies.push_back(new GotRouterMessage(
pending->target, pending->requesterTX, &R[0]));
pending->target, pending->requesterTX, &R[0], false));
}
}
else
@ -101,7 +109,7 @@ namespace llarp
if(pending->requester != dht.OurKey())
{
replies.push_back(new GotRouterMessage(
pending->target, pending->requesterTX, nullptr));
pending->target, pending->requesterTX, nullptr, false));
}
}
}

@ -67,7 +67,6 @@ namespace llarp
return false;
}
dht.services->PutNode(I);
llarp::LogInfo("Put Introset for ", I.A.Addr().ToString());
replies.push_back(new GotIntroMessage({I}, txID));
Key_t peer;
std::set< Key_t > exclude;

@ -24,8 +24,9 @@ namespace llarp
SearchJob::SearchJob(const Key_t &asker, uint64_t tx, const Key_t &key,
const std::set< Key_t > &excludes,
IntroSetHookFunc foundIntroset)
IntroSetHookFunc foundIntroset, DoneFunc done)
: foundIntroHook(foundIntroset)
, onDone(done)
, started(llarp_time_now_ms())
, requester(asker)
, requesterTX(tx)
@ -35,8 +36,9 @@ namespace llarp
}
SearchJob::SearchJob(const Key_t &asker, uint64_t tx,
IntroSetHookFunc found)
IntroSetHookFunc found, DoneFunc done)
: foundIntroHook(found)
, onDone(done)
, started(llarp_time_now_ms())
, requester(asker)
, requesterTX(tx)
@ -44,12 +46,16 @@ namespace llarp
target.Zero();
}
void
bool
SearchJob::FoundIntros(
const std::vector< llarp::service::IntroSet > &introsets) const
{
if(foundIntroHook)
foundIntroHook(introsets);
if(foundIntroHook && foundIntroHook(introsets))
{
onDone();
return true;
}
return foundIntroHook == nullptr;
}
void

@ -1,9 +0,0 @@
#include <llarp/messages/discard.hpp>
namespace llarp
{
DiscardMessage::~DiscardMessage()
{
llarp::LogDebug("~DiscardMessage");
}
} // namespace llarp

@ -1,3 +1,4 @@
#include <llarp/endian.h>
#include <string.h>
#include "dnsd.hpp" // for llarp_handle_dnsd_recvfrom, dnsc
#include "logger.hpp"
@ -42,9 +43,7 @@ extern "C"
uint16_t
get16bits(const char *&buffer) throw()
{
uint16_t value = static_cast< unsigned char >(buffer[0]);
value = value << 8;
value += static_cast< unsigned char >(buffer[1]);
uint16_t value = bufbe16toh(buffer);
buffer += 2;
return value;
}
@ -52,9 +51,7 @@ extern "C"
uint32_t
get32bits(const char *&buffer) throw()
{
uint32_t value = uint32_t(
(unsigned char)(buffer[0]) << 24 | (unsigned char)(buffer[1]) << 16
| (unsigned char)(buffer[2]) << 8 | (unsigned char)(buffer[3]));
uint32_t value = bufbe32toh(buffer);
buffer += 4;
return value;
}
@ -181,18 +178,14 @@ extern "C"
void
put16bits(char *&buffer, uint16_t value) throw()
{
buffer[0] = (value & 0xFF00) >> 8;
buffer[1] = value & 0xFF;
htobe16buf(buffer, value);
buffer += 2;
}
void
put32bits(char *&buffer, uint32_t value) throw()
{
buffer[0] = (value & 0xFF000000) >> 24;
buffer[1] = (value & 0x00FF0000) >> 16;
buffer[2] = (value & 0x0000FF00) >> 8;
buffer[3] = (value & 0x000000FF) >> 0;
htobe32buf(buffer, value);
buffer += 4;
}

@ -281,6 +281,7 @@ handle_recvfrom(const char *buffer, ssize_t nbytes, const struct sockaddr *from,
// llarp::LogInfo("from ", test);
dnsd_query_hook_response *intercept =
request->context->intercept(request->question.name, fromCopy, request);
// if(!forward_dns_request(m_qName))
if(intercept != nullptr)
{
llarp::LogDebug("hook returned a response");

@ -10,6 +10,11 @@ namespace llarp
UpdateBuffer();
}
Encrypted::Encrypted(const Encrypted& other)
: Encrypted(other._data, other._sz)
{
}
Encrypted::Encrypted(const byte_t* buf, size_t sz) : _sz(sz)
{
_data = new byte_t[sz];

@ -2,6 +2,8 @@
#include <llarp/logic.h>
#include "mem.hpp"
#define EV_TICK_INTERVAL 100
#ifdef __linux__
#include "ev_epoll.hpp"
#endif
@ -47,8 +49,8 @@ llarp_ev_loop_run(struct llarp_ev_loop *ev, struct llarp_logic *logic)
{
while(true)
{
if(ev->tick(100) == -1)
break;
if(ev->tick(EV_TICK_INTERVAL) == -1)
return -1;
llarp_logic_tick(logic);
}
return 0;
@ -59,10 +61,9 @@ llarp_ev_loop_run_single_process(struct llarp_ev_loop *ev,
struct llarp_threadpool *tp,
struct llarp_logic *logic)
{
while(true)
while(ev->running())
{
if(ev->tick(10) == -1)
return;
ev->tick(EV_TICK_INTERVAL);
llarp_logic_tick(logic);
llarp_threadpool_tick(tp);
}

@ -55,6 +55,9 @@ struct llarp_ev_loop
virtual bool
close_ev(llarp::ev_io* ev) = 0;
virtual bool
running() const = 0;
virtual ~llarp_ev_loop(){};
std::list< llarp_udp_io* > udp_listeners;

@ -82,6 +82,12 @@ struct llarp_epoll_loop : public llarp_ev_loop
close(epollfd);
}
bool
running() const
{
return epollfd != -1;
}
bool
init()
{
@ -105,7 +111,6 @@ struct llarp_epoll_loop : public llarp_ev_loop
{
epoll_event events[1024];
int result;
byte_t readbuf[2048];
result = epoll_wait(epollfd, events, 1024, ms);
if(result > 0)
@ -122,11 +127,7 @@ struct llarp_epoll_loop : public llarp_ev_loop
llarp::ev_io* ev = static_cast< llarp::ev_io* >(events[idx].data.ptr);
if(events[idx].events & EPOLLIN)
{
if(ev->read(readbuf, sizeof(readbuf)) == -1)
{
llarp::LogDebug("close ev");
close_ev(ev);
}
ev->read(readbuf, sizeof(readbuf));
}
++idx;
}
@ -142,10 +143,9 @@ struct llarp_epoll_loop : public llarp_ev_loop
{
epoll_event events[1024];
int result;
byte_t readbuf[2048];
do
{
result = epoll_wait(epollfd, events, 1024, 10);
result = epoll_wait(epollfd, events, 1024, EV_TICK_INTERVAL);
if(result > 0)
{
int idx = 0;
@ -160,11 +160,7 @@ struct llarp_epoll_loop : public llarp_ev_loop
llarp::ev_io* ev = static_cast< llarp::ev_io* >(events[idx].data.ptr);
if(events[idx].events & EPOLLIN)
{
if(ev->read(readbuf, sizeof(readbuf)) == -1)
{
llarp::LogDebug("close ev");
close_ev(ev);
}
ev->read(readbuf, sizeof(readbuf));
}
++idx;
}
@ -271,6 +267,8 @@ struct llarp_epoll_loop : public llarp_ev_loop
auto val = write(pipefds[1], &i, sizeof(i));
(void)val;
}
byte_t readbuf[2048];
};
#endif

@ -98,6 +98,12 @@ struct llarp_kqueue_loop : public llarp_ev_loop
return kqueuefd != -1;
}
bool
running() const
{
return kqueuefd != -1;
}
int
tick(int ms)
{
@ -115,14 +121,7 @@ struct llarp_kqueue_loop : public llarp_ev_loop
while(idx < result)
{
llarp::ev_io* ev = static_cast< llarp::ev_io* >(events[idx].udata);
if(ev->read(readbuf, sizeof(readbuf)) == -1)
{
llarp::LogInfo("tick close ev");
close_ev(ev);
// ev->fd = 0;
delete ev;
// break;
}
ev->read(readbuf, sizeof(readbuf));
++idx;
}
}
@ -137,7 +136,7 @@ struct llarp_kqueue_loop : public llarp_ev_loop
{
timespec t;
t.tv_sec = 0;
t.tv_nsec = 10000UL;
t.tv_nsec = 1000UL * EV_TICK_INTERVAL;
struct kevent events[1024];
int result;
byte_t readbuf[2048];
@ -154,14 +153,7 @@ struct llarp_kqueue_loop : public llarp_ev_loop
if(ev && ev->fd)
{
// printf("reading_ev [%x] fd[%d]\n", ev, ev->fd);
if(ev->read(readbuf, sizeof(readbuf)) == -1)
{
llarp::LogInfo("run error reading, should close ev");
close_ev(ev);
// ev->fd = 0;
// delete ev;
// break;
}
ev->read(readbuf, sizeof(readbuf));
}
else
{

@ -97,6 +97,8 @@ struct llarp_win32_loop : public llarp_ev_loop
{
HANDLE iocpfd;
bool _running = false;
llarp_win32_loop() : iocpfd(INVALID_HANDLE_VALUE)
{
WSADATA wsockd;
@ -123,10 +125,10 @@ struct llarp_win32_loop : public llarp_ev_loop
if(iocpfd == INVALID_HANDLE_VALUE)
iocpfd = ::CreateIoCompletionPort(INVALID_HANDLE_VALUE, nullptr, 0, 0);
if(iocpfd != INVALID_HANDLE_VALUE)
return true; // we don't have a socket to attach to this IOCP yet
return false;
if(iocpfd == INVALID_HANDLE_VALUE)
return false;
_running = true;
return true;
}
// it works! -despair86, 3-Aug-18 @0420
@ -153,11 +155,7 @@ struct llarp_win32_loop : public llarp_ev_loop
reinterpret_cast< llarp::udp_listener* >(ev_id);
if(ev && ev->fd)
{
if(ev->getData(readbuf, sizeof(readbuf), iolen) == -1)
{
llarp::LogInfo("tick close ev");
close_ev(ev);
}
ev->getData(readbuf, sizeof(readbuf), iolen);
}
}
++idx;
@ -203,11 +201,7 @@ struct llarp_win32_loop : public llarp_ev_loop
reinterpret_cast< llarp::udp_listener* >(ev_id);
if(ev && ev->fd)
{
if(ev->getData(readbuf, sizeof(readbuf), iolen) == -1)
{
llarp::LogInfo("close ev");
close_ev(ev);
}
ev->getData(readbuf, sizeof(readbuf), iolen);
}
}
++idx;
@ -321,10 +315,16 @@ struct llarp_win32_loop : public llarp_ev_loop
return ret;
}
bool
running() const
{
return _running;
}
void
stop()
{
// do nothing, cancel io in close_ev()
_running = false;
}
};

@ -6,9 +6,9 @@ llarp_link::llarp_link(const llarp_iwp_args& args)
, crypto(args.crypto)
, logic(args.logic)
, worker(args.cryptoworker)
, keyfile(args.keyfile)
, m_name("IWP")
{
strncpy(keyfile, args.keyfile, sizeof(keyfile));
iwp = llarp_async_iwp_new(crypto, logic, worker);
pumpingLogic.store(false);
}
@ -206,15 +206,23 @@ llarp_link::PumpLogic()
void
llarp_link::RemoveSession(llarp_link_session* s)
{
lock_t lock(m_sessions_Mutex);
auto itr = m_sessions.find(s->addr);
if(itr != m_sessions.end())
{
UnmapAddr(s->addr);
s->done();
m_sessions.erase(itr);
delete s;
lock_t lock(m_sessions_Mutex);
auto itr = m_sessions.find(s->addr);
if(itr != m_sessions.end())
{
UnmapAddr(s->addr);
s->done();
m_sessions.erase(itr);
}
}
{
lock_t lock(m_PendingSessions_Mutex);
auto itr = m_PendingSessions.find(s->addr);
if(itr != m_PendingSessions.end())
m_PendingSessions.erase(itr);
}
delete s;
}
uint8_t*
@ -230,7 +238,7 @@ llarp_link::ensure_privkey()
std::error_code ec;
if(!fs::exists(keyfile, ec))
{
if(!keygen(keyfile))
if(!keygen(keyfile.c_str()))
return false;
}
std::ifstream f(keyfile);

@ -1,9 +1,9 @@
#ifdef _MSC_VER
#define NOMINMAX
#endif
#include <llarp/iwp.h>
#include <algorithm>
#include <llarp/crypto.hpp>
#include <llarp/iwp.hpp>
#include <llarp/iwp/server.hpp>
#include <llarp/iwp/session.hpp>
#include "address_info.hpp"

@ -29,10 +29,16 @@ llarp_init_single_process_logic(struct llarp_threadpool* tp)
void
llarp_logic_tick(struct llarp_logic* logic)
{
llarp_timer_tick_all(logic->timer, logic->thread);
llarp_timer_tick_all(logic->timer);
llarp_threadpool_tick(logic->thread);
}
void
llarp_logic_tick_async(struct llarp_logic* logic)
{
llarp_timer_tick_all_async(logic->timer, logic->thread);
}
void
llarp_free_logic(struct llarp_logic** logic)
{

@ -23,7 +23,7 @@ namespace llarp
}
}
template < typename T, size_t align = 8 >
template < typename T, size_t align = 128 >
void
DumpBuffer(const T &buff)
{
@ -35,10 +35,6 @@ namespace llarp
{
printf("%c[1;31m", 27);
}
else
{
printf("%c[0;0m", 27);
}
if(std::isprint(buff.base[idx]))
{
printf("%c", buff.base[idx]);
@ -47,6 +43,10 @@ namespace llarp
{
printf("X");
}
if(buff.base + idx == buff.cur)
{
printf("%c[0;0m", 27);
}
++idx;
if(idx % align == 0)
printf("\n");

@ -132,7 +132,7 @@ struct llarp_nodedb
llarp_rc entry;
llarp::Zero(&entry, sizeof(entry));
llarp_rc_copy(&entry, rc);
entries[pk] = entry;
entries.insert(std::make_pair(pk, entry));
if(llarp_rc_bencode(&entry, &buf))
{
@ -273,8 +273,9 @@ disk_threadworker_setRC(void *user)
llarp_async_verify_rc *verify_request =
static_cast< llarp_async_verify_rc * >(user);
verify_request->valid = verify_request->nodedb->setRC(&verify_request->rc);
llarp_logic_queue_job(verify_request->logic,
{verify_request, &logic_threadworker_callback});
if(verify_request->logic)
llarp_logic_queue_job(verify_request->logic,
{verify_request, &logic_threadworker_callback});
}
// we run the crypto verify in the crypto threadpool worker

@ -78,7 +78,7 @@ namespace llarp
IHopHandler*
MapGet(Map_t& map, const Key_t& k, CheckValue_t check, GetFunc_t get)
{
std::unique_lock< std::mutex > lock(map.first);
util::Lock lock(map.first);
auto range = map.second.equal_range(k);
for(auto i = range.first; i != range.second; ++i)
{
@ -92,7 +92,7 @@ namespace llarp
bool
MapHas(Map_t& map, const Key_t& k, CheckValue_t check)
{
std::unique_lock< std::mutex > lock(map.first);
util::Lock lock(map.first);
auto range = map.second.equal_range(k);
for(auto i = range.first; i != range.second; ++i)
{
@ -106,7 +106,7 @@ namespace llarp
void
MapPut(Map_t& map, const Key_t& k, const Value_t& v)
{
std::unique_lock< std::mutex > lock(map.first);
util::Lock lock(map.first);
map.second.insert(std::make_pair(k, v));
}
@ -114,7 +114,7 @@ namespace llarp
void
MapIter(Map_t& map, Visit_t v)
{
std::unique_lock< std::mutex > lock(map.first);
util::Lock lock(map.first);
for(const auto& item : map.second)
v(item);
}
@ -123,7 +123,7 @@ namespace llarp
void
MapDel(Map_t& map, const Key_t& k, Check_t check)
{
std::unique_lock< std::mutex > lock(map.first);
util::Lock lock(map.first);
auto range = map.second.equal_range(k);
for(auto i = range.first; i != range.second;)
{
@ -185,7 +185,7 @@ namespace llarp
PathContext::GetLocalPathSet(const PathID_t& id)
{
auto& map = m_OurPaths;
std::unique_lock< std::mutex > lock(map.first);
util::Lock lock(map.first);
auto itr = map.second.find(id);
if(itr != map.second.end())
{
@ -216,7 +216,7 @@ namespace llarp
void
PathContext::ExpirePaths()
{
std::unique_lock< std::mutex > lock(m_TransitPaths.first);
util::Lock lock(m_TransitPaths.first);
auto now = llarp_time_now_ms();
auto& map = m_TransitPaths.second;
auto itr = map.begin();
@ -263,6 +263,31 @@ namespace llarp
builder->Tick(now, m_Router);
}
routing::IMessageHandler*
PathContext::GetHandler(const PathID_t& id)
{
routing::IMessageHandler* h = nullptr;
auto pathset = GetLocalPathSet(id);
if(pathset)
{
h = pathset->GetPathByID(id);
}
if(h)
return h;
RouterID us(OurRouterID());
auto& map = m_TransitPaths;
{
util::Lock lock(map.first);
auto range = map.second.equal_range(id);
for(auto i = range.first; i != range.second; ++i)
{
if(i->second->info.upstream == us)
return i->second;
}
}
return nullptr;
}
void
PathContext::AddPathBuilder(llarp_pathbuilder_context* ctx)
{
@ -366,7 +391,10 @@ namespace llarp
msg->X = buf;
msg->Y = Y;
msg->pathid = TXID();
return r->SendToOrQueue(Upstream(), msg);
if(r->SendToOrQueue(Upstream(), msg))
return true;
llarp::LogError("send to ", Upstream(), " failed");
return false;
}
bool
@ -411,7 +439,11 @@ namespace llarp
byte_t tmp[MAX_LINK_MSG_SIZE / 2];
auto buf = llarp::StackBuffer< decltype(tmp) >(tmp);
if(!msg->BEncode(&buf))
{
llarp::LogError("Bencode failed");
llarp::DumpBuffer(buf);
return false;
}
// make nonce
TunnelNonce N;
N.Randomize();

@ -219,6 +219,13 @@ llarp_pathbuilder_context::BuildOne()
llarp_pathbuilder_build_path(job);
}
void
llarp_pathbuilder_context::ManualRebuild(size_t num)
{
while(num--)
BuildOne();
}
struct llarp_pathbuilder_context*
llarp_pathbuilder_context_new(struct llarp_router* router,
struct llarp_dht_context* dht, size_t sz,

@ -81,6 +81,19 @@ namespace llarp
return nullptr;
}
Path*
PathSet::GetPathByID(const PathID_t& id) const
{
auto itr = m_Paths.begin();
while(itr != m_Paths.end())
{
if(itr->second->RXID() == id)
return itr->second;
++itr;
}
return nullptr;
}
size_t
PathSet::NumInStatus(PathStatus st) const
{

@ -9,13 +9,6 @@ namespace llarp
{
}
bool
PoW::BDecode(llarp_buffer_t* buf)
{
// TODO: implement me
return false;
}
bool
PoW::DecodeKey(llarp_buffer_t k, llarp_buffer_t* val)
{
@ -27,7 +20,9 @@ namespace llarp
PoW::BEncode(llarp_buffer_t* buf) const
{
// TODO: implement me
return false;
if(!bencode_start_dict(buf))
return false;
return bencode_end(buf);
}
bool

@ -1,6 +1,6 @@
#include "router.hpp"
#include <llarp/iwp.h>
#include <llarp/proto.h>
#include <llarp/iwp.hpp>
#include <llarp/link_message.hpp>
#include "llarp/iwp/establish_job.hpp"
#include "llarp/iwp/server.hpp"
@ -745,10 +745,10 @@ llarp_router::InitOutboundLink()
return true;
llarp_iwp_args args = {
&crypto, logic, tp, this, transport_keyfile.string().c_str(),
&crypto, logic, tp, this, transport_keyfile.string(),
};
auto link = new(std::nothrow) llarp_link(args);
auto link = new llarp_link(args);
auto afs = {AF_INET, AF_INET6};
@ -1093,6 +1093,7 @@ namespace llarp
const char *key, const char *val)
{
llarp_router *self = static_cast< llarp_router * >(iter->user);
int af;
uint16_t proto;
if(StrEq(val, "eth"))
@ -1117,17 +1118,15 @@ namespace llarp
{
if(!StrEq(key, "*"))
{
llarp::LogInfo("interface specific binding activated");
llarp_iwp_args args = {
&self->crypto,
self->logic,
self->tp,
self,
self->transport_keyfile.string().c_str(),
self->transport_keyfile.string(),
};
link = new(std::nothrow) llarp_link(args);
llarp::LogInfo("interface specific binding activated");
link = new llarp_link(args);
if(link)
{
@ -1175,6 +1174,9 @@ namespace llarp
{
self->connect[key] = val;
}
else if(StrEq(section, "network"))
{
}
else if(StrEq(section, "router"))
{
if(StrEq(key, "nickname"))

@ -14,6 +14,7 @@
#include <llarp/link_message.hpp>
#include <llarp/routing/handler.hpp>
#include <llarp/service.hpp>
#include <llarp/service/tun.hpp>
#include "llarp/iwp/establish_job.hpp"
#include "crypto.hpp"
@ -96,6 +97,8 @@ struct llarp_router
llarp::service::Context hiddenServiceContext;
llarp::service::TunEndpoint *tunEndpoint = nullptr;
llarp_link *outboundLink = nullptr;
std::list< llarp_link * > inboundLinks;

@ -220,13 +220,15 @@ llarp_rc_bencode(const struct llarp_rc *rc, llarp_buffer_t *buff)
if(!bencode_write_bytestring(buff, rc->pubkey, PUBKEYSIZE))
return false;
/* write nickname */
if(!bencode_write_bytestring(buff, "n", 1))
return false;
if(!bencode_write_bytestring(
buff, rc->nickname,
strnlen((char *)rc->nickname, sizeof(rc->nickname))))
return false;
auto nicklen = strnlen((char *)rc->nickname, sizeof(rc->nickname));
if(nicklen)
{
/* write nickname */
if(!bencode_write_bytestring(buff, "n", 1))
return false;
if(!bencode_write_bytestring(buff, rc->nickname, nicklen))
return false;
}
/* write encryption pubkey */
if(!bencode_write_bytestring(buff, "p", 1))

@ -53,6 +53,9 @@ namespace llarp
case 'T':
self->msg = new PathTransferMessage();
break;
case 'H':
self->msg = new service::ProtocolFrame();
break;
default:
llarp::LogError("invalid routing message id: ", *strbuf.cur);
}

@ -22,18 +22,13 @@ namespace llarp
return false;
if(!BEncodeMaybeReadDictInt("S", S, read, key, val))
return false;
if(llarp_buffer_eq(key, "T"))
{
if(T)
delete T;
T = new service::ProtocolFrame();
return T->BDecode(val);
}
if(!BEncodeMaybeReadDictEntry("T", T, read, key, val))
return false;
if(!BEncodeMaybeReadDictInt("V", V, read, key, val))
return false;
if(!BEncodeMaybeReadDictEntry("Y", Y, read, key, val))
return false;
return false;
return read;
}
bool
@ -49,9 +44,7 @@ namespace llarp
if(!BEncodeWriteDictInt("S", S, buf))
return false;
if(!bencode_write_bytestring(buf, "T", 1))
return false;
if(!T->BEncode(buf))
if(!BEncodeWriteDictEntry("T", T, buf))
return false;
if(!BEncodeWriteDictInt("V", LLARP_PROTO_VERSION, buf))
@ -66,31 +59,7 @@ namespace llarp
PathTransferMessage::HandleMessage(IMessageHandler* h,
llarp_router* r) const
{
auto path = r->paths.GetByUpstream(r->pubkey(), P);
if(!path)
{
llarp::LogWarn("No such path for path transfer pathid=", P);
return false;
}
if(!T)
{
llarp::LogError("no data to transfer on data message");
return false;
}
byte_t tmp[service::MAX_PROTOCOL_MESSAGE_SIZE];
auto buf = llarp::StackBuffer< decltype(tmp) >(tmp);
if(!T->BEncode(&buf))
{
llarp::LogWarn("failed to transfer data message, encode failed");
return false;
}
// rewind
buf.sz = buf.cur - buf.base;
buf.cur = buf.base;
// send
llarp::LogInfo("Transfer ", buf.sz, " bytes", " to ", P);
return path->HandleDownstream(buf, Y, r);
return h->HandlePathTransferMessage(this, r);
}
} // namespace routing

@ -65,7 +65,7 @@ namespace llarp
// end introduction list
// topic tag
if(!topic.IsZero())
if(topic.ToString().size())
{
if(!BEncodeWriteDictEntry("n", topic, buf))
return false;
@ -161,7 +161,6 @@ namespace llarp
bool
Identity::BEncode(llarp_buffer_t* buf) const
{
/// TODO: implement me
if(!bencode_start_dict(buf))
return false;
if(!BEncodeWriteDictEntry("e", enckey, buf))
@ -195,10 +194,8 @@ namespace llarp
{
crypto->encryption_keygen(enckey);
crypto->identity_keygen(signkey);
pub.enckey = llarp::seckey_topublic(enckey);
pub.signkey = llarp::seckey_topublic(signkey);
pub.vanity.Zero();
pub.UpdateAddr();
pub.Update(llarp::seckey_topublic(enckey),
llarp::seckey_topublic(signkey));
}
bool
@ -273,7 +270,7 @@ namespace llarp
// rewind and resize buffer
buf.sz = buf.cur - buf.base;
buf.cur = buf.base;
return crypto->verify(A.signkey, buf, Z);
return A.Verify(crypto, buf, Z);
}
bool

@ -38,6 +38,20 @@ namespace llarp
if(addr.FromString(v))
m_PrefetchAddrs.insert(addr);
}
if(k == "netns")
{
m_NetNS = v;
m_OnInit.push_back(std::bind(&Endpoint::IsolateNetwork, this));
}
return true;
}
bool
Endpoint::IsolateNetwork()
{
m_IsolatedWorker = llarp_init_isolated_net_threadpool(
m_Name.c_str(), &SetupIsolatedNetwork, this);
m_IsolatedLogic = llarp_init_single_process_logic(m_IsolatedWorker);
return true;
}
@ -54,7 +68,6 @@ namespace llarp
{
if(context)
{
llarp::LogInfo("BEEP");
byte_t tmp[128] = {0};
memcpy(tmp, "BEEP", 4);
auto buf = llarp::StackBuffer< decltype(tmp) >(tmp);
@ -68,6 +81,19 @@ namespace llarp
}
};
bool
Endpoint::SetupIsolatedNetwork(void* user)
{
return static_cast< Endpoint* >(user)->DoNetworkIsolation();
}
bool
Endpoint::HasPendingPathToService(const Address& addr) const
{
return m_PendingServiceLookups.find(addr)
!= m_PendingServiceLookups.end();
}
void
Endpoint::Tick(llarp_time_t now)
{
@ -146,6 +172,8 @@ namespace llarp
}
for(const auto& introset : itr->second.result)
{
if(HasPendingPathToService(introset.A.Addr()))
continue;
PathAlignJob* j = new PathAlignJob(introset.A.Addr());
if(!EnsurePathToService(j->remote,
std::bind(&PathAlignJob::HandleResult, j,
@ -153,7 +181,7 @@ namespace llarp
10000))
{
llarp::LogWarn("failed to ensure path to ", introset.A.Addr(),
" for tag");
" for tag ", tag.ToString());
delete j;
}
}
@ -254,6 +282,89 @@ namespace llarp
return result;
}
void
Endpoint::PutSenderFor(const ConvoTag& tag, const ServiceInfo& info)
{
auto itr = m_Sessions.find(tag);
if(itr == m_Sessions.end())
{
itr = m_Sessions.insert(std::make_pair(tag, Session{})).first;
}
itr->second.remote = info;
itr->second.lastUsed = llarp_time_now_ms();
}
bool
Endpoint::GetSenderFor(const ConvoTag& tag, ServiceInfo& si) const
{
auto itr = m_Sessions.find(tag);
if(itr == m_Sessions.end())
return false;
si = itr->second.remote;
return true;
}
void
Endpoint::PutIntroFor(const ConvoTag& tag, const Introduction& intro)
{
auto itr = m_Sessions.find(tag);
if(itr == m_Sessions.end())
{
itr = m_Sessions.insert(std::make_pair(tag, Session{})).first;
}
itr->second.intro = intro;
itr->second.lastUsed = llarp_time_now_ms();
}
bool
Endpoint::GetIntroFor(const ConvoTag& tag, Introduction& intro) const
{
auto itr = m_Sessions.find(tag);
if(itr == m_Sessions.end())
return false;
intro = itr->second.intro;
return true;
}
bool
Endpoint::GetConvoTagsForService(const ServiceInfo& info,
std::set< ConvoTag >& tags) const
{
bool inserted = false;
auto itr = m_Sessions.begin();
while(itr != m_Sessions.end())
{
if(itr->second.remote == info)
{
inserted |= tags.insert(itr->first).second;
}
}
return inserted;
}
bool
Endpoint::GetCachedSessionKeyFor(const ConvoTag& tag,
SharedSecret& secret) const
{
auto itr = m_Sessions.find(tag);
if(itr == m_Sessions.end())
return false;
secret = itr->second.sharedKey;
return true;
}
void
Endpoint::PutCachedSessionKeyFor(const ConvoTag& tag, const SharedSecret& k)
{
auto itr = m_Sessions.find(tag);
if(itr == m_Sessions.end())
{
itr = m_Sessions.insert(std::make_pair(tag, Session{})).first;
}
itr->second.sharedKey = k;
itr->second.lastUsed = llarp_time_now_ms();
}
bool
Endpoint::Start()
{
@ -267,7 +378,17 @@ namespace llarp
{
m_Identity.RegenerateKeys(crypto);
}
if(!m_DataHandler)
{
m_DataHandler = this;
}
while(m_OnInit.size())
{
if(m_OnInit.front()())
m_OnInit.pop_front();
else
return false;
}
return true;
}
@ -328,7 +449,7 @@ namespace llarp
bool
Endpoint::PublishIntroSet(llarp_router* r)
{
auto path = GetEstablishedPathClosestTo(m_Identity.pub.Addr());
auto path = GetEstablishedPathClosestTo(m_Identity.pub.Addr().ToRouter());
if(path)
{
m_CurrentPublishTX = llarp_randint();
@ -374,27 +495,30 @@ namespace llarp
struct HiddenServiceAddressLookup : public IServiceLookup
{
Address remote;
Endpoint* endpoint;
typedef std::function< bool(const IntroSet*) > HandlerFunc;
HandlerFunc handle;
HiddenServiceAddressLookup(Endpoint* p, const Address& addr, uint64_t tx)
: IServiceLookup(p, tx), remote(addr), endpoint(p)
HiddenServiceAddressLookup(Endpoint* p, HandlerFunc h,
const Address& addr, uint64_t tx)
: IServiceLookup(p, tx), remote(addr), handle(h)
{
llarp::LogInfo("New hidden service lookup for ", addr.ToString());
}
bool
HandleResponse(const std::set< IntroSet >& results)
{
llarp::LogInfo("found ", results.size(), " for ", remote.ToString());
if(results.size() == 1)
{
llarp::LogInfo("hidden service lookup for ", remote.ToString(),
" success");
endpoint->PutNewOutboundContext(*results.begin());
handle(&*results.begin());
}
else
{
llarp::LogInfo("no response in hidden service lookup for ",
remote.ToString());
handle(nullptr);
}
delete this;
return true;
@ -404,16 +528,26 @@ namespace llarp
BuildRequestMessage()
{
llarp::routing::DHTMessage* msg = new llarp::routing::DHTMessage();
msg->M.push_back(new llarp::dht::FindIntroMessage(remote, txid));
auto FIM = new llarp::dht::FindIntroMessage(txid, remote);
FIM->R = 5;
msg->M.push_back(FIM);
llarp::LogInfo("build request for ", remote);
return msg;
}
};
bool
Endpoint::DoNetworkIsolation()
{
/// TODO: implement me
return false;
}
void
Endpoint::PutNewOutboundContext(const llarp::service::IntroSet& introset)
{
Address addr;
introset.A.CalculateAddress(addr);
introset.A.CalculateAddress(addr.data());
// only add new session if it's not there
if(m_RemoteSessions.find(addr) == m_RemoteSessions.end())
@ -432,6 +566,55 @@ namespace llarp
}
}
bool
Endpoint::HandleGotRouterMessage(const llarp::dht::GotRouterMessage* msg)
{
bool success = false;
if(msg->R.size() == 1)
{
auto itr = m_PendingRouters.find(msg->R[0].pubkey);
if(itr == m_PendingRouters.end())
return false;
llarp_async_verify_rc* job = new llarp_async_verify_rc;
job->nodedb = m_Router->nodedb;
job->cryptoworker = m_Router->tp;
job->diskworker = m_Router->disk;
job->logic = nullptr;
job->hook = nullptr;
llarp_rc_clear(&job->rc);
llarp_rc_copy(&job->rc, &msg->R[0]);
llarp_nodedb_async_verify(job);
return true;
}
return success;
}
void
Endpoint::EnsureRouterIsKnown(const RouterID& router)
{
if(!llarp_nodedb_get_rc(m_Router->nodedb, router))
{
if(m_PendingRouters.find(router) == m_PendingRouters.end())
{
auto path = GetEstablishedPathClosestTo(router);
routing::DHTMessage msg;
auto txid = GenTXID();
msg.M.push_back(
new dht::FindRouterMessage({}, dht::Key_t(router), txid));
if(path->SendRoutingMessage(&msg, m_Router))
{
llarp::LogInfo(Name(), " looking up ", router);
m_PendingRouters.insert(std::make_pair(router, txid));
}
else
{
llarp::LogError("failed to send request for router lookup");
}
}
}
}
void
Endpoint::HandlePathBuilt(path::Path* p)
{
@ -442,8 +625,8 @@ namespace llarp
bool
Endpoint::HandleHiddenServiceFrame(const ProtocolFrame* frame)
{
llarp::LogInfo("handle hidden service frame");
return true;
return frame->AsyncDecryptAndVerify(EndpointLogic(), Crypto(), Worker(),
m_Identity.enckey, m_DataHandler);
}
void
@ -467,11 +650,20 @@ namespace llarp
return m_Parent->HandleHiddenServiceFrame(frame);
}
bool
Endpoint::OnOutboundLookup(const IntroSet* introset)
{
if(!introset)
return false;
PutNewOutboundContext(*introset);
return true;
}
bool
Endpoint::EnsurePathToService(const Address& remote, PathEnsureHook hook,
llarp_time_t timeoutMS)
{
auto path = GetEstablishedPathClosestTo(remote);
auto path = GetEstablishedPathClosestTo(remote.ToRouter());
if(!path)
{
llarp::LogWarn("No outbound path for lookup yet");
@ -497,10 +689,15 @@ namespace llarp
m_PendingServiceLookups.insert(std::make_pair(remote, hook));
HiddenServiceAddressLookup* job =
new HiddenServiceAddressLookup(this, remote, GenTXID());
HiddenServiceAddressLookup* job = new HiddenServiceAddressLookup(
this,
std::bind(&Endpoint::OnOutboundLookup, this, std::placeholders::_1),
remote, GenTXID());
return job->SendRequestViaPath(path, Router());
if(job->SendRequestViaPath(path, Router()))
return true;
llarp::LogError("send via path failed");
return false;
}
Endpoint::OutboundContext::OutboundContext(const IntroSet& intro,
@ -519,51 +716,28 @@ namespace llarp
{
}
void
Endpoint::OutboundContext::ShiftIntroduction()
bool
Endpoint::OutboundContext::OnIntroSetUpdate(const IntroSet* i)
{
for(const auto& intro : currentIntroSet.I)
if(i && i->IsNewerThan(currentIntroSet))
{
if(intro.expiresAt > selectedIntro.expiresAt)
{
selectedIntro = intro;
}
currentIntroSet = *i;
}
return true;
}
bool
Endpoint::OutboundContext::HandleGotIntroMessage(
const llarp::dht::GotIntroMessage* msg)
void
Endpoint::OutboundContext::ShiftIntroduction()
{
if(msg->T != m_UpdateIntrosetTX)
{
llarp::LogError("unwarrented introset message txid=", msg->T);
return false;
}
auto crypto = m_Parent->Crypto();
if(msg->I.size() == 1)
for(const auto& intro : currentIntroSet.I)
{
// found intro set
const auto& introset = msg->I[0];
if(introset.VerifySignature(crypto) && currentIntroSet.A == introset.A)
{
// update
currentIntroSet = introset;
// reset tx
m_UpdateIntrosetTX = 0;
// shift to newest intro
// TODO: check timestamp on introset to make sure it's new enough
ShiftIntroduction();
return true;
}
else
m_Parent->EnsureRouterIsKnown(selectedIntro.router);
if(intro.expiresAt > selectedIntro.expiresAt)
{
llarp::LogError("Signature Error for intro set ", introset);
return false;
selectedIntro = intro;
}
}
llarp::LogError("Bad number of intro sets in response");
return false;
ManualRebuild(numHops);
}
void
@ -572,7 +746,7 @@ namespace llarp
{
if(sequenceNo)
{
AsyncEncrypt(data);
EncryptAndSendTo(data);
}
else
{
@ -585,19 +759,24 @@ namespace llarp
llarp_logic* logic;
llarp_crypto* crypto;
byte_t* sharedKey;
byte_t* remotePubkey;
ServiceInfo remote;
Identity* m_LocalIdentity;
ProtocolMessage msg;
ProtocolFrame frame;
Introduction intro;
std::function< void(ProtocolFrame&) > hook;
IDataHandler* handler;
AsyncIntroGen(llarp_logic* l, llarp_crypto* c, byte_t* key,
byte_t* remote, Identity* localident)
const ServiceInfo& r, Identity* localident,
const Introduction& us, IDataHandler* h)
: logic(l)
, crypto(c)
, sharedKey(key)
, remotePubkey(remote)
, remote(r)
, m_LocalIdentity(localident)
, intro(us)
, handler(h)
{
}
@ -605,6 +784,10 @@ namespace llarp
Result(void* user)
{
AsyncIntroGen* self = static_cast< AsyncIntroGen* >(user);
// put values
self->handler->PutCachedSessionKeyFor(self->msg.tag, self->sharedKey);
self->handler->PutIntroFor(self->msg.tag, self->msg.introReply);
self->handler->PutSenderFor(self->msg.tag, self->remote);
self->hook(self->frame);
delete self;
}
@ -615,9 +798,21 @@ namespace llarp
AsyncIntroGen* self = static_cast< AsyncIntroGen* >(user);
// randomize Nounce
self->frame.N.Randomize();
// ephemeral public key
SecretKey ephem;
self->crypto->encryption_keygen(ephem);
self->frame.H = llarp::seckey_topublic(ephem);
// randomize tag
self->msg.tag.Randomize();
// set sender
self->msg.sender = self->m_LocalIdentity->pub;
// set our introduction
self->msg.introReply = self->intro;
// derive session key
self->crypto->dh_server(self->sharedKey, self->remotePubkey,
self->m_LocalIdentity->enckey, self->frame.N);
self->crypto->dh_server(self->sharedKey,
self->remote.EncryptionPublicKey(), ephem,
self->frame.N);
// encrypt and sign
self->frame.EncryptAndSign(self->crypto, &self->msg, self->sharedKey,
self->m_LocalIdentity->signkey);
@ -629,9 +824,10 @@ namespace llarp
void
Endpoint::OutboundContext::AsyncGenIntro(llarp_buffer_t payload)
{
AsyncIntroGen* ex =
new AsyncIntroGen(m_Parent->Logic(), m_Parent->Crypto(), sharedKey,
currentIntroSet.A.enckey, m_Parent->GetIdentity());
AsyncIntroGen* ex = new AsyncIntroGen(
m_Parent->RouterLogic(), m_Parent->Crypto(), sharedKey,
currentIntroSet.A, m_Parent->GetIdentity(), selectedIntro,
m_Parent->m_DataHandler);
ex->hook = std::bind(&Endpoint::OutboundContext::Send, this,
std::placeholders::_1);
@ -656,10 +852,7 @@ namespace llarp
auto path = GetPathByRouter(selectedIntro.router);
if(path)
{
routing::PathTransferMessage transfer;
transfer.T = &msg;
transfer.Y.Randomize();
transfer.P = selectedIntro.pathID;
routing::PathTransferMessage transfer(msg, selectedIntro.pathID);
llarp::LogInfo("sending frame via ", path->Upstream(), " to ",
path->Endpoint(), " for ", Name());
path->SendRoutingMessage(&transfer, m_Parent->Router());
@ -680,17 +873,18 @@ namespace llarp
void
Endpoint::OutboundContext::UpdateIntroSet()
{
auto path = GetEstablishedPathClosestTo(currentIntroSet.A.Addr());
auto addr = currentIntroSet.A.Addr();
auto path = m_Parent->GetEstablishedPathClosestTo(addr.ToRouter());
if(path)
{
if(m_UpdateIntrosetTX == 0)
{
m_UpdateIntrosetTX = llarp_randint();
routing::DHTMessage msg;
msg.M.push_back(new llarp::dht::FindIntroMessage(
currentIntroSet.A.Addr(), m_UpdateIntrosetTX));
path->SendRoutingMessage(&msg, m_Parent->Router());
}
HiddenServiceAddressLookup* job = new HiddenServiceAddressLookup(
m_Parent,
std::bind(&Endpoint::OutboundContext::OnIntroSetUpdate, this,
std::placeholders::_1),
addr, m_Parent->GenTXID());
if(!job->SendRequestViaPath(path, m_Parent->Router()))
llarp::LogError("send via path failed");
}
else
{
@ -703,7 +897,8 @@ namespace llarp
bool
Endpoint::OutboundContext::Tick(llarp_time_t now)
{
if(selectedIntro.expiresAt >= now || selectedIntro.expiresAt - now < 5000)
if(selectedIntro.expiresAt >= now
|| selectedIntro.expiresAt - now < 30000)
{
UpdateIntroSet();
}
@ -715,9 +910,7 @@ namespace llarp
Endpoint::OutboundContext::SelectHop(llarp_nodedb* db, llarp_rc* prev,
llarp_rc* cur, size_t hop)
{
// TODO: don't hard code
llarp::LogInfo("Select hop ", hop);
if(hop == 3)
if(hop == numHops - 1)
{
auto localcopy = llarp_nodedb_get_rc(db, selectedIntro.router);
if(localcopy)
@ -729,8 +922,10 @@ namespace llarp
{
// we don't have it?
llarp::LogError(
"cannot build aligned path, don't have router for introduction ",
"cannot build aligned path, don't have router for "
"introduction ",
selectedIntro);
m_Parent->EnsureRouterIsKnown(selectedIntro.router);
return false;
}
}
@ -738,18 +933,81 @@ namespace llarp
return llarp_pathbuilder_context::SelectHop(db, prev, cur, hop);
}
uint64_t
Endpoint::GetSeqNoForConvo(const ConvoTag& tag)
{
auto itr = m_Sessions.find(tag);
if(itr == m_Sessions.end())
return 0;
return ++(itr->second.seqno);
}
void
Endpoint::OutboundContext::AsyncEncrypt(llarp_buffer_t payload)
Endpoint::OutboundContext::EncryptAndSendTo(llarp_buffer_t payload)
{
// TODO: implement me
auto path = GetPathByRouter(selectedIntro.router);
if(path)
{
std::set< ConvoTag > tags;
if(!m_Parent->m_DataHandler->GetConvoTagsForService(currentIntroSet.A,
tags))
{
llarp::LogError("no open converstations with remote endpoint?");
return;
}
auto crypto = m_Parent->Crypto();
SharedSecret shared;
routing::PathTransferMessage msg;
ProtocolFrame& f = msg.T;
f.N.Randomize();
f.T = *tags.begin();
f.S = m_Parent->GetSeqNoForConvo(f.T);
if(m_Parent->m_DataHandler->GetCachedSessionKeyFor(f.T, shared))
{
ProtocolMessage m;
m.introReply = selectedIntro;
m.sender = m_Parent->m_Identity.pub;
m.PutBuffer(payload);
if(!f.EncryptAndSign(crypto, &m, shared,
m_Parent->m_Identity.signkey))
{
llarp::LogError("failed to sign");
return;
}
}
else
{
llarp::LogError("No cached session key");
return;
}
msg.P = selectedIntro.pathID;
msg.Y.Randomize();
if(!path->SendRoutingMessage(&msg, m_Parent->Router()))
{
llarp::LogWarn("Failed to send routing message for data");
}
}
else
{
llarp::LogError("no outbound path for sending message");
}
}
llarp_logic*
Endpoint::Logic()
Endpoint::RouterLogic()
{
return m_Router->logic;
}
llarp_logic*
Endpoint::EndpointLogic()
{
return m_IsolatedLogic ? m_IsolatedLogic : m_Router->logic;
}
llarp_crypto*
Endpoint::Crypto()
{

@ -6,16 +6,6 @@ namespace llarp
{
namespace service
{
ServiceInfo::ServiceInfo()
{
vanity.Zero();
m_CachedAddr.Zero();
}
ServiceInfo::~ServiceInfo()
{
}
bool
ServiceInfo::DecodeKey(llarp_buffer_t key, llarp_buffer_t* val)
{
@ -56,7 +46,7 @@ namespace llarp
if(m_CachedAddr.IsZero())
{
Address addr;
CalculateAddress(addr);
CalculateAddress(addr.data());
return addr.ToString();
}
return m_CachedAddr.ToString();
@ -65,9 +55,10 @@ namespace llarp
bool
ServiceInfo::CalculateAddress(byte_t* addr) const
{
byte_t tmp[128];
auto buf = llarp::StackBuffer< decltype(tmp) >(tmp);
assert(BEncode(&buf));
byte_t tmp[256] = {0};
auto buf = llarp::StackBuffer< decltype(tmp) >(tmp);
if(!BEncode(&buf))
return false;
return crypto_generichash(addr, 32, buf.base, buf.cur - buf.base, nullptr,
0)
!= -1;
@ -76,7 +67,7 @@ namespace llarp
bool
ServiceInfo::UpdateAddr()
{
return CalculateAddress(m_CachedAddr);
return CalculateAddress(m_CachedAddr.data());
}
} // namespace service

@ -1,6 +1,7 @@
#include <llarp/routing/handler.hpp>
#include <llarp/service/protocol.hpp>
#include "buffer.hpp"
#include "mem.hpp"
namespace llarp
{
@ -8,25 +9,15 @@ namespace llarp
{
ProtocolMessage::ProtocolMessage()
{
tag.Zero();
}
ProtocolMessage::~ProtocolMessage()
{
}
bool
ProtocolMessage::BEncode(llarp_buffer_t* buf) const
ProtocolMessage::ProtocolMessage(const ConvoTag& t) : tag(t)
{
if(!bencode_start_dict(buf))
return false;
return bencode_end(buf);
}
bool
ProtocolMessage::DecodeKey(llarp_buffer_t key, llarp_buffer_t* val)
ProtocolMessage::~ProtocolMessage()
{
// TODO: implement me
return false;
}
void
@ -37,6 +28,64 @@ namespace llarp
payload.shrink_to_fit();
}
void
ProtocolMessage::ProcessAsync(void* user)
{
ProtocolMessage* self = static_cast< ProtocolMessage* >(user);
self->handler->HandleDataMessage(self);
delete self;
}
bool
ProtocolMessage::DecodeKey(llarp_buffer_t k, llarp_buffer_t* buf)
{
bool read = false;
if(!BEncodeMaybeReadDictInt("a", proto, read, k, buf))
return false;
if(llarp_buffer_eq(k, "d"))
{
llarp_buffer_t strbuf;
if(!bencode_read_string(buf, &strbuf))
return false;
PutBuffer(strbuf);
return true;
}
if(!BEncodeMaybeReadDictEntry("i", introReply, read, k, buf))
return false;
if(!BEncodeMaybeReadDictEntry("s", sender, read, k, buf))
return false;
if(!BEncodeMaybeReadDictEntry("t", tag, read, k, buf))
return false;
if(!BEncodeMaybeReadDictInt("v", version, read, k, buf))
return false;
return read;
}
bool
ProtocolMessage::BEncode(llarp_buffer_t* buf) const
{
if(!bencode_start_dict(buf))
return false;
if(!BEncodeWriteDictInt("a", proto, buf))
return false;
if(!bencode_write_bytestring(buf, "d", 1))
return false;
if(!bencode_write_bytestring(buf, payload.data(), payload.size()))
return false;
if(!BEncodeWriteDictEntry("i", introReply, buf))
return false;
if(!BEncodeWriteDictEntry("s", sender, buf))
return false;
if(!tag.IsZero())
{
if(!BEncodeWriteDictEntry("t", tag, buf))
return false;
}
if(!bencode_write_version_entry(buf))
return false;
return bencode_end(buf);
}
ProtocolFrame::~ProtocolFrame()
{
}
@ -59,6 +108,11 @@ namespace llarp
return false;
if(!BEncodeWriteDictInt("S", S, buf))
return false;
if(S == 0)
{
if(!BEncodeWriteDictEntry("T", T, buf))
return false;
}
if(!BEncodeWriteDictInt("V", version, buf))
return false;
if(!BEncodeWriteDictEntry("Z", Z, buf))
@ -70,6 +124,15 @@ namespace llarp
ProtocolFrame::DecodeKey(llarp_buffer_t key, llarp_buffer_t* val)
{
bool read = false;
if(llarp_buffer_eq(key, "A"))
{
llarp_buffer_t strbuf;
if(!bencode_read_string(val, &strbuf))
return false;
if(strbuf.sz != 1)
return false;
return *strbuf.cur == 'H';
}
if(!BEncodeMaybeReadDictEntry("D", D, read, key, val))
return false;
if(!BEncodeMaybeReadDictEntry("H", H, read, key, val))
@ -78,6 +141,8 @@ namespace llarp
return false;
if(!BEncodeMaybeReadDictInt("S", S, read, key, val))
return false;
if(!BEncodeMaybeReadDictEntry("T", T, read, key, val))
return false;
if(!BEncodeMaybeReadVersion("V", version, LLARP_PROTO_VERSION, read, key,
val))
return false;
@ -86,6 +151,16 @@ namespace llarp
return read;
}
bool
ProtocolFrame::DecryptPayloadInto(llarp_crypto* crypto, byte_t* sharedkey,
ProtocolMessage* msg) const
{
auto buf = D.Buffer();
crypto->xchacha20(buf, sharedkey, N);
msg->PutBuffer(buf);
return true;
}
bool
ProtocolFrame::EncryptAndSign(llarp_crypto* crypto,
const ProtocolMessage* msg,
@ -110,27 +185,142 @@ namespace llarp
return crypto->sign(Z, signingkey, buf);
}
struct AsyncFrameDH
{
llarp_crypto* crypto;
llarp_logic* logic;
ProtocolMessage* msg;
byte_t* localSecret;
PubKey H;
KeyExchangeNonce N;
IDataHandler* handler;
Address remote;
Encrypted D;
AsyncFrameDH(llarp_logic* l, llarp_crypto* c, byte_t* sec,
IDataHandler* h, ProtocolMessage* m,
const ProtocolFrame* frame)
: crypto(c)
, logic(l)
, msg(m)
, localSecret(sec)
, H(frame->H)
, N(frame->N)
, handler(h)
, D(frame->D)
{
}
static void
Work(void* user)
{
AsyncFrameDH* self = static_cast< AsyncFrameDH* >(user);
auto crypto = self->crypto;
SharedSecret shared;
if(!crypto->dh_client(shared, self->H, self->localSecret, self->N))
{
llarp::LogError(
"Failed to derive shared secret for initial message H=", self->H,
" N=", self->N);
delete self->msg;
delete self;
return;
}
auto buf = self->D.Buffer();
crypto->xchacha20(*buf, shared, self->N);
if(!self->msg->BDecode(buf))
{
llarp::LogError("failed to decode inner protocol message");
llarp::DumpBuffer(*buf);
delete self->msg;
delete self;
return;
}
self->handler->PutIntroFor(self->msg->tag, self->msg->introReply);
self->handler->PutSenderFor(self->msg->tag, self->msg->sender);
self->handler->PutCachedSessionKeyFor(self->msg->tag, shared);
self->msg->handler = self->handler;
llarp_logic_queue_job(self->logic,
{self->msg, &ProtocolMessage::ProcessAsync});
delete self;
}
};
bool
ProtocolFrame::AsyncDecryptAndVerify(llarp_logic* logic,
llarp_crypto* crypto,
llarp_threadpool* worker,
byte_t* localSecret,
IDataHandler* handler) const
{
if(S == 0)
{
ProtocolMessage* msg = new ProtocolMessage();
// we need to dh
auto dh =
new AsyncFrameDH(logic, crypto, localSecret, handler, msg, this);
llarp_threadpool_queue_job(worker, {dh, &AsyncFrameDH::Work});
return true;
}
SharedSecret shared;
if(!handler->GetCachedSessionKeyFor(T, shared))
{
llarp::LogError("No cached session for T=", T);
return false;
}
ServiceInfo si;
if(!handler->GetSenderFor(T, si))
{
llarp::LogError("No sender for T=", T);
return false;
}
if(!Verify(crypto, si))
{
llarp::LogError("Signature failure");
return false;
}
ProtocolMessage* msg = new ProtocolMessage();
if(!DecryptPayloadInto(crypto, shared, msg))
{
llarp::LogError("failed to decrypt message");
delete msg;
return false;
}
msg->handler = handler;
llarp_logic_queue_job(logic, {msg, &ProtocolMessage::ProcessAsync});
return true;
}
ProtocolFrame::ProtocolFrame()
{
T.Zero();
}
ProtocolFrame::ProtocolFrame(const ProtocolFrame& other)
: D(other.D), H(other.H), N(other.N), Z(other.Z), T(other.T)
{
}
bool
ProtocolFrame::Verify(llarp_crypto* crypto, byte_t* signkey)
ProtocolFrame::Verify(llarp_crypto* crypto, const ServiceInfo& from) const
{
ProtocolFrame copy(*this);
// save signature
llarp::Signature sig = Z;
// zero out signature for verify
Z.Zero();
copy.Z.Zero();
bool result = false;
// serialize
byte_t tmp[MAX_PROTOCOL_MESSAGE_SIZE];
auto buf = llarp::StackBuffer< decltype(tmp) >(tmp);
if(BEncode(&buf))
if(copy.BEncode(&buf))
{
// rewind buffer
buf.sz = buf.cur - buf.base;
buf.cur = buf.base;
// verify
result = crypto->verify(sig, buf, signkey);
result = from.Verify(crypto, buf, Z);
}
// restore signature
Z = sig;
return result;
}

@ -0,0 +1,14 @@
#include <llarp/service/tun.hpp>
namespace llarp
{
namespace service
{
TunEndpoint::TunEndpoint(const std::string& ifname, llarp_router* r)
: Endpoint("tun-" + ifname, r)
{
m_tunif = tuntap_init();
tuntap_set_ifname(m_tunif, ifname.c_str());
}
} // namespace service
} // namespace llarp

@ -5,6 +5,7 @@
#include <cstring>
#include <llarp/time.h>
#include <functional>
#include <queue>
#include "logger.hpp"
@ -13,6 +14,10 @@
#include <pthread_np.h>
#endif
#ifdef __linux__
#include <sys/wait.h>
#endif
#ifdef _MSC_VER
#include <windows.h>
extern "C" void
@ -23,7 +28,8 @@ namespace llarp
{
namespace thread
{
Pool::Pool(size_t workers, const char *name)
void
Pool::Spawn(size_t workers, const char *name)
{
stop = false;
while(workers--)
@ -46,10 +52,18 @@ namespace llarp
llarp_thread_job *job;
{
lock_t lock(this->queue_mutex);
this->condition.wait(
this->condition.WaitUntil(
lock, [this] { return this->stop || !this->jobs.empty(); });
if(this->stop && this->jobs.empty())
if(this->stop)
{
// discard pending jobs
while(this->jobs.size())
{
delete this->jobs.top().job;
this->jobs.pop();
}
return;
}
job = this->jobs.top().job;
this->jobs.pop();
}
@ -69,7 +83,7 @@ namespace llarp
lock_t lock(queue_mutex);
stop = true;
}
condition.notify_all();
condition.NotifyAll();
}
void
@ -78,7 +92,7 @@ namespace llarp
for(auto &t : threads)
t.join();
threads.clear();
done.notify_all();
done.NotifyAll();
}
void
@ -93,9 +107,86 @@ namespace llarp
jobs.emplace(ids++, new llarp_thread_job(job.user, job.work));
}
condition.notify_one();
condition.NotifyOne();
}
static int
runIsolated(void *arg)
{
IsolatedPool *self = static_cast< IsolatedPool * >(arg);
if(!self->Isolated())
{
llarp::LogError("failed to set up isolated environment");
return 1;
}
auto func = std::bind(&Pool::Spawn, self, self->m_IsolatedWorkers,
self->m_IsolatedName);
func();
return 0;
}
void
IsolatedPool::Spawn(int workers, const char *name)
{
if(m_isolated)
return;
#ifdef __linux__
IsolatedPool *self = this;
self->m_IsolatedName = name;
self->m_IsolatedWorkers = workers;
m_isolated = new std::thread([self] {
pid_t isolated;
isolated =
clone(runIsolated, self->m_childstack + sizeof(self->m_childstack),
self->m_flags | SIGCHLD, self);
if(isolated == -1)
{
llarp::LogError("failed to run isolated threadpool, ",
strerror(errno));
return;
}
llarp::LogInfo("Spawned isolated process pool");
if(waitpid(isolated, nullptr, 0) == -1)
{
llarp::LogError("failed to wait for pid ", isolated, ", ",
strerror(errno));
}
});
#else
llarp::LogError("isolated processes not supported on your platform");
Pool::Spawn(workers, name);
#endif
}
void
IsolatedPool::Join()
{
Pool::Join();
if(m_isolated)
{
m_isolated->join();
delete m_isolated;
m_isolated = nullptr;
}
}
#ifdef __linux__
NetIsolatedPool::NetIsolatedPool(std::function< bool(void *) > setupNet,
void *user)
: IsolatedPool(CLONE_NEWNET)
{
m_NetSetup = setupNet;
m_user = user;
}
#else
NetIsolatedPool::NetIsolatedPool(std::function< bool(void *) > setupNet,
void *user)
: IsolatedPool(0)
{
m_NetSetup = setupNet;
m_user = user;
}
#endif
} // namespace thread
} // namespace llarp
@ -103,12 +194,17 @@ struct llarp_threadpool
{
llarp::thread::Pool *impl;
std::mutex m_access;
llarp::util::Mutex m_access;
std::queue< llarp_thread_job * > jobs;
llarp_threadpool(int workers, const char *name)
: impl(new llarp::thread::Pool(workers, name))
llarp_threadpool(int workers, const char *name, bool isolate,
setup_net_func setup = nullptr, void *user = nullptr)
{
if(isolate)
impl = new llarp::thread::NetIsolatedPool(setup, user);
else
impl = new llarp::thread::Pool();
impl->Spawn(workers, name);
}
llarp_threadpool() : impl(nullptr)
@ -120,7 +216,7 @@ struct llarp_threadpool *
llarp_init_threadpool(int workers, const char *name)
{
if(workers > 0)
return new llarp_threadpool(workers, name);
return new llarp_threadpool(workers, name, false);
else
return nullptr;
}
@ -131,6 +227,13 @@ llarp_init_same_process_threadpool()
return new llarp_threadpool();
}
struct llarp_threadpool *
llarp_init_isolated_net_threadpool(const char *name, setup_net_func setup,
void *context)
{
return new llarp_threadpool(1, name, true, setup, context);
}
void
llarp_threadpool_join(struct llarp_threadpool *pool)
{
@ -155,12 +258,12 @@ llarp_threadpool_stop(struct llarp_threadpool *pool)
void
llarp_threadpool_wait(struct llarp_threadpool *pool)
{
std::mutex mtx;
llarp::util::Mutex mtx;
llarp::LogDebug("threadpool wait");
if(pool->impl)
{
std::unique_lock< std::mutex > lock(mtx);
pool->impl->done.wait(lock);
llarp::util::Lock lock(mtx);
pool->impl->done.Wait(lock);
}
}
@ -176,7 +279,7 @@ llarp_threadpool_queue_job(struct llarp_threadpool *pool,
j->work = job.work;
j->user = job.user;
{
std::unique_lock< std::mutex > lock(pool->m_access);
llarp::util::Lock lock(pool->m_access);
pool->jobs.push(j);
}
}
@ -189,7 +292,7 @@ llarp_threadpool_tick(struct llarp_threadpool *pool)
{
llarp_thread_job *job;
{
std::unique_lock< std::mutex > lock(pool->m_access);
llarp::util::Lock lock(pool->m_access);
job = pool->jobs.front();
pool->jobs.pop();
}

@ -4,6 +4,7 @@
#include <llarp/threadpool.h>
#include <llarp/threading.hpp>
#include <functional>
#include <queue>
#include <thread>
@ -13,15 +14,17 @@ namespace llarp
{
namespace thread
{
typedef std::mutex mtx_t;
typedef std::unique_lock< mtx_t > lock_t;
typedef util::Mutex mtx_t;
typedef util::Lock lock_t;
struct Pool
{
Pool(size_t sz, const char* name);
virtual void
Spawn(size_t sz, const char* name);
void
QueueJob(const llarp_thread_job& job);
void
virtual void
Join();
void
@ -46,11 +49,52 @@ namespace llarp
std::priority_queue< Job_t > jobs;
uint32_t ids = 0;
mtx_t queue_mutex;
std::condition_variable condition;
std::condition_variable done;
util::Condition condition;
util::Condition done;
bool stop;
};
struct IsolatedPool : public Pool
{
IsolatedPool(int flags) : Pool(), m_flags(flags)
{
}
void
Spawn(int workers, const char* name);
void
Join();
// override me to do specific setups after isolation
// return true for success
virtual bool
Isolated()
{
return true;
}
std::thread* m_isolated = nullptr;
int m_flags;
int m_IsolatedWorkers = 0;
const char* m_IsolatedName = nullptr;
char m_childstack[(1024 * 1024 * 8)];
};
struct NetIsolatedPool : public IsolatedPool
{
NetIsolatedPool(std::function< bool(void*) > setupNet, void* user);
bool
Isolated()
{
return m_NetSetup(m_user);
}
std::function< bool(void*) > m_NetSetup;
void* m_user;
};
} // namespace thread
} // namespace llarp

@ -55,11 +55,11 @@ namespace llarp
struct llarp_timer_context
{
std::mutex timersMutex;
llarp::util::Mutex timersMutex;
std::unordered_map< uint32_t, llarp::timer* > timers;
std::priority_queue< llarp::timer* > calling;
std::mutex tickerMutex;
std::condition_variable* ticker = nullptr;
llarp::util::Mutex tickerMutex;
llarp::util::Condition* ticker = nullptr;
std::chrono::milliseconds nextTickLen = std::chrono::milliseconds(100);
uint32_t ids = 0;
@ -86,7 +86,7 @@ struct llarp_timer_context
void
cancel(uint32_t id)
{
std::unique_lock< std::mutex > lock(timersMutex);
llarp::util::Lock lock(timersMutex);
auto itr = timers.find(id);
if(itr == timers.end())
return;
@ -96,7 +96,7 @@ struct llarp_timer_context
void
remove(uint32_t id)
{
std::unique_lock< std::mutex > lock(timersMutex);
llarp::util::Lock lock(timersMutex);
auto itr = timers.find(id);
if(itr == timers.end())
return;
@ -107,7 +107,7 @@ struct llarp_timer_context
uint32_t
call_later(void* user, llarp_timer_handler_func func, uint64_t timeout_ms)
{
std::unique_lock< std::mutex > lock(timersMutex);
llarp::util::Lock lock(timersMutex);
uint32_t id = ++ids;
timers[id] = new llarp::timer(timeout_ms, user, func);
return id;
@ -119,7 +119,7 @@ struct llarp_timer_context
std::list< uint32_t > ids;
{
std::unique_lock< std::mutex > lock(timersMutex);
llarp::util::Lock lock(timersMutex);
for(auto& item : timers)
{
@ -169,7 +169,7 @@ llarp_timer_stop(struct llarp_timer_context* t)
t->timers.clear();
t->stop();
if(t->ticker)
t->ticker->notify_all();
t->ticker->NotifyAll();
}
void
@ -179,8 +179,7 @@ llarp_timer_cancel_job(struct llarp_timer_context* t, uint32_t id)
}
void
llarp_timer_tick_all(struct llarp_timer_context* t,
struct llarp_threadpool* pool)
llarp_timer_tick_all(struct llarp_timer_context* t)
{
if(!t->run())
return;
@ -206,24 +205,37 @@ llarp_timer_tick_all(struct llarp_timer_context* t,
}
}
static void
llarp_timer_tick_all_job(void* user)
{
llarp_timer_tick_all(static_cast< llarp_timer_context* >(user));
}
void
llarp_timer_tick_all_async(struct llarp_timer_context* t,
struct llarp_threadpool* pool)
{
llarp_threadpool_queue_job(pool, {t, llarp_timer_tick_all_job});
}
void
llarp_timer_run(struct llarp_timer_context* t, struct llarp_threadpool* pool)
{
t->ticker = new std::condition_variable;
t->ticker = new llarp::util::Condition();
while(t->run())
{
// wait for timer mutex
if(t->ticker)
{
std::unique_lock< std::mutex > lock(t->tickerMutex);
t->ticker->wait_for(lock, t->nextTickLen);
llarp::util::Lock lock(t->tickerMutex);
t->ticker->WaitFor(lock, t->nextTickLen);
}
if(t->run())
{
std::unique_lock< std::mutex > lock(t->timersMutex);
llarp::util::Lock lock(t->timersMutex);
// we woke up
llarp_timer_tick_all(t, pool);
llarp_timer_tick_all_async(t, pool);
}
}
}

@ -133,7 +133,26 @@ namespace llarp
TransitHop::HandlePathTransferMessage(
const llarp::routing::PathTransferMessage* msg, llarp_router* r)
{
return false;
auto path = r->paths.GetByUpstream(r->pubkey(), msg->P);
if(!path)
{
llarp::LogWarn("No such path for path transfer pathid=", msg->P);
return false;
}
byte_t tmp[service::MAX_PROTOCOL_MESSAGE_SIZE];
auto buf = llarp::StackBuffer< decltype(tmp) >(tmp);
if(!msg->T.BEncode(&buf))
{
llarp::LogWarn("failed to transfer data message, encode failed");
return false;
}
// rewind0
buf.sz = buf.cur - buf.base;
buf.cur = buf.base;
// send
llarp::LogInfo("Transfer ", buf.sz, " bytes", " to ", msg->P);
return path->HandleDownstream(buf, msg->Y, r);
}
} // namespace path

@ -0,0 +1 @@
#include <llarp/service/tun_endpoint.hpp>

@ -21,7 +21,7 @@ struct HiddenServiceTest : public ::testing::Test
SetUp()
{
ident.RegenerateKeys(Crypto());
ident.pub.vanity.Randomize();
ident.pub.RandomizeVanity();
ident.pub.UpdateAddr();
}
};
@ -29,7 +29,7 @@ struct HiddenServiceTest : public ::testing::Test
TEST_F(HiddenServiceTest, TestGenerateIntroSet)
{
llarp::service::Address addr;
ASSERT_TRUE(ident.pub.CalculateAddress(addr));
ASSERT_TRUE(ident.pub.CalculateAddress(addr.data()));
llarp::service::IntroSet I;
while(I.I.size() < 10)
{

@ -1,213 +0,0 @@
/*
* Copyright (c) 2012 Tristan Le Guern <leguern AT medu DOT se>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* Copyright (c) 2016 Mahdi Mokhtari <mokhi64@gmail.com>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <sys/types.h>
#if defined Windows
# include <In6addr.h>
#else /* Unix */
# include <sys/socket.h>
#endif
#if !defined Windows /* Unix :) */
# if defined Linux
# include <linux/if.h>
# else
# include <net/if.h>
# endif
# include <netinet/in.h>
# include <netinet/if_ether.h>
#endif
#include <stdint.h>
#ifndef LIBTUNTAP_H_
# define LIBTUNTAP_H_
/*
* Uniformize macros
* - ETHER_ADDR_LEN: Magic number from IEEE 802.3
* - IF_NAMESIZE: Length of interface external name
* - IF_DESCRSIZE: Length of interface description
* - TUNSDEBUG: ioctl flag to enable the debug mode of a tun device
* - TUNFD_INVALID_VALUE: Invalid value for tun_fd
*/
# if defined ETH_ALEN /* Linux */
# define ETHER_ADDR_LEN ETH_ALEN
# elif defined Windows
# define ETHER_ADDR_LEN 6
# endif
# if defined IFNAMSIZ && !defined IF_NAMESIZE
# define IF_NAMESIZE IFNAMSIZ /* Historical BSD name */
# elif !defined IF_NAMESIZE
# define IF_NAMESIZE 16
# endif
# define IF_DESCRSIZE 50 /* XXX: Tests needed on NetBSD and OpenBSD */
# if defined TUNSETDEBUG
# define TUNSDEBUG TUNSETDEBUG
# endif
# if defined Windows
# define TUNFD_INVALID_VALUE INVALID_HANDLE_VALUE
# else /* Unix */
# define TUNFD_INVALID_VALUE -1
# endif
/*
* Uniformize types
* - t_tun: tun device file descriptor
* - t_tun_in_addr: struct in_addr/IN_ADDR
* - t_tun_in6_addr: struct in6_addr/IN6_ADDR
*/
# if defined Windows
typedef HANDLE t_tun;
typedef IN_ADDR t_tun_in_addr;
typedef IN6_ADDR t_tun_in6_addr;
# else /* Unix */
typedef int t_tun;
typedef struct in_addr t_tun_in_addr;
typedef struct in6_addr t_tun_in6_addr;
# endif
/*
* Windows helpers
*/
# if defined Windows
# define snprintf(x, y, z, ...) _snprintf_s((x), (y), (y), (z), __VA_ARGS__);
# define strncat(x, y, z) strncat_s((x), _countof(x), (y), (z));
# define strdup(x) _strdup(x)
# endif
# define TUNTAP_ID_MAX 256
# define TUNTAP_ID_ANY 257
# define TUNTAP_MODE_ETHERNET 0x0001
# define TUNTAP_MODE_TUNNEL 0x0002
# define TUNTAP_MODE_PERSIST 0x0004
# define TUNTAP_LOG_NONE 0x0000
# define TUNTAP_LOG_DEBUG 0x0001
# define TUNTAP_LOG_INFO 0x0002
# define TUNTAP_LOG_NOTICE 0x0004
# define TUNTAP_LOG_WARN 0x0008
# define TUNTAP_LOG_ERR 0x0016
/* Versioning: 0xMMmm, with 'M' for major and 'm' for minor */
# define TUNTAP_VERSION_MAJOR 0
# define TUNTAP_VERSION_MINOR 3
# define TUNTAP_VERSION ((TUNTAP_VERSION_MAJOR<<8)|TUNTAP_VERSION_MINOR)
# define TUNTAP_GET_FD(x) (x)->tun_fd
/* Handle Windows symbols export */
# if defined Windows
# if defined(tuntap_EXPORTS) /* CMake generated goo */
# define TUNTAP_EXPORT __declspec(dllexport)
# else
# define TUNTAP_EXPORT __declspec(dllimport)
# endif
# else /* Unix */
# define TUNTAP_EXPORT
# endif
# ifdef __cplusplus
extern "C" {
# endif
struct device {
t_tun tun_fd;
int ctrl_sock;
int flags; /* ifr.ifr_flags on Unix */
unsigned char hwaddr[ETHER_ADDR_LEN];
char if_name[IF_NAMESIZE];
#if defined(FreeBSD)
int mode;
#endif
};
/* User definable log callback */
typedef void (*t_tuntap_log)(int, const char *);
TUNTAP_EXPORT t_tuntap_log tuntap_log;
/* Portable "public" functions */
TUNTAP_EXPORT struct device *tuntap_init(void);
TUNTAP_EXPORT int tuntap_version(void);
TUNTAP_EXPORT void tuntap_destroy(struct device *);
TUNTAP_EXPORT void tuntap_release(struct device *);
TUNTAP_EXPORT int tuntap_start(struct device *, int, int);
TUNTAP_EXPORT char *tuntap_get_ifname(struct device *);
TUNTAP_EXPORT int tuntap_set_ifname(struct device *, const char *);
TUNTAP_EXPORT char *tuntap_get_hwaddr(struct device *);
TUNTAP_EXPORT int tuntap_set_hwaddr(struct device *, const char *);
TUNTAP_EXPORT int tuntap_set_descr(struct device *, const char *);
TUNTAP_EXPORT int tuntap_up(struct device *);
TUNTAP_EXPORT int tuntap_down(struct device *);
TUNTAP_EXPORT int tuntap_get_mtu(struct device *);
TUNTAP_EXPORT int tuntap_set_mtu(struct device *, int);
/*
* It's impossible to set single IP for `tun` devices on FreeBSD .
* FreeBSD's `tun` interface needs 2 IP addresses.
* So a new (and backward compatible) version of tuntap_set_ip() is implemented.
*/
TUNTAP_EXPORT int tuntap_set_ip(struct device *, ...);
//TUNTAP_EXPORT int tuntap_set_ip_old(struct device *, const char *, int);
/*TUNTAP_EXPORT int tuntap_set_ip_old(struct device *, const char *, int);*/
TUNTAP_EXPORT int tuntap_read(struct device *, void *, size_t);
TUNTAP_EXPORT int tuntap_write(struct device *, void *, size_t);
TUNTAP_EXPORT int tuntap_get_readable(struct device *);
TUNTAP_EXPORT int tuntap_set_nonblocking(struct device *dev, int);
TUNTAP_EXPORT int tuntap_set_debug(struct device *dev, int);
/* Logging functions */
TUNTAP_EXPORT void tuntap_log_set_cb(t_tuntap_log cb);
void tuntap_log_default(int, const char *);
void tuntap_log_hexdump(void *, size_t);
void tuntap_log_chksum(void *, int);
/* OS specific functions */
int tuntap_sys_start(struct device *, int, int);
void tuntap_sys_destroy(struct device *);
int tuntap_sys_set_hwaddr(struct device *, struct ether_addr *);
int tuntap_sys_set_ipv4(struct device *, t_tun_in_addr *, uint32_t);
#if defined(FreeBSD)
int tuntap_sys_set_ipv4_tap(struct device *, t_tun_in_addr *, uint32_t);
int tuntap_sys_set_ipv4_tun(struct device *dev, t_tun_in_addr *s4, t_tun_in_addr *s4dest, uint32_t bits);
#endif
int tuntap_sys_set_ipv6(struct device *, t_tun_in6_addr *, uint32_t);
int tuntap_sys_set_ifname(struct device *, const char *, size_t);
int tuntap_sys_set_descr(struct device *, const char *, size_t);
# ifdef __cplusplus
}
# endif
#endif

@ -1,163 +0,0 @@
/**
* Copyright (c) 2012, PICHOT Fabien Paul Leonard <pichot.fabienATgmail.com>
* Copyright (c) 2012, Tristan Le Guern <tleguern@bouledef.eu>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
* REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
* INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
* LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
**/
#if defined Windows
#include <windows.h>
#endif
#include <ctype.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include "tuntap.h"
void
tuntap_log_set_cb(t_tuntap_log cb)
{
if(cb == NULL)
{
tuntap_log = tuntap_log_default;
}
tuntap_log = cb;
}
void
tuntap_log_default(int level, const char *errmsg)
{
char *name;
switch(level)
{
case TUNTAP_LOG_DEBUG:
name = "Debug";
break;
case TUNTAP_LOG_INFO:
name = "Info";
break;
case TUNTAP_LOG_NOTICE:
name = "Notice";
break;
case TUNTAP_LOG_WARN:
name = "Warning";
break;
case TUNTAP_LOG_ERR:
name = "Error";
break;
case TUNTAP_LOG_NONE:
default:
name = NULL;
break;
}
if(name == NULL)
{
(void)fprintf(stderr, "%s\n", errmsg);
}
else
{
(void)fprintf(stderr, "%s: %s\n", name, errmsg);
}
}
void
tuntap_log_hexdump(void *data, size_t size)
{
unsigned char *p = (unsigned char *)data;
unsigned int c;
size_t n;
char bytestr[4] = {0};
char addrstr[10] = {0};
char hexstr[16 * 3 + 5] = {0};
char charstr[16 * 1 + 5] = {0};
char buf[1024];
for(n = 1; n <= size; n++)
{
if(n % 16 == 1)
{
/* store address for this line */
snprintf(addrstr, sizeof(addrstr), "%.4lx",
((uintptr_t)p - (uintptr_t)data));
}
c = *p;
if(isalnum(c) == 0)
{
c = '.';
}
/* store hex str (for left side) */
snprintf(bytestr, sizeof(bytestr), "%02X ", *p);
strncat(hexstr, bytestr, sizeof(hexstr) - strlen(hexstr) - 1);
/* store char str (for right side) */
snprintf(bytestr, sizeof(bytestr), "%c", c);
strncat(charstr, bytestr, sizeof(charstr) - strlen(charstr) - 1);
if(n % 16 == 0)
{
/* line completed */
(void)memset(buf, 0, sizeof buf);
(void)snprintf(buf, sizeof buf, "[%4.4s] %-50.50s %s", addrstr, hexstr,
charstr);
tuntap_log(TUNTAP_LOG_NONE, buf);
hexstr[0] = 0;
charstr[0] = 0;
}
else if(n % 8 == 0)
{
/* half line: add whitespaces */
strncat(hexstr, " ", sizeof(hexstr) - strlen(hexstr) - 1);
strncat(charstr, " ", sizeof(charstr) - strlen(charstr) - 1);
}
p++; /* next byte */
}
/* print the rest of the buffer if not empty */
if(strlen(hexstr) > 0)
{
(void)memset(buf, 0, sizeof buf);
(void)snprintf(buf, sizeof buf, "[%4.4s] %-50.50s %s", addrstr, hexstr,
charstr);
tuntap_log(TUNTAP_LOG_NONE, buf);
}
}
void
tuntap_log_chksum(void *addr, int count)
{
int sum;
short *sptr;
char buf[32];
sum = 0;
sptr = (short *)addr;
while(count > 1)
{
sum = sum + *sptr;
count = count - 2;
sptr++;
}
addr = (char *)sptr;
if(count > 0)
sum = sum + *((char *)addr);
sum = ~sum;
(void)memset(buf, 0, sizeof buf);
(void)snprintf(buf, sizeof buf, "Checksum of this block: %0#4x", sum);
tuntap_log(TUNTAP_LOG_NONE, buf);
}

@ -0,0 +1,156 @@
/**
* Copyright (c) 2012, PICHOT Fabien Paul Leonard <pichot.fabienATgmail.com>
* Copyright (c) 2012, Tristan Le Guern <tleguern@bouledef.eu>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
* REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
* INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
* LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
**/
#if defined Windows
#include <windows.h>
#endif
#include <ctype.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <llarp/logger.hpp>
#include "tuntap.h"
extern "C"
{
void
tuntap_log_set_cb(t_tuntap_log cb)
{
if(cb == NULL)
{
tuntap_log = tuntap_log_default;
}
tuntap_log = cb;
}
void
tuntap_log_default(int level, const char *errmsg)
{
switch(level)
{
case TUNTAP_LOG_DEBUG:
llarp::LogDebug(errmsg);
break;
case TUNTAP_LOG_INFO:
llarp::LogInfo(errmsg);
break;
case TUNTAP_LOG_NOTICE:
llarp::LogInfo(errmsg);
break;
case TUNTAP_LOG_WARN:
llarp::LogWarn(errmsg);
break;
case TUNTAP_LOG_ERR:
llarp::LogError(errmsg);
break;
case TUNTAP_LOG_NONE:
default:
return;
}
}
void
tuntap_log_hexdump(void *data, size_t size)
{
unsigned char *p = (unsigned char *)data;
unsigned int c;
size_t n;
char bytestr[4] = {0};
char addrstr[10] = {0};
char hexstr[16 * 3 + 5] = {0};
char charstr[16 * 1 + 5] = {0};
char buf[1024];
for(n = 1; n <= size; n++)
{
if(n % 16 == 1)
{
/* store address for this line */
snprintf(addrstr, sizeof(addrstr), "%.4lx",
((uintptr_t)p - (uintptr_t)data));
}
c = *p;
if(isalnum(c) == 0)
{
c = '.';
}
/* store hex str (for left side) */
snprintf(bytestr, sizeof(bytestr), "%02X ", *p);
strncat(hexstr, bytestr, sizeof(hexstr) - strlen(hexstr) - 1);
/* store char str (for right side) */
snprintf(bytestr, sizeof(bytestr), "%c", c);
strncat(charstr, bytestr, sizeof(charstr) - strlen(charstr) - 1);
if(n % 16 == 0)
{
/* line completed */
(void)memset(buf, 0, sizeof buf);
(void)snprintf(buf, sizeof buf, "[%4.4s] %-50.50s %s", addrstr,
hexstr, charstr);
tuntap_log(TUNTAP_LOG_NONE, buf);
hexstr[0] = 0;
charstr[0] = 0;
}
else if(n % 8 == 0)
{
/* half line: add whitespaces */
strncat(hexstr, " ", sizeof(hexstr) - strlen(hexstr) - 1);
strncat(charstr, " ", sizeof(charstr) - strlen(charstr) - 1);
}
p++; /* next byte */
}
/* print the rest of the buffer if not empty */
if(strlen(hexstr) > 0)
{
(void)memset(buf, 0, sizeof buf);
(void)snprintf(buf, sizeof buf, "[%4.4s] %-50.50s %s", addrstr, hexstr,
charstr);
tuntap_log(TUNTAP_LOG_NONE, buf);
}
}
void
tuntap_log_chksum(void *addr, int count)
{
int sum;
short *sptr;
char buf[32];
sum = 0;
sptr = (short *)addr;
while(count > 1)
{
sum = sum + *sptr;
count = count - 2;
sptr++;
}
addr = (char *)sptr;
if(count > 0)
sum = sum + *((char *)addr);
sum = ~sum;
(void)memset(buf, 0, sizeof buf);
(void)snprintf(buf, sizeof buf, "Checksum of this block: %0#4x", sum);
tuntap_log(TUNTAP_LOG_NONE, buf);
}
}
Loading…
Cancel
Save