2

I asked a question yesterday regarding converting HEX string to IP and got the answer here: C# convert hex into ip

The problem is, when I'm using the function

var ip = new IPAddress(long.Parse(ipString, NumberStyles.AllowHexSpecifier));

it does return a valid IPAddress but does it in a reverse way. For example:

Hex String:

c0a8000a

and it should be parsed to:

192.168.0.10

The long.Parse() function returns

3232235530

But my IP after calling the IPAddress constructor is

10.0.168.192 

instead of the right one. Online tools, like http://www.smartconversion.com/unit_conversion/IP_Address_Converter.aspx are working fine. Is it a thing with a little or big endian? Do I have to flip the string myself or is there a simpler answer?

Community
  • 1
  • 1
wtrmeln
  • 121
  • 11

3 Answers3

3

So a little research yielded, that you guessed correctly. It has something to do with endianness.

The constructor: IPAddress(long newAddress) expects the value to be in network byte order which is defined to be big-endian.

I am assuming that your system architecture uses little-endian (as most intel systems do)

.NET uses the endianness of the underlying system, so when you parse a long on such a system it is stored little-endian.

Thats why when you parse the integers string via IPAddress.Parse, the result is correct.


As for a solution.

Eigther you parse your IPAddress as such (by string):

IPAddress ip = IPAddress.Parse(uint.Parse(ipString, NumberStyles.AllowHexSpecifier).ToString());

Or to be more 'correct' you could check for the BitConverter.IsLittleEndian field and flip the byte order if nescessery:

    static IPAddress ParseHexIPAddress(String szIPAddress) {
        uint uiIP = uint.Parse(szIPAddress, System.Globalization.NumberStyles.AllowHexSpecifier);
        IPAddress ip = null;
        if (BitConverter.IsLittleEndian) {
            uint uiIPRev = BitConverter.ToUInt32(BitConverter.GetBytes(uiIP).Reverse().ToArray(), 0);
            ip = new IPAddress(uiIPRev);
        } else {
            ip = new IPAddress(uiIP);
        }
        return ip;
    }
MrPaulch
  • 1,423
  • 17
  • 21
0

By default numbers (in your case long) are stored in Little Endian format in memory of x86 architecture and that is why you get the IP address reversed. You can check this out with the help of the BitConverter.IsLittleEndian field. A simple solution is to reverse the input string's byte order and then parse the reversed string to long like this:

string ipString = "c0a8000a";

// Reverse the HEX string byte order
int length = ipString.Length;
char[] reversedChars = new char[length];
for (int i = 0; i < length; i += 2)
{
    reversedChars[i] = ipString[length - i - 2];
    reversedChars[i + 1] = ipString[length - i - 1];
}

string reversedString = new string(reversedChars);

// Parse the reversed byte string
long parsedValue = long.Parse(reversedString, NumberStyles.AllowHexSpecifier);
IPAddress ip = new IPAddress(parsedValue);
Pavel Vladov
  • 4,707
  • 3
  • 35
  • 39
0

As it has been pointed out the problem is that you have to convert from the host byte order (litte endian) to the network byte order (big endian). You can use the IPAddress.HostToNetworkOrder method to do this:

var ip = new IPAddress(
  IPAddress.HostToNetworkOrder(
    int.Parse(ipString, NumberStyles.AllowHexSpecifier)
  )
);

Note that you need to use int.Parse instead of long.Parse for this to work because in IPv4 address is 32 bits, not 64 bits.

This method does not involve string conversions or use of other classes like BitConverter to perform the conversion.

Martin Liversage
  • 104,481
  • 22
  • 209
  • 256
  • Oh well, i missed that one. I think it is hillarious that the constructor doesn't already do this, but well at least they gave us a way to quickly convert the byte order ourselves if we **really** want to. By the time someone found this though, 10 people have written a `HostToNetworkOrder` method themselves. – MrPaulch Nov 07 '14 at 12:17