IP Address Calculations with C# (Subnetmasks, Networks, …)

Recently I wanted to develop a wake-on-lan application for my media center.

For that I needed the broadcast address of my local LAN.

So I decided to write a small but interesting library.. (you can leverage it for all kinds of network calculations like subnets, etc..).

What it does is do a lot of funny calculations around IPv4.

  • Network Address: This is the first address of each network which is reserved to identify the entire network (or subnet).
    If your ip address is                    192.168.2.234
    and your subnetmask                 255.255.255.0
    then your network address is    192.168.2.0.
  • Broadcast Address: This is the "send-to-all" address. If any traffic is targeted for the broadcast address it is forwarded to all of the machines in the network.
    If your ip address is                    192.168.2.234
    and your subnetmask                 255.255.255.0
    then your broadcast address is  192.168.2.255.

Are you interested in the calculations behind that? Visit my other blog post.

In .NET there is a class called System.Net.IPAddress, which is used for storing IPv4 addresses. So what I did is build a bunch of extension methods for this class:

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

The first two calculate the Broadcast- as well as the NetworkAddress. With the help of the network address you can then calculate whether two IP addresses are in the same subnet (simply by comparing the two network addresses). If they are.. fine, communication is done directly. If not, then the default gateway (a router) is used for the communication between them.

These extension methods (keep in mind they’re in a static class, are static methods and have the special this (extension) parameter) extend an existing type (at least it seems so to use when using Visual Studio). Now we can call..

 var ip1 = IPAddress.Parse("192.168.0.1");
var ip2 = IPAddress.Parse("192.168.1.40");
var mask = IPAddress.Parse("255.255.255.0");
bool inSameNet = ip1.IsInSameSubnet(ip2, mask);

I’ve used the GetBroadcastAddress method in another sample to send a Wake-On-Lan packet to ALL computers on my subnet.

The subnet mask indicates how large the network is. To ease work with it I’ve also built a helper class called Subnet.

 public static class SubnetMask
{
    public static readonly IPAddress ClassA = IPAddress.Parse("255.0.0.0");
    public static readonly IPAddress ClassB = IPAddress.Parse("255.255.0.0");
    public static readonly IPAddress ClassC = IPAddress.Parse("255.255.255.0");

    public static IPAddress CreateByHostBitLength(int hostpartLength)
    {
        int hostPartLength = hostpartLength;
        int netPartLength = 32 - hostPartLength;

        if (netPartLength < 2)
            throw new ArgumentException("Number of hosts is to large for IPv4");

        Byte[] binaryMask = new byte[4];

        for (int i = 0; i < 4; i++)
        {
            if (i * 8 + 8 <= netPartLength)
                binaryMask[i] = (byte)255;
            else if (i * 8 > netPartLength)
                binaryMask[i] = (byte)0;
            else
            {
                int oneLength = netPartLength - i * 8;
                string binaryDigit =
                    String.Empty.PadLeft(oneLength, '1').PadRight(8, '0');
                binaryMask[i] = Convert.ToByte(binaryDigit, 2);
            }
        }
        return new IPAddress(binaryMask);
    }

    public static IPAddress CreateByNetBitLength(int netpartLength)
    {
        int hostPartLength = 32 - netpartLength;
        return CreateByHostBitLength(hostPartLength);
    }

    public static IPAddress CreateByHostNumber(int numberOfHosts)
    {
        int maxNumber = numberOfHosts + 1;

        string b = Convert.ToString(maxNumber, 2);

        return CreateByHostBitLength(b.Length);
    }
}

This class provides constant subnet masks for Class A-C networks as well as methods for calculating subnet masks. A subnet mask is 32-bit long which consist of the network-part as well as the host-part. The methods create subnet masks either by the number of bits in the host- or network part or by the number of hosts, which should fit into the network.

 var classCMask = SubnetMask.CreateByNetBitLength(24);

creates a subnet mask with 24-bits network part, hence a class C subnet mask.

Have a lot of fun with IP calculations and visit my post about a wake-on-lan client.

Also feel free to download the sources here.

IPAddressExtensions.cs