aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
authorJason A. Donenfeld <Jason@zx2c4.com>2021-08-09 22:38:35 +0200
committerJason A. Donenfeld <Jason@zx2c4.com>2021-08-10 02:30:33 +0200
commit747f5d07fbf14c76c9b43e91a7f81f1cab5edc51 (patch)
treea7b1e8748dc3ed2122ee4e812e4c9de91b071c3f
parentembeddable-dll-service: use wgnt always (diff)
downloadwireguard-windows-747f5d07fbf14c76c9b43e91a7f81f1cab5edc51.tar.xz
wireguard-windows-747f5d07fbf14c76c9b43e91a7f81f1cab5edc51.zip
embeddable-dll-service: csharp: update for wgnt
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
-rw-r--r--embeddable-dll-service/csharp/DemoUI/MainWindow.cs58
-rw-r--r--embeddable-dll-service/csharp/TunnelDll/Driver.cs236
-rw-r--r--embeddable-dll-service/csharp/TunnelDll/Service.cs5
-rw-r--r--embeddable-dll-service/csharp/TunnelDll/Win32.cs52
4 files changed, 316 insertions, 35 deletions
diff --git a/embeddable-dll-service/csharp/DemoUI/MainWindow.cs b/embeddable-dll-service/csharp/DemoUI/MainWindow.cs
index 7d1e3f6f..6e3eb21f 100644
--- a/embeddable-dll-service/csharp/DemoUI/MainWindow.cs
+++ b/embeddable-dll-service/csharp/DemoUI/MainWindow.cs
@@ -66,49 +66,43 @@ namespace DemoUI
private void tailTransfer()
{
- StreamReader reader = null;
- NamedPipeClientStream stream = null;
+ Tunnel.Driver.Adapter adapter = null;
while (threadsRunning)
{
- try
+ if (adapter == null)
{
- stream = Tunnel.Service.GetPipe(configFile);
- stream.Connect();
- reader = new StreamReader(stream);
- break;
+ while (threadsRunning)
+ {
+ try
+ {
+ adapter = Tunnel.Service.GetAdapter(configFile);
+ break;
+ }
+ catch
+ {
+ try
+ {
+ Thread.Sleep(1000);
+ }
+ catch { }
+ }
+ }
}
- catch { }
- Thread.Sleep(1000);
- }
-
- try
- {
- while (threadsRunning)
+ if (adapter == null)
+ continue;
+ try
{
- stream.Write(Encoding.UTF8.GetBytes("get=1\n\n"));
ulong rx = 0, tx = 0;
- while (threadsRunning)
+ var config = adapter.GetConfiguration();
+ foreach (var peer in config.Peers)
{
- var line = reader.ReadLine();
- if (line == null)
- break;
- line = line.Trim();
- if (line.Length == 0)
- break;
- if (line.StartsWith("rx_bytes="))
- rx += ulong.Parse(line.Substring(9));
- else if (line.StartsWith("tx_bytes="))
- tx += ulong.Parse(line.Substring(9));
+ rx += peer.RxBytes;
+ tx += peer.TxBytes;
}
Invoke(new Action<ulong, ulong>(updateTransferTitle), new object[] { rx, tx });
Thread.Sleep(1000);
}
- }
- catch { }
- finally
- {
- if (stream.IsConnected)
- stream.Close();
+ catch { adapter = null; }
}
}
diff --git a/embeddable-dll-service/csharp/TunnelDll/Driver.cs b/embeddable-dll-service/csharp/TunnelDll/Driver.cs
new file mode 100644
index 00000000..2e7b69a5
--- /dev/null
+++ b/embeddable-dll-service/csharp/TunnelDll/Driver.cs
@@ -0,0 +1,236 @@
+/* SPDX-License-Identifier: MIT
+ *
+ * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+ */
+
+using System;
+using System.ComponentModel;
+using System.Net;
+using System.Runtime.InteropServices;
+
+namespace Tunnel
+{
+ public class Driver
+ {
+ [DllImport("wireguard.dll", EntryPoint = "WireGuardOpenAdapter", CallingConvention = CallingConvention.Cdecl, SetLastError = true)]
+ private static extern IntPtr openAdapter([MarshalAs(UnmanagedType.LPWStr)] string pool, [MarshalAs(UnmanagedType.LPWStr)] string name);
+ [DllImport("wireguard.dll", EntryPoint = "WireGuardFreeAdapter", CallingConvention = CallingConvention.Cdecl)]
+ private static extern void freeAdapter(IntPtr adapter);
+ [DllImport("wireguard.dll", EntryPoint = "WireGuardGetConfiguration", CallingConvention = CallingConvention.Cdecl, SetLastError = true)]
+ private static extern bool getConfiguration(IntPtr adapter, byte[] iface, ref UInt32 bytes);
+
+ private const string defaultPool = "WireGuard";
+
+ public class Adapter
+ {
+ private IntPtr _handle;
+ private UInt32 _lastGetGuess;
+ public Adapter(string name)
+ {
+ _lastGetGuess = 1024;
+ _handle = openAdapter(defaultPool, name);
+ if (_handle == IntPtr.Zero)
+ throw new Win32Exception();
+ }
+ ~Adapter()
+ {
+ freeAdapter(_handle);
+ }
+ public unsafe Interface GetConfiguration()
+ {
+ var iface = new Interface();
+ byte[] bytes;
+ for (; ; )
+ {
+ bytes = new byte[_lastGetGuess];
+ if (getConfiguration(_handle, bytes, ref _lastGetGuess))
+ break;
+ if (Marshal.GetLastWin32Error() != 234 /* ERROR_MORE_DATA */)
+ throw new Win32Exception();
+ }
+ fixed (void* start = bytes)
+ {
+ var ioctlIface = (IoctlInterface*)start;
+ if ((ioctlIface->Flags & IoctlInterfaceFlags.HasPublicKey) != 0)
+ iface.PublicKey = new Key(ioctlIface->PublicKey);
+ if ((ioctlIface->Flags & IoctlInterfaceFlags.HasPrivateKey) != 0)
+ iface.PrivateKey = new Key(ioctlIface->PrivateKey);
+ if ((ioctlIface->Flags & IoctlInterfaceFlags.HasListenPort) != 0)
+ iface.ListenPort = ioctlIface->ListenPort;
+ var peers = new Peer[ioctlIface->PeersCount];
+ var ioctlPeer = (IoctlPeer*)((byte*)ioctlIface + sizeof(IoctlInterface));
+ for (UInt32 i = 0; i < peers.Length; ++i)
+ {
+ var peer = new Peer();
+ if ((ioctlPeer->Flags & IoctlPeerFlags.HasPublicKey) != 0)
+ peer.PublicKey = new Key(ioctlPeer->PublicKey);
+ if ((ioctlPeer->Flags & IoctlPeerFlags.HasPresharedKey) != 0)
+ peer.PresharedKey = new Key(ioctlPeer->PresharedKey);
+ if ((ioctlPeer->Flags & IoctlPeerFlags.HasPersistentKeepalive) != 0)
+ peer.PersistentKeepalive = ioctlPeer->PersistentKeepalive;
+ if ((ioctlPeer->Flags & IoctlPeerFlags.HasEndpoint) != 0)
+ {
+ if (ioctlPeer->Endpoint.si_family == Win32.ADDRESS_FAMILY.AF_INET)
+ {
+ var ip = new byte[4];
+ Marshal.Copy((IntPtr)ioctlPeer->Endpoint.Ipv4.sin_addr.bytes, ip, 0, 4);
+ peer.Endpoint = new IPEndPoint(new IPAddress(ip), IPAddress.NetworkToHostOrder(ioctlPeer->Endpoint.Ipv4.sin_port));
+ }
+ else if (ioctlPeer->Endpoint.si_family == Win32.ADDRESS_FAMILY.AF_INET6)
+ {
+ var ip = new byte[16];
+ Marshal.Copy((IntPtr)ioctlPeer->Endpoint.Ipv6.sin6_addr.bytes, ip, 0, 16);
+ peer.Endpoint = new IPEndPoint(new IPAddress(ip), IPAddress.NetworkToHostOrder(ioctlPeer->Endpoint.Ipv6.sin6_port));
+ }
+ }
+ peer.TxBytes = ioctlPeer->TxBytes;
+ peer.RxBytes = ioctlPeer->RxBytes;
+ if (ioctlPeer->LastHandshake != 0)
+ peer.LastHandshake = DateTime.FromFileTimeUtc((long)ioctlPeer->LastHandshake);
+ var allowedIPs = new AllowedIP[ioctlPeer->AllowedIPsCount];
+ var ioctlAllowedIP = (IoctlAllowedIP*)((byte*)ioctlPeer + sizeof(IoctlPeer));
+ for (UInt32 j = 0; j < allowedIPs.Length; ++j)
+ {
+ var allowedIP = new AllowedIP();
+ if (ioctlAllowedIP->AddressFamily == Win32.ADDRESS_FAMILY.AF_INET)
+ {
+ var ip = new byte[4];
+ Marshal.Copy((IntPtr)ioctlAllowedIP->V4.bytes, ip, 0, 4);
+ allowedIP.Address = new IPAddress(ip);
+ }
+ else if (ioctlAllowedIP->AddressFamily == Win32.ADDRESS_FAMILY.AF_INET6)
+ {
+ var ip = new byte[16];
+ Marshal.Copy((IntPtr)ioctlAllowedIP->V6.bytes, ip, 0, 16);
+ allowedIP.Address = new IPAddress(ip);
+ }
+ allowedIP.Cidr = ioctlAllowedIP->Cidr;
+ allowedIPs[j] = allowedIP;
+ ioctlAllowedIP = (IoctlAllowedIP*)((byte*)ioctlAllowedIP + sizeof(IoctlAllowedIP));
+ }
+ peer.AllowedIPs = allowedIPs;
+ peers[i] = peer;
+ ioctlPeer = (IoctlPeer*)ioctlAllowedIP;
+ }
+ iface.Peers = peers;
+ }
+ return iface;
+ }
+
+ public class Key
+ {
+ private byte[] _bytes;
+ public byte[] Bytes
+ {
+ get
+ {
+ return _bytes;
+ }
+ set
+ {
+ if (value == null || value.Length != 32)
+ throw new ArgumentException("Keys must be 32 bytes");
+ _bytes = value;
+ }
+ }
+ public Key(byte[] bytes)
+ {
+ Bytes = bytes;
+ }
+ public unsafe Key(byte* bytes)
+ {
+ _bytes = new byte[32];
+ Marshal.Copy((IntPtr)bytes, _bytes, 0, 32);
+ }
+ public override String ToString()
+ {
+ return Convert.ToBase64String(_bytes);
+ }
+ }
+
+ public class Interface
+ {
+ public UInt16 ListenPort { get; set; }
+ public Key PrivateKey { get; set; }
+ public Key PublicKey { get; set; }
+ public Peer[] Peers { get; set; }
+ }
+
+ public class Peer
+ {
+ public Key PublicKey { get; set; }
+ public Key PresharedKey { get; set; }
+ public UInt16 PersistentKeepalive { get; set; }
+ public IPEndPoint Endpoint { get; set; }
+ public UInt64 TxBytes { get; set; }
+ public UInt64 RxBytes { get; set; }
+ public DateTime LastHandshake { get; set; }
+ public AllowedIP[] AllowedIPs { get; set; }
+ }
+
+ public class AllowedIP
+ {
+ public IPAddress Address { get; set; }
+ public byte Cidr { get; set; }
+ }
+
+ private enum IoctlInterfaceFlags : UInt32
+ {
+ HasPublicKey = 1 << 0,
+ HasPrivateKey = 1 << 1,
+ HasListenPort = 1 << 2,
+ ReplacePeers = 1 << 3
+ };
+
+ [StructLayout(LayoutKind.Sequential, Pack = 8, Size = 80)]
+ private unsafe struct IoctlInterface
+ {
+ public IoctlInterfaceFlags Flags;
+ public UInt16 ListenPort;
+ public fixed byte PrivateKey[32];
+ public fixed byte PublicKey[32];
+ public UInt32 PeersCount;
+ };
+
+ private enum IoctlPeerFlags : UInt32
+ {
+ HasPublicKey = 1 << 0,
+ HasPresharedKey = 1 << 1,
+ HasPersistentKeepalive = 1 << 2,
+ HasEndpoint = 1 << 3,
+ ReplaceAllowedIPs = 1 << 5,
+ Remove = 1 << 6,
+ Update = 1 << 7
+ };
+
+ [StructLayout(LayoutKind.Sequential, Pack = 8, Size = 136)]
+ private unsafe struct IoctlPeer
+ {
+ public IoctlPeerFlags Flags;
+ public UInt32 Reserved;
+ public fixed byte PublicKey[32];
+ public fixed byte PresharedKey[32];
+ public UInt16 PersistentKeepalive;
+ public Win32.SOCKADDR_INET Endpoint;
+ public UInt64 TxBytes, RxBytes;
+ public UInt64 LastHandshake;
+ public UInt32 AllowedIPsCount;
+ };
+
+ [StructLayout(LayoutKind.Explicit, Pack = 8, Size = 24)]
+ private unsafe struct IoctlAllowedIP
+ {
+ [FieldOffset(0)]
+ [MarshalAs(UnmanagedType.Struct)]
+ public Win32.IN_ADDR V4;
+ [FieldOffset(0)]
+ [MarshalAs(UnmanagedType.Struct)]
+ public Win32.IN6_ADDR V6;
+ [FieldOffset(16)]
+ public Win32.ADDRESS_FAMILY AddressFamily;
+ [FieldOffset(20)]
+ public byte Cidr;
+ }
+ }
+ }
+}
diff --git a/embeddable-dll-service/csharp/TunnelDll/Service.cs b/embeddable-dll-service/csharp/TunnelDll/Service.cs
index 7f2c622e..8e25b6c4 100644
--- a/embeddable-dll-service/csharp/TunnelDll/Service.cs
+++ b/embeddable-dll-service/csharp/TunnelDll/Service.cs
@@ -21,10 +21,9 @@ namespace Tunnel
[DllImport("tunnel.dll", EntryPoint = "WireGuardTunnelService", CallingConvention = CallingConvention.Cdecl)]
public static extern bool Run([MarshalAs(UnmanagedType.LPWStr)] string configFile);
- public static NamedPipeClientStream GetPipe(string configFile)
+ public static Driver.Adapter GetAdapter(string configFile)
{
- var pipepath = "ProtectedPrefix\\Administrators\\WireGuard\\" + Path.GetFileNameWithoutExtension(configFile);
- return new NamedPipeClientStream(pipepath);
+ return new Driver.Adapter(Path.GetFileNameWithoutExtension(configFile));
}
public static void Add(string configFile, bool ephemeral)
diff --git a/embeddable-dll-service/csharp/TunnelDll/Win32.cs b/embeddable-dll-service/csharp/TunnelDll/Win32.cs
index d8447f7f..4987fe8f 100644
--- a/embeddable-dll-service/csharp/TunnelDll/Win32.cs
+++ b/embeddable-dll-service/csharp/TunnelDll/Win32.cs
@@ -135,6 +135,58 @@ namespace Tunnel
SidInfo = 5
}
+ [StructLayout(LayoutKind.Sequential)]
+ public unsafe struct IN_ADDR
+ {
+ public fixed byte bytes[4];
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ public unsafe struct IN6_ADDR
+ {
+ public fixed byte bytes[16];
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ public struct SOCKADDR_IN
+ {
+ public ushort sin_family;
+ public ushort sin_port;
+ public IN_ADDR sin_addr;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ public struct SOCKADDR_IN6
+ {
+ public ushort sin6_family;
+ public ushort sin6_port;
+ public uint sin6_flowinfo;
+ public IN6_ADDR sin6_addr;
+ public uint sin6_scope_id;
+ }
+
+ [StructLayout(LayoutKind.Explicit)]
+ public struct SOCKADDR_INET
+ {
+ [FieldOffset(0)]
+ [MarshalAs(UnmanagedType.Struct)]
+ public SOCKADDR_IN Ipv4;
+
+ [FieldOffset(0)]
+ [MarshalAs(UnmanagedType.Struct)]
+ public SOCKADDR_IN6 Ipv6;
+
+ [FieldOffset(0)]
+ public ADDRESS_FAMILY si_family;
+ }
+
+ public enum ADDRESS_FAMILY : UInt32
+ {
+ AF_UNSPEC = 0,
+ AF_INET = 2,
+ AF_INET6 = 23
+ }
+
[DllImport("advapi32.dll", EntryPoint = "OpenSCManagerW", ExactSpelling = true, CharSet = CharSet.Unicode, SetLastError = true)]
public static extern IntPtr OpenSCManager(string machineName, string databaseName, ScmAccessRights dwDesiredAccess);