ln.types/net/Network4.cs

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;
}
}
}
}