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  }