Merge branch 'master' of ssh://github.com/loki-project/loki-network

pull/23/head
Jeff 6 years ago
commit 0c4709efdd

@ -1,5 +1,5 @@
Copyright (c) 2018 Jeff Becker Copyright (c) 2018 Jeff Becker
Win32 port and portions copyright ©2018 Rick V. Windows NT port and portions copyright ©2018 Rick V.
This software is provided 'as-is', without any express or implied This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages warranty. In no event will the authors be held liable for any damages

@ -5,17 +5,48 @@
#include "rq.h" #include "rq.h"
#include "r3.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) \ #define MULSTEP_gcc(j,h0,h1,h2,h3,h4) \
gj = g[j]; \ gj = g[j]; \
h0 += f0 * gj; \ h0 += f0 * gj; \
_mm256_storeu_ps(&h[i + j],h0); \ _mm256_storeu_ps((float*)&h[i + j],h0); \
h1 += f1 * gj; \ h1 += f1 * gj; \
h2 += f2 * gj; \ h2 += f2 * gj; \
h3 += f3 * gj; \ h3 += f3 * gj; \
h4 += f4 * gj; \ h4 += f4 * gj; \
h0 = _mm256_loadu_ps(&h[i + j + 5]); \ h0 = _mm256_loadu_ps((float*)&h[i + j + 5]); \
h0 += f5 * gj; 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) \ #define MULSTEP_asm(j,h0,h1,h2,h3,h4) \
gj = g[j]; \ gj = g[j]; \
__asm__( \ __asm__( \
@ -30,8 +61,6 @@
: "+x"(h0),"+x"(h1),"+x"(h2),"+x"(h3),"+x"(h4) \ : "+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])); : "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) \ #define MULSTEP_noload(j,h0,h1,h2,h3,h4) \
gj = g[j]; \ gj = g[j]; \
__asm__( \ __asm__( \
@ -57,6 +86,7 @@
"vmulps %5,%11,%0 \n\t" \ "vmulps %5,%11,%0 \n\t" \
: "=&x"(h0),"=&x"(h1),"=&x"(h2),"=&x"(h3),"=&x"(h4) \ : "=&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])); : "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) static inline __m128i _mm_load_cvtepi8_epi16(const long long *x)
{ {

@ -21,6 +21,12 @@
#define broadcast(r) _mm256_set1_pd(r) #define broadcast(r) _mm256_set1_pd(r)
#define floor(x) _mm256_floor_pd(x) #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) void rq_encode(unsigned char *c,const modq *f)
{ {
crypto_int32 f0, f1, f2, f3, f4; crypto_int32 f0, f1, f2, f3, f4;

@ -1,5 +1,6 @@
#if __AVX2__ #if __AVX2__
#include <immintrin.h> #include <immintrin.h>
#include <smmintrin.h>
#include "mod3.h" #include "mod3.h"
#include "rq.h" #include "rq.h"
@ -9,6 +10,12 @@
#define v4591_16 _mm256_set1_epi16(4591) #define v4591_16 _mm256_set1_epi16(4591)
#define v10923_16 _mm256_set1_epi16(10923) #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) static inline __m256i squeeze(__m256i x)
{ {
__m256i q = _mm256_mulhrs_epi16(x,v7); __m256i q = _mm256_mulhrs_epi16(x,v7);

@ -100,7 +100,8 @@ main(int argc, char *argv[])
conffname = fname.string(); conffname = fname.string();
if(basedir.string().empty()) if(basedir.string().empty())
{ {
if(!llarp_ensure_config(fname.string().c_str(), nullptr, overWrite, asRouter)) if(!llarp_ensure_config(fname.string().c_str(), nullptr, overWrite,
asRouter))
return 1; return 1;
} }
else else

@ -137,18 +137,18 @@ namespace llarp
size_t m_NumPaths; size_t m_NumPaths;
private: private:
typedef std::pair< RouterID, PathID_t > PathInfo_t; typedef std::pair< RouterID, PathID_t > PathInfo_t;
struct PathInfoHash 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(); 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; PathMap_t m_Paths;
}; };

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

@ -82,7 +82,7 @@ writecname_dnss_response(std::string cname, const struct sockaddr *from,
dnsd_question_request *request) dnsd_question_request *request)
{ {
const size_t BUFFER_SIZE = 1024 + (request->question.name.size() * 2); 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); memset(buf, 0, BUFFER_SIZE);
char *write_buffer = buf; char *write_buffer = buf;
char *bufferBegin = 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) const void *buf, size_t sz)
{ {
auto ret = static_cast< llarp::ev_io * >(udp->impl)->sendto(to, buf, 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)); llarp::LogWarn("sendto failed ", strerror(errno));
errno = 0; errno = 0;

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

@ -206,13 +206,13 @@ struct llarp_kqueue_loop : public llarp_ev_loop
while(idx < result) while(idx < result)
{ {
llarp::ev_io* ev = static_cast< llarp::ev_io* >(events[idx].udata); llarp::ev_io* ev = static_cast< llarp::ev_io* >(events[idx].udata);
if (ev) if(ev)
{ {
ev->read(readbuf, sizeof(readbuf)); ev->read(readbuf, sizeof(readbuf));
} }
else else
{ {
llarp::LogWarn("event[", idx,"] udata is not an ev_io"); llarp::LogWarn("event[", idx, "] udata is not an ev_io");
} }
++idx; ++idx;
} }
@ -313,7 +313,6 @@ struct llarp_kqueue_loop : public llarp_ev_loop
close(fd); close(fd);
return -1; return -1;
} }
return fd; return fd;
} }

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

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

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

@ -15,6 +15,9 @@ namespace llarp
} // namespace llarp } // namespace llarp
// use std::chrono because otherwise the network breaks with Daylight Savings // 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_t
llarp_time_now_ms() llarp_time_now_ms()
{ {

@ -49,10 +49,4 @@ for a development environment:
## Usage ## 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) see the [lokinet-builder](https://github.com/loki-project/lokinet-builder)

@ -63,7 +63,7 @@ formated_error(LPWSTR pMessage, DWORD m, ...)
LPWSTR pBuffer = NULL; LPWSTR pBuffer = NULL;
va_list args = NULL; va_list args = NULL;
va_start(args, pMessage); va_start(args, m);
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER, FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER,
pMessage, m, 0, (LPSTR)&pBuffer, 0, &args); 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) if(mode == TUNTAP_MODE_TUNNEL)
{ {
tuntap_log(TUNTAP_LOG_NOTICE, "Layer 3 tunneling is not implemented"); deviceid = reg_query(NETWORK_ADAPTERS);
return -1; 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) else if(mode != TUNTAP_MODE_ETHERNET)
{ {
@ -198,14 +201,9 @@ tuntap_start(struct device *dev, int mode, int tun)
return -1; 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) if(tun_fd == TUNFD_INVALID_VALUE)
{ {
int errcode = GetLastError(); int errcode = GetLastError();
tuntap_log(TUNTAP_LOG_ERR, (const char *)formated_error(L"%1%0", errcode)); tuntap_log(TUNTAP_LOG_ERR, (const char *)formated_error(L"%1%0", errcode));
return -1; return -1;
} }
@ -241,8 +239,8 @@ tuntap_get_hwaddr(struct device *dev)
char buf[128]; char buf[128];
(void)_snprintf(buf, sizeof buf, (void)_snprintf(buf, sizeof buf,
"MAC address: %.2x:%.2x:%.2x:%.2x:%.2x:%.2x", hwaddr[0], "MAC address: %.2x:%.2x:%.2x:%.2x:%.2x:%.2x", hwaddr[0],
hwaddr[1], hwaddr[2], hwaddr[3], hwaddr[4], hwaddr[5]); hwaddr[1], hwaddr[2], hwaddr[3], hwaddr[4], hwaddr[5]);
tuntap_log(TUNTAP_LOG_DEBUG, buf); tuntap_log(TUNTAP_LOG_DEBUG, buf);
} }
return (char *)hwaddr; return (char *)hwaddr;
@ -274,8 +272,7 @@ tuntap_sys_set_updown(struct device *dev, ULONG flag)
{ {
char buf[32]; char buf[32];
(void)_snprintf(buf, sizeof buf, "Status: %s", (void)_snprintf(buf, sizeof buf, "Status: %s", flag ? "Up" : "Down");
flag ? "Up" : "Down");
tuntap_log(TUNTAP_LOG_DEBUG, buf); tuntap_log(TUNTAP_LOG_DEBUG, buf);
return 0; return 0;
} }
@ -330,26 +327,54 @@ tuntap_set_mtu(struct device *dev, int mtu)
int int
tuntap_sys_set_ipv4(struct device *dev, t_tun_in_addr *s, uint32_t mask) tuntap_sys_set_ipv4(struct device *dev, t_tun_in_addr *s, uint32_t mask)
{ {
IPADDR psock[4]; IPADDR sock[3];
DWORD len; DWORD len, ret;
IPADDR ep[4];
/* Address + Netmask */ #pragma pack(push)
psock[0] = s->S_un.S_addr; #pragma pack(1)
psock[1] = mask; struct
/* DHCP server address (We don't want it) */ {
psock[2] = 0; uint8_t dhcp_opt;
/* DHCP lease time */ uint8_t length;
psock[3] = 0; uint32_t value[2];
} dns;
if(DeviceIoControl(dev->tun_fd, TAP_IOCTL_CONFIG_DHCP_MASQ, &psock, #pragma pack(pop)
sizeof(psock), &psock, sizeof(psock), &len, NULL)
== 0) 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(); int errcode = GetLastError();
tuntap_log(TUNTAP_LOG_ERR, (const char *)formated_error(L"%1%0", errcode)); tuntap_log(TUNTAP_LOG_ERR, (const char *)formated_error(L"%1%0", errcode));
return -1; return -1;
} }
return 0; return 0;
} }
@ -369,12 +394,17 @@ tuntap_read(struct device *dev, void *buf, size_t size)
{ {
DWORD len; 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(); int errcode = GetLastError();
tuntap_log(TUNTAP_LOG_ERR, (const char *)formated_error(L"%1%0", errcode)); if (errcode != 997)
return -1; {
tuntap_log(TUNTAP_LOG_ERR, (const char *)formated_error(L"%1%0", errcode));
return -1;
}
else
return 0;
} }
return 0; return 0;
@ -385,12 +415,17 @@ tuntap_write(struct device *dev, void *buf, size_t size)
{ {
DWORD len; 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(); int errcode = GetLastError();
tuntap_log(TUNTAP_LOG_ERR, (const char *)formated_error(L"%1%0", errcode)); if (errcode != 997)
return -1; {
tuntap_log(TUNTAP_LOG_ERR, (const char *)formated_error(L"%1%0", errcode));
return -1;
}
else
return 0;
} }
return 0; return 0;
@ -411,7 +446,7 @@ tuntap_set_nonblocking(struct device *dev, int set)
(void)dev; (void)dev;
(void)set; (void)set;
tuntap_log(TUNTAP_LOG_NOTICE, 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; return -1;
} }
@ -438,7 +473,6 @@ tuntap_set_descr(struct device *dev, const char *descr)
int int
tuntap_set_ifname(struct device *dev, const char *name) tuntap_set_ifname(struct device *dev, const char *name)
{ {
/* TODO: Check Windows API to know how to rename an interface */
(void)dev; (void)dev;
(void)name; (void)name;
tuntap_log(TUNTAP_LOG_NOTICE, tuntap_log(TUNTAP_LOG_NOTICE,

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

Loading…
Cancel
Save