Skip to content

Commit

Permalink
[2.1] Fix IPNetwork.Contains for prefixes which are not at start of s…
Browse files Browse the repository at this point in the history
…ubnet range. (#50967)

* Fix IPNetwork.Contains behavior for prefixes which are not at start of subnet range.

Backport of 3d00915 to 2.1.

* Update patchconfig.
  • Loading branch information
adityamandaleeka authored Dec 9, 2023
1 parent 1be20f4 commit 5599953
Show file tree
Hide file tree
Showing 3 changed files with 36 additions and 2 deletions.
1 change: 1 addition & 0 deletions eng/PatchConfig.props
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,7 @@ Later on, this will be checked using this condition:
Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv;
Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets;
Microsoft.AspNetCore.SignalR.Redis;
Microsoft.AspNetCore.HttpOverrides;
</PackagesInPatch>
</PropertyGroup>
</Project>
25 changes: 23 additions & 2 deletions src/Middleware/HttpOverrides/src/IPNetwork.cs
Original file line number Diff line number Diff line change
@@ -1,14 +1,17 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.

using System;
using System.Net;
using System.Net.Sockets;

namespace Microsoft.AspNetCore.HttpOverrides
{
public class IPNetwork
{
public IPNetwork(IPAddress prefix, int prefixLength)
{
CheckPrefixLengthRange(prefix, prefixLength);
Prefix = prefix;
PrefixLength = prefixLength;
PrefixBytes = Prefix.GetAddressBytes();
Expand All @@ -20,7 +23,7 @@ public IPNetwork(IPAddress prefix, int prefixLength)
private byte[] PrefixBytes { get; }

/// <summary>
/// The CIDR notation of the subnet mask
/// The CIDR notation of the subnet mask
/// </summary>
public int PrefixLength { get; }

Expand All @@ -36,7 +39,7 @@ public bool Contains(IPAddress address)
var addressBytes = address.GetAddressBytes();
for (int i = 0; i < PrefixBytes.Length && Mask[i] != 0; i++)
{
if (PrefixBytes[i] != (addressBytes[i] & Mask[i]))
if ((PrefixBytes[i] & Mask[i]) != (addressBytes[i] & Mask[i]))
{
return false;
}
Expand All @@ -63,5 +66,23 @@ private byte[] CreateMask()

return mask;
}

private static void CheckPrefixLengthRange(IPAddress prefix, int prefixLength)
{
if (prefixLength < 0)
{
throw new ArgumentOutOfRangeException(nameof(prefixLength));
}

if (prefix.AddressFamily == AddressFamily.InterNetwork && prefixLength > 32)
{
throw new ArgumentOutOfRangeException(nameof(prefixLength));
}

if (prefix.AddressFamily == AddressFamily.InterNetworkV6 && prefixLength > 128)
{
throw new ArgumentOutOfRangeException(nameof(prefixLength));
}
}
}
}
12 changes: 12 additions & 0 deletions src/Middleware/HttpOverrides/test/IPNetworkTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,15 @@ public class IPNetworkTest
[InlineData("174.0.0.0", 7, "175.1.1.10")]
[InlineData("10.174.0.0", 15, "10.175.1.10")]
[InlineData("10.168.0.0", 14, "10.171.1.10")]
[InlineData("192.168.0.1", 31, "192.168.0.0")]
[InlineData("192.168.0.1", 31, "192.168.0.1")]
[InlineData("192.168.0.1", 32, "192.168.0.1")]
[InlineData("192.168.1.1", 0, "0.0.0.0")]
[InlineData("192.168.1.1", 0, "255.255.255.255")]
[InlineData("2001:db8:3c4d::", 127, "2001:db8:3c4d::1")]
[InlineData("2001:db8:3c4d::1", 128, "2001:db8:3c4d::1")]
[InlineData("2001:db8:3c4d::1", 0, "::")]
[InlineData("2001:db8:3c4d::1", 0, "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff")]
public void Contains_Positive(string prefixText, int length, string addressText)
{
var network = new IPNetwork(IPAddress.Parse(prefixText), length);
Expand All @@ -23,6 +32,9 @@ public void Contains_Positive(string prefixText, int length, string addressText)
[InlineData("174.0.0.0", 7, "173.1.1.10")]
[InlineData("10.174.0.0", 15, "10.173.1.10")]
[InlineData("10.168.0.0", 14, "10.172.1.10")]
[InlineData("192.168.0.1", 31, "192.168.0.2")]
[InlineData("192.168.0.1", 32, "192.168.0.0")]
[InlineData("2001:db8:3c4d::", 127, "2001:db8:3c4d::2")]
public void Contains_Negative(string prefixText, int length, string addressText)
{
var network = new IPNetwork(IPAddress.Parse(prefixText), length);
Expand Down

0 comments on commit 5599953

Please sign in to comment.