Big code refactoring #10
@ -37,19 +37,33 @@
|
||||
const DEVPROPKEY devpkey_name = { { 0x65726957, 0x7547, 0x7261, { 0x64, 0x4e, 0x61, 0x6d, 0x65, 0x4b, 0x65, 0x79 } }, DEVPROPID_FIRST_USABLE + 1 };
|
||||
#define IFNAMSIZ MAX_ADAPTER_NAME - 1
|
||||
|
||||
// Create Wireguard adapter
|
||||
static WIREGUARD_CREATE_ADAPTER_FUNC *WireGuardCreateAdapter;
|
||||
// Open Wireguard adapter by name if exists
|
||||
static WIREGUARD_OPEN_ADAPTER_FUNC *WireGuardOpenAdapter;
|
||||
// Close Wireguard adapter
|
||||
static WIREGUARD_CLOSE_ADAPTER_FUNC *WireGuardCloseAdapter;
|
||||
// Get Wireguard adapter LUID
|
||||
static WIREGUARD_GET_ADAPTER_LUID_FUNC *WireGuardGetAdapterLUID;
|
||||
// Get running Wireguard driver version
|
||||
static WIREGUARD_GET_RUNNING_DRIVER_VERSION_FUNC *WireGuardGetRunningDriverVersion;
|
||||
// Delete Wireguard driver if non exists adapters
|
||||
static WIREGUARD_DELETE_DRIVER_FUNC *WireGuardDeleteDriver;
|
||||
// Set logger for Wireguard adapter
|
||||
static WIREGUARD_SET_LOGGER_FUNC *WireGuardSetLogger;
|
||||
// Set adapter logging for Wireguard adapter
|
||||
static WIREGUARD_SET_ADAPTER_LOGGING_FUNC *WireGuardSetAdapterLogging;
|
||||
// Get adapter state for Wireguard adapter
|
||||
static WIREGUARD_GET_ADAPTER_STATE_FUNC *WireGuardGetAdapterState;
|
||||
// Set adapter state for Wireguard adapter
|
||||
static WIREGUARD_SET_ADAPTER_STATE_FUNC *WireGuardSetAdapterState;
|
||||
// Get Wireguard adapter configuration
|
||||
static WIREGUARD_GET_CONFIGURATION_FUNC *WireGuardGetConfiguration;
|
||||
// Set Wireguard adapter configuration
|
||||
static WIREGUARD_SET_CONFIGURATION_FUNC *WireGuardSetConfiguration;
|
||||
|
||||
LPCWSTR WireguardAddonDescription = WireguardAddonDescription;
|
||||
|
||||
// Function to check if the current user has administrator privileges
|
||||
bool IsRunAsAdmin() {
|
||||
BOOL fRet = FALSE;
|
||||
@ -92,90 +106,6 @@ std::string parseEndpoint(SOCKADDR_INET *input) {
|
||||
return std::string(saddr).append(":").append(std::to_string(htons(input->Ipv4.sin_port)));
|
||||
}
|
||||
|
||||
int parse_dns_retries() {
|
||||
unsigned long ret;
|
||||
char *retries = getenv("WG_ENDPOINT_RESOLUTION_RETRIES"), *end;
|
||||
|
||||
if (!retries) return 15;
|
||||
if (!strcmp(retries, "infinity")) return -1;
|
||||
|
||||
ret = strtoul(retries, &end, 10);
|
||||
if (*end || ret > INT_MAX) {
|
||||
fprintf(stderr, "Unable to parse WG_ENDPOINT_RESOLUTION_RETRIES: `%s'\n", retries);
|
||||
exit(1);
|
||||
}
|
||||
return (int)ret;
|
||||
}
|
||||
|
||||
void insertEndpoint(SOCKADDR_INET *endpoint, std::string value) {
|
||||
int ret, retries = parse_dns_retries();
|
||||
char *begin, *end;
|
||||
auto mmutable = strdup(value.c_str());
|
||||
if (!mmutable) throw std::string("strdup");
|
||||
if (!value.size()) {
|
||||
free(mmutable);
|
||||
throw std::string("Unable to parse empty endpoint");
|
||||
}
|
||||
if (mmutable[0] == '[') {
|
||||
begin = &mmutable[1];
|
||||
end = strchr(mmutable, ']');
|
||||
if (!end) {
|
||||
free(mmutable);
|
||||
throw std::string("Unable to find matching brace of endpoint: ").append(value);
|
||||
}
|
||||
*end++ = '\0';
|
||||
if (*end++ != ':' || !*end) {
|
||||
free(mmutable);
|
||||
throw std::string("Unable to find port of endpoint: ").append(value);
|
||||
}
|
||||
} else {
|
||||
begin = mmutable;
|
||||
end = strrchr(mmutable, ':');
|
||||
if (!end || !*(end + 1)) {
|
||||
free(mmutable);
|
||||
throw std::string("Unable to find port of endpoint: ").append(value);
|
||||
}
|
||||
*end++ = '\0';
|
||||
}
|
||||
|
||||
|
||||
ADDRINFOA *resolved;
|
||||
// #define min(a, b) ((a) < (b) ? (a) : (b))
|
||||
for (unsigned int timeout = 1000000;; timeout = ((20000000) < (timeout * 6 / 5) ? (20000000) : (timeout * 6 / 5))) {
|
||||
// ret = getaddrinfo(begin, end, &hints, &resolved);
|
||||
ret = getaddrinfo(begin, end, NULL, &resolved);
|
||||
if (!ret) break;
|
||||
/* The set of return codes that are "permanent failures". All other possibilities are potentially transient.
|
||||
*
|
||||
* This is according to https://sourceware.org/glibc/wiki/NameResolver which states:
|
||||
* "From the perspective of the application that calls getaddrinfo() it perhaps
|
||||
* doesn't matter that much since EAI_FAIL, EAI_NONAME and EAI_NODATA are all
|
||||
* permanent failure codes and the causes are all permanent failures in the
|
||||
* sense that there is no point in retrying later."
|
||||
*
|
||||
* So this is what we do, except FreeBSD removed EAI_NODATA some time ago, so that's conditional.
|
||||
*/
|
||||
if (ret == EAI_NONAME || ret == EAI_FAIL ||
|
||||
#ifdef EAI_NODATA
|
||||
ret == EAI_NODATA ||
|
||||
#endif
|
||||
(retries >= 0 && !retries--)) {
|
||||
free(mmutable);
|
||||
throw std::string("Error code: ").append(std::to_string(ret));
|
||||
}
|
||||
std::this_thread::sleep_for(std::chrono::microseconds(timeout));
|
||||
}
|
||||
|
||||
if ((resolved->ai_family == AF_INET && resolved->ai_addrlen == sizeof(SOCKADDR_IN))) memcpy(&endpoint->Ipv4, resolved->ai_addr, resolved->ai_addrlen);
|
||||
else if (resolved->ai_family == AF_INET6 && resolved->ai_addrlen == sizeof(SOCKADDR_IN6)) memcpy(&endpoint->Ipv6, resolved->ai_addr, resolved->ai_addrlen);
|
||||
else {
|
||||
freeaddrinfo(resolved);
|
||||
throw std::string("Neither IPv4 nor IPv6 address found: ").append(value);
|
||||
}
|
||||
freeaddrinfo(resolved);
|
||||
free(mmutable);
|
||||
}
|
||||
|
||||
std::string getErrorString(DWORD errorMessageID) {
|
||||
if (errorMessageID == 0 || errorMessageID < 0) std::string("Error code: ").append(std::to_string(errorMessageID));
|
||||
LPSTR messageBuffer = nullptr;
|
||||
@ -211,7 +141,9 @@ std::string driveLoad(std::map<std::string, std::string> load) {
|
||||
}
|
||||
|
||||
std::string getWireguardVersion() {
|
||||
WIREGUARD_ADAPTER_HANDLE Adapter = WireGuardCreateAdapter(L"getWgVersion", L"Wireguard-tools.js", NULL);
|
||||
// Create interface to get version
|
||||
WIREGUARD_ADAPTER_HANDLE Adapter = WireGuardCreateAdapter(L"getWgVersion", WireguardAddonDescription, NULL);
|
||||
WireGuardCloseAdapter(Adapter);
|
||||
DWORD Version = WireGuardGetRunningDriverVersion();
|
||||
if (Version == 0) {
|
||||
auto statusErr = GetLastError();
|
||||
@ -219,49 +151,25 @@ std::string getWireguardVersion() {
|
||||
if (statusErr == ERROR_FILE_NOT_FOUND) return "Driver not loaded";
|
||||
return std::string("Cannot get version drive, ").append(getErrorString(GetLastError()));
|
||||
}
|
||||
WireGuardCloseAdapter(Adapter);
|
||||
return std::string("WireGuardNT v").append(std::to_string((Version >> 16) & 0xff)).append(".").append(std::to_string((Version >> 0) & 0xff));
|
||||
return std::string("WireGuardNT v").append(std::to_string((Version >> 16) & 0xff)).append(".").append(std::to_string((Version >> 0) & 0xff)).append(".").append(std::to_string((Version >> 8) & 0xff));
|
||||
}
|
||||
|
||||
void WireguardDevices::getInterfaces() {
|
||||
// std::vector<std::string> arrayPrefix;
|
||||
// arrayPrefix.push_back("ProtectedPrefix\\Administrators\\WireGuard\\");
|
||||
// arrayPrefix.push_back("WireGuard\\");
|
||||
|
||||
// WIN32_FIND_DATA find_data;
|
||||
// HANDLE find_handle;
|
||||
// for (auto &preit : arrayPrefix) {
|
||||
// int ret = 0;
|
||||
// find_handle = FindFirstFile("\\\\.\\pipe\\*", &find_data);
|
||||
// if (find_handle == INVALID_HANDLE_VALUE) continue;
|
||||
|
||||
// char *iface;
|
||||
// do {
|
||||
// if (strncmp(preit.c_str(), find_data.cFileName, strlen(preit.c_str()))) continue;
|
||||
// iface = find_data.cFileName + strlen(preit.c_str());
|
||||
// this->push_back(std::string("\\\\.\\pipe\\").append(preit).append(iface));
|
||||
// } while (FindNextFile(find_handle, &find_data));
|
||||
// FindClose(find_handle);
|
||||
// if (ret < 0) throw std::string("Erro code: ").append(std::to_string(ret));
|
||||
// }
|
||||
|
||||
HDEVINFO dev_info = SetupDiGetClassDevsExW(&GUID_DEVCLASS_NET, L"SWD\\WireGuard", NULL, DIGCF_PRESENT, NULL, NULL, NULL);
|
||||
if (dev_info == INVALID_HANDLE_VALUE) throw ("Cannot get devices");
|
||||
|
||||
for (DWORD i = 0;; ++i) {
|
||||
DWORD buf_len;
|
||||
WCHAR adapter_name[MAX_ADAPTER_NAME];
|
||||
if (dev_info == INVALID_HANDLE_VALUE) throw std::string("Cannot get devices");
|
||||
for (DWORD devIndex = 0;; ++devIndex) {
|
||||
SP_DEVINFO_DATA dev_info_data;
|
||||
dev_info_data.cbSize = sizeof(SP_DEVINFO_DATA);
|
||||
DEVPROPTYPE prop_type;
|
||||
ULONG status, problem_code;
|
||||
char *interface_name;
|
||||
|
||||
if (!SetupDiEnumDeviceInfo(dev_info, i, &dev_info_data)) {
|
||||
if (!SetupDiEnumDeviceInfo(dev_info, devIndex, &dev_info_data)) {
|
||||
if (GetLastError() == ERROR_NO_MORE_ITEMS) break;
|
||||
continue;
|
||||
}
|
||||
|
||||
DWORD buf_len; ULONG status, problem_code;
|
||||
WCHAR adapter_name[MAX_ADAPTER_NAME];
|
||||
char *interface_name;
|
||||
DEVPROPTYPE prop_type;
|
||||
|
||||
if (!SetupDiGetDevicePropertyW(dev_info, &dev_info_data, &devpkey_name, &prop_type, (PBYTE)adapter_name, sizeof(adapter_name), NULL, 0) || prop_type != DEVPROP_TYPE_STRING) continue;
|
||||
adapter_name[_countof(adapter_name) - 1] = L'0';
|
||||
if (!adapter_name[0]) continue;
|
||||
@ -281,28 +189,31 @@ void WireguardDevices::getInterfaces() {
|
||||
SetupDiDestroyDeviceInfoList(dev_info);
|
||||
}
|
||||
|
||||
/*
|
||||
Delete wireguard interface
|
||||
|
||||
Current bug from Addon: Set interface down and not delete wireguard interface
|
||||
*/
|
||||
void WireguardDevices::deleteInterface(std::string wgName) {
|
||||
WIREGUARD_ADAPTER_HANDLE Adapter = WireGuardOpenAdapter(toLpcwstr(wgName));
|
||||
if (!Adapter) throw std::string("This interface not exists in Wireguard-Tools.js addon!");
|
||||
if (!(WireGuardSetAdapterState(Adapter, WIREGUARD_ADAPTER_STATE::WIREGUARD_ADAPTER_STATE_DOWN))) throw std::string(std::string("Failed to set down interface, ").append(getErrorString(GetLastError())));
|
||||
if (!(WireGuardSetAdapterState(Adapter, WIREGUARD_ADAPTER_STATE::WIREGUARD_ADAPTER_STATE_DOWN))) throw std::string("Failed to set down interface, ").append(getErrorString(GetLastError()));
|
||||
WireGuardCloseAdapter(Adapter);
|
||||
}
|
||||
|
||||
/**
|
||||
* Change point from calloc or malloc
|
||||
*
|
||||
* T: to
|
||||
* C: From
|
||||
* Change point from calloc or malloc, T: from, C: to
|
||||
*/
|
||||
template <typename T, typename C> C* changePoint(T *x) {
|
||||
// reinterpret_cast<WIREGUARD_ALLOWED_IP*>(((char*)x) + sizeof(WIREGUARD_PEER));
|
||||
// std::cout << "Sizeof: " << sizeof(C) << ", " << typeid(T).name() << " -> " << typeid(C).name() << std::endl;
|
||||
return reinterpret_cast<C*>(((char*)x) + sizeof(T));
|
||||
}
|
||||
|
||||
void WireguardConfig::getWireguardConfig() {
|
||||
if (this->name.length() == 0) throw std::string("Require interface name!");
|
||||
else if (!(WireguardDevices().exist(this->name))) throw std::string("This interface not exists in Wireguard-Tools.js addon!");
|
||||
|
||||
WIREGUARD_ADAPTER_HANDLE Adapter = WireGuardOpenAdapter(toLpcwstr(this->name));
|
||||
if (!Adapter) throw ("This interface not exists in Wireguard-Tools.js addon!");
|
||||
if (!Adapter) throw std::string("This interface not exists in Wireguard-Tools.js addon!");
|
||||
NET_LUID InterfaceLuid;
|
||||
WireGuardGetAdapterLUID(Adapter, &InterfaceLuid);
|
||||
this->interfaceAddress.GetInInterface(this->name);
|
||||
@ -312,28 +223,27 @@ void WireguardConfig::getWireguardConfig() {
|
||||
|
||||
while (!(WireGuardGetConfiguration(Adapter, wg_iface, &buf_len))) {
|
||||
free(wg_iface);
|
||||
if (GetLastError() != ERROR_MORE_DATA) throw ((std::string("Failed get interface config, code: ")).append(std::to_string(GetLastError())));
|
||||
if (GetLastError() != ERROR_MORE_DATA) throw std::string("Failed get interface config, code: ").append(std::to_string(GetLastError()));
|
||||
wg_iface = (WIREGUARD_INTERFACE *)malloc(buf_len);
|
||||
if (!wg_iface) throw std::string("Failed get interface config, ").append(std::to_string(-errno));
|
||||
}
|
||||
|
||||
if (wg_iface->Flags & WIREGUARD_INTERFACE_FLAG::WIREGUARD_INTERFACE_HAS_PRIVATE_KEY) privateKey = wgKeys::toString(wg_iface->PrivateKey);
|
||||
if (wg_iface->Flags & WIREGUARD_INTERFACE_FLAG::WIREGUARD_INTERFACE_HAS_PUBLIC_KEY) publicKey = wgKeys::toString(wg_iface->PublicKey);
|
||||
portListen = 0;
|
||||
if (wg_iface->Flags & WIREGUARD_INTERFACE_FLAG::WIREGUARD_INTERFACE_HAS_LISTEN_PORT) portListen = wg_iface->ListenPort;
|
||||
|
||||
if (wg_iface->Flags & WIREGUARD_INTERFACE_FLAG::WIREGUARD_INTERFACE_HAS_PRIVATE_KEY) this->privateKey = wgKeys::toString(wg_iface->PrivateKey);
|
||||
if (wg_iface->Flags & WIREGUARD_INTERFACE_FLAG::WIREGUARD_INTERFACE_HAS_PUBLIC_KEY) this->publicKey = wgKeys::toString(wg_iface->PublicKey);
|
||||
if (wg_iface->ListenPort > 0) this->portListen = wg_iface->ListenPort;
|
||||
|
||||
WIREGUARD_PEER *wg_peer = changePoint<WIREGUARD_INTERFACE, WIREGUARD_PEER>(wg_iface);
|
||||
for (DWORD i = 0; i < wg_iface->PeersCount; i++) {
|
||||
auto pubKey = wgKeys::toString(wg_peer->PublicKey);
|
||||
Peer peerConfig;
|
||||
|
||||
peerConfig.txBytes = wg_peer->TxBytes;
|
||||
peerConfig.rxBytes = wg_peer->RxBytes;
|
||||
peerConfig.lastHandshake = (wg_peer->LastHandshake - 116444736000000000LL) / (100 / 1000);
|
||||
|
||||
if (wg_peer->Flags & WIREGUARD_PEER_FLAG::WIREGUARD_PEER_HAS_PRESHARED_KEY) peerConfig.presharedKey = wgKeys::toString(wg_peer->PresharedKey);
|
||||
if (wg_peer->Flags & WIREGUARD_PEER_FLAG::WIREGUARD_PEER_HAS_ENDPOINT) peerConfig.endpoint = parseEndpoint(&wg_peer->Endpoint);
|
||||
if (wg_peer->Flags & WIREGUARD_PEER_FLAG::WIREGUARD_PEER_HAS_PERSISTENT_KEEPALIVE) peerConfig.keepInterval = wg_peer->PersistentKeepalive;
|
||||
if (wg_peer->LastHandshake > 0) peerConfig.lastHandshake = (wg_peer->LastHandshake - 116444736000000000LL) / (100 / 1000);
|
||||
|
||||
WIREGUARD_ALLOWED_IP* wg_aip = changePoint<WIREGUARD_PEER, WIREGUARD_ALLOWED_IP>(wg_peer);
|
||||
for (DWORD __aip = 0; __aip < wg_peer->AllowedIPsCount; __aip++) {
|
||||
@ -355,26 +265,28 @@ void WireguardConfig::getWireguardConfig() {
|
||||
}
|
||||
|
||||
void WireguardConfig::setWireguardConfig() {
|
||||
if (this->name.length() == 0) throw std::string("Require interface name!");
|
||||
else if (this->name.length() > IFNAMSIZ) throw std::string("Interface name too long");
|
||||
|
||||
DWORD buf_len = sizeof(WIREGUARD_INTERFACE);
|
||||
for (auto peer : this->Peers) {
|
||||
if (DWORD_MAX - buf_len < sizeof(WIREGUARD_PEER)) throw ("Buffer overflow");
|
||||
if (DWORD_MAX - buf_len < sizeof(WIREGUARD_PEER)) throw std::string("Buffer overflow");
|
||||
buf_len += sizeof(WIREGUARD_PEER);
|
||||
for (auto aip : peer.second.allowedIPs) {
|
||||
if (DWORD_MAX - buf_len < sizeof(WIREGUARD_ALLOWED_IP)) throw ("Buffer overflow");
|
||||
if (DWORD_MAX - buf_len < sizeof(WIREGUARD_ALLOWED_IP)) throw std::string("Buffer overflow");
|
||||
buf_len += sizeof(WIREGUARD_ALLOWED_IP);
|
||||
}
|
||||
}
|
||||
WIREGUARD_INTERFACE *wg_iface = reinterpret_cast<WIREGUARD_INTERFACE*>(calloc(1, buf_len));
|
||||
if (!wg_iface) throw ("Cannot alloc buff");
|
||||
if (!wg_iface) throw std::string("Cannot alloc buff");
|
||||
wg_iface->PeersCount = 0;
|
||||
|
||||
wgKeys::stringToKey(wg_iface->PrivateKey, privateKey);
|
||||
wgKeys::stringToKey(wg_iface->PrivateKey, this->privateKey);
|
||||
wg_iface->Flags = WIREGUARD_INTERFACE_FLAG::WIREGUARD_INTERFACE_HAS_PRIVATE_KEY;
|
||||
|
||||
wg_iface->ListenPort = portListen;
|
||||
if (portListen >= 0 && 65535 <= portListen) wg_iface->Flags = (WIREGUARD_INTERFACE_FLAG)(wg_iface->Flags|WIREGUARD_INTERFACE_FLAG::WIREGUARD_INTERFACE_HAS_LISTEN_PORT);
|
||||
|
||||
if (replacePeers) wg_iface->Flags = (WIREGUARD_INTERFACE_FLAG)(wg_iface->Flags|WIREGUARD_INTERFACE_FLAG::WIREGUARD_INTERFACE_REPLACE_PEERS);
|
||||
wg_iface->ListenPort = this->portListen;
|
||||
if (this->portListen >= 0) wg_iface->Flags = (WIREGUARD_INTERFACE_FLAG)(wg_iface->Flags|WIREGUARD_INTERFACE_FLAG::WIREGUARD_INTERFACE_HAS_LISTEN_PORT);
|
||||
if (this->replacePeers) wg_iface->Flags = (WIREGUARD_INTERFACE_FLAG)(wg_iface->Flags|WIREGUARD_INTERFACE_FLAG::WIREGUARD_INTERFACE_REPLACE_PEERS);
|
||||
|
||||
WIREGUARD_ALLOWED_IP *wg_aip;
|
||||
WIREGUARD_PEER *wg_peer = changePoint<WIREGUARD_INTERFACE, WIREGUARD_PEER>(wg_iface);
|
||||
@ -398,7 +310,75 @@ void WireguardConfig::setWireguardConfig() {
|
||||
if (peerConfig.keepInterval >= 0) wg_peer->Flags = (WIREGUARD_PEER_FLAG)(wg_peer->Flags|WIREGUARD_PEER_FLAG::WIREGUARD_PEER_HAS_PERSISTENT_KEEPALIVE);
|
||||
|
||||
if (peerConfig.endpoint.size() > 0) {
|
||||
insertEndpoint(&wg_peer->Endpoint, peerConfig.endpoint.c_str());
|
||||
int ret, retries = ([]() -> int {
|
||||
unsigned long ret;
|
||||
char *retries = getenv("WG_ENDPOINT_RESOLUTION_RETRIES"), *end;
|
||||
|
||||
if (!retries) return 15;
|
||||
if (!strcmp(retries, "infinity")) return -1;
|
||||
|
||||
ret = strtoul(retries, &end, 10);
|
||||
if (*end || ret > INT_MAX) {
|
||||
fprintf(stderr, "Unable to parse WG_ENDPOINT_RESOLUTION_RETRIES: `%s'\n", retries);
|
||||
exit(1);
|
||||
}
|
||||
return (int)ret;
|
||||
})();
|
||||
|
||||
char *begin, *end;
|
||||
auto mmutable = strdup(peerConfig.endpoint.c_str());
|
||||
if (!mmutable) throw std::string("strdup");
|
||||
if (!peerConfig.endpoint.size()) {
|
||||
free(mmutable);
|
||||
throw std::string("Unable to parse empty endpoint");
|
||||
}
|
||||
if (mmutable[0] == '[') {
|
||||
begin = &mmutable[1];
|
||||
end = strchr(mmutable, ']');
|
||||
if (!end) {
|
||||
free(mmutable);
|
||||
throw std::string("Unable to find matching brace of endpoint: ").append(peerConfig.endpoint);
|
||||
}
|
||||
*end++ = '\0';
|
||||
if (*end++ != ':' || !*end) {
|
||||
free(mmutable);
|
||||
throw std::string("Unable to find port of endpoint: ").append(peerConfig.endpoint);
|
||||
}
|
||||
} else {
|
||||
begin = mmutable;
|
||||
end = strrchr(mmutable, ':');
|
||||
if (!end || !*(end + 1)) {
|
||||
free(mmutable);
|
||||
throw std::string("Unable to find port of endpoint: ").append(peerConfig.endpoint);
|
||||
}
|
||||
*end++ = '\0';
|
||||
}
|
||||
|
||||
ADDRINFOA *resolved;
|
||||
for (unsigned int timeout = 1000000;; timeout = ((20000000) < (timeout * 6 / 5) ? (20000000) : (timeout * 6 / 5))) {
|
||||
// ret = getaddrinfo(begin, end, &hints, &resolved);
|
||||
ret = getaddrinfo(begin, end, NULL, &resolved);
|
||||
if (!ret) break;
|
||||
if (ret == EAI_NONAME || ret == EAI_FAIL ||
|
||||
#ifdef EAI_NODATA
|
||||
ret == EAI_NODATA ||
|
||||
#endif
|
||||
(retries >= 0 && !retries--)) {
|
||||
free(mmutable);
|
||||
throw std::string("Error code: ").append(std::to_string(ret));
|
||||
}
|
||||
std::this_thread::sleep_for(std::chrono::microseconds(timeout));
|
||||
}
|
||||
|
||||
if ((resolved->ai_family == AF_INET && resolved->ai_addrlen == sizeof(SOCKADDR_IN))) memcpy(&wg_peer->Endpoint.Ipv4, resolved->ai_addr, resolved->ai_addrlen);
|
||||
else if (resolved->ai_family == AF_INET6 && resolved->ai_addrlen == sizeof(SOCKADDR_IN6)) memcpy(&wg_peer->Endpoint.Ipv6, resolved->ai_addr, resolved->ai_addrlen);
|
||||
else {
|
||||
freeaddrinfo(resolved);
|
||||
throw std::string("Neither IPv4 nor IPv6 address found: ").append(peerConfig.endpoint);
|
||||
}
|
||||
freeaddrinfo(resolved);
|
||||
free(mmutable);
|
||||
|
||||
wg_peer->Flags = (WIREGUARD_PEER_FLAG)(wg_peer->Flags|WIREGUARD_PEER_FLAG::WIREGUARD_PEER_HAS_ENDPOINT);
|
||||
}
|
||||
|
||||
@ -420,38 +400,74 @@ void WireguardConfig::setWireguardConfig() {
|
||||
}
|
||||
|
||||
WIREGUARD_ADAPTER_HANDLE Adapter = WireGuardOpenAdapter(toLpcwstr(this->name));
|
||||
if (!Adapter) Adapter = WireGuardCreateAdapter(toLpcwstr(this->name), L"Wireguard-tools.js", NULL);
|
||||
if (!Adapter) Adapter = WireGuardCreateAdapter(toLpcwstr(this->name), WireguardAddonDescription, NULL);
|
||||
if (!Adapter) throw std::string("Failed to create adapter, ").append(getErrorString(GetLastError()));
|
||||
else if (!WireGuardSetConfiguration(Adapter, reinterpret_cast<WIREGUARD_INTERFACE*>(wg_iface), buf_len)) {
|
||||
|
||||
auto status = WireGuardSetConfiguration(Adapter, reinterpret_cast<WIREGUARD_INTERFACE*>(wg_iface), buf_len) && WireGuardSetAdapterState(Adapter, WIREGUARD_ADAPTER_STATE::WIREGUARD_ADAPTER_STATE_UP);
|
||||
free(wg_iface);
|
||||
|
||||
if (!status) {
|
||||
auto status = GetLastError();
|
||||
WireGuardCloseAdapter(Adapter);
|
||||
throw std::string("Failed to set interface config, ").append(getErrorString(status));
|
||||
} else if (!WireGuardSetAdapterState(Adapter, WIREGUARD_ADAPTER_STATE::WIREGUARD_ADAPTER_STATE_UP)) {
|
||||
auto status = GetLastError();
|
||||
WireGuardCloseAdapter(Adapter);
|
||||
throw std::string("Failed to set interface up, ").append(getErrorString(status));
|
||||
} else {
|
||||
this->interfaceAddress.SetInInterface(this->name);
|
||||
}
|
||||
free(wg_iface);
|
||||
|
||||
this->interfaceAddress.SetInInterface(this->name);
|
||||
}
|
||||
|
||||
void IpManeger::GetInInterface(std::string interfaceName) {
|
||||
// Define the InterfaceLuid of the network interface you want to query
|
||||
NET_IFINDEX ind;
|
||||
NET_LUID InterfaceLuid;
|
||||
WIREGUARD_ADAPTER_HANDLE Adapter = WireGuardOpenAdapter(toLpcwstr(interfaceName));
|
||||
if (!Adapter) throw std::string("Cannot open wireguard adapter");
|
||||
NET_LUID InterfaceLuid;
|
||||
WireGuardGetAdapterLUID(Adapter, &InterfaceLuid);
|
||||
if (ConvertInterfaceLuidToIndex(&InterfaceLuid, &ind) != NO_ERROR) throw std::string("Cannot get interface index");
|
||||
|
||||
ULONG bufferSize = 0; // Initial buffer size
|
||||
|
||||
// Call GetAdaptersAddresses to get the required buffer size
|
||||
if (GetAdaptersAddresses(AF_UNSPEC, GAA_FLAG_INCLUDE_PREFIX, nullptr, nullptr, &bufferSize) == ERROR_BUFFER_OVERFLOW) {
|
||||
// Allocate memory for the buffer
|
||||
PIP_ADAPTER_ADDRESSES addresses = reinterpret_cast<IP_ADAPTER_ADDRESSES*>(malloc(bufferSize));
|
||||
// Call GetAdaptersAddresses again with the allocated buffer
|
||||
if (GetAdaptersAddresses(AF_UNSPEC, GAA_FLAG_INCLUDE_PREFIX, nullptr, addresses, &bufferSize) == NO_ERROR) {
|
||||
// Iterate through the list of adapters
|
||||
for (PIP_ADAPTER_ADDRESSES adapter = addresses; adapter != nullptr; adapter = adapter->Next) {
|
||||
// Check if the adapter matches the specified InterfaceLuid
|
||||
if (memcmp(&adapter->Luid, &InterfaceLuid, sizeof(NET_LUID)) == 0) {
|
||||
// Iterate through the list of IP addresses associated with the adapter
|
||||
for (PIP_ADAPTER_UNICAST_ADDRESS address = adapter->FirstUnicastAddress; address != nullptr; address = address->Next) {
|
||||
// Access the IP address in the address structure
|
||||
sockaddr* sa = address->Address.lpSockaddr;
|
||||
char ip[INET6_ADDRSTRLEN];
|
||||
if (sa->sa_family == AF_INET) {
|
||||
inet_ntop(AF_INET, &reinterpret_cast<sockaddr_in*>(sa)->sin_addr, ip, sizeof(ip));
|
||||
} else if (sa->sa_family == AF_INET6) {
|
||||
inet_ntop(AF_INET6, &reinterpret_cast<sockaddr_in6*>(sa)->sin6_addr, ip, sizeof(ip));
|
||||
} else continue;
|
||||
// Print or use the IP address as needed
|
||||
this->addIPMask(std::string(ip).append("/").append(std::to_string(address->Address.iSockaddrLength)));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Free the allocated buffer
|
||||
free(addresses);
|
||||
}
|
||||
}
|
||||
|
||||
// https://docs.microsoft.com/en-us/windows/desktop/api/netioapi/nf-netioapi-createunicastipaddressentry
|
||||
void IpManeger::SetInInterface(std::string interfaceName) {
|
||||
if (this->size() == 0) return;
|
||||
WIREGUARD_ADAPTER_HANDLE Adapter = WireGuardOpenAdapter(toLpcwstr(interfaceName));
|
||||
if (!Adapter) throw std::string("Cannot open wireguard adapter");
|
||||
|
||||
NET_LUID InterfaceLuid;
|
||||
WireGuardGetAdapterLUID(Adapter, &InterfaceLuid);
|
||||
ULONG bufferSize = 0; // Initial buffer size
|
||||
// Call GetAdaptersAddresses to get the required buffer size
|
||||
if (GetAdaptersAddresses(AF_UNSPEC, GAA_FLAG_INCLUDE_PREFIX, nullptr, nullptr, &bufferSize) == ERROR_BUFFER_OVERFLOW) {
|
||||
// Allocate memory for the buffer
|
||||
PIP_ADAPTER_ADDRESSES addresses = reinterpret_cast<IP_ADAPTER_ADDRESSES*>(malloc(bufferSize));
|
||||
// Call GetAdaptersAddresses again with the allocated buffer
|
||||
if (GetAdaptersAddresses(AF_UNSPEC, GAA_FLAG_INCLUDE_PREFIX, nullptr, addresses, &bufferSize) == NO_ERROR) {
|
||||
// Iterate through the list of adapters
|
||||
@ -469,8 +485,19 @@ void IpManeger::GetInInterface(std::string interfaceName) {
|
||||
inet_ntop(AF_INET6, &reinterpret_cast<sockaddr_in6*>(sa)->sin6_addr, ip, sizeof(ip));
|
||||
} else continue;
|
||||
|
||||
// Print or use the IP address as needed
|
||||
this->addIPMask(std::string(ip).append("/").append(std::to_string(address->Address.iSockaddrLength)));
|
||||
// Delete the IP address
|
||||
MIB_UNICASTIPADDRESS_ROW row;
|
||||
memset(&row, 0, sizeof(row));
|
||||
WireGuardGetAdapterLUID(Adapter, &row.InterfaceLuid);
|
||||
if (sa->sa_family == AF_INET) {
|
||||
row.Address.si_family = AF_INET;
|
||||
inet_pton(AF_INET, ip, &row.Address.Ipv4.sin_addr);
|
||||
} else if (sa->sa_family == AF_INET6) {
|
||||
row.Address.si_family = AF_INET6;
|
||||
inet_pton(AF_INET6, ip, &row.Address.Ipv6.sin6_addr);
|
||||
} else continue;
|
||||
|
||||
if (DeleteUnicastIpAddressEntry(&row) != NO_ERROR) throw std::string("Cannot delete IP address from interface");
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -479,14 +506,25 @@ void IpManeger::GetInInterface(std::string interfaceName) {
|
||||
// Free the allocated buffer
|
||||
free(addresses);
|
||||
}
|
||||
}
|
||||
|
||||
void IpManeger::SetInInterface(std::string interfaceName) {
|
||||
if (this->size() == 0) return;
|
||||
NET_IFINDEX interfaceIndex;
|
||||
NET_LUID InterfaceLuid;
|
||||
WIREGUARD_ADAPTER_HANDLE Adapter = WireGuardOpenAdapter(toLpcwstr(interfaceName));
|
||||
if (!Adapter) throw std::string("Cannot open wireguard adapter");
|
||||
WireGuardGetAdapterLUID(Adapter, &InterfaceLuid);
|
||||
if (ConvertInterfaceLuidToIndex(&InterfaceLuid, &interfaceIndex) != NO_ERROR) throw std::string("Cannot get interface index");
|
||||
for (auto ip : this->getIpParsed()) {
|
||||
MIB_UNICASTIPADDRESS_ROW row;
|
||||
memset(&row, 0, sizeof(row));
|
||||
memcpy(&row.InterfaceLuid, &InterfaceLuid, sizeof(NET_LUID));
|
||||
|
||||
row.DadState = NldsPreferred;
|
||||
row.ValidLifetime = 0xffffffff;
|
||||
row.PreferredLifetime = 0xffffffff;
|
||||
|
||||
row.OnLinkPrefixLength = ip.Mask;
|
||||
if (ip.Proto == 4) {
|
||||
row.Address.si_family = AF_INET;
|
||||
inet_pton(AF_INET, ip.Address.c_str(), &row.Address.Ipv4.sin_addr);
|
||||
} else if (ip.Proto == 6) {
|
||||
row.Address.si_family = AF_INET6;
|
||||
inet_pton(AF_INET6, ip.Address.c_str(), &row.Address.Ipv6.sin6_addr);
|
||||
} else continue;
|
||||
|
||||
if (CreateUnicastIpAddressEntry(&row) != NO_ERROR) throw std::string("Cannot add IP address to interface");
|
||||
}
|
||||
}
|
@ -1,164 +0,0 @@
|
||||
#include "wginterface.hh"
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <windows.h>
|
||||
#include <iostream>
|
||||
#include <comdef.h>
|
||||
#include <Wbemidl.h>
|
||||
#include <windows.h>
|
||||
#include <ws2ipdef.h>
|
||||
#include <ws2def.h>
|
||||
#include <winsock2.h>
|
||||
#include <ws2tcpip.h>
|
||||
#include <netioapi.h>
|
||||
#include <iphlpapi.h>
|
||||
#include <win/wireguard.h>
|
||||
|
||||
#pragma comment(lib, "wbemuuid.lib")
|
||||
|
||||
std::string convertWcharString(const wchar_t *wcStr) {
|
||||
int MAXLEN = sizeof(wcStr);
|
||||
static char *tx;
|
||||
wcstombs(tx, wcStr, MAXLEN+1);
|
||||
tx[MAXLEN+1] = 0;
|
||||
return std::string(tx);
|
||||
}
|
||||
|
||||
LPCWSTR toLpcwstr(std::string s) {
|
||||
wchar_t* wString = new wchar_t[s.length()+1];
|
||||
MultiByteToWideChar(CP_ACP, 0, s.c_str(), -1, wString, s.length()+1);
|
||||
return wString;
|
||||
}
|
||||
|
||||
void SetIPAddress(IWbemServices* pSvc, IWbemClassObject* pclsObj, const wchar_t* propertyName, const wchar_t* ip) {
|
||||
VARIANT vtProp;
|
||||
HRESULT hres = pclsObj->Get(propertyName, 0, &vtProp, 0, 0);
|
||||
if (SUCCEEDED(hres)) {
|
||||
vtProp.vt = VT_BSTR;
|
||||
vtProp.bstrVal = SysAllocString(ip);
|
||||
hres = pclsObj->Put(propertyName, 0, &vtProp, 0);
|
||||
VariantClear(&vtProp);
|
||||
|
||||
if (FAILED(hres)) {
|
||||
std::cerr << "Failed to set " << propertyName << ". Error code: " << hres << std::endl;
|
||||
throw std::string("Failed to set ").append(convertWcharString(propertyName)).append(". Error code: ").append(std::to_string(hres));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void IpManeger::GetInInterface(std::string interfaceName) {
|
||||
NET_LUID InterfaceLuid;
|
||||
NET_IFINDEX ind;
|
||||
if (ConvertInterfaceLuidToIndex(&InterfaceLuid, &ind) != NO_ERROR) throw std::string("Cannot get interface index");
|
||||
|
||||
IP_ADAPTER_INFO *pAdapterInfo;
|
||||
ULONG ulOutBufLen;
|
||||
DWORD dwRetVal;
|
||||
pAdapterInfo = (IP_ADAPTER_INFO *)malloc( sizeof(IP_ADAPTER_INFO) );
|
||||
ulOutBufLen = sizeof(IP_ADAPTER_INFO);
|
||||
if (GetAdaptersInfo( pAdapterInfo, &ulOutBufLen) != ERROR_SUCCESS) {
|
||||
free (pAdapterInfo);
|
||||
pAdapterInfo = (IP_ADAPTER_INFO *) malloc(ulOutBufLen);
|
||||
}
|
||||
if ((dwRetVal = GetAdaptersInfo(pAdapterInfo, &ulOutBufLen)) != ERROR_SUCCESS) throw std::string("GetAdaptersInfo call failed with ").append(std::to_string(dwRetVal));
|
||||
PIP_ADAPTER_INFO pAdapter = pAdapterInfo;
|
||||
while (pAdapter) {
|
||||
if (pAdapter->Index == ind) this->push_back(std::string(pAdapter->IpAddressList.IpAddress.String).append("/32"));
|
||||
pAdapter = pAdapter->Next;
|
||||
}
|
||||
if (pAdapterInfo) free(pAdapterInfo);
|
||||
}
|
||||
|
||||
void IpManeger::SetInInterface(std::string interfaceName) {
|
||||
if (this->size() == 0) return;
|
||||
HRESULT hres;
|
||||
|
||||
// Initialize COM
|
||||
hres = CoInitializeEx(0, COINIT_MULTITHREADED);
|
||||
if (FAILED(hres)) throw std::string("Failed to initialize COM library. Error code: ").append(std::to_string(hres));
|
||||
|
||||
// Initialize security
|
||||
hres = CoInitializeSecurity(NULL, -1, NULL, NULL, RPC_C_AUTHN_LEVEL_DEFAULT, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE, NULL);
|
||||
|
||||
if (FAILED(hres)) {
|
||||
CoUninitialize();
|
||||
throw std::string("Failed to initialize security. Error code: ").append(std::to_string(hres));
|
||||
}
|
||||
|
||||
// Obtain the initial locator
|
||||
IWbemLocator* pLoc = NULL;
|
||||
hres = CoCreateInstance(CLSID_WbemLocator, 0, CLSCTX_INPROC_SERVER, IID_IWbemLocator, (LPVOID*)&pLoc);
|
||||
|
||||
if (FAILED(hres)) {
|
||||
CoUninitialize();
|
||||
throw std::string("Failed to create IWbemLocator object. Error code: ").append(std::to_string(hres));
|
||||
}
|
||||
|
||||
// Connect to WMI through the IWbemLocator::ConnectServer method
|
||||
IWbemServices* pSvc = NULL;
|
||||
hres = pLoc->ConnectServer( _bstr_t(L"ROOT\\CIMV2"), NULL, NULL, 0, NULL, 0, 0, &pSvc);
|
||||
|
||||
if (FAILED(hres)) {
|
||||
pLoc->Release();
|
||||
CoUninitialize();
|
||||
throw std::string("Failed to connect to ROOT\\CIMV2. Error code: ").append(std::to_string(hres));
|
||||
}
|
||||
|
||||
// Set the security levels on the proxy
|
||||
hres = CoSetProxyBlanket(pSvc, RPC_C_AUTHN_WINNT, RPC_C_AUTHZ_NONE, NULL, RPC_C_AUTHN_LEVEL_CALL, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE);
|
||||
|
||||
if (FAILED(hres)) {
|
||||
pSvc->Release();
|
||||
pLoc->Release();
|
||||
CoUninitialize();
|
||||
throw std::string("Failed to set proxy blanket. Error code: ").append(std::to_string(hres));
|
||||
}
|
||||
|
||||
// Define the IP addresses and subnet mask
|
||||
const wchar_t* subnetMask = L"255.255.255.0";
|
||||
const wchar_t* adapterDescription = L"Your Network Adapter Description";
|
||||
|
||||
// Construct the query
|
||||
wchar_t query[256];
|
||||
NET_IFINDEX ind;
|
||||
if (ConvertInterfaceLuidToIndex(&InterfaceLuid, &ind) != NO_ERROR) throw std::string("Cannot get interface index");
|
||||
swprintf(query, L"SELECT * FROM Win32_NetworkAdapterConfiguration WHERE InterfaceIndex = '%s'", ind);
|
||||
|
||||
// Execute the query to get the network adapter configuration
|
||||
IEnumWbemClassObject* pEnumerator = NULL;
|
||||
hres = pSvc->ExecQuery(bstr_t("WQL"), bstr_t(query), WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, NULL, &pEnumerator);
|
||||
|
||||
if (FAILED(hres)) {
|
||||
pSvc->Release();
|
||||
pLoc->Release();
|
||||
CoUninitialize();
|
||||
throw std::string("Query failed. Error code: ").append(std::to_string(hres));
|
||||
}
|
||||
|
||||
// Iterate over the query results
|
||||
IWbemClassObject* pclsObj = NULL;
|
||||
ULONG uReturn = 0;
|
||||
|
||||
while (pEnumerator) {
|
||||
hres = pEnumerator->Next(WBEM_INFINITE, 1, &pclsObj, &uReturn);
|
||||
|
||||
if (uReturn == 0) break;
|
||||
|
||||
// Set each IP address
|
||||
for (const auto &ip : this->getIpParsed()) SetIPAddress(pSvc, pclsObj, L"IPAddress", toLpcwstr(ip.Address));
|
||||
|
||||
// Set the subnet mask
|
||||
SetIPAddress(pSvc, pclsObj, L"IPSubnet", subnetMask);
|
||||
|
||||
// Save changes
|
||||
hres = pSvc->PutInstance(pclsObj, WBEM_FLAG_UPDATE_ONLY, NULL, NULL);
|
||||
if (FAILED(hres)) throw std::string("Failed to save changes. Error code: ").append(std::to_string(hres));
|
||||
|
||||
pclsObj->Release();
|
||||
}
|
||||
|
||||
// Cleanup
|
||||
pSvc->Release();
|
||||
pLoc->Release();
|
||||
CoUninitialize();
|
||||
}
|
@ -64,18 +64,7 @@ export interface SetConfig extends Config<SetPeer> {
|
||||
replacePeers?: boolean;
|
||||
};
|
||||
|
||||
const addon = (await loadAddon(path.resolve(__dirname, "../binding.yaml"))).wginterface.load_addon<{
|
||||
/** Userspace support */
|
||||
userspace?: {
|
||||
/** Wireguard-go version */
|
||||
driveVersion?: string;
|
||||
createTunel(wgName: string): Promise<string>;
|
||||
deleteTunel(wgName: string): Promise<void>;
|
||||
checkTunel(wgName: string): Promise<boolean>;
|
||||
listTunels(): Promise<string[]>;
|
||||
};
|
||||
|
||||
/** Kernel wireguard version */
|
||||
export const addon = (await loadAddon(path.resolve(__dirname, "../binding.yaml"))).wginterface.load_addon<{
|
||||
driveVersion?: string;
|
||||
deleteInterface(name: string): Promise<void>;
|
||||
listDevices(): Promise<string[]>;
|
||||
|
Loading…
x
Reference in New Issue
Block a user