Added IPAddress.Increment/Decrement; Added ParseNetwork, ExpandNetwork
This commit is contained in:
@@ -37,6 +37,7 @@
|
||||
|
||||
<ItemGroup>
|
||||
<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="Unclassified.DeepConvert" Version="1.4.0" />
|
||||
<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.NetworkInformation;
|
||||
using System.Net.Sockets;
|
||||
using Microsoft.AspNetCore.HttpOverrides;
|
||||
|
||||
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)
|
||||
{
|
||||
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
|
||||
### 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
|
||||
- `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
|
||||
- Updated all package references to latest builds (as on 2022-07-23)
|
||||
|
||||
### 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
|
||||
### Added
|
||||
- `BasicAuthenticationAttribute` sets the `HttpContext.User` property when successfully validated.
|
||||
- `BasicAuthenticationAttribute` sets the `HttpContext.User` property when successfully validated
|
||||
|
||||
### Changed
|
||||
- Moved `BasicAuthenticationAttribute` from `ActionFilter` to `IAsyncAuthorizationFilter`.
|
||||
- Moved `BasicAuthenticationAttribute` from `ActionFilter` to `IAsyncAuthorizationFilter`
|
||||
|
||||
### 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
|
||||
### Changed
|
||||
- All attributes now reside in `Microsoft.AspNetCore.Mvc.Filters` namespace.
|
||||
- All attributes now reside in `Microsoft.AspNetCore.Mvc.Filters` namespace
|
||||
|
||||
### 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
|
||||
### Changed
|
||||
- `BasicAuthenticationAttribute` is now in namespace `AMWD.Common.AspNetCore.Attributes`.
|
||||
- `BasicAuthenticationAttribute` is now in namespace `AMWD.Common.AspNetCore.Attributes`
|
||||
|
||||
### Fixed
|
||||
- Fixed problem with `ForbidResult` without having an authentication schema defined.
|
||||
Now only HTTP Status 403 (Forbid) is returned.
|
||||
- Fixed problem with `ForbidResult` without having an authentication schema defined
|
||||
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
|
||||
@@ -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
|
||||
### 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
|
||||
### Added
|
||||
- `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)
|
||||
- `HttpContext.IsLocalRequest()` to determine whether the request was from local or remote.
|
||||
- `IPWhitelistAttribute` and `IPBlacklistAttribute` to allow/restrict access on specific controllers/actions.
|
||||
- `HttpContext.IsLocalRequest()` to determine whether the request was from local or remote
|
||||
- `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
|
||||
@@ -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
|
||||
### 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
|
||||
### Added
|
||||
- `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
|
||||
- `ApplyMigrationsAsync` uses `WaitAvailableAsync` internally.
|
||||
- `ApplyMigrationsAsync` uses `WaitAvailableAsync` internally
|
||||
|
||||
### Fixed
|
||||
- `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