This question is related to this article
I'm trying to write a tool in C# to handle subnetting of IPv4 addresses. I know there are other libraries, the most popular being IpNetwork2. Currently that library doesn't load in my existing project, and I need to move forward. I wound up converting a PowerShell module, SubnetTools, to fit my needs. The problem is that it relies on the IpAddress.Address property which is deprecated.
For simplicity I'll use the shortest snip from the original article
public int GetAddress(string ipAddress)
{
string hex = string.Concat(ipAddress.Split('.').Reverse().Select(x => int.Parse(x).ToString("X").PadLeft(2, '0'))); // 0100007F
return Convert.ToInt32(hex, 16); //16777343
}
The output is as expected for the normal ip address but when reversed it gives the wrong value. See the output below:
[IpTools.IpObject]::new('172.18.16.0')
ForwardIpAddress ForwardDecimalAddress ReverseIpAddress ReverseDecimalAddress
---------------- --------------------- ---------------- ---------------------
172.18.16.0 1053356 0.16.18.172 -1408102400
Here is the output from IpAddress:
[ipaddress]'172.18.16.0'
AddressFamily : InterNetwork
ScopeId :
IsIPv6Multicast : False
IsIPv6LinkLocal : False
IsIPv6SiteLocal : False
IsIPv6Teredo : False
IsIPv6UniqueLocal : False
IsIPv4MappedToIPv6 : False
Address : 1053356
IPAddressToString : 172.18.16.0
[ipaddress]'0.16.18.172'
AddressFamily : InterNetwork
ScopeId :
IsIPv6Multicast : False
IsIPv6LinkLocal : False
IsIPv6SiteLocal : False
IsIPv6Teredo : False
IsIPv6UniqueLocal : False
IsIPv4MappedToIPv6 : False
Address : 2886864896
IPAddressToString : 0.16.18.172
The address numbers on the reversed Ip are very different and the way that code I have works means I get the incorrect values. So I guess the question is, How do I get the address of 2886864896 from an ip address of 0.16.18.172. Or how is it done in System.Net.IPAddress?
I'm also very open to suggestions on better ways to deal with Subnetting without using nuget packages, thus far, the two I've tried have both failed.
Related to the first comment, my existing object uses long for the address properties.
public string ForwardIpAddress { get; set; } = string.Empty;
public long ForwardDecimalAddress { get; set; } = 0;
public string ReverseIpAddress { get; set; } = string.Empty;
public long ReverseDecimalAddress { get; set; } = 0;
I have used several answers from the original question but here is one sample that returns a long and I still get the same result.
public long GetAddress(string ipAddress)
{
byte[] bytes = IPAddress.Parse(ipAddress).GetAddressBytes();
if (!BitConverter.IsLittleEndian)
{
Array.Reverse(bytes);
}
long r = BitConverter.ToInt64(bytes, 0);
return r;
}
Per the comments I've updated the snip above to use BitConverter.ToInt64(). This results in an error when it runs on the reverse.
[IpTools.IpObject]::new('172.18.16.0')
MethodInvocationException: Exception calling ".ctor" with "1" argument(s): "Destination array is not long enough to copy all the items in the collection. Check array index and length. (Parameter 'value')"
The GetAddress() runs for both forward and reverse.
ForwardIpAddress = ip.ToString();
ForwardDecimalAddress = new Address().GetAddress(ForwardIpAddress);
ReverseIpAddress = reveresed.ToString();
ReverseDecimalAddress = new Address().GetAddress(ReverseIpAddress);