// /** // * 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 { 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 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 GetEnumerator() { return new Network4Enumerator(this); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } class Network4Enumerator : IEnumerator { 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; } } } }