A class that encapsulates an IPv4 or IPv6 range. Used for checking if an IPAddress is within an IPRange.
Beispiel #1
0
        static IPRange()
        {
            //We want to ignore IP's that have been auto assigned
            //169.254.0.0
            IPAddress autoAssignSubnetv4 = new IPAddress(new byte[] { 169, 254, 0, 0 });
            //255.255.0.0
            IPAddress autoAssignSubnetMaskv4 = new IPAddress(new byte[] { 255, 255, 0, 0 });

            IPRange autoAssignRangev4 = new IPRange(autoAssignSubnetv4, autoAssignSubnetMaskv4);

            //IPv6 equivalent of 169.254.x.x is fe80: /64
            IPAddress autoAssignSubnetv6 = new IPAddress(new byte[] { 0xfe, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 });
            //mask for above
            IPAddress autoAssignSubnetMaskv6 = new IPAddress(new byte[] { 255, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 });

            IPRange autoAssignRangev6 = new IPRange(autoAssignSubnetv6, autoAssignSubnetMaskv6);

            AutoAssignRanges = new List <IPRange>()
            {
                autoAssignRangev4, autoAssignRangev6
            };
        }
Beispiel #2
0
            /// <summary>
            /// Returns all allowed local IP addresses. Caches results for up to 5 second since the previous refresh unless forceCacheUpdate is true.
            /// If <see cref="RestrictLocalAdaptorNames"/> has been set only returns IP addresses corresponding with specified adaptors.
            /// If <see cref="RestrictLocalAddressRanges"/> has been set only returns matching addresses ordered in descending
            /// preference. i.e. Most preferred at [0].
            /// </summary>
            /// <param name="forceCacheUpdate">If true will refresh the cache and return latest result</param>
            /// <returns></returns>
            public static List <IPAddress> FilteredLocalAddresses(bool forceCacheUpdate)
            {
                if (filteredLocalAddressesCache != null &&
                    (DateTime.UtcNow - filteredLocalAddressesCacheUpdate).TotalSeconds < 5)
                {
                    return(filteredLocalAddressesCache);
                }
                else
                {
#if WINDOWS_PHONE || NETFX_CORE
                    //On windows phone we simply ignore IP addresses from the auto assigned range as well as those without a valid prefix
                    List <IPAddress> allowedIPs = new List <IPAddress>();

                    foreach (var hName in Windows.Networking.Connectivity.NetworkInformation.GetHostNames())
                    {
                        IPAddress temp;

                        if (!hName.DisplayName.StartsWith("169.254") && IPAddress.TryParse(hName.DisplayName, out temp))
                        {
                            if (RestrictLocalAddressRanges != null)
                            {
                                bool valid = false;

                                for (int i = 0; i < RestrictLocalAddressRanges.Length; i++)
                                {
                                    valid |= RestrictLocalAddressRanges[i].Contains(hName.DisplayName);
                                }

                                if (valid)
                                {
                                    allowedIPs.Add(IPAddress.Parse(hName.DisplayName));
                                }
                            }
                            else
                            {
                                allowedIPs.Add(IPAddress.Parse(hName.DisplayName));
                            }
                        }
                    }

                    return(allowedIPs);
#else
                    List <IPAddress> validIPAddresses = new List <IPAddress>();

#if ANDROID
                    var iFaces = Java.Net.NetworkInterface.NetworkInterfaces;
                    while (iFaces.HasMoreElements)
                    {
                        bool interfaceValid = false;
                        var  iFace          = iFaces.NextElement() as Java.Net.NetworkInterface;
                        var  javaAddresses  = iFace.InetAddresses;

                        if (RestrictLocalAdaptorNames != null)
                        {
                            foreach (var id in RestrictLocalAdaptorNames)
                            {
                                if (id == iFace.Name)
                                {
                                    interfaceValid = true;
                                    break;
                                }
                            }
                        }
                        else
                        {
                            interfaceValid = true;
                        }

                        if (!interfaceValid)
                        {
                            continue;
                        }

                        javaAddresses = iFace.InetAddresses;

                        while (javaAddresses.HasMoreElements)
                        {
                            var       javaAddress = javaAddresses.NextElement() as Java.Net.InetAddress;
                            IPAddress address     = default(IPAddress);

                            if (IPAddress.TryParse(javaAddress.HostAddress, out address))
                            {
                                if (address.AddressFamily == AddressFamily.InterNetwork || address.AddressFamily == AddressFamily.InterNetworkV6)
                                {
                                    if (!IPRange.IsAutoAssignedAddress(address))
                                    {
                                        bool allowed = false;

                                        if (RestrictLocalAddressRanges != null)
                                        {
                                            if (IPRange.Contains(RestrictLocalAddressRanges, address))
                                            {
                                                allowed = true;
                                            }
                                        }
                                        else
                                        {
                                            allowed = true;
                                        }

                                        if (!allowed)
                                        {
                                            continue;
                                        }

                                        if (address != IPAddress.None)
                                        {
                                            validIPAddresses.Add(address);
                                        }
                                    }
                                }
                            }
                        }
                    }
#else
                    foreach (var iFace in NetworkInterface.GetAllNetworkInterfaces())
                    {
                        bool interfaceValid   = false;
                        var  unicastAddresses = iFace.GetIPProperties().UnicastAddresses;

                        //Check if this adaptor is allowed
                        if (RestrictLocalAdaptorNames != null &&
                            iFace.OperationalStatus == OperationalStatus.Up)
                        {
                            foreach (var currentName in RestrictLocalAdaptorNames)
                            {
                                if (iFace.Name == currentName)
                                {
                                    interfaceValid = true;
                                    break;
                                }
                            }
                        }
                        else if (iFace.OperationalStatus == OperationalStatus.Up)
                        {
                            interfaceValid = true;
                        }

                        //If the interface is not allowed move to the next adaptor
                        if (!interfaceValid)
                        {
                            continue;
                        }

                        //If the adaptor is allowed we can now investigate the individual addresses
                        foreach (var address in unicastAddresses)
                        {
                            if (address.Address.AddressFamily == AddressFamily.InterNetwork || address.Address.AddressFamily == AddressFamily.InterNetworkV6)
                            {
                                if (!IPRange.IsAutoAssignedAddress(address.Address))
                                {
                                    bool allowed = false;

                                    if (RestrictLocalAddressRanges != null)
                                    {
                                        if (IPRange.Contains(RestrictLocalAddressRanges, address.Address))
                                        {
                                            allowed = true;
                                        }
                                    }
                                    else
                                    {
                                        allowed = true;
                                    }

                                    if (!allowed)
                                    {
                                        continue;
                                    }

                                    if (address.Address != IPAddress.None)
                                    {
                                        validIPAddresses.Add(address.Address);
                                    }
                                }
                            }
                        }
                    }
#endif

                    //Sort the results to be returned
                    if (RestrictLocalAddressRanges != null)
                    {
                        validIPAddresses.Sort((a, b) =>
                        {
                            for (int i = 0; i < RestrictLocalAddressRanges.Length; i++)
                            {
                                if (RestrictLocalAddressRanges[i].Contains(a))
                                {
                                    if (RestrictLocalAddressRanges[i].Contains(b))
                                    {
                                        return(0);
                                    }
                                    else
                                    {
                                        return(-1);
                                    }
                                }
                                else if (RestrictLocalAddressRanges[i].Contains(b))
                                {
                                    return(1);
                                }
                            }

                            return(0);
                        });
                    }

                    filteredLocalAddressesCache       = validIPAddresses;
                    filteredLocalAddressesCacheUpdate = DateTime.UtcNow;

                    return(validIPAddresses);
#endif
                }
            }
        static IPRange()
        {
            //We want to ignore IP's that have been auto assigned                    
            //169.254.0.0
            IPAddress autoAssignSubnetv4 = new IPAddress(new byte[] { 169, 254, 0, 0 });
            //255.255.0.0
            IPAddress autoAssignSubnetMaskv4 = new IPAddress(new byte[] { 255, 255, 0, 0 });

            IPRange autoAssignRangev4 = new IPRange(autoAssignSubnetv4, autoAssignSubnetMaskv4);

            //IPv6 equivalent of 169.254.x.x is fe80: /64
            IPAddress autoAssignSubnetv6 = new IPAddress(new byte[] { 0xfe, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 });
            //mask for above
            IPAddress autoAssignSubnetMaskv6 = new IPAddress(new byte[] { 255, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 });

            IPRange autoAssignRangev6 = new IPRange(autoAssignSubnetv6, autoAssignSubnetMaskv6);

            AutoAssignRanges = new List<IPRange>() { autoAssignRangev4, autoAssignRangev6 };
        }
        /// <summary>
        /// Discover peers using TCP port scan
        /// </summary>
        /// <param name="discoverTimeMS"></param>
        /// <returns></returns>
        private static Dictionary<ShortGuid, Dictionary<ConnectionType, List<EndPoint>>> DiscoverPeersTCP(int discoverTimeMS)
        {
            #region Determine All Possible Peers/Port Combinations
            //Get a list of all IPEndPoint that we should try and connect to
            //This requires the network and peer portion of current IP addresses
            List<IPEndPoint> allIPEndPointsToConnect = new List<IPEndPoint>();

            //Look at all possible addresses
            foreach (var iFace in NetworkInterface.GetAllNetworkInterfaces())
            {
                bool interfaceValid = false;
                var unicastAddresses = iFace.GetIPProperties().UnicastAddresses;

                //Check if this adaptor is allowed
                if (HostInfo.RestrictLocalAdaptorNames != null)
                {
                    foreach (var currentName in HostInfo.RestrictLocalAdaptorNames)
                    {
                        if (iFace.Name == currentName)
                        {
                            interfaceValid = true;
                            break;
                        }
                    }
                }
                else
                    interfaceValid = true;

                //If the interface is not allowed move to the next adaptor
                if (!interfaceValid)
                    continue;

                //If the adaptor is allowed we can now investigate the individual addresses
                foreach (var address in unicastAddresses)
                {
                    //We are only interested in IPV4 ranges. A TCPPortScan on an IPV6 range may take a while
                    if (address.Address.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork &&
                        !IPRange.IsAutoAssignedAddress(address.Address))
                    {
                        //Check if we have restricted the addresses
                        bool addressAllowed = true;
                        if (HostInfo.IP.RestrictLocalAddressRanges != null)
                            addressAllowed = IPRange.Contains(HostInfo.IP.RestrictLocalAddressRanges, address.Address);

                        if (addressAllowed)
                        {
                            //Generate all possible IPEndPoints for the current address and subnetmask
                            //We have a special catch for the loopback address which has a very large range
                            List<IPAddress> addressesInRange;
                            if (address.Address.Equals(IPAddress.Loopback))
                                addressesInRange = new List<IPAddress>() { IPAddress.Loopback };
                            else
                            {
                                IPRange range = new IPRange(address.Address, address.IPv4Mask);
                                addressesInRange = range.AllAddressesInRange();
                            }

                            foreach (IPAddress currentAddressInRange in addressesInRange)
                            {
                                for (int port = MinTargetLocalIPPort; port <= MaxTargetLocalIPPort; port++)
                                    allIPEndPointsToConnect.Add(new IPEndPoint(currentAddressInRange, port));
                            }
                        }
                    }
                }
            }
            #endregion

            #region Send Discovery Packet & Wait
            //For each address send the discovery packet
            SendReceiveOptions nullOptions = new SendReceiveOptions<NullSerializer>();
            StreamTools.StreamSendWrapper sendStream =
                new StreamTools.StreamSendWrapper(new StreamTools.ThreadSafeStream(new MemoryStream(new byte[0])));

            int previousConnectionTimeout = NetworkComms.ConnectionEstablishTimeoutMS;
            NetworkComms.ConnectionEstablishTimeoutMS = 1000;

            AutoResetEvent allSendsCompleteEvent = new AutoResetEvent(false);
            long interlockedCompletedCount = 0;
            object _syncRoot = new object();
            List<Connection> allConnections = new List<Connection>();

            //Get unconnected TCP connections
            foreach (IPEndPoint remoteEndPoint in allIPEndPointsToConnect)
            {
                Connection conn = TCPConnection.GetConnection(new ConnectionInfo(remoteEndPoint), false);
                conn.AppendIncomingPacketHandler<byte[]>(discoveryPacketType, PeerDiscoveryHandler);
                allConnections.Add(conn);
            }

            using (Packet sendPacket = new Packet(discoveryPacketType, sendStream, nullOptions))
            {
                foreach (Connection conn in allConnections)
                {
                    Connection innerConnection = conn;

                    //The longest wait for the port scan is the TCP connect timeout
                    //The thread pool will start a large number of threads (each of which does very little)
                    // to greatly speed this up
                    _tcpPortScanThreadPool.EnqueueItem(QueueItemPriority.Normal, (state) =>
                    {
                        try
                        {
                            try
                            {
								innerConnection.EstablishConnection();
								innerConnection.SendPacket<byte[]>(sendPacket);
                            }
                            catch (CommsException)
                            {
                            }

                            lock (_syncRoot)
                            {
                                interlockedCompletedCount++;
                                if (interlockedCompletedCount == allIPEndPointsToConnect.Count)
                                    allSendsCompleteEvent.Set();
                            }
                        }
                        catch (Exception) { }
                    }, null);
                }

                allSendsCompleteEvent.WaitOne();
            }

            NetworkComms.ConnectionEstablishTimeoutMS = previousConnectionTimeout;
            
            sendStream.ThreadSafeStream.Dispose(true);

            AutoResetEvent sleep = new AutoResetEvent(false);
            //We wait at least 1 second so that connected peers can respond
            //If we do not wait and close all connections immediately we may miss some replies
#if NET2
            sleep.WaitOne(Math.Max(discoverTimeMS, 500), false);
#else
            sleep.WaitOne(Math.Max(discoverTimeMS, 500));
#endif

            //Close any connections we may have established
            foreach (Connection conn in allConnections)
            {
                try
                {
                    conn.CloseConnection(false);
                }
                catch (CommsException) { }
            }
            #endregion

            #region Return Discovered Peers
            Dictionary<ShortGuid, Dictionary<ConnectionType, List<EndPoint>>> result = new Dictionary<ShortGuid, Dictionary<ConnectionType, List<EndPoint>>>();
            lock (_syncRoot)
            {
                foreach (var idPair in _discoveredPeers)
                {
                    if (!result.ContainsKey(idPair.Key))
                        result.Add(idPair.Key, new Dictionary<ConnectionType, List<EndPoint>>());

                    foreach (var typePair in idPair.Value)
                    {
                        if (!result[idPair.Key].ContainsKey(typePair.Key))
                            result[idPair.Key].Add(typePair.Key, new List<EndPoint>());

                        foreach (var endPoint in typePair.Value)
                            if (!result[idPair.Key][typePair.Key].Contains(endPoint.Key))
                                result[idPair.Key][typePair.Key].Add(endPoint.Key);
                    }
                }
            }

            return result;
            #endregion
        }