golang.zx2c4.com/wireguard/windows@v0.5.4-0.20230123132234-dcc0eb72a04b/embeddable-dll-service/csharp/TunnelDll/Driver.cs (about) 1 /* SPDX-License-Identifier: MIT 2 * 3 * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved. 4 */ 5 6 using System; 7 using System.ComponentModel; 8 using System.Net; 9 using System.Runtime.InteropServices; 10 11 namespace Tunnel 12 { 13 public class Driver 14 { 15 [DllImport("wireguard.dll", EntryPoint = "WireGuardOpenAdapter", CallingConvention = CallingConvention.StdCall, SetLastError = true)] 16 private static extern IntPtr openAdapter([MarshalAs(UnmanagedType.LPWStr)] string name); 17 [DllImport("wireguard.dll", EntryPoint = "WireGuardCloseAdapter", CallingConvention = CallingConvention.StdCall)] 18 private static extern void freeAdapter(IntPtr adapter); 19 [DllImport("wireguard.dll", EntryPoint = "WireGuardGetConfiguration", CallingConvention = CallingConvention.StdCall, SetLastError = true)] 20 private static extern bool getConfiguration(IntPtr adapter, byte[] iface, ref UInt32 bytes); 21 22 public class Adapter 23 { 24 private IntPtr _handle; 25 private UInt32 _lastGetGuess; 26 public Adapter(string name) 27 { 28 _lastGetGuess = 1024; 29 _handle = openAdapter(name); 30 if (_handle == IntPtr.Zero) 31 throw new Win32Exception(); 32 } 33 ~Adapter() 34 { 35 freeAdapter(_handle); 36 } 37 public unsafe Interface GetConfiguration() 38 { 39 var iface = new Interface(); 40 byte[] bytes; 41 for (; ; ) 42 { 43 bytes = new byte[_lastGetGuess]; 44 if (getConfiguration(_handle, bytes, ref _lastGetGuess)) 45 break; 46 if (Marshal.GetLastWin32Error() != 234 /* ERROR_MORE_DATA */) 47 throw new Win32Exception(); 48 } 49 fixed (void* start = bytes) 50 { 51 var ioctlIface = (IoctlInterface*)start; 52 if ((ioctlIface->Flags & IoctlInterfaceFlags.HasPublicKey) != 0) 53 iface.PublicKey = new Key(ioctlIface->PublicKey); 54 if ((ioctlIface->Flags & IoctlInterfaceFlags.HasPrivateKey) != 0) 55 iface.PrivateKey = new Key(ioctlIface->PrivateKey); 56 if ((ioctlIface->Flags & IoctlInterfaceFlags.HasListenPort) != 0) 57 iface.ListenPort = ioctlIface->ListenPort; 58 var peers = new Peer[ioctlIface->PeersCount]; 59 var ioctlPeer = (IoctlPeer*)((byte*)ioctlIface + sizeof(IoctlInterface)); 60 for (UInt32 i = 0; i < peers.Length; ++i) 61 { 62 var peer = new Peer(); 63 if ((ioctlPeer->Flags & IoctlPeerFlags.HasPublicKey) != 0) 64 peer.PublicKey = new Key(ioctlPeer->PublicKey); 65 if ((ioctlPeer->Flags & IoctlPeerFlags.HasPresharedKey) != 0) 66 peer.PresharedKey = new Key(ioctlPeer->PresharedKey); 67 if ((ioctlPeer->Flags & IoctlPeerFlags.HasPersistentKeepalive) != 0) 68 peer.PersistentKeepalive = ioctlPeer->PersistentKeepalive; 69 if ((ioctlPeer->Flags & IoctlPeerFlags.HasEndpoint) != 0) 70 { 71 if (ioctlPeer->Endpoint.si_family == Win32.ADDRESS_FAMILY.AF_INET) 72 { 73 var ip = new byte[4]; 74 Marshal.Copy((IntPtr)ioctlPeer->Endpoint.Ipv4.sin_addr.bytes, ip, 0, 4); 75 peer.Endpoint = new IPEndPoint(new IPAddress(ip), (ushort)IPAddress.NetworkToHostOrder((short)ioctlPeer->Endpoint.Ipv4.sin_port)); 76 } 77 else if (ioctlPeer->Endpoint.si_family == Win32.ADDRESS_FAMILY.AF_INET6) 78 { 79 var ip = new byte[16]; 80 Marshal.Copy((IntPtr)ioctlPeer->Endpoint.Ipv6.sin6_addr.bytes, ip, 0, 16); 81 peer.Endpoint = new IPEndPoint(new IPAddress(ip), (ushort)IPAddress.NetworkToHostOrder((short)ioctlPeer->Endpoint.Ipv6.sin6_port)); 82 } 83 } 84 peer.TxBytes = ioctlPeer->TxBytes; 85 peer.RxBytes = ioctlPeer->RxBytes; 86 if (ioctlPeer->LastHandshake != 0) 87 peer.LastHandshake = DateTime.FromFileTimeUtc((long)ioctlPeer->LastHandshake); 88 var allowedIPs = new AllowedIP[ioctlPeer->AllowedIPsCount]; 89 var ioctlAllowedIP = (IoctlAllowedIP*)((byte*)ioctlPeer + sizeof(IoctlPeer)); 90 for (UInt32 j = 0; j < allowedIPs.Length; ++j) 91 { 92 var allowedIP = new AllowedIP(); 93 if (ioctlAllowedIP->AddressFamily == Win32.ADDRESS_FAMILY.AF_INET) 94 { 95 var ip = new byte[4]; 96 Marshal.Copy((IntPtr)ioctlAllowedIP->V4.bytes, ip, 0, 4); 97 allowedIP.Address = new IPAddress(ip); 98 } 99 else if (ioctlAllowedIP->AddressFamily == Win32.ADDRESS_FAMILY.AF_INET6) 100 { 101 var ip = new byte[16]; 102 Marshal.Copy((IntPtr)ioctlAllowedIP->V6.bytes, ip, 0, 16); 103 allowedIP.Address = new IPAddress(ip); 104 } 105 allowedIP.Cidr = ioctlAllowedIP->Cidr; 106 allowedIPs[j] = allowedIP; 107 ioctlAllowedIP = (IoctlAllowedIP*)((byte*)ioctlAllowedIP + sizeof(IoctlAllowedIP)); 108 } 109 peer.AllowedIPs = allowedIPs; 110 peers[i] = peer; 111 ioctlPeer = (IoctlPeer*)ioctlAllowedIP; 112 } 113 iface.Peers = peers; 114 } 115 return iface; 116 } 117 118 public class Key 119 { 120 private byte[] _bytes; 121 public byte[] Bytes 122 { 123 get 124 { 125 return _bytes; 126 } 127 set 128 { 129 if (value == null || value.Length != 32) 130 throw new ArgumentException("Keys must be 32 bytes"); 131 _bytes = value; 132 } 133 } 134 public Key(byte[] bytes) 135 { 136 Bytes = bytes; 137 } 138 public unsafe Key(byte* bytes) 139 { 140 _bytes = new byte[32]; 141 Marshal.Copy((IntPtr)bytes, _bytes, 0, 32); 142 } 143 public override String ToString() 144 { 145 return Convert.ToBase64String(_bytes); 146 } 147 } 148 149 public class Interface 150 { 151 public UInt16 ListenPort { get; set; } 152 public Key PrivateKey { get; set; } 153 public Key PublicKey { get; set; } 154 public Peer[] Peers { get; set; } 155 } 156 157 public class Peer 158 { 159 public Key PublicKey { get; set; } 160 public Key PresharedKey { get; set; } 161 public UInt16 PersistentKeepalive { get; set; } 162 public IPEndPoint Endpoint { get; set; } 163 public UInt64 TxBytes { get; set; } 164 public UInt64 RxBytes { get; set; } 165 public DateTime LastHandshake { get; set; } 166 public AllowedIP[] AllowedIPs { get; set; } 167 } 168 169 public class AllowedIP 170 { 171 public IPAddress Address { get; set; } 172 public byte Cidr { get; set; } 173 } 174 175 private enum IoctlInterfaceFlags : UInt32 176 { 177 HasPublicKey = 1 << 0, 178 HasPrivateKey = 1 << 1, 179 HasListenPort = 1 << 2, 180 ReplacePeers = 1 << 3 181 }; 182 183 [StructLayout(LayoutKind.Sequential, Pack = 8, Size = 80)] 184 private unsafe struct IoctlInterface 185 { 186 public IoctlInterfaceFlags Flags; 187 public UInt16 ListenPort; 188 public fixed byte PrivateKey[32]; 189 public fixed byte PublicKey[32]; 190 public UInt32 PeersCount; 191 }; 192 193 private enum IoctlPeerFlags : UInt32 194 { 195 HasPublicKey = 1 << 0, 196 HasPresharedKey = 1 << 1, 197 HasPersistentKeepalive = 1 << 2, 198 HasEndpoint = 1 << 3, 199 ReplaceAllowedIPs = 1 << 5, 200 Remove = 1 << 6, 201 UpdateOnly = 1 << 7 202 }; 203 204 [StructLayout(LayoutKind.Sequential, Pack = 8, Size = 136)] 205 private unsafe struct IoctlPeer 206 { 207 public IoctlPeerFlags Flags; 208 public UInt32 Reserved; 209 public fixed byte PublicKey[32]; 210 public fixed byte PresharedKey[32]; 211 public UInt16 PersistentKeepalive; 212 public Win32.SOCKADDR_INET Endpoint; 213 public UInt64 TxBytes, RxBytes; 214 public UInt64 LastHandshake; 215 public UInt32 AllowedIPsCount; 216 }; 217 218 [StructLayout(LayoutKind.Explicit, Pack = 8, Size = 24)] 219 private unsafe struct IoctlAllowedIP 220 { 221 [FieldOffset(0)] 222 [MarshalAs(UnmanagedType.Struct)] 223 public Win32.IN_ADDR V4; 224 [FieldOffset(0)] 225 [MarshalAs(UnmanagedType.Struct)] 226 public Win32.IN6_ADDR V6; 227 [FieldOffset(16)] 228 public Win32.ADDRESS_FAMILY AddressFamily; 229 [FieldOffset(20)] 230 public byte Cidr; 231 } 232 } 233 } 234 }