diff --git a/TunSafe.vcxproj b/TunSafe.vcxproj
index 48c8261..94651a4 100644
--- a/TunSafe.vcxproj
+++ b/TunSafe.vcxproj
@@ -202,6 +202,7 @@
+
@@ -221,6 +222,7 @@
+
diff --git a/TunSafe.vcxproj.filters b/TunSafe.vcxproj.filters
index 71677f1..a035bde 100644
--- a/TunSafe.vcxproj.filters
+++ b/TunSafe.vcxproj.filters
@@ -120,6 +120,9 @@
crypto\chacha20poly1305
+
+ Source Files
+
@@ -185,6 +188,9 @@
crypto\chacha20poly1305
+
+ Source Files
+
diff --git a/netapi.h b/netapi.h
index 9a33cdf..ca187ce 100644
--- a/netapi.h
+++ b/netapi.h
@@ -3,9 +3,8 @@
#ifndef TINYVPN_NETAPI_H_
#define TINYVPN_NETAPI_H_
-#include "stdafx.h"
#include "tunsafe_types.h"
-
+#include "tunsafe_ipaddr.h"
#include
#include
@@ -18,17 +17,6 @@
#pragma warning (disable: 4200)
-union IpAddr {
- sockaddr_in sin;
- sockaddr_in6 sin6;
-};
-
-struct WgCidrAddr {
- uint8 addr[16];
- uint8 size;
- uint8 cidr;
-};
-
struct Packet {
union {
Packet *next;
diff --git a/network_win32.h b/network_win32.h
index bcd8adf..10532a4 100644
--- a/network_win32.h
+++ b/network_win32.h
@@ -9,6 +9,7 @@
#include "network_win32_dnsblock.h"
#include "wireguard_config.h"
#include "tunsafe_threading.h"
+#include "tunsafe_dnsresolve.h"
#include
enum {
diff --git a/tunsafe_amalgam.cpp b/tunsafe_amalgam.cpp
index 19108eb..664e79a 100644
--- a/tunsafe_amalgam.cpp
+++ b/tunsafe_amalgam.cpp
@@ -13,6 +13,7 @@
#include "tunsafe_threading.cpp"
#include "tunsafe_cpu.cpp"
#include "ip_to_peer_map.cpp"
+#include "tunsafe_ipaddr.cpp"
#include "crypto/curve25519/curve25519-donna.cpp"
#include "crypto/chacha20poly1305.cpp"
#include "crypto/blake2s/blake2s.cpp"
diff --git a/tunsafe_dnsresolve.h b/tunsafe_dnsresolve.h
new file mode 100644
index 0000000..f3a1ff4
--- /dev/null
+++ b/tunsafe_dnsresolve.h
@@ -0,0 +1,41 @@
+#ifndef TUNSAFE_DNSRESOLVE_H_
+#define TUNSAFE_DNSRESOLVE_H_
+
+#include "tunsafe_threading.h"
+#include "tunsafe_ipaddr.h"
+
+class DnsBlocker;
+
+class DnsResolverCanceller {
+public:
+ DnsResolverCanceller() : cancel_(false) {}
+ void Cancel();
+ void Reset() { cancel_ = false; }
+ bool is_cancelled() { return cancel_; }
+public:
+ bool cancel_;
+ ConditionVariable condvar_;
+};
+
+class DnsResolver {
+public:
+ explicit DnsResolver(DnsBlocker *dns_blocker);
+ ~DnsResolver();
+
+ bool Resolve(const char *hostname, IpAddr *result);
+ void ClearCache();
+
+ void Cancel() { token_.Cancel(); }
+ void ResetCancel() { token_.Reset(); }
+private:
+ struct Entry {
+ std::string name;
+ IpAddr ip;
+ Entry(const std::string &name, const IpAddr &ip) : name(name), ip(ip) {}
+ };
+ std::vector cache_;
+ DnsBlocker *dns_blocker_;
+ DnsResolverCanceller token_;
+};
+
+#endif // TUNSAFE_DNSRESOLVE_H_
\ No newline at end of file
diff --git a/tunsafe_ipaddr.cpp b/tunsafe_ipaddr.cpp
new file mode 100644
index 0000000..aed2abf
--- /dev/null
+++ b/tunsafe_ipaddr.cpp
@@ -0,0 +1,380 @@
+#include "stdafx.h"
+#include "tunsafe_ipaddr.h"
+#include "tunsafe_dnsresolve.h"
+
+#if defined(OS_WIN)
+#include "network_win32_dnsblock.h"
+#include
+#endif
+
+#if defined(OS_POSIX)
+#include
+#include
+#include
+#endif // defined(OS_POSIX)
+
+#include
+#include "util.h"
+
+const char *print_ip_prefix(char buf[kSizeOfAddress], int family, const void *ip, int prefixlen) {
+ // cast to void* to work on VS2015
+ if (!inet_ntop(family, (void*)ip, buf, kSizeOfAddress - 8)) {
+ memcpy(buf, "unknown", 8);
+ }
+ if (prefixlen >= 0)
+ snprintf(buf + strlen(buf), 8, "/%d", prefixlen);
+ return buf;
+}
+
+char *PrintIpAddr(const IpAddr &addr, char buf[kSizeOfAddress]) {
+ if (addr.sin.sin_family == AF_INET) {
+ print_ip_prefix(buf, addr.sin.sin_family, &addr.sin.sin_addr, -1);
+ } else if (addr.sin.sin_family == AF_INET6) {
+ print_ip_prefix(buf, addr.sin.sin_family, &addr.sin6.sin6_addr, -1);
+ } else {
+ buf[0] = 0;
+ }
+ return buf;
+}
+
+
+char *PrintWgCidrAddr(const WgCidrAddr &addr, char buf[kSizeOfAddress]) {
+ if (addr.size == 32) {
+ print_ip_prefix(buf, AF_INET, addr.addr, addr.cidr);
+ } else if (addr.size == 128) {
+ print_ip_prefix(buf, AF_INET6, addr.addr, addr.cidr);
+ } else {
+ buf[0] = 0;
+ }
+ return buf;
+}
+
+struct Addr {
+ byte addr[4];
+ uint8 cidr;
+};
+
+bool ParseCidrAddr(const char *s, WgCidrAddr *out) {
+ const char *slash = strchr(s, '/');
+ if (!slash)
+ return false;
+
+ size_t len = slash - s;
+ char *tmp = (char*)alloca(len + 1);
+ tmp[len] = 0;
+ memcpy(tmp, s, len);
+
+ int e = atoi(slash + 1);
+ if (e < 0) return false;
+
+ if (inet_pton(AF_INET, tmp, out->addr) == 1) {
+ if (e > 32) return false;
+ out->cidr = e;
+ out->size = 32;
+ return true;
+ }
+ if (inet_pton(AF_INET6, tmp, out->addr) == 1) {
+ if (e > 128) return false;
+ out->cidr = e;
+ out->size = 128;
+ return true;
+ }
+ return false;
+}
+
+static Mutex g_dns_mutex;
+
+// This starts a background thread for running DNS resolving.
+class DnsResolverThread : private Thread::Runner {
+public:
+ DnsResolverThread();
+ ~DnsResolverThread();
+
+ // Resolve the hostname and store the result in |result|.
+ // The function will block until it's resolved. If the cancellation
+ // token or becomes signalled, the call will fail.
+ bool Resolve(const char *hostname, IpAddr *result, DnsResolverCanceller *token);
+
+private:
+ virtual void ThreadMain();
+ void StartThread();
+
+ struct Entry {
+ enum {
+ // Set when it's been posted to the job queue
+ POSTED = 0,
+ // Set when the thread has finished and original thread should delete
+ COMPLETE = 1,
+ // Set when the original thread has cancelled and worker thread should delete
+ CANCELLED = 2,
+ };
+
+ Entry() : hostname(NULL) {}
+ ~Entry() { free(hostname); }
+
+ char *hostname;
+ IpAddr *result;
+ Entry *next;
+ uint32 state;
+ ConditionVariable *condvar;
+ };
+ Entry *entry_;
+ Thread thread_;
+ bool thread_active_;
+};
+
+DnsResolverThread::DnsResolverThread() {
+ thread_active_ = false;
+ entry_ = NULL;
+}
+
+DnsResolverThread::~DnsResolverThread() {
+ assert(entry_ == NULL);
+ thread_.StopThread();
+}
+
+void DnsResolverCanceller::Cancel() {
+ g_dns_mutex.Acquire();
+ cancel_ = true;
+ condvar_.Wake();
+ g_dns_mutex.Release();
+}
+
+bool DnsResolverThread::Resolve(const char *hostname, IpAddr *result, DnsResolverCanceller *token) {
+ if (token->cancel_)
+ return false;
+
+ Entry *e = new Entry;
+ e->hostname = _strdup(hostname);
+ e->result = result;
+ e->next = NULL;
+ e->state = Entry::POSTED;
+ e->condvar = &token->condvar_;
+ result->sin.sin_family = 0;
+
+ // Push it to the queue and start thread
+ g_dns_mutex.Acquire();
+ Entry **p = &entry_;
+ while (*p) p = &(*p)->next;
+ *p = e;
+ if (!thread_active_)
+ StartThread();
+ // Wait for something to happen with it.
+ while (!token->cancel_ && e->state == Entry::POSTED)
+ token->condvar_.Wait(&g_dns_mutex);
+ if (e->state == Entry::COMPLETE) {
+ delete e;
+ } else {
+ e->state = Entry::CANCELLED;
+ }
+ g_dns_mutex.Release();
+ return result->sin.sin_family != 0;
+}
+
+void DnsResolverThread::StartThread() {
+ thread_.StopThread();
+ thread_active_ = true;
+ thread_.StartThread(this);
+}
+
+void DnsResolverThread::ThreadMain() {
+ Entry *e;
+ struct addrinfo *ai;
+ g_dns_mutex.Acquire();
+ while ((e = entry_) != NULL) {
+ entry_ = e->next;
+ g_dns_mutex.Release();
+
+ struct addrinfo hints = {0};
+ hints.ai_family = PF_UNSPEC;
+ hints.ai_socktype = SOCK_DGRAM;
+ hints.ai_flags = AI_DEFAULT;
+ ai = NULL;
+ if (getaddrinfo(e->hostname, NULL, &hints, &ai) != 0)
+ ai = NULL;
+ // he = gethostbyname(e->hostname);
+ g_dns_mutex.Acquire();
+ if (e->state == Entry::CANCELLED) {
+ delete e;
+ } else {
+ if (ai) {
+ e->result->sin.sin_family = ai->ai_family;
+ e->result->sin.sin_port = 0;
+ if (ai->ai_family == AF_INET)
+ memcpy(&e->result->sin.sin_addr, &((sockaddr_in*)ai->ai_addr)->sin_addr, 4);
+ else
+ memcpy(&e->result->sin6.sin6_addr, &((sockaddr_in6*)ai->ai_addr)->sin6_addr, 16);
+ }
+/* if (he) {
+ e->result->sin.sin_family = AF_INET;
+ e->result->sin.sin_port = 0;
+ memcpy(&e->result->sin.sin_addr, he->h_addr_list[0], 4);
+ }*/
+
+ e->state = Entry::COMPLETE;
+ e->condvar->Wake();
+ }
+
+ if (ai)
+ freeaddrinfo(ai);
+ }
+ thread_active_ = false;
+ g_dns_mutex.Release();
+}
+
+static DnsResolverThread g_dnsresolver_thread;
+
+static bool InterruptibleSleep(int delay, DnsResolverCanceller *token) {
+ g_dns_mutex.Acquire();
+ uint32 time_at_start = (uint32)OsGetMilliseconds();
+ while (delay > 0 && !token->cancel_) {
+ token->condvar_.WaitTimed(&g_dns_mutex, delay);
+ uint32 now = (uint32)OsGetMilliseconds();
+ delay -= (now - time_at_start);
+ time_at_start = now;
+ }
+ g_dns_mutex.Release();
+ return (delay <= 0);
+}
+
+DnsResolver::DnsResolver(DnsBlocker *dns_blocker) {
+ dns_blocker_ = dns_blocker;
+}
+
+DnsResolver::~DnsResolver() {
+}
+
+void DnsResolver::ClearCache() {
+ cache_.clear();
+}
+
+bool DnsResolver::Resolve(const char *hostname, IpAddr *result) {
+ int attempt = 0;
+ static const uint8 retry_delays[] = {1, 2, 3, 5, 10};
+ char buf[kSizeOfAddress];
+
+ memset(result, 0, sizeof(IpAddr));
+
+ // First check cache
+ for (auto it = cache_.begin(); it != cache_.end(); ++it) {
+ if (it->name == hostname) {
+
+ *result = it->ip;
+ RINFO("Resolved %s to %s%s", hostname, PrintIpAddr(*result, buf), " (cached)");
+ return true;
+ }
+ }
+
+#if defined(OS_WIN)
+ // Then disable dns blocker (otherwise the windows dns client service can't resolve)
+ if (dns_blocker_ && dns_blocker_->IsActive()) {
+ RINFO("Disabling DNS blocker to resolve %s", hostname);
+ dns_blocker_->RestoreDns();
+ }
+#endif // defined(OS_WIN)
+
+ for (;;) {
+ if (g_dnsresolver_thread.Resolve(hostname, result, &token_)) {
+ // add to cache
+ cache_.emplace_back(hostname, *result);
+ RINFO("Resolved %s to %s%s", hostname, PrintIpAddr(*result, buf), "");
+ return true;
+ }
+ if (token_.is_cancelled())
+ return false;
+
+ RINFO("Unable to resolve %s. Trying again in %d second(s)", hostname, retry_delays[attempt]);
+ if (!InterruptibleSleep(retry_delays[attempt] * 1000, &token_))
+ return false;
+
+ if (attempt != ARRAY_SIZE(retry_delays) - 1)
+ attempt++;
+ }
+}
+
+// Parse an IPV4 address into sin, doing NAT64 translation if applicable (on IOS)
+static bool ParseIpv4WithNAT64Translation(const char *s, IpAddr *sin, int flags) {
+ // First verify it's actually a valid ipv4 address to prevent getaddrinfo from doing a slow resolve
+ if (inet_pton(AF_INET, s, &sin->sin.sin_addr) != 1)
+ return false;
+ sin->sin.sin_family = AF_INET;
+
+#if defined(OS_IOS)
+ if (!(flags & kParseSockaddrDontDoNAT64)) {
+ struct addrinfo hints = {0};
+ hints.ai_family = PF_UNSPEC;
+ hints.ai_socktype = SOCK_DGRAM;
+ hints.ai_flags = AI_DEFAULT;
+ struct addrinfo* ai = NULL;
+ // When NAT64 is enabled, I don't get an IPv4 address back.
+ if (getaddrinfo(s, NULL, &hints, &ai) == 0) {
+ // check so we have an AF_INET6 and no AF_INET
+ struct sockaddr_in6 *found = NULL;
+ for(struct addrinfo *t = ai; t; t = t->ai_next) {
+ if (t->ai_family == AF_INET) { found = NULL; break; }
+ if (t->ai_family == AF_INET6) found = (sockaddr_in6*)t->ai_addr;
+ }
+ if (found) {
+ memset(&sin->sin.sin_addr, 0, 4); // clear out ipv4 address already written
+ memcpy(&sin->sin6.sin6_addr, &found->sin6_addr, 16);
+ sin->sin.sin_family = AF_INET6;
+ }
+ freeaddrinfo(ai);
+ }
+ }
+#endif // defined(OS_IOS)
+ return true;
+}
+
+bool ParseSockaddrInWithPort(const char *si, IpAddr *sin, DnsResolver *resolver, int flags) {
+ size_t len = strlen(si) + 1;
+ char *s = (char*)alloca(len);
+ memcpy(s, si, len);
+
+ memset(sin, 0, sizeof(IpAddr));
+ if (*s == '[') {
+ char *end = strchr(s, ']');
+ if (end == NULL)
+ return false;
+ *end = 0;
+ if (inet_pton(AF_INET6, s + 1, &sin->sin6.sin6_addr) != 1)
+ return false;
+ char *x = strchr(end + 1, ':');
+ if (!x)
+ return false;
+ sin->sin6.sin6_family = AF_INET6;
+ sin->sin6.sin6_port = htons(atoi(x + 1));
+ return true;
+ }
+ char *x = strchr(s, ':');
+ if (!x) return false;
+ *x = 0;
+
+ if (!ParseIpv4WithNAT64Translation(s, sin, flags)) {
+ if (!resolver) {
+ return false;
+ } else if (!resolver->Resolve(s, sin)) {
+ RERROR("Unable to resolve %s", s);
+ return false;
+ }
+ }
+ sin->sin.sin_port = htons(atoi(x + 1));
+ return true;
+}
+
+bool ParseSockaddrInWithoutPort(char *s, IpAddr *sin, DnsResolver *resolver, int flags) {
+ memset(sin, 0, sizeof(IpAddr));
+
+ if (inet_pton(AF_INET6, s, &sin->sin6.sin6_addr) == 1) {
+ sin->sin.sin_family = AF_INET6;
+ return true;
+ } else if (ParseIpv4WithNAT64Translation(s, sin, flags)) {
+ return true;
+ } else if (!resolver) {
+ return false;
+ } else if (!resolver->Resolve(s, sin)) {
+ RERROR("Unable to resolve %s", s);
+ return false;
+ }
+ return true;
+}
diff --git a/tunsafe_ipaddr.h b/tunsafe_ipaddr.h
new file mode 100644
index 0000000..8b398a2
--- /dev/null
+++ b/tunsafe_ipaddr.h
@@ -0,0 +1,40 @@
+#ifndef TUNSAFE_IPADDR_H_
+#define TUNSAFE_IPADDR_H_
+
+#include "tunsafe_types.h"
+
+#if !defined(OS_WIN)
+#include
+#include
+#include
+#include
+#endif
+
+union IpAddr {
+ sockaddr_in sin;
+ sockaddr_in6 sin6;
+};
+
+struct WgCidrAddr {
+ uint8 addr[16];
+ uint8 size;
+ uint8 cidr;
+};
+
+class DnsResolver;
+
+#define kSizeOfAddress 64
+const char *print_ip_prefix(char buf[kSizeOfAddress], int family, const void *ip, int prefixlen);
+char *PrintIpAddr(const IpAddr &addr, char buf[kSizeOfAddress]);
+char *PrintWgCidrAddr(const WgCidrAddr &addr, char buf[kSizeOfAddress]);
+
+bool ParseCidrAddr(const char *s, WgCidrAddr *out);
+
+enum {
+ kParseSockaddrDontDoNAT64 = 1,
+};
+bool ParseSockaddrInWithPort(const char *s, IpAddr *sin, DnsResolver *resolver, int flags = 0);
+bool ParseSockaddrInWithoutPort(char *s, IpAddr *sin, DnsResolver *resolver, int flags = 0);
+
+
+#endif // TUNSAFE_IPADDR_H_
diff --git a/wireguard_config.cpp b/wireguard_config.cpp
index c0abc51..9004fad 100644
--- a/wireguard_config.cpp
+++ b/wireguard_config.cpp
@@ -2,333 +2,13 @@
// Copyright (C) 2018 Ludvig Strigeus . All Rights Reserved.
#include "stdafx.h"
#include "wireguard_config.h"
-#include "netapi.h"
-#include "tunsafe_endian.h"
#include "wireguard.h"
#include "util.h"
#include
-#include
#include
#include
#include
-
-#if defined(OS_POSIX)
-#include
-#include
-#include
-#include
-#include
-#endif
-
-#if defined(OS_WIN)
-#include "network_win32_dnsblock.h"
-#endif
-
-const char *print_ip_prefix(char buf[kSizeOfAddress], int family, const void *ip, int prefixlen) {
- // cast to void* to work on VS2015
- if (!inet_ntop(family, (void*)ip, buf, kSizeOfAddress - 8)) {
- memcpy(buf, "unknown", 8);
- }
- if (prefixlen >= 0)
- snprintf(buf + strlen(buf), 8, "/%d", prefixlen);
- return buf;
-}
-
-char *PrintIpAddr(const IpAddr &addr, char buf[kSizeOfAddress]) {
- if (addr.sin.sin_family == AF_INET) {
- print_ip_prefix(buf, addr.sin.sin_family, &addr.sin.sin_addr, -1);
- } else if (addr.sin.sin_family == AF_INET) {
- print_ip_prefix(buf, addr.sin.sin_family, &addr.sin6.sin6_addr, -1);
- } else {
- buf[0] = 0;
- }
- return buf;
-}
-
-
-char *PrintWgCidrAddr(const WgCidrAddr &addr, char buf[kSizeOfAddress]) {
- if (addr.size == 32) {
- print_ip_prefix(buf, AF_INET, addr.addr, addr.cidr);
- } else if (addr.size == 128) {
- print_ip_prefix(buf, AF_INET6, addr.addr, addr.cidr);
- } else {
- buf[0] = 0;
- }
- return buf;
-}
-
-struct Addr {
- byte addr[4];
- uint8 cidr;
-};
-
-bool ParseCidrAddr(char *s, WgCidrAddr *out) {
- char *slash = strchr(s, '/');
- if (!slash)
- return false;
-
- *slash = 0;
- int e = atoi(slash + 1);
- if (e < 0) return false;
-
- if (inet_pton(AF_INET, s, out->addr) == 1) {
- if (e > 32) return false;
- out->cidr = e;
- out->size = 32;
- return true;
- }
- if (inet_pton(AF_INET6, s, out->addr) == 1) {
- if (e > 128) return false;
- out->cidr = e;
- out->size = 128;
- return true;
- }
- return false;
-}
-
-static Mutex g_dns_mutex;
-
-// This starts a background thread for running DNS resolving.
-class DnsResolverThread : private Thread::Runner {
-public:
- DnsResolverThread();
- ~DnsResolverThread();
-
- // Resolve the hostname and store the result in |result|.
- // The function will block until it's resolved. If the cancellation
- // token or becomes signalled, the call will fail.
- bool Resolve(const char *hostname, IpAddr *result, DnsResolverCanceller *token);
-
-private:
- virtual void ThreadMain();
- void StartThread();
-
- struct Entry {
- enum {
- // Set when it's been posted to the job queue
- POSTED = 0,
- // Set when the thread has finished and original thread should delete
- COMPLETE = 1,
- // Set when the original thread has cancelled and worker thread should delete
- CANCELLED = 2,
- };
-
- Entry() : hostname(NULL) {}
- ~Entry() { free(hostname); }
-
- char *hostname;
- IpAddr *result;
- Entry *next;
- uint32 state;
- ConditionVariable *condvar;
- };
- Entry *entry_;
- Thread thread_;
- bool thread_active_;
-};
-
-DnsResolverThread::DnsResolverThread() {
- thread_active_ = false;
- entry_ = NULL;
-}
-
-DnsResolverThread::~DnsResolverThread() {
- assert(entry_ == NULL);
- thread_.StopThread();
-}
-
-void DnsResolverCanceller::Cancel() {
- g_dns_mutex.Acquire();
- cancel_ = true;
- condvar_.Wake();
- g_dns_mutex.Release();
-}
-
-bool DnsResolverThread::Resolve(const char *hostname, IpAddr *result, DnsResolverCanceller *token) {
- if (token->cancel_)
- return false;
-
- Entry *e = new Entry;
- e->hostname = _strdup(hostname);
- e->result = result;
- e->next = NULL;
- e->state = Entry::POSTED;
- e->condvar = &token->condvar_;
- result->sin.sin_family = 0;
-
- // Push it to the queue and start thread
- g_dns_mutex.Acquire();
- Entry **p = &entry_;
- while (*p) p = &(*p)->next;
- *p = e;
- if (!thread_active_)
- StartThread();
- // Wait for something to happen with it.
- while (!token->cancel_ && e->state == Entry::POSTED)
- token->condvar_.Wait(&g_dns_mutex);
- if (e->state == Entry::COMPLETE) {
- delete e;
- } else {
- e->state = Entry::CANCELLED;
- }
- g_dns_mutex.Release();
- return result->sin.sin_family != 0;
-}
-
-void DnsResolverThread::StartThread() {
- thread_.StopThread();
- thread_active_ = true;
- thread_.StartThread(this);
-}
-
-void DnsResolverThread::ThreadMain() {
- Entry *e = NULL;
- struct hostent *he = NULL;
- for (;;) {
- g_dns_mutex.Acquire();
- if (e) {
- if (e->state == Entry::CANCELLED) {
- delete e;
- } else {
- if (he) {
- e->result->sin.sin_family = AF_INET;
- e->result->sin.sin_port = 0;
- memcpy(&e->result->sin.sin_addr, he->h_addr_list[0], 4);
- }
- e->state = Entry::COMPLETE;
- e->condvar->Wake();
- }
- }
- if (!(e = entry_)) {
- thread_active_ = false;
- break;
- }
- entry_ = e->next;
- g_dns_mutex.Release();
- he = gethostbyname(e->hostname);
- }
- g_dns_mutex.Release();
-}
-
-static DnsResolverThread g_dnsresolver_thread;
-
-bool InterruptibleSleep(int delay, DnsResolverCanceller *token) {
- g_dns_mutex.Acquire();
- uint32 time_at_start = (uint32)OsGetMilliseconds();
- while (delay > 0 && !token->cancel_) {
- token->condvar_.WaitTimed(&g_dns_mutex, delay);
- uint32 now = (uint32)OsGetMilliseconds();
- delay -= (now - time_at_start);
- time_at_start = now;
- }
- g_dns_mutex.Release();
- return (delay <= 0);
-}
-
-DnsResolver::DnsResolver(DnsBlocker *dns_blocker) {
- dns_blocker_ = dns_blocker;
-}
-
-DnsResolver::~DnsResolver() {
-}
-
-void DnsResolver::ClearCache() {
- cache_.clear();
-}
-
-bool DnsResolver::Resolve(const char *hostname, IpAddr *result) {
- int attempt = 0;
- static const uint8 retry_delays[] = {1, 2, 3, 5, 10};
- char buf[kSizeOfAddress];
-
- memset(result, 0, sizeof(IpAddr));
-
- // First check cache
- for (auto it = cache_.begin(); it != cache_.end(); ++it) {
- if (it->name == hostname) {
-
- *result = it->ip;
- RINFO("Resolved %s to %s%s", hostname, PrintIpAddr(*result, buf), " (cached)");
- return true;
- }
- }
-
-#if defined(OS_WIN)
- // Then disable dns blocker (otherwise the windows dns client service can't resolve)
- if (dns_blocker_ && dns_blocker_->IsActive()) {
- RINFO("Disabling DNS blocker to resolve %s", hostname);
- dns_blocker_->RestoreDns();
- }
-#endif // defined(OS_WIN)
-
- for (;;) {
- if (g_dnsresolver_thread.Resolve(hostname, result, &token_)) {
- // add to cache
- cache_.emplace_back(hostname, *result);
- RINFO("Resolved %s to %s%s", hostname, PrintIpAddr(*result, buf), "");
- return true;
- }
- if (token_.is_cancelled())
- return false;
-
- RINFO("Unable to resolve %s. Trying again in %d second(s)", hostname, retry_delays[attempt]);
- if (!InterruptibleSleep(retry_delays[attempt] * 1000, &token_))
- return false;
-
- if (attempt != ARRAY_SIZE(retry_delays) - 1)
- attempt++;
- }
-}
-
-bool ParseSockaddrInWithPort(const char *si, IpAddr *sin, DnsResolver *resolver) {
- size_t len = strlen(si) + 1;
- char *s = (char*)alloca(len);
- memcpy(s, si, len);
-
- memset(sin, 0, sizeof(IpAddr));
- if (*s == '[') {
- char *end = strchr(s, ']');
- if (end == NULL)
- return false;
- *end = 0;
- if (inet_pton(AF_INET6, s + 1, &sin->sin6.sin6_addr) != 1)
- return false;
- char *x = strchr(end + 1, ':');
- if (!x)
- return false;
- sin->sin.sin_family = AF_INET6;
- sin->sin.sin_port = htons(atoi(x + 1));
- return true;
- }
- char *x = strchr(s, ':');
- if (!x) return false;
- *x = 0;
-
- if (inet_pton(AF_INET, s, &sin->sin.sin_addr) == 1) {
- sin->sin.sin_family = AF_INET;
- } else if (!resolver) {
- return false;
- } else if (!resolver->Resolve(s, sin)) {
- RERROR("Unable to resolve %s", s);
- return false;
- }
- sin->sin.sin_port = htons(atoi(x + 1));
- return true;
-}
-
-static bool ParseSockaddrInWithoutPort(char *s, IpAddr *sin, DnsResolver *resolver) {
- if (inet_pton(AF_INET6, s, &sin->sin6.sin6_addr) == 1) {
- sin->sin.sin_family = AF_INET6;
- return true;
- } else if (inet_pton(AF_INET, s, &sin->sin.sin_addr) == 1) {
- sin->sin.sin_family = AF_INET;
- return true;
- } else if (!resolver->Resolve(s, sin)) {
- RERROR("Unable to resolve %s", s);
- return false;
- }
- return true;
-}
+#include
class WgFileParser {
public:
@@ -449,7 +129,7 @@ bool WgFileParser::ParseFlag(const char *group, const char *key, char *value) {
} else if (strcmp(key, "DNS") == 0) {
SplitString(value, ',', &ss);
for (size_t i = 0; i < ss.size(); i++) {
- if (!ParseSockaddrInWithoutPort(ss[i], &sin, dns_resolver_))
+ if (!ParseSockaddrInWithoutPort(ss[i], &sin, dns_resolver_, kParseSockaddrDontDoNAT64))
return false;
wg_->AddDnsServer(sin);
}
diff --git a/wireguard_config.h b/wireguard_config.h
index 632f7df..7ba57ca 100644
--- a/wireguard_config.h
+++ b/wireguard_config.h
@@ -3,44 +3,10 @@
#ifndef TINYVPN_TINYVPN_H_
#define TINYVPN_TINYVPN_H_
-#include "netapi.h"
-#include "tunsafe_threading.h"
+#include
+class DnsResolver;
class WireguardProcessor;
-class DnsBlocker;
-
-class DnsResolverCanceller {
-public:
- DnsResolverCanceller() : cancel_(false) {}
- void Cancel();
- void Reset() { cancel_ = false; }
- bool is_cancelled() { return cancel_; }
-public:
- bool cancel_;
- ConditionVariable condvar_;
-};
-
-class DnsResolver {
-public:
- explicit DnsResolver(DnsBlocker *dns_blocker);
- ~DnsResolver();
-
- bool Resolve(const char *hostname, IpAddr *result);
- void ClearCache();
-
- void Cancel() { token_.Cancel(); }
- void ResetCancel() { token_.Reset(); }
-private:
- struct Entry {
- std::string name;
- IpAddr ip;
- Entry(const std::string &name, const IpAddr &ip) : name(name), ip(ip) {}
- };
- std::vector cache_;
- DnsBlocker *dns_blocker_;
- DnsResolverCanceller token_;
-};
-
class WgConfig {
public:
@@ -52,12 +18,5 @@ private:
bool ParseWireGuardConfigString(WireguardProcessor *wg, char *buf, size_t buf_size, DnsResolver *dns_resolver);
bool ParseWireGuardConfigFile(WireguardProcessor *wg, const char *filename, DnsResolver *dns_resolver);
-#define kSizeOfAddress 64
-const char *print_ip_prefix(char buf[kSizeOfAddress], int family, const void *ip, int prefixlen);
-char *PrintIpAddr(const IpAddr &addr, char buf[kSizeOfAddress]);
-char *PrintWgCidrAddr(const WgCidrAddr &addr, char buf[kSizeOfAddress]);
-
-bool ParseCidrAddr(char *s, WgCidrAddr *out);
-bool ParseSockaddrInWithPort(const char *s, IpAddr *sin, DnsResolver *resolver);
#endif // TINYVPN_TINYVPN_H_