Skip to content

Commit

Permalink
split range operators of IPv4 and IPv6
Browse files Browse the repository at this point in the history
  • Loading branch information
jsakamoto committed Aug 18, 2020
1 parent 12107bb commit 4f75699
Show file tree
Hide file tree
Showing 6 changed files with 586 additions and 21 deletions.
32 changes: 11 additions & 21 deletions IPAddressRange/IPAddressRange.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using System.Net;
using System.Text.RegularExpressions;
using System.ComponentModel;
using NetTools.Internals;

#if NET45
using System.Runtime.Serialization;
Expand Down Expand Up @@ -78,6 +79,8 @@ public class IPAddressRange : IEnumerable<IPAddress>, IReadOnlyDictionary<string

public IPAddress End { get; set; }

private IRangeOperator Operator { get; set; }

/// <summary>
/// Creates an empty range object, equivalent to "0.0.0.0/0".
/// </summary>
Expand All @@ -93,6 +96,7 @@ public IPAddressRange(IPAddress singleAddress)
throw new ArgumentNullException(nameof(singleAddress));

Begin = End = singleAddress;
Operator = RangeOperatorFactory.Create(this);
}

/// <summary>
Expand All @@ -116,6 +120,8 @@ public IPAddressRange(IPAddress begin, IPAddress end)
if (Begin.AddressFamily != End.AddressFamily) throw new ArgumentException("Elements must be of the same address family", nameof(end));

if (!Bits.GtECore(endBytes, beginBytes)) throw new ArgumentException("Begin must be smaller than the End", nameof(begin));

Operator = RangeOperatorFactory.Create(this);
}

/// <summary>
Expand Down Expand Up @@ -145,6 +151,7 @@ public IPAddressRange(string ipRangeString)
var parsed = Parse(ipRangeString);
Begin = parsed.Begin;
End = parsed.End;
Operator = RangeOperatorFactory.Create(this);
}

#if NET45
Expand All @@ -159,6 +166,7 @@ protected IPAddressRange(SerializationInfo info, StreamingContext context)

this.Begin = deserialize("Begin");
this.End = deserialize("End");
Operator = RangeOperatorFactory.Create(this);
}

public virtual void GetObjectData(SerializationInfo info, StreamingContext context)
Expand All @@ -177,14 +185,7 @@ public bool Contains(IPAddress ipaddress)

if (ipaddress.AddressFamily != this.Begin.AddressFamily) return false;

var offset = 0;
if (Begin.IsIPv4MappedToIPv6 && ipaddress.IsIPv4MappedToIPv6)
{
offset = 12; //ipv4 has prefix of 10 zero bytes and two 255 bytes.
}

var adrBytes = ipaddress.GetAddressBytes();
return Bits.LtECore(this.Begin.GetAddressBytes(), adrBytes, offset) && Bits.GtECore(this.End.GetAddressBytes(), adrBytes, offset);
return Operator.Contains(ipaddress);
}

public bool Contains(IPAddressRange range)
Expand All @@ -194,15 +195,7 @@ public bool Contains(IPAddressRange range)

if (this.Begin.AddressFamily != range.Begin.AddressFamily) return false;

var offset = 0;
if (Begin.IsIPv4MappedToIPv6 && range.Begin.IsIPv4MappedToIPv6)
{
offset = 12; //ipv4 has prefix of 10 zero bytes and two 255 bytes.
}

return
Bits.LtECore(this.Begin.GetAddressBytes(), range.Begin.GetAddressBytes(), offset) &&
Bits.GtECore(this.End.GetAddressBytes(), range.End.GetAddressBytes(), offset);
return Operator.Contains(range);
}

public static IPAddressRange Parse(string ipRangeString)
Expand Down Expand Up @@ -324,10 +317,7 @@ public static int SubnetMaskLength(IPAddress subnetMask)

public IEnumerator<IPAddress> GetEnumerator()
{
var first = Begin.GetAddressBytes();
var last = End.GetAddressBytes();
for (var ip = first; Bits.LtECore(ip, last); ip = Bits.Increment(ip))
yield return new IPAddress(ip);
return Operator.GetEnumerator();
}

IEnumerator IEnumerable.GetEnumerator()
Expand Down
48 changes: 48 additions & 0 deletions IPAddressRange/Internals/IPv4RangeOperator.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
using System.Collections.Generic;
using System.Net;

namespace NetTools.Internals
{
internal class IPv4RangeOperator : IRangeOperator
{
private IPAddressRange Range { get; }

public IPv4RangeOperator(IPAddressRange range)
{
this.Range = range;
}

public bool Contains(IPAddress ipaddress)
{
var offset = 0;
if (Range.Begin.IsIPv4MappedToIPv6 && ipaddress.IsIPv4MappedToIPv6)
{
offset = 12; //ipv4 has prefix of 10 zero bytes and two 255 bytes.
}

var adrBytes = ipaddress.GetAddressBytes();
return Bits.LtECore(this.Range.Begin.GetAddressBytes(), adrBytes, offset) && Bits.GtECore(this.Range.End.GetAddressBytes(), adrBytes, offset);
}

public bool Contains(IPAddressRange range)
{
var offset = 0;
if (Range.Begin.IsIPv4MappedToIPv6 && range.Begin.IsIPv4MappedToIPv6)
{
offset = 12; //ipv4 has prefix of 10 zero bytes and two 255 bytes.
}

return
Bits.LtECore(Range.Begin.GetAddressBytes(), range.Begin.GetAddressBytes(), offset) &&
Bits.GtECore(Range.End.GetAddressBytes(), range.End.GetAddressBytes(), offset);
}

public IEnumerator<IPAddress> GetEnumerator()
{
var first = Range.Begin.GetAddressBytes();
var last = Range.End.GetAddressBytes();
for (var ip = first; Bits.LtECore(ip, last); ip = Bits.Increment(ip))
yield return new IPAddress(ip);
}
}
}
48 changes: 48 additions & 0 deletions IPAddressRange/Internals/IPv6RangeOperator.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
using System.Collections.Generic;
using System.Net;

namespace NetTools.Internals
{
internal class IPv6RangeOperator : IRangeOperator
{
private IPAddressRange Range { get; }

public IPv6RangeOperator(IPAddressRange range)
{
this.Range = range;
}

public bool Contains(IPAddress ipaddress)
{
var offset = 0;
if (Range.Begin.IsIPv4MappedToIPv6 && ipaddress.IsIPv4MappedToIPv6)
{
offset = 12; //ipv4 has prefix of 10 zero bytes and two 255 bytes.
}

var adrBytes = ipaddress.GetAddressBytes();
return Bits.LtECore(this.Range.Begin.GetAddressBytes(), adrBytes, offset) && Bits.GtECore(this.Range.End.GetAddressBytes(), adrBytes, offset);
}

public bool Contains(IPAddressRange range)
{
var offset = 0;
if (Range.Begin.IsIPv4MappedToIPv6 && range.Begin.IsIPv4MappedToIPv6)
{
offset = 12; //ipv4 has prefix of 10 zero bytes and two 255 bytes.
}

return
Bits.LtECore(Range.Begin.GetAddressBytes(), range.Begin.GetAddressBytes(), offset) &&
Bits.GtECore(Range.End.GetAddressBytes(), range.End.GetAddressBytes(), offset);
}

public IEnumerator<IPAddress> GetEnumerator()
{
var first = Range.Begin.GetAddressBytes();
var last = Range.End.GetAddressBytes();
for (var ip = first; Bits.LtECore(ip, last); ip = Bits.Increment(ip))
yield return new IPAddress(ip);
}
}
}
12 changes: 12 additions & 0 deletions IPAddressRange/Internals/IRangeOperator.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
using System.Collections.Generic;
using System.Net;

namespace NetTools.Internals
{
internal interface IRangeOperator
{
bool Contains(IPAddress ipaddress);
bool Contains(IPAddressRange range);
IEnumerator<IPAddress> GetEnumerator();
}
}
14 changes: 14 additions & 0 deletions IPAddressRange/Internals/RangeOperatorFactory.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
using System.Net.Sockets;

namespace NetTools.Internals
{
internal static class RangeOperatorFactory
{
public static IRangeOperator Create(IPAddressRange range)
{
return range.Begin.AddressFamily == AddressFamily.InterNetwork ?
new IPv4RangeOperator(range) :
new IPv6RangeOperator(range) as IRangeOperator;
}
}
}
Loading

0 comments on commit 4f75699

Please sign in to comment.