mirror of
https://github.com/Maassoft/ColorControl.git
synced 2026-10-22 08:32:18 -05:00
add better logging of network devices when sending WOL
This commit is contained in:
1 parent
91fd44d698
commit
5268e6679e
25 files changed
+1915
-8
No files matched your search
@@ -27,7 +27,7 @@
|
||||
<ProductName>ColorControl</ProductName>
|
||||
<PublisherName>Maassoft</PublisherName>
|
||||
<ApplicationRevision>0</ApplicationRevision>
|
||||
<ApplicationVersion>1.5.3.0</ApplicationVersion>
|
||||
<ApplicationVersion>1.5.4.0</ApplicationVersion>
|
||||
<UseApplicationTrust>false</UseApplicationTrust>
|
||||
<PublishWizardCompleted>true</PublishWizardCompleted>
|
||||
<BootstrapperEnabled>true</BootstrapperEnabled>
|
||||
|
||||
@@ -32,5 +32,5 @@ using System.Runtime.InteropServices;
|
||||
// You can specify all the values or you can default the Build and Revision Numbers
|
||||
// by using the '*' as shown below:
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion("1.5.3.0")]
|
||||
[assembly: AssemblyFileVersion("1.5.3.0")]
|
||||
[assembly: AssemblyVersion("1.5.4.0")]
|
||||
[assembly: AssemblyFileVersion("1.5.4.0")]
|
||||
+14
-5
@@ -1,12 +1,10 @@
|
||||
using NLog;
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using PacketDotNet;
|
||||
using System.Net.NetworkInformation;
|
||||
using SharpPcap;
|
||||
using System.Diagnostics;
|
||||
using SharpPcap.Npcap;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
|
||||
namespace ColorControl
|
||||
{
|
||||
@@ -14,8 +12,12 @@ namespace ColorControl
|
||||
{
|
||||
private static readonly Logger Logger = LogManager.GetCurrentClassLogger();
|
||||
|
||||
//You need SharpPcap for this to work
|
||||
public static void WakeFunction2(string macAddress)
|
||||
{
|
||||
//PhysicalAddress.Parse(macAddress).SendWol();
|
||||
}
|
||||
|
||||
//You need SharpPcap for this to work
|
||||
public static void WakeFunction(string macAddress)
|
||||
{
|
||||
/* Retrieve the device list */
|
||||
@@ -40,7 +42,14 @@ namespace ColorControl
|
||||
// }
|
||||
//}
|
||||
|
||||
Logger.Debug("Opening network device: " + device.Name);
|
||||
if (device is NpcapDevice npcapDevice)
|
||||
{
|
||||
Logger.Debug($"Opening network device (NpcapDevice): FriendlyName: {npcapDevice.Interface.FriendlyName}, Description: {npcapDevice.Interface.Description}");
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger.Debug($"Opening network device (NOT A NpcapDevice!): {device.Name}, Description: {device.Description}");
|
||||
}
|
||||
|
||||
//Open the device
|
||||
device.Open();
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
using System.ComponentModel;
|
||||
using System.Net.NetworkInformation;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace System.Net
|
||||
{
|
||||
/// <summary>Stellt Methoden für das Senden von Anfragen über das ARP-Protokoll bereit.</summary>
|
||||
public static class ArpRequest
|
||||
{
|
||||
/// <summary>
|
||||
/// Sendet eine Anfrage über das ARP-Protokoll, um eine IP-Adresse in die Physikalische Adresse aufzulösen. Falls sich die physikalische Adresse bereits im Cache des Hosts befindet, wird diese zurückgegeben.
|
||||
/// </summary>
|
||||
/// <param name="destination">Destination <see cref="IPAddress"/>.</param>
|
||||
/// <returns>Eine <see cref="T:System.Net.ArpRequestResult">ArpRequestResult</see>-Instanz, welche die Ergebnisse der Anfrage enthält.</returns>
|
||||
public static ArpRequestResult Send(IPAddress destination)
|
||||
{
|
||||
if (destination == null)
|
||||
throw new ArgumentNullException(nameof(destination));
|
||||
|
||||
int destIp = BitConverter.ToInt32(destination.GetAddressBytes(), 0);
|
||||
|
||||
var addr = new byte[6];
|
||||
var len = addr.Length;
|
||||
|
||||
var res = NativeMethods.SendARP(destIp, 0, addr, ref len);
|
||||
|
||||
if (res == 0)
|
||||
return new ArpRequestResult(new PhysicalAddress(addr));
|
||||
return new ArpRequestResult(new Win32Exception(res));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sendet eine Anfrage über das ARP-Protokoll, um eine IP-Adresse in die Physikalische Adresse aufzulösen. Falls sich die physikalische Adresse bereits im Cache des Hosts befindet, wird diese zurückgegeben.
|
||||
/// </summary>
|
||||
/// <param name="destination">Destination <see cref="IPAddress"/>.</param>
|
||||
/// <returns>Ein asynchroner Task, welcher einen ARP-Request sendet.</returns>
|
||||
public static Task<ArpRequestResult> SendAsync(IPAddress destination) => Task.Run(() => Send(destination));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
using System.Net.NetworkInformation;
|
||||
using System.Text;
|
||||
|
||||
namespace System.Net
|
||||
{
|
||||
// TODO: rethink the whole exception thing
|
||||
|
||||
/// <summary>
|
||||
/// Enthält die Rückgabewerte der ArpRequest.Send-Funktion.
|
||||
/// </summary>
|
||||
public class ArpRequestResult
|
||||
{
|
||||
/// <summary>Falls Fehler bei der Protokollanfrage auftreten, werden diese in dieser Eigenschaft abgelegt. Andernfalls null.</summary>
|
||||
public Exception Exception { get; }
|
||||
|
||||
/// <summary>Die aufgelöste physikalische Adresse.</summary>
|
||||
public PhysicalAddress Address { get; }
|
||||
|
||||
/// <summary>Erstellt eine neue ArpRequestResult-Instanz</summary>
|
||||
/// <param name="address">Die physikalische Adresse</param>
|
||||
public ArpRequestResult(PhysicalAddress address)
|
||||
{
|
||||
this.Exception = null;
|
||||
Address = address;
|
||||
}
|
||||
|
||||
/// <summary>Erstellt eine neue ArpRequestResult-Instanz</summary>
|
||||
/// <param name="exception">Der aufgetretene Fehler</param>
|
||||
public ArpRequestResult(Exception exception)
|
||||
{
|
||||
this.Exception = exception;
|
||||
Address = null;
|
||||
}
|
||||
|
||||
/// <summary>Konvertiert ARP-Rückgabewerte in eine Zeichenfolge.</summary>
|
||||
public override string ToString()
|
||||
{
|
||||
var sb = new StringBuilder();
|
||||
if (Address == null)
|
||||
sb.Append("no address");
|
||||
else
|
||||
{
|
||||
sb.Append("address: ");
|
||||
sb.Append(Address);
|
||||
}
|
||||
sb.Append(", ");
|
||||
if (Exception == null)
|
||||
sb.Append("no exception");
|
||||
else
|
||||
{
|
||||
sb.Append("exception: ");
|
||||
sb.Append(Exception.Message);
|
||||
}
|
||||
return sb.ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
// This file is used by Code Analysis to maintain SuppressMessage
|
||||
// attributes that are applied to this project.
|
||||
// Project-level suppressions either have no target or are given
|
||||
// a specific target and scoped to a namespace, type, member, etc.
|
||||
//
|
||||
// To add a suppression to this file, right-click the message in the
|
||||
// Code Analysis results, point to "Suppress Message", and click
|
||||
// "In Suppression File".
|
||||
// You do not need to add suppressions to this file manually.
|
||||
|
||||
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Wol", Scope = "member", Target = "System.Net.IPAddressExtensions.#SendWol(System.Net.IPAddress,System.Byte,System.Byte,System.Byte,System.Byte,System.Byte,System.Byte,System.Int32)")]
|
||||
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Wol", Scope = "member", Target = "System.Net.IPAddressExtensions.#SendWol(System.Net.IPAddress,System.Byte,System.Byte,System.Byte,System.Byte,System.Byte,System.Byte)")]
|
||||
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Wol", Scope = "member", Target = "System.Net.IPAddressExtensions.#SendWol(System.Net.IPAddress,System.Byte[],System.Int32)")]
|
||||
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Wol", Scope = "member", Target = "System.Net.IPAddressExtensions.#SendWol(System.Net.IPAddress,System.Byte[],System.Int32,System.Net.SecureOnPassword)")]
|
||||
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Wol", Scope = "member", Target = "System.Net.IPAddressExtensions.#SendWol(System.Net.IPAddress,System.Byte[])")]
|
||||
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Wol", Scope = "member", Target = "System.Net.IPAddressExtensions.#SendWol(System.Net.IPAddress,System.Byte[],System.Net.SecureOnPassword)")]
|
||||
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Wol", Scope = "member", Target = "System.Net.IPAddressExtensions.#SendWol(System.Net.IPAddress,System.Net.NetworkInformation.PhysicalAddress)")]
|
||||
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Wol", Scope = "member", Target = "System.Net.IPAddressExtensions.#SendWol(System.Net.IPAddress,System.Net.NetworkInformation.PhysicalAddress,System.Net.SecureOnPassword)")]
|
||||
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Wol", Scope = "member", Target = "System.Net.IPAddressExtensions.#SendWolAsync(System.Net.IPAddress,System.Byte,System.Byte,System.Byte,System.Byte,System.Byte,System.Byte,System.Int32)")]
|
||||
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Wol", Scope = "member", Target = "System.Net.IPAddressExtensions.#SendWolAsync(System.Net.IPAddress,System.Byte,System.Byte,System.Byte,System.Byte,System.Byte,System.Byte)")]
|
||||
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Wol", Scope = "member", Target = "System.Net.IPAddressExtensions.#SendWolAsync(System.Net.IPAddress,System.Byte[],System.Int32)")]
|
||||
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Wol", Scope = "member", Target = "System.Net.IPAddressExtensions.#SendWolAsync(System.Net.IPAddress,System.Byte[],System.Int32,System.Net.SecureOnPassword)")]
|
||||
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Wol", Scope = "member", Target = "System.Net.IPAddressExtensions.#SendWolAsync(System.Net.IPAddress,System.Byte[])")]
|
||||
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Wol", Scope = "member", Target = "System.Net.IPAddressExtensions.#SendWolAsync(System.Net.IPAddress,System.Byte[],System.Net.SecureOnPassword)")]
|
||||
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Wol", Scope = "member", Target = "System.Net.IPAddressExtensions.#SendWolAsync(System.Net.IPAddress,System.Net.NetworkInformation.PhysicalAddress)")]
|
||||
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Wol", Scope = "member", Target = "System.Net.IPAddressExtensions.#SendWolAsync(System.Net.IPAddress,System.Net.NetworkInformation.PhysicalAddress,System.Net.SecureOnPassword)")]
|
||||
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Wol", Scope = "member", Target = "System.Net.IPEndPointExtensions.#SendWol(System.Net.IPEndPoint,System.Byte,System.Byte,System.Byte,System.Byte,System.Byte,System.Byte)")]
|
||||
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Wol", Scope = "member", Target = "System.Net.IPEndPointExtensions.#SendWol(System.Net.IPEndPoint,System.Byte[])")]
|
||||
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Wol", Scope = "member", Target = "System.Net.IPEndPointExtensions.#SendWol(System.Net.IPEndPoint,System.Net.NetworkInformation.PhysicalAddress)")]
|
||||
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Wol", Scope = "member", Target = "System.Net.IPEndPointExtensions.#SendWol(System.Net.IPEndPoint,System.Byte[],System.Net.SecureOnPassword)")]
|
||||
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Wol", Scope = "member", Target = "System.Net.IPEndPointExtensions.#SendWol(System.Net.IPEndPoint,System.Net.NetworkInformation.PhysicalAddress,System.Net.SecureOnPassword)")]
|
||||
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Wol", Scope = "member", Target = "System.Net.IPEndPointExtensions.#SendWolAsync(System.Net.IPEndPoint,System.Byte,System.Byte,System.Byte,System.Byte,System.Byte,System.Byte)")]
|
||||
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Wol", Scope = "member", Target = "System.Net.IPEndPointExtensions.#SendWolAsync(System.Net.IPEndPoint,System.Byte[])")]
|
||||
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Wol", Scope = "member", Target = "System.Net.IPEndPointExtensions.#SendWolAsync(System.Net.IPEndPoint,System.Net.NetworkInformation.PhysicalAddress)")]
|
||||
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Wol", Scope = "member", Target = "System.Net.IPEndPointExtensions.#SendWolAsync(System.Net.IPEndPoint,System.Byte[],System.Net.SecureOnPassword)")]
|
||||
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Wol", Scope = "member", Target = "System.Net.IPEndPointExtensions.#SendWolAsync(System.Net.IPEndPoint,System.Net.NetworkInformation.PhysicalAddress,System.Net.SecureOnPassword)")]
|
||||
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Lan")]
|
||||
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1024:UsePropertiesWhereAppropriate", Scope = "member", Target = "System.Net.Topology.INetMask.#GetMaskBytes()")]
|
||||
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "n", Scope = "member", Target = "System.Net.Topology.NetMask.#op_Equality(System.Net.Topology.NetMask,System.Net.Topology.NetMask)")]
|
||||
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "n", Scope = "member", Target = "System.Net.Topology.NetMask.#op_Inequality(System.Net.Topology.NetMask,System.Net.Topology.NetMask)")]
|
||||
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "n", Scope = "member", Target = "System.Net.Topology.NetMask.#op_BitwiseAnd(System.Net.Topology.NetMask,System.Net.Topology.NetMask)")]
|
||||
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1008:EnumsShouldHaveZeroValue", Scope = "type", Target = "System.Net.Topology.SiblingOptions")]
|
||||
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Wol", Scope = "type", Target = "System.Net.SendWol")]
|
||||
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Wol", Scope = "member", Target = "System.Net.PhysicalAddressExtensions.#SendWolAsync(System.Net.NetworkInformation.PhysicalAddress,System.Net.IPEndPoint)")]
|
||||
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Wol", Scope = "member", Target = "System.Net.PhysicalAddressExtensions.#SendWolAsync(System.Net.NetworkInformation.PhysicalAddress,System.Net.SecureOnPassword)")]
|
||||
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Wol", Scope = "member", Target = "System.Net.PhysicalAddressExtensions.#SendWolAsync(System.Net.NetworkInformation.PhysicalAddress)")]
|
||||
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Wol", Scope = "member", Target = "System.Net.PhysicalAddressExtensions.#SendWol(System.Net.NetworkInformation.PhysicalAddress,System.Net.IPEndPoint,System.Net.SecureOnPassword)")]
|
||||
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Wol", Scope = "member", Target = "System.Net.PhysicalAddressExtensions.#SendWol(System.Net.NetworkInformation.PhysicalAddress,System.Net.IPEndPoint)")]
|
||||
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Wol", Scope = "member", Target = "System.Net.PhysicalAddressExtensions.#SendWol(System.Net.NetworkInformation.PhysicalAddress,System.Net.IPAddress,System.Net.SecureOnPassword)")]
|
||||
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Wol", Scope = "member", Target = "System.Net.PhysicalAddressExtensions.#SendWol(System.Net.NetworkInformation.PhysicalAddress,System.Net.IPAddress)")]
|
||||
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Wol", Scope = "member", Target = "System.Net.PhysicalAddressExtensions.#SendWol(System.Net.NetworkInformation.PhysicalAddress,System.Net.SecureOnPassword)")]
|
||||
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Wol", Scope = "member", Target = "System.Net.PhysicalAddressExtensions.#SendWol(System.Net.NetworkInformation.PhysicalAddress)")]
|
||||
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "n", Scope = "member", Target = "System.Net.Topology.NetMask.#op_BitwiseOr(System.Net.Topology.NetMask,System.Net.Topology.NetMask)")]
|
||||
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "n", Scope = "member", Target = "System.Net.Topology.NetMask.#BitwiseOr(System.Net.Topology.NetMask,System.Net.Topology.NetMask)")]
|
||||
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Wol", Scope = "member", Target = "System.Net.PhysicalAddressExtensions.#SendWolAsync(System.Net.NetworkInformation.PhysicalAddress,System.Net.IPAddress)")]
|
||||
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Wol", Scope = "member", Target = "System.Net.PhysicalAddressExtensions.#SendWolAsync(System.Net.NetworkInformation.PhysicalAddress,System.Net.IPAddress,System.Net.SecureOnPassword)")]
|
||||
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Wol", Scope = "member", Target = "System.Net.PhysicalAddressExtensions.#SendWolAsync(System.Net.NetworkInformation.PhysicalAddress,System.Net.IPEndPoint,System.Net.SecureOnPassword)")]
|
||||
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Cidr", Scope = "member", Target = "System.Net.Topology.INetMask.#Cidr")]
|
||||
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "m", Scope = "member", Target = "System.Net.Topology.NetMask.#.ctor(System.Byte,System.Byte,System.Byte,System.Byte)")]
|
||||
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "n", Scope = "member", Target = "System.Net.Topology.NetMask.#BitwiseAnd(System.Net.Topology.NetMask,System.Net.Topology.NetMask)")]
|
||||
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "cidr", Scope = "member", Target = "System.Net.Topology.NetMask.#.ctor(System.Int32)")]
|
||||
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "cidr", Scope = "member", Target = "System.Net.Topology.NetMask.#.ctor(System.Byte)")]
|
||||
@@ -0,0 +1,166 @@
|
||||
using System.Threading.Tasks;
|
||||
using System.Net.NetworkInformation;
|
||||
using System.Net.Sockets;
|
||||
|
||||
namespace System.Net
|
||||
{
|
||||
/// <summary>Provides extension methods for sending Wake On LAN signals (magic packets) to a specific <see cref="IPAddress"/>.</summary>
|
||||
public static class IPAddressExtensions
|
||||
{
|
||||
private const int DefaultWolPort = 7;
|
||||
#region Wol
|
||||
|
||||
/// <summary>Sends a Wake On LAN signal (magic packet) to a client.</summary>
|
||||
/// <param name="target">Destination <see cref="IPAddress"/>.</param>
|
||||
/// <param name="macAddress">The MAC address of the client.</param>
|
||||
/// <param name="port">The port to send the packet to.</param>
|
||||
/// <exception cref="ArgumentException">The length of the <see cref="T:System.Byte" /> array <paramref name="macAddress"/> is not 6.</exception>
|
||||
/// <exception cref="ArgumentNullException"><paramref name="macAddress"/> is null.</exception>
|
||||
/// <exception cref="SocketException">An error occurred when accessing the socket. See Remarks section of <see cref="UdpClient.Send(byte[], int, IPEndPoint)"/> for more information.</exception>
|
||||
public static void SendWol(this IPAddress target, byte[] macAddress, int port) => target.SendWol(macAddress, port, null);
|
||||
|
||||
/// <summary>Sends a Wake On LAN signal (magic packet) to a client.</summary>
|
||||
/// <param name="target">Destination <see cref="IPAddress"/>.</param>
|
||||
/// <param name="macAddress">The MAC address of the client.</param>
|
||||
/// <param name="port">The port to send the packet to.</param>
|
||||
/// <param name="password">The SecureOn password of the client.</param>
|
||||
/// <exception cref="ArgumentException">The length of the <see cref="T:System.Byte" /> array <paramref name="macAddress"/> is not 6.</exception>
|
||||
/// <exception cref="ArgumentNullException"><paramref name="macAddress"/> is null.</exception>
|
||||
/// <exception cref="SocketException">An error occurred when accessing the socket. See Remarks section of <see cref="UdpClient.Send(byte[], int, IPEndPoint)"/> for more information.</exception>
|
||||
public static void SendWol(this IPAddress target, byte[] macAddress, int port, SecureOnPassword password)
|
||||
{
|
||||
Net.MagicPacket.Send(new IPEndPoint(target, port), macAddress, password);
|
||||
}
|
||||
/// <summary>Sends a Wake On LAN signal (magic packet) to a client.</summary>
|
||||
/// <param name="target">Destination <see cref="IPAddress"/>.</param>
|
||||
/// <param name="macAddress">The MAC address of the client.</param>
|
||||
/// <exception cref="ArgumentException">The length of the <see cref="T:System.Byte" /> array <paramref name="macAddress"/> is not 6.</exception>
|
||||
/// <exception cref="ArgumentNullException"><paramref name="macAddress"/> is null.</exception>
|
||||
/// <exception cref="SocketException">An error occurred when accessing the socket. See Remarks section of <see cref="UdpClient.Send(byte[], int, IPEndPoint)"/> for more information.</exception>
|
||||
public static void SendWol(this IPAddress target, byte[] macAddress) => target.SendWol(macAddress, null);
|
||||
|
||||
/// <summary>Sends a Wake On LAN signal (magic packet) to a client.</summary>
|
||||
/// <param name="target">Destination <see cref="IPAddress"/>.</param>
|
||||
/// <param name="macAddress">The MAC address of the client.</param>
|
||||
/// <param name="password">The SecureOn password of the client.</param>
|
||||
/// <exception cref="ArgumentException">The length of the <see cref="T:System.Byte" /> array <paramref name="macAddress"/> is not 6.</exception>
|
||||
/// <exception cref="ArgumentNullException"><paramref name="macAddress"/> is null.</exception>
|
||||
/// <exception cref="SocketException">An error occurred when accessing the socket. See Remarks section of <see cref="UdpClient.Send(byte[], int, IPEndPoint)"/> for more information.</exception>
|
||||
public static void SendWol(this IPAddress target, byte[] macAddress, SecureOnPassword password)
|
||||
{
|
||||
Net.MagicPacket.Send(new IPEndPoint(target, DefaultWolPort), macAddress, password);
|
||||
}
|
||||
|
||||
/// <summary>Sends a Wake On LAN signal (magic packet) to a client.</summary>
|
||||
/// <param name="target">Destination <see cref="IPAddress"/>.</param>
|
||||
/// <param name="macAddress">The MAC address of the client.</param>
|
||||
/// <exception cref="ArgumentException">The length of the <see cref="PhysicalAddress" /> <paramref name="macAddress"/> is not 6.</exception>
|
||||
/// <exception cref="ArgumentNullException"><paramref name="macAddress"/> is null.</exception>
|
||||
/// <exception cref="SocketException">An error occurred when accessing the socket. See Remarks section of <see cref="UdpClient.Send(byte[], int, IPEndPoint)"/> for more information.</exception>
|
||||
public static void SendWol(this IPAddress target, PhysicalAddress macAddress) => target.SendWol(macAddress, null);
|
||||
|
||||
/// <summary>Sends a Wake On LAN signal (magic packet) to a client.</summary>
|
||||
/// <param name="target">Destination <see cref="IPAddress"/>.</param>
|
||||
/// <param name="macAddress">The MAC address of the client.</param>
|
||||
/// <param name="password">The SecureOn password of the client.</param>
|
||||
/// <exception cref="ArgumentException">The length of the <see cref="PhysicalAddress" /> <paramref name="macAddress"/> is not 6.</exception>
|
||||
/// <exception cref="ArgumentNullException"><paramref name="macAddress"/> is null.</exception>
|
||||
/// <exception cref="SocketException">An error occurred when accessing the socket. See Remarks section of <see cref="UdpClient.Send(byte[], int, IPEndPoint)"/> for more information.</exception>
|
||||
public static void SendWol(this IPAddress target, PhysicalAddress macAddress, SecureOnPassword password)
|
||||
{
|
||||
Net.MagicPacket.Send(new IPEndPoint(target, DefaultWolPort), macAddress, password);
|
||||
}
|
||||
|
||||
#endregion
|
||||
#region ARP
|
||||
|
||||
/// <summary>
|
||||
/// Sendet eine Anfrage über das ARP-Protokoll, um eine IP-Adresse in die Physikalische Adresse aufzulösen. Falls sich die physikalische Adresse bereits im Cache des Hosts befindet, wird diese zurückgegeben.
|
||||
/// </summary>
|
||||
/// <param name="destination">Destination <see cref="IPAddress"/>.</param>
|
||||
/// <returns>Eine <see cref="T:System.Net.ArpRequestResult">ArpRequestResult</see>-Instanz, welche die Ergebnisse der Anfrage enthält.</returns>
|
||||
public static ArpRequestResult SendArpRequest(this IPAddress destination) => ArpRequest.Send(destination);
|
||||
|
||||
#endregion
|
||||
#region TAP
|
||||
|
||||
#region Wol
|
||||
|
||||
/// <summary>Sends a Wake On LAN signal (magic packet) to a client.</summary>
|
||||
/// <param name="target">Destination <see cref="IPAddress"/>.</param>
|
||||
/// <param name="macAddress">The MAC address of the client.</param>
|
||||
/// <param name="port">The port to send the packet to.</param>
|
||||
/// <exception cref="ArgumentException">The length of the <see cref="T:System.Byte" /> array <paramref name="macAddress"/> is not 6.</exception>
|
||||
/// <exception cref="ArgumentNullException"><paramref name="macAddress"/> is null.</exception>
|
||||
/// <returns>An asynchronous <see cref="Task"/> which sends a Wake On LAN signal (magic packet) to a client.</returns>
|
||||
public static Task SendWolAsync(this IPAddress target, byte[] macAddress, int port) => target.SendWolAsync(macAddress, port, null);
|
||||
|
||||
/// <summary>Sends a Wake On LAN signal (magic packet) to a client.</summary>
|
||||
/// <param name="target">Destination <see cref="IPAddress"/>.</param>
|
||||
/// <param name="macAddress">The MAC address of the client.</param>
|
||||
/// <param name="port">The port to send the packet to.</param>
|
||||
/// <param name="password">The SecureOn password of the client.</param>
|
||||
/// <exception cref="ArgumentException">The length of the <see cref="T:System.Byte" /> array <paramref name="macAddress"/> is not 6.</exception>
|
||||
/// <exception cref="ArgumentNullException"><paramref name="macAddress"/> is null.</exception>
|
||||
/// <returns>An asynchronous <see cref="Task"/> which sends a Wake On LAN signal (magic packet) to a client.</returns>
|
||||
public static Task SendWolAsync(this IPAddress target, byte[] macAddress, int port, SecureOnPassword password)
|
||||
{
|
||||
return Net.MagicPacket.SendAsync(new IPEndPoint(target, port), macAddress, password);
|
||||
}
|
||||
|
||||
/// <summary>Sends a Wake On LAN signal (magic packet) to a client.</summary>
|
||||
/// <param name="target">Destination <see cref="IPAddress"/>.</param>
|
||||
/// <param name="macAddress">The MAC address of the client.</param>
|
||||
/// <exception cref="ArgumentException">The length of the <see cref="T:System.Byte" /> array <paramref name="macAddress"/> is not 6.</exception>
|
||||
/// <exception cref="ArgumentNullException"><paramref name="macAddress"/> is null.</exception>
|
||||
/// <returns>An asynchronous <see cref="Task"/> which sends a Wake On LAN signal (magic packet) to a client.</returns>
|
||||
public static Task SendWolAsync(this IPAddress target, byte[] macAddress) => target.SendWolAsync(macAddress, null);
|
||||
|
||||
/// <summary>Sends a Wake On LAN signal (magic packet) to a client.</summary>
|
||||
/// <param name="target">Destination <see cref="IPAddress"/>.</param>
|
||||
/// <param name="macAddress">The MAC address of the client.</param>
|
||||
/// <param name="password">The SecureOn password of the client.</param>
|
||||
/// <exception cref="ArgumentException">The length of the <see cref="T:System.Byte" /> array <paramref name="macAddress"/> is not 6.</exception>
|
||||
/// <exception cref="ArgumentNullException"><paramref name="macAddress"/> is null.</exception>
|
||||
/// <exception cref="ArgumentNullException"><paramref name="password"/> is null.</exception>
|
||||
/// <returns>An asynchronous <see cref="Task"/> which sends a Wake On LAN signal (magic packet) to a client.</returns>
|
||||
public static Task SendWolAsync(this IPAddress target, byte[] macAddress, SecureOnPassword password)
|
||||
{
|
||||
return Net.MagicPacket.SendAsync(new IPEndPoint(target, DefaultWolPort), macAddress, password);
|
||||
}
|
||||
|
||||
/// <summary>Sends a Wake On LAN signal (magic packet) to a client.</summary>
|
||||
/// <param name="target">Destination <see cref="IPAddress"/>.</param>
|
||||
/// <param name="macAddress">The MAC address of the client.</param>
|
||||
/// <exception cref="ArgumentException">The length of the <see cref="PhysicalAddress" /> <paramref name="macAddress"/> is not 6.</exception>
|
||||
/// <exception cref="ArgumentNullException"><paramref name="macAddress"/> is null.</exception>
|
||||
/// <returns>An asynchronous <see cref="Task"/> which sends a Wake On LAN signal (magic packet) to a client.</returns>
|
||||
public static Task SendWolAsync(this IPAddress target, PhysicalAddress macAddress) => target.SendWolAsync(macAddress, null);
|
||||
|
||||
/// <summary>Sends a Wake On LAN signal (magic packet) to a client.</summary>
|
||||
/// <param name="target">Destination <see cref="IPAddress"/>.</param>
|
||||
/// <param name="macAddress">The MAC address of the client.</param>
|
||||
/// <param name="password">The SecureOn password of the client.</param>
|
||||
/// <exception cref="ArgumentException">The length of the <see cref="PhysicalAddress" /> <paramref name="macAddress"/> is not 6.</exception>
|
||||
/// <exception cref="ArgumentNullException"><paramref name="macAddress"/> is null.</exception>
|
||||
/// <exception cref="ArgumentNullException"><paramref name="password"/> is null.</exception>
|
||||
/// <returns>An asynchronous <see cref="Task"/> which sends a Wake On LAN signal (magic packet) to a client.</returns>
|
||||
public static Task SendWolAsync(this IPAddress target, PhysicalAddress macAddress, SecureOnPassword password)
|
||||
{
|
||||
return Net.MagicPacket.SendAsync(new IPEndPoint(target, DefaultWolPort), macAddress, password);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region ARP
|
||||
|
||||
/// <summary>Sends a request via ARP to resolve an IP address to aphysical address. If the physical address is already cached, it's cached value is returned.</summary>
|
||||
/// <param name="destination">Destination <see cref="IPAddress"/>.</param>
|
||||
/// <returns>An asynchronous <see cref="Task"/> which sends an ARP request.</returns>
|
||||
public static Task<ArpRequestResult> SendArpRequestAsync(this IPAddress destination) => ArpRequest.SendAsync(destination);
|
||||
|
||||
#endregion
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,101 @@
|
||||
using System.Threading.Tasks;
|
||||
using System.Net.NetworkInformation;
|
||||
|
||||
namespace System.Net
|
||||
{
|
||||
/// <summary>Provides extension methods for sending Wake On LAN signals (magic packets) to a specific <see cref="IPEndPoint"/>.</summary>
|
||||
public static class IPEndPointExtensions
|
||||
{
|
||||
#region Wol
|
||||
|
||||
/// <summary>Sends a Wake On LAN signal (magic packet) to a client.</summary>
|
||||
/// <param name="target">Destination <see cref="IPEndPoint"/>.</param>
|
||||
/// <param name="macAddress">The MAC address of the client.</param>
|
||||
/// <exception cref="ArgumentException">The length of the <see cref="T:System.Byte" /> array macAddress is not 6.</exception>
|
||||
/// <exception cref="ArgumentNullException"><paramref name="macAddress"/> is null.</exception>
|
||||
public static void SendWol(this IPEndPoint target, byte[] macAddress)
|
||||
{
|
||||
Net.MagicPacket.Send(target, macAddress);
|
||||
}
|
||||
|
||||
/// <summary>Sends a Wake On LAN signal (magic packet) to a client.</summary>
|
||||
/// <param name="target">Destination <see cref="IPEndPoint"/>.</param>
|
||||
/// <param name="macAddress">The MAC address of the client.</param>
|
||||
/// <exception cref="ArgumentNullException"><paramref name="macAddress"/> is null.</exception>
|
||||
public static void SendWol(this IPEndPoint target, PhysicalAddress macAddress)
|
||||
{
|
||||
Net.MagicPacket.Send(target, macAddress);
|
||||
}
|
||||
|
||||
/// <summary>Sends a Wake On LAN signal (magic packet) to a client.</summary>
|
||||
/// <param name="target">Destination <see cref="IPEndPoint"/>.</param>
|
||||
/// <param name="macAddress">The MAC address of the client.</param>
|
||||
/// <param name="password">The SecureOn password of the client.</param>
|
||||
/// <exception cref="ArgumentException">The length of the <see cref="T:System.Byte" /> array macAddress is not 6.</exception>
|
||||
/// <exception cref="ArgumentNullException"><paramref name="macAddress"/> is null.</exception>
|
||||
public static void SendWol(this IPEndPoint target, byte[] macAddress, SecureOnPassword password)
|
||||
{
|
||||
Net.MagicPacket.Send(target, macAddress, password);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sendet ein Wake-On-LAN-Signal an einen Client.
|
||||
/// </summary>
|
||||
/// <param name="target">Der Ziel-IPEndPoint.</param>
|
||||
/// <param name="macAddress">The MAC address of the client.</param>
|
||||
/// <param name="password">The SecureOn password of the client.</param>
|
||||
/// <exception cref="ArgumentNullException"><paramref name="macAddress"/> is null.</exception>
|
||||
public static void SendWol(this IPEndPoint target, PhysicalAddress macAddress, SecureOnPassword password)
|
||||
{
|
||||
Net.MagicPacket.Send(target, macAddress, password);
|
||||
}
|
||||
|
||||
#endregion
|
||||
#region TAP
|
||||
|
||||
/// <summary>Sends a Wake On LAN signal (magic packet) to a client.</summary>
|
||||
/// <param name="target">Destination <see cref="IPEndPoint"/>.</param>
|
||||
/// <param name="macAddress">The MAC address of the client.</param>
|
||||
/// <exception cref="ArgumentException">The length of the <see cref="T:System.Byte" /> array macAddress is not 6.</exception>
|
||||
/// <exception cref="ArgumentNullException"><paramref name="macAddress"/> is null.</exception>
|
||||
/// <returns>An asynchronous <see cref="Task"/> which sends a Wake On LAN signal (magic packet) to a client.</returns>
|
||||
public static Task SendWolAsync(this IPEndPoint target, byte[] macAddress)
|
||||
{
|
||||
return Net.MagicPacket.SendAsync(target, macAddress);
|
||||
}
|
||||
|
||||
/// <summary>Sends a Wake On LAN signal (magic packet) to a client.</summary>
|
||||
/// <param name="target">Destination <see cref="IPEndPoint"/>.</param>
|
||||
/// <param name="macAddress">The MAC address of the client.</param>
|
||||
/// <exception cref="ArgumentNullException"><paramref name="macAddress"/> is null.</exception>
|
||||
/// <returns>An asynchronous <see cref="Task"/> which sends a Wake On LAN signal (magic packet) to a client.</returns>
|
||||
public static Task SendWolAsync(this IPEndPoint target, PhysicalAddress macAddress)
|
||||
{
|
||||
return Net.MagicPacket.SendAsync(target, macAddress);
|
||||
}
|
||||
|
||||
/// <summary>Sends a Wake On LAN signal (magic packet) to a client.</summary>
|
||||
/// <param name="target">Destination <see cref="IPEndPoint"/>.</param>
|
||||
/// <param name="macAddress">The MAC address of the client.</param>
|
||||
/// <param name="password">The SecureOn password of the client.</param>
|
||||
/// <exception cref="ArgumentException">The length of the <see cref="T:System.Byte" /> array macAddress is not 6.</exception>
|
||||
/// <exception cref="ArgumentNullException"><paramref name="macAddress"/> is null.</exception>
|
||||
/// <returns>An asynchronous <see cref="Task"/> which sends a Wake On LAN signal (magic packet) to a client.</returns>
|
||||
public static Task SendWolAsync(this IPEndPoint target, byte[] macAddress, SecureOnPassword password)
|
||||
{
|
||||
return Net.MagicPacket.SendAsync(target, macAddress, password);
|
||||
}
|
||||
|
||||
/// <summary>Sends a Wake On LAN signal (magic packet) to a client.</summary>
|
||||
/// <param name="target">Destination <see cref="IPEndPoint"/>.</param>
|
||||
/// <param name="macAddress">The MAC address of the client.</param>
|
||||
/// <param name="password">The SecureOn password of the client.</param>
|
||||
/// <exception cref="ArgumentNullException"><paramref name="macAddress"/> is null.</exception>
|
||||
/// <returns>An asynchronous <see cref="Task"/> which sends a Wake On LAN signal (magic packet) to a client.</returns>
|
||||
public static Task SendWolAsync(this IPEndPoint target, PhysicalAddress macAddress, SecureOnPassword password)
|
||||
{
|
||||
return Net.MagicPacket.SendAsync(target, macAddress, password);
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
#define GERMAN
|
||||
|
||||
namespace System.Net
|
||||
{
|
||||
internal static class Localization
|
||||
{
|
||||
public const string ArgumentExceptionInvalidMacAddressLength = "Invalid MAC address length.";
|
||||
public const string ArgumentExceptionInvalidPasswordLength = "Invalid password length.";
|
||||
|
||||
public const string ArgumentExceptionIsNotAValidMadAddress = " is not a valid MAC address.";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,171 @@
|
||||
using System.Threading.Tasks;
|
||||
using System.Net.NetworkInformation;
|
||||
using System.Net.Sockets;
|
||||
|
||||
namespace System.Net
|
||||
{
|
||||
/// <summary>Provides methods for sending Wake On LAN signals (magic packets).</summary>
|
||||
public static class MagicPacket
|
||||
{
|
||||
#region Wol
|
||||
|
||||
/// <summary>Sends a Wake On LAN signal (magic packet) to a client.</summary>
|
||||
/// <param name="target">Destination <see cref="IPEndPoint"/>.</param>
|
||||
/// <param name="macAddress">The MAC address of the designated client.</param>
|
||||
/// <exception cref="ArgumentNullException">target is null.</exception>
|
||||
/// <exception cref="ArgumentNullException"><paramref name="macAddress"/> is null.</exception>
|
||||
/// <exception cref="ArgumentException">The length of the <see cref="T:System.Byte" /> array macAddress is not 6.</exception>
|
||||
/// <exception cref="SocketException">An error occurred when accessing the socket. See Remarks section of <see cref="UdpClient.Send(byte[], int, IPEndPoint)"/> for more information.</exception>
|
||||
public static void Send(IPEndPoint target, byte[] macAddress) => Send(target, macAddress, null);
|
||||
|
||||
/// <summary>Sends a Wake On LAN signal (magic packet) to a client.</summary>
|
||||
/// <param name="target">Destination <see cref="IPEndPoint"/>.</param>
|
||||
/// <param name="macAddress">The MAC address of the designated client.</param>
|
||||
/// <param name="password">The SecureOn password of the client.</param>
|
||||
/// <exception cref="ArgumentNullException"><paramref name="target"/> is null.</exception>
|
||||
/// <exception cref="ArgumentNullException"><paramref name="macAddress"/> is null.</exception>
|
||||
/// <exception cref="ArgumentException">The length of the <see cref="T:System.Byte" /> array <paramref name="macAddress"/> is not 6.</exception>
|
||||
/// <exception cref="SocketException">An error occurred when accessing the socket. See Remarks section of <see cref="UdpClient.Send(byte[], int, IPEndPoint)"/> for more information.</exception>
|
||||
public static void Send(IPEndPoint target, byte[] macAddress, SecureOnPassword password)
|
||||
{
|
||||
if (macAddress == null)
|
||||
throw new ArgumentNullException(nameof(macAddress));
|
||||
|
||||
byte[] passwordBuffer = password?.GetPasswordBytes();
|
||||
byte[] packet = GetWolPacket(macAddress, passwordBuffer);
|
||||
SendPacket(target, packet);
|
||||
}
|
||||
|
||||
/// <summary>Sends a Wake On LAN signal (magic packet) to a client.</summary>
|
||||
/// <param name="target">Destination <see cref="IPEndPoint"/>.</param>
|
||||
/// <param name="macAddress">The MAC address of the designated client.</param>
|
||||
/// <exception cref="ArgumentNullException"><paramref name="macAddress"/> is null.</exception>
|
||||
/// <exception cref="SocketException">An error occurred when accessing the socket. See Remarks section of <see cref="UdpClient.Send(byte[], int, IPEndPoint)"/> for more information.</exception>
|
||||
public static void Send(IPEndPoint target, PhysicalAddress macAddress) => Send(target, macAddress, null);
|
||||
|
||||
/// <summary>Sends a Wake On LAN signal (magic packet) to a client.</summary>
|
||||
/// <param name="target">Destination <see cref="IPEndPoint"/>.</param>
|
||||
/// <param name="macAddress">The MAC address of the designated client.</param>
|
||||
/// <param name="password">The SecureOn password of the client.</param>
|
||||
/// <exception cref="ArgumentNullException"><paramref name="macAddress"/> is null.</exception>
|
||||
/// <exception cref="SocketException">An error occurred when accessing the socket. See Remarks section of <see cref="UdpClient.Send(byte[], int, IPEndPoint)"/> for more information.</exception>
|
||||
public static void Send(IPEndPoint target, PhysicalAddress macAddress, SecureOnPassword password)
|
||||
{
|
||||
if (macAddress == null)
|
||||
throw new ArgumentNullException(nameof(macAddress));
|
||||
|
||||
byte[] passwordBuffer = password?.GetPasswordBytes();
|
||||
byte[] packet = GetWolPacket(macAddress.GetAddressBytes(), passwordBuffer);
|
||||
SendPacket(target, packet);
|
||||
}
|
||||
|
||||
private static void SendPacket(IPEndPoint target, byte[] packet)
|
||||
{
|
||||
using (var cl = new UdpClient())
|
||||
cl.Send(packet, packet.Length, target);
|
||||
}
|
||||
|
||||
#endregion
|
||||
#region TAP
|
||||
|
||||
/// <summary>Sends a Wake On LAN signal (magic packet) to a client.</summary>
|
||||
/// <param name="target">Destination <see cref="IPEndPoint"/>.</param>
|
||||
/// <param name="macAddress">The MAC address of the designated client.</param>
|
||||
/// <exception cref="ArgumentNullException"><paramref name="target"/> is null.</exception>
|
||||
/// <exception cref="ArgumentNullException"><paramref name="macAddress"/> is null.</exception>
|
||||
/// <exception cref="ArgumentException">The length of the <see cref="Byte" /> array <paramref name="macAddress"/> is not 6.</exception>
|
||||
/// <returns>An asynchronous <see cref="Task"/> which sends a Wake On LAN signal (magic packet) to a client.</returns>
|
||||
public static Task SendAsync(IPEndPoint target, byte[] macAddress) => SendAsync(target, macAddress);
|
||||
|
||||
/// <summary>Sends a Wake On LAN signal (magic packet) to a client.</summary>
|
||||
/// <param name="target">Destination <see cref="IPEndPoint"/>.</param>
|
||||
/// <param name="macAddress">The MAC address of the designated client.</param>
|
||||
/// <param name="password">The SecureOn password of the client.</param>
|
||||
/// <exception cref="ArgumentNullException"><paramref name="target"/> is null.</exception>
|
||||
/// <exception cref="ArgumentNullException"><paramref name="macAddress"/> is null.</exception>
|
||||
/// <exception cref="ArgumentNullException"><paramref name="password"/> is null.</exception>
|
||||
/// <returns>An asynchronous <see cref="Task"/> which sends a Wake On LAN signal (magic packet) to a client.</returns>
|
||||
public static Task SendAsync(IPEndPoint target, byte[] macAddress, SecureOnPassword password)
|
||||
{
|
||||
if (target == null)
|
||||
throw new ArgumentNullException(nameof(target));
|
||||
if (macAddress == null)
|
||||
throw new ArgumentNullException(nameof(macAddress));
|
||||
|
||||
var passwordBuffer = password?.GetPasswordBytes();
|
||||
var packet = GetWolPacket(macAddress, passwordBuffer);
|
||||
return SendPacketAsync(target, packet);
|
||||
}
|
||||
|
||||
/// <summary>Sends a Wake On LAN signal (magic packet) to a client.</summary>
|
||||
/// <param name="target">Destination <see cref="IPEndPoint"/>.</param>
|
||||
/// <param name="macAddress">The MAC address of the designated client.</param>
|
||||
/// <exception cref="ArgumentNullException"><paramref name="target"/> is null.</exception>
|
||||
/// <exception cref="ArgumentNullException"><paramref name="macAddress"/> is null.</exception>
|
||||
/// <returns>An asynchronous <see cref="Task"/> which sends a Wake On LAN signal (magic packet) to a client.</returns>
|
||||
public static Task SendAsync(IPEndPoint target, PhysicalAddress macAddress) => SendAsync(target, macAddress, null);
|
||||
|
||||
/// <summary>Sends a Wake On LAN signal (magic packet) to a client.</summary>
|
||||
/// <param name="target">Destination <see cref="IPEndPoint"/>.</param>
|
||||
/// <param name="macAddress">The MAC address of the designated client.</param>
|
||||
/// <param name="password">The SecureOn password of the client.</param>
|
||||
/// <exception cref="ArgumentNullException"><paramref name="target"/> is null.</exception>
|
||||
/// <exception cref="ArgumentNullException"><paramref name="macAddress"/> is null.</exception>
|
||||
/// <returns>An asynchronous <see cref="Task"/> which sends a Wake On LAN signal (magic packet) to a client.</returns>
|
||||
public static Task SendAsync(IPEndPoint target, PhysicalAddress macAddress, SecureOnPassword password)
|
||||
{
|
||||
if (target == null)
|
||||
throw new ArgumentNullException(nameof(target));
|
||||
if (macAddress == null)
|
||||
throw new ArgumentNullException(nameof(macAddress));
|
||||
|
||||
var passwordBuffer = password?.GetPasswordBytes();
|
||||
var p = GetWolPacket(macAddress.GetAddressBytes(), passwordBuffer);
|
||||
return SendPacketAsync(target, p);
|
||||
}
|
||||
|
||||
private static Task SendPacketAsync(IPEndPoint target, byte[] packet)
|
||||
{
|
||||
var cl = new UdpClient();
|
||||
return cl.SendAsync(packet, packet.Length, target).ContinueWith((Task t) => cl.Close());
|
||||
}
|
||||
|
||||
#endregion
|
||||
#region internal
|
||||
|
||||
/// <exception cref="ArgumentNullException"><paramref name="macAddress"/> is null.</exception>
|
||||
/// <exception cref="ArgumentException">The length of the <see cref="T:System.Byte" /> array <paramref name="macAddress"/> is not 6.</exception>
|
||||
/// <exception cref="ArgumentException">The length of the <see cref="T:System.Byte" /> array <paramref name="password"/> is not 0 or 6.</exception>
|
||||
private static byte[] GetWolPacket(byte[] macAddress, byte[] password)
|
||||
{
|
||||
if (macAddress == null)
|
||||
throw new ArgumentNullException(nameof(macAddress));
|
||||
if (macAddress.Length != 6)
|
||||
throw new ArgumentException(Localization.ArgumentExceptionInvalidMacAddressLength);
|
||||
|
||||
password = password ?? new byte[0];
|
||||
if (password.Length != 0 && password.Length != 6)
|
||||
throw new ArgumentException(Localization.ArgumentExceptionInvalidPasswordLength);
|
||||
|
||||
var packet = new byte[17 * 6 + password.Length];
|
||||
|
||||
int offset, i;
|
||||
for (offset = 0; offset < 6; ++offset)
|
||||
packet[offset] = 0xFF;
|
||||
|
||||
for (offset = 6; offset < 17 * 6; offset += 6)
|
||||
for (i = 0; i < 6; ++i)
|
||||
packet[i + offset] = macAddress[i];
|
||||
|
||||
if (password.Length > 0)
|
||||
{
|
||||
for (offset = 16 * 6 + 6; offset < (17 * 6 + password.Length); offset += 6)
|
||||
for (i = 0; i < 6; ++i)
|
||||
packet[i + offset] = password[i];
|
||||
}
|
||||
return packet;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Security;
|
||||
|
||||
namespace System.Net
|
||||
{
|
||||
internal static class NativeMethods
|
||||
{
|
||||
private const string IphlpApi = "iphlpapi.dll";
|
||||
|
||||
[DllImport(IphlpApi, ExactSpelling = true)]
|
||||
[SecurityCritical]
|
||||
internal static extern int SendARP(int destinationIp, int sourceIp, byte[] macAddress, ref int physicalAddrLength);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,148 @@
|
||||
using System.Threading.Tasks;
|
||||
using System.Net.NetworkInformation;
|
||||
|
||||
namespace System.Net
|
||||
{
|
||||
/// <summary>Provides extension methods for sending Wake On LAN signals (magic packets) using a specific <see cref="PhysicalAddress"/>.</summary>
|
||||
public static class PhysicalAddressExtensions
|
||||
{
|
||||
#region Wol
|
||||
|
||||
/// <summary>Sends a Wake On LAN signal (magic packet) to the broadcast IP address with the physical address.</summary>
|
||||
/// <param name="address">The instance of the physical address that should be used in the magic packet.</param>
|
||||
/// <exception cref="ArgumentNullException"><paramref name="address"/> is null.</exception>
|
||||
public static void SendWol(this PhysicalAddress address) => address.SendWol(IPAddress.Broadcast, null);
|
||||
|
||||
/// <summary>Sends a Wake On LAN signal (magic packet) to a specific IP address with the physical address.</summary>
|
||||
/// <param name="address">The instance of the physical address that should be used in the magic packet.</param>
|
||||
/// <param name="target">Destination <see cref="IPEndPoint"/>.</param>
|
||||
/// <exception cref="ArgumentNullException"><paramref name="address"/> is null.</exception>
|
||||
public static void SendWol(this PhysicalAddress address, IPAddress target) => address.SendWol(target, null);
|
||||
|
||||
/// <summary>Sends a Wake On LAN signal (magic packet) to a specific IP address with the physical address.</summary>
|
||||
/// <param name="address">The instance of the physical address that should be used in the magic packet.</param>
|
||||
/// <param name="target">Destination <see cref="IPAddress"/>.</param>
|
||||
/// <param name="password">The SecureOn password of the client.</param>
|
||||
/// <exception cref="ArgumentNullException"><paramref name="address"/> is null.</exception>
|
||||
public static void SendWol(this PhysicalAddress address, IPAddress target, SecureOnPassword password)
|
||||
{
|
||||
if (address == null)
|
||||
throw new ArgumentNullException(nameof(address));
|
||||
|
||||
target.SendWol(address.GetAddressBytes(), password);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>Sends a Wake On LAN signal (magic packet) to a specific IP end point with the physical address.</summary>
|
||||
/// <param name="address">The instance of the physical address that should be used in the magic packet.</param>
|
||||
/// <param name="target">Destination <see cref="IPEndPoint"/>.</param>
|
||||
/// <exception cref="ArgumentNullException"><paramref name="address"/> is null.</exception>
|
||||
public static void SendWol(this PhysicalAddress address, IPEndPoint target) => address.SendWol(target, null);
|
||||
|
||||
/// <summary>Sends a Wake On LAN signal (magic packet) to a specific IP end point with the physical address.</summary>
|
||||
/// <param name="address">The instance of the physical address that should be used in the magic packet.</param>
|
||||
/// <param name="target">Destination <see cref="IPEndPoint"/>.</param>
|
||||
/// <param name="password">The SecureOn password of the client.</param>
|
||||
/// <exception cref="ArgumentNullException"><paramref name="address"/> is null.</exception>
|
||||
public static void SendWol(this PhysicalAddress address, IPEndPoint target, SecureOnPassword password)
|
||||
{
|
||||
if (address == null)
|
||||
throw new ArgumentNullException(nameof(address));
|
||||
|
||||
target.SendWol(address.GetAddressBytes(), password);
|
||||
}
|
||||
|
||||
#endregion
|
||||
#region TAP
|
||||
|
||||
/// <summary>Sends a Wake On LAN signal (magic packet) to the broadcast IP address with the physical address.</summary>
|
||||
/// <param name="address">The instance of the physical address that should be used in the magic packet.</param>
|
||||
/// <returns>An asynchronous <see cref="Task"/> which sends a Wake On LAN signal (magic packet) to a client.</returns>
|
||||
/// <exception cref="ArgumentNullException"><paramref name="address"/> is null.</exception>
|
||||
public static Task SendWolAsync(this PhysicalAddress address)
|
||||
{
|
||||
if (address == null)
|
||||
throw new ArgumentNullException(nameof(address));
|
||||
|
||||
return IPAddress.Broadcast.SendWolAsync(address.GetAddressBytes());
|
||||
}
|
||||
|
||||
/// <summary>Sends a Wake On LAN signal (magic packet) to a specific IP address with the physical address.</summary>
|
||||
/// <param name="address">The instance of the physical address that should be used in the magic packet.</param>
|
||||
/// <param name="target">Destination <see cref="IPAddress"/>.</param>
|
||||
/// <exception cref="ArgumentNullException"><paramref name="address"/> is null.</exception>
|
||||
/// <returns>An asynchronous <see cref="Task"/> which sends a Wake On LAN signal (magic packet) to a client.</returns>
|
||||
public static Task SendWolAsync(this PhysicalAddress address, IPAddress target) => address.SendWolAsync(target, null);
|
||||
|
||||
|
||||
/// <summary>Sends a Wake On LAN signal (magic packet) to a specific IP address with the physical address.</summary>
|
||||
/// <param name="address">The instance of the physical address that should be used in the magic packet.</param>
|
||||
/// <param name="target">Destination <see cref="IPAddress"/>.</param>
|
||||
/// <param name="password">The SecureOn password of the client.</param>
|
||||
/// <exception cref="ArgumentNullException"><paramref name="address"/> is null.</exception>
|
||||
/// <returns>An asynchronous <see cref="Task"/> which sends a Wake On LAN signal (magic packet) to a client.</returns>
|
||||
public static Task SendWolAsync(this PhysicalAddress address, IPAddress target, SecureOnPassword password)
|
||||
{
|
||||
if (address == null)
|
||||
throw new ArgumentNullException(nameof(address));
|
||||
|
||||
return target.SendWolAsync(address.GetAddressBytes(), password);
|
||||
}
|
||||
|
||||
/// <summary>Sends a Wake On LAN signal (magic packet) to a specific IP end point with the physical address.</summary>
|
||||
/// <param name="address">The instance of the physical address that should be used in the magic packet.</param>
|
||||
/// <param name="target">Destination <see cref="IPEndPoint"/>.</param>
|
||||
/// <exception cref="ArgumentNullException"><paramref name="address"/> is null.</exception>
|
||||
/// <returns>An asynchronous <see cref="Task"/> which sends a Wake On LAN signal (magic packet) to a client.</returns>
|
||||
public static Task SendWolAsync(this PhysicalAddress address, IPEndPoint target) => address.SendWolAsync(target, null);
|
||||
|
||||
/// <summary>Sends a Wake On LAN signal (magic packet) to a specific IP end point with the physical address.</summary>
|
||||
/// <param name="address">The instance of the physical address that should be used in the magic packet.</param>
|
||||
/// <param name="target">Destination <see cref="IPEndPoint"/>.</param>
|
||||
/// <param name="password">The SecureOn password of the client.</param>
|
||||
/// <exception cref="ArgumentNullException"><paramref name="address"/> is null.</exception>
|
||||
/// <returns>An asynchronous <see cref="Task"/> which sends a Wake On LAN signal (magic packet) to a client.</returns>
|
||||
public static Task SendWolAsync(this PhysicalAddress address, IPEndPoint target, SecureOnPassword password)
|
||||
{
|
||||
if (address == null)
|
||||
throw new ArgumentNullException(nameof(address));
|
||||
|
||||
return target.SendWolAsync(address.GetAddressBytes(), password);
|
||||
}
|
||||
|
||||
#endregion
|
||||
#region common
|
||||
|
||||
/// <summary>Gets the type (<see cref="PhysicalAddressAdministrator"/>) of the <see cref="PhysicalAddress" />.</summary>
|
||||
/// <param name="address">The address.</param>
|
||||
/// <exception cref="ArgumentNullException"><paramref name="address"/> is null.</exception>
|
||||
/// <returns>The <see cref="PhysicalAddressType" /> of the physical addess (MAC address).</returns>
|
||||
public static PhysicalAddressType GetAddressType(this PhysicalAddress address)
|
||||
{
|
||||
if (address == null)
|
||||
throw new ArgumentNullException(nameof(address));
|
||||
|
||||
var bytes = address.GetAddressBytes();
|
||||
if (bytes == null || bytes.Length < 1)
|
||||
throw new ArgumentException($"Invalid {nameof(address)}.");
|
||||
return (bytes[0] & 0x1) == 0 ? PhysicalAddressType.Unicast : PhysicalAddressType.Multicast;
|
||||
}
|
||||
|
||||
/// <summary>Gets the administrator (<see cref="PhysicalAddressAdministrator"/>) of the <see cref="PhysicalAddress" />.</summary>
|
||||
/// <param name="address">The address.</param>
|
||||
/// <exception cref="ArgumentNullException"><paramref name="address"/> is null.</exception>
|
||||
/// <returns>The <see cref="PhysicalAddressAdministrator" /> of the physical addess (MAC address).</returns>
|
||||
public static PhysicalAddressAdministrator GetAddressAdministrator(this PhysicalAddress address)
|
||||
{
|
||||
if (address == null)
|
||||
throw new ArgumentNullException(nameof(address));
|
||||
|
||||
var bytes = address.GetAddressBytes();
|
||||
if (bytes == null || bytes.Length < 1)
|
||||
throw new ArgumentException($"Invalid {nameof(address)}.");
|
||||
return (bytes[0] & 0x2) == 0 ? PhysicalAddressAdministrator.Global : PhysicalAddressAdministrator.Local;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
namespace System.Net
|
||||
{
|
||||
/// <summary>
|
||||
/// Der Administrator der physikalischen Adresse gibt an, ob die Adresse globally unique oder local administrated ist.
|
||||
/// </summary>
|
||||
public enum PhysicalAddressAdministrator
|
||||
{
|
||||
/// <summary>
|
||||
/// Die Adresse ist global einzigartig (nach der OUI).
|
||||
/// </summary>
|
||||
Global,
|
||||
|
||||
/// <summary>
|
||||
/// Die Adresse ist lokal administriert.
|
||||
/// </summary>
|
||||
Local
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Der Typ der physikalischen Adresse gibt an, ob es um eine UNicast oder Multicast-Adresse handelt.
|
||||
/// </summary>
|
||||
public enum PhysicalAddressType
|
||||
{
|
||||
/// <summary>
|
||||
/// Bezeichnet eine Unicast-Adresse.
|
||||
/// </summary>
|
||||
Unicast,
|
||||
|
||||
/// <summary>
|
||||
/// Bezeichnet eine Multicast-Adresse
|
||||
/// </summary>
|
||||
Multicast
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
using System.Runtime.CompilerServices;
|
||||
using System;
|
||||
|
||||
[assembly: InternalsVisibleTo("WakeOnLan.Tests")]
|
||||
@@ -0,0 +1,95 @@
|
||||
namespace System.Net
|
||||
{
|
||||
/// <summary>Provides a SecureOn password.</summary>
|
||||
[Serializable]
|
||||
public sealed class SecureOnPassword
|
||||
{
|
||||
private readonly byte[] _password;
|
||||
|
||||
/// <summary>Initializes a new instance of <see cref="SecureOnPassword"/> with the given password.</summary>
|
||||
/// <param name="password">The password as <see cref="Byte"/> array.</param>
|
||||
/// <exception cref="ArgumentNullException"><paramref name="password"/> is null.</exception>
|
||||
/// <exception cref="ArgumentException">The length of the <see cref="T:System.Byte" /> array password is not 6.</exception>
|
||||
public SecureOnPassword(byte[] password)
|
||||
{
|
||||
if (password == null)
|
||||
throw new ArgumentNullException(nameof(password));
|
||||
if (password.Length != 6)
|
||||
throw new ArgumentException(Localization.ArgumentExceptionInvalidPasswordLength);
|
||||
_password = password;
|
||||
}
|
||||
|
||||
/// <summary>Gets the buffer of the password.</summary>
|
||||
public byte[] GetPasswordBytes()
|
||||
{
|
||||
if (_password == null)
|
||||
return null;
|
||||
var buffer = new byte[_password.Length];
|
||||
Array.Copy(_password, buffer, 0);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
/// <summary>Initializes a new instance of <see cref="SecureOnPassword"/> with the given password.</summary>
|
||||
/// <param name="password">The password as <see cref="String"/>.</param>
|
||||
/// <exception cref="ArgumentNullException"><paramref name="password"/> is null.</exception>
|
||||
/// <remarks>Uses <see cref="Text.Encoding.Default" /> as encoding.</remarks>
|
||||
public SecureOnPassword(string password)
|
||||
: this(password, Text.Encoding.Default)
|
||||
{ }
|
||||
|
||||
|
||||
/// <summary>Initializes a new instance of <see cref="SecureOnPassword"/> with the given password.</summary>
|
||||
/// <param name="password">The password as <see cref="String"/>.</param>
|
||||
/// <param name="encoding">The <see cref="Text.Encoding"/> instance to use for the password.</param>
|
||||
/// <exception cref="ArgumentNullException"><paramref name="password"/> is null.</exception>
|
||||
/// <exception cref="ArgumentNullException"><paramref name="encoding"/> is null.</exception>
|
||||
/// <exception cref="ArgumentException">The <see cref="Byte"/> array wich is created using the password has more elements than 6.</exception>
|
||||
public SecureOnPassword(string password, Text.Encoding encoding)
|
||||
{
|
||||
if (password == null)
|
||||
throw new ArgumentNullException(nameof(password));
|
||||
if (encoding == null)
|
||||
throw new ArgumentNullException(nameof(encoding));
|
||||
|
||||
if (string.IsNullOrEmpty(password))
|
||||
_password = new byte[6];
|
||||
|
||||
var bytes = encoding.GetBytes(password);
|
||||
if (bytes.Length > 6)
|
||||
throw new ArgumentException(Localization.ArgumentExceptionInvalidPasswordLength);
|
||||
|
||||
_password = new byte[6];
|
||||
for (int i = 0; i < bytes.Length; i++)
|
||||
_password[i] = bytes[i];
|
||||
if (bytes.Length < 6)
|
||||
{
|
||||
for (int i = bytes.Length - 1; i < 6; i++)
|
||||
_password[i] = 0x00;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Converts the <see cref="SecureOnPassword"/> to dash notation.</summary>
|
||||
/// <returns>A <see cref="String"/> representing the <see cref="SecureOnPassword"/> as dash notation.</returns>
|
||||
public override string ToString() => ToString("X2");
|
||||
|
||||
/// <summary>Converts the <see cref="SecureOnPassword"/> to dash notation.</summary>
|
||||
/// <returns>A <see cref="String"/> representing the <see cref="SecureOnPassword"/> as dash notation.</returns>
|
||||
private string ToString(string format)
|
||||
{
|
||||
var f = new string[6];
|
||||
for (int i = 0; i < f.Length; i++)
|
||||
f[i] = _password[i].ToString(format);
|
||||
return string.Join("-", f);
|
||||
}
|
||||
|
||||
/// <summary>Converts the <see cref="SecureOnPassword"/> to dash notation.</summary>
|
||||
/// <returns>A <see cref="String"/> representing the <see cref="SecureOnPassword"/> as dash notation.</returns>
|
||||
public string ToString(IFormatProvider format)
|
||||
{
|
||||
var f = new string[6];
|
||||
for (int i = 0; i < f.Length; i++)
|
||||
f[i] = _password[i].ToString(format);
|
||||
return string.Join("-", f);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,287 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Text;
|
||||
|
||||
namespace System.Net.Topology
|
||||
{
|
||||
internal static class ByteArrayExtensions
|
||||
{
|
||||
internal static IEnumerable<bool> ToBitStream(this byte[] bytes, bool fromLeft)
|
||||
{
|
||||
if (bytes == null)
|
||||
throw new ArgumentNullException(nameof(bytes));
|
||||
|
||||
if (fromLeft)
|
||||
{
|
||||
for (int i = 0; i < bytes.Length; ++i)
|
||||
{
|
||||
byte tmp = bytes[i].ReverseBits();
|
||||
for (int j = 0; j < 8; ++j)
|
||||
{
|
||||
yield return (tmp & 1) == 1;
|
||||
tmp >>= 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = bytes.Length - 1; i >= 0; --i)
|
||||
{
|
||||
byte tmp = bytes[i];
|
||||
for (int j = 0; j < 8; ++j)
|
||||
{
|
||||
yield return (tmp & 1) == 1;
|
||||
tmp >>= 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static int CountFromSide(byte[] bits, bool value, bool fromleft)
|
||||
{
|
||||
int counter = 0;
|
||||
var str = bits.ToBitStream(fromleft);
|
||||
foreach (var bit in str)
|
||||
{
|
||||
if (bit == value)
|
||||
++counter;
|
||||
else return counter;
|
||||
}
|
||||
return counter;
|
||||
}
|
||||
|
||||
internal static int CountFromLeft(this byte[] bits, bool value)
|
||||
{
|
||||
if (bits == null)
|
||||
throw new ArgumentNullException(nameof(bits));
|
||||
return CountFromSide(bits, value, true);
|
||||
}
|
||||
|
||||
internal static int CountFromRight(this byte[] bits, bool value)
|
||||
{
|
||||
if (bits == null)
|
||||
throw new ArgumentNullException(nameof(bits));
|
||||
return CountFromSide(bits, value, false);
|
||||
}
|
||||
|
||||
internal static string ToBinaryString(this byte[] bits, char separator)
|
||||
{
|
||||
if (bits == null)
|
||||
throw new ArgumentNullException(nameof(bits));
|
||||
|
||||
const int radix = 2;
|
||||
const int padding = 8;
|
||||
const char paddingChar = '0';
|
||||
|
||||
var sb = new StringBuilder();
|
||||
sb.Append(Convert.ToString(bits[0], radix).PadLeft(padding, paddingChar)).Append(separator);
|
||||
sb.Append(Convert.ToString(bits[1], radix).PadLeft(padding, paddingChar)).Append(separator);
|
||||
sb.Append(Convert.ToString(bits[2], radix).PadLeft(padding, paddingChar)).Append(separator);
|
||||
sb.Append(Convert.ToString(bits[3], radix).PadLeft(padding, paddingChar));
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
internal static string ToBinaryString(this byte[] bits)
|
||||
{
|
||||
if (bits == null)
|
||||
throw new ArgumentNullException(nameof(bits));
|
||||
|
||||
const int radix = 2;
|
||||
const int padding = 8;
|
||||
const char paddingChar = '0';
|
||||
|
||||
var sb = new StringBuilder();
|
||||
sb.Append(Convert.ToString(bits[0], radix).PadLeft(padding, paddingChar));
|
||||
sb.Append(Convert.ToString(bits[1], radix).PadLeft(padding, paddingChar));
|
||||
sb.Append(Convert.ToString(bits[2], radix).PadLeft(padding, paddingChar));
|
||||
sb.Append(Convert.ToString(bits[3], radix).PadLeft(padding, paddingChar));
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
internal static bool RepresentsValidNetMask(this byte[] bits)
|
||||
{
|
||||
if (bits == null)
|
||||
throw new ArgumentNullException(nameof(bits));
|
||||
|
||||
int fromLeft = bits.CountFromLeft(true);
|
||||
int fromRight = bits.CountFromRight(false);
|
||||
|
||||
// Sum of all counted indexes schloud be equal the whole length
|
||||
return (fromLeft + fromRight) == (8 * NetMask.MaskLength);
|
||||
}
|
||||
|
||||
internal static byte[] And(this byte[] b1, byte[] b2)
|
||||
{
|
||||
if (b1 == null)
|
||||
throw new ArgumentNullException(nameof(b1));
|
||||
if (b2 == null)
|
||||
throw new ArgumentNullException(nameof(b2));
|
||||
|
||||
if (b1.Length == 1 && b2.Length == 1)
|
||||
{
|
||||
int ib1 = b1[0];
|
||||
int ib2 = b2[0];
|
||||
return new[] { (byte)(ib1 & ib2) };
|
||||
}
|
||||
if (b1.Length == 2 && b2.Length == 2)
|
||||
{
|
||||
var sb1 = BitConverter.ToInt16(b1, 0);
|
||||
var sb2 = BitConverter.ToInt16(b2, 0);
|
||||
return BitConverter.GetBytes((short)(sb1 & sb2));
|
||||
}
|
||||
if (b1.Length == 4 && b2.Length == 4)
|
||||
{
|
||||
var ib1 = BitConverter.ToInt32(b1, 0);
|
||||
var ib2 = BitConverter.ToInt32(b2, 0);
|
||||
return BitConverter.GetBytes(ib1 & ib2);
|
||||
}
|
||||
if (b1.Length != b2.Length)
|
||||
{
|
||||
// Or maybe throw exception?
|
||||
|
||||
int maxIndex = Math.Max(b1.Length, b2.Length);
|
||||
byte[] biggerArray = b1.Length > b2.Length ? b1 : b2;
|
||||
byte[] smallerArray = b1.Length <= b2.Length ? b1 : b2;
|
||||
|
||||
var paddedArray = new byte[maxIndex];
|
||||
|
||||
Buffer.BlockCopy(smallerArray, 0, paddedArray, 0, smallerArray.Length);
|
||||
|
||||
Debug.Assert(biggerArray.Length == paddedArray.Length);
|
||||
|
||||
return And(biggerArray, paddedArray);
|
||||
}
|
||||
|
||||
var targetIndex = b1.Length;
|
||||
var andedArray = new byte[targetIndex];
|
||||
Buffer.BlockCopy(b1, 0, andedArray, 0, andedArray.Length);
|
||||
|
||||
for (int i = 0; i < targetIndex; ++i)
|
||||
andedArray[i] &= b2[i];
|
||||
|
||||
return andedArray;
|
||||
}
|
||||
|
||||
internal static byte[] Or(this byte[] b1, byte[] b2)
|
||||
{
|
||||
if (b1 == null)
|
||||
throw new ArgumentNullException(nameof(b1));
|
||||
if (b2 == null)
|
||||
throw new ArgumentNullException(nameof(b2));
|
||||
|
||||
if (b1.Length == 1 && b2.Length == 1)
|
||||
{
|
||||
int ib1 = b1[0];
|
||||
int ib2 = b2[0];
|
||||
return new[] { (byte)(ib1 | ib2) };
|
||||
}
|
||||
if (b1.Length == 2 && b2.Length == 2)
|
||||
{
|
||||
var sb1 = BitConverter.ToInt16(b1, 0);
|
||||
var sb2 = BitConverter.ToInt16(b2, 0);
|
||||
return BitConverter.GetBytes((short)(sb1 | sb2));
|
||||
}
|
||||
if (b1.Length == 4 && b2.Length == 4)
|
||||
{
|
||||
var ib1 = BitConverter.ToInt32(b1, 0);
|
||||
var ib2 = BitConverter.ToInt32(b2, 0);
|
||||
return BitConverter.GetBytes(ib1 | ib2);
|
||||
}
|
||||
if (b1.Length != b2.Length)
|
||||
{
|
||||
// Or maybe throw exception?
|
||||
|
||||
int maxIndex = Math.Max(b1.Length, b2.Length);
|
||||
byte[] biggerArray = b1.Length > b2.Length ? b1 : b2;
|
||||
byte[] smallerArray = b1.Length <= b2.Length ? b1 : b2;
|
||||
|
||||
var paddedArray = new byte[maxIndex];
|
||||
|
||||
Buffer.BlockCopy(smallerArray, 0, paddedArray, 0, smallerArray.Length);
|
||||
|
||||
Debug.Assert(biggerArray.Length == paddedArray.Length);
|
||||
|
||||
return Or(biggerArray, paddedArray);
|
||||
}
|
||||
|
||||
var targetIndex = b1.Length;
|
||||
var oredArray = new byte[targetIndex];
|
||||
Buffer.BlockCopy(b1, 0, oredArray, 0, oredArray.Length);
|
||||
|
||||
for (int i = 0; i < targetIndex; ++i)
|
||||
oredArray[i] |= b2[i];
|
||||
|
||||
return oredArray;
|
||||
}
|
||||
|
||||
internal static byte[] Xor(this byte[] b1, byte[] b2)
|
||||
{
|
||||
if (b1 == null)
|
||||
throw new ArgumentNullException(nameof(b1));
|
||||
if (b2 == null)
|
||||
throw new ArgumentNullException(nameof(b2));
|
||||
|
||||
// TODO: Testing
|
||||
|
||||
if (b1.Length == 1 && b2.Length == 1)
|
||||
{
|
||||
int ib1 = b1[0];
|
||||
int ib2 = b2[0];
|
||||
return new[] { (byte)(ib1 ^ ib2) };
|
||||
}
|
||||
if (b1.Length == 2 && b2.Length == 2)
|
||||
{
|
||||
var sb1 = BitConverter.ToInt16(b1, 0);
|
||||
var sb2 = BitConverter.ToInt16(b2, 0);
|
||||
return BitConverter.GetBytes((short)(sb1 ^ sb2));
|
||||
}
|
||||
if (b1.Length == 4 && b2.Length == 4)
|
||||
{
|
||||
var ib1 = BitConverter.ToInt32(b1, 0);
|
||||
var ib2 = BitConverter.ToInt32(b2, 0);
|
||||
return BitConverter.GetBytes(ib1 ^ ib2);
|
||||
}
|
||||
if (b1.Length != b2.Length)
|
||||
{
|
||||
// Or maybe throw exception?
|
||||
|
||||
int maxIndex = Math.Max(b1.Length, b2.Length);
|
||||
byte[] biggerArray = b1.Length > b2.Length ? b1 : b2;
|
||||
byte[] smallerArray = b1.Length <= b2.Length ? b1 : b2;
|
||||
|
||||
var paddedArray = new byte[maxIndex];
|
||||
|
||||
Buffer.BlockCopy(smallerArray, 0, paddedArray, 0, smallerArray.Length);
|
||||
|
||||
Debug.Assert(biggerArray.Length == paddedArray.Length);
|
||||
|
||||
return Xor(biggerArray, paddedArray);
|
||||
}
|
||||
|
||||
var targetIndex = b1.Length;
|
||||
var xoredArray = new byte[targetIndex];
|
||||
Buffer.BlockCopy(b1, 0, xoredArray, 0, xoredArray.Length);
|
||||
|
||||
for (int i = 0; i < targetIndex; ++i)
|
||||
xoredArray[i] ^= b2[i];
|
||||
|
||||
return xoredArray;
|
||||
}
|
||||
|
||||
internal static byte[] Not(this byte[] bits)
|
||||
{
|
||||
if (bits == null)
|
||||
throw new ArgumentNullException(nameof(bits));
|
||||
|
||||
if (bits.Length == 4)
|
||||
{
|
||||
var i = BitConverter.ToInt32(bits, 0);
|
||||
return BitConverter.GetBytes(~i);
|
||||
}
|
||||
var newBytes = new byte[bits.Length];
|
||||
for (int i = 0; i < newBytes.Length; ++i)
|
||||
newBytes[i] = unchecked((byte)(~bits[i]));
|
||||
return newBytes;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
|
||||
namespace System.Net.Topology
|
||||
{
|
||||
internal static class ByteExtensions
|
||||
{
|
||||
public static byte[] BitReverseTable = {
|
||||
0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0,
|
||||
0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0,
|
||||
0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8,
|
||||
0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8,
|
||||
0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4,
|
||||
0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,
|
||||
0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec,
|
||||
0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc,
|
||||
0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2,
|
||||
0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2,
|
||||
0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea,
|
||||
0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,
|
||||
0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6,
|
||||
0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6,
|
||||
0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee,
|
||||
0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe,
|
||||
0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1,
|
||||
0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1,
|
||||
0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9,
|
||||
0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9,
|
||||
0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5,
|
||||
0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5,
|
||||
0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed,
|
||||
0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd,
|
||||
0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3,
|
||||
0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3,
|
||||
0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb,
|
||||
0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb,
|
||||
0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7,
|
||||
0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7,
|
||||
0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef,
|
||||
0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff
|
||||
};
|
||||
|
||||
public static byte ReverseBits(this byte toReverse) => BitReverseTable[toReverse];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
|
||||
namespace System.Net.Topology
|
||||
{
|
||||
/// <summary>Provides an interface for IP net masks.</summary>
|
||||
public interface INetMask
|
||||
{
|
||||
/// <summary>Gets the length of the net mask in bits.</summary>
|
||||
int AddressLength { get; }
|
||||
|
||||
/// <summary>Gets the amount of set bits from the left side (used in CIDR-Notation of net masks).</summary>
|
||||
int Cidr { get; }
|
||||
|
||||
/// <summary>Gets the bits of the net mask instance as an BitArray object instance.</summary>
|
||||
/// <returns>The bits of the net mask instance as an BitArray object instance</returns>
|
||||
byte[] GetMaskBytes();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,167 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace System.Net.Topology
|
||||
{
|
||||
/// <summary>Provides extension methods for the <see cref="T:System.Net.IPAddress"/>.</summary>
|
||||
public static class IPAddressExtensions
|
||||
{
|
||||
private const string OnlyIPv4Supported = "Only IPv4 is currently supported";
|
||||
|
||||
/// <summary>Enumerates through the siblings of an <see cref="T:System.Net.IPAddress"/> in a network. Compliant to RFC 950 (2^n-2).</summary>
|
||||
/// <param name="address">The address</param>
|
||||
/// <param name="mask">The net mask of the network</param>
|
||||
public static IEnumerable<IPAddress> GetSiblings(this IPAddress address, NetMask mask)
|
||||
{
|
||||
return GetSiblings(address, mask, SiblingOptions.ExcludeUnusable);
|
||||
}
|
||||
|
||||
/// <summary>Enumerates through the siblings of an <see cref="T:System.Net.IPAddress"/> in a network.</summary>
|
||||
/// <param name="address">The address</param>
|
||||
/// <param name="mask">The net mask of the network</param>
|
||||
/// <param name="options">Options which addresses to include an which not</param>
|
||||
public static IEnumerable<IPAddress> GetSiblings(this IPAddress address, NetMask mask, SiblingOptions options)
|
||||
{
|
||||
if (address == null)
|
||||
throw new ArgumentNullException(nameof(address));
|
||||
if (mask == null)
|
||||
throw new ArgumentNullException(nameof(mask));
|
||||
if (address.AddressFamily != Sockets.AddressFamily.InterNetwork)
|
||||
throw new NotSupportedException(OnlyIPv4Supported);
|
||||
|
||||
bool includeSelf = BitHelper.IsOptionSet(options, SiblingOptions.IncludeSelf);
|
||||
bool includeBroadcast = BitHelper.IsOptionSet(options, SiblingOptions.IncludeBroadcast);
|
||||
bool includeNetworkIdentifier = BitHelper.IsOptionSet(options, SiblingOptions.IncludeNetworkIdentifier);
|
||||
|
||||
bool alreadyReturnedSelf = false;
|
||||
|
||||
var netPrefix = address.GetNetworkPrefix(mask);
|
||||
|
||||
if (includeNetworkIdentifier)
|
||||
{
|
||||
netPrefix = address.GetNetworkPrefix(mask);
|
||||
if (netPrefix.Equals(address))
|
||||
alreadyReturnedSelf = true;
|
||||
yield return netPrefix;
|
||||
}
|
||||
|
||||
var selfAddressBytes = address.GetAddressBytes();
|
||||
|
||||
var netPrefixBytes = netPrefix.GetAddressBytes();
|
||||
|
||||
int cidr = mask.Cidr;
|
||||
uint maxHosts = 0xFFFFFFFF;
|
||||
|
||||
if (cidr > 0)
|
||||
maxHosts = (uint)(1 << (8 * NetMask.MaskLength - cidr)) - 1;
|
||||
|
||||
var hostBytes = new byte[NetMask.MaskLength];
|
||||
for (int hostPart = 1; hostPart < maxHosts; ++hostPart)
|
||||
{
|
||||
unchecked
|
||||
{
|
||||
hostBytes[0] = (byte)(hostPart >> 24);
|
||||
hostBytes[1] = (byte)(hostPart >> 16);
|
||||
hostBytes[2] = (byte)(hostPart >> 8);
|
||||
hostBytes[3] = (byte)(hostPart >> 0);
|
||||
}
|
||||
|
||||
Debug.WriteLine("HostPart: " + hostPart.ToString("X2").PadLeft(8, '0') + " (" + BitConverter.ToString(hostBytes) + ")");
|
||||
|
||||
var nextIpBytes = netPrefixBytes.Or(hostBytes);
|
||||
var nextIp = new IPAddress(nextIpBytes);
|
||||
|
||||
if (!alreadyReturnedSelf)
|
||||
{
|
||||
if (includeSelf)
|
||||
{
|
||||
if (nextIpBytes[0] == selfAddressBytes[0]
|
||||
&& nextIpBytes[1] == selfAddressBytes[1]
|
||||
&& nextIpBytes[2] == selfAddressBytes[2]
|
||||
&& nextIpBytes[3] == selfAddressBytes[3])
|
||||
alreadyReturnedSelf = true;
|
||||
yield return nextIp;
|
||||
}
|
||||
else if (nextIpBytes[0] != selfAddressBytes[0]
|
||||
|| nextIpBytes[1] != selfAddressBytes[1]
|
||||
|| nextIpBytes[2] != selfAddressBytes[2]
|
||||
|| nextIpBytes[3] != selfAddressBytes[3])
|
||||
yield return nextIp;
|
||||
}
|
||||
else
|
||||
yield return nextIp;
|
||||
}
|
||||
|
||||
if (includeBroadcast)
|
||||
{
|
||||
var broadcastAddress = address.GetBroadcastAddress(mask);
|
||||
if (!address.Equals(broadcastAddress) || (address.Equals(broadcastAddress) && !alreadyReturnedSelf))
|
||||
yield return broadcastAddress;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Gets the network prefix of an <see cref="T:System.Net.IPAddress"/>.</summary>
|
||||
/// <param name="address">The address</param>
|
||||
/// <param name="mask">The net mask of the network</param>
|
||||
/// <returns>The network prefix of an <see cref="T:System.Net.IPAddress"/></returns>
|
||||
public static IPAddress GetNetworkPrefix(this IPAddress address, NetMask mask)
|
||||
{
|
||||
if (address == null)
|
||||
throw new ArgumentNullException(nameof(address));
|
||||
if (mask == null)
|
||||
throw new ArgumentNullException(nameof(mask));
|
||||
|
||||
if (address.AddressFamily != Sockets.AddressFamily.InterNetwork)
|
||||
throw new NotSupportedException(OnlyIPv4Supported);
|
||||
|
||||
return mask & address;
|
||||
}
|
||||
|
||||
/// <summary>Gets the broadcast address of an <see cref="T:System.Net.IPAddress"/>.</summary>
|
||||
/// <param name="address">The address</param>
|
||||
/// <param name="mask">The net mask of the network</param>
|
||||
/// <returns>The broadcast address of an <see cref="T:System.Net.IPAddress"/></returns>
|
||||
public static IPAddress GetBroadcastAddress(this IPAddress address, NetMask mask)
|
||||
{
|
||||
if (address == null)
|
||||
throw new ArgumentNullException("address");
|
||||
if (mask == null)
|
||||
throw new ArgumentNullException("mask");
|
||||
|
||||
if (address.AddressFamily != Sockets.AddressFamily.InterNetwork)
|
||||
throw new NotSupportedException(OnlyIPv4Supported);
|
||||
|
||||
// TODO: Test
|
||||
|
||||
var ipBytes = address.GetAddressBytes();
|
||||
var notMaskBytes = mask.GetMaskBytes().Not();
|
||||
|
||||
var broadcastAddressBytes = notMaskBytes.Or(ipBytes);
|
||||
return new IPAddress(broadcastAddressBytes);
|
||||
}
|
||||
|
||||
/// <summary>Gets the host identifier (rest) an <see cref="T:System.Net.IPAddress"/>.</summary>
|
||||
/// <param name="address">The address</param>
|
||||
/// <param name="mask">The net mask of the network</param>
|
||||
/// <returns>The host identifier (rest) an <see cref="T:System.Net.IPAddress"/></returns>
|
||||
public static IPAddress GetHostIdentifier(this IPAddress address, NetMask mask)
|
||||
{
|
||||
if (address == null)
|
||||
throw new ArgumentNullException(nameof(address));
|
||||
if (mask == null)
|
||||
throw new ArgumentNullException(nameof(mask));
|
||||
if (address.AddressFamily != Sockets.AddressFamily.InterNetwork)
|
||||
throw new NotSupportedException(OnlyIPv4Supported);
|
||||
|
||||
var maskBits = mask.GetMaskBytes();
|
||||
var ipBits = address.GetAddressBytes();
|
||||
|
||||
// ~Mask & IP
|
||||
var retVal = maskBits.Not().And(ipBits);
|
||||
var bytes = new byte[NetMask.MaskLength];
|
||||
Buffer.BlockCopy(retVal, 0, bytes, 0, bytes.Length);
|
||||
|
||||
return new IPAddress(bytes);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,312 @@
|
||||
using System.Diagnostics;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
|
||||
namespace System.Net.Topology
|
||||
{
|
||||
// TODO: Use Span<T> when available (instead of byte arrays)
|
||||
/// <summary>Represents an IPv4 net mask.</summary>
|
||||
[StructLayout(LayoutKind.Explicit)]
|
||||
public struct NetMask : INetMask, IEquatable<NetMask>
|
||||
{
|
||||
[FieldOffset(0)]
|
||||
private readonly uint _mask;
|
||||
|
||||
#region byte-wise fields
|
||||
|
||||
// We are assuming here, that the byte-ordering is like on a normal x86 system
|
||||
|
||||
[FieldOffset(3)]
|
||||
private readonly byte _maskB0;
|
||||
[FieldOffset(2)]
|
||||
private readonly byte _maskB1;
|
||||
[FieldOffset(1)]
|
||||
private readonly byte _maskB2;
|
||||
[FieldOffset(0)]
|
||||
private readonly byte _maskB3;
|
||||
|
||||
#endregion
|
||||
|
||||
internal const int MaskLength = 4;
|
||||
|
||||
/// <summary>Represents an empty IPv4 NetMask (all bits set to 0).</summary>
|
||||
public static NetMask Empty { get; } = new NetMask();
|
||||
|
||||
/// <summary>Gets the length of the net mask in bits.</summary>
|
||||
public int AddressLength => MaskLength * 8;
|
||||
|
||||
/// <summary>Gets the amount of set bits from the left side (used in CIDR-Notation of net masks).</summary>
|
||||
public int Cidr => GetCidr(_mask);
|
||||
|
||||
#region Ctors
|
||||
|
||||
/// <summary>Creates a new instance of <see cref="T:System.Net.Topology.NetMask"/> cloning an existing instance of <see cref="T:System.Net.Topology.NetMask"/>.</summary>
|
||||
public NetMask(NetMask mask)
|
||||
{
|
||||
if (mask == null)
|
||||
throw new ArgumentNullException(nameof(mask));
|
||||
_maskB0 = _maskB1 = _maskB2 = _maskB3 = 0;
|
||||
_mask = mask._mask;
|
||||
}
|
||||
|
||||
/// <summary>Creates a new instance of <see cref="T:System.Net.Topology.NetMask"/> from an array of <see cref="System.Byte"/>.</summary>
|
||||
public NetMask(byte[] value)
|
||||
{
|
||||
_maskB0 = _maskB1 = _maskB2 = _maskB3 = 0;
|
||||
_mask = 0;
|
||||
if (value == null || value.Length == 0) // maybe throw ArgumentNullException?
|
||||
return;
|
||||
|
||||
if (value.Length != MaskLength)
|
||||
throw new ArgumentException("Invalid mask length.");
|
||||
|
||||
CheckMaskBytes(value); // check if passed mask are a valid mask. if not, throw Exception
|
||||
_maskB0 = value[0];
|
||||
_maskB1 = value[1];
|
||||
_maskB2 = value[2];
|
||||
_maskB3 = value[3];
|
||||
}
|
||||
|
||||
/// <summary>Creates a new instance of <see cref="T:System.Net.Topology.NetMask"/> from a given <see cref="T:System.Net.IPAddress"/>.</summary>
|
||||
/// <param name="address">The IPv4 address.</param>
|
||||
public NetMask(IPAddress address)
|
||||
: this(address == null ? null : address.GetAddressBytes())
|
||||
{ }
|
||||
|
||||
/// <summary>Creates a new instance of <see cref="T:System.Net.Topology.NetMask"/>.</summary>
|
||||
/// <param name="m0">The first byte.</param>
|
||||
/// <param name="m1">The second byte.</param>
|
||||
/// <param name="m2">The third byte.</param>
|
||||
/// <param name="m3">The fourth byte.</param>
|
||||
public NetMask(byte m0, byte m1, byte m2, byte m3)
|
||||
: this(new[] { m0, m1, m2, m3 })
|
||||
{ }
|
||||
|
||||
/// <summary>Creates a new instance of <see cref="T:System.Net.Topology.NetMask"/>.</summary>
|
||||
/// <param name="cidr">The mask represented by the CIDR notation integer.</param>
|
||||
public NetMask(byte cidr)
|
||||
{
|
||||
// maybe change parameter type interpretation to CIDR?
|
||||
if (cidr > MaskLength * 8)
|
||||
throw new ArgumentException("Invalid CIDR length");
|
||||
_maskB0 = _maskB1 = _maskB2 = _maskB3 = 0; // to keep init checks happy
|
||||
_mask = GetUIntFromCidrValue(cidr);
|
||||
}
|
||||
|
||||
private NetMask(uint ipv4Mask)
|
||||
{
|
||||
_maskB0 = _maskB1 = _maskB2 = _maskB3 = 0; // to keep init checks happy
|
||||
_mask = ipv4Mask;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private static void CheckMaskBytes(byte[] bytes)
|
||||
{
|
||||
if (!bytes.RepresentsValidNetMask())
|
||||
throw new ArgumentException("The passed mask do not represent a valid net mask.");
|
||||
}
|
||||
|
||||
/// <summary>Gets the bits of the net mask instance as an BitArray object instance.</summary>
|
||||
/// <returns>The bits of the net mask instance as an BitArray object instance.</returns>
|
||||
public byte[] GetMaskBytes() => new[] { _maskB0, _maskB1, _maskB2, _maskB3 };
|
||||
|
||||
private static int GetCidr(uint mask)
|
||||
{
|
||||
Debug.Assert(sizeof(uint) == MaskLength);
|
||||
return mask.CountOnesFromLeft();
|
||||
}
|
||||
|
||||
/// <summary>Extends the current <see cref="T:System.Net.Topology.NetMask"/> instance by a given value (CIDR-wise).</summary>
|
||||
/// <param name="mask">The mask to use as a reference.</param>
|
||||
/// <param name="value">The value.</param>
|
||||
/// <remarks>Because <see cref="T:System.Net.Topology.NetMask"/> is a reference type, this method is static. If it were not like this, you could change the value of <see cref="T:System.Net.Topology.NetMask"/>.Empty, for example.</remarks>
|
||||
public static NetMask Extend(NetMask mask, int value)
|
||||
{
|
||||
int currentCidr = mask.Cidr;
|
||||
if (currentCidr >= MaskLength * 8)
|
||||
return new NetMask(mask);
|
||||
if (currentCidr <= 0)
|
||||
currentCidr = 0;
|
||||
|
||||
int newLength = Math.Max(Math.Min(currentCidr + value, 32), 0);
|
||||
|
||||
var m = BytesFromCidrValue(newLength);
|
||||
|
||||
return new NetMask(m);
|
||||
}
|
||||
|
||||
/// <summary>Abbreviates the current <see cref="T:System.Net.Topology.NetMask"/> instance by a given value (CIDR-wise).</summary>
|
||||
/// <param name="mask">The mask to use as a reference.</param>
|
||||
/// <param name="value">The value.</param>
|
||||
/// <remarks>Because <see cref="T:System.Net.Topology.NetMask"/> is a reference type, this method is static. If it were not like this, you could change the value of <see cref="T:System.Net.Topology.NetMask"/>.Empty, for example.</remarks>
|
||||
public static NetMask Abbreviate(NetMask mask, int value)
|
||||
{
|
||||
int currentCidr = mask.Cidr;
|
||||
if (currentCidr < 1)
|
||||
return new NetMask(mask);
|
||||
if (currentCidr >= MaskLength * 8)
|
||||
currentCidr = MaskLength * 8;
|
||||
|
||||
int newLength = Math.Max(Math.Min(currentCidr - value, 32), 0);
|
||||
|
||||
var m = BytesFromCidrValue(newLength);
|
||||
return new NetMask(m);
|
||||
}
|
||||
|
||||
/// <summary>Returns a value indicating whether the given array of <see cref="T:System.Byte"/> represents a valid net mask.</summary>
|
||||
/// <returns>True if the given array of <see cref="T:System.Byte"/> represents a valid net mask, otherwise false.</returns>
|
||||
public static bool GetIsValidNetMask(byte[] mask) => mask.RepresentsValidNetMask();
|
||||
|
||||
// TODO: Testing(!)
|
||||
[Obsolete]
|
||||
private static byte[] BytesFromCidrValue(int cidr)
|
||||
{
|
||||
int target = MaskLength * 8 - cidr;
|
||||
int mask = 0;
|
||||
for (int i = 0; i < target; ++i)
|
||||
{
|
||||
mask >>= 1;
|
||||
mask |= unchecked((int)0x80000000);
|
||||
}
|
||||
var bytes = BitConverter.GetBytes(~mask);
|
||||
return new[] {
|
||||
bytes[0].ReverseBits(),
|
||||
bytes[1].ReverseBits(),
|
||||
bytes[2].ReverseBits(),
|
||||
bytes[3].ReverseBits()
|
||||
};
|
||||
}
|
||||
|
||||
// TODO: Testing(!)
|
||||
private static uint GetUIntFromCidrValue(int cidr) => UIntExtensions.CreateWithOnesFromLeft(cidr);
|
||||
|
||||
#region Operators
|
||||
|
||||
#region Equality
|
||||
|
||||
/// <summary>Returns a other indicating whether two instances of <see cref="T:System.Net.Topology.NetMask" /> are equal.</summary>
|
||||
/// <param name="n1">The first other to compare.</param>
|
||||
/// <param name="n2">The second other to compare.</param>
|
||||
/// <returns>true if <paramref name="n1" /> and <paramref name="n2" /> are equal; otherwise, false.</returns>
|
||||
public static bool operator ==(NetMask n1, NetMask n2)
|
||||
{
|
||||
if (ReferenceEquals(n1, n2))
|
||||
return true;
|
||||
if (((object)n1 == null) || ((object)n2 == null))
|
||||
return false;
|
||||
return n1.Equals(n2);
|
||||
}
|
||||
|
||||
/// <summary>Returns a other indicating whether two instances of <see cref="T:System.Net.Topology.NetMask" /> are not equal.</summary>
|
||||
/// <param name="n1">The first other to compare. </param>
|
||||
/// <param name="n2">The second other to compare. </param>
|
||||
/// <returns>true if <paramref name="n1" /> and <paramref name="n2" /> are not equal; otherwise, false.</returns>
|
||||
public static bool operator !=(NetMask n1, NetMask n2) => !(n1 == n2); // Problem solved
|
||||
|
||||
#endregion
|
||||
#region And
|
||||
|
||||
/// <summary>Bitwise combines a <see cref="T:System.Net.Topology.NetMask" /> instance and an <see cref="T:System.Net.IPAddress"/> the AND operation.</summary>
|
||||
/// <param name="mask">The net mask.</param>
|
||||
/// <param name="address">The IPAddress.</param>
|
||||
/// <returns>The bitwised combination using the AND operation.</returns>
|
||||
public static IPAddress operator &(IPAddress address, NetMask mask) => mask & address;
|
||||
|
||||
/// <summary>Bitwise combines a <see cref="T:System.Net.Topology.NetMask" /> instance and an <see cref="T:System.Net.IPAddress"/> the AND operation.</summary>
|
||||
/// <param name="mask">The net mask.</param>
|
||||
/// <param name="address">The IPAddress.</param>
|
||||
/// <returns>The bitwised combination using the AND operation.</returns>
|
||||
public static IPAddress BitwiseAnd(IPAddress address, NetMask mask) => mask & address;
|
||||
|
||||
/// <summary>Bitwise combines a <see cref="T:System.Net.Topology.NetMask" /> instance and an <see cref="T:System.Net.IPAddress"/> the AND operation.</summary>
|
||||
/// <param name="mask">The net mask.</param>
|
||||
/// <param name="address">The IPAddress.</param>
|
||||
/// <returns>The bitwised combination using the AND operation.</returns>
|
||||
public static IPAddress operator &(NetMask mask, IPAddress address)
|
||||
{
|
||||
var ipBytes = address == null
|
||||
? new byte[MaskLength]
|
||||
: address.GetAddressBytes();
|
||||
var maskBytes = mask == null
|
||||
? new byte[MaskLength]
|
||||
: new byte[] { mask._maskB0, mask._maskB1, mask._maskB2, mask._maskB3 };
|
||||
|
||||
byte[] combinedBytes = maskBytes.And(ipBytes);
|
||||
return new IPAddress(combinedBytes);
|
||||
}
|
||||
|
||||
/// <summary>Bitwise combines a <see cref="T:System.Net.Topology.NetMask" /> instance and an <see cref="T:System.Net.IPAddress"/> the AND operation.</summary>
|
||||
/// <param name="mask">The net mask.</param>
|
||||
/// <param name="address">The IPAddress.</param>
|
||||
/// <returns>The bitwised combination using the AND operation.</returns>
|
||||
public static IPAddress BitwiseAnd(NetMask mask, IPAddress address) => mask & address;
|
||||
|
||||
/// <summary>Bitwise combines the two instances of <see cref="T:System.Net.Topology.NetMask" /> using the AND operation.</summary>
|
||||
/// <param name="n1">The first other.</param>
|
||||
/// <param name="n2">The second other.</param>
|
||||
/// <returns>The bitwised combination using the AND operation.</returns>
|
||||
public static NetMask operator &(NetMask n1, NetMask n2) => new NetMask(n1._mask & n2._mask);
|
||||
|
||||
/// <summary>Bitwise combines the two instances of <see cref="T:System.Net.Topology.NetMask" /> using the AND operation.</summary>
|
||||
/// <param name="n1">The first other.</param>
|
||||
/// <param name="n2">The second other.</param>
|
||||
/// <returns>The bitwised combination using the AND operation.</returns>
|
||||
public static NetMask BitwiseAnd(NetMask n1, NetMask n2) => n1 & n2;
|
||||
|
||||
#endregion
|
||||
#region Or
|
||||
|
||||
/// <summary>Bitwise combines the two instances of <see cref="T:System.Net.Topology.NetMask" /> using the OR operation.</summary>
|
||||
/// <param name="n1">The first other.</param>
|
||||
/// <param name="n2">The second other.</param>
|
||||
/// <returns>The bitwised combination using the OR operation.</returns>
|
||||
public static NetMask operator |(NetMask n1, NetMask n2) => new NetMask(n1._mask | n2._mask);
|
||||
|
||||
/// <summary>Bitwise combines the two instances of <see cref="T:System.Net.Topology.NetMask" /> using the OR operation.</summary>
|
||||
/// <param name="n1">The first other.</param>
|
||||
/// <param name="n2">The second other.</param>
|
||||
/// <returns>The bitwised combination using the OR operation.</returns>
|
||||
public static NetMask BitwiseOr(NetMask n1, NetMask n2) => n1 | n2;
|
||||
|
||||
#endregion
|
||||
|
||||
#endregion
|
||||
#region Common overrides
|
||||
|
||||
/// <summary>Converts the other of this instance to its equivalent string representation.</summary>
|
||||
/// <returns>A string that represents the other of this instance.</returns>
|
||||
/// <filterpriority>1</filterpriority>
|
||||
public override string ToString()
|
||||
{
|
||||
var sb = new StringBuilder(4 * 3 + 3 * 3 + 32 + 3 + 3); // 255.255.255.255 (11111111111111111111111111111111)
|
||||
|
||||
var arr = new byte[] { _maskB0, _maskB1, _maskB2, _maskB3 };
|
||||
var asString = arr.ToBinaryString('.');
|
||||
|
||||
sb.Append(arr[0]).Append('.').Append(arr[1]).Append('.').Append(arr[2]).Append('.').Append(arr[3]).Append(" (");
|
||||
sb.Append(asString).Append(')');
|
||||
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
/// <summary>Returns a value indicating whether this instance and a specified <see cref="T:System.Object" /> represent the same type and other.</summary>
|
||||
/// <returns>true if <paramref name="obj" /> is a <see cref="T:System.Net.Topology.NetMask" /> and equal to this instance; otherwise, false.</returns>
|
||||
/// <param name="obj">The object to compare with this instance. </param>
|
||||
/// <filterpriority>2</filterpriority>
|
||||
public override bool Equals(object obj) => obj != null && obj is NetMask && Equals((NetMask)obj);
|
||||
|
||||
/// <summary>Returns a value indicating whether this instance and a specified <see cref="T:System.Net.Topology.NetMask" /> object represent the same other.</summary>
|
||||
/// <returns>true if <paramref name="other" /> is equal to this instance; otherwise, false.</returns>
|
||||
/// <param name="other">An object to compare to this instance.</param>
|
||||
/// <filterpriority>2</filterpriority>
|
||||
public bool Equals(NetMask other) => other._mask == _mask;
|
||||
|
||||
/// <summary>Returns the hash code for this instance.</summary>
|
||||
/// <returns>A 32-bit signed integer hash code.</returns>
|
||||
/// <filterpriority>2</filterpriority>
|
||||
public override int GetHashCode() => unchecked((int)_mask);
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
|
||||
namespace System.Net.Topology
|
||||
{
|
||||
/// <summary>Provides extension methods for the <see cref="T:System.Net.Topology.NetMask"/>.</summary>
|
||||
public static class NetMaskExtensions
|
||||
{
|
||||
/// <summary>Gets the number of siblings an <see cref="T:System.Net.IPAddress"/> can have in a given network. Compliant to RFC 950 (2^n-2).</summary>
|
||||
/// <param name="mask">The net mask of the network</param>
|
||||
/// <returns>The number of siblings an <see cref="T:System.Net.IPAddress"/> can have in the given network.</returns>
|
||||
public static int GetSiblingCount(this NetMask mask) => GetSiblingCount(mask, SiblingOptions.ExcludeUnusable);
|
||||
|
||||
/// <summary>Gets the number of siblings an <see cref="T:System.Net.IPAddress"/> can have in a given network.</summary>
|
||||
/// <param name="mask">The net mask of the network</param>
|
||||
/// <param name="options">Options which addresses to include an which not</param>
|
||||
/// <returns>The number of siblings an <see cref="T:System.Net.IPAddress"/> can have in the given network.</returns>
|
||||
public static int GetSiblingCount(this NetMask mask, SiblingOptions options)
|
||||
{
|
||||
if (mask == null)
|
||||
throw new ArgumentNullException(nameof(mask));
|
||||
|
||||
bool includeSelf = BitHelper.IsOptionSet(options, SiblingOptions.IncludeSelf);
|
||||
bool includeBroadcast = BitHelper.IsOptionSet(options, SiblingOptions.IncludeBroadcast);
|
||||
bool includeNetworkIdentifier = BitHelper.IsOptionSet(options, SiblingOptions.IncludeNetworkIdentifier);
|
||||
|
||||
var hostPartBits = mask.GetMaskBytes().CountFromRight(false);
|
||||
var total = 1 << hostPartBits;
|
||||
total -= includeSelf ? 0 : 1;
|
||||
total -= includeBroadcast ? 0 : 1;
|
||||
total -= includeNetworkIdentifier ? 0 : 1;
|
||||
|
||||
// TODO: Testing
|
||||
|
||||
return total;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
namespace System.Net.Topology
|
||||
{
|
||||
/// <summary>Provides options for doing network sibling calculations using a net mask.</summary>
|
||||
[Flags]
|
||||
public enum SiblingOptions
|
||||
{
|
||||
/// <summary>Do not include the broadcast or net address neither the addess passed to the method.</summary>
|
||||
ExcludeAll = 0,
|
||||
/// <summary>Include the addess passed to the method.</summary>
|
||||
IncludeSelf = 1,
|
||||
/// <summary>Include the addess passed to the method. Compliant to RFC 950 (2^n-2).</summary>
|
||||
ExcludeUnusable = IncludeSelf,
|
||||
/// <summary>Include the broadcast address.</summary>
|
||||
IncludeBroadcast = 2,
|
||||
/// <summary>Include the net address.</summary>
|
||||
IncludeNetworkIdentifier = 4,
|
||||
/// <summary>Include all addresses possible. RFC 1878 (2^n).</summary>
|
||||
IncludeAll = IncludeSelf | IncludeBroadcast | IncludeNetworkIdentifier
|
||||
}
|
||||
|
||||
internal static class BitHelper
|
||||
{
|
||||
[Runtime.TargetedPatchingOptOut("Performance critical to inline across NGen image boundaries")] // as if NGen will ever compile this assembly ;)
|
||||
[Runtime.CompilerServices.MethodImpl(Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
|
||||
internal static bool IsOptionSet(SiblingOptions value, SiblingOptions testValue) => (value & testValue) == testValue;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
|
||||
namespace System.Net.Topology
|
||||
{
|
||||
internal static class StringExtensions
|
||||
{
|
||||
// TODO: The following method uses unsafe stuff. We don't want to pass the /unsafe flag to the compiler, so we use a simple, safe method instead.
|
||||
// As soon as .NET Standard with Span<T> and the new String.Create is available, we can make this faster and safe.
|
||||
/*
|
||||
internal static unsafe string Reverse(this string input)
|
||||
{
|
||||
int len = input.Length;
|
||||
|
||||
// Why allocate a char[] array on the heap when you won't use it
|
||||
// outside of this method? Use the stack.
|
||||
char* reversed = stackalloc char[len];
|
||||
|
||||
// Avoid bounds-checking performance penalties.
|
||||
fixed (char* str = input)
|
||||
{
|
||||
int i = 0;
|
||||
int j = i + len - 1;
|
||||
while (i < len)
|
||||
reversed[i++] = str[j--];
|
||||
}
|
||||
|
||||
// Need to use this overload for the System.String constructor
|
||||
// as providing just the char* pointer could result in garbage
|
||||
// at the end of the string (no guarantee of null terminator).
|
||||
return new string(reversed, 0, len);
|
||||
}
|
||||
*/
|
||||
internal static string Reverse(this string input)
|
||||
{
|
||||
char[] chars = input.ToCharArray();
|
||||
Array.Reverse(chars);
|
||||
return new string(chars);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Text;
|
||||
|
||||
namespace System.Net.Topology
|
||||
{
|
||||
internal static class UIntExtensions
|
||||
{
|
||||
// TODO: Tests
|
||||
public static int CountOnesFromLeft(this uint value)
|
||||
{
|
||||
var occurences = 0;
|
||||
for (uint i = 1u << 31; i >= 0; i >>= 1)
|
||||
{
|
||||
if ((i & value) != 0)
|
||||
++occurences;
|
||||
else
|
||||
break;
|
||||
}
|
||||
return occurences;
|
||||
}
|
||||
|
||||
// TODO: Tests
|
||||
public static uint CreateWithOnesFromLeft(int count)
|
||||
{
|
||||
if (count > 32)
|
||||
throw new ArgumentException("Cannot set more than 32 bits to one!");
|
||||
|
||||
var value = 0u;
|
||||
|
||||
var mask = 1u << 31;
|
||||
for (int i = 0; i < count; ++i)
|
||||
{
|
||||
value |= mask;
|
||||
mask >>= 1;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netstandard2.0</TargetFramework>
|
||||
<Authors>Niklas Mollenhauer</Authors>
|
||||
<PackageVersion>2.0.2</PackageVersion>
|
||||
<Description>Library for Sending magic packets and performing IP address operations.</Description>
|
||||
<PackageLicenseExpression>LGPL-3.0-only</PackageLicenseExpression>
|
||||
<PackageProjectUrl>https://github.com/nikeee/wake-on-lan</PackageProjectUrl>
|
||||
<RepositoryUrl>https://github.com/nikeee/wake-on-lan.git</RepositoryUrl>
|
||||
<PackageTags>WakeOnLan, magic packets</PackageTags>
|
||||
<GeneratePackageOnBuild>True</GeneratePackageOnBuild>
|
||||
<RootNamespace>System.Net</RootNamespace>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
<LangVersion>latest</LangVersion>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.CSharp" Version="4.6.0" />
|
||||
<PackageReference Include="System.Runtime.Serialization.Formatters" Version="4.3.0" />
|
||||
<PackageReference Include="System.ValueTuple" Version="4.5.0" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
Reference in new issue
Block a user