258 lines
7.1 KiB
C#
258 lines
7.1 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;
|
|
using Newtonsoft.Json;
|
|
|
|
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,32);
|
|
}
|
|
|
|
private readonly uint _ip;
|
|
private readonly uint _netmask;
|
|
|
|
public int MaskWidth => (int)getNetWidth(_netmask);
|
|
public CIDR Network => new CIDR(_ip & _netmask, _netmask);
|
|
public CIDR Host => new CIDR(_ip, 0xffffffff);
|
|
|
|
public int Size => (1 << (32 - MaskWidth));
|
|
|
|
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 CIDR[] Divide(int bits)
|
|
{
|
|
if (MaskWidth + bits > 32)
|
|
throw new ArgumentException("Netmask would be > 32bits", nameof(bits));
|
|
|
|
int count = (1 << bits);
|
|
uint newmask = maskFromWidth((uint)(MaskWidth + bits));
|
|
uint nip = _ip;
|
|
CIDR[] result = new CIDR[count];
|
|
for (int n=0;n<count;n++)
|
|
{
|
|
nip += (uint)(1 << (32 - MaskWidth - bits));
|
|
result[n] = new CIDR(nip, newmask);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
|
|
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.IPBytes );
|
|
}
|
|
public static implicit operator CIDR(IPAddress iPAddress)
|
|
{
|
|
return new CIDR(BitConverter.ToUInt32(iPAddress.GetAddressBytes().Reverse().ToArray(),0),0xFFFFFFFF);
|
|
}
|
|
|
|
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;
|
|
}
|
|
}
|
|
|
|
|
|
static bool ___init = ____init();
|
|
static bool ____init()
|
|
{
|
|
List<JsonConverter> converters = new List<JsonConverter>();
|
|
converters.Add(new CIDRJsonConverter());
|
|
JsonConvert.DefaultSettings = () => new JsonSerializerSettings { Converters = converters };
|
|
return true;
|
|
}
|
|
|
|
}
|
|
|
|
public class CIDRJsonConverter : JsonConverter
|
|
{
|
|
public override bool CanConvert(Type objectType)
|
|
{
|
|
return (objectType == typeof(CIDR));
|
|
}
|
|
|
|
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
|
|
{
|
|
return CIDR.Parse(reader.ReadAsString());
|
|
}
|
|
|
|
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
|
|
{
|
|
writer.WriteValue((value as CIDR).ToString());
|
|
}
|
|
}
|
|
|
|
}
|