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
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
warranty. In no event will the authors be held liable for any damages

@ -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);

@ -100,7 +100,8 @@ main(int argc, char *argv[])
conffname = fname.string();
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;
}
else

@ -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;
};

@ -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);
}

@ -206,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;
}
@ -313,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));
}

@ -15,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()
{

@ -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