Ryan Tharp 6 years ago
commit 4d3ad13daa

@ -1,5 +1,9 @@
LokiNET is the reference implementation of LLARP (Low Latency Anonymous
Routing Protocol) and is licensed under ZLIB license, however the protocol
specifications are placed into the public domian using the CC0 License.
Copyright (c) 2018 Jeff Becker
Win32 port and portions copyright ©2018 Rick V.
Windows NT port and portions Copyright (c) 2018 Rick V.
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
@ -15,4 +19,4 @@ freely, subject to the following restrictions:
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
3. This notice may not be removed or altered from any source distribution.

@ -5,17 +5,48 @@
#include "rq.h"
#include "r3.h"
// 32-bit hosts: use compiler builtins and let compiler
// perform register allocation and/or spilling to core
//
// Confirmed working 3/10/18 -despair
// Less than 5% performance hit,
// all in register loads/stores to/from core
#ifndef __amd64__
#define MULSTEP_gcc(j,h0,h1,h2,h3,h4) \
gj = g[j]; \
h0 += f0 * gj; \
_mm256_storeu_ps(&h[i + j],h0); \
_mm256_storeu_ps((float*)&h[i + j],h0); \
h1 += f1 * gj; \
h2 += f2 * gj; \
h3 += f3 * gj; \
h4 += f4 * gj; \
h0 = _mm256_loadu_ps(&h[i + j + 5]); \
h0 = _mm256_loadu_ps((float*)&h[i + j + 5]); \
h0 += f5 * gj;
#define MULSTEP MULSTEP_gcc
#define MULSTEP_noload(j,h0,h1,h2,h3,h4) \
gj = g[j]; \
h0 += gj*f0; \
_mm256_storeu_ps((float*)&h[i+j], h0); \
h1 += gj*f1; \
h2 += gj*f2; \
h3 += gj*f3; \
h4 += gj*f4; \
h0 = gj* f5;
#define MULSTEP_fromzero(j,h0,h1,h2,h3,h4) \
gj = g[j]; \
h0 = gj*f0; \
_mm256_storeu_ps((float*)&h[i+j], h0); \
h1 = gj*f1; \
h2 = gj*f2; \
h3 = gj*f3; \
h4 = gj*f4; \
h0 = gj*f5;
#else
// 64-bit hosts: use inline asm as before
#define MULSTEP MULSTEP_asm
#define MULSTEP_asm(j,h0,h1,h2,h3,h4) \
gj = g[j]; \
__asm__( \
@ -30,8 +61,6 @@
: "+x"(h0),"+x"(h1),"+x"(h2),"+x"(h3),"+x"(h4) \
: "x"(gj),"x"(f0),"x"(f1),"x"(f2),"x"(f3),"x"(f4),"x"(f5),"m"(h[i+j]),"m"(h[i+j+5]));
#define MULSTEP MULSTEP_asm
#define MULSTEP_noload(j,h0,h1,h2,h3,h4) \
gj = g[j]; \
__asm__( \
@ -57,6 +86,7 @@
"vmulps %5,%11,%0 \n\t" \
: "=&x"(h0),"=&x"(h1),"=&x"(h2),"=&x"(h3),"=&x"(h4) \
: "x"(gj),"x"(f0),"x"(f1),"x"(f2),"x"(f3),"x"(f4),"x"(f5),"m"(h[i+j]));
#endif
static inline __m128i _mm_load_cvtepi8_epi16(const long long *x)
{

@ -21,6 +21,12 @@
#define broadcast(r) _mm256_set1_pd(r)
#define floor(x) _mm256_floor_pd(x)
// 32-bit hosts only
#ifndef __amd64__
#define _mm_extract_epi64(X, N) (__extension__ ({ __v2di __a = (__v2di)(X); \
__a[N];}))
#endif
void rq_encode(unsigned char *c,const modq *f)
{
crypto_int32 f0, f1, f2, f3, f4;

@ -1,5 +1,6 @@
#if __AVX2__
#include <immintrin.h>
#include <smmintrin.h>
#include "mod3.h"
#include "rq.h"
@ -9,6 +10,12 @@
#define v4591_16 _mm256_set1_epi16(4591)
#define v10923_16 _mm256_set1_epi16(10923)
// 32-bit hosts only
#ifndef __amd64__
#define _mm_extract_epi64(X, N) (__extension__ ({ __v2di __a = (__v2di)(X); \
__a[N];}))
#endif
static inline __m256i squeeze(__m256i x)
{
__m256i q = _mm256_mulhrs_epi16(x,v7);

1
doc

@ -0,0 +1 @@
docs

@ -0,0 +1,7 @@
Low Latency Anonymous Routing Protocol Specification
Written in 2017 by Jeff Becker <jeff@i2p.rocks>
To the extent possible under law, the author(s) have dedicated all copyright and related and neighboring rights to
this protocol specfication to the public domain worldwide. This software is distributed without any warranty.
You should have received a copy of the CC0 Public Domain Dedication along with this software. If not, see
<http://creativecommons.org/publicdomain/zero/1.0/>.

@ -0,0 +1,5 @@
Protocol Specifications Directory
All documents in this directory are licened CC0 and placed into the public domain.
Please note that the reference implementation LokiNET is licensed under ZLIB license

@ -29,7 +29,7 @@ namespace llarp
bool
operator<(const RCNode& other) const
{
return rc.OtherIsNewer(other.rc);
return rc.last_updated < other.rc.last_updated;
}
};
@ -53,7 +53,7 @@ namespace llarp
bool
operator<(const ISNode& other) const
{
return introset.OtherIsNewer(other.introset);
return introset.T < other.introset.T;
}
};
} // namespace dht

@ -8,6 +8,7 @@
#include <llarp/ev.h>
#include <llarp/link/session.hpp>
#include <llarp/logic.h>
#include <llarp/time.h>
#include <list>
struct llarp_router;

@ -4,6 +4,7 @@
#include <llarp/crypto.hpp>
#include <llarp/net.hpp>
#include <llarp/router_contact.hpp>
#include <llarp/types.h>
#include <functional>
namespace llarp

@ -1,6 +1,6 @@
#ifndef LLARP_LOGGER_HPP
#define LLARP_LOGGER_HPP
#include <llarp/time.h>
#include <llarp/time.hpp>
#include <ctime>
#include <iomanip>
#include <iostream>
@ -79,6 +79,17 @@ namespace llarp
return std::to_string(id);
}
struct log_timestamp
{
std::string format = "%c %Z";
friend
std::ostream & operator << (std::ostream & out, const log_timestamp & ts)
{
auto now = llarp::Clock_t::to_time_t(llarp::Clock_t::now());
return out << std::put_time(std::localtime(&now), ts.format.c_str());
}
};
/** internal */
template < typename... TArgs >
void
@ -132,7 +143,7 @@ namespace llarp
#endif
std::string tag = fname;
ss << _glog.nodeName << " (" << thread_id_string() << ") "
<< llarp_time_now_ms() << " " << tag << ":" << lineno;
<< log_timestamp() << " " << tag << ":" << lineno;
ss << "\t";
LogAppend(ss, std::forward< TArgs >(args)...);
#ifndef ANDROID

@ -409,6 +409,9 @@ namespace llarp
IHopHandler*
GetByUpstream(const RouterID& id, const PathID_t& path);
IHopHandler*
GetPathForTransfer(const PathID_t & topath);
IHopHandler*
GetByDownstream(const RouterID& id, const PathID_t& path);

@ -137,18 +137,18 @@ namespace llarp
size_t m_NumPaths;
private:
typedef std::pair< RouterID, PathID_t > PathInfo_t;
struct PathInfoHash
{
size_t operator()(const PathInfo_t & i) const
size_t
operator()(const PathInfo_t& i) const
{
return *i.first.data_l() ^ *i.second.data_l();
}
};
typedef std::unordered_map< PathInfo_t, Path* , PathInfoHash> PathMap_t;
typedef std::unordered_map< PathInfo_t, Path*, PathInfoHash > PathMap_t;
PathMap_t m_Paths;
};

@ -77,7 +77,7 @@ namespace llarp
bool
operator!=(const Introduction& other) const
{
return !(*this == other);
return pathID != other.pathID || router != other.router;
}
struct Hash

@ -0,0 +1,12 @@
#ifndef LLARP_TIME_HPP
#define LLARP_TIME_HPP
#include <chrono>
namespace llarp
{
typedef std::chrono::system_clock Clock_t;
}
#endif

@ -143,6 +143,9 @@ extern "C"
char if_name[IF_NAMESIZE];
#if defined(FreeBSD)
int mode;
#endif
#if defined(Windows)
OVERLAPPED ovl;
#endif
};

@ -82,7 +82,7 @@ writecname_dnss_response(std::string cname, const struct sockaddr *from,
dnsd_question_request *request)
{
const size_t BUFFER_SIZE = 1024 + (request->question.name.size() * 2);
char buf[BUFFER_SIZE];
char buf[BUFFER_SIZE]; // heh, another UNIX compiler extension: VLAs in C++
memset(buf, 0, BUFFER_SIZE);
char *write_buffer = buf;
char *bufferBegin = buf;

@ -96,7 +96,7 @@ llarp_ev_udp_sendto(struct llarp_udp_io *udp, const sockaddr *to,
const void *buf, size_t sz)
{
auto ret = static_cast< llarp::ev_io * >(udp->impl)->sendto(to, buf, sz);
if(ret == -1)
if(ret == -1 && errno)
{
llarp::LogWarn("sendto failed ", strerror(errno));
errno = 0;

@ -5,14 +5,16 @@
#ifndef _WIN32
#include <sys/uio.h>
#endif
#ifndef _MSC_VER
#include <unistd.h>
#endif
#include <llarp/buffer.h>
#include <list>
#include <llarp/codel.hpp>
#include <vector>
#ifdef _WIN32
#include <variant>
#endif
#ifndef MAX_WRITE_QUEUE_SIZE
#define MAX_WRITE_QUEUE_SIZE 1024
#endif
@ -29,13 +31,18 @@ namespace llarp
int fd;
ev_io(int f) : fd(f), m_writeq("writequeue"){};
#else
SOCKET fd;
// on windows, udp event loops are socket fds
// and TUN device is a plain old fd
std::variant< SOCKET, HANDLE > fd;
// the unique completion key that helps us to
// identify the object instance for which we receive data
// Here, we'll use the address of the udp_listener instance, converted to
// its literal int/int64 representation.
// Here, we'll use the address of the udp_listener instance, converted
// to its literal int/int64 representation.
ULONG_PTR listener_id = 0;
ev_io(SOCKET f) : fd(f), m_writeq("writequeue"){};
ev_io(HANDLE t)
: fd(t), m_writeq("writequeue"){}; // overload for TUN device, which
// _is_ a regular file descriptor
#endif
virtual int
read(void* buf, size_t sz) = 0;
@ -50,7 +57,8 @@ namespace llarp
#ifndef _WIN32
return write(fd, data, sz) != -1;
#else
return WriteFile((void*)fd, data, sz, nullptr, nullptr);
DWORD w;
return WriteFile(std::get< HANDLE >(fd), data, sz, &w, nullptr);
#endif
}
@ -129,7 +137,7 @@ namespace llarp
#ifndef _WIN32
::close(fd);
#else
closesocket(fd);
closesocket(std::get< SOCKET >(fd));
#endif
};
};
@ -156,7 +164,11 @@ struct llarp_ev_loop
auto ev = create_udp(l, src);
if(ev)
{
#ifdef _WIN32
l->fd = std::get< SOCKET >(ev->fd);
#else
l->fd = ev->fd;
#endif
}
return ev && add_ev(ev, false);
}

@ -46,10 +46,6 @@ namespace llarp
llarp::LogWarn("recvfrom failed");
return -1;
}
if (addr)
{
llarp::LogWarn("no source addr");
}
// Addr is the source
udp->recvfrom(udp, addr, buf, ret);
return 0;
@ -210,13 +206,13 @@ 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)
if(ev)
{
ev->read(readbuf, sizeof(readbuf));
}
else
{
llarp::LogWarn("event[", idx,"] udata is not an ev_io");
llarp::LogWarn("event[", idx, "] udata is not an ev_io");
}
++idx;
}
@ -317,7 +313,6 @@ struct llarp_kqueue_loop : public llarp_ev_loop
close(fd);
return -1;
}
return fd;
}

@ -17,11 +17,13 @@ namespace llarp
// we receive queued data in the OVERLAPPED data field,
// much like the pipefds in the UNIX kqueue and loonix
// epoll handles
// 0 is the read port, 1 is the write port
WSAOVERLAPPED portfds[2] = {0};
WSAOVERLAPPED portfd;
size_t iosz;
udp_listener(SOCKET fd, llarp_udp_io* u) : ev_io(fd), udp(u){};
udp_listener(SOCKET fd, llarp_udp_io* u) : ev_io(fd), udp(u)
{
memset((void*)&portfd, 0, sizeof(WSAOVERLAPPED));
};
~udp_listener()
{
@ -43,8 +45,9 @@ namespace llarp
unsigned long flags = 0;
WSABUF wbuf = {sz, static_cast< char* >(buf)};
// WSARecvFrom
int ret = ::WSARecvFrom(fd, &wbuf, 1, nullptr, &flags, addr, &slen,
&portfds[0], nullptr);
llarp::LogDebug("read ", sz, " bytes into socket");
int ret = ::WSARecvFrom(std::get< SOCKET >(fd), &wbuf, 1, nullptr, &flags,
addr, &slen, &portfd, nullptr);
// 997 is the error code for queued ops
int s_errno = ::WSAGetLastError();
if(ret && s_errno != 997)
@ -74,9 +77,10 @@ namespace llarp
return -1;
}
// WSASendTo
ssize_t sent =
::WSASendTo(fd, &wbuf, 1, nullptr, 0, to, slen, &portfds[1], nullptr);
int s_errno = ::WSAGetLastError();
llarp::LogDebug("write ", sz, " bytes into socket");
ssize_t sent = ::WSASendTo(std::get< SOCKET >(fd), &wbuf, 1, nullptr, 0,
to, slen, &portfd, nullptr);
int s_errno = ::WSAGetLastError();
if(sent && s_errno != 997)
{
llarp::LogWarn("send socket error ", s_errno);
@ -90,8 +94,9 @@ namespace llarp
{
llarp_tun_io* t;
device* tunif;
OVERLAPPED* tun_async;
tun(llarp_tun_io* tio)
: ev_io(-1)
: ev_io(INVALID_HANDLE_VALUE)
, t(tio)
, tunif(tuntap_init())
@ -115,6 +120,12 @@ namespace llarp
ev_io::flush_write();
}
bool
do_write(void* data, size_t sz)
{
return WriteFile(std::get< HANDLE >(fd), data, sz, nullptr, tun_async);
}
int
read(void* buf, size_t sz)
{
@ -136,23 +147,24 @@ namespace llarp
llarp::LogWarn("failed to start interface");
return false;
}
if(tuntap_up(tunif) == -1)
if(tuntap_set_ip(tunif, t->ifaddr, t->ifaddr, t->netmask) == -1)
{
llarp::LogWarn("failed to put interface up: ", strerror(errno));
llarp::LogWarn("failed to set ip");
return false;
}
if(tuntap_set_ip(tunif, t->ifaddr, t->ifaddr, t->netmask) == -1)
if(tuntap_up(tunif) == -1)
{
llarp::LogWarn("failed to set ip");
llarp::LogWarn("failed to put interface up: ", strerror(errno));
return false;
}
fd = (SOCKET)tunif->tun_fd;
if(fd == -1)
fd = tunif->tun_fd;
tun_async = &tunif->ovl;
if(std::get< HANDLE >(fd) == INVALID_HANDLE_VALUE)
return false;
// set non blocking
int on = 1;
return ioctlsocket(fd, FIONBIO, (u_long*)&on) != -1;
// we're already non-blocking
return true;
}
~tun()
@ -199,35 +211,29 @@ struct llarp_win32_loop : public llarp_ev_loop
// as an arch-specific pointer value
ULONG_PTR ev_id = 0;
WSAOVERLAPPED* qdata = nullptr;
int result = 0;
int idx = 0;
BOOL result =
::GetQueuedCompletionStatus(iocpfd, &iolen, &ev_id, &qdata, ms);
do
if(result && qdata)
{
if(ev_id && qdata && iolen)
llarp::udp_listener* ev = reinterpret_cast< llarp::udp_listener* >(ev_id);
if(ev && !ev->fd.valueless_by_exception())
{
llarp::udp_listener* ev =
reinterpret_cast< llarp::udp_listener* >(ev_id);
if(ev && ev->fd)
{
ev->getData(readbuf, sizeof(readbuf), iolen);
}
llarp::LogDebug("size: ", iolen, "\tev_id: ", ev_id,
"\tqdata: ", qdata);
ev->getData(readbuf, sizeof(readbuf), iolen);
}
++idx;
} while(::GetQueuedCompletionStatus(iocpfd, &iolen, &ev_id, &qdata, ms));
// tick_listeners inlined since win32 does not
// implement ev_tun
for(auto& l : udp_listeners)
{
if(l->tick)
l->tick(l);
}
if(!idx)
return -1;
else
{
tick_listeners();
result = idx;
}
return result;
}
@ -244,35 +250,30 @@ struct llarp_win32_loop : public llarp_ev_loop
// as an arch-specific pointer value
ULONG_PTR ev_id = 0;
WSAOVERLAPPED* qdata = nullptr;
int result = 0;
int idx = 0;
int result =
::GetQueuedCompletionStatus(iocpfd, &iolen, &ev_id, &qdata, 10);
// unlike epoll and kqueue, we only need to run so long as the
// system call returns TRUE
do
if(result)
{
if(ev_id && qdata && iolen)
llarp::udp_listener* ev = reinterpret_cast< llarp::udp_listener* >(ev_id);
if(ev && !ev->fd.valueless_by_exception())
{
llarp::udp_listener* ev =
reinterpret_cast< llarp::udp_listener* >(ev_id);
if(ev && ev->fd)
{
ev->getData(readbuf, sizeof(readbuf), iolen);
}
llarp::LogInfo("size: ", iolen, "\tev_id: ", ev_id, "\tqdata: ", qdata);
ev->getData(readbuf, sizeof(readbuf), iolen);
}
++idx;
} while(::GetQueuedCompletionStatus(iocpfd, &iolen, &ev_id, &qdata, 10));
for(auto& l : udp_listeners)
{
if(l->tick)
l->tick(l);
}
if(!idx)
return -1;
else
{
tick_listeners();
result = idx;
}
return result;
}
@ -292,8 +293,8 @@ struct llarp_win32_loop : public llarp_ev_loop
default:
return INVALID_SOCKET;
}
SOCKET fd = ::WSASocket(addr->sa_family, SOCK_DGRAM, 0, nullptr, 0,
WSA_FLAG_OVERLAPPED);
DWORD on = 1;
SOCKET fd = ::socket(addr->sa_family, SOCK_DGRAM, 0);
if(fd == INVALID_SOCKET)
{
perror("WSASocket()");
@ -322,7 +323,8 @@ struct llarp_win32_loop : public llarp_ev_loop
closesocket(fd);
return INVALID_SOCKET;
}
llarp::LogInfo("socket fd is ", fd);
llarp::LogDebug("socket fd is ", fd);
ioctlsocket(fd, FIONBIO, &on);
return fd;
}
@ -331,8 +333,9 @@ struct llarp_win32_loop : public llarp_ev_loop
{
// On Windows, just close the socket to decrease the iocp refcount
// and stop any pending I/O
BOOL stopped = ::CancelIo(reinterpret_cast< HANDLE >(ev->fd));
return closesocket(ev->fd) == 0 && stopped == TRUE;
BOOL stopped =
::CancelIo(reinterpret_cast< HANDLE >(std::get< SOCKET >(ev->fd)));
return closesocket(std::get< SOCKET >(ev->fd)) == 0 && stopped == TRUE;
}
llarp::ev_io*
@ -361,12 +364,37 @@ struct llarp_win32_loop : public llarp_ev_loop
bool
add_ev(llarp::ev_io* ev, bool write)
{
ev->listener_id = reinterpret_cast< ULONG_PTR >(ev);
if(!::CreateIoCompletionPort(reinterpret_cast< HANDLE >(ev->fd), iocpfd,
ev->listener_id, 0))
uint8_t buf[1024];
llarp::udp_listener* udp = nullptr;
llarp::tun* t = nullptr;
ev->listener_id = reinterpret_cast< ULONG_PTR >(ev);
memset(&buf, 0, 1024);
switch(ev->fd.index())
{
delete ev;
return false;
case 0:
udp = dynamic_cast< llarp::udp_listener* >(ev);
if(!::CreateIoCompletionPort((HANDLE)std::get< 0 >(ev->fd), iocpfd,
ev->listener_id, 0))
{
delete ev;
return false;
}
::ReadFile((HANDLE)std::get< 0 >(ev->fd), &buf, 1024, nullptr,
&udp->portfd);
break;
case 1:
t = dynamic_cast< llarp::tun* >(ev);
if(!::CreateIoCompletionPort(std::get< 1 >(ev->fd), iocpfd,
ev->listener_id, 0))
{
delete ev;
return false;
}
::ReadFile(std::get< 1 >(ev->fd), &buf, 1024, nullptr, t->tun_async);
break;
default:
return false;
}
return true;
}

@ -110,7 +110,8 @@ namespace llarp
llarp::Addr tunIp(source_addr);
// related to dns_iptracker_setup_dotLokiLookup(&this->dll, tunIp);
dns_iptracker_setup(this->dll.ip_tracker, tunIp); // claim GW IP to make sure it's not inuse
dns_iptracker_setup(this->dll.ip_tracker,
tunIp); // claim GW IP to make sure it's not inuse
return true;
}
return Endpoint::SetOption(k, v);
@ -150,7 +151,8 @@ namespace llarp
llarp::Addr tunIp(tunif.ifaddr);
dns_iptracker_setup_dotLokiLookup(
&this->dll, tunIp); // just set ups dll to use global iptracker
dns_iptracker_setup(this->dll.ip_tracker, tunIp); // claim GW IP to make sure it's not inuse
dns_iptracker_setup(this->dll.ip_tracker,
tunIp); // claim GW IP to make sure it's not inuse
// set up networking in currrent thread if we are not isolated
if(!SetupNetworking())
@ -162,8 +164,9 @@ namespace llarp
llarp::Addr tunIp(tunif.ifaddr);
this->dll.ip_tracker = new dns_iptracker;
dns_iptracker_setup_dotLokiLookup(
&this->dll, tunIp); // just set ups dll to use global iptracker
dns_iptracker_setup(this->dll.ip_tracker, tunIp); // claim GW IP to make sure it's not inuse
&this->dll, tunIp); // just set ups dll to use global iptracker
dns_iptracker_setup(this->dll.ip_tracker,
tunIp); // claim GW IP to make sure it's not inuse
}
// wait for result for network setup
llarp::LogInfo("waiting for tun interface...");
@ -254,9 +257,8 @@ namespace llarp
{
llarp::LogInfo("Set Up networking for ", Name());
bool result = SetupTun();
#ifndef _WIN32
m_TunSetupResult.set_value(result);
#endif
m_TunSetupResult.set_value(
result); // now that NT has tun, we don't need the CPP guard
if(!NetworkIsIsolated())
{
// need to check to see if we have more than one hidden service

@ -350,7 +350,8 @@ namespace llarp
" bytes");
if(::sendto(l->m_udp.fd, (char*)arg->buf, arg->len, arg->flags,
arg->address, arg->address_len)
== -1)
== -1
&& errno)
{
llarp::LogError("sendto failed: ", strerror(errno));
}

@ -204,6 +204,23 @@ namespace llarp
return m_Router;
}
IHopHandler *
PathContext::GetPathForTransfer(const PathID_t & id)
{
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::PutTransitHop(TransitHop* hop)
{
@ -341,7 +358,6 @@ namespace llarp
}
// initialize parts of the introduction
intro.router = hops[hsz - 1].rc.pubkey;
// TODO: or is it rxid ?
intro.pathID = hops[hsz - 1].txID;
EnterState(ePathBuilding);
}

@ -44,8 +44,8 @@ namespace llarp
RouterProfile::IsGood(uint64_t chances) const
{
return connectTimeoutCount <= connectGoodCount
/// 4 hops + N chances
&& (pathSuccessCount * 4 * chances) >= (pathFailCount / chances);
/// N chances
&& (pathSuccessCount * chances) >= pathFailCount;
}
bool

@ -2,6 +2,7 @@
#include <llarp/router_contact.hpp>
#include <llarp/version.h>
#include <llarp/crypto.hpp>
#include <llarp/time.h>
#include "buffer.hpp"
#include "logger.hpp"
#include "mem.hpp"

@ -572,6 +572,8 @@ namespace llarp
bool
Endpoint::ShouldPublishDescriptors(llarp_time_t now) const
{
if(NumInStatus(llarp::path::ePathEstablished) < 3)
return false;
if(m_IntroSet.HasExpiredIntros(now))
return now - m_LastPublishAttempt >= INTROSET_PUBLISH_RETRY_INTERVAL;
return now - m_LastPublishAttempt >= INTROSET_PUBLISH_INTERVAL;
@ -617,7 +619,6 @@ namespace llarp
{
llarp::routing::DHTMessage* msg = new llarp::routing::DHTMessage();
msg->M.emplace_back(new llarp::dht::FindIntroMessage(txid, remote, 5));
llarp::LogInfo("build request for ", remote);
return msg;
}
};
@ -739,7 +740,6 @@ namespace llarp
p->SetDeadChecker(std::bind(&Endpoint::CheckPathIsDead, this,
std::placeholders::_1,
std::placeholders::_2));
RegenAndPublishIntroSet(llarp_time_now_ms());
path::Builder::HandlePathBuilt(p);
}
@ -762,7 +762,6 @@ namespace llarp
p->Endpoint(), " via ", dst);
if(MarkCurrentIntroBad(llarp_time_now_ms()))
{
SwapIntros();
llarp::LogInfo(Name(), " switched intros to ", remoteIntro.router,
" via ", remoteIntro.pathID);
}
@ -830,9 +829,6 @@ namespace llarp
{
if(latency >= m_MinPathLatency)
{
// rebuild path next tick
llarp_logic_queue_job(RouterLogic(), {this, &HandlePathDead});
return true;
}
return false;
}
@ -1164,6 +1160,10 @@ namespace llarp
lastShift = now;
BuildOneAlignedTo(m_NextIntro.router);
}
else if(shiftedIntro)
{
SwapIntros();
}
return shiftedIntro;
}
@ -1418,13 +1418,15 @@ namespace llarp
{
// shift intro if it expires "soon"
ShiftIntroduction();
}
if(remoteIntro != m_NextIntro)
{
if(GetPathByRouter(m_NextIntro.router) != nullptr)
if(remoteIntro != m_NextIntro)
{
// we can safely set remoteIntro to the next one
SwapIntros();
if(GetPathByRouter(m_NextIntro.router) != nullptr)
{
// we can safely set remoteIntro to the next one
SwapIntros();
llarp::LogInfo(Name(), "swapped intro");
}
}
}
// lookup router in intro if set and unknown
@ -1565,6 +1567,7 @@ namespace llarp
{
llarp::LogDebug("sent message via ", remoteIntro.pathID, " on ",
remoteIntro.router);
lastGoodSend = now;
}
else
{

@ -1,10 +1,8 @@
#include <llarp/time.h>
#include <chrono>
#include <llarp/time.hpp>
namespace llarp
{
typedef std::chrono::system_clock Clock_t;
template < typename Res >
static llarp_time_t
time_since_epoch()
@ -17,6 +15,9 @@ namespace llarp
} // namespace llarp
// use std::chrono because otherwise the network breaks with Daylight Savings
// this time, it doesn't get truncated -despair
// that concern is what drove me back to the POSIX C time functions
// in the first place
llarp_time_t
llarp_time_now_ms()
{

@ -151,11 +151,11 @@ namespace llarp
TransitHop::HandlePathTransferMessage(
const llarp::routing::PathTransferMessage* msg, llarp_router* r)
{
auto path = r->paths.GetByUpstream(r->pubkey(), msg->P);
auto path = r->paths.GetPathForTransfer(msg->P);
if(!path)
{
llarp::routing::DataDiscardMessage discarded(msg->P, msg->S);
path = r->paths.GetByUpstream(r->pubkey(), msg->from);
path = r->paths.GetPathForTransfer(msg->from);
return path && path->SendRoutingMessage(&discarded, r);
}

@ -2,9 +2,9 @@
LokiNet is the reference implementation of LLARP (low latency anonymous routing protocol), a layer 3 onion routing protocol.
You can learn more about the high level design of LLARP [here](doc/high-level.txt)
You can learn more about the high level design of LLARP [here](docs/high-level.txt)
And you can read the LLARP protocol specification [here](doc/proto_v0.txt)
And you can read the LLARP protocol specification [here](docs/proto_v0.txt)
## Building
@ -49,10 +49,4 @@ for a development environment:
## Usage
### Windows
Windows only supports client mode so you run `lokinet.exe` and that's it.
### Linux
see the [lokinet-builder](https://github.com/loki-project/lokinet-builder)

@ -63,7 +63,7 @@ formated_error(LPWSTR pMessage, DWORD m, ...)
LPWSTR pBuffer = NULL;
va_list args = NULL;
va_start(args, pMessage);
va_start(args, m);
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER,
pMessage, m, 0, (LPSTR)&pBuffer, 0, &args);
@ -189,8 +189,11 @@ tuntap_start(struct device *dev, int mode, int tun)
if(mode == TUNTAP_MODE_TUNNEL)
{
tuntap_log(TUNTAP_LOG_NOTICE, "Layer 3 tunneling is not implemented");
return -1;
deviceid = reg_query(NETWORK_ADAPTERS);
snprintf(buf, sizeof buf, "\\\\.\\Global\\%s.tap", deviceid);
tun_fd = CreateFile(buf, GENERIC_WRITE | GENERIC_READ,
FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING,
FILE_ATTRIBUTE_SYSTEM | FILE_FLAG_OVERLAPPED, 0);
}
else if(mode != TUNTAP_MODE_ETHERNET)
{
@ -198,14 +201,9 @@ tuntap_start(struct device *dev, int mode, int tun)
return -1;
}
deviceid = reg_query(NETWORK_ADAPTERS);
snprintf(buf, sizeof buf, "\\\\.\\Global\\%s.tap", deviceid);
tun_fd = CreateFile(buf, GENERIC_WRITE | GENERIC_READ, 0, 0, OPEN_EXISTING,
FILE_ATTRIBUTE_SYSTEM | FILE_FLAG_OVERLAPPED, 0);
if(tun_fd == TUNFD_INVALID_VALUE)
{
int errcode = GetLastError();
tuntap_log(TUNTAP_LOG_ERR, (const char *)formated_error(L"%1%0", errcode));
return -1;
}
@ -241,8 +239,8 @@ tuntap_get_hwaddr(struct device *dev)
char buf[128];
(void)_snprintf(buf, sizeof buf,
"MAC address: %.2x:%.2x:%.2x:%.2x:%.2x:%.2x", hwaddr[0],
hwaddr[1], hwaddr[2], hwaddr[3], hwaddr[4], hwaddr[5]);
"MAC address: %.2x:%.2x:%.2x:%.2x:%.2x:%.2x", hwaddr[0],
hwaddr[1], hwaddr[2], hwaddr[3], hwaddr[4], hwaddr[5]);
tuntap_log(TUNTAP_LOG_DEBUG, buf);
}
return (char *)hwaddr;
@ -274,8 +272,7 @@ tuntap_sys_set_updown(struct device *dev, ULONG flag)
{
char buf[32];
(void)_snprintf(buf, sizeof buf, "Status: %s",
flag ? "Up" : "Down");
(void)_snprintf(buf, sizeof buf, "Status: %s", flag ? "Up" : "Down");
tuntap_log(TUNTAP_LOG_DEBUG, buf);
return 0;
}
@ -330,26 +327,54 @@ tuntap_set_mtu(struct device *dev, int mtu)
int
tuntap_sys_set_ipv4(struct device *dev, t_tun_in_addr *s, uint32_t mask)
{
IPADDR psock[4];
DWORD len;
/* Address + Netmask */
psock[0] = s->S_un.S_addr;
psock[1] = mask;
/* DHCP server address (We don't want it) */
psock[2] = 0;
/* DHCP lease time */
psock[3] = 0;
if(DeviceIoControl(dev->tun_fd, TAP_IOCTL_CONFIG_DHCP_MASQ, &psock,
sizeof(psock), &psock, sizeof(psock), &len, NULL)
== 0)
IPADDR sock[3];
DWORD len, ret;
IPADDR ep[4];
#pragma pack(push)
#pragma pack(1)
struct
{
uint8_t dhcp_opt;
uint8_t length;
uint32_t value[2];
} dns;
#pragma pack(pop)
sock[0] = s->S_un.S_addr;
sock[2] = mask;
sock[1] = sock[0] & sock[2];
ret = DeviceIoControl(dev->tun_fd, TAP_IOCTL_CONFIG_TUN, &sock, sizeof(sock),
&sock, sizeof(sock), &len, NULL);
ep[0] = s->S_un.S_addr;
ep[1] = mask;
ep[2] = (s->S_un.S_addr | ~mask)
- (mask + 1); /* For the 10.x.0.y subnet (in a class C config), _should_
be 10.x.0.254 i think */
ep[3] = 3153600; /* one year */
ret = DeviceIoControl(dev->tun_fd, TAP_IOCTL_CONFIG_DHCP_MASQ, ep, sizeof(ep),
ep, sizeof(ep), &len, NULL);
/* set DNS address to 127.0.0.1 as lokinet-client runs its own DNS resolver
* inline */
dns.dhcp_opt = 6;
dns.length = 4;
dns.value[0] =
htonl(0x7F000001); /* apparently this doesn't show in network properties,
but it works 🤷🏻 */
dns.value[1] = 0;
ret = DeviceIoControl(dev->tun_fd, TAP_IOCTL_CONFIG_DHCP_SET_OPT, &dns,
sizeof(dns), &dns, sizeof(dns), &len, NULL);
if(!ret)
{
int errcode = GetLastError();
tuntap_log(TUNTAP_LOG_ERR, (const char *)formated_error(L"%1%0", errcode));
return -1;
}
return 0;
}
@ -369,12 +394,17 @@ tuntap_read(struct device *dev, void *buf, size_t size)
{
DWORD len;
if(ReadFile(dev->tun_fd, buf, (DWORD)size, &len, NULL) == 0)
if(ReadFile(dev->tun_fd, buf, (DWORD)size, &len, &dev->ovl) == 0)
{
int errcode = GetLastError();
tuntap_log(TUNTAP_LOG_ERR, (const char *)formated_error(L"%1%0", errcode));
return -1;
if (errcode != 997)
{
tuntap_log(TUNTAP_LOG_ERR, (const char *)formated_error(L"%1%0", errcode));
return -1;
}
else
return 0;
}
return 0;
@ -385,12 +415,17 @@ tuntap_write(struct device *dev, void *buf, size_t size)
{
DWORD len;
if(WriteFile(dev->tun_fd, buf, (DWORD)size, &len, NULL) == 0)
if(WriteFile(dev->tun_fd, buf, (DWORD)size, &len, &dev->ovl) == 0)
{
int errcode = GetLastError();
tuntap_log(TUNTAP_LOG_ERR, (const char *)formated_error(L"%1%0", errcode));
return -1;
int errcode = GetLastError();
if (errcode != 997)
{
tuntap_log(TUNTAP_LOG_ERR, (const char *)formated_error(L"%1%0", errcode));
return -1;
}
else
return 0;
}
return 0;
@ -411,7 +446,7 @@ tuntap_set_nonblocking(struct device *dev, int set)
(void)dev;
(void)set;
tuntap_log(TUNTAP_LOG_NOTICE,
"Your system does not support tuntap_set_nonblocking()");
"TUN/TAP devices on Windows are non-blocking by default using either overlapped I/O or IOCPs");
return -1;
}
@ -438,7 +473,6 @@ tuntap_set_descr(struct device *dev, const char *descr)
int
tuntap_set_ifname(struct device *dev, const char *name)
{
/* TODO: Check Windows API to know how to rename an interface */
(void)dev;
(void)name;
tuntap_log(TUNTAP_LOG_NOTICE,

@ -68,6 +68,9 @@ extern "C"
dev->tun_fd = TUNFD_INVALID_VALUE;
dev->ctrl_sock = -1;
dev->flags = 0;
#if defined(Windows)
memset(&dev->ovl, 0, sizeof(OVERLAPPED));
#endif
__tuntap_log = &tuntap_log_default;
return dev;

Loading…
Cancel
Save