208 lines
5.4 KiB
C#
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;
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|