diff --git a/.idea/jarRepositories.xml b/.idea/jarRepositories.xml
index fdc392f..0b1d32f 100644
--- a/.idea/jarRepositories.xml
+++ b/.idea/jarRepositories.xml
@@ -16,5 +16,10 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/kotlinc.xml b/.idea/kotlinc.xml
new file mode 100644
index 0000000..ae3f30a
--- /dev/null
+++ b/.idea/kotlinc.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/modules.xml b/.idea/modules.xml
new file mode 100644
index 0000000..053b796
--- /dev/null
+++ b/.idea/modules.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/modules/TVPN.main.iml b/.idea/modules/TVPN.main.iml
new file mode 100644
index 0000000..b4c8ac5
--- /dev/null
+++ b/.idea/modules/TVPN.main.iml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/build-dll.bat b/build-dll.bat
new file mode 100644
index 0000000..a8cc79f
--- /dev/null
+++ b/build-dll.bat
@@ -0,0 +1,3 @@
+@echo off
+cmake -DCMAKE_BUILD_TYPE=Release -G "CodeBlocks - MinGW Makefiles" -S .\src\main\cpp -B .\src\main\cpp\build
+cmake --build .\src\main\cpp\build --target wireguard_wrapper -- -j 14
\ No newline at end of file
diff --git a/build.gradle.kts b/build.gradle.kts
new file mode 100644
index 0000000..450c1c0
--- /dev/null
+++ b/build.gradle.kts
@@ -0,0 +1,55 @@
+plugins {
+ java
+ kotlin("jvm") version "1.9.21"
+ id("com.github.johnrengelman.shadow") version "8.1.1"
+ id("edu.sc.seis.launch4j") version "3.0.6"
+}
+
+group = "tech.nevets"
+version = "0.3.1"
+
+repositories {
+ mavenCentral()
+ maven {
+ url = uri("https://git.nevets.tech/api/packages/Steven/maven")
+ }
+}
+
+dependencies {
+ implementation("com.miglayout:miglayout-swing:11.4.2")
+ implementation("com.miglayout:miglayout-core:11.4.2")
+ implementation("com.formdev:flatlaf:3.5.1")
+ implementation("com.google.code.gson:gson:2.11.0")
+ implementation("tech.nevets:JConf:0.1.0:no-deps")
+}
+
+kotlin {
+ jvmToolchain(21)
+}
+
+//tasks.withType(JavaCompile).configureEach {
+// options.encoding = "UTF-8"
+//}
+
+tasks.jar {
+ manifest {
+ attributes["Main-Class"] = "tech.nevets.tvpn.Main"
+ }
+ configurations["compileClasspath"].forEach { file: File ->
+ from(zipTree(file.absoluteFile))
+ }
+ duplicatesStrategy = DuplicatesStrategy.INCLUDE
+}
+
+launch4j {
+ mainClassName.set("tech.nevets.tvpn.Main")
+ outfile.set("TVPN.exe")
+ setJarTask(project.tasks["shadowJar"])
+ fileDescription.set("TVPN Client")
+ icon.set("$projectDir/src/main/resources/icon.ico")
+ productName.set("TVPN")
+ version.set("$this.version")
+ textVersion.set("$this.version")
+ bundledJrePath.set("./jre")
+ manifest.set("$projectDir/TVPN.exe.manifest")
+}
\ No newline at end of file
diff --git a/build.gradle b/build.gradle.old
similarity index 100%
rename from build.gradle
rename to build.gradle.old
diff --git a/gradle.properties b/gradle.properties
index 5033aa5..63ab434 100644
--- a/gradle.properties
+++ b/gradle.properties
@@ -1,2 +1,2 @@
-org.gradle.jvmargs=-Xmx8192M
-org.gradle.parallel=true
\ No newline at end of file
+org.gradle.jvmargs=-Xmx8192M -Dfile.encoding=UTF-8
+org.gradle.parallel=true
diff --git a/settings.gradle b/settings.gradle
deleted file mode 100644
index b409860..0000000
--- a/settings.gradle
+++ /dev/null
@@ -1,2 +0,0 @@
-rootProject.name = 'TVPN'
-
diff --git a/settings.gradle.kts b/settings.gradle.kts
new file mode 100644
index 0000000..9444639
--- /dev/null
+++ b/settings.gradle.kts
@@ -0,0 +1 @@
+rootProject.name = "TVPN"
diff --git a/src/main/cpp/CMakeLists.txt b/src/main/cpp/CMakeLists.txt
index 1401235..e5e7f5e 100644
--- a/src/main/cpp/CMakeLists.txt
+++ b/src/main/cpp/CMakeLists.txt
@@ -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
diff --git a/src/main/cpp/build.ps1 b/src/main/cpp/build.ps1
new file mode 100644
index 0000000..546c605
--- /dev/null
+++ b/src/main/cpp/build.ps1
@@ -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
\ No newline at end of file
diff --git a/src/main/cpp/example.c b/src/main/cpp/example.c
index 7d8e5bf..1e36c4a 100644
--- a/src/main/cpp/example.c
+++ b/src/main/cpp/example.c
@@ -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];
diff --git a/src/main/cpp/wireguard_wrapper.c b/src/main/cpp/wireguard_wrapper.c
index 8af66fb..ab6d669 100644
--- a/src/main/cpp/wireguard_wrapper.c
+++ b/src/main/cpp/wireguard_wrapper.c
@@ -1,17 +1,23 @@
#include
-#include
#include
-#include
#include
#include
#include
#include "wireguard.h"
+#include
+#include
#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;
+
}
\ No newline at end of file
diff --git a/src/main/java/tech/nevets/tvpn/LogOutputStream.java b/src/main/java/tech/nevets/tvpn/LogOutputStream.java
index e11d587..1ff7294 100644
--- a/src/main/java/tech/nevets/tvpn/LogOutputStream.java
+++ b/src/main/java/tech/nevets/tvpn/LogOutputStream.java
@@ -43,6 +43,8 @@ public class LogOutputStream extends OutputStream {
for (int i = 0; i < pointer; i++) {
sb.append(buf[i]);
}
- textArea.append(sb.toString());
+ if (textArea != null) {
+ textArea.append(sb.toString());
+ }
}
}
diff --git a/src/main/java/tech/nevets/tvpn/Main.java b/src/main/java/tech/nevets/tvpn/Main.java
index b01e2cb..0af7f73 100644
--- a/src/main/java/tech/nevets/tvpn/Main.java
+++ b/src/main/java/tech/nevets/tvpn/Main.java
@@ -2,20 +2,20 @@ package tech.nevets.tvpn;
import com.formdev.flatlaf.FlatDarkLaf;
import tech.nevets.jconf.JsonConfig;
-import tech.nevets.tvpn.cli.CommandBrigadier;
import tech.nevets.tvpn.ui.UIManager;
-import tech.nevets.tvpn.wg.WireGuardJNI;
import javax.swing.*;
import java.io.File;
+import tech.nevets.tvpn.cli.CommandBrigadier;
+
public class Main {
private static final Logger LOGGER = new Logger(Main.class);
public static void main(String[] args) {
LogOutputStream logOut = new LogOutputStream();
Logger.loadLogOutStream(logOut);
- JsonConfig conf = new JsonConfig("");
+ JsonConfig conf = new JsonConfig("config.json");
if (args.length > 0) {
new CommandBrigadier().execute(args);
diff --git a/src/main/java/tech/nevets/tvpn/cli/Command.java b/src/main/java/tech/nevets/tvpn/cli/Command.java
deleted file mode 100644
index 64f0e28..0000000
--- a/src/main/java/tech/nevets/tvpn/cli/Command.java
+++ /dev/null
@@ -1,12 +0,0 @@
-package tech.nevets.tvpn.cli;
-
-public interface Command {
-
- void execute(String[] args);
-
- String getName();
-
- String getUsage();
-
- String getDescription();
-}
diff --git a/src/main/java/tech/nevets/tvpn/cli/CommandBrigadier.java b/src/main/java/tech/nevets/tvpn/cli/CommandBrigadier.java
deleted file mode 100644
index b09f4f5..0000000
--- a/src/main/java/tech/nevets/tvpn/cli/CommandBrigadier.java
+++ /dev/null
@@ -1,49 +0,0 @@
-package tech.nevets.tvpn.cli;
-
-import tech.nevets.tvpn.Logger;
-import tech.nevets.tvpn.cli.commands.HelpCmd;
-import tech.nevets.tvpn.cli.commands.InstallTunnelServiceCmd;
-import tech.nevets.tvpn.cli.commands.UninstallTunnelServiceCmd;
-
-import java.util.ArrayList;
-import java.util.List;
-
-public class CommandBrigadier {
- private static final Logger LOGGER = new Logger(CommandBrigadier.class);
-
- private final List registeredCommands;
- private final HelpCmd helpCmd;
-
- public CommandBrigadier() {
- this.registeredCommands = new ArrayList<>();
- helpCmd = new HelpCmd(this);
-
- registerCommand(helpCmd);
- registerCommand(new InstallTunnelServiceCmd());
- registerCommand(new UninstallTunnelServiceCmd());
- }
-
- public void registerCommand(Command cmd) {
- for (Command c : registeredCommands) {
- if (c.getName().equals(cmd.getName())) {
- LOGGER.warn("Command with name " + cmd.getName() + " already registered, skipping.");
- return;
- }
- }
- registeredCommands.add(cmd);
- }
-
- public void execute(String[] args) {
- for (Command c : registeredCommands) {
- if (c.getName().equals(args[0])) {
- c.execute(args);
- return;
- }
- }
- helpCmd.execute(new String[0]);
- }
-
- public List getCommands() {
- return registeredCommands;
- }
-}
diff --git a/src/main/java/tech/nevets/tvpn/cli/commands/HelpCmd.java b/src/main/java/tech/nevets/tvpn/cli/commands/HelpCmd.java
deleted file mode 100644
index 366a69e..0000000
--- a/src/main/java/tech/nevets/tvpn/cli/commands/HelpCmd.java
+++ /dev/null
@@ -1,52 +0,0 @@
-package tech.nevets.tvpn.cli.commands;
-
-import tech.nevets.tvpn.cli.Command;
-import tech.nevets.tvpn.cli.CommandBrigadier;
-
-public class HelpCmd implements Command {
- private final CommandBrigadier cb;
-
- public HelpCmd(CommandBrigadier cb) {
- this.cb = cb;
- }
-
- @Override
- public void execute(String[] args) {
- if (args.length > 0) {
- for (Command c : cb.getCommands()) {
- if (!(args.length == 1) && args[1].equals(c.getName())) {
- System.out.println("TVPN - Usage Menu [" + c.getName() + "]");
- System.out.println(c.getName() + " " + c.getUsage() + ": " + c.getDescription());
- System.exit(0);
- }
- }
- }
-
- StringBuilder sb = new StringBuilder();
- sb.append("TVPN - Help Menu\n");
- for (Command c : cb.getCommands()) {
- sb.append(" - ").append(c.getName())
- .append(" ").append(c.getUsage())
- .append(": ").append(c.getDescription())
- .append("\n");
- }
-
- System.out.println(sb);
- System.exit(0);
- }
-
- @Override
- public String getName() {
- return "help";
- }
-
- @Override
- public String getUsage() {
- return "";
- }
-
- @Override
- public String getDescription() {
- return "Displays the help menu";
- }
-}
diff --git a/src/main/java/tech/nevets/tvpn/cli/commands/InstallTunnelServiceCmd.java b/src/main/java/tech/nevets/tvpn/cli/commands/InstallTunnelServiceCmd.java
deleted file mode 100644
index 6602669..0000000
--- a/src/main/java/tech/nevets/tvpn/cli/commands/InstallTunnelServiceCmd.java
+++ /dev/null
@@ -1,71 +0,0 @@
-package tech.nevets.tvpn.cli.commands;
-
-import tech.nevets.tvpn.Utils;
-import tech.nevets.tvpn.cli.Command;
-import tech.nevets.tvpn.wg.WireGuardJNI;
-
-import java.util.regex.Pattern;
-
-public class InstallTunnelServiceCmd implements Command {
- @Override
- public void execute(String[] args) {
-
-
- System.out.println("Executing InstallTunnelServiceCmd");
- String path = Utils.APP_DIR + "/configurations/" + args[1] + ".conf";
- System.out.println(new WireGuardJNI().installTunnel(args[1], path));
- System.exit(0);
- }
-
- @Override
- public String getName() {
- return "/installtunnelservice";
- }
-
- @Override
- public String getUsage() {
- return "(/path/to/tunnel/config)";
- }
-
- @Override
- public String getDescription() {
- return "Creates and starts a WireGuard Tunnel Service";
- }
-
- String[] reservedNames = new String[]{
- "CON", "PRN", "AUX", "NUL",
- "COM1", "COM2", "COM3", "COM4", "COM5", "COM6", "COM7", "COM8", "COM9",
- "LPT1", "LPT2", "LPT3", "LPT4", "LPT5", "LPT6", "LPT7", "LPT8", "LPT9",
- };
-
-
- private boolean isReserved(String name) {
- if (name.isEmpty()) {
- return false;
- }
- for (String s : reservedNames) {
- if (name.contains(s)) {
- return true;
- }
- }
- return false;
- }
-
- private static final String[] SPECIAL_CHARS = new String[]{"$", "\\", "/", ":", "*", "?", "\"", "'", "<", ">", "|", "\t", "\00"};
- private boolean hasSpecialChars(String name) {
- for (String s : SPECIAL_CHARS) {
- if (name.contains(s)) {
- return true;
- }
- }
- return false;
- }
-
- private static final Pattern PATTERN = Pattern.compile("^[a-zA-Z0-9_=+.-]{1,32}$");
- private boolean tunnelNameIsValid(String name) {
- if (isReserved(name) || hasSpecialChars(name)) {
- return false;
- }
- return PATTERN.matcher(name).hasMatch();
- }
-}
diff --git a/src/main/java/tech/nevets/tvpn/cli/commands/UninstallTunnelServiceCmd.java b/src/main/java/tech/nevets/tvpn/cli/commands/UninstallTunnelServiceCmd.java
deleted file mode 100644
index 9f812e0..0000000
--- a/src/main/java/tech/nevets/tvpn/cli/commands/UninstallTunnelServiceCmd.java
+++ /dev/null
@@ -1,28 +0,0 @@
-package tech.nevets.tvpn.cli.commands;
-
-import tech.nevets.tvpn.cli.Command;
-import tech.nevets.tvpn.wg.WireGuardJNI;
-
-public class UninstallTunnelServiceCmd implements Command {
- @Override
- public void execute(String[] args) {
- System.out.println("Executing UnInstallTunnelServiceCmd");
- System.out.println(new WireGuardJNI().removeTunnel(args[1]));
- System.exit(0);
- }
-
- @Override
- public String getName() {
- return "/uninstalltunnelservice";
- }
-
- @Override
- public String getUsage() {
- return "(tunnel name)";
- }
-
- @Override
- public String getDescription() {
- return "Stops and removes WireGuard Tunnel Service";
- }
-}
diff --git a/src/main/java/tech/nevets/tvpn/wg/WGConf.java b/src/main/java/tech/nevets/tvpn/wg/WGConf.java
new file mode 100644
index 0000000..d771251
--- /dev/null
+++ b/src/main/java/tech/nevets/tvpn/wg/WGConf.java
@@ -0,0 +1,92 @@
+package tech.nevets.tvpn.wg;
+
+public class WGConf {
+ public Interface iface;
+ public Peer peer;
+ public AllowedIP allowedIP;
+
+ public WGConf(Interface iface, Peer peer, AllowedIP allowedIP) {
+ this.iface = iface;
+ this.peer = peer;
+ this.allowedIP = allowedIP;
+ }
+
+ /*
+ struct WIREGUARD_INTERFACE {
+ WIREGUARD_INTERFACE_FLAG Flags; < Bitwise combination of flags
+ WORD ListenPort; < Port for UDP listen socket, or 0 to choose randomly
+ BYTE PrivateKey[WIREGUARD_KEY_LENGTH]; < Private key of interface
+ BYTE PublicKey[WIREGUARD_KEY_LENGTH]; < Corresponding public key of private key
+ DWORD PeersCount; < Number of peer structs following this struct
+ };
+
+ typedef enum {
+ WIREGUARD_INTERFACE_HAS_PUBLIC_KEY = (1 << 0), < The PublicKey field is set
+ WIREGUARD_INTERFACE_HAS_PRIVATE_KEY = (1 << 1), < The PrivateKey field is set
+ WIREGUARD_INTERFACE_HAS_LISTEN_PORT = (1 << 2), < The ListenPort field is set
+ WIREGUARD_INTERFACE_REPLACE_PEERS = (1 << 3) < Remove all peers before adding new ones
+ } WIREGUARD_INTERFACE_FLAG;
+ */
+ public class Interface {
+ public int flags;
+ public int port; // Should be 0 for random
+ public byte[] privateKey;
+ public byte[] publicKey; // Should be unused, will be calculated by privateKey
+ public int peersCount; // Should be 1
+ }
+
+ /*
+ struct WIREGUARD_PEER {
+ WIREGUARD_PEER_FLAG Flags; < Bitwise combination of flags
+ DWORD Reserved; < Reserved; must be zero
+ BYTE PublicKey[32]; < Public key, the peer's primary identifier
+ BYTE PresharedKey[32]; < Preshared key for additional layer of post-quantum resistance
+ WORD PersistentKeepalive; < Seconds interval, or 0 to disable
+ SOCKADDR_INET Endpoint; < Endpoint, with IP address and UDP port number
+ DWORD64 TxBytes; < Number of bytes transmitted
+ DWORD64 RxBytes; < Number of bytes received
+ DWORD64 LastHandshake; < Time of the last handshake, in 100ns intervals since 1601-01-01 UTC
+ DWORD AllowedIPsCount; < Number of allowed IP structs following this struct
+ };
+
+ typedef enum {
+ WIREGUARD_PEER_HAS_PUBLIC_KEY = 1 << 0, < The PublicKey field is set
+ WIREGUARD_PEER_HAS_PRESHARED_KEY = 1 << 1, < The PresharedKey field is set
+ WIREGUARD_PEER_HAS_PERSISTENT_KEEPALIVE = 1 << 2, < The PersistentKeepAlive field is set
+ WIREGUARD_PEER_HAS_ENDPOINT = 1 << 3, < The Endpoint field is set
+ WIREGUARD_PEER_REPLACE_ALLOWED_IPS = 1 << 5, < Remove all allowed IPs before adding new ones
+ WIREGUARD_PEER_REMOVE = 1 << 6, < Remove specified peer
+ WIREGUARD_PEER_UPDATE = 1 << 7 < Do not add a new peer
+ } WIREGUARD_PEER_FLAG;
+ */
+ public class Peer {
+ public int flags;
+ public int reserved = 0; // "Must be 0"
+ public byte[] publicKey;
+ public byte[] presharedKey;
+ public int persistentKeepalive; // In seconds, or 0 to disable
+ public byte[] endpoint; // Going to have to figure out how to parse this. IP + UDP Port
+ public int txBytes; // Unused, changed later
+ public int rxBytes; // Unused, changed later
+ public long lastHandshake; // Time of last handshake, in 100ns intervals since 1601-01-01 UTC. Unused, changed later
+ public int allowedIPsCount; // Number of allowed IP structures
+ }
+
+ /*
+ struct WIREGUARD_ALLOWED_IP {
+ union
+ {
+ IN_ADDR V4;
+ IN6_ADDR V6;
+ } Address; < IP address
+ ADDRESS_FAMILY AddressFamily; < Address family, either AF_INET or AF_INET6
+ BYTE Cidr; < CIDR of allowed IPs
+ };
+ */
+ public class AllowedIP {
+ public String address; // IP address; the V4 member is an IN_ADDR and the V6 member is an IN6_ADDR
+ public String addressFamily; // Address family, either AF_INET or AF_INET6
+ public byte cidr; // The CIDR of the address range
+ }
+}
+
diff --git a/src/main/java/tech/nevets/tvpn/wg/WireGuardJNI.java b/src/main/java/tech/nevets/tvpn/wg/WireGuardJNI.java
index 5251a65..dc11f5e 100644
--- a/src/main/java/tech/nevets/tvpn/wg/WireGuardJNI.java
+++ b/src/main/java/tech/nevets/tvpn/wg/WireGuardJNI.java
@@ -1,9 +1,14 @@
package tech.nevets.tvpn.wg;
+import tech.nevets.tvpn.Logger;
+
public class WireGuardJNI {
+ private static final Logger LOGGER = new Logger(WireGuardJNI.class);
+
// Load the native library
static {
System.loadLibrary("libwireguard_wrapper"); // This will load wireguard_wrapper.dll (or .so on Linux)
+ LOGGER.log("Loaded libwireguard_wrapper");
}
// Native method declaration
@@ -29,5 +34,8 @@ public class WireGuardJNI {
public native int initializeWireGuard(String configFilePath);
public native void cleanup();
+ public native String getWGVersion();
+ public native long parseConfig(WGConf conf);
+
// Other methods for WireGuard interaction can be added here if needed
}
diff --git a/src/main/kotlin/tech/nevets/tvpn/cli/Command.kt b/src/main/kotlin/tech/nevets/tvpn/cli/Command.kt
new file mode 100644
index 0000000..18b76b9
--- /dev/null
+++ b/src/main/kotlin/tech/nevets/tvpn/cli/Command.kt
@@ -0,0 +1,11 @@
+package tech.nevets.tvpn.cli
+
+interface Command {
+ fun execute(args: Array)
+
+ fun getName(): String
+
+ fun getUsage(): String
+
+ fun getDescription(): String
+}
\ No newline at end of file
diff --git a/src/main/kotlin/tech/nevets/tvpn/cli/CommandBrigadier.kt b/src/main/kotlin/tech/nevets/tvpn/cli/CommandBrigadier.kt
new file mode 100644
index 0000000..a70d29c
--- /dev/null
+++ b/src/main/kotlin/tech/nevets/tvpn/cli/CommandBrigadier.kt
@@ -0,0 +1,41 @@
+package tech.nevets.tvpn.cli
+
+import tech.nevets.tvpn.cli.commands.*
+import tech.nevets.tvpn.Logger
+
+class CommandBrigadier {
+ private val logger: Logger = Logger(CommandBrigadier::class.java)
+ private val registeredCmds: List = ArrayList()
+ private val helpCmd: HelpCmd = HelpCmd(this)
+
+ init {
+ registerCmd(helpCmd)
+ registerCmd(InstallTunnelServiceCmd())
+ registerCmd(UninstallTunnelServiceCmd())
+ registerCmd(VersionCmd())
+ }
+
+ private fun registerCmd(cmd: Command) {
+ for (c in registeredCmds) {
+ if (c.getName() == cmd.getName()) {
+ logger.warn("Command with name " + cmd.getName() + " already registered, skipping.")
+ return
+ }
+ }
+ registeredCmds.addLast(cmd)
+ }
+
+ fun execute(args: Array) {
+ for (c in registeredCmds) {
+ if (c.getName() == args[0]) {
+ c.execute(args)
+ return
+ }
+ }
+ helpCmd.execute(arrayOf(""))
+ }
+
+ fun getCommands(): List {
+ return registeredCmds
+ }
+}
\ No newline at end of file
diff --git a/src/main/kotlin/tech/nevets/tvpn/cli/commands/HelpCmd.kt b/src/main/kotlin/tech/nevets/tvpn/cli/commands/HelpCmd.kt
new file mode 100644
index 0000000..4d4151d
--- /dev/null
+++ b/src/main/kotlin/tech/nevets/tvpn/cli/commands/HelpCmd.kt
@@ -0,0 +1,45 @@
+package tech.nevets.tvpn.cli.commands
+
+import tech.nevets.tvpn.cli.Command
+import tech.nevets.tvpn.cli.CommandBrigadier
+import kotlin.system.exitProcess
+
+class HelpCmd(private val cb: CommandBrigadier) : Command {
+
+ override fun execute(args: Array) {
+ if (args.isNotEmpty()) {
+ for (c in cb.getCommands()) {
+ if (args.size != 1 && args[1] == c.getName()) {
+ println(("TVPN - Usage Menu [" + c.getName()) + "]")
+ println((c.getName() + " " + c.getUsage()) + ": " + c.getDescription())
+ exitProcess(0)
+ }
+ }
+ }
+
+ val sb = StringBuilder()
+ sb.append("TVPN - Help Menu\n")
+ for (c in cb.getCommands()) {
+ sb.append(" - ").append(c.getName())
+ .append(" ").append(c.getUsage())
+ .append(": ").append(c.getDescription())
+ .append("\n")
+ }
+
+ println(sb)
+ exitProcess(0)
+ }
+
+ override fun getName(): String {
+ return "help"
+ }
+
+ override fun getUsage(): String {
+ return ""
+ }
+
+ override fun getDescription(): String {
+ return "Displays the help menu"
+ }
+
+}
\ No newline at end of file
diff --git a/src/main/kotlin/tech/nevets/tvpn/cli/commands/InstallTunnelServiceCmd.kt b/src/main/kotlin/tech/nevets/tvpn/cli/commands/InstallTunnelServiceCmd.kt
new file mode 100644
index 0000000..93517ad
--- /dev/null
+++ b/src/main/kotlin/tech/nevets/tvpn/cli/commands/InstallTunnelServiceCmd.kt
@@ -0,0 +1,65 @@
+package tech.nevets.tvpn.cli.commands
+
+import tech.nevets.tvpn.Utils
+import tech.nevets.tvpn.cli.Command
+import tech.nevets.tvpn.wg.WireGuardJNI
+import java.util.regex.Pattern
+import kotlin.system.exitProcess
+
+class InstallTunnelServiceCmd : Command {
+ override fun execute(args: Array) {
+ println("Executing InstallTunnelServiceCmd")
+ val path = Utils.APP_DIR.toString() + "/configurations/" + args[1] + ".conf"
+ println(WireGuardJNI().installTunnel(args[1], path))
+ exitProcess(0)
+ }
+
+ override fun getName(): String {
+ return "/installtunnelservice"
+ }
+
+ override fun getUsage(): String {
+ return "(/path/to/tunnel/config)"
+ }
+
+ override fun getDescription(): String {
+ return "Creates and starts a WireGuard Tunnel Service"
+ }
+
+ private var reservedNames: Array = arrayOf(
+ "CON", "PRN", "AUX", "NUL",
+ "COM1", "COM2", "COM3", "COM4", "COM5", "COM6", "COM7", "COM8", "COM9",
+ "LPT1", "LPT2", "LPT3", "LPT4", "LPT5", "LPT6", "LPT7", "LPT8", "LPT9",
+ )
+
+
+ private fun isReserved(name: String): Boolean {
+ if (name.isEmpty()) {
+ return false
+ }
+ for (s in reservedNames) {
+ if (name.contains(s)) {
+ return true
+ }
+ }
+ return false
+ }
+
+ private val specialChars = arrayOf("$", "\\", "/", ":", "*", "?", "\"", "'", "<", ">", "|", "\t", "\u0000")
+ private fun hasSpecialChars(name: String): Boolean {
+ for (s in specialChars) {
+ if (name.contains(s)) {
+ return true
+ }
+ }
+ return false
+ }
+
+ private val pattern: Pattern = Pattern.compile("^[a-zA-Z0-9_=+.-]{1,32}$")
+ private fun tunnelNameIsValid(name: String): Boolean {
+ if (isReserved(name) || hasSpecialChars(name)) {
+ return false
+ }
+ return pattern.matcher(name).hasMatch()
+ }
+}
\ No newline at end of file
diff --git a/src/main/kotlin/tech/nevets/tvpn/cli/commands/UninstallTunnelServiceCmd.kt b/src/main/kotlin/tech/nevets/tvpn/cli/commands/UninstallTunnelServiceCmd.kt
new file mode 100644
index 0000000..c7435ad
--- /dev/null
+++ b/src/main/kotlin/tech/nevets/tvpn/cli/commands/UninstallTunnelServiceCmd.kt
@@ -0,0 +1,25 @@
+package tech.nevets.tvpn.cli.commands
+
+import tech.nevets.tvpn.cli.Command
+import tech.nevets.tvpn.wg.WireGuardJNI
+import kotlin.system.exitProcess
+
+class UninstallTunnelServiceCmd : Command {
+ override fun execute(args: Array) {
+ println("Executing UnInstallTunnelServiceCmd")
+ println(WireGuardJNI().removeTunnel(args[1]))
+ exitProcess(0)
+ }
+
+ override fun getName(): String {
+ return "/uninstalltunnelservice"
+ }
+
+ override fun getUsage(): String {
+ return "(tunnel name)"
+ }
+
+ override fun getDescription(): String {
+ return "Stops and removes WireGuard Tunnel Service"
+ }
+}
\ No newline at end of file
diff --git a/src/main/kotlin/tech/nevets/tvpn/cli/commands/VersionCmd.kt b/src/main/kotlin/tech/nevets/tvpn/cli/commands/VersionCmd.kt
new file mode 100644
index 0000000..0d09728
--- /dev/null
+++ b/src/main/kotlin/tech/nevets/tvpn/cli/commands/VersionCmd.kt
@@ -0,0 +1,26 @@
+package tech.nevets.tvpn.cli.commands
+
+import tech.nevets.tvpn.cli.Command
+import tech.nevets.tvpn.wg.WireGuardJNI
+import kotlin.system.exitProcess
+
+class VersionCmd : Command {
+ override fun execute(args: Array) {
+ println("Version: 0.3.1")
+ print("WireGuard Version: ")
+ WireGuardJNI().getWGVersion()
+ exitProcess(0)
+ }
+
+ override fun getName(): String {
+ return "version"
+ }
+
+ override fun getUsage(): String {
+ return ""
+ }
+
+ override fun getDescription(): String {
+ return "Shows the current running version."
+ }
+}
\ No newline at end of file