217 lines
5.7 KiB
C#
217 lines
5.7 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.Linq;
|
|
using System.Collections.Generic;
|
|
using System.Collections;
|
|
|
|
namespace ln.types.net
|
|
{
|
|
public class Network4 : IEnumerable<IPv4>
|
|
{
|
|
public static Network4 Parse(String source)
|
|
{
|
|
string[] toks = source.Split('/');
|
|
IPv4 ipv4 = IPv4.Parse(toks[0]);
|
|
|
|
if (toks.Length == 2)
|
|
{
|
|
if (toks[1].IndexOf('.') != -1)
|
|
{
|
|
IPv4 mask = IPv4.Parse(toks[1]);
|
|
return new Network4(ipv4, mask);
|
|
}
|
|
else
|
|
{
|
|
uint w = uint.Parse(toks[1]);
|
|
return new Network4(ipv4, w);
|
|
}
|
|
}
|
|
return ipv4;
|
|
}
|
|
|
|
private readonly IPv4 network;
|
|
public IPv4 Network => network;
|
|
|
|
private readonly IPv4 netmask;
|
|
public IPv4 Netmask => netmask;
|
|
|
|
public uint Width => getNetWidth(netmask.AsUInt);
|
|
public int Size => 1 << (int)(32-Width);
|
|
|
|
/* Erste IP dieses Netzbereich */
|
|
public IPv4 First => network;
|
|
/* Letzte IP in diesem Netzbereich */
|
|
public IPv4 Last => new IPv4(network.AsUInt + (uint)Size - 1);
|
|
/* Erste IP folgend diesem Netzbereich */
|
|
public IPv4 Next => new IPv4(network.AsUInt + (uint)Size);
|
|
|
|
public Network4()
|
|
{
|
|
}
|
|
|
|
public Network4(uint ip, uint mask)
|
|
{
|
|
network = new IPv4(ip & mask);
|
|
netmask = new IPv4(mask);
|
|
getNetWidth(netmask.AsUInt);
|
|
}
|
|
public Network4(IPv4 ip, IPv4 mask)
|
|
:this(ip.AsUInt,mask.AsUInt)
|
|
{}
|
|
public Network4(IPv4 ip, uint mask)
|
|
:this(ip.AsUInt, maskFromWidth(mask))
|
|
{}
|
|
|
|
private static 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 static 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 Network4[] Divide(int bits)
|
|
{
|
|
if (Width + bits > 32)
|
|
throw new ArgumentException("Netmask would be > 32bits", nameof(bits));
|
|
|
|
int count = (1 << bits);
|
|
uint newmask = maskFromWidth((uint)(Width + bits));
|
|
uint nip = network.AsUInt;
|
|
|
|
Network4[] result = new Network4[count];
|
|
for (int n = 0; n < count; n++)
|
|
{
|
|
result[n] = new Network4(nip, newmask);
|
|
nip += (uint)(1 << (int)(32 - Width - bits));
|
|
}
|
|
return result;
|
|
}
|
|
|
|
public override string ToString()
|
|
{
|
|
return String.Format("{0}/{1}", String.Join(".", Network.IPBytes.Select((x) => x.ToString())), Width);
|
|
}
|
|
|
|
public static implicit operator Network4(IPv4 ip)
|
|
{
|
|
return new Network4(ip, 32);
|
|
}
|
|
|
|
|
|
public bool Contains(IPv4 ip)
|
|
{
|
|
return ((ip.AsUInt & netmask.AsUInt) == (network.AsUInt));
|
|
}
|
|
public bool Contains(Network4 other)
|
|
{
|
|
return (other.First >= First) && (other.Last <= Last);
|
|
}
|
|
|
|
public bool Contains(IEnumerable<IPv4> candidates)
|
|
{
|
|
foreach (IPv4 ip in candidates)
|
|
if (Contains(ip))
|
|
return true;
|
|
return false;
|
|
}
|
|
|
|
|
|
public override int GetHashCode()
|
|
{
|
|
return (int)(Network.GetHashCode() ^ Netmask.GetHashCode());
|
|
}
|
|
public override bool Equals(object obj)
|
|
{
|
|
if (obj is IPv4)
|
|
{
|
|
IPv4 you = obj as IPv4;
|
|
return (Width == 32) && network.Equals(you);
|
|
}
|
|
else if (obj is Network4)
|
|
{
|
|
Network4 you = obj as Network4;
|
|
return (network.Equals(you.network) && netmask.Equals(you.netmask));
|
|
}
|
|
return false;
|
|
}
|
|
|
|
public IEnumerator<IPv4> GetEnumerator()
|
|
{
|
|
return new Network4Enumerator(this);
|
|
}
|
|
|
|
IEnumerator IEnumerable.GetEnumerator()
|
|
{
|
|
return GetEnumerator();
|
|
}
|
|
|
|
class Network4Enumerator : IEnumerator<IPv4>
|
|
{
|
|
Network4 net4;
|
|
IPv4 currentIP;
|
|
|
|
public IPv4 Current => currentIP;
|
|
object IEnumerator.Current => currentIP;
|
|
|
|
public Network4Enumerator(Network4 network)
|
|
{
|
|
this.net4 = network;
|
|
Reset();
|
|
}
|
|
|
|
public void Dispose()
|
|
{
|
|
}
|
|
|
|
public bool MoveNext()
|
|
{
|
|
if (currentIP == null)
|
|
currentIP = net4.network;
|
|
else
|
|
currentIP++;
|
|
|
|
return net4.Contains(currentIP);
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
currentIP = null;
|
|
}
|
|
}
|
|
}
|
|
}
|