public int GetPrefixLength()
        {
            byte[] byteBegin = Begin.GetAddressBytes();
            byte[] byteEnd   = End.GetAddressBytes();

            // Handle single IP
            if (Begin.Equals(End))
            {
                return(byteBegin.Length * 8);
            }
            int length = (byteBegin.Length * 8);

            for (int i = 0; i < length; i++)
            {
                byte[] mask = BitsUtil.GetBitMask(byteBegin.Length, i);
                if (new IPAddress(BitsUtil.And(byteBegin, mask)).Equals(Begin))
                {
                    if (new IPAddress(BitsUtil.Or(byteBegin, BitsUtil.Not(mask))).Equals(End))
                    {
                        return(i);
                    }
                }
            }
            throw new FormatException(String.Format("{0} is not a CIDR Subnet", ToString()));
        }
        public IEnumerator <IPAddress> GetEnumerator()
        {
            var first = Begin.GetAddressBytes();
            var last  = End.GetAddressBytes();

            for (var ip = first; BitsUtil.LtECore(ip, last); ip = BitsUtil.Increment(ip))
            {
                yield return(new IPAddress(ip));
            }
        }
        /// <summary>
        /// Takes a subnetmask (eg, "255.255.254.0") and returns the CIDR bit length of that
        /// address. Throws an exception if the passed address is not valid as a subnet mask.
        /// </summary>
        /// <param name="subnetMask">The subnet mask to use.</param>
        /// <returns></returns>
        public static int SubnetMaskLength(IPAddress subnetMask)
        {
            if (subnetMask == null)
            {
                throw new ArgumentNullException("subnetMask");
            }
            var length = BitsUtil.GetBitMaskLength(subnetMask.GetAddressBytes());

            if (length == null)
            {
                throw new ArgumentException("Not a valid subnet mask", "subnetMask");
            }
            return(length.Value);
        }
        /// <summary>
        /// Creates a range from a base address and mask bits.
        /// This can also be used with <see cref="SubnetMaskLength"/> to create a
        /// range based on a subnet mask.
        /// </summary>
        /// <param name="baseAddress"></param>
        /// <param name="maskLength"></param>
        public IPAddressRange(IPAddress baseAddress, int maskLength)
        {
            if (baseAddress == null)
            {
                throw new ArgumentNullException("baseAddress");
            }
            var baseAdrBytes = baseAddress.GetAddressBytes();

            if (baseAdrBytes.Length * 8 < maskLength)
            {
                throw new FormatException();
            }
            var maskBytes = BitsUtil.GetBitMask(baseAdrBytes.Length, maskLength);

            baseAdrBytes = BitsUtil.And(baseAdrBytes, maskBytes);
            Begin        = new IPAddress(baseAdrBytes);
            End          = new IPAddress(BitsUtil.Or(baseAdrBytes, BitsUtil.Not(maskBytes)));
        }
        public bool Contains(IPAddressRange range)
        {
            if (range == null)
            {
                throw new ArgumentNullException("range");
            }
            if (this.Begin.AddressFamily != range.Begin.AddressFamily)
            {
                return(false);
            }
            var offset = 0;

            if (Begin.IsIPv4MappedToIPv6 && range.Begin.IsIPv4MappedToIPv6)
            {
                offset = 12; //ipv4 has prefix of 10 zero bytes and two 255 bytes.
            }
            return
                (BitsUtil.LtECore(this.Begin.GetAddressBytes(), range.Begin.GetAddressBytes(), offset) &&
                 BitsUtil.GtECore(this.End.GetAddressBytes(), range.End.GetAddressBytes(), offset));
        }
        public bool Contains(IPAddress ipaddress)
        {
            if (ipaddress == null)
            {
                throw new ArgumentNullException("ipaddress");
            }
            if (ipaddress.AddressFamily != this.Begin.AddressFamily)
            {
                return(false);
            }
            var offset = 0;

            if (Begin.IsIPv4MappedToIPv6 && ipaddress.IsIPv4MappedToIPv6)
            {
                offset = 12; //ipv4 has prefix of 10 zero bytes and two 255 bytes.
            }
            var adrBytes = ipaddress.GetAddressBytes();

            return
                (BitsUtil.LtECore(this.Begin.GetAddressBytes(), adrBytes, offset) &&
                 BitsUtil.GtECore(this.End.GetAddressBytes(), adrBytes, offset));
        }
        /// <summary>
        /// Create a new range from a begin and end address.
        /// Throws an exception if Begin comes after End, or the
        /// addresses are not in the same family.
        /// </summary>
        public IPAddressRange(IPAddress begin, IPAddress end)
        {
            if (begin == null)
            {
                throw new ArgumentNullException("begin");
            }
            if (end == null)
            {
                throw new ArgumentNullException("end");
            }
            Begin = new IPAddress(begin.GetAddressBytes());
            End   = new IPAddress(end.GetAddressBytes());
            if (Begin.AddressFamily != End.AddressFamily)
            {
                throw new ArgumentException("Elements must be of the same address family", "end");
            }
            var beginBytes = Begin.GetAddressBytes();
            var endBytes   = End.GetAddressBytes();

            if (!BitsUtil.GtECore(endBytes, beginBytes))
            {
                throw new ArgumentException("Begin must be smaller than the End", "begin");
            }
        }
        public static IPAddressRange Parse(string ipRangeString)
        {
            if (ipRangeString == null)
            {
                throw new ArgumentNullException("ipRangeString");
            }
            // trim white spaces.
            ipRangeString = ipRangeString.Trim();

            // Pattern 1. CIDR range: "192.168.0.0/24", "fe80::/10%eth0"
            var m1 = m1_regex.Match(ipRangeString);

            if (m1.Success)
            {
                var baseAdrBytes = IPAddress.Parse(StripScopeIP(m1.Groups["adr"].Value)).GetAddressBytes();
                var maskLen      = int.Parse(m1.Groups["maskLen"].Value);
                if (baseAdrBytes.Length * 8 < maskLen)
                {
                    throw new FormatException();
                }
                var maskBytes = BitsUtil.GetBitMask(baseAdrBytes.Length, maskLen);
                baseAdrBytes = BitsUtil.And(baseAdrBytes, maskBytes);
                return(new IPAddressRange(new IPAddress(baseAdrBytes), new IPAddress(BitsUtil.Or(baseAdrBytes, BitsUtil.Not(maskBytes)))));
            }

            // Pattern 2. Uni address: "127.0.0.1", ":;1"
            var m2 = m2_regex.Match(ipRangeString);

            if (m2.Success)
            {
                return(new IPAddressRange(IPAddress.Parse(StripScopeIP(ipRangeString))));
            }

            // Pattern 3. Begin end range: "169.258.0.0-169.258.0.255"
            var m3 = m3_regex.Match(ipRangeString);

            if (m3.Success)
            {
                // if the left part contains dot, but the right one does not, we treat it as a shortuct notation
                // and simply copy the part before last dot from the left part as the prefix to the right one
                var begin = m3.Groups["begin"].Value;
                var end   = m3.Groups["end"].Value;
                if (begin.Contains('.') && !end.Contains('.'))
                {
                    if (end.Contains('%'))
                    {
                        throw new FormatException("The end of IPv4 range shortcut notation contains scope id.");
                    }
                    var lastDotAt = begin.LastIndexOf('.');
                    end = begin.Substring(0, lastDotAt + 1) + end;
                }

                return(new IPAddressRange(
                           begin: IPAddress.Parse(StripScopeIP(begin)),
                           end: IPAddress.Parse(StripScopeIP(end))));
            }

            // Pattern 4. Bit mask range: "192.168.0.0/255.255.255.0"
            var m4 = m4_regex.Match(ipRangeString);

            if (m4.Success)
            {
                var baseAdrBytes = IPAddress.Parse(StripScopeIP(m4.Groups["adr"].Value)).GetAddressBytes();
                var maskBytes    = IPAddress.Parse(m4.Groups["bitmask"].Value).GetAddressBytes();
                baseAdrBytes = BitsUtil.And(baseAdrBytes, maskBytes);
                return(new IPAddressRange(new IPAddress(baseAdrBytes), new IPAddress(BitsUtil.Or(baseAdrBytes, BitsUtil.Not(maskBytes)))));
            }
            throw new FormatException("Unknown IP range string.");
        }