Added IPAddress.Increment/Decrement; Added ParseNetwork, ExpandNetwork
This commit is contained in:
@@ -37,6 +37,7 @@
|
|||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Dns" Version="7.0.0" />
|
<PackageReference Include="Dns" Version="7.0.0" />
|
||||||
|
<PackageReference Include="Microsoft.AspNetCore.HttpOverrides" Version="2.2.0" />
|
||||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
|
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
|
||||||
<PackageReference Include="Unclassified.DeepConvert" Version="1.4.0" />
|
<PackageReference Include="Unclassified.DeepConvert" Version="1.4.0" />
|
||||||
<PackageReference Include="Unclassified.NetRevisionTask" Version="0.4.3">
|
<PackageReference Include="Unclassified.NetRevisionTask" Version="0.4.3">
|
||||||
|
|||||||
46
AMWD.Common/Extensions/IPAddressExtensions.cs
Normal file
46
AMWD.Common/Extensions/IPAddressExtensions.cs
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
namespace System.Net
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Provides extension methods for <see cref="IPAddress"/>es.
|
||||||
|
/// </summary>
|
||||||
|
public static class IPAddressExtensions
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Increments the <see cref="IPAddress"/> by one and returns a new instance.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="address">The <see cref="IPAddress"/> to increment.</param>
|
||||||
|
public static IPAddress Increment(this IPAddress address)
|
||||||
|
{
|
||||||
|
byte[] bytes = address.GetAddressBytes();
|
||||||
|
int bytePos = bytes.Length - 1;
|
||||||
|
|
||||||
|
while (bytes[bytePos] == byte.MaxValue)
|
||||||
|
{
|
||||||
|
bytes[bytePos] = 0;
|
||||||
|
bytePos--;
|
||||||
|
}
|
||||||
|
bytes[bytePos]++;
|
||||||
|
|
||||||
|
return new IPAddress(bytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Decrements the <see cref="IPAddress"/> by one and returns a new instance.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="address">The <see cref="IPAddress"/> to decrement.</param>
|
||||||
|
public static IPAddress Decrement(this IPAddress address)
|
||||||
|
{
|
||||||
|
byte[] bytes = address.GetAddressBytes();
|
||||||
|
int bytePos = bytes.Length - 1;
|
||||||
|
|
||||||
|
while (bytes[bytePos] == 0)
|
||||||
|
{
|
||||||
|
bytes[bytePos] = byte.MaxValue;
|
||||||
|
bytePos--;
|
||||||
|
}
|
||||||
|
bytes[bytePos]--;
|
||||||
|
|
||||||
|
return new IPAddress(bytes);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -4,6 +4,7 @@ using System.Linq;
|
|||||||
using System.Net;
|
using System.Net;
|
||||||
using System.Net.NetworkInformation;
|
using System.Net.NetworkInformation;
|
||||||
using System.Net.Sockets;
|
using System.Net.Sockets;
|
||||||
|
using Microsoft.AspNetCore.HttpOverrides;
|
||||||
|
|
||||||
namespace AMWD.Common.Utilities
|
namespace AMWD.Common.Utilities
|
||||||
{
|
{
|
||||||
@@ -77,6 +78,66 @@ namespace AMWD.Common.Utilities
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Parses a CIDR network definition.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="network">The network in CIDR.</param>
|
||||||
|
/// <returns>The <see cref="IPNetwork"/> or <c>null</c>.</returns>
|
||||||
|
public static IPNetwork ParseNetwork(string network)
|
||||||
|
{
|
||||||
|
TryParseNetwork(network, out var ipNetwork);
|
||||||
|
return ipNetwork;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Tries to parse a CIDR network definition.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="network">The network in CIDR.</param>
|
||||||
|
/// <param name="ipNetwork">The parsed <see cref="IPNetwork"/>.</param>
|
||||||
|
/// <returns><c>true</c> on success, otherwise <c>false</c>.</returns>
|
||||||
|
public static bool TryParseNetwork(string network, out IPNetwork ipNetwork)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
string[] parts = network.Split('/');
|
||||||
|
if (parts.Length != 2)
|
||||||
|
throw new ArgumentException($"Invalid network type");
|
||||||
|
|
||||||
|
var prefix = IPAddress.Parse(parts.First());
|
||||||
|
int prefixLength = int.Parse(parts.Last());
|
||||||
|
|
||||||
|
ipNetwork = new IPNetwork(prefix, prefixLength);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
ipNetwork = null;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Uses the <see cref="IPNetwork"/> and expands the whole subnet.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// The network identifier and the broadcast address are included in the response list.
|
||||||
|
/// </remarks>
|
||||||
|
/// <param name="network">The <see cref="IPNetwork"/> to expand.</param>
|
||||||
|
/// <returns>A list with all valid <see cref="IPAddress"/>es.</returns>
|
||||||
|
public static List<IPAddress> ExpandNetwork(this IPNetwork network)
|
||||||
|
{
|
||||||
|
var list = new List<IPAddress>();
|
||||||
|
|
||||||
|
var ipAddress = network.Prefix;
|
||||||
|
while (network.Contains(ipAddress))
|
||||||
|
{
|
||||||
|
list.Add(ipAddress);
|
||||||
|
ipAddress = ipAddress.Increment();
|
||||||
|
}
|
||||||
|
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
private static IPAddress ResolveIpAddress(string address, AddressFamily addressFamily)
|
private static IPAddress ResolveIpAddress(string address, AddressFamily addressFamily)
|
||||||
{
|
{
|
||||||
if (IPAddress.TryParse(address, out var ipAddress))
|
if (IPAddress.TryParse(address, out var ipAddress))
|
||||||
|
|||||||
38
CHANGELOG.md
38
CHANGELOG.md
@@ -6,42 +6,46 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
|
|
||||||
## [Unreleased](https://git.am-wd.de/AM.WD/common/compare/v1.6.1...master) - 0000-00-00
|
## [Unreleased](https://git.am-wd.de/AM.WD/common/compare/v1.6.1...master) - 0000-00-00
|
||||||
### Added
|
### Added
|
||||||
- UnitTests for `AspNetCore` as far as testable without massive work.
|
- UnitTests for `AspNetCore` as far as testable without massive work
|
||||||
|
- `IPAddress.Increment` and `IPAddress.Decrement` extensions
|
||||||
|
- `NetworkHelper.ParseNetwork` and `NetworkHelper.TryParseNetwork` to parse a CIDR (e.g. 192.168.178.0/24) network
|
||||||
|
- `IPNetwork.ExpandNetwork` to create a list with all contained `IPAddress`es
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
- `BasicAuthenticationAttribute` now respects the `IBasicAuthenticationValidator.Realm` when the own `Realm` property is not set.
|
- `BasicAuthenticationAttribute` now respects the `IBasicAuthenticationValidator.Realm` when the own `Realm` property is not set
|
||||||
- CI scripts
|
- CI scripts
|
||||||
|
- Updated all package references to latest builds (as on 2022-07-23)
|
||||||
|
|
||||||
### Removed
|
### Removed
|
||||||
- `IBasicAuthenticationValidator.Realm` is now a read-only property (removed public set).
|
- `IBasicAuthenticationValidator.Realm` is now a read-only property (removed public set)
|
||||||
|
|
||||||
|
|
||||||
## [v1.6.1](https://git.am-wd.de/AM.WD/common/compare/v1.6.0...v1.6.1) - 2022-06-23
|
## [v1.6.1](https://git.am-wd.de/AM.WD/common/compare/v1.6.0...v1.6.1) - 2022-06-23
|
||||||
### Added
|
### Added
|
||||||
- `BasicAuthenticationAttribute` sets the `HttpContext.User` property when successfully validated.
|
- `BasicAuthenticationAttribute` sets the `HttpContext.User` property when successfully validated
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
- Moved `BasicAuthenticationAttribute` from `ActionFilter` to `IAsyncAuthorizationFilter`.
|
- Moved `BasicAuthenticationAttribute` from `ActionFilter` to `IAsyncAuthorizationFilter`
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
- `TimeSpan.ToShortString()` is now capable of negative values.
|
- `TimeSpan.ToShortString()` is now capable of negative values
|
||||||
|
|
||||||
|
|
||||||
## [v1.6.0](https://git.am-wd.de/AM.WD/common/compare/v1.5.3...v1.6.0) - 2022-06-22
|
## [v1.6.0](https://git.am-wd.de/AM.WD/common/compare/v1.5.3...v1.6.0) - 2022-06-22
|
||||||
### Changed
|
### Changed
|
||||||
- All attributes now reside in `Microsoft.AspNetCore.Mvc.Filters` namespace.
|
- All attributes now reside in `Microsoft.AspNetCore.Mvc.Filters` namespace
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
- Fixed `BasicAuthenticationAttribute`.
|
- Fixed `BasicAuthenticationAttribute`
|
||||||
|
|
||||||
|
|
||||||
## [v1.5.3](https://git.am-wd.de/AM.WD/common/compare/v1.5.2...v1.5.3) - 2022-06-22
|
## [v1.5.3](https://git.am-wd.de/AM.WD/common/compare/v1.5.2...v1.5.3) - 2022-06-22
|
||||||
### Changed
|
### Changed
|
||||||
- `BasicAuthenticationAttribute` is now in namespace `AMWD.Common.AspNetCore.Attributes`.
|
- `BasicAuthenticationAttribute` is now in namespace `AMWD.Common.AspNetCore.Attributes`
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
- Fixed problem with `ForbidResult` without having an authentication schema defined.
|
- Fixed problem with `ForbidResult` without having an authentication schema defined
|
||||||
Now only HTTP Status 403 (Forbid) is returned.
|
Now only HTTP Status 403 (Forbid) is returned
|
||||||
|
|
||||||
|
|
||||||
## [v1.5.2](https://git.am-wd.de/AM.WD/common/compare/v1.5.1...v1.5.2) - 2022-06-20
|
## [v1.5.2](https://git.am-wd.de/AM.WD/common/compare/v1.5.1...v1.5.2) - 2022-06-20
|
||||||
@@ -51,15 +55,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
|
|
||||||
## [v1.5.1](https://git.am-wd.de/AM.WD/common/compare/v1.5.0...v1.5.1) - 2022-06-20
|
## [v1.5.1](https://git.am-wd.de/AM.WD/common/compare/v1.5.0...v1.5.1) - 2022-06-20
|
||||||
### Changed
|
### Changed
|
||||||
- Changed from `Assembly.GetExecutingAssmebly().Location` to `AppContext.BaseDirectory` due to single-file applications.
|
- Changed from `Assembly.GetExecutingAssmebly().Location` to `AppContext.BaseDirectory` due to single-file applications
|
||||||
|
|
||||||
|
|
||||||
## [v1.5.0](https://git.am-wd.de/AM.WD/common/compare/v1.4.3...v1.5.0) - 2022-06-15
|
## [v1.5.0](https://git.am-wd.de/AM.WD/common/compare/v1.4.3...v1.5.0) - 2022-06-15
|
||||||
### Added
|
### Added
|
||||||
- `TcpClientMoq` to test communication via a `TcpClient`
|
- `TcpClientMoq` to test communication via a `TcpClient`
|
||||||
- EntityFramework Core Converters for new `DateOnly` and `TimeOnly` datatypes when using SQL Server on .NET 6.0 (Bug on Microsoft's EntityFramework)
|
- EntityFramework Core Converters for new `DateOnly` and `TimeOnly` datatypes when using SQL Server on .NET 6.0 (Bug on Microsoft's EntityFramework)
|
||||||
- `HttpContext.IsLocalRequest()` to determine whether the request was from local or remote.
|
- `HttpContext.IsLocalRequest()` to determine whether the request was from local or remote
|
||||||
- `IPWhitelistAttribute` and `IPBlacklistAttribute` to allow/restrict access on specific controllers/actions.
|
- `IPWhitelistAttribute` and `IPBlacklistAttribute` to allow/restrict access on specific controllers/actions
|
||||||
|
|
||||||
|
|
||||||
## [v1.4.3](https://git.am-wd.de/AM.WD/common/compare/v1.4.2...v1.4.3) - 2022-05-12
|
## [v1.4.3](https://git.am-wd.de/AM.WD/common/compare/v1.4.2...v1.4.3) - 2022-05-12
|
||||||
@@ -69,16 +73,16 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
|
|
||||||
## [v1.4.2](https://git.am-wd.de/AM.WD/common/compare/v1.4.1...v1.4.2) - 2022-05-06
|
## [v1.4.2](https://git.am-wd.de/AM.WD/common/compare/v1.4.1...v1.4.2) - 2022-05-06
|
||||||
### Added
|
### Added
|
||||||
- New extension for `StringBuilder` `AppendLine(value: string, newLine: string)` to add a line with a explicit defined new line character.
|
- New extension for `StringBuilder` `AppendLine(value: string, newLine: string)` to add a line with a explicit defined new line character
|
||||||
|
|
||||||
|
|
||||||
## [v1.4.1](https://git.am-wd.de/AM.WD/common/compare/v1.4.0...v1.4.1) - 2022-03-23
|
## [v1.4.1](https://git.am-wd.de/AM.WD/common/compare/v1.4.0...v1.4.1) - 2022-03-23
|
||||||
### Added
|
### Added
|
||||||
- `IntegrityHashTagHelper` can be used with `asp-integrity="true|false"` and `asp-integrity-strength="256|384|512"`
|
- `IntegrityHashTagHelper` can be used with `asp-integrity="true|false"` and `asp-integrity-strength="256|384|512"`
|
||||||
- `WaitAvailableAsync` can be used to wait for a database connection to be available.
|
- `WaitAvailableAsync` can be used to wait for a database connection to be available
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
- `ApplyMigrationsAsync` uses `WaitAvailableAsync` internally.
|
- `ApplyMigrationsAsync` uses `WaitAvailableAsync` internally
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
- `InMemory` database provider does not fail on "migration" (none possible)
|
- `InMemory` database provider does not fail on "migration" (none possible)
|
||||||
|
|||||||
67
UnitTests/Common/Extensions/IPAddressExtensionsTests.cs
Normal file
67
UnitTests/Common/Extensions/IPAddressExtensionsTests.cs
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Net;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||||
|
|
||||||
|
namespace UnitTests.Common.Extensions
|
||||||
|
{
|
||||||
|
[TestClass]
|
||||||
|
[System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage]
|
||||||
|
public class IPAddressExtensionsTests
|
||||||
|
{
|
||||||
|
[TestMethod]
|
||||||
|
public void ShouldIncrementLastByte()
|
||||||
|
{
|
||||||
|
// arrange
|
||||||
|
var ipAddress = IPAddress.Parse("192.168.178.22");
|
||||||
|
|
||||||
|
// act
|
||||||
|
var incremented = ipAddress.Increment();
|
||||||
|
|
||||||
|
// assert
|
||||||
|
Assert.AreEqual("192.168.178.23", incremented.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void ShouldIncrementAllBytes()
|
||||||
|
{
|
||||||
|
// arrange
|
||||||
|
var ipAddress = IPAddress.Parse("192.255.255.255");
|
||||||
|
|
||||||
|
// act
|
||||||
|
var incremented = ipAddress.Increment();
|
||||||
|
|
||||||
|
// assert
|
||||||
|
Assert.AreEqual("193.0.0.0", incremented.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void ShouldDecrementLastByte()
|
||||||
|
{
|
||||||
|
// arrange
|
||||||
|
var ipAddress = IPAddress.Parse("192.168.178.22");
|
||||||
|
|
||||||
|
// act
|
||||||
|
var decremented = ipAddress.Decrement();
|
||||||
|
|
||||||
|
// assert
|
||||||
|
Assert.AreEqual("192.168.178.21", decremented.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void ShouldDecrementAllBytes()
|
||||||
|
{
|
||||||
|
// arrange
|
||||||
|
var ipAddress = IPAddress.Parse("192.0.0.0");
|
||||||
|
|
||||||
|
// act
|
||||||
|
var decremented = ipAddress.Decrement();
|
||||||
|
|
||||||
|
// assert
|
||||||
|
Assert.AreEqual("191.255.255.255", decremented.ToString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user