Here's a couple of implementations of getting IPv4 subnet mask expansion or more specifically a CIDR IP subnet mask expansion.
CIDR notation is a compact representation of an IP address and its associated routing prefix. The notation is constructed from an IP address, a slash ('/') character, and a decimal number. The trailing number is the count of leading 1 bits in the routing mask, traditionally called the network mask. The IP address in the notation is always represented according to the standards for IPv4 or IPv6.
192.168.100.14/24 represents the IPv4 address 192.168.100.14 and its associated routing prefix 192.168.100.0, or equivalently, its subnet mask 255.255.255.0, which has 24 leading 1-bits.
https://en.wikipedia.org/wiki/Classless_Inter-Domain_Routing
Code
CIDR notation is a compact representation of an IP address and its associated routing prefix. The notation is constructed from an IP address, a slash ('/') character, and a decimal number. The trailing number is the count of leading 1 bits in the routing mask, traditionally called the network mask. The IP address in the notation is always represented according to the standards for IPv4 or IPv6.
192.168.100.14/24 represents the IPv4 address 192.168.100.14 and its associated routing prefix 192.168.100.0, or equivalently, its subnet mask 255.255.255.0, which has 24 leading 1-bits.
https://en.wikipedia.org/wiki/Classless_Inter-Domain_Routing
Code
using System; using System.Diagnostics; //https://docs.microsoft.com/en-us/archive/blogs/knom/ip-address-calculations-with-c-subnetmasks-networks public static class SubnetMask { public static readonly System.Net.IPAddress ClassA = System.Net.IPAddress.Parse("255.0.0.0"); public static readonly System.Net.IPAddress ClassB = System.Net.IPAddress.Parse("255.255.0.0"); public static readonly System.Net.IPAddress ClassC = System.Net.IPAddress.Parse("255.255.255.0"); public static System.Net.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 System.Net.IPAddress(binaryMask); } public static System.Net.IPAddress CreateByNetBitLength(int netpartLength) { int hostPartLength = 32 - netpartLength; return CreateByHostBitLength(hostPartLength); } public static System.Net.IPAddress CreateByHostNumber(int numberOfHosts) { int maxNumber = numberOfHosts + 1; string b = Convert.ToString(maxNumber, 2); return CreateByHostBitLength(b.Length); } } public static class Extensions { /// <summary> /// Fastest way to to find 1st number in a string and convert it into an absolute integer /// </summary> /// <param name="intStr"></param> /// <returns></returns> // https://metadataconsulting.blogspot.com/2020/06/CSharp-Fastest-way-to-find-a-number-or-integer-in-a-string.html public static int GetFirstAbsIntFast(this string intStr) { int sum = int.MinValue; //any error val -9999 char[] n = intStr.ToCharArray(); //fastest way to index a string //int idxFirstDigit = -1; for (int i = 0; i < n.Length; i++) { if (n[i] >= 48 && n[i] <= 57) //'0'=48 and '9'=57 get lead number only { //if (idxFirstDigit == -1) idxFirstDigit = i; int z = sum * 10 + (n[i] - 48); if (z < 0) //we get into negative, if over int.MaxValue return sum; //we have negative number, it's an error or throw error sum = z; } else //if (idxFirstDigit > -1) break; //return int.MinValue; //or throw error } //if (intStr.IndexOf('-') == idxFirstDigit - 1) //chek for neg sign // sum *= -1; return sum; } public static string GetIPv4NetworkMaskByPrefix(this string subnet) { //CIDR IP format accepted xxx.xxx.xxx.xxx/1-32 int idxForwardSlash = subnet.IndexOf('/'); if (string.IsNullOrEmpty(subnet) && idxForwardSlash > -1) return string.Empty; string CIDRIP = subnet.Substring(idxForwardSlash+1); int numCIDRIP = 0; numCIDRIP = CIDRIP.GetFirstAbsIntFast(); if (numCIDRIP < 1 || numCIDRIP > 32) return string.Empty; // /1-32 range accepted for ip4 int calSubNet = 0; calSubNet = numCIDRIP; switch (calSubNet) { case 1: return "128.0.0.0"; //2,147,483,646 case 2: return "192.0.0.0"; //1,073,741,822 case 3: return "224.0.0.0"; //536,870,910 case 4: return "240.0.0.0"; //268,435,454 case 5: return "248.0.0.0"; //134,217,726 case 6: return "252.0.0.0"; //67,108,862 case 7: return "254.0.0.0"; //33,554,430 case 8: return "255.0.0.0"; case 9: return "255.128.0.0"; case 10: return "255.192.0.0"; case 11: return "255.224.0.0"; case 12: return "255.240.0.0"; case 13: return "255.248.0.0"; case 14: return "255.252.0.0"; case 15: return "255.254.0.0"; case 16: return "255.255.0.0"; case 17: return "255.255.128.0"; case 18: return "255.255.192.0"; case 19: return "255.255.224.0"; case 20: return "255.255.240.0"; case 21: return "255.255.248.0"; case 22: return "255.255.252.0"; case 23: return "255.255.254.0"; case 24: return "255.255.255.0"; //254 case 25: return "255.255.255.128"; case 26: return "255.255.255.192"; case 27: return "255.255.255.224"; case 28: return "255.255.255.240"; case 29: return "255.255.255.248"; case 30: return "255.255.255.252"; case 31: return "255.255.255.254"; case 32: return "255.255.255.255"; default: return ""; } } //https://www.ipaddressguide.com/netmask //A CIDR IP address looks like a normal IP address except that it ends with a slash followed by a number, called the IP network prefix. //10.0.0.0/24 -> Netmask = 255.255.255.0 public static string GetIPv4SubnetMask(this string subnet) { //CIDR IP format accepts -> {xxx.xxx.xxx.xxx}/[1-32] int idxForwardSlash = subnet.IndexOf('/'); if (string.IsNullOrEmpty(subnet) && idxForwardSlash > -1) return string.Empty; string CIDRIP = subnet.Substring(idxForwardSlash+1); int numCIDRIP = 0; numCIDRIP = CIDRIP.GetFirstAbsIntFast(); if (numCIDRIP < 1 || numCIDRIP > 32) return string.Empty; // /1-32 range accepted for ip4 int calSubNet = 0; calSubNet = 32 - numCIDRIP; // https://weblogs.asp.net/razan/finding-subnet-mask-from-ip4-address-using-c long mask = (0xffffffffL << calSubNet & 0xffffffffL); mask = System.Net.IPAddress.HostToNetworkOrder((int)mask); return new System.Net.IPAddress((UInt32)mask).ToString(); } public static string getSubnetAddressFromIPv4NetMask(this string netMask) { //CIDR IP format accepted xxx.xxx.xxx.xxx/1-32 int idxForwardSlash = netMask.IndexOf('/'); if (string.IsNullOrEmpty(netMask) && idxForwardSlash > -1) return string.Empty; string CIDRIP = netMask.Substring(idxForwardSlash + 1); int numCIDRIP = 0; numCIDRIP = CIDRIP.GetFirstAbsIntFast(); if (numCIDRIP < 1 || numCIDRIP > 32) return string.Empty; // /1-32 range accepted for ip4 //long bit = 1; //bit <<= pow; //now this bitwise shift works int calSubNet = 0; calSubNet = 32 - numCIDRIP; string subNetMask = string.Empty; double result = 0; if (calSubNet >= 0 && calSubNet <= 8) { for (int ipower = 0; ipower < calSubNet; ipower++) { long bit = 1; bit <<= ipower; //now this bitwise shift works result += bit; //result += Math.Pow(2, ipower); } double finalSubnet = 255 - result; subNetMask = "255.255.255." + Convert.ToString(finalSubnet); } else if (calSubNet > 8 && calSubNet <= 16) { int secOctet = 16 - calSubNet; secOctet = 8 - secOctet; for (int ipower = 0; ipower < secOctet; ipower++) { long bit = 1; bit <<= ipower; //now this bitwise shift works result += bit; //result += Math.Pow(2, ipower); } double finalSubnet = 255 - result; subNetMask = "255.255." + Convert.ToString(finalSubnet) + ".0"; } else if (calSubNet > 16 && calSubNet <= 24) { int thirdOctet = 24 - calSubNet; thirdOctet = 8 - thirdOctet; for (int ipower = 0; ipower < thirdOctet; ipower++) { long bit = 1; bit <<= ipower; //now this bitwise shift works result += bit; //result += Math.Pow(2, ipower); } double finalSubnet = 255 - result; subNetMask = "255." + Convert.ToString(finalSubnet) + ".0.0"; } else if (calSubNet > 24 && calSubNet <= 32) { int fourthOctet = 32 - calSubNet; fourthOctet = 8 - fourthOctet; for (int ipower = 0; ipower < fourthOctet; ipower++) { long bit = 1; bit <<= ipower; //now this bitwise shift works result += bit; //result += Math.Pow(2, ipower); } double finalSubnet = 255 - result; subNetMask = Convert.ToString(finalSubnet) + ".0.0.0"; } return subNetMask; } public static System.Net.IPAddress CreateBySubNetBitLength(this string netMask) { //CIDR IP format accepted xxx.xxx.xxx.xxx/1-32 int idxForwardSlash = netMask.IndexOf('/'); if (string.IsNullOrEmpty(netMask) && idxForwardSlash > -1) return System.Net.IPAddress.None; string CIDRIP = netMask.Substring(idxForwardSlash + 1); int numCIDRIP = 0; numCIDRIP = CIDRIP.GetFirstAbsIntFast(); if (numCIDRIP < 1 || numCIDRIP > 32) return System.Net.IPAddress.None; // /1-32 range accepted for ip4 int calSubNet = 32 - numCIDRIP; return SubnetMask.CreateByNetBitLength(calSubNet); } } public class Program { public static void Main() { //https://www.calculator.net/ip-subnet-calculator.html dup this functionality partially string subnetprefix = "/25"; Stopwatch sw = new Stopwatch(); sw.Start(); Console.WriteLine("Using getSubnetAddressFromIPNetMask"); Console.WriteLine(subnetprefix.getSubnetAddressFromIPv4NetMask()); sw.Stop(); Console.WriteLine(sw.ElapsedTicks.ToString("#,0") + " ticks"); sw.Reset(); sw.Start(); Console.WriteLine("Using compact GetSubnetMask"); Console.WriteLine(subnetprefix.GetIPv4SubnetMask()); sw.Stop(); Console.WriteLine(sw.ElapsedTicks.ToString("#,0") + " ticks"); sw.Reset(); sw.Start(); Console.WriteLine("Using compact getNetworkMaskByPrefix"); Console.WriteLine(subnetprefix.GetIPv4NetworkMaskByPrefix()); sw.Stop(); Console.WriteLine(sw.ElapsedTicks.ToString("#,0") + " ticks"); //https://docs.microsoft.com/en-us/archive/blogs/knom/ip-address-calculations-with-c-subnetmasks-networks Console.WriteLine("Using Microsoft's recommended imp - CreateBySubNetBitLength"); Console.WriteLine(subnetprefix.GetIPv4NetworkMaskByPrefix()); sw.Stop(); Console.WriteLine(sw.ElapsedTicks.ToString("#,0") + " ticks"); } }
No comments:
Post a Comment