ln.types/CIDR.cs

208 lines
5.4 KiB
C#

// /**
// * File: CIDR.cs
// * Author: haraldwolff
// *
// * This file and it's content is copyrighted by the Author and / or copyright holder.
// * Any use wihtout proper permission is illegal and may lead to legal actions.
// *
// *
// **/
using System;
using System.Net;
using System.Linq;
using System.Collections.Generic;
using System.Collections;
namespace ln.types
{
public class CIDR : IEnumerable<CIDR>
{
public static CIDR Parse(String source)
{
string[] toks = source.Split('/');
IPAddress ip = IPAddress.Parse(toks[0]);
if (toks.Length == 2)
{
if (toks[1].IndexOf('.') != -1)
{
IPAddress mask = IPAddress.Parse(toks[1]);
return new CIDR(ip, mask);
}
else
{
uint w = uint.Parse(toks[1]);
return new CIDR(ip, w);
}
}
return new CIDR(ip);
}
private readonly uint _ip;
private readonly uint _netmask;
public int MaskWidth => (int)getNetWidth(_netmask);
public CIDR Network => new CIDR(_ip & _netmask, _netmask);
public byte[] IPBytes
{
get => BitConverter.GetBytes(_ip).Reverse().ToArray();
//set => _ip = BitConverter.ToUInt32(value.Reverse().ToArray(), 0);
}
public byte[] MaskBytes
{
get => BitConverter.GetBytes(_netmask).Reverse().ToArray();
//set => _netmask = BitConverter.ToUInt32(value.Reverse().ToArray(), 0);
}
public CIDR()
{
}
public CIDR(uint ip, uint netmask)
{
this._ip = ip;
this._netmask = netmask;
}
public CIDR(CIDR ip)
{
this._ip = ip._ip;
this._netmask = 0xFFFFFFFF;
}
public CIDR(CIDR ip, uint maskwidth)
{
this._ip = ip._ip;
this._netmask = maskFromWidth(maskwidth);
}
public CIDR(IPAddress ip, uint maskwidth)
{
_ip = BitConverter.ToUInt32(ip.GetAddressBytes().Reverse().ToArray(), 0);
_netmask = maskFromWidth(maskwidth);
}
public CIDR(IPAddress ip, IPAddress mask)
{
_ip = BitConverter.ToUInt32(ip.GetAddressBytes().Reverse().ToArray(), 0);
_netmask = BitConverter.ToUInt32(mask.GetAddressBytes().Reverse().ToArray(), 0);
getNetWidth(_netmask);
}
private uint maskFromWidth(uint value)
{
uint nm = 0;
if (value == 0)
nm = 0;
else if (value == 32)
nm = 0xFFFFFFFF;
else
{
nm = 0xFFFFFFFF;
nm <<= (int)(32 - value);
}
return nm;
}
private uint getNetWidth(uint nm)
{
uint w = 0;
for (w = 32; w > 0; w--)
{
if ((nm & (1 << (int)(32-w))) != 0)
break;
}
for (uint n = w; n > 0; n--)
{
if ((nm & (1 << (int)(32-n))) == 0)
throw new FormatException("Netmask with holes");
}
return w;
}
public override string ToString()
{
if (_netmask == 0xFFFFFFFF)
return String.Format("{0}", String.Join(".", IPBytes.Select((x) => x.ToString())));
else
return String.Format("{0}/{1}", String.Join(".", IPBytes.Select((x) => x.ToString())),getNetWidth(_netmask));
}
public static implicit operator IPAddress(CIDR cidr)
{
return new IPAddress(cidr._ip);
}
public static implicit operator CIDR(IPAddress iPAddress)
{
return new CIDR(iPAddress);
}
public bool Contains(CIDR you)
{
return (you.MaskWidth >= MaskWidth) && ((you._ip & _netmask)==(_ip & _netmask));
}
public override int GetHashCode()
{
return (int)(_ip ^ _netmask);
}
public override bool Equals(object obj)
{
if (obj is IPAddress)
obj = (CIDR)(obj as IPAddress);
if (obj is CIDR)
{
CIDR you = obj as CIDR;
return (you._ip == _ip) && (you._netmask == _netmask);
}
return false;
}
public IEnumerator<CIDR> GetEnumerator()
{
return new CIDREnumerator(this);
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
class CIDREnumerator : IEnumerator<CIDR>
{
CIDR network;
CIDR curCIDR;
public CIDR Current => curCIDR;
object IEnumerator.Current => curCIDR;
public CIDREnumerator(CIDR network)
{
this.network = network.Network;
Reset();
}
public void Dispose()
{
}
public bool MoveNext()
{
curCIDR = new CIDR(curCIDR._ip + 1, 0xFFFFFFFF);
return network.Contains(curCIDR);
}
public void Reset()
{
curCIDR = network;
}
}
}
}