This commit is contained in:
@@ -15,9 +15,11 @@ set(JNI_INCLUDE_DIR2 "${JAVA_HOME}/include/win32")
|
||||
include_directories(${JNI_INCLUDE_DIR} ${JNI_INCLUDE_DIR2})
|
||||
|
||||
# Add the source file that includes your JNI C wrapper code
|
||||
add_library(wireguard_wrapper SHARED wireguard_wrapper.c)
|
||||
add_library(wireguard_wrapper SHARED wireguard_wrapper.c
|
||||
example.c)
|
||||
|
||||
target_link_libraries(wireguard_wrapper PRIVATE Rpcrt4)
|
||||
#target_link_libraries(wireguard_wrapper PRIVATE Rpcrt4)
|
||||
target_link_libraries(wireguard_wrapper ws2_32 rpcrt4)
|
||||
|
||||
# Optionally, you can specify output directory for the compiled library
|
||||
set_target_properties(wireguard_wrapper PROPERTIES
|
||||
|
||||
4
src/main/cpp/build.ps1
Normal file
4
src/main/cpp/build.ps1
Normal file
@@ -0,0 +1,4 @@
|
||||
Get-ChildItem -Path build -Recurse | Remove-Item -force -recurse
|
||||
if (Test-Path -Path .\build) { Remove-Item -Path .\build -Recurse -Force }
|
||||
cmake -DCMAKE_BUILD_TYPE=Release -G "CodeBlocks - MinGW Makefiles" -S . -B .\build
|
||||
cmake --build .\build --target wireguard_wrapper -- -j 14
|
||||
@@ -276,10 +276,19 @@ int __cdecl main(void)
|
||||
WIREGUARD_INTERFACE Interface;
|
||||
WIREGUARD_PEER DemoServer;
|
||||
WIREGUARD_ALLOWED_IP AllV4;
|
||||
} Config = { .Interface = { .Flags = WIREGUARD_INTERFACE_HAS_PRIVATE_KEY, .PeersCount = 1 },
|
||||
.DemoServer = { .Flags = WIREGUARD_PEER_HAS_PUBLIC_KEY | WIREGUARD_PEER_HAS_ENDPOINT,
|
||||
.AllowedIPsCount = 1 },
|
||||
.AllV4 = { .AddressFamily = AF_INET } };
|
||||
} Config = {
|
||||
.Interface = {
|
||||
.Flags = WIREGUARD_INTERFACE_HAS_PRIVATE_KEY,
|
||||
.PeersCount = 1
|
||||
},
|
||||
.DemoServer = {
|
||||
.Flags = WIREGUARD_PEER_HAS_PUBLIC_KEY | WIREGUARD_PEER_HAS_ENDPOINT,
|
||||
.AllowedIPsCount = 1
|
||||
},
|
||||
.AllV4 = {
|
||||
.AddressFamily = AF_INET
|
||||
}
|
||||
};
|
||||
|
||||
Log(WIREGUARD_LOG_INFO, L"Generating keypair");
|
||||
BYTE PublicKey[WIREGUARD_KEY_LENGTH];
|
||||
|
||||
@@ -1,17 +1,23 @@
|
||||
#include <jni.h>
|
||||
#include <rpc.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <wchar.h>
|
||||
#include <winsock2.h>
|
||||
#include <windows.h>
|
||||
#include "wireguard.h"
|
||||
#include <string.h>
|
||||
#include <ws2tcpip.h>
|
||||
#include "tech_nevets_tvpn_wg_WireGuardJNI.h"
|
||||
|
||||
#pragma comment(lib, "Rpcrt4.lib")
|
||||
|
||||
const wchar_t *APP_DIR = L"C:\\Program Files\\TVPN\\";
|
||||
|
||||
typedef struct {
|
||||
WIREGUARD_INTERFACE Interface;
|
||||
WIREGUARD_PEER Peer;
|
||||
WIREGUARD_ALLOWED_IP AllowedIP;
|
||||
} Config;
|
||||
|
||||
static WIREGUARD_CREATE_ADAPTER_FUNC *WireGuardCreateAdapter;
|
||||
static WIREGUARD_OPEN_ADAPTER_FUNC *WireGuardOpenAdapter;
|
||||
static WIREGUARD_CLOSE_ADAPTER_FUNC *WireGuardCloseAdapter;
|
||||
@@ -26,12 +32,12 @@ static WIREGUARD_GET_CONFIGURATION_FUNC *WireGuardGetConfiguration;
|
||||
static WIREGUARD_SET_CONFIGURATION_FUNC *WireGuardSetConfiguration;
|
||||
|
||||
static HMODULE InitializeWireGuardNT(void) {
|
||||
HMODULE WireGuardDll = LoadLibraryExW(
|
||||
L"wireguard.dll",
|
||||
NULL,
|
||||
LOAD_LIBRARY_SEARCH_APPLICATION_DIR | LOAD_LIBRARY_SEARCH_SYSTEM32
|
||||
);
|
||||
if (!WireGuardDll) return NULL;
|
||||
printf("[C] Starting InitializeWireGuardNT!\n");
|
||||
HMODULE WireGuardDll = LoadLibraryW(L"wireguard.dll");
|
||||
if (!WireGuardDll) {
|
||||
printf("[C] Error loading wireguard.dll\n");
|
||||
return NULL;
|
||||
}
|
||||
#define X(Name) ((*(FARPROC *)&Name = GetProcAddress(WireGuardDll, #Name)) == NULL)
|
||||
if (X(WireGuardCreateAdapter) || X(WireGuardOpenAdapter) || X(WireGuardCloseAdapter) ||
|
||||
X(WireGuardGetAdapterLUID) || X(WireGuardGetRunningDriverVersion) || X(WireGuardDeleteDriver) ||
|
||||
@@ -40,14 +46,16 @@ static HMODULE InitializeWireGuardNT(void) {
|
||||
#undef X
|
||||
{
|
||||
DWORD LastError = GetLastError();
|
||||
fprintf(stderr, "[C] Failed to load wireguard.dll, error code: %lu\n", LastError);
|
||||
FreeLibrary(WireGuardDll);
|
||||
SetLastError(LastError);
|
||||
return NULL;
|
||||
}
|
||||
printf("[C] Finished Init WG.dll\n");
|
||||
return WireGuardDll;
|
||||
}
|
||||
|
||||
GUID generateGUID() {
|
||||
static GUID generateGUID(void) {
|
||||
UUID uuid;
|
||||
RPC_STATUS status = UuidCreate(&uuid);
|
||||
|
||||
@@ -115,7 +123,7 @@ JNIEXPORT jint JNICALL Java_tech_nevets_tvpn_wg_WireGuardJNI_installTunnel(JNIEn
|
||||
const jchar *rawStr = (*env)->GetStringChars(env, tunnelName, 0); //TODO mem cleanup
|
||||
LPWSTR tnlName = (LPWSTR) rawStr;
|
||||
|
||||
wprintf(L"[C] Tunnel Name: %ls", tnlName);
|
||||
wprintf(L"[C] Tunnel Name: %ls\n", tnlName);
|
||||
|
||||
wchar_t *servicePrefix = L"WireGuardTunnel$";
|
||||
wchar_t *serviceName = malloc(sizeof(wchar_t) * (wcslen(servicePrefix) + wcslen(tnlName) + 1)); //TODO mem cleanup
|
||||
@@ -244,4 +252,115 @@ JNIEXPORT jint JNICALL Java_tech_nevets_tvpn_wg_WireGuardJNI_removeTunnel(JNIEnv
|
||||
free(tnlName);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
JNIEXPORT jlong JNICALL Java_tech_nevets_tvpn_wg_WireGuardJNI_getWGVersion(JNIEnv *env, jobject obj) {
|
||||
WSADATA WsaData;
|
||||
if (WSAStartup(MAKEWORD(2, 2), &WsaData)) {
|
||||
fprintf(stderr, "[C] Failed to initialize Winsock\n");
|
||||
return 0;
|
||||
}
|
||||
HMODULE WireGuardDLL = InitializeWireGuardNT();
|
||||
printf("[C] Post Init WGNT\n");
|
||||
|
||||
if (WireGuardDLL == NULL) {
|
||||
fprintf(stderr, "[C] Failed to initialize WireGuardNT library\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
DWORD Version = WireGuardGetRunningDriverVersion();
|
||||
printf("[C] Before Printed version\n");
|
||||
|
||||
|
||||
//printf("[C] WG Ver: %lu\n", Version);
|
||||
wprintf(L"WireGuardNT v%u.%u loaded", (Version >> 16) & 0xff, (Version >> 0) & 0xff);
|
||||
|
||||
FreeLibrary(WireGuardDLL);
|
||||
return Version;
|
||||
}
|
||||
|
||||
JNIEXPORT jlong JNICALL Java_tech_nevets_tvpn_wg_WireGuardJNI_parseConfig(JNIEnv *env, jobject obj, jobject conf) {
|
||||
// Allocate memory for Config struct
|
||||
Config *config = (Config *)malloc(sizeof(Config));
|
||||
if (config == NULL) {
|
||||
return 0; // Memory allocation failed
|
||||
}
|
||||
|
||||
// Get WGConf class and fields
|
||||
jclass wgConfClass = (*env)->GetObjectClass(env, conf);
|
||||
|
||||
// Step 1: Fill Interface fields
|
||||
jfieldID ifaceFieldID = (*env)->GetFieldID(env, wgConfClass, "iface", "Ltech/nevets/tvpn/wg/WGConf$Interface;");
|
||||
jobject ifaceObj = (*env)->GetObjectField(env, conf, ifaceFieldID);
|
||||
|
||||
jclass ifaceClass = (*env)->GetObjectClass(env, ifaceObj);
|
||||
config->Interface.Flags = (WIREGUARD_INTERFACE_FLAG)(*env)->GetIntField(env, ifaceObj, (*env)->GetFieldID(env, ifaceClass, "flags", "I"));
|
||||
config->Interface.ListenPort = (WORD)(*env)->GetIntField(env, ifaceObj, (*env)->GetFieldID(env, ifaceClass, "port", "I"));
|
||||
|
||||
// Get and copy privateKey
|
||||
jbyteArray privateKeyArray = (jbyteArray)(*env)->GetObjectField(env, ifaceObj, (*env)->GetFieldID(env, ifaceClass, "privateKey", "[B"));
|
||||
(*env)->GetByteArrayRegion(env, privateKeyArray, 0, WIREGUARD_KEY_LENGTH, (jbyte *)config->Interface.PrivateKey);
|
||||
|
||||
// Get and copy publicKey
|
||||
jbyteArray publicKeyArray = (jbyteArray)(*env)->GetObjectField(env, ifaceObj, (*env)->GetFieldID(env, ifaceClass, "publicKey", "[B"));
|
||||
(*env)->GetByteArrayRegion(env, publicKeyArray, 0, WIREGUARD_KEY_LENGTH, (jbyte *)config->Interface.PublicKey);
|
||||
|
||||
config->Interface.PeersCount = (DWORD)(*env)->GetIntField(env, ifaceObj, (*env)->GetFieldID(env, ifaceClass, "peersCount", "I"));
|
||||
|
||||
// Step 2: Fill Peer fields
|
||||
jfieldID peerFieldID = (*env)->GetFieldID(env, wgConfClass, "peer", "Ltech/nevets/tvpn/wg/WGConf$Peer;");
|
||||
jobject peerObj = (*env)->GetObjectField(env, conf, peerFieldID);
|
||||
|
||||
jclass peerClass = (*env)->GetObjectClass(env, peerObj);
|
||||
config->Peer.Flags = (WIREGUARD_PEER_FLAG)(*env)->GetIntField(env, peerObj, (*env)->GetFieldID(env, peerClass, "flags", "I"));
|
||||
config->Peer.Reserved = (DWORD)(*env)->GetIntField(env, peerObj, (*env)->GetFieldID(env, peerClass, "reserved", "I"));
|
||||
|
||||
// Get and copy publicKey
|
||||
jbyteArray peerPublicKeyArray = (jbyteArray)(*env)->GetObjectField(env, peerObj, (*env)->GetFieldID(env, peerClass, "publicKey", "[B"));
|
||||
(*env)->GetByteArrayRegion(env, peerPublicKeyArray, 0, WIREGUARD_KEY_LENGTH, (jbyte *)config->Peer.PublicKey);
|
||||
|
||||
// Get and copy presharedKey
|
||||
jbyteArray presharedKeyArray = (jbyteArray)(*env)->GetObjectField(env, peerObj, (*env)->GetFieldID(env, peerClass, "presharedKey", "[B"));
|
||||
(*env)->GetByteArrayRegion(env, presharedKeyArray, 0, WIREGUARD_KEY_LENGTH, (jbyte *)config->Peer.PresharedKey);
|
||||
|
||||
config->Peer.PersistentKeepalive = (WORD)(*env)->GetIntField(env, peerObj, (*env)->GetFieldID(env, peerClass, "persistentKeepalive", "I"));
|
||||
config->Peer.AllowedIPsCount = (DWORD)(*env)->GetIntField(env, peerObj, (*env)->GetFieldID(env, peerClass, "allowedIPsCount", "I"));
|
||||
|
||||
// Endpoint is more complex: requires parsing from byte array and setting `SOCKADDR_INET`
|
||||
jbyteArray endpointArray = (jbyteArray)(*env)->GetObjectField(env, peerObj, (*env)->GetFieldID(env, peerClass, "endpoint", "[B"));
|
||||
jsize endpointLen = (*env)->GetArrayLength(env, endpointArray);
|
||||
jbyte *endpointBytes = (*env)->GetByteArrayElements(env, endpointArray, NULL);
|
||||
|
||||
if (endpointLen == sizeof(SOCKADDR_INET)) {
|
||||
memcpy(&config->Peer.Endpoint, endpointBytes, sizeof(SOCKADDR_INET));
|
||||
}
|
||||
(*env)->ReleaseByteArrayElements(env, endpointArray, endpointBytes, 0);
|
||||
|
||||
// Step 3: Fill AllowedIP fields
|
||||
jfieldID allowedIPFieldID = (*env)->GetFieldID(env, wgConfClass, "allowedIP", "Ltech/nevets/tvpn/wg/WGConf$AllowedIP;");
|
||||
jobject allowedIPObj = (*env)->GetObjectField(env, conf, allowedIPFieldID);
|
||||
|
||||
jclass allowedIPClass = (*env)->GetObjectClass(env, allowedIPObj);
|
||||
jstring addressStr = (jstring)(*env)->GetObjectField(env, allowedIPObj, (*env)->GetFieldID(env, allowedIPClass, "address", "Ljava/lang/String;"));
|
||||
const char *addressChars = (*env)->GetStringUTFChars(env, addressStr, NULL);
|
||||
|
||||
// Assuming address parsing logic here, converting to either IN_ADDR or IN6_ADDR based on `addressFamily`
|
||||
jstring familyStr = (jstring)(*env)->GetObjectField(env, allowedIPObj, (*env)->GetFieldID(env, allowedIPClass, "addressFamily", "Ljava/lang/String;"));
|
||||
const char *familyChars = (*env)->GetStringUTFChars(env, familyStr, NULL);
|
||||
|
||||
if (strcmp(familyChars, "AF_INET") == 0) {
|
||||
config->AllowedIP.AddressFamily = AF_INET;
|
||||
inet_pton(AF_INET, addressChars, &config->AllowedIP.Address.V4);
|
||||
} else if (strcmp(familyChars, "AF_INET6") == 0) {
|
||||
config->AllowedIP.AddressFamily = AF_INET6;
|
||||
inet_pton(AF_INET6, addressChars, &config->AllowedIP.Address.V6);
|
||||
}
|
||||
(*env)->ReleaseStringUTFChars(env, familyStr, familyChars);
|
||||
(*env)->ReleaseStringUTFChars(env, addressStr, addressChars);
|
||||
|
||||
config->AllowedIP.Cidr = (BYTE)(*env)->GetByteField(env, allowedIPObj, (*env)->GetFieldID(env, allowedIPClass, "cidr", "B"));
|
||||
|
||||
// Return the pointer to Config struct as jlong
|
||||
return (jlong)(uintptr_t)config;
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user