Skip to content

Smdn.Net.AddressResolution version 1.0.1

Compare
Choose a tag to compare
@smdn smdn released this 02 May 12:49
· 47 commits to main since this release
c7f3065

Released package

Release notes

The full release notes are available at gist.

Change log

Change log in this release:

API changes

API changes in this release:
diff --git a/doc/api-list/Smdn.Net.AddressResolution/Smdn.Net.AddressResolution-net6.0.apilist.cs b/doc/api-list/Smdn.Net.AddressResolution/Smdn.Net.AddressResolution-net6.0.apilist.cs
index 45fe092..f8fac88 100644
--- a/doc/api-list/Smdn.Net.AddressResolution/Smdn.Net.AddressResolution-net6.0.apilist.cs
+++ b/doc/api-list/Smdn.Net.AddressResolution/Smdn.Net.AddressResolution-net6.0.apilist.cs
@@ -1,295 +1,299 @@
-// Smdn.Net.AddressResolution.dll (Smdn.Net.AddressResolution-1.0.0)
+// Smdn.Net.AddressResolution.dll (Smdn.Net.AddressResolution-1.0.1)
 //   Name: Smdn.Net.AddressResolution
-//   AssemblyVersion: 1.0.0.0
-//   InformationalVersion: 1.0.0+b2ffdef7b9a768c14df101d2076bc63c12331f73
+//   AssemblyVersion: 1.0.1.0
+//   InformationalVersion: 1.0.1+12cda679d681acbeb81dac8a0cb03dbf6a3a0a3d
 //   TargetFramework: .NETCoreApp,Version=v6.0
 //   Configuration: Release
 //   Referenced assemblies:
 //     Microsoft.Extensions.DependencyInjection.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60
 //     Microsoft.Extensions.Logging.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60
 //     System.Collections, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
 //     System.Collections.Concurrent, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
 //     System.ComponentModel, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
 //     System.ComponentModel.Primitives, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
 //     System.Diagnostics.Process, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
 //     System.Linq, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
 //     System.Memory, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51
 //     System.Net.NetworkInformation, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
 //     System.Net.Ping, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
 //     System.Net.Primitives, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
 //     System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
 //     System.Runtime.InteropServices, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
 //     System.Runtime.InteropServices.RuntimeInformation, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
 //     System.Threading, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
 //     Vanara.PInvoke.IpHlpApi, Version=3.4.13.0, Culture=neutral, PublicKeyToken=c37e4080322237fa
 //     Vanara.PInvoke.Shared, Version=3.4.13.0, Culture=neutral, PublicKeyToken=c37e4080322237fa
 //     Vanara.PInvoke.Ws2_32, Version=3.4.13.0, Culture=neutral, PublicKeyToken=c37e4080322237fa
 #nullable enable annotations
 
 using System;
 using System.Collections.Generic;
 using System.Diagnostics;
 using System.Diagnostics.CodeAnalysis;
 using System.Net;
 using System.Net.NetworkInformation;
 using System.Runtime.CompilerServices;
 using System.Threading;
 using System.Threading.Tasks;
 using Microsoft.Extensions.Logging;
 using Smdn.Net;
 using Smdn.Net.AddressResolution;
 using Smdn.Net.AddressTables;
 using Smdn.Net.NetworkScanning;
 
 namespace Smdn.Net {
   public abstract class IPNetworkProfile {
     public static IPNetworkProfile Create() {}
     public static IPNetworkProfile Create(Func<IEnumerable<IPAddress>?> addressRangeGenerator, NetworkInterface? networkInterface = null) {}
     public static IPNetworkProfile Create(IPAddress baseAddress, IPAddress subnetMask, NetworkInterface? networkInterface = null) {}
     public static IPNetworkProfile Create(IPAddress baseAddress, int prefixLength, NetworkInterface? networkInterface = null) {}
     public static IPNetworkProfile Create(NetworkInterface networkInterface) {}
     public static IPNetworkProfile Create(Predicate<NetworkInterface> predicateForNetworkInterface) {}
+    public static IPNetworkProfile CreateFromNetworkInterface(Guid id) {}
+    public static IPNetworkProfile CreateFromNetworkInterface(PhysicalAddress physicalAddress) {}
+    public static IPNetworkProfile CreateFromNetworkInterface(string id) {}
+    public static IPNetworkProfile CreateFromNetworkInterfaceName(string name) {}
 
     protected IPNetworkProfile(NetworkInterface? networkInterface) {}
 
     public NetworkInterface? NetworkInterface { get; }
 
     public abstract IEnumerable<IPAddress>? GetAddressRange();
   }
 
   public static class PhysicalAddressExtensions {
     public static string ToMacAddressString(this PhysicalAddress hardwareAddress, char delimiter = ':') {}
   }
 }
 
 namespace Smdn.Net.AddressResolution {
   public interface IAddressResolver<TAddress, TResolvedAddress> where TAddress : notnull where TResolvedAddress : notnull {
     void Invalidate(TAddress address);
     ValueTask<TResolvedAddress?> ResolveAsync(TAddress address, CancellationToken cancellationToken);
   }
 
   public class MacAddressResolver : MacAddressResolverBase {
     protected MacAddressResolver(IAddressTable addressTable, bool shouldDisposeAddressTable, INetworkScanner? networkScanner, bool shouldDisposeNetworkScanner, NetworkInterface? networkInterface, int maxParallelCountForRefreshInvalidatedAddresses, ILogger? logger) {}
     public MacAddressResolver() {}
     public MacAddressResolver(IAddressTable? addressTable, INetworkScanner? networkScanner, bool shouldDisposeAddressTable = false, bool shouldDisposeNetworkScanner = false, NetworkInterface? networkInterface = null, int maxParallelCountForRefreshInvalidatedAddresses = 3, IServiceProvider? serviceProvider = null) {}
     public MacAddressResolver(IPNetworkProfile? networkProfile, IServiceProvider? serviceProvider = null) {}
 
     public bool CanPerformNetworkScan { get; }
     public override bool HasInvalidated { get; }
     public TimeSpan NetworkScanInterval { get; set; }
     public TimeSpan NetworkScanMinInterval { get; set; }
 
     protected override void Dispose(bool disposing) {}
     public IAsyncEnumerable<AddressTableEntry> EnumerateAddressTableEntriesAsync(CancellationToken cancellationToken = default) {}
     public IAsyncEnumerable<AddressTableEntry> EnumerateAddressTableEntriesAsync(Predicate<AddressTableEntry> predicate, CancellationToken cancellationToken = default) {}
     protected override void InvalidateCore(IPAddress ipAddress) {}
     protected override void InvalidateCore(PhysicalAddress macAddress) {}
     protected override ValueTask RefreshAddressTableAsyncCore(CancellationToken cancellationToken = default) {}
     protected override ValueTask RefreshInvalidatedAddressesAsyncCore(CancellationToken cancellationToken = default) {}
     protected override async ValueTask<PhysicalAddress?> ResolveIPAddressToMacAddressAsyncCore(IPAddress ipAddress, CancellationToken cancellationToken) {}
     protected override async ValueTask<IPAddress?> ResolveMacAddressToIPAddressAsyncCore(PhysicalAddress macAddress, CancellationToken cancellationToken) {}
     protected virtual async ValueTask<AddressTableEntry> SelectAddressTableEntryAsync(Predicate<AddressTableEntry> predicate, CancellationToken cancellationToken) {}
   }
 
   public abstract class MacAddressResolverBase :
     IAddressResolver<IPAddress, PhysicalAddress>,
     IAddressResolver<PhysicalAddress, IPAddress>,
     IDisposable
   {
     protected static PhysicalAddress AllZeroMacAddress { get; }
     public static MacAddressResolverBase Null { get; }
 
     protected MacAddressResolverBase(ILogger? logger = null) {}
 
     public abstract bool HasInvalidated { get; }
     protected ILogger? Logger { get; }
 
     protected virtual void Dispose(bool disposing) {}
     public void Dispose() {}
     public void Invalidate(IPAddress ipAddress) {}
     public void Invalidate(PhysicalAddress macAddress) {}
     protected abstract void InvalidateCore(IPAddress ipAddress);
     protected abstract void InvalidateCore(PhysicalAddress macAddress);
     public ValueTask RefreshAddressTableAsync(CancellationToken cancellationToken = default) {}
     protected virtual ValueTask RefreshAddressTableAsyncCore(CancellationToken cancellationToken) {}
     public ValueTask RefreshInvalidatedAddressesAsync(CancellationToken cancellationToken = default) {}
     protected virtual ValueTask RefreshInvalidatedAddressesAsyncCore(CancellationToken cancellationToken) {}
     public ValueTask<PhysicalAddress?> ResolveIPAddressToMacAddressAsync(IPAddress ipAddress, CancellationToken cancellationToken = default) {}
     protected abstract ValueTask<PhysicalAddress?> ResolveIPAddressToMacAddressAsyncCore(IPAddress ipAddress, CancellationToken cancellationToken);
     public ValueTask<IPAddress?> ResolveMacAddressToIPAddressAsync(PhysicalAddress macAddress, CancellationToken cancellationToken = default) {}
     protected abstract ValueTask<IPAddress?> ResolveMacAddressToIPAddressAsyncCore(PhysicalAddress macAddress, CancellationToken cancellationToken);
     void IAddressResolver<IPAddress, PhysicalAddress>.Invalidate(IPAddress address) {}
     ValueTask<PhysicalAddress?> IAddressResolver<IPAddress, PhysicalAddress>.ResolveAsync(IPAddress address, CancellationToken cancellationToken) {}
     void IAddressResolver<PhysicalAddress, IPAddress>.Invalidate(PhysicalAddress address) {}
     ValueTask<IPAddress?> IAddressResolver<PhysicalAddress, IPAddress>.ResolveAsync(PhysicalAddress address, CancellationToken cancellationToken) {}
     protected void ThrowIfDisposed() {}
   }
 }
 
 namespace Smdn.Net.AddressTables {
   public interface IAddressTable : IDisposable {
     IAsyncEnumerable<AddressTableEntry> EnumerateEntriesAsync(CancellationToken cancellationToken);
   }
 
   public enum AddressTableEntryState : int {
     Delay = 4,
     Incomplete = 1,
     None = 0,
     Probe = 5,
     Reachable = 2,
     Stale = 3,
   }
 
   public abstract class AddressTable : IAddressTable {
     public static IAddressTable Null { get; }
 
     public static IAddressTable Create(IServiceProvider? serviceProvider = null) {}
 
     protected AddressTable(ILogger? logger = null) {}
 
     protected ILogger? Logger { get; }
 
     protected virtual void Dispose(bool disposing) {}
     public void Dispose() {}
     public IAsyncEnumerable<AddressTableEntry> EnumerateEntriesAsync(CancellationToken cancellationToken = default) {}
     protected abstract IAsyncEnumerable<AddressTableEntry> EnumerateEntriesAsyncCore(CancellationToken cancellationToken);
     protected void ThrowIfDisposed() {}
   }
 
   public sealed class IpHlpApiAddressTable : AddressTable {
     public static bool IsSupported { get; }
 
     public IpHlpApiAddressTable(IServiceProvider? serviceProvider = null) {}
 
     [AsyncIteratorStateMachine(typeof(IpHlpApiAddressTable.<EnumerateEntriesAsyncCore>d__4))]
     protected override IAsyncEnumerable<AddressTableEntry> EnumerateEntriesAsyncCore([EnumeratorCancellation] CancellationToken cancellationToken) {}
   }
 
   public sealed class ProcfsArpAddressTable : AddressTable {
     public static bool IsSupported { get; }
 
     public ProcfsArpAddressTable(IServiceProvider? serviceProvider = null) {}
 
     [AsyncIteratorStateMachine(typeof(ProcfsArpAddressTable.<EnumerateEntriesAsyncCore>d__5))]
     protected override IAsyncEnumerable<AddressTableEntry> EnumerateEntriesAsyncCore([EnumeratorCancellation] CancellationToken cancellationToken) {}
   }
 
   public readonly struct AddressTableEntry :
     IEquatable<AddressTableEntry>,
     IEquatable<IPAddress>,
     IEquatable<PhysicalAddress>
   {
     public static readonly AddressTableEntry Empty; // = "{IP=, MAC=(null), IsPermanent=False, State=None, Iface=}"
 
     public static IEqualityComparer<AddressTableEntry> DefaultEqualityComparer { get; }
     public static IEqualityComparer<AddressTableEntry> ExceptStateEqualityComparer { get; }
 
     public AddressTableEntry(IPAddress ipAddress, PhysicalAddress? physicalAddress, bool isPermanent, AddressTableEntryState state, string? interfaceId) {}
 
     public IPAddress? IPAddress { get; }
     public string? InterfaceId { get; }
     [MemberNotNullWhen(false, "IPAddress")]
     public bool IsEmpty { [MemberNotNullWhen(false, "IPAddress")] get; }
     public bool IsPermanent { get; }
     public PhysicalAddress? PhysicalAddress { get; }
     public AddressTableEntryState State { get; }
 
     public bool Equals(AddressTableEntry other) {}
     public bool Equals(IPAddress? other) {}
     public bool Equals(PhysicalAddress? other) {}
     public override bool Equals(object? obj) {}
     public override int GetHashCode() {}
     public override string ToString() {}
   }
 }
 
 namespace Smdn.Net.NetworkScanning {
   public interface INetworkScanner : IDisposable {
     ValueTask ScanAsync(CancellationToken cancellationToken);
     ValueTask ScanAsync(IEnumerable<IPAddress> addresses, CancellationToken cancellationToken);
   }
 
   public sealed class ArpScanCommandNetworkScanner : CommandNetworkScanner {
     public static bool IsSupported { get; }
 
     public ArpScanCommandNetworkScanner(IPNetworkProfile? networkProfile, IServiceProvider? serviceProvider = null) {}
 
     protected override bool GetCommandLineArguments(IEnumerable<IPAddress> addressesToScan, out string executable, out string arguments) {}
     protected override bool GetCommandLineArguments(out string executable, out string arguments) {}
   }
 
   public abstract class CommandNetworkScanner : INetworkScanner {
     public interface IProcessFactory {
       Process CreateProcess(ProcessStartInfo processStartInfo);
     }
 
     protected readonly struct Command {
       public Command(string name, string? executablePath) {}
 
       public bool IsAvailable { get; }
       public string Name { get; }
 
       public string GetExecutablePathOrThrow() {}
     }
 
     protected static IReadOnlyCollection<string> DefaultCommandPaths { get; }
 
     protected static CommandNetworkScanner.Command FindCommand(string command, IEnumerable<string> paths) {}
 
     protected CommandNetworkScanner(ILogger? logger, IServiceProvider? serviceProvider) {}
 
     protected virtual void Dispose(bool disposing) {}
     public void Dispose() {}
     protected abstract bool GetCommandLineArguments(IEnumerable<IPAddress> addressesToScan, out string executable, out string? arguments);
     protected abstract bool GetCommandLineArguments(out string executable, out string? arguments);
     public virtual ValueTask ScanAsync(CancellationToken cancellationToken = default) {}
     public virtual ValueTask ScanAsync(IEnumerable<IPAddress> addresses, CancellationToken cancellationToken = default) {}
     protected void ThrowIfDisposed() {}
   }
 
   public sealed class IpHlpApiNetworkScanner : NetworkScanner {
     public static bool IsSupported { get; }
 
     public IpHlpApiNetworkScanner(IPNetworkProfile networkProfile, IServiceProvider? serviceProvider = null) {}
 
     protected override async ValueTask ScanAsyncCore(IPAddress address, CancellationToken cancellationToken = default) {}
   }
 
   public abstract class NetworkScanner : INetworkScanner {
     public static INetworkScanner Null { get; }
 
     public static INetworkScanner Create(IPNetworkProfile? networkProfile, IServiceProvider? serviceProvider = null) {}
 
     protected NetworkScanner(IPNetworkProfile networkProfile, ILogger? logger = null) {}
 
     protected ILogger? Logger { get; }
     protected IPNetworkProfile NetworkProfile { get; }
 
     protected virtual void Dispose(bool disposing) {}
     public void Dispose() {}
     public virtual ValueTask ScanAsync(CancellationToken cancellationToken = default) {}
     public virtual ValueTask ScanAsync(IEnumerable<IPAddress> addresses, CancellationToken cancellationToken = default) {}
     protected virtual ValueTask ScanAsyncCore(IPAddress address, CancellationToken cancellationToken) {}
     protected void ThrowIfDisposed() {}
   }
 
   public sealed class NmapCommandNetworkScanner : CommandNetworkScanner {
     public static bool IsSupported { get; }
 
     public NmapCommandNetworkScanner(IPNetworkProfile networkProfile, IServiceProvider? serviceProvider = null) {}
 
     protected override bool GetCommandLineArguments(IEnumerable<IPAddress> addressesToScan, out string executable, out string arguments) {}
     protected override bool GetCommandLineArguments(out string executable, out string arguments) {}
   }
 
   public sealed class PingNetworkScanner : NetworkScanner {
     public static bool IsSupported { get; }
 
     public PingNetworkScanner(IPNetworkProfile networkProfile, IServiceProvider? serviceProvider = null) {}
 
     protected override void Dispose(bool disposing) {}
     protected override async ValueTask ScanAsyncCore(IPAddress address, CancellationToken cancellationToken = default) {}
   }
 }
 // API list generated by Smdn.Reflection.ReverseGenerating.ListApi.MSBuild.Tasks v1.2.1.0.
 // Smdn.Reflection.ReverseGenerating.ListApi.Core v1.2.0.0 (https://github.com/smdn/Smdn.Reflection.ReverseGenerating)
diff --git a/doc/api-list/Smdn.Net.AddressResolution/Smdn.Net.AddressResolution-net7.0.apilist.cs b/doc/api-list/Smdn.Net.AddressResolution/Smdn.Net.AddressResolution-net7.0.apilist.cs
index 3ac24fa..a813ee7 100644
--- a/doc/api-list/Smdn.Net.AddressResolution/Smdn.Net.AddressResolution-net7.0.apilist.cs
+++ b/doc/api-list/Smdn.Net.AddressResolution/Smdn.Net.AddressResolution-net7.0.apilist.cs
@@ -1,294 +1,298 @@
-// Smdn.Net.AddressResolution.dll (Smdn.Net.AddressResolution-1.0.0)
+// Smdn.Net.AddressResolution.dll (Smdn.Net.AddressResolution-1.0.1)
 //   Name: Smdn.Net.AddressResolution
-//   AssemblyVersion: 1.0.0.0
-//   InformationalVersion: 1.0.0+b2ffdef7b9a768c14df101d2076bc63c12331f73
+//   AssemblyVersion: 1.0.1.0
+//   InformationalVersion: 1.0.1+12cda679d681acbeb81dac8a0cb03dbf6a3a0a3d
 //   TargetFramework: .NETCoreApp,Version=v7.0
 //   Configuration: Release
 //   Referenced assemblies:
 //     Microsoft.Extensions.DependencyInjection.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60
 //     Microsoft.Extensions.Logging.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60
 //     System.Collections, Version=7.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
 //     System.Collections.Concurrent, Version=7.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
 //     System.ComponentModel, Version=7.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
 //     System.ComponentModel.Primitives, Version=7.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
 //     System.Diagnostics.Process, Version=7.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
 //     System.Linq, Version=7.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
 //     System.Memory, Version=7.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51
 //     System.Net.NetworkInformation, Version=7.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
 //     System.Net.Ping, Version=7.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
 //     System.Net.Primitives, Version=7.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
 //     System.Runtime, Version=7.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
 //     System.Runtime.InteropServices, Version=7.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
 //     System.Threading, Version=7.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
 //     Vanara.PInvoke.IpHlpApi, Version=3.4.13.0, Culture=neutral, PublicKeyToken=c37e4080322237fa
 //     Vanara.PInvoke.Shared, Version=3.4.13.0, Culture=neutral, PublicKeyToken=c37e4080322237fa
 //     Vanara.PInvoke.Ws2_32, Version=3.4.13.0, Culture=neutral, PublicKeyToken=c37e4080322237fa
 #nullable enable annotations
 
 using System;
 using System.Collections.Generic;
 using System.Diagnostics;
 using System.Diagnostics.CodeAnalysis;
 using System.Net;
 using System.Net.NetworkInformation;
 using System.Runtime.CompilerServices;
 using System.Threading;
 using System.Threading.Tasks;
 using Microsoft.Extensions.Logging;
 using Smdn.Net;
 using Smdn.Net.AddressResolution;
 using Smdn.Net.AddressTables;
 using Smdn.Net.NetworkScanning;
 
 namespace Smdn.Net {
   public abstract class IPNetworkProfile {
     public static IPNetworkProfile Create() {}
     public static IPNetworkProfile Create(Func<IEnumerable<IPAddress>?> addressRangeGenerator, NetworkInterface? networkInterface = null) {}
     public static IPNetworkProfile Create(IPAddress baseAddress, IPAddress subnetMask, NetworkInterface? networkInterface = null) {}
     public static IPNetworkProfile Create(IPAddress baseAddress, int prefixLength, NetworkInterface? networkInterface = null) {}
     public static IPNetworkProfile Create(NetworkInterface networkInterface) {}
     public static IPNetworkProfile Create(Predicate<NetworkInterface> predicateForNetworkInterface) {}
+    public static IPNetworkProfile CreateFromNetworkInterface(Guid id) {}
+    public static IPNetworkProfile CreateFromNetworkInterface(PhysicalAddress physicalAddress) {}
+    public static IPNetworkProfile CreateFromNetworkInterface(string id) {}
+    public static IPNetworkProfile CreateFromNetworkInterfaceName(string name) {}
 
     protected IPNetworkProfile(NetworkInterface? networkInterface) {}
 
     public NetworkInterface? NetworkInterface { get; }
 
     public abstract IEnumerable<IPAddress>? GetAddressRange();
   }
 
   public static class PhysicalAddressExtensions {
     public static string ToMacAddressString(this PhysicalAddress hardwareAddress, char delimiter = ':') {}
   }
 }
 
 namespace Smdn.Net.AddressResolution {
   public interface IAddressResolver<TAddress, TResolvedAddress> where TAddress : notnull where TResolvedAddress : notnull {
     void Invalidate(TAddress address);
     ValueTask<TResolvedAddress?> ResolveAsync(TAddress address, CancellationToken cancellationToken);
   }
 
   public class MacAddressResolver : MacAddressResolverBase {
     protected MacAddressResolver(IAddressTable addressTable, bool shouldDisposeAddressTable, INetworkScanner? networkScanner, bool shouldDisposeNetworkScanner, NetworkInterface? networkInterface, int maxParallelCountForRefreshInvalidatedAddresses, ILogger? logger) {}
     public MacAddressResolver() {}
     public MacAddressResolver(IAddressTable? addressTable, INetworkScanner? networkScanner, bool shouldDisposeAddressTable = false, bool shouldDisposeNetworkScanner = false, NetworkInterface? networkInterface = null, int maxParallelCountForRefreshInvalidatedAddresses = 3, IServiceProvider? serviceProvider = null) {}
     public MacAddressResolver(IPNetworkProfile? networkProfile, IServiceProvider? serviceProvider = null) {}
 
     public bool CanPerformNetworkScan { get; }
     public override bool HasInvalidated { get; }
     public TimeSpan NetworkScanInterval { get; set; }
     public TimeSpan NetworkScanMinInterval { get; set; }
 
     protected override void Dispose(bool disposing) {}
     public IAsyncEnumerable<AddressTableEntry> EnumerateAddressTableEntriesAsync(CancellationToken cancellationToken = default) {}
     public IAsyncEnumerable<AddressTableEntry> EnumerateAddressTableEntriesAsync(Predicate<AddressTableEntry> predicate, CancellationToken cancellationToken = default) {}
     protected override void InvalidateCore(IPAddress ipAddress) {}
     protected override void InvalidateCore(PhysicalAddress macAddress) {}
     protected override ValueTask RefreshAddressTableAsyncCore(CancellationToken cancellationToken = default) {}
     protected override ValueTask RefreshInvalidatedAddressesAsyncCore(CancellationToken cancellationToken = default) {}
     protected override async ValueTask<PhysicalAddress?> ResolveIPAddressToMacAddressAsyncCore(IPAddress ipAddress, CancellationToken cancellationToken) {}
     protected override async ValueTask<IPAddress?> ResolveMacAddressToIPAddressAsyncCore(PhysicalAddress macAddress, CancellationToken cancellationToken) {}
     protected virtual async ValueTask<AddressTableEntry> SelectAddressTableEntryAsync(Predicate<AddressTableEntry> predicate, CancellationToken cancellationToken) {}
   }
 
   public abstract class MacAddressResolverBase :
     IAddressResolver<IPAddress, PhysicalAddress>,
     IAddressResolver<PhysicalAddress, IPAddress>,
     IDisposable
   {
     protected static PhysicalAddress AllZeroMacAddress { get; }
     public static MacAddressResolverBase Null { get; }
 
     protected MacAddressResolverBase(ILogger? logger = null) {}
 
     public abstract bool HasInvalidated { get; }
     protected ILogger? Logger { get; }
 
     protected virtual void Dispose(bool disposing) {}
     public void Dispose() {}
     public void Invalidate(IPAddress ipAddress) {}
     public void Invalidate(PhysicalAddress macAddress) {}
     protected abstract void InvalidateCore(IPAddress ipAddress);
     protected abstract void InvalidateCore(PhysicalAddress macAddress);
     public ValueTask RefreshAddressTableAsync(CancellationToken cancellationToken = default) {}
     protected virtual ValueTask RefreshAddressTableAsyncCore(CancellationToken cancellationToken) {}
     public ValueTask RefreshInvalidatedAddressesAsync(CancellationToken cancellationToken = default) {}
     protected virtual ValueTask RefreshInvalidatedAddressesAsyncCore(CancellationToken cancellationToken) {}
     public ValueTask<PhysicalAddress?> ResolveIPAddressToMacAddressAsync(IPAddress ipAddress, CancellationToken cancellationToken = default) {}
     protected abstract ValueTask<PhysicalAddress?> ResolveIPAddressToMacAddressAsyncCore(IPAddress ipAddress, CancellationToken cancellationToken);
     public ValueTask<IPAddress?> ResolveMacAddressToIPAddressAsync(PhysicalAddress macAddress, CancellationToken cancellationToken = default) {}
     protected abstract ValueTask<IPAddress?> ResolveMacAddressToIPAddressAsyncCore(PhysicalAddress macAddress, CancellationToken cancellationToken);
     void IAddressResolver<IPAddress, PhysicalAddress>.Invalidate(IPAddress address) {}
     ValueTask<PhysicalAddress?> IAddressResolver<IPAddress, PhysicalAddress>.ResolveAsync(IPAddress address, CancellationToken cancellationToken) {}
     void IAddressResolver<PhysicalAddress, IPAddress>.Invalidate(PhysicalAddress address) {}
     ValueTask<IPAddress?> IAddressResolver<PhysicalAddress, IPAddress>.ResolveAsync(PhysicalAddress address, CancellationToken cancellationToken) {}
     protected void ThrowIfDisposed() {}
   }
 }
 
 namespace Smdn.Net.AddressTables {
   public interface IAddressTable : IDisposable {
     IAsyncEnumerable<AddressTableEntry> EnumerateEntriesAsync(CancellationToken cancellationToken);
   }
 
   public enum AddressTableEntryState : int {
     Delay = 4,
     Incomplete = 1,
     None = 0,
     Probe = 5,
     Reachable = 2,
     Stale = 3,
   }
 
   public abstract class AddressTable : IAddressTable {
     public static IAddressTable Null { get; }
 
     public static IAddressTable Create(IServiceProvider? serviceProvider = null) {}
 
     protected AddressTable(ILogger? logger = null) {}
 
     protected ILogger? Logger { get; }
 
     protected virtual void Dispose(bool disposing) {}
     public void Dispose() {}
     public IAsyncEnumerable<AddressTableEntry> EnumerateEntriesAsync(CancellationToken cancellationToken = default) {}
     protected abstract IAsyncEnumerable<AddressTableEntry> EnumerateEntriesAsyncCore(CancellationToken cancellationToken);
     protected void ThrowIfDisposed() {}
   }
 
   public sealed class IpHlpApiAddressTable : AddressTable {
     public static bool IsSupported { get; }
 
     public IpHlpApiAddressTable(IServiceProvider? serviceProvider = null) {}
 
     [AsyncIteratorStateMachine(typeof(IpHlpApiAddressTable.<EnumerateEntriesAsyncCore>d__4))]
     protected override IAsyncEnumerable<AddressTableEntry> EnumerateEntriesAsyncCore([EnumeratorCancellation] CancellationToken cancellationToken) {}
   }
 
   public sealed class ProcfsArpAddressTable : AddressTable {
     public static bool IsSupported { get; }
 
     public ProcfsArpAddressTable(IServiceProvider? serviceProvider = null) {}
 
     [AsyncIteratorStateMachine(typeof(ProcfsArpAddressTable.<EnumerateEntriesAsyncCore>d__5))]
     protected override IAsyncEnumerable<AddressTableEntry> EnumerateEntriesAsyncCore([EnumeratorCancellation] CancellationToken cancellationToken) {}
   }
 
   public readonly struct AddressTableEntry :
     IEquatable<AddressTableEntry>,
     IEquatable<IPAddress>,
     IEquatable<PhysicalAddress>
   {
     public static readonly AddressTableEntry Empty; // = "{IP=, MAC=(null), IsPermanent=False, State=None, Iface=}"
 
     public static IEqualityComparer<AddressTableEntry> DefaultEqualityComparer { get; }
     public static IEqualityComparer<AddressTableEntry> ExceptStateEqualityComparer { get; }
 
     public AddressTableEntry(IPAddress ipAddress, PhysicalAddress? physicalAddress, bool isPermanent, AddressTableEntryState state, string? interfaceId) {}
 
     public IPAddress? IPAddress { get; }
     public string? InterfaceId { get; }
     [MemberNotNullWhen(false, "IPAddress")]
     public bool IsEmpty { [MemberNotNullWhen(false, "IPAddress")] get; }
     public bool IsPermanent { get; }
     public PhysicalAddress? PhysicalAddress { get; }
     public AddressTableEntryState State { get; }
 
     public bool Equals(AddressTableEntry other) {}
     public bool Equals(IPAddress? other) {}
     public bool Equals(PhysicalAddress? other) {}
     public override bool Equals(object? obj) {}
     public override int GetHashCode() {}
     public override string ToString() {}
   }
 }
 
 namespace Smdn.Net.NetworkScanning {
   public interface INetworkScanner : IDisposable {
     ValueTask ScanAsync(CancellationToken cancellationToken);
     ValueTask ScanAsync(IEnumerable<IPAddress> addresses, CancellationToken cancellationToken);
   }
 
   public sealed class ArpScanCommandNetworkScanner : CommandNetworkScanner {
     public static bool IsSupported { get; }
 
     public ArpScanCommandNetworkScanner(IPNetworkProfile? networkProfile, IServiceProvider? serviceProvider = null) {}
 
     protected override bool GetCommandLineArguments(IEnumerable<IPAddress> addressesToScan, out string executable, out string arguments) {}
     protected override bool GetCommandLineArguments(out string executable, out string arguments) {}
   }
 
   public abstract class CommandNetworkScanner : INetworkScanner {
     public interface IProcessFactory {
       Process CreateProcess(ProcessStartInfo processStartInfo);
     }
 
     protected readonly struct Command {
       public Command(string name, string? executablePath) {}
 
       public bool IsAvailable { get; }
       public string Name { get; }
 
       public string GetExecutablePathOrThrow() {}
     }
 
     protected static IReadOnlyCollection<string> DefaultCommandPaths { get; }
 
     protected static CommandNetworkScanner.Command FindCommand(string command, IEnumerable<string> paths) {}
 
     protected CommandNetworkScanner(ILogger? logger, IServiceProvider? serviceProvider) {}
 
     protected virtual void Dispose(bool disposing) {}
     public void Dispose() {}
     protected abstract bool GetCommandLineArguments(IEnumerable<IPAddress> addressesToScan, out string executable, out string? arguments);
     protected abstract bool GetCommandLineArguments(out string executable, out string? arguments);
     public virtual ValueTask ScanAsync(CancellationToken cancellationToken = default) {}
     public virtual ValueTask ScanAsync(IEnumerable<IPAddress> addresses, CancellationToken cancellationToken = default) {}
     protected void ThrowIfDisposed() {}
   }
 
   public sealed class IpHlpApiNetworkScanner : NetworkScanner {
     public static bool IsSupported { get; }
 
     public IpHlpApiNetworkScanner(IPNetworkProfile networkProfile, IServiceProvider? serviceProvider = null) {}
 
     protected override async ValueTask ScanAsyncCore(IPAddress address, CancellationToken cancellationToken = default) {}
   }
 
   public abstract class NetworkScanner : INetworkScanner {
     public static INetworkScanner Null { get; }
 
     public static INetworkScanner Create(IPNetworkProfile? networkProfile, IServiceProvider? serviceProvider = null) {}
 
     protected NetworkScanner(IPNetworkProfile networkProfile, ILogger? logger = null) {}
 
     protected ILogger? Logger { get; }
     protected IPNetworkProfile NetworkProfile { get; }
 
     protected virtual void Dispose(bool disposing) {}
     public void Dispose() {}
     public virtual ValueTask ScanAsync(CancellationToken cancellationToken = default) {}
     public virtual ValueTask ScanAsync(IEnumerable<IPAddress> addresses, CancellationToken cancellationToken = default) {}
     protected virtual ValueTask ScanAsyncCore(IPAddress address, CancellationToken cancellationToken) {}
     protected void ThrowIfDisposed() {}
   }
 
   public sealed class NmapCommandNetworkScanner : CommandNetworkScanner {
     public static bool IsSupported { get; }
 
     public NmapCommandNetworkScanner(IPNetworkProfile networkProfile, IServiceProvider? serviceProvider = null) {}
 
     protected override bool GetCommandLineArguments(IEnumerable<IPAddress> addressesToScan, out string executable, out string arguments) {}
     protected override bool GetCommandLineArguments(out string executable, out string arguments) {}
   }
 
   public sealed class PingNetworkScanner : NetworkScanner {
     public static bool IsSupported { get; }
 
     public PingNetworkScanner(IPNetworkProfile networkProfile, IServiceProvider? serviceProvider = null) {}
 
     protected override void Dispose(bool disposing) {}
     protected override async ValueTask ScanAsyncCore(IPAddress address, CancellationToken cancellationToken = default) {}
   }
 }
 // API list generated by Smdn.Reflection.ReverseGenerating.ListApi.MSBuild.Tasks v1.2.1.0.
 // Smdn.Reflection.ReverseGenerating.ListApi.Core v1.2.0.0 (https://github.com/smdn/Smdn.Reflection.ReverseGenerating)
diff --git a/doc/api-list/Smdn.Net.AddressResolution/Smdn.Net.AddressResolution-netstandard2.0.apilist.cs b/doc/api-list/Smdn.Net.AddressResolution/Smdn.Net.AddressResolution-netstandard2.0.apilist.cs
index e5a2cd3..9a44d04 100644
--- a/doc/api-list/Smdn.Net.AddressResolution/Smdn.Net.AddressResolution-netstandard2.0.apilist.cs
+++ b/doc/api-list/Smdn.Net.AddressResolution/Smdn.Net.AddressResolution-netstandard2.0.apilist.cs
@@ -1,284 +1,288 @@
-// Smdn.Net.AddressResolution.dll (Smdn.Net.AddressResolution-1.0.0)
+// Smdn.Net.AddressResolution.dll (Smdn.Net.AddressResolution-1.0.1)
 //   Name: Smdn.Net.AddressResolution
-//   AssemblyVersion: 1.0.0.0
-//   InformationalVersion: 1.0.0+b2ffdef7b9a768c14df101d2076bc63c12331f73
+//   AssemblyVersion: 1.0.1.0
+//   InformationalVersion: 1.0.1+12cda679d681acbeb81dac8a0cb03dbf6a3a0a3d
 //   TargetFramework: .NETStandard,Version=v2.0
 //   Configuration: Release
 //   Referenced assemblies:
 //     Microsoft.Bcl.AsyncInterfaces, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51
 //     Microsoft.Bcl.HashCode, Version=1.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51
 //     Microsoft.Extensions.DependencyInjection.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60
 //     Microsoft.Extensions.Logging.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60
 //     System.Memory, Version=4.0.1.2, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51
 //     System.Threading.Tasks.Extensions, Version=4.2.0.1, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51
 //     Vanara.PInvoke.IpHlpApi, Version=3.4.13.0, Culture=neutral, PublicKeyToken=c37e4080322237fa
 //     Vanara.PInvoke.Shared, Version=3.4.13.0, Culture=neutral, PublicKeyToken=c37e4080322237fa
 //     Vanara.PInvoke.Ws2_32, Version=3.4.13.0, Culture=neutral, PublicKeyToken=c37e4080322237fa
 //     netstandard, Version=2.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51
 #nullable enable annotations
 
 using System;
 using System.Collections.Generic;
 using System.Diagnostics;
 using System.Net;
 using System.Net.NetworkInformation;
 using System.Runtime.CompilerServices;
 using System.Threading;
 using System.Threading.Tasks;
 using Microsoft.Extensions.Logging;
 using Smdn.Net;
 using Smdn.Net.AddressResolution;
 using Smdn.Net.AddressTables;
 using Smdn.Net.NetworkScanning;
 
 namespace Smdn.Net {
   public abstract class IPNetworkProfile {
     public static IPNetworkProfile Create() {}
     public static IPNetworkProfile Create(Func<IEnumerable<IPAddress>?> addressRangeGenerator, NetworkInterface? networkInterface = null) {}
     public static IPNetworkProfile Create(IPAddress baseAddress, IPAddress subnetMask, NetworkInterface? networkInterface = null) {}
     public static IPNetworkProfile Create(IPAddress baseAddress, int prefixLength, NetworkInterface? networkInterface = null) {}
     public static IPNetworkProfile Create(NetworkInterface networkInterface) {}
     public static IPNetworkProfile Create(Predicate<NetworkInterface> predicateForNetworkInterface) {}
+    public static IPNetworkProfile CreateFromNetworkInterface(Guid id) {}
+    public static IPNetworkProfile CreateFromNetworkInterface(PhysicalAddress physicalAddress) {}
+    public static IPNetworkProfile CreateFromNetworkInterface(string id) {}
+    public static IPNetworkProfile CreateFromNetworkInterfaceName(string name) {}
 
     protected IPNetworkProfile(NetworkInterface? networkInterface) {}
 
     public NetworkInterface? NetworkInterface { get; }
 
     public abstract IEnumerable<IPAddress>? GetAddressRange();
   }
 
   public static class PhysicalAddressExtensions {
     public static string ToMacAddressString(this PhysicalAddress hardwareAddress, char delimiter = ':') {}
   }
 }
 
 namespace Smdn.Net.AddressResolution {
   public interface IAddressResolver<TAddress, TResolvedAddress> where TAddress : notnull where TResolvedAddress : notnull {
     void Invalidate(TAddress address);
     ValueTask<TResolvedAddress?> ResolveAsync(TAddress address, CancellationToken cancellationToken);
   }
 
   public class MacAddressResolver : MacAddressResolverBase {
     protected MacAddressResolver(IAddressTable addressTable, bool shouldDisposeAddressTable, INetworkScanner? networkScanner, bool shouldDisposeNetworkScanner, NetworkInterface? networkInterface, int maxParallelCountForRefreshInvalidatedAddresses, ILogger? logger) {}
     public MacAddressResolver() {}
     public MacAddressResolver(IAddressTable? addressTable, INetworkScanner? networkScanner, bool shouldDisposeAddressTable = false, bool shouldDisposeNetworkScanner = false, NetworkInterface? networkInterface = null, int maxParallelCountForRefreshInvalidatedAddresses = 3, IServiceProvider? serviceProvider = null) {}
     public MacAddressResolver(IPNetworkProfile? networkProfile, IServiceProvider? serviceProvider = null) {}
 
     public bool CanPerformNetworkScan { get; }
     public override bool HasInvalidated { get; }
     public TimeSpan NetworkScanInterval { get; set; }
     public TimeSpan NetworkScanMinInterval { get; set; }
 
     protected override void Dispose(bool disposing) {}
     public IAsyncEnumerable<AddressTableEntry> EnumerateAddressTableEntriesAsync(CancellationToken cancellationToken = default) {}
     public IAsyncEnumerable<AddressTableEntry> EnumerateAddressTableEntriesAsync(Predicate<AddressTableEntry> predicate, CancellationToken cancellationToken = default) {}
     protected override void InvalidateCore(IPAddress ipAddress) {}
     protected override void InvalidateCore(PhysicalAddress macAddress) {}
     protected override ValueTask RefreshAddressTableAsyncCore(CancellationToken cancellationToken = default) {}
     protected override ValueTask RefreshInvalidatedAddressesAsyncCore(CancellationToken cancellationToken = default) {}
     protected override async ValueTask<PhysicalAddress?> ResolveIPAddressToMacAddressAsyncCore(IPAddress ipAddress, CancellationToken cancellationToken) {}
     protected override async ValueTask<IPAddress?> ResolveMacAddressToIPAddressAsyncCore(PhysicalAddress macAddress, CancellationToken cancellationToken) {}
     protected virtual async ValueTask<AddressTableEntry> SelectAddressTableEntryAsync(Predicate<AddressTableEntry> predicate, CancellationToken cancellationToken) {}
   }
 
   public abstract class MacAddressResolverBase :
     IAddressResolver<IPAddress, PhysicalAddress>,
     IAddressResolver<PhysicalAddress, IPAddress>,
     IDisposable
   {
     protected static PhysicalAddress AllZeroMacAddress { get; }
     public static MacAddressResolverBase Null { get; }
 
     protected MacAddressResolverBase(ILogger? logger = null) {}
 
     public abstract bool HasInvalidated { get; }
     protected ILogger? Logger { get; }
 
     protected virtual void Dispose(bool disposing) {}
     public void Dispose() {}
     public void Invalidate(IPAddress ipAddress) {}
     public void Invalidate(PhysicalAddress macAddress) {}
     protected abstract void InvalidateCore(IPAddress ipAddress);
     protected abstract void InvalidateCore(PhysicalAddress macAddress);
     public ValueTask RefreshAddressTableAsync(CancellationToken cancellationToken = default) {}
     protected virtual ValueTask RefreshAddressTableAsyncCore(CancellationToken cancellationToken) {}
     public ValueTask RefreshInvalidatedAddressesAsync(CancellationToken cancellationToken = default) {}
     protected virtual ValueTask RefreshInvalidatedAddressesAsyncCore(CancellationToken cancellationToken) {}
     public ValueTask<PhysicalAddress?> ResolveIPAddressToMacAddressAsync(IPAddress ipAddress, CancellationToken cancellationToken = default) {}
     protected abstract ValueTask<PhysicalAddress?> ResolveIPAddressToMacAddressAsyncCore(IPAddress ipAddress, CancellationToken cancellationToken);
     public ValueTask<IPAddress?> ResolveMacAddressToIPAddressAsync(PhysicalAddress macAddress, CancellationToken cancellationToken = default) {}
     protected abstract ValueTask<IPAddress?> ResolveMacAddressToIPAddressAsyncCore(PhysicalAddress macAddress, CancellationToken cancellationToken);
     void IAddressResolver<IPAddress, PhysicalAddress>.Invalidate(IPAddress address) {}
     ValueTask<PhysicalAddress?> IAddressResolver<IPAddress, PhysicalAddress>.ResolveAsync(IPAddress address, CancellationToken cancellationToken) {}
     void IAddressResolver<PhysicalAddress, IPAddress>.Invalidate(PhysicalAddress address) {}
     ValueTask<IPAddress?> IAddressResolver<PhysicalAddress, IPAddress>.ResolveAsync(PhysicalAddress address, CancellationToken cancellationToken) {}
     protected void ThrowIfDisposed() {}
   }
 }
 
 namespace Smdn.Net.AddressTables {
   public interface IAddressTable : IDisposable {
     IAsyncEnumerable<AddressTableEntry> EnumerateEntriesAsync(CancellationToken cancellationToken);
   }
 
   public enum AddressTableEntryState : int {
     Delay = 4,
     Incomplete = 1,
     None = 0,
     Probe = 5,
     Reachable = 2,
     Stale = 3,
   }
 
   public abstract class AddressTable : IAddressTable {
     public static IAddressTable Null { get; }
 
     public static IAddressTable Create(IServiceProvider? serviceProvider = null) {}
 
     protected AddressTable(ILogger? logger = null) {}
 
     protected ILogger? Logger { get; }
 
     protected virtual void Dispose(bool disposing) {}
     public void Dispose() {}
     public IAsyncEnumerable<AddressTableEntry> EnumerateEntriesAsync(CancellationToken cancellationToken = default) {}
     protected abstract IAsyncEnumerable<AddressTableEntry> EnumerateEntriesAsyncCore(CancellationToken cancellationToken);
     protected void ThrowIfDisposed() {}
   }
 
   public sealed class IpHlpApiAddressTable : AddressTable {
     public static bool IsSupported { get; }
 
     public IpHlpApiAddressTable(IServiceProvider? serviceProvider = null) {}
 
     [AsyncIteratorStateMachine(typeof(IpHlpApiAddressTable.<EnumerateEntriesAsyncCore>d__4))]
     protected override IAsyncEnumerable<AddressTableEntry> EnumerateEntriesAsyncCore([EnumeratorCancellation] CancellationToken cancellationToken) {}
   }
 
   public sealed class ProcfsArpAddressTable : AddressTable {
     public static bool IsSupported { get; }
 
     public ProcfsArpAddressTable(IServiceProvider? serviceProvider = null) {}
 
     [AsyncIteratorStateMachine(typeof(ProcfsArpAddressTable.<EnumerateEntriesAsyncCore>d__5))]
     protected override IAsyncEnumerable<AddressTableEntry> EnumerateEntriesAsyncCore([EnumeratorCancellation] CancellationToken cancellationToken) {}
   }
 
   public readonly struct AddressTableEntry :
     IEquatable<AddressTableEntry>,
     IEquatable<IPAddress>,
     IEquatable<PhysicalAddress>
   {
     public static readonly AddressTableEntry Empty; // = "{IP=, MAC=(null), IsPermanent=False, State=None, Iface=}"
 
     public static IEqualityComparer<AddressTableEntry> DefaultEqualityComparer { get; }
     public static IEqualityComparer<AddressTableEntry> ExceptStateEqualityComparer { get; }
 
     public AddressTableEntry(IPAddress ipAddress, PhysicalAddress? physicalAddress, bool isPermanent, AddressTableEntryState state, string? interfaceId) {}
 
     public IPAddress? IPAddress { get; }
     public string? InterfaceId { get; }
     public bool IsEmpty { get; }
     public bool IsPermanent { get; }
     public PhysicalAddress? PhysicalAddress { get; }
     public AddressTableEntryState State { get; }
 
     public bool Equals(AddressTableEntry other) {}
     public bool Equals(IPAddress? other) {}
     public bool Equals(PhysicalAddress? other) {}
     public override bool Equals(object? obj) {}
     public override int GetHashCode() {}
     public override string ToString() {}
   }
 }
 
 namespace Smdn.Net.NetworkScanning {
   public interface INetworkScanner : IDisposable {
     ValueTask ScanAsync(CancellationToken cancellationToken);
     ValueTask ScanAsync(IEnumerable<IPAddress> addresses, CancellationToken cancellationToken);
   }
 
   public sealed class ArpScanCommandNetworkScanner : CommandNetworkScanner {
     public static bool IsSupported { get; }
 
     public ArpScanCommandNetworkScanner(IPNetworkProfile? networkProfile, IServiceProvider? serviceProvider = null) {}
 
     protected override bool GetCommandLineArguments(IEnumerable<IPAddress> addressesToScan, out string executable, out string arguments) {}
     protected override bool GetCommandLineArguments(out string executable, out string arguments) {}
   }
 
   public abstract class CommandNetworkScanner : INetworkScanner {
     public interface IProcessFactory {
       Process CreateProcess(ProcessStartInfo processStartInfo);
     }
 
     protected readonly struct Command {
       public Command(string name, string? executablePath) {}
 
       public bool IsAvailable { get; }
       public string Name { get; }
 
       public string GetExecutablePathOrThrow() {}
     }
 
     protected static IReadOnlyCollection<string> DefaultCommandPaths { get; }
 
     protected static CommandNetworkScanner.Command FindCommand(string command, IEnumerable<string> paths) {}
 
     protected CommandNetworkScanner(ILogger? logger, IServiceProvider? serviceProvider) {}
 
     protected virtual void Dispose(bool disposing) {}
     public void Dispose() {}
     protected abstract bool GetCommandLineArguments(IEnumerable<IPAddress> addressesToScan, out string executable, out string? arguments);
     protected abstract bool GetCommandLineArguments(out string executable, out string? arguments);
     public virtual ValueTask ScanAsync(CancellationToken cancellationToken = default) {}
     public virtual ValueTask ScanAsync(IEnumerable<IPAddress> addresses, CancellationToken cancellationToken = default) {}
     protected void ThrowIfDisposed() {}
   }
 
   public sealed class IpHlpApiNetworkScanner : NetworkScanner {
     public static bool IsSupported { get; }
 
     public IpHlpApiNetworkScanner(IPNetworkProfile networkProfile, IServiceProvider? serviceProvider = null) {}
 
     protected override async ValueTask ScanAsyncCore(IPAddress address, CancellationToken cancellationToken = default) {}
   }
 
   public abstract class NetworkScanner : INetworkScanner {
     public static INetworkScanner Null { get; }
 
     public static INetworkScanner Create(IPNetworkProfile? networkProfile, IServiceProvider? serviceProvider = null) {}
 
     protected NetworkScanner(IPNetworkProfile networkProfile, ILogger? logger = null) {}
 
     protected ILogger? Logger { get; }
     protected IPNetworkProfile NetworkProfile { get; }
 
     protected virtual void Dispose(bool disposing) {}
     public void Dispose() {}
     public virtual ValueTask ScanAsync(CancellationToken cancellationToken = default) {}
     public virtual ValueTask ScanAsync(IEnumerable<IPAddress> addresses, CancellationToken cancellationToken = default) {}
     protected virtual ValueTask ScanAsyncCore(IPAddress address, CancellationToken cancellationToken) {}
     protected void ThrowIfDisposed() {}
   }
 
   public sealed class NmapCommandNetworkScanner : CommandNetworkScanner {
     public static bool IsSupported { get; }
 
     public NmapCommandNetworkScanner(IPNetworkProfile networkProfile, IServiceProvider? serviceProvider = null) {}
 
     protected override bool GetCommandLineArguments(IEnumerable<IPAddress> addressesToScan, out string executable, out string arguments) {}
     protected override bool GetCommandLineArguments(out string executable, out string arguments) {}
   }
 
   public sealed class PingNetworkScanner : NetworkScanner {
     public static bool IsSupported { get; }
 
     public PingNetworkScanner(IPNetworkProfile networkProfile, IServiceProvider? serviceProvider = null) {}
 
     protected override void Dispose(bool disposing) {}
     protected override async ValueTask ScanAsyncCore(IPAddress address, CancellationToken cancellationToken = default) {}
   }
 }
 // API list generated by Smdn.Reflection.ReverseGenerating.ListApi.MSBuild.Tasks v1.2.1.0.
 // Smdn.Reflection.ReverseGenerating.ListApi.Core v1.2.0.0 (https://github.com/smdn/Smdn.Reflection.ReverseGenerating)
diff --git a/doc/api-list/Smdn.Net.AddressResolution/Smdn.Net.AddressResolution-netstandard2.1.apilist.cs b/doc/api-list/Smdn.Net.AddressResolution/Smdn.Net.AddressResolution-netstandard2.1.apilist.cs
index 28fbe5e..ce88513 100644
--- a/doc/api-list/Smdn.Net.AddressResolution/Smdn.Net.AddressResolution-netstandard2.1.apilist.cs
+++ b/doc/api-list/Smdn.Net.AddressResolution/Smdn.Net.AddressResolution-netstandard2.1.apilist.cs
@@ -1,280 +1,284 @@
-// Smdn.Net.AddressResolution.dll (Smdn.Net.AddressResolution-1.0.0)
+// Smdn.Net.AddressResolution.dll (Smdn.Net.AddressResolution-1.0.1)
 //   Name: Smdn.Net.AddressResolution
-//   AssemblyVersion: 1.0.0.0
-//   InformationalVersion: 1.0.0+b2ffdef7b9a768c14df101d2076bc63c12331f73
+//   AssemblyVersion: 1.0.1.0
+//   InformationalVersion: 1.0.1+12cda679d681acbeb81dac8a0cb03dbf6a3a0a3d
 //   TargetFramework: .NETStandard,Version=v2.1
 //   Configuration: Release
 //   Referenced assemblies:
 //     Microsoft.Extensions.DependencyInjection.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60
 //     Microsoft.Extensions.Logging.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60
 //     Vanara.PInvoke.IpHlpApi, Version=3.4.13.0, Culture=neutral, PublicKeyToken=c37e4080322237fa
 //     Vanara.PInvoke.Shared, Version=3.4.13.0, Culture=neutral, PublicKeyToken=c37e4080322237fa
 //     Vanara.PInvoke.Ws2_32, Version=3.4.13.0, Culture=neutral, PublicKeyToken=c37e4080322237fa
 //     netstandard, Version=2.1.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51
 #nullable enable annotations
 
 using System;
 using System.Collections.Generic;
 using System.Diagnostics;
 using System.Net;
 using System.Net.NetworkInformation;
 using System.Runtime.CompilerServices;
 using System.Threading;
 using System.Threading.Tasks;
 using Microsoft.Extensions.Logging;
 using Smdn.Net;
 using Smdn.Net.AddressResolution;
 using Smdn.Net.AddressTables;
 using Smdn.Net.NetworkScanning;
 
 namespace Smdn.Net {
   public abstract class IPNetworkProfile {
     public static IPNetworkProfile Create() {}
     public static IPNetworkProfile Create(Func<IEnumerable<IPAddress>?> addressRangeGenerator, NetworkInterface? networkInterface = null) {}
     public static IPNetworkProfile Create(IPAddress baseAddress, IPAddress subnetMask, NetworkInterface? networkInterface = null) {}
     public static IPNetworkProfile Create(IPAddress baseAddress, int prefixLength, NetworkInterface? networkInterface = null) {}
     public static IPNetworkProfile Create(NetworkInterface networkInterface) {}
     public static IPNetworkProfile Create(Predicate<NetworkInterface> predicateForNetworkInterface) {}
+    public static IPNetworkProfile CreateFromNetworkInterface(Guid id) {}
+    public static IPNetworkProfile CreateFromNetworkInterface(PhysicalAddress physicalAddress) {}
+    public static IPNetworkProfile CreateFromNetworkInterface(string id) {}
+    public static IPNetworkProfile CreateFromNetworkInterfaceName(string name) {}
 
     protected IPNetworkProfile(NetworkInterface? networkInterface) {}
 
     public NetworkInterface? NetworkInterface { get; }
 
     public abstract IEnumerable<IPAddress>? GetAddressRange();
   }
 
   public static class PhysicalAddressExtensions {
     public static string ToMacAddressString(this PhysicalAddress hardwareAddress, char delimiter = ':') {}
   }
 }
 
 namespace Smdn.Net.AddressResolution {
   public interface IAddressResolver<TAddress, TResolvedAddress> where TAddress : notnull where TResolvedAddress : notnull {
     void Invalidate(TAddress address);
     ValueTask<TResolvedAddress?> ResolveAsync(TAddress address, CancellationToken cancellationToken);
   }
 
   public class MacAddressResolver : MacAddressResolverBase {
     protected MacAddressResolver(IAddressTable addressTable, bool shouldDisposeAddressTable, INetworkScanner? networkScanner, bool shouldDisposeNetworkScanner, NetworkInterface? networkInterface, int maxParallelCountForRefreshInvalidatedAddresses, ILogger? logger) {}
     public MacAddressResolver() {}
     public MacAddressResolver(IAddressTable? addressTable, INetworkScanner? networkScanner, bool shouldDisposeAddressTable = false, bool shouldDisposeNetworkScanner = false, NetworkInterface? networkInterface = null, int maxParallelCountForRefreshInvalidatedAddresses = 3, IServiceProvider? serviceProvider = null) {}
     public MacAddressResolver(IPNetworkProfile? networkProfile, IServiceProvider? serviceProvider = null) {}
 
     public bool CanPerformNetworkScan { get; }
     public override bool HasInvalidated { get; }
     public TimeSpan NetworkScanInterval { get; set; }
     public TimeSpan NetworkScanMinInterval { get; set; }
 
     protected override void Dispose(bool disposing) {}
     public IAsyncEnumerable<AddressTableEntry> EnumerateAddressTableEntriesAsync(CancellationToken cancellationToken = default) {}
     public IAsyncEnumerable<AddressTableEntry> EnumerateAddressTableEntriesAsync(Predicate<AddressTableEntry> predicate, CancellationToken cancellationToken = default) {}
     protected override void InvalidateCore(IPAddress ipAddress) {}
     protected override void InvalidateCore(PhysicalAddress macAddress) {}
     protected override ValueTask RefreshAddressTableAsyncCore(CancellationToken cancellationToken = default) {}
     protected override ValueTask RefreshInvalidatedAddressesAsyncCore(CancellationToken cancellationToken = default) {}
     protected override async ValueTask<PhysicalAddress?> ResolveIPAddressToMacAddressAsyncCore(IPAddress ipAddress, CancellationToken cancellationToken) {}
     protected override async ValueTask<IPAddress?> ResolveMacAddressToIPAddressAsyncCore(PhysicalAddress macAddress, CancellationToken cancellationToken) {}
     protected virtual async ValueTask<AddressTableEntry> SelectAddressTableEntryAsync(Predicate<AddressTableEntry> predicate, CancellationToken cancellationToken) {}
   }
 
   public abstract class MacAddressResolverBase :
     IAddressResolver<IPAddress, PhysicalAddress>,
     IAddressResolver<PhysicalAddress, IPAddress>,
     IDisposable
   {
     protected static PhysicalAddress AllZeroMacAddress { get; }
     public static MacAddressResolverBase Null { get; }
 
     protected MacAddressResolverBase(ILogger? logger = null) {}
 
     public abstract bool HasInvalidated { get; }
     protected ILogger? Logger { get; }
 
     protected virtual void Dispose(bool disposing) {}
     public void Dispose() {}
     public void Invalidate(IPAddress ipAddress) {}
     public void Invalidate(PhysicalAddress macAddress) {}
     protected abstract void InvalidateCore(IPAddress ipAddress);
     protected abstract void InvalidateCore(PhysicalAddress macAddress);
     public ValueTask RefreshAddressTableAsync(CancellationToken cancellationToken = default) {}
     protected virtual ValueTask RefreshAddressTableAsyncCore(CancellationToken cancellationToken) {}
     public ValueTask RefreshInvalidatedAddressesAsync(CancellationToken cancellationToken = default) {}
     protected virtual ValueTask RefreshInvalidatedAddressesAsyncCore(CancellationToken cancellationToken) {}
     public ValueTask<PhysicalAddress?> ResolveIPAddressToMacAddressAsync(IPAddress ipAddress, CancellationToken cancellationToken = default) {}
     protected abstract ValueTask<PhysicalAddress?> ResolveIPAddressToMacAddressAsyncCore(IPAddress ipAddress, CancellationToken cancellationToken);
     public ValueTask<IPAddress?> ResolveMacAddressToIPAddressAsync(PhysicalAddress macAddress, CancellationToken cancellationToken = default) {}
     protected abstract ValueTask<IPAddress?> ResolveMacAddressToIPAddressAsyncCore(PhysicalAddress macAddress, CancellationToken cancellationToken);
     void IAddressResolver<IPAddress, PhysicalAddress>.Invalidate(IPAddress address) {}
     ValueTask<PhysicalAddress?> IAddressResolver<IPAddress, PhysicalAddress>.ResolveAsync(IPAddress address, CancellationToken cancellationToken) {}
     void IAddressResolver<PhysicalAddress, IPAddress>.Invalidate(PhysicalAddress address) {}
     ValueTask<IPAddress?> IAddressResolver<PhysicalAddress, IPAddress>.ResolveAsync(PhysicalAddress address, CancellationToken cancellationToken) {}
     protected void ThrowIfDisposed() {}
   }
 }
 
 namespace Smdn.Net.AddressTables {
   public interface IAddressTable : IDisposable {
     IAsyncEnumerable<AddressTableEntry> EnumerateEntriesAsync(CancellationToken cancellationToken);
   }
 
   public enum AddressTableEntryState : int {
     Delay = 4,
     Incomplete = 1,
     None = 0,
     Probe = 5,
     Reachable = 2,
     Stale = 3,
   }
 
   public abstract class AddressTable : IAddressTable {
     public static IAddressTable Null { get; }
 
     public static IAddressTable Create(IServiceProvider? serviceProvider = null) {}
 
     protected AddressTable(ILogger? logger = null) {}
 
     protected ILogger? Logger { get; }
 
     protected virtual void Dispose(bool disposing) {}
     public void Dispose() {}
     public IAsyncEnumerable<AddressTableEntry> EnumerateEntriesAsync(CancellationToken cancellationToken = default) {}
     protected abstract IAsyncEnumerable<AddressTableEntry> EnumerateEntriesAsyncCore(CancellationToken cancellationToken);
     protected void ThrowIfDisposed() {}
   }
 
   public sealed class IpHlpApiAddressTable : AddressTable {
     public static bool IsSupported { get; }
 
     public IpHlpApiAddressTable(IServiceProvider? serviceProvider = null) {}
 
     [AsyncIteratorStateMachine(typeof(IpHlpApiAddressTable.<EnumerateEntriesAsyncCore>d__4))]
     protected override IAsyncEnumerable<AddressTableEntry> EnumerateEntriesAsyncCore([EnumeratorCancellation] CancellationToken cancellationToken) {}
   }
 
   public sealed class ProcfsArpAddressTable : AddressTable {
     public static bool IsSupported { get; }
 
     public ProcfsArpAddressTable(IServiceProvider? serviceProvider = null) {}
 
     [AsyncIteratorStateMachine(typeof(ProcfsArpAddressTable.<EnumerateEntriesAsyncCore>d__5))]
     protected override IAsyncEnumerable<AddressTableEntry> EnumerateEntriesAsyncCore([EnumeratorCancellation] CancellationToken cancellationToken) {}
   }
 
   public readonly struct AddressTableEntry :
     IEquatable<AddressTableEntry>,
     IEquatable<IPAddress>,
     IEquatable<PhysicalAddress>
   {
     public static readonly AddressTableEntry Empty; // = "{IP=, MAC=(null), IsPermanent=False, State=None, Iface=}"
 
     public static IEqualityComparer<AddressTableEntry> DefaultEqualityComparer { get; }
     public static IEqualityComparer<AddressTableEntry> ExceptStateEqualityComparer { get; }
 
     public AddressTableEntry(IPAddress ipAddress, PhysicalAddress? physicalAddress, bool isPermanent, AddressTableEntryState state, string? interfaceId) {}
 
     public IPAddress? IPAddress { get; }
     public string? InterfaceId { get; }
     public bool IsEmpty { get; }
     public bool IsPermanent { get; }
     public PhysicalAddress? PhysicalAddress { get; }
     public AddressTableEntryState State { get; }
 
     public bool Equals(AddressTableEntry other) {}
     public bool Equals(IPAddress? other) {}
     public bool Equals(PhysicalAddress? other) {}
     public override bool Equals(object? obj) {}
     public override int GetHashCode() {}
     public override string ToString() {}
   }
 }
 
 namespace Smdn.Net.NetworkScanning {
   public interface INetworkScanner : IDisposable {
     ValueTask ScanAsync(CancellationToken cancellationToken);
     ValueTask ScanAsync(IEnumerable<IPAddress> addresses, CancellationToken cancellationToken);
   }
 
   public sealed class ArpScanCommandNetworkScanner : CommandNetworkScanner {
     public static bool IsSupported { get; }
 
     public ArpScanCommandNetworkScanner(IPNetworkProfile? networkProfile, IServiceProvider? serviceProvider = null) {}
 
     protected override bool GetCommandLineArguments(IEnumerable<IPAddress> addressesToScan, out string executable, out string arguments) {}
     protected override bool GetCommandLineArguments(out string executable, out string arguments) {}
   }
 
   public abstract class CommandNetworkScanner : INetworkScanner {
     public interface IProcessFactory {
       Process CreateProcess(ProcessStartInfo processStartInfo);
     }
 
     protected readonly struct Command {
       public Command(string name, string? executablePath) {}
 
       public bool IsAvailable { get; }
       public string Name { get; }
 
       public string GetExecutablePathOrThrow() {}
     }
 
     protected static IReadOnlyCollection<string> DefaultCommandPaths { get; }
 
     protected static CommandNetworkScanner.Command FindCommand(string command, IEnumerable<string> paths) {}
 
     protected CommandNetworkScanner(ILogger? logger, IServiceProvider? serviceProvider) {}
 
     protected virtual void Dispose(bool disposing) {}
     public void Dispose() {}
     protected abstract bool GetCommandLineArguments(IEnumerable<IPAddress> addressesToScan, out string executable, out string? arguments);
     protected abstract bool GetCommandLineArguments(out string executable, out string? arguments);
     public virtual ValueTask ScanAsync(CancellationToken cancellationToken = default) {}
     public virtual ValueTask ScanAsync(IEnumerable<IPAddress> addresses, CancellationToken cancellationToken = default) {}
     protected void ThrowIfDisposed() {}
   }
 
   public sealed class IpHlpApiNetworkScanner : NetworkScanner {
     public static bool IsSupported { get; }
 
     public IpHlpApiNetworkScanner(IPNetworkProfile networkProfile, IServiceProvider? serviceProvider = null) {}
 
     protected override async ValueTask ScanAsyncCore(IPAddress address, CancellationToken cancellationToken = default) {}
   }
 
   public abstract class NetworkScanner : INetworkScanner {
     public static INetworkScanner Null { get; }
 
     public static INetworkScanner Create(IPNetworkProfile? networkProfile, IServiceProvider? serviceProvider = null) {}
 
     protected NetworkScanner(IPNetworkProfile networkProfile, ILogger? logger = null) {}
 
     protected ILogger? Logger { get; }
     protected IPNetworkProfile NetworkProfile { get; }
 
     protected virtual void Dispose(bool disposing) {}
     public void Dispose() {}
     public virtual ValueTask ScanAsync(CancellationToken cancellationToken = default) {}
     public virtual ValueTask ScanAsync(IEnumerable<IPAddress> addresses, CancellationToken cancellationToken = default) {}
     protected virtual ValueTask ScanAsyncCore(IPAddress address, CancellationToken cancellationToken) {}
     protected void ThrowIfDisposed() {}
   }
 
   public sealed class NmapCommandNetworkScanner : CommandNetworkScanner {
     public static bool IsSupported { get; }
 
     public NmapCommandNetworkScanner(IPNetworkProfile networkProfile, IServiceProvider? serviceProvider = null) {}
 
     protected override bool GetCommandLineArguments(IEnumerable<IPAddress> addressesToScan, out string executable, out string arguments) {}
     protected override bool GetCommandLineArguments(out string executable, out string arguments) {}
   }
 
   public sealed class PingNetworkScanner : NetworkScanner {
     public static bool IsSupported { get; }
 
     public PingNetworkScanner(IPNetworkProfile networkProfile, IServiceProvider? serviceProvider = null) {}
 
     protected override void Dispose(bool disposing) {}
     protected override async ValueTask ScanAsyncCore(IPAddress address, CancellationToken cancellationToken = default) {}
   }
 }
 // API list generated by Smdn.Reflection.ReverseGenerating.ListApi.MSBuild.Tasks v1.2.1.0.
 // Smdn.Reflection.ReverseGenerating.ListApi.Core v1.2.0.0 (https://github.com/smdn/Smdn.Reflection.ReverseGenerating)

Full changes

Full changes in this release:
diff --git a/src/Smdn.Net.AddressResolution/Smdn.Net.AddressResolution.csproj b/src/Smdn.Net.AddressResolution/Smdn.Net.AddressResolution.csproj
index a07c8cb..64a810c 100644
--- a/src/Smdn.Net.AddressResolution/Smdn.Net.AddressResolution.csproj
+++ b/src/Smdn.Net.AddressResolution/Smdn.Net.AddressResolution.csproj
@@ -7,11 +7,13 @@ SPDX-License-Identifier: MIT
     <TargetFrameworks>netstandard2.0;netstandard2.1;net6.0</TargetFrameworks>
     <TargetFrameworks Condition="$([MSBuild]::VersionGreaterThanOrEquals('$(NETCoreSdkVersion)', '7.0.0'))">net7.0;$(TargetFrameworks)</TargetFrameworks>
     <TargetFrameworks Condition="$([MSBuild]::VersionGreaterThanOrEquals('$(NETCoreSdkVersion)', '8.0.0'))">net8.0;$(TargetFrameworks)</TargetFrameworks>
-    <VersionPrefix>1.0.0</VersionPrefix>
+    <VersionPrefix>1.0.1</VersionPrefix>
     <VersionSuffix></VersionSuffix>
-    <!-- <PackageValidationBaselineVersion>1.0.0</PackageValidationBaselineVersion> -->
+    <PackageValidationBaselineVersion>1.0.0</PackageValidationBaselineVersion>
     <Nullable>enable</Nullable>
-    <NoWarn>CA1848</NoWarn> <!-- use the LoggerMessage delegates instead -->
+    <GenerateDocumentationFile>true</GenerateDocumentationFile>
+    <NoWarn>CA1848;$(NoWarn)</NoWarn> <!-- use the LoggerMessage delegates instead -->
+    <NoWarn>CS1591;$(NoWarn)</NoWarn> <!-- CS1591: Missing XML comment for publicly visible type or member 'Type_or_Member' -->
   </PropertyGroup>
 
   <PropertyGroup Label="assembly attributes">
@@ -63,7 +65,7 @@ $([System.IO.File]::ReadAllText('$(MSBuildThisFileDirectory)..\..\examples\mac-a

Contributing

-This project welcomes contributions, feedback and suggestions. You can contribute to this project by submitting Issues or Pull Requests on the GitHub repository.
+This project welcomes contributions, feedbacks and suggestions. You can contribute to this project by submitting Issues or Pull Requests on the GitHub repository.
]]>


diff --git a/src/Smdn.Net.AddressResolution/Smdn.Net.AddressResolution/IAddressResolver.cs b/src/Smdn.Net.AddressResolution/Smdn.Net.AddressResolution/IAddressResolver.cs
index 1d99714..8ab3da7 100644
--- a/src/Smdn.Net.AddressResolution/Smdn.Net.AddressResolution/IAddressResolver.cs
+++ b/src/Smdn.Net.AddressResolution/Smdn.Net.AddressResolution/IAddressResolver.cs
@@ -15,22 +15,22 @@ public interface IAddressResolver<TAddress, TResolvedAddress>
where TResolvedAddress : notnull
{
///

  • /// Resolves from a address of to its corresponding address of .
  • /// Resolves from a address of to its corresponding address of .
    ///
  • /// The address of to be resolved.
  • /// The address of to be resolved.
    /// The to monitor for cancellation requests.
    ///
  • /// A representing the result of address resolution.
  • /// If the address is successfully resolved, representing the resolved address is set. If not, is set.
  • /// A representing the result of address resolution.

  • /// If the address is successfully resolved, representing the resolved address is set. If not, is set.
    ///
    ///
    ValueTask<TResolvedAddress?> ResolveAsync(TAddress address, CancellationToken cancellationToken);

    ///

  • /// Marks the as 'invalidated', for example, if the resolved
  • /// Marks the as 'invalidated', for example, if the resolved
    /// corresponding to the is unreachable or expired.
    ///
  • /// The to mark as 'invalidated'.
  • /// The to mark as 'invalidated'.
    ///
    void Invalidate(TAddress address);
    }
    diff --git a/src/Smdn.Net.AddressResolution/Smdn.Net.AddressResolution/MacAddressResolver.AddressTable.cs b/src/Smdn.Net.AddressResolution/Smdn.Net.AddressResolution/MacAddressResolver.AddressTable.cs
    index fa92b39..80536b5 100644
    --- a/src/Smdn.Net.AddressResolution/Smdn.Net.AddressResolution/MacAddressResolver.AddressTable.cs
    +++ b/src/Smdn.Net.AddressResolution/Smdn.Net.AddressResolution/MacAddressResolver.AddressTable.cs
    @@ -40,6 +40,10 @@ partial class MacAddressResolver {
    ///
    /// A that filters the entries enumerated from .
    ///
  • ///
  • /// The to monitor for cancellation requests.
  • /// The default value is .
  • ///
    public IAsyncEnumerable EnumerateAddressTableEntriesAsync(
    Predicate predicate,
    CancellationToken cancellationToken = default
    diff --git a/src/Smdn.Net.AddressResolution/Smdn.Net.AddressResolution/MacAddressResolver.NetworkScanning.cs b/src/Smdn.Net.AddressResolution/Smdn.Net.AddressResolution/MacAddressResolver.NetworkScanning.cs
    index 5d559cb..db82dff 100644
    --- a/src/Smdn.Net.AddressResolution/Smdn.Net.AddressResolution/MacAddressResolver.NetworkScanning.cs
    +++ b/src/Smdn.Net.AddressResolution/Smdn.Net.AddressResolution/MacAddressResolver.NetworkScanning.cs
    @@ -1,6 +1,5 @@
    // SPDX-FileCopyrightText: 2022 smdn smdn@smdn.jp
    // SPDX-License-Identifier: MIT
    -using System;
    using System.Diagnostics;
    using System.Net;
    using System.Net.NetworkInformation;
    diff --git a/src/Smdn.Net.AddressResolution/Smdn.Net.AddressResolution/MacAddressResolver.cs b/src/Smdn.Net.AddressResolution/Smdn.Net.AddressResolution/MacAddressResolver.cs
    index 5fc9b6f..091068f 100644
    --- a/src/Smdn.Net.AddressResolution/Smdn.Net.AddressResolution/MacAddressResolver.cs
    +++ b/src/Smdn.Net.AddressResolution/Smdn.Net.AddressResolution/MacAddressResolver.cs
    @@ -49,16 +49,16 @@ public partial class MacAddressResolver : MacAddressResolverBase {
    /// value of will be and no network scan will be performed.
    ///
    ///
  • /// If is , calling or
  • /// throws .
  • /// Also, automatic network scanning by calling of or
  • /// will not performed.
  • /// If is , calling or
  • /// throws .
  • /// Also, automatic network scanning by calling of or
  • /// will not performed.
    ///
    ///
    ///
    ///
  • ///
  • ///
  • ///

  • ///
    public bool CanPerformNetworkScan => networkScanner is not null;

    private static Exception CreateCanNotPerformNetworkScanException()
    @@ -74,8 +74,8 @@ public partial class MacAddressResolver : MacAddressResolverBase {
    ///
    ///
    /// If the period represented by this property has elapsed since the lastest network scan,

  • /// the instance performs network scan automatically when the or
  • /// is called.
  • /// the instance performs network scan automatically when the or
  • /// is called.
    ///
    ///
    /// If is specified, the instance does not perform network scan automatically.
    @@ -83,8 +83,8 @@ public partial class MacAddressResolver : MacAddressResolverBase {
    ///
    ///
    ///
  • ///
  • ///
  • ///
  • ///
    public TimeSpan NetworkScanInterval {
    get => networkScanInterval;
    set {
    @@ -106,9 +106,9 @@ public partial class MacAddressResolver : MacAddressResolverBase {
    /// the instance will not performs network scan.
    ///
    ///
  • /// The network scan will be performed automatically when the or
  • /// is called, or explicitly performed by calling the
  • /// .
  • /// The network scan will be performed automatically when the or
  • /// is called, or explicitly performed by calling the
  • /// .
    ///
    ///
    /// If is specified, the instance does not perform the network scan.
    @@ -117,9 +117,9 @@ public partial class MacAddressResolver : MacAddressResolverBase {
    ///
    ///
    ///
  • ///
  • ///
  • ///
  • ///
  • ///
  • ///
    public TimeSpan NetworkScanMinInterval {
    get => networkScanMinInterval;
    set {
    diff --git a/src/Smdn.Net.AddressResolution/Smdn.Net.AddressResolution/MacAddressResolverBase.cs b/src/Smdn.Net.AddressResolution/Smdn.Net.AddressResolution/MacAddressResolverBase.cs
    index 157d3d0..6f17a60 100644
    --- a/src/Smdn.Net.AddressResolution/Smdn.Net.AddressResolution/MacAddressResolverBase.cs
    +++ b/src/Smdn.Net.AddressResolution/Smdn.Net.AddressResolution/MacAddressResolverBase.cs
    @@ -108,7 +108,7 @@ public abstract class MacAddressResolverBase :
    /// The to be resolved.
    /// The to monitor for cancellation requests. The default value is .
    ///
  • /// A representing the result of address resolution.
  • /// A representing the result of address resolution.
    /// If the address is successfully resolved, representing the resolved address is set. If not, is set.
    ///
    ///
    @@ -205,7 +205,7 @@ public abstract class MacAddressResolverBase :
    /// The to be resolved.
    /// The to monitor for cancellation requests. The default value is .
    ///
  • /// A representing the result of address resolution.
  • /// A representing the result of address resolution.
    /// If the address is successfully resolved, representing the resolved address is set. If not, is set.
    ///
    ///
    diff --git a/src/Smdn.Net.AddressResolution/Smdn.Net.AddressTables/AddressTableEntry.cs b/src/Smdn.Net.AddressResolution/Smdn.Net.AddressTables/AddressTableEntry.cs
    index 2509cc8..d1bd402 100644
    --- a/src/Smdn.Net.AddressResolution/Smdn.Net.AddressTables/AddressTableEntry.cs
    +++ b/src/Smdn.Net.AddressResolution/Smdn.Net.AddressTables/AddressTableEntry.cs
    @@ -7,7 +7,6 @@ using System.Diagnostics.CodeAnalysis;
    #endif
    using System.Net;
    using System.Net.NetworkInformation;
    -using System.Runtime.InteropServices;

namespace Smdn.Net.AddressTables;

@@ -96,14 +95,6 @@ public readonly struct AddressTableEntry : IEquatable, IEquat
=> $"{{IP={IPAddress}, MAC={PhysicalAddress?.ToMacAddressString() ?? "(null)"}, IsPermanent={IsPermanent}, State={State}, Iface={InterfaceId}}}";

private sealed class EqualityComparer : EqualityComparer {

  • // On Windows, NetworkInterface.Id is set to a string representing

  • // the GUID of the network interface, but its casing conventions is

  • // not specified explicitly, so perform the case-insensitive comparison.

  • private static readonly StringComparer interfaceIdComparer =

  •  RuntimeInformation.IsOSPlatform(OSPlatform.Windows)
    
  •    ? StringComparer.OrdinalIgnoreCase
    
  •    : StringComparer.Ordinal;
    
  • private readonly bool compareExceptState;

    public EqualityComparer(bool compareExceptState)
    @@ -112,7 +103,7 @@ public readonly struct AddressTableEntry : IEquatable, IEquat
    }

    internal static bool InterfaceIdEquals(string? x, string? y)

  •  => interfaceIdComparer.Equals(x, y);
    
  •  => NetworkInterfaceIdComparer.Comparer.Equals(x, y);
    

    public override bool Equals(AddressTableEntry x, AddressTableEntry y)
    =>
    @@ -125,7 +116,7 @@ public readonly struct AddressTableEntry : IEquatable, IEquat
    public override int GetHashCode(AddressTableEntry obj)
    {
    static int GetHashCodeForInterfaceId(AddressTableEntry obj)

  •    => obj.InterfaceId is null ? 0 : interfaceIdComparer.GetHashCode(obj.InterfaceId);
    
  •    => obj.InterfaceId is null ? 0 : NetworkInterfaceIdComparer.Comparer.GetHashCode(obj.InterfaceId);
    

#if SYSTEM_HASHCODE
return HashCode.Combine(
diff --git a/src/Smdn.Net.AddressResolution/Smdn.Net.AddressTables/ProcfsArpAddressTable.cs b/src/Smdn.Net.AddressResolution/Smdn.Net.AddressTables/ProcfsArpAddressTable.cs
index a2f9da2..14d1b62 100644
--- a/src/Smdn.Net.AddressResolution/Smdn.Net.AddressTables/ProcfsArpAddressTable.cs
+++ b/src/Smdn.Net.AddressResolution/Smdn.Net.AddressTables/ProcfsArpAddressTable.cs
@@ -102,8 +102,8 @@ public sealed class ProcfsArpAddressTable : AddressTable {

// [/proc/net/arp]
// IP address HW type Flags HW address Mask Device

  • // 192.168.0.1 0x1 0x0 00:00:00:00:00:00 * eth0
  • // 192.168.0.2 0x1 0x0 00:00:00:00:00:00 * eth0
  • // 192.0.2.1 0x1 0x0 00:00:00:00:00:00 * eth0

  • // 192.0.2.2 0x1 0x0 00:00:00:00:00:00 * eth0
    // : : : : : :
    private static bool TryParse(
    string arpTableEntryLine,
    diff --git a/src/Smdn.Net.AddressResolution/Smdn.Net/IPNetworkProfile.CreateFromNetworkInterface.cs b/src/Smdn.Net.AddressResolution/Smdn.Net/IPNetworkProfile.CreateFromNetworkInterface.cs
    index dafc71d..2189da7 100644
    --- a/src/Smdn.Net.AddressResolution/Smdn.Net/IPNetworkProfile.CreateFromNetworkInterface.cs
    +++ b/src/Smdn.Net.AddressResolution/Smdn.Net/IPNetworkProfile.CreateFromNetworkInterface.cs
    @@ -11,9 +11,71 @@ namespace Smdn.Net;
    partial class IPNetworkProfile {
    #pragma warning restore IDE0040

  • ///

  • /// Creates an using the first found.

  • ///

  • /// The appropriate could not be selected.
    public static IPNetworkProfile Create()
    => Create(predicateForNetworkInterface: static _ => true /* select first one */);

  • ///

  • /// Creates an using

  • /// which has GUID specified by .

  • ///

  • /// A for selecting a specific network interface.

  • /// The appropriate could not be selected.

  • public static IPNetworkProfile CreateFromNetworkInterface(Guid id)

  • // On Windows OS, GUID in 'B' format is used for the network interface ID.

  • => CreateFromNetworkInterface(id: id.ToString("B", provider: null));

  • ///

  • /// Creates an using

  • /// which has ID specified by .

  • ///

  • /// An ID for selecting a specific network interface.

  • /// The appropriate could not be selected.

  • public static IPNetworkProfile CreateFromNetworkInterface(string id)

  • {

  • if (id is null)

  •  throw new ArgumentNullException(nameof(id));
    
  • return Create(predicateForNetworkInterface: iface => string.Equals(iface.Id, id, NetworkInterfaceIdComparer.Comparison));

  • }

  • ///

  • /// Creates an using

  • /// whose physical address equals to .

  • ///

  • /// A for selecting a specific network interface.

  • /// The appropriate could not be selected.

  • public static IPNetworkProfile CreateFromNetworkInterface(PhysicalAddress physicalAddress)

  • {

  • if (physicalAddress is null)

  •  throw new ArgumentNullException(nameof(physicalAddress));
    
  • return Create(predicateForNetworkInterface: iface => physicalAddress.Equals(iface.GetPhysicalAddress()));

  • }

  • ///

  • /// Creates an using

  • /// which has the name specified by .

  • ///

  • /// A name for selecting a specific network interface.

  • /// The appropriate could not be selected.

  • public static IPNetworkProfile CreateFromNetworkInterfaceName(string name)

  • {

  • if (name is null)

  •  throw new ArgumentNullException(nameof(name));
    
  • return Create(predicateForNetworkInterface: iface => string.Equals(iface.Name, name, StringComparison.Ordinal));

  • }

  • ///

  • /// Creates an using

  • /// which specified by .

  • ///

  • /// A for selecting a specific network interface.

  • /// The appropriate could not be selected.
    public static IPNetworkProfile Create(Predicate predicateForNetworkInterface)
    {
    if (predicateForNetworkInterface is null)
    @@ -34,6 +96,10 @@ partial class IPNetworkProfile {
    throw new InvalidOperationException("The appropriate network interface was not selected.");
    }

  • ///

  • /// Creates an using .

  • ///

  • /// A describing the network used by .
    public static IPNetworkProfile Create(NetworkInterface networkInterface)
    {
    if (networkInterface is null)
    diff --git a/src/Smdn.Net.AddressResolution/Smdn.Net/IPNetworkProfile.cs b/src/Smdn.Net.AddressResolution/Smdn.Net/IPNetworkProfile.cs
    index 7423c49..f656eba 100644
    --- a/src/Smdn.Net.AddressResolution/Smdn.Net/IPNetworkProfile.cs
    +++ b/src/Smdn.Net.AddressResolution/Smdn.Net/IPNetworkProfile.cs
    @@ -7,6 +7,14 @@ using System.Net.NetworkInformation;

namespace Smdn.Net;

+///

Defines the target network interface and/or the network address range.
+///
+/// uses to specify a
+/// range of network addresses when performing address resolution and network scanning,
+/// as well as the target network interface to be scanned.
+///
+///
+///
public abstract partial class IPNetworkProfile {
private static Exception CreateIPv6FeatureNotImplemented()
=> new NotImplementedException("IPv6 is not supported yet. Please contribute to the implementation of the feature.");
diff --git a/src/Smdn.Net.AddressResolution/Smdn.Net/NetworkInterfaceIdComparer.cs b/src/Smdn.Net.AddressResolution/Smdn.Net/NetworkInterfaceIdComparer.cs
new file mode 100644
index 0000000..bacb61a
--- /dev/null
+++ b/src/Smdn.Net.AddressResolution/Smdn.Net/NetworkInterfaceIdComparer.cs
@@ -0,0 +1,29 @@
+// SPDX-FileCopyrightText: 2023 smdn smdn@smdn.jp
+// SPDX-License-Identifier: MIT
+using System;
+using System.Runtime.InteropServices;
+
+namespace Smdn.Net;
+
+///
+/// Provides and for comparing the network interface ID strings.
+///

+///
+/// On Windows,
+/// is set to a string representing the GUID of the network interface,
+/// but its casing conventions is not specified explicitly, so perform the
+/// case-insensitive comparison.
+///
+internal static class NetworkInterfaceIdComparer {

  • /// for comparing the network interface ID strings.
  • public static readonly StringComparer Comparer =
  • RuntimeInformation.IsOSPlatform(OSPlatform.Windows)
  •  ? StringComparer.OrdinalIgnoreCase
    
  •  : StringComparer.Ordinal;
    
  • /// for comparing the network interface ID strings.
  • public static readonly StringComparison Comparison =
  • RuntimeInformation.IsOSPlatform(OSPlatform.Windows)
  •  ? StringComparison.OrdinalIgnoreCase
    
  •  : StringComparison.Ordinal;
    

+}


</div>
</details>

## Notes
<!-- Release notes generated using configuration in .github/release.yml at releases/Smdn.Net.AddressResolution-1.0.1 -->



**Full Changelog**: https://github.com/smdn/Smdn.Net.AddressResolution/compare/releases/Smdn.Net.AddressResolution-1.0.0...releases/Smdn.Net.AddressResolution-1.0.1