1

As title suggests, I have 2 IPAddress objects:

var fromIP = IPAddress.Parse("127.0.01");
var toIP = IPAddress.Parse("255.255.255.255");

Question

How can I assert that fromIP is <= to the toIP?

What I've Tried

I have a clunky solution - split by . and iterate through each of the 4 components of both IPAddress issues, and checking each one in order. I'm not sure if this fails to cover a particular part of the IPv4/IPv6 spec that I'm missing? Or whether there's a 'better' approach to cover all cases.

JᴀʏMᴇᴇ
  • 218
  • 2
  • 15
  • What you have done is right. I sometimes write a IComparable class which does the same that your code already does but is cleaner. I will post my solution – jdweng Apr 29 '21 at 10:06
  • 1
    You could use TryWriteBytes or GetAddressBytes, and just compare byte by byte? you still have all the same "what does less than mean?" problems, but at least you don't have to split and parse each token... – Marc Gravell Apr 29 '21 at 10:08
  • already answered here: https://stackoverflow.com/a/13631626/7149235 – Rami Assi Apr 29 '21 at 10:12

2 Answers2

2

The dotted decimal notation of an IPv4 address is just a friendly way of writing a 32-bit int: we take each byte, write out its decimal representation, and separate them with periods.

Each IP address can therefore just be represented as a 32-bit int, and these can be directly compared.

The 4 raw bytes of the IPv4 address can be read with IPAddress.GetAddressBytes(). From there, we can use BinaryPrimitives.ReadUInt32BigEndian as an easy way to convert these into a big-endian unsigned 32-bit integer:

var ipAddress = IPAddress.Parse("127.0.0.1");
uint ipInt = BinaryPrimitives.ReadUInt32BigEndian(ipAddress.GetAddressBytes());

You can then compare your two uints in the normal way.

If you want to compare the IP addresses as signed ints, rather than unsigned ints, you can do the similar:

var ipAddress = IPAddress.Parse("127.0.0.1");
int ipInt = BinaryPrimitives.ReadInt32BigEndian(ipAddress.GetAddressBytes());

BinaryPrimitives was introduced in .NET Standard 2.1. If you're stuck on something older, you can use BitConverter. However, BitConverter uses the host's endianness, whereas the bytes in an IP address are always big-endian, so you'll have to convert between them:

uint ipInt = unchecked((uint)IPAddress.NetworkToHostOrder(BitConverter.ToInt32(ipAddress.GetAddressBytes())));

For the signed version, it's a bit simpler:

int ipInt = IPAddress.NetworkToHostOrder(BitConverter.ToInt32(ipAddress.GetAddressBytes()));
canton7
  • 37,633
  • 3
  • 64
  • 77
  • 2
    FYI you can also use spans here to avoid a `byte[]`; it won't matter unless you're doing *lots* of it, but: https://sharplab.io/#v2:EYLgxg9gTgpgtADwGwBYA+ABATARgLABQGADAAQY4B0AQgK4Bm9MUAzjQJYB2AhlAJ4BuQiXJUAcjAAuQgoQBuvUuwAOAQQAm62CxakAvKQCSABQ1aYOysd4sYACgBEOLAHZKxd5RwOAlDIDKytycADzAfJIwAHykwAxMUPqkLJLcYADW3AA2WRBgsREwANooALoy7PSkdgCEKmbabAAq/ADqUOyR1IUsdnGMzAA0pBC0kkqc4wDuHZKRnD6kaGikM53zpDUGKD6EpPukkgAWUBBTpJww54acClns6gDyyszckuwQnACiCGAwyu9Po4xBBxiY5CgAPy+GS0LjjFQ3cYGahcXh8YwdAC2nXYcgslAASjBuOoAKpIgDMWFRAHMvpx1Oxgn14sw/EA= – Marc Gravell Apr 29 '21 at 10:21
0

Try following :

using System;
using System.Collections.Generic;
using System.Collections;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Serialization;
using System.Net;

namespace ConsoleApplication
{
    public class Program
    {
        
        public static void Main(string[] args)
        {
            IPAddress ip1 = IPAddress.Parse("127.0.01");
            IPAddress ip2 = IPAddress.Parse("255.255.255.255");

            int results = (new CompareIP(ip1)).CompareTo(new CompareIP(ip2));
        }
    }
    public class CompareIP : IComparable<CompareIP>
    {
        private byte[] ipAddress { get; set; }

        public CompareIP(IPAddress ipAddress)
        {
            this.ipAddress = ipAddress.GetAddressBytes();
        }
        public int CompareTo(CompareIP  other)
        {
            int results = 0;
            for (int i = 0; i < ipAddress.Length; i++)
            {
                results = this.ipAddress[i].CompareTo(other.ipAddress[i]);
                if (results != 0) break;
            }

            return results;
        }

    }


}

Using Icomparer

using System.Collections.Generic;
using System.Collections;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Serialization;
using System.Net;

namespace ConsoleApplication
{
    public class Program
    {
        
        public static void Main(string[] args)
        {
            IPAddress ip1 = IPAddress.Parse("127.0.0.1");
            IPAddress ip2 = IPAddress.Parse("255.255.255.255");

            int results = (new CompareIP()).Compare(ip1,ip2);
        }
    }
    public class CompareIP : IComparer<IPAddress>
    {
        public int Compare(IPAddress ip1, IPAddress ip2)
        {
            int results = 0;
            byte[] ip1Bytes = ip1.GetAddressBytes();
            byte[] ip2Bytes = ip2.GetAddressBytes();               
            for (int i = 0; i < ip1Bytes.Length; i++)
            {
                results = ip1Bytes[i].CompareTo(ip2Bytes[i]);
                if (results != 0) break;
            }

            return results;
        }

    }


}
jdweng
  • 33,250
  • 2
  • 15
  • 20