45

I have a subnet in the format 10.132.0.0/20 and an IP address from the ASP.Net request object.

Is there a .NET framework function to check to see if the IP address is within the given subnet?

If not, how can it be done? Bit manipulation, I guess?

Ryan Michela
  • 8,284
  • 5
  • 33
  • 47
  • Does this answer your question? [How to check a input IP fall in a specific IP range](https://stackoverflow.com/questions/2138706/how-to-check-a-input-ip-fall-in-a-specific-ip-range) – Michael Freidgeim May 01 '22 at 21:23

9 Answers9

41

Take a look at IP Address Calculations with C# on MSDN blogs. It contains an extension method (IsInSameSubnet) that should meet your needs as well as some other goodies.

public static class IPAddressExtensions
{
    public static IPAddress GetBroadcastAddress(this IPAddress address, IPAddress subnetMask)
    {
        byte[] ipAdressBytes = address.GetAddressBytes();
        byte[] subnetMaskBytes = subnetMask.GetAddressBytes();

        if (ipAdressBytes.Length != subnetMaskBytes.Length)
            throw new ArgumentException("Lengths of IP address and subnet mask do not match.");

        byte[] broadcastAddress = new byte[ipAdressBytes.Length];
        for (int i = 0; i < broadcastAddress.Length; i++)
        {
            broadcastAddress[i] = (byte)(ipAdressBytes[i] | (subnetMaskBytes[i] ^ 255));
        }
        return new IPAddress(broadcastAddress);
    }

    public static IPAddress GetNetworkAddress(this IPAddress address, IPAddress subnetMask)
    {
        byte[] ipAdressBytes = address.GetAddressBytes();
        byte[] subnetMaskBytes = subnetMask.GetAddressBytes();

        if (ipAdressBytes.Length != subnetMaskBytes.Length)
            throw new ArgumentException("Lengths of IP address and subnet mask do not match.");

        byte[] broadcastAddress = new byte[ipAdressBytes.Length];
        for (int i = 0; i < broadcastAddress.Length; i++)
        {
            broadcastAddress[i] = (byte)(ipAdressBytes[i] & (subnetMaskBytes[i]));
        }
        return new IPAddress(broadcastAddress);
    }

    public static bool IsInSameSubnet(this IPAddress address2, IPAddress address, IPAddress subnetMask)
    {
        IPAddress network1 = address.GetNetworkAddress(subnetMask);
        IPAddress network2 = address2.GetNetworkAddress(subnetMask);

        return network1.Equals(network2);
    }
}
jmoreno
  • 12,752
  • 4
  • 60
  • 91
Chris Shouts
  • 5,377
  • 2
  • 29
  • 40
34

Using the answers from Thomas and Chris together with Ciscos Subnetting Examples I finally got something to work for IPv4 and IPv6 if you use the CIDR notation (IPAddress/PrefixLength). My IPv6-Implementation might be a bit too straight forward but as there is no UInt128-datatype I couldn't adapt Thomas's solution. Here is the code that seems to work well:

public static bool IsInSubnet(this IPAddress address, string subnetMask)
{
    var slashIdx = subnetMask.IndexOf("/");
    if (slashIdx == -1)
    { // We only handle netmasks in format "IP/PrefixLength".
        throw new NotSupportedException("Only SubNetMasks with a given prefix length are supported.");
    }

    // First parse the address of the netmask before the prefix length.
    var maskAddress = IPAddress.Parse(subnetMask.Substring(0, slashIdx));

    if (maskAddress.AddressFamily != address.AddressFamily)
    { // We got something like an IPV4-Address for an IPv6-Mask. This is not valid.
        return false;
    }

    // Now find out how long the prefix is.
    int maskLength = int.Parse(subnetMask.Substring(slashIdx + 1));

    if (maskLength == 0)
    {
        return true;
    }

    if (maskLength < 0)
    {
        throw new NotSupportedException("A Subnetmask should not be less than 0.");
    }

    if (maskAddress.AddressFamily == AddressFamily.InterNetwork)
    {
        // Convert the mask address to an unsigned integer.
        var maskAddressBits = BitConverter.ToUInt32(maskAddress.GetAddressBytes().Reverse().ToArray(), 0);

        // And convert the IpAddress to an unsigned integer.
        var ipAddressBits = BitConverter.ToUInt32(address.GetAddressBytes().Reverse().ToArray(), 0);

        // Get the mask/network address as unsigned integer.
        uint mask = uint.MaxValue << (32 - maskLength);

        // https://stackoverflow.com/a/1499284/3085985
        // Bitwise AND mask and MaskAddress, this should be the same as mask and IpAddress
        // as the end of the mask is 0000 which leads to both addresses to end with 0000
        // and to start with the prefix.
        return (maskAddressBits & mask) == (ipAddressBits & mask);
    }

    if (maskAddress.AddressFamily == AddressFamily.InterNetworkV6)
    {
        // Convert the mask address to a BitArray. Reverse the BitArray to compare the bits of each byte in the right order.
        var maskAddressBits = new BitArray(maskAddress.GetAddressBytes().Reverse().ToArray());

        // And convert the IpAddress to a BitArray. Reverse the BitArray to compare the bits of each byte in the right order.
        var ipAddressBits = new BitArray(address.GetAddressBytes().Reverse().ToArray());
        var ipAddressLength = ipAddressBits.Length;

        if (maskAddressBits.Length != ipAddressBits.Length)
        {
            throw new ArgumentException("Length of IP Address and Subnet Mask do not match.");
        }

        // Compare the prefix bits.
        for (var i = ipAddressLength - 1; i >= ipAddressLength - maskLength; i--)
        {
            if (ipAddressBits[i] != maskAddressBits[i])
            {
                return false;
            }
        }

        return true;
    }

    throw new NotSupportedException("Only InterNetworkV6 or InterNetwork address families are supported.");
}

And this are the XUnit tests I tested it with:

public class IpAddressExtensionsTests
{
    [Theory]
    [InlineData("192.168.5.85/24", "192.168.5.1")]
    [InlineData("192.168.5.85/24", "192.168.5.254")]
    [InlineData("10.128.240.50/30", "10.128.240.48")]
    [InlineData("10.128.240.50/30", "10.128.240.49")]
    [InlineData("10.128.240.50/30", "10.128.240.50")]
    [InlineData("10.128.240.50/30", "10.128.240.51")]
    [InlineData("192.168.5.85/0", "0.0.0.0")]
    [InlineData("192.168.5.85/0", "255.255.255.255")]
    public void IpV4SubnetMaskMatchesValidIpAddress(string netMask, string ipAddress)
    {
        var ipAddressObj = IPAddress.Parse(ipAddress);
        Assert.True(ipAddressObj.IsInSubnet(netMask));
    }

    [Theory]
    [InlineData("192.168.5.85/24", "192.168.4.254")]
    [InlineData("192.168.5.85/24", "191.168.5.254")]
    [InlineData("10.128.240.50/30", "10.128.240.47")]
    [InlineData("10.128.240.50/30", "10.128.240.52")]
    [InlineData("10.128.240.50/30", "10.128.239.50")]
    [InlineData("10.128.240.50/30", "10.127.240.51")]
    public void IpV4SubnetMaskDoesNotMatchInvalidIpAddress(string netMask, string ipAddress)
    {
        var ipAddressObj = IPAddress.Parse(ipAddress);
        Assert.False(ipAddressObj.IsInSubnet(netMask));
    }

    [Theory]
    [InlineData("2001:db8:abcd:0012::0/64", "2001:0DB8:ABCD:0012:0000:0000:0000:0000")]
    [InlineData("2001:db8:abcd:0012::0/64", "2001:0DB8:ABCD:0012:FFFF:FFFF:FFFF:FFFF")]
    [InlineData("2001:db8:abcd:0012::0/64", "2001:0DB8:ABCD:0012:0001:0000:0000:0000")]
    [InlineData("2001:db8:abcd:0012::0/64", "2001:0DB8:ABCD:0012:FFFF:FFFF:FFFF:FFF0")]
    [InlineData("2001:db8:abcd:0012::0/128", "2001:0DB8:ABCD:0012:0000:0000:0000:0000")]
    [InlineData("2001:db8:abcd:5678::0/53", "2001:0db8:abcd:5000:0000:0000:0000:0000")]
    [InlineData("2001:db8:abcd:5678::0/53", "2001:0db8:abcd:57ff:ffff:ffff:ffff:ffff")]
    [InlineData("2001:db8:abcd:0012::0/0", "::")]
    [InlineData("2001:db8:abcd:0012::0/0", "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff")]
    public void IpV6SubnetMaskMatchesValidIpAddress(string netMask, string ipAddress)
    {
        var ipAddressObj = IPAddress.Parse(ipAddress);
        Assert.True(ipAddressObj.IsInSubnet(netMask));
    }

    [Theory]
    [InlineData("2001:db8:abcd:0012::0/64", "2001:0DB8:ABCD:0011:FFFF:FFFF:FFFF:FFFF")]
    [InlineData("2001:db8:abcd:0012::0/64", "2001:0DB8:ABCD:0013:0000:0000:0000:0000")]
    [InlineData("2001:db8:abcd:0012::0/64", "2001:0DB8:ABCD:0013:0001:0000:0000:0000")]
    [InlineData("2001:db8:abcd:0012::0/64", "2001:0DB8:ABCD:0011:FFFF:FFFF:FFFF:FFF0")]
    [InlineData("2001:db8:abcd:0012::0/128", "2001:0DB8:ABCD:0012:0000:0000:0000:0001")]
    [InlineData("2001:db8:abcd:5678::0/53", "2001:0db8:abcd:4999:0000:0000:0000:0000")]
    [InlineData("2001:db8:abcd:5678::0/53", "2001:0db8:abcd:5800:0000:0000:0000:0000")]
    public void IpV6SubnetMaskDoesNotMatchInvalidIpAddress(string netMask, string ipAddress)
    {
        var ipAddressObj = IPAddress.Parse(ipAddress);
        Assert.False(ipAddressObj.IsInSubnet(netMask));
    }
}

As base for the tests I used Ciscos Subnetting Examples and IBMs IPV6 address examples.

I hope someone finds this helpful ;)

Christoph Sonntag
  • 4,459
  • 1
  • 24
  • 49
  • In the case of v6 IPs, is there a reason behind converting the byte array to bit array for comparison? – Ankit Aggarwal Mar 11 '20 at 14:03
  • As the prefix length (e.g. /24) represents the amount of bits that are allowed to differ we need to compare the bits - we could compare the bytes for prefix lengths that are dividable by 8, but this will not work for odd prefix lengths like /25. There probably are operations where this is not necessary, but I am no expert in the field of bit comparisons so this was the easiest way I could think of. – Christoph Sonntag Mar 11 '20 at 14:29
  • Thanks. There's one thing I want to point out. Your v6 comparison returns true in case mask length is 0 whereas v4 comparison returns false in case mask length is 0. You should put a 0 mask length check in case of v6. – Ankit Aggarwal Apr 03 '20 at 06:54
  • 1
    Beware, the code for IPv6 does not work for prefixes that are not product of 8! Bytes in constructed `BitArray` are laid out correctly, but bits within them are reversed, making the for loop compare less significant bits of each byte first, which is wrong, but still works when prefix is aligned on a byte. Provided tests do not cover this! – R. V. Jul 30 '21 at 16:56
  • 1
    The correct approach would be to first reverse the bytes before passing them to `BitArray` contructor - `.GetAddressBytes().Reverse().ToArray()` and then `for` loop over the `BitArray` backwards, like this: `for (int i = ipAddressBits.Length - 1; i >= ipAddressBits.Length - maskLength; i--)` – R. V. Jul 30 '21 at 17:37
  • Good catch @R.V. ,thank you very much! I adjusted the code & tests to cover the scenario you described. I also added a check for the mask length to be at least 1 to catch what Ankit described. Can you please have a quick look if it works as expected now? Thanks! – Christoph Sonntag Aug 01 '21 at 10:34
  • After some more thoughts a mask length of 0 should actually return true as it should match all IP adresses - So I changed that one and throw an exception if the mask length is less than 0 now ;) – Christoph Sonntag Aug 01 '21 at 19:03
  • I found it more aligned with NetworkInterface APIs to use a mask for ipv4 and a length for ipv6. I added some examples that also avoid the address bytes allocations here https://dotnetfiddle.net/cuSIBo – eglasius Feb 16 '23 at 15:29
20

Bit manipulation works. Stuff the IP into a 32-bits unsigned integer, do the same with the subnet's address, &-mask both with 0xFFFFFFFF << (32-20) and compare:

unsigned int net = ..., ip = ...;
int network_bits = 20;
unsigned int mask = 0xFFFFFFFF << (32 - network_bits);
if ((net & mask) == (ip & mask)) {
  // ...
}
Thomas
  • 174,939
  • 50
  • 355
  • 478
  • 1
    Or, if as common, the subnet is given as a number like 255.255.240.0, just stuff the mask into a 32-bit integer instead of the shift. – erikkallen Sep 30 '09 at 16:39
  • 4
    I found the System.Net.IPAddress class helpful for parsing and decomposing IP addresses into bytes – Ryan Michela Sep 30 '09 at 19:12
  • @RyanMichela a single line of C# is always faster and smaller than a library – AaA May 26 '19 at 03:57
  • 1
    This was a great basis for the IPv4-part of the implementation working with IPv6 and IPv4 I added in [my response](https://stackoverflow.com/a/56461160/3085985) - it would be great if you could review it as my head doesn't work with binary operations that well ;) – Christoph Sonntag Jun 05 '19 at 13:14
4

Since the MSDN blog code relies on a broadcast and IPv6 doesn't have one, I don't know if it works with IPv6.

I ended up with these methods (thanks to nu everest). You can get the subnet and mask from a CIDR notation ("1.2.3.4/5") and check whether an adress is within this network or not.

This works for IPv4 and IPv6:

public static class IpAddresses
{
    public static Tuple<IPAddress, IPAddress> GetSubnetAndMaskFromCidr(string cidr)
    {
        var delimiterIndex = cidr.IndexOf('/');
        string ipSubnet = cidr.Substring(0, delimiterIndex);
        string mask = cidr.Substring(delimiterIndex + 1);

        var subnetAddress = IPAddress.Parse(ipSubnet);

        if (subnetAddress.AddressFamily == AddressFamily.InterNetworkV6)
        {
            // ipv6
            var ip = BigInteger.Parse("00FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", NumberStyles.HexNumber) << (128 - int.Parse(mask));

            var maskBytes = new[]
            {
                (byte)((ip & BigInteger.Parse("00FF000000000000000000000000000000", NumberStyles.HexNumber)) >> 120),
                (byte)((ip & BigInteger.Parse("0000FF0000000000000000000000000000", NumberStyles.HexNumber)) >> 112),
                (byte)((ip & BigInteger.Parse("000000FF00000000000000000000000000", NumberStyles.HexNumber)) >> 104),
                (byte)((ip & BigInteger.Parse("00000000FF000000000000000000000000", NumberStyles.HexNumber)) >> 96),
                (byte)((ip & BigInteger.Parse("0000000000FF0000000000000000000000", NumberStyles.HexNumber)) >> 88),
                (byte)((ip & BigInteger.Parse("000000000000FF00000000000000000000", NumberStyles.HexNumber)) >> 80),
                (byte)((ip & BigInteger.Parse("00000000000000FF000000000000000000", NumberStyles.HexNumber)) >> 72),
                (byte)((ip & BigInteger.Parse("0000000000000000FF0000000000000000", NumberStyles.HexNumber)) >> 64),
                (byte)((ip & BigInteger.Parse("000000000000000000FF00000000000000", NumberStyles.HexNumber)) >> 56),
                (byte)((ip & BigInteger.Parse("00000000000000000000FF000000000000", NumberStyles.HexNumber)) >> 48),
                (byte)((ip & BigInteger.Parse("0000000000000000000000FF0000000000", NumberStyles.HexNumber)) >> 40),
                (byte)((ip & BigInteger.Parse("000000000000000000000000FF00000000", NumberStyles.HexNumber)) >> 32),
                (byte)((ip & BigInteger.Parse("00000000000000000000000000FF000000", NumberStyles.HexNumber)) >> 24),
                (byte)((ip & BigInteger.Parse("0000000000000000000000000000FF0000", NumberStyles.HexNumber)) >> 16),
                (byte)((ip & BigInteger.Parse("000000000000000000000000000000FF00", NumberStyles.HexNumber)) >> 8),
                (byte)((ip & BigInteger.Parse("00000000000000000000000000000000FF", NumberStyles.HexNumber)) >> 0),
            };

            return Tuple.Create(subnetAddress, new IPAddress(maskBytes));
        }
        else
        {
            // ipv4
            uint ip = 0xFFFFFFFF << (32 - int.Parse(mask));

            var maskBytes = new[]
            {
                (byte)((ip & 0xFF000000) >> 24),
                (byte)((ip & 0x00FF0000) >> 16),
                (byte)((ip & 0x0000FF00) >> 8),
                (byte)((ip & 0x000000FF) >> 0),
            };

            return Tuple.Create(subnetAddress, new IPAddress(maskBytes));
        }
    }

    public static bool IsAddressOnSubnet(IPAddress address, IPAddress subnet, IPAddress mask)
    {
        byte[] addressOctets = address.GetAddressBytes();
        byte[] subnetOctets = mask.GetAddressBytes();
        byte[] networkOctets = subnet.GetAddressBytes();

        // ensure that IPv4 isn't mixed with IPv6
        if (addressOctets.Length != subnetOctets.Length
            || addressOctets.Length != networkOctets.Length)
        {
            return false;
        }

        for (int i = 0; i < addressOctets.Length; i += 1)
        {
            var addressOctet = addressOctets[i];
            var subnetOctet = subnetOctets[i];
            var networkOctet = networkOctets[i];

            if (networkOctet != (addressOctet & subnetOctet))
            {
                return false;
            }
        }
        return true;
    }
}

Example usage:

var subnetAndMask = IpAddresses.GetSubnetAndMaskFromCidr("10.132.0.0/20");
bool result = IpAddresses.IsAddressOnSubnet(
    IPAddress.Parse("10.132.12.34"),
    subnetAndMask.Item1,
    subnetAndMask.Item2);
Oliver Schimmer
  • 387
  • 2
  • 14
  • I think, I found an exception in your solution. When subnet bits equals to 23, "IsAddressOnSubnet" returned false results. I changed the if line to `if ((networkOctet & subnetOctet) != (addressOctet & subnetOctet))` and it started to return correct results. – Sukru Alatas Jul 09 '18 at 07:24
2

The solution is to convert the IP Address into bytes using System.Net.IPAddress and perform bitwise comparisons on the address, subnet, and mask octets.

The Binary AND Operator & copies a bit to the result if it exists in both operands.

The code:

using System.Net;   // Used to access IPAddress

bool IsAddressOnSubnet(string address, string subnet, string mask)
{
    try
    {
        IPAddress Address = IPAddress.Parse(address);
        IPAddress Subnet = IPAddress.Parse(subnet);
        IPAddress Mask = IPAddress.Parse(mask);            

        Byte[] addressOctets = Address.GetAddressBytes();
        Byte[] subnetOctets = Mask.GetAddressBytes();
        Byte[] networkOctets = Subnet.GetAddressBytes();

        return
            ((networkOctets[0] & subnetOctets[0]) == (addressOctets[0] & subnetOctets[0])) &&
            ((networkOctets[1] & subnetOctets[1]) == (addressOctets[1] & subnetOctets[1])) &&
            ((networkOctets[2] & subnetOctets[2]) == (addressOctets[2] & subnetOctets[2])) &&
            ((networkOctets[3] & subnetOctets[3]) == (addressOctets[3] & subnetOctets[3]));
    }
    catch (System.Exception ex)
    {
        return false;                
    }
}

Special thanks to Reference

Dharman
  • 30,962
  • 25
  • 85
  • 135
nu everest
  • 9,589
  • 12
  • 71
  • 90
2

I'm late to the party here, but had a similar need, and put together a quick package to do exactly this.

https://www.nuget.org/packages/IpMatcher/

and source:

https://github.com/jchristn/IpMatcher

Simple use:

using IpMatcher;

Matcher matcher = new Matcher();
matcher.Add("192.168.1.0", "255.255.255.0");
matcher.Add("192.168.2.0", "255.255.255.0");
matcher.Remove("192.168.2.0");
matcher.Exists("192.168.1.0", "255.255.255.0");  // true
matcher.Match("192.168.1.34"); // true
matcher.Match("10.10.10.10");  // false
joelc
  • 2,687
  • 5
  • 40
  • 60
2

If you are working with ASP.NET Core there is a new class IPNetwork which can be used to test if a IP Address is in a specific network.

Peter Csala
  • 17,736
  • 16
  • 35
  • 75
prochnowc
  • 21
  • 1
0

I have also created a class which calculates the network and broadcast address and checks if the IP is neither broadcast nor network address.

private static IPValidationFailedReason PerformIPRangeValidation(string ipAddress, string subnetMask)
        {
            IPValidationFailedReason ipValidationType = IPValidationFailedReason.None;
            string networkaddress = string.Empty;
            string broadcastAddress = string.Empty;
            string networkAddressBinary = string.Empty;
            string broadcastAddressBinary = string.Empty;
            int zerosCountInSubnetMask = 0;

            Array.ForEach(subnetMask.Split(SplitterChar), (eachOctet) => Array.ForEach(IPInterfaceHelper.GetOctetWithPadding(eachOctet).Where(c => c == CharZero).ToArray(), (k) => zerosCountInSubnetMask++));

            if (zerosCountInSubnetMask == 0)
            {
                return ipValidationType;
            }

            string ipAddressBinary = IPInterfaceHelper.ToBinary(ipAddress);
            networkAddressBinary = GetNetworkAddressInBinaryFormat(zerosCountInSubnetMask, ipAddressBinary);
            broadcastAddressBinary = GetBroadcastAddressInBinaryFormat(zerosCountInSubnetMask, ipAddressBinary);

            networkaddress = ToIPFromBinary(networkAddressBinary);
            broadcastAddress = ToIPFromBinary(broadcastAddressBinary);

            if (ipAddress == networkaddress)
            {
                ipValidationType = IPValidationFailedReason.NetworkAddressZero;
                return ipValidationType;
            }
            if (ipAddress == broadcastAddress)
            {
                ipValidationType = IPValidationFailedReason.BroadcastAddressNotPermiited;
                return ipValidationType;
            }

            return ipValidationType;
        }


private static string GetNetworkAddressInBinaryFormat(int zeroCountInSubnetMask, string ipAddressBinary)
    {
        string networkAddressBinary = string.Empty;
        int countOfOnesInSubnetMask = TotalBitCount - zeroCountInSubnetMask;
        StringBuilder sb = new StringBuilder(ipAddressBinary);
        //When Subnet is like 255.255.255.0
        if (zeroCountInSubnetMask >= 1 && zeroCountInSubnetMask <= 8)
        {
            networkAddressBinary = sb.Replace(CharOne, CharZero, countOfOnesInSubnetMask + 3, zeroCountInSubnetMask).ToString();
        }
        //When Subnet is like 255.255.0.0
        if (zeroCountInSubnetMask > 8 && zeroCountInSubnetMask <= 16)
        {
            networkAddressBinary = sb.Replace(CharOne, CharZero, countOfOnesInSubnetMask + 2, zeroCountInSubnetMask + 1).ToString();
        }
        //When Subnet is like 255.0.0.0
        if (zeroCountInSubnetMask > 16 && zeroCountInSubnetMask <= 24)
        {
            networkAddressBinary = sb.Replace(CharOne, CharZero, countOfOnesInSubnetMask + 1, zeroCountInSubnetMask + 2).ToString();
        }
        //When Subnet is like 128.0.0.0
        if (zeroCountInSubnetMask > 24 && zeroCountInSubnetMask < 32)
        {
            networkAddressBinary = sb.Replace(CharOne, CharZero, countOfOnesInSubnetMask , zeroCountInSubnetMask + 3).ToString();
        }
        return networkAddressBinary;
    }


 private static string GetBroadcastAddressInBinaryFormat(int zeroCountInSubnetMask, string ipAddressBinary)
    {
        string broadcastAddressBinary = string.Empty;
        int countOfOnesInSubnetMask = TotalBitCount - zeroCountInSubnetMask;
        StringBuilder sb = new StringBuilder(ipAddressBinary);
        //When Subnet is like 255.255.255.0
        if (zeroCountInSubnetMask >= 1 && zeroCountInSubnetMask <= 8)
        {
            broadcastAddressBinary = sb.Replace(CharZero, CharOne, countOfOnesInSubnetMask + 3, zeroCountInSubnetMask).ToString();
        }
        //When Subnet is like 255.255.0.0
        if (zeroCountInSubnetMask > 8 && zeroCountInSubnetMask <= 16)
        {
            broadcastAddressBinary = sb.Replace(CharZero, CharOne, countOfOnesInSubnetMask + 2, zeroCountInSubnetMask + 1).ToString();
        }
        //When Subnet is like 255.0.0.0
        if (zeroCountInSubnetMask > 16 && zeroCountInSubnetMask <= 24)
        {
            broadcastAddressBinary = sb.Replace(CharZero, CharOne, countOfOnesInSubnetMask + 1, zeroCountInSubnetMask + 2).ToString();
        }
        //When Subnet is like 128.0.0.0
        if (zeroCountInSubnetMask > 24 && zeroCountInSubnetMask < 32)
        {
            broadcastAddressBinary = sb.Replace(CharZero, CharOne, countOfOnesInSubnetMask , zeroCountInSubnetMask + 3).ToString();
        }
        return broadcastAddressBinary;
    }

private static string ToIPFromBinary(string ipAddressBinary)
        {
            string addrTemp = string.Empty;
            string[] networkAddressBinaryOctets = ipAddressBinary.Split(SplitterChar);
            foreach (var eachOctet in networkAddressBinaryOctets)
            {
                string temp = Convert.ToUInt32(eachOctet, 2).ToString(CultureInfo.InvariantCulture);
                addrTemp += temp + SplitterChar;
            }
            // remove last '.'
            string ipAddress = addrTemp.Substring(0, addrTemp.Length - 1);
            return ipAddress;
        }
Neetin
  • 9
  • 2
0

A little correction of Chris Shouts answer for the comments asking for IPV6 support:

public static IPAddress GetNetworkAddress(this IPAddress address, IPAddress subnetMask)
        {
            byte[] ipAdressBytes = address.GetAddressBytes();
            byte[] subnetMaskBytes = subnetMask.GetAddressBytes();

            if (ipAdressBytes.Length != subnetMaskBytes.Length)
                subnetMaskBytes = subnetMask.MapToIPv6().GetAddressBytes();

            byte[] broadcastAddress = new byte[ipAdressBytes.Length];
            for (int i = 0; i < broadcastAddress.Length; i++)
            {
                broadcastAddress[i] = (byte)(ipAdressBytes[i] & (subnetMaskBytes[i]));
            }
            return new IPAddress(broadcastAddress);
        }