1
0

Added IPAddress.Increment/Decrement; Added ParseNetwork, ExpandNetwork

This commit is contained in:
2022-07-24 01:56:44 +02:00
parent 4938becdd7
commit e449176682
5 changed files with 196 additions and 17 deletions

View File

@@ -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">

View 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);
}
}
}

View File

@@ -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))

View File

@@ -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)

View 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());
}
}
}