tags:

views:

2338

answers:

4

I have been looking around quite a bit to find some C# code to convert a network in CIDR notation (72.20.10.0/24) to an IP address range, without much luck. There are some threads about CIDR on stackoverlow, but none seems to have any C# code and cover exactly what I need. So I decided to cook it myself, and I did not want the code to rely on System.Net for any conversions in this version.

Perhaps it may be of help to someone.

References:

http://stackoverflow.com/questions/218604/whats-the-best-way-to-convert-from-network-bitcount-to-netmask

"Whatmask" C code from http://www.laffeycomputer.com/whatmask.html

Usage:

uint startIP, endIP;  
Network2IpRange("72.20.10.0/24", out startIP, out endIP);

The code assumes 32 bits for everything.

 static void Network2IpRange(string sNetwork, out uint startIP, out uint endIP)
 {   
  uint ip,  /* ip address */
   mask,  /* subnet mask */    
   broadcast, /* Broadcast address */
   network; /* Network address */

  int bits;     

  string[] elements = sNetwork.Split(new Char[] { '/' });   

  ip = IP2Int(elements[0]);
  bits = Convert.ToInt32(elements[1]);

  mask = ~(0xffffffff >> bits);

  network = ip & mask;
  broadcast = network + ~mask;

  usableIps = (bits >30)?0:(broadcast - network - 1); 

  if (usableIps <= 0)
  {
   startIP = endIP = 0; 
  }
  else
  {
   startIP = network + 1;    
   endIP = broadcast - 1;
  }
 }

 public static uint IP2Int(string IPNumber)
 {
  uint ip = 0;
  string[] elements = IPNumber.Split(new Char[] { '.' });
  if (elements.Length==4)
  {
   ip  = Convert.ToUInt32(elements[0])<<24;
   ip += Convert.ToUInt32(elements[1])<<16;
   ip += Convert.ToUInt32(elements[2])<<8;
   ip += Convert.ToUInt32(elements[3]);
  }
  return ip;
 }

Feel free to submit your improvements.

A: 

The steps would go like this for a network/maskBits,

You compute the mask in one of these two ways,

mask = ~((1 << (32 - maskBits)) - 1) // or,
mask = ~(0xFFFFFFFF >> maskBits)

then the range is,

StartIP = network 
EndIP   = network | ~mask

More precisely,

StartIP = network & mask
EndIP   = (network & mask) | ~mask

Where,

  • << is bitwise left shift (without rollover)
  • & is bitwise AND,
  • | is bitwise OR, and
  • ~ is bitwise INVERT.
nik
A: 

Here is how you do it for your example 72.20.10.0/24,

Let Network be 72.20.10.0
Mask is ~((1 << (32-24)) - 1) // or
Mask is ~(0xFFFFFFFF >> 24)

  • which is 0xFFFFFF00

StartIP is -- (Network & Mask);

  • which is 72.20.10.0 & 0xFFFFFF00

EndIP is -- ((Network & Mask) | ~Mask);

  • which is (72.20.10.0 & 0xFFFFFF00) | 0x000000FF

This will be 72.20.10.0 -- 72.20.10.255.

nik
+2  A: 

I recommend to use the C# IPNetwork class from codeplex http://ipnetwork.codeplex.com/.

string net = "192.168.168.100/24";
IPNetwork ipnetwork = IPNetwork.Parse(net);

Console.WriteLine("Network : {0}", ipnetwork.Network);
Console.WriteLine("Netmask : {0}", ipnetwork.Netmask);
Console.WriteLine("Broadcast : {0}", ipnetwork.Broadcast);
Console.WriteLine("FirstUsable : {0}", ipnetwork.FirstUsable);
Console.WriteLine("LastUsable : {0}", ipnetwork.LastUsable);
Console.WriteLine("Usable : {0}", ipnetwork.Usable);
Console.WriteLine("Cidr : {0}", ipnetwork.Cidr);

It will ouput

Network : 192.168.168.0
Netmask : 255.255.255.0
Broadcast : 192.168.168.255
FirstUsable : 192.168.168.1
LastUsable : 192.168.168.254
Usable : 254 
Cidr : 24

Have fun.

Thanks Luke, didn't know about that one.
Kurt
A: 

Number of usable addresses is 254, not 253.