예제 #1
0
        /// <summary>
        /// Prints and error message and then exits with exit code 1
        /// </summary>
        /// <param name="msg">Error message to print</param>
        /// <param name="pause">Wait for user input before exitingt</param>
        public static void ErrorAndExit(string msg)
        {
            Display.Error(msg);
            WaitForUserInput();

            Environment.Exit(1);
        }
예제 #2
0
        public static void Start(CancellationToken cancellationToken)
        {
            IPAddress   localAddress    = null;
            Socket      listeningSocket = null;
            PingResults results         = new PingResults();
            int         bufferSize      = 4096;

            // Find local address
            localAddress = IPAddress.Parse(Lookup.GetLocalAddress());

            try {
                // Create listener socket
                listeningSocket = new Socket(AddressFamily.InterNetwork, SocketType.Raw, ProtocolType.Icmp);
                listeningSocket.Bind(new IPEndPoint(localAddress, 0));
                listeningSocket.IOControl(IOControlCode.ReceiveAll, new byte[] { 1, 0, 0, 0 }, new byte[] { 1, 0, 0, 0 }); // Set SIO_RCVALL flag to socket IO control
                listeningSocket.ReceiveBufferSize = bufferSize;

                Display.ListenIntroMsg(localAddress.ToString());

                // Listening loop
                while (!cancellationToken.IsCancellationRequested)
                {
                    byte[] buffer = new byte[bufferSize];

                    // Recieve any incoming ICMPv4 packets
                    EndPoint remoteEndPoint = new IPEndPoint(IPAddress.Any, 0);
                    int      bytesRead      = Helper.RunWithCancellationToken(() => listeningSocket.ReceiveFrom(buffer, ref remoteEndPoint), cancellationToken);
                    ICMP     response       = new ICMP(buffer, bytesRead);

                    // Display captured packet
                    Display.CapturedPacket(response, remoteEndPoint.ToString(), DateTime.Now.ToString("h:mm:ss.ff tt"), bytesRead);

                    // Store results
                    results.CountPacketType(response.Type);
                    results.Received++;
                }
            }
            catch (OperationCanceledException) {
            }
            catch (SocketException) {
                Display.Error("Could not read packet from socket");
            }
            catch (Exception e) {
                Display.Error($"General exception occured while trying to create listening socket (Exception: {e.GetType().ToString().Split('.').Last()}");
            }

            // Clean up
            listeningSocket.Close();

            // TODO: Implement ListenResults method
            //Display.ListenResults(results);
        }
예제 #3
0
        public static void ListenForICMPOnAddress(IPAddress address)
        {
            Socket      listeningSocket = null;
            PingResults results         = new PingResults();
            int         bufferSize      = 4096;

            // Create listener socket
            try
            {
                listeningSocket = new Socket(AddressFamily.InterNetwork, SocketType.Raw, ProtocolType.Icmp);
                listeningSocket.Bind(new IPEndPoint(address, 0));
                listeningSocket.IOControl(IOControlCode.ReceiveAll, new byte[] { 1, 0, 0, 0 }, new byte[] { 1, 0, 0, 0 }); // Set SIO_RCVALL flag to socket IO control
                listeningSocket.ReceiveBufferSize = bufferSize;
            } catch (Exception e) {
                Display.Error($"Exception occured while trying to create listening socket for {address.ToString()} ({e.GetType().ToString().Split('.').Last()})");
                return;
            }

            Display.ListenIntroMsg(address.ToString());

            // Listening loop
            while (true)
            {
                byte[] buffer = new byte[bufferSize];


                try {
                    // Recieve any incoming ICMPv4 packets
                    EndPoint remoteEndPoint = new IPEndPoint(IPAddress.Any, 0);
                    int      bytesRead      = listeningSocket.ReceiveFrom(buffer, ref remoteEndPoint);
                    ICMP     response       = new ICMP(buffer, bytesRead);

                    // Display captured packet
                    Display.CapturedPacket(address.ToString(), response, remoteEndPoint.ToString(), DateTime.Now.ToString("h:mm:ss.ff tt"), bytesRead);

                    // Store results
                    results.CountPacketType(response.Type);
                    results.Received++;
                } catch (OperationCanceledException) {
                } catch (SocketException) {
                    Display.Error("Could not read packet from socket");
                }
            }



            listeningSocket.Close();
        }
예제 #4
0
        private static IPAddress[] GetLocalAddresses()
        {
            IPHostEntry hostAddress = null;

            // Get all addresses assocatied with this computer
            try {
                hostAddress = Dns.GetHostEntry(Dns.GetHostName());
            } catch (Exception e) {
                Display.Error($"Could not fetch local addresses ({e.GetType().ToString().Split('.').Last()})");
            }

            // Only get IPv4 address
            List <IPAddress> addresses = new List <IPAddress>();

            foreach (IPAddress address in hostAddress.AddressList)
            {
                if (address.AddressFamily == AddressFamily.InterNetwork)
                {
                    addresses.Add(address);
                }
            }

            return(addresses.ToArray());
        }
예제 #5
0
파일: Ping.cs 프로젝트: jdpurcell/PowerPing
        /// <summary>
        /// Network scanning method.
        ///
        /// Uses pings to scan a IP address range and identify hosts
        /// that are active.
        ///
        /// range should be in format 192.0.0.1-255, where - denotes the range
        /// This can be specified at any octlet of the address (192.0.1-100.1.255)
        /// </summary>
        /// <param name="range">Range of addresses to scan</param>
        public void Scan(string range, bool recursing = false)
        {
            List <string> scanList = new List <string>(); // List of addresses to scan

            String[]      ipSegments      = range.Split('.');
            PingResults   results         = new PingResults();
            List <string> activeHosts     = new List <string>();
            List <double> activeHostTimes = new List <double>();
            Stopwatch     scanTimer       = new Stopwatch();
            int           scanned         = 0;

            // Setup scan ping attributes
            PingAttributes attrs = new PingAttributes();

            attrs.Timeout      = 500;
            attrs.Interval     = 0;
            attrs.Count        = 1;
            Display.ShowOutput = false;

            // Check format of address (for '-'s and disallow multipl '-'s in one segment)
            if (!range.Contains("-"))
            {
                Display.Error("Scan - No range specified, must be specified in format: 192.168.1.1-254", true, true);
            }

            // Holds the ranges for each ip segment
            int[] segLower = new int[4];
            int[] segUpper = new int[4];

            // Work out upper and lower ranges for each segment
            try{
                for (int y = 0; y < 4; y++)
                {
                    string[] ranges = ipSegments[y].Split('-');
                    segLower[y] = Convert.ToInt16(ranges[0]);
                    segUpper[y] = (ranges.Length == 1) ? segLower[y] : Convert.ToInt16(ranges[1]);
                }
            } catch (FormatException) {
                Display.Error("Scan - Incorrect format [" + range + "], must be specified in format: 192.168.1.1-254", true, true);
            }

            // Build list of addresses from ranges
            for (int seg1 = segLower[0]; seg1 <= segUpper[0]; seg1++)
            {
                for (int seg2 = segLower[1]; seg2 <= segUpper[1]; seg2++)
                {
                    for (int seg3 = segLower[2]; seg3 <= segUpper[2]; seg3++)
                    {
                        for (int seg4 = segLower[3]; seg4 <= segUpper[3]; seg4++)
                        {
                            scanList.Add(new IPAddress(new byte[] { (byte)seg1, (byte)seg2, (byte)seg3, (byte)seg4 }).ToString());
                        }
                    }
                }
            }

            scanTimer.Start();

            // Scan loop
            foreach (string host in scanList)
            {
                // Update host
                attrs.Address = host;
                scanned++;

                // Reset global results for accurate results
                // (results need to be set globally while running for graph but need to be semi local for scan
                // or results bleed through so active hosts can't be determined)
                this.Results = new PingResults();

                // Send ping
                results = SendICMP(attrs);
                Display.ScanProgress(scanned, activeHosts.Count, scanList.Count, scanTimer.Elapsed, range, attrs.Address);

                if (results.Lost == 0 && results.ErrorPackets != 1)
                {
                    // If host is active, add to list
                    activeHosts.Add(host);
                    activeHostTimes.Add(results.CurTime);
                }
            }

            scanTimer.Stop();
            PowerPing.Display.ScanResults(scanList.Count, activeHosts, activeHostTimes);
        }
예제 #6
0
파일: Ping.cs 프로젝트: zanderphh/PowerPing
        private void SendPacket()
        {
            byte[] receiveBuffer = new byte[m_PingAttributes.ReceiveBufferSize]; // Ipv4Header.length + IcmpHeader.length + attrs.recievebuffersize
            int    bytesRead     = 0;

            // Sending loop
            for (int index = 1; m_PingAttributes.Continous || index <= m_PingAttributes.Count; index++)
            {
                if (index != 1)
                {
                    // Wait for set interval before sending again or cancel if requested
                    if (m_CancellationToken.WaitHandle.WaitOne(m_PingAttributes.Interval))
                    {
                        break;
                    }

                    // Generate random interval when RandomTiming flag is set
                    if (m_PingAttributes.RandomTiming)
                    {
                        m_PingAttributes.Interval = Helper.RandomInt(5000, 100000);
                    }
                }

                // Update packet before sending
                UpdatePacketSequenceNumber(index);
                if (m_PingAttributes.RandomMessage)
                {
                    UpdatePacketMessage(Encoding.ASCII.GetBytes(Helper.RandomString()));
                }
                UpdatePacketChecksum();

                try {
                    // Show request packet
                    if (Display.ShowRequests)
                    {
                        Display.RequestPacket(m_Packet, Display.UseInputtedAddress | Display.UseResolvedAddress ? m_PingAttributes.InputtedAddress : m_PingAttributes.ResolvedAddress, index);
                    }

                    // If there were extra responses from a prior request, ignore them
                    while (m_Socket.Available != 0)
                    {
                        bytesRead = m_Socket.Receive(receiveBuffer);
                    }

                    // Send ping request
                    m_Socket.SendTo(m_Packet.GetBytes(), m_PacketSize, SocketFlags.None, m_RemoteEndpoint); // Packet size = message field + 4 header bytes
                    long requestTimestamp = Stopwatch.GetTimestamp();
                    m_PingResults.IncrementSentPackets();

                    // Just for artifically testing higher ping response times
                    if (m_Debug)
                    {
                        Random rnd = new Random();
                        Thread.Sleep(rnd.Next(10, 400));
                        if (rnd.Next(3) == 1)
                        {
                            throw new SocketException();
                        }
                    }

                    // Try and recieve a packet
                    ICMP     response   = null;
                    EndPoint responseEP = m_RemoteEndpoint;
                    TimeSpan replyTime  = TimeSpan.Zero;
                    ReceivePacket(ref response, ref responseEP, ref replyTime, ref bytesRead, requestTimestamp);

                    if (Display.ShowReplies)
                    {
                        // Determine what form the response address is going to be displayed in
                        string responseAddress = responseEP.ToString();
                        if (Display.UseResolvedAddress)
                        {
                            // Returned address normally have port at the end (eg 8.8.8.8:0) so we need to remove that before trying to query the DNS
                            string responseIP = responseEP.ToString().Split(':')[0];

                            // Resolve the ip and store as the response address
                            responseAddress = Helper.RunWithCancellationToken(() => Lookup.QueryHost(responseIP), m_CancellationToken);
                        }
                        else if (Display.UseInputtedAddress)
                        {
                            responseAddress = m_PingAttributes.InputtedAddress;
                        }

                        Display.ReplyPacket(response, responseAddress, index, replyTime, bytesRead);
                    }

                    // Store response info
                    m_PingResults.IncrementReceivedPackets();
                    m_PingResults.CountPacketType(response.Type);
                    m_PingResults.SaveResponseTime(replyTime.TotalMilliseconds);

                    if (m_PingAttributes.BeepMode == 2)
                    {
                        try { Console.Beep(); }
                        catch (Exception) { } // Silently continue if Console.Beep errors
                    }
                }
                catch (IOException) {
                    if (Display.ShowOutput)
                    {
                        Display.Error("General transmit error");
                    }
                    m_PingResults.SaveResponseTime(-1);
                    m_PingResults.IncrementLostPackets();
                }
                catch (SocketException) {
                    Display.Timeout(index);
                    if (m_PingAttributes.BeepMode == 1)
                    {
                        try { Console.Beep(); }
                        catch (Exception) { }
                    }
                    m_PingResults.SaveResponseTime(-1);
                    m_PingResults.IncrementLostPackets();
                }
                catch (OperationCanceledException) {
                    m_PingResults.ScanWasCanceled = true;
                    break;
                }
                catch (Exception) {
                    if (Display.ShowOutput)
                    {
                        Display.Error("General error occured");
                    }
                    m_PingResults.SaveResponseTime(-1);
                    m_PingResults.IncrementLostPackets();
                }

                // Run callback (if provided) to notify of updated results
                OnPingResultsUpdateCallback?.Invoke(m_PingResults);
            }
        }
예제 #7
0
        /// <summary>
        /// Pases command line arguments and store properties in attributes object
        /// </summary>
        /// <param name="args">Command line arguments</param>
        /// <param name="attributes">PingAttributes object to store propterties from arguments</param>
        /// <returns>bool based on if parsing was successful or not</returns>
        public static bool Parse(string[] args, ref PingAttributes attributes)
        {
            int curArg = 0;

            // Loop through arguments
            try {
                checked {
                    for (int count = 0; count < args.Length; count++)
                    {
                        curArg = count;

                        switch (args[count])
                        {
                        case "/version":
                        case "-version":
                        case "--version":
                        case "/v":
                        case "-v":
                        case "--v":
                            Display.Version(true);
                            Helper.CheckRecentVersion();
                            Helper.WaitForUserInput();
                            Environment.Exit(0);
                            break;

                        case "/beep":
                        case "-beep":
                        case "--beep":
                        case "/b":
                        case "-b":
                        case "--b":
                            int level = Convert.ToInt32(args[count + 1]);
                            if (level > 2)
                            {
                                Display.Message("Invalid beep level, please use a number between 0 & 2");
                                throw new ArgumentFormatException();
                            }
                            attributes.BeepLevel = level;
                            break;

                        case "/count":
                        case "-count":
                        case "--count":
                        case "/c":
                        case "-c":
                        case "--c":     // Ping count
                            attributes.Count = Convert.ToInt32(args[count + 1]);
                            break;

                        case "/infinite":
                        case "-infinite":
                        case "--infinite":
                        case "/t":
                        case "-t":
                        case "--t":     // Infinitely send
                            attributes.Continous = true;
                            break;

                        case "/timeout":
                        case "-timeout":
                        case "--timeout":
                        case "/w":
                        case "-w":
                        case "--w":     // Timeout
                            attributes.Timeout = Convert.ToInt32(args[count + 1]);
                            break;

                        case "/message":
                        case "-message":
                        case "--message":
                        case "/m":
                        case "-m":
                        case "--m":     // Message
                            if (args[count + 1].Contains("--") || args[count + 1].Contains('/') || args[count + 1].Contains("-"))
                            {
                                throw new ArgumentFormatException();
                            }
                            attributes.Message = args[count + 1];
                            break;

                        case "/ttl":
                        case "-ttl":
                        case "--ttl":
                        case "/i":
                        case "-i":
                        case "--i":     // Time To Live
                            int ttl = Convert.ToInt16(args[count + 1]);
                            if (ttl > 255)
                            {
                                Display.Message("TTL has to be between 0 and 255");
                                throw new ArgumentFormatException();
                            }
                            attributes.Ttl = ttl;
                            break;

                        case "/interval":
                        case "-interval":
                        case "--interval":
                        case "/in":
                        case "-in":
                        case "--in":     // Interval
                            attributes.Interval = Convert.ToInt32(args[count + 1]);
                            if (attributes.Interval < 1)
                            {
                                Display.Message("Ping interval cannot be less than 1ms");
                                throw new ArgumentFormatException();
                            }
                            break;

                        case "/type":
                        case "-type":
                        case "--type":
                        case "/pt":
                        case "-pt":
                        case "--pt":     // Ping type
                            var type = Convert.ToByte(args[count + 1]);
                            if (type > 255)
                            {
                                throw new ArgumentFormatException();
                            }
                            attributes.Type = type;
                            break;

                        case "/code":
                        case "-code":
                        case "--code":
                        case "/pc":
                        case "-pc":
                        case "--pc":     // Ping code
                            attributes.Code = Convert.ToByte(args[count + 1]);
                            break;

                        case "/displaymsg":
                        case "-displaymsg":
                        case "--displaymsg":
                        case "/dm":
                        case "-dm":
                        case "--dm":     // Display packet message
                            Display.ShowMessages = true;
                            break;

                        case "/ipv4":
                        case "-ipv4":
                        case "--ipv4":
                        case "/4":
                        case "-4":
                        case "--4":     // Force ping with IPv4
                            if (attributes.ForceV6)
                            {
                                // Reset IPv6 force if already set
                                attributes.ForceV6 = false;
                            }
                            attributes.ForceV4 = true;
                            break;

                        case "/ipv6":
                        case "-ipv6":
                        case "--ipv6":
                        case "/6":
                        case "-6":
                        case "--6":     // Force ping with IPv6
                            if (attributes.ForceV4)
                            {
                                // Reset IPv4 force if already set
                                attributes.ForceV4 = false;
                            }
                            attributes.ForceV6 = true;
                            break;

                        case "/help":
                        case "-help":
                        case "--help":
                        case "/?":
                        case "-?":
                        case "--?":     // Display help message
                            Display.Help();
                            Helper.WaitForUserInput();
                            Environment.Exit(0);
                            break;

                        case "/examples":
                        case "-examples":
                        case "--examples":
                        case "/ex":
                        case "-ex":
                        case "--ex":             // Displays examples
                            Display.Examples();
                            Environment.Exit(0); // Exit after displaying examples
                            break;

                        case "/shorthand":
                        case "-shorthand":
                        case "--shorthand":
                        case "/sh":
                        case "-sh":
                        case "--sh":     // Use short hand messages
                            Display.Short = true;
                            break;

                        case "/nocolor":
                        case "-nocolor":
                        case "--nocolor":
                        case "/nc":
                        case "-nc":
                        case "--nc":     // No color mode
                            Display.NoColor = true;
                            break;

                        case "/ni":
                        case "-ni":
                        case "--ni":
                        case "/noinput":
                        case "-noinput":
                        case "--noinput":    // No input mode
                            Display.NoInput = true;
                            if (Properties.Settings.Default.RequireInput != true)
                            {
                                Display.Message(
                                    "(RequireInput is now permenantly OFF, you will no longer be prompted for user input anytime PowerPing is finished)",
                                    ConsoleColor.Cyan);
                            }
                            Properties.Settings.Default.RequireInput = false;
                            Properties.Settings.Default.Save();
                            break;

                        case "/ri":
                        case "-ri":
                        case "--ri":
                        case "/requireinput":
                        case "-requireinput":
                        case "--requireinput":
                            Display.NoInput = false;
                            if (Properties.Settings.Default.RequireInput != true)
                            {
                                Display.Message(
                                    "(RequireInput is now permenantly ON, from now on you will be prompted for user input whenever PowerPing is finished)",
                                    ConsoleColor.Cyan);
                            }
                            Properties.Settings.Default.RequireInput = true;
                            Properties.Settings.Default.Save();

                            break;

                        case "/decimals":
                        case "-decimals":
                        case "--decimals":
                        case "/dp":
                        case "-dp":
                        case "--dp":     // Decimal places
                            if (Convert.ToInt32(args[count + 1]) > 3 || Convert.ToInt32(args[count + 1]) < 0)
                            {
                                throw new ArgumentFormatException();
                            }
                            Display.DecimalPlaces = Convert.ToInt32(args[count + 1]);
                            break;

                        case "/symbols":
                        case "-symbols":
                        case "--symbols":
                        case "/sym":
                        case "-sym":
                        case "--sym":
                            Display.UseSymbols = true;
                            Display.SetAsciiReplySymbolsTheme(0);

                            // Change symbols theme if an argument is present
                            if (args.Length < count + 1)
                            {
                                count++;
                                continue;
                            }
                            if (args[count + 1].Contains("--") ||
                                args[count + 1].Contains('/') ||
                                args[count + 1].Contains("-") ||
                                args[count + 1].Contains("."))
                            {
                                count++;
                                continue;
                            }
                            int theme = Convert.ToInt32(args[count + 1]);
                            Display.SetAsciiReplySymbolsTheme(theme);
                            break;

                        case "/random":
                        case "-random":
                        case "--random":
                        case "/rng":
                        case "-rng":
                        case "--rng":
                            attributes.RandomMsg = true;
                            break;

                        case "/limit":
                        case "-limit":
                        case "--limit":
                        case "/l":
                        case "-l":
                        case "--l":
                            if (Convert.ToInt32(args[count + 1]) == 1)
                            {
                                Display.ShowSummary = false;
                                Display.ShowIntro   = false;
                            }
                            else if (Convert.ToInt32(args[count + 1]) == 2)
                            {
                                Display.ShowSummary  = false;
                                Display.ShowIntro    = false;
                                Display.ShowReplies  = false;
                                Display.ShowRequests = true;
                            }
                            else if (Convert.ToInt32(args[count + 1]) == 3)
                            {
                                Display.ShowReplies  = false;
                                Display.ShowRequests = false;
                            }
                            else
                            {
                                throw new ArgumentFormatException();
                            }
                            break;

                        case "/notimeout":
                        case "-notimeout":
                        case "--notimeout":
                        case "/nt":
                        case "-nt":
                        case "--nt":
                            Display.ShowTimeouts = false;
                            break;

                        case "/timestamp":
                        case "-timestamp":
                        case "--timestamp":
                        case "/ts":
                        case "-ts":
                        case "--ts":     // Display timestamp
                            if (args[count + 1].ToLower() == "utc")
                            {
                                Display.ShowtimeStampUTC = true;
                            }
                            else
                            {
                                Display.ShowTimeStamp = true;
                            }
                            break;

                        case "/fulltimestamp":
                        case "-fulltimestamp":
                        case "--fulltimestamp":
                        case "/fts":
                        case "-fts":
                        case "--fts":     // Display timestamp with date
                            if (count + 1 > args.Length)
                            {
                                Display.ShowFullTimeStamp = true;
                            }
                            else if (args[count + 1].ToLower() == "utc")
                            {
                                Display.ShowFullTimeStampUTC = true;
                            }
                            else
                            {
                                Display.ShowFullTimeStamp = true;
                            }
                            break;

                        case "/timing":
                        case "-timing":
                        case "--timing":
                        case "/ti":
                        case "-ti":
                        case "--ti":     // Timing option
                            switch (args[count + 1].ToLowerInvariant())
                            {
                            case "0":
                            case "paranoid":
                                attributes.Timeout  = 10000;
                                attributes.Interval = 300000;
                                break;

                            case "1":
                            case "sneaky":
                                attributes.Timeout  = 5000;
                                attributes.Interval = 120000;
                                break;

                            case "2":
                            case "quiet":
                                attributes.Timeout  = 5000;
                                attributes.Interval = 30000;
                                break;

                            case "3":
                            case "polite":
                                attributes.Timeout  = 3000;
                                attributes.Interval = 3000;
                                break;

                            case "4":
                            case "nimble":
                                attributes.Timeout  = 2000;
                                attributes.Interval = 750;
                                break;

                            case "5":
                            case "speedy":
                                attributes.Timeout  = 1500;
                                attributes.Interval = 500;
                                break;

                            case "6":
                            case "insane":
                                attributes.Timeout  = 750;
                                attributes.Interval = 100;
                                break;

                            case "7":
                            case "random":
                                attributes.RandomTiming = true;
                                attributes.RandomMsg    = true;
                                attributes.Interval     = Helper.RandomInt(5000, 100000);
                                attributes.Timeout      = 15000;
                                break;

                            default:         // Unknown timing type
                                throw new ArgumentFormatException();
                            }
                            break;

                        case "/request":
                        case "-request":
                        case "--request":
                        case "/requests":
                        case "-requests":
                        case "--requests":
                        case "/r":
                        case "-r":
                        case "--r":
                            Display.ShowRequests = true;
                            break;

                        case "/quiet":
                        case "-quiet":
                        case "--quiet":
                        case "/q":
                        case "-q":
                        case "--q":
                            Display.ShowOutput = false;
                            break;

                        case "/resolve":
                        case "-resolve":
                        case "--resolve":
                        case "/res":
                        case "-res":
                        case "--res":
                            Display.UseResolvedAddress = true;
                            break;

                        case "/inputaddr":
                        case "-inputaddr":
                        case "--inputaddr":
                        case "/ia":
                        case "-ia":
                        case "--ia":
                            Display.UseInputtedAddress = true;
                            break;

                        case "/buffer":
                        case "-buffer":
                        case "--buffer":
                        case "/rb":
                        case "-rb":
                        case "--rb":
                            int recvbuff = Convert.ToInt32(args[count + 1]);
                            if (recvbuff < 65000)
                            {
                                attributes.RecieveBufferSize = recvbuff;
                            }
                            else
                            {
                                throw new ArgumentFormatException();
                            }
                            break;

                        case "/checksum":
                        case "-checksum":
                        case "--checksum":
                        case "/chk":
                        case "-chk":
                        case "--chk":
                            Display.ShowChecksum = true;
                            break;

                        case "/dontfrag":
                        case "-dontfrag":
                        case "--dontfrag":
                        case "/df":
                        case "-df":
                        case "--df":
                            attributes.DontFragment = true;
                            break;

                        case "/size":
                        case "-size":
                        case "--size":
                        case "/s":
                        case "-s":
                        case "--s":
                            int size = Convert.ToInt32(args[count + 1]);
                            if (size < 100000)
                            {
                                attributes.Size = size;
                            }
                            else
                            {
                                throw new ArgumentFormatException();
                            }
                            break;

                        case "/whois":
                        case "-whois":
                        case "--whois":     // Whois lookup
                            attributes.Operation = PingOperation.Whois;
                            break;

                        case "/whoami":
                        case "-whoami":
                        case "--whoami":     // Current computer location
                            attributes.Operation = PingOperation.Whoami;
                            break;

                        case "/location":
                        case "-location":
                        case "--location":
                        case "/loc":
                        case "-loc":
                        case "--loc":     // Location lookup
                            attributes.Operation = PingOperation.Location;
                            break;

                        case "/listen":
                        case "-listen":
                        case "--listen":
                        case "/li":
                        case "-li":
                        case "--li":     // Listen for ICMP packets
                            attributes.Operation = PingOperation.Listen;
                            break;

                        case "/graph":
                        case "-graph":
                        case "--graph":
                        case "/g":
                        case "-g":
                        case "--g":     // Graph view
                            attributes.Operation = PingOperation.Graph;
                            break;

                        case "/compact":
                        case "-compact":
                        case "--compact":
                        case "/cg":
                        case "-cg":
                        case "--cg":     // Compact graph view
                            attributes.Operation = PingOperation.CompactGraph;
                            break;

                        case "/flood":
                        case "-flood":
                        case "--flood":
                        case "/fl":
                        case "-fl":
                        case "--fl":     // Flood
                            attributes.Operation = PingOperation.Flood;
                            break;

                        case "/scan":
                        case "-scan":
                        case "--scan":
                        case "/sc":
                        case "-sc":
                        case "--sc":     // Scan
                            attributes.Operation = PingOperation.Scan;
                            break;

                        default:
                            // Check for invalid argument
                            if ((args[count].Contains("--") || args[count].Contains("/") || args[count].Contains("-")) &&
                                attributes.Operation != PingOperation.Scan &&     // (ignore if scanning) // TODO: Change this
                                (!Helper.IsURL(args[count]) && !Helper.IsIPv4Address(args[count])))
                            {
                                throw new InvalidArgumentException();
                            }
                            break;
                        }
                    }
                }
            }
            catch (IndexOutOfRangeException) {
                Display.Error($"Missing argument parameter @ \"PowerPing >>>{args[curArg]}<<<\"");
                return(false);
            }
            catch (OverflowException) {
                Display.Error($"Overflow while converting @ \"PowerPing {args[curArg]} >>>{args[curArg + 1]}<<<\"");
                return(false);
            }
            catch (InvalidArgumentException) {
                Display.Error($"Invalid argument @ \"PowerPing >>>{args[curArg]}<<<\"");
                return(false);
            }
            catch (ArgumentFormatException) {
                Display.Error($"Incorrect parameter for [{args[curArg]}] @ \"PowerPing {args[curArg]} >>>{args[curArg + 1]}<<<\"");
                return(false);
            }
            catch (Exception e) {
                Display.Error($"An {e.GetType().ToString().Split('.').Last()} exception occured @ \"PowerPing >>>{args[curArg]}<<<\"");
                return(false);
            }
            return(true);
        }
예제 #8
0
        private PingResults SendICMP(PingAttributes attrs, Action <PingResults> resultsUpdateCallback = null)
        {
            PingResults results = new PingResults();
            ICMP        packet  = new ICMP();

            byte[] receiveBuffer = new byte[attrs.RecieveBufferSize]; // Ipv4Header.length + IcmpHeader.length + attrs.recievebuffersize
            int    bytesRead, packetSize;

            // Convert to IPAddress
            IPAddress ipAddr = IPAddress.Parse(attrs.Address);

            // Setup endpoint
            IPEndPoint iep = new IPEndPoint(ipAddr, 0);

            // Setup raw socket
            Socket sock = CreateRawSocket(ipAddr.AddressFamily);

            // Helper function to set receive timeout (only if it's changing)
            int appliedReceiveTimeout = 0;

            void SetReceiveTimeout(int receiveTimeout)
            {
                if (receiveTimeout != appliedReceiveTimeout)
                {
                    sock.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReceiveTimeout, receiveTimeout);
                    appliedReceiveTimeout = receiveTimeout;
                }
            }

            // Set socket options
            sock.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.IpTimeToLive, attrs.Ttl);
            sock.DontFragment      = attrs.DontFragment;
            sock.ReceiveBufferSize = attrs.RecieveBufferSize;

            // Create packet message payload
            byte[] payload;
            if (attrs.Size != -1)
            {
                payload = Helper.GenerateByteArray(attrs.Size);
            }
            else
            {
                payload = Encoding.ASCII.GetBytes(attrs.Message);
            }

            // Construct our ICMP packet
            packet.Type = attrs.Type;
            packet.Code = attrs.Code;
            Buffer.BlockCopy(BitConverter.GetBytes(m_SessionId), 0, packet.Message, 0, 2); // Add identifier to ICMP message
            Buffer.BlockCopy(payload, 0, packet.Message, 4, payload.Length);               // Add text into ICMP message
            packet.MessageSize = payload.Length + 4;
            packetSize         = packet.MessageSize + 4;

            // Sending loop
            for (int index = 1; attrs.Continous || index <= attrs.Count; index++)
            {
                if (index != 1)
                {
                    // Wait for set interval before sending again or cancel if requested
                    if (m_CancellationToken.WaitHandle.WaitOne(attrs.Interval))
                    {
                        break;
                    }

                    // Generate random interval when RandomTimings flag is set
                    if (attrs.RandomTiming)
                    {
                        attrs.Interval = Helper.RandomInt(5000, 100000);
                    }
                }

                // Include sequence number in ping message
                ushort sequenceNum = (ushort)index;
                Buffer.BlockCopy(BitConverter.GetBytes(sequenceNum), 0, packet.Message, 2, 2);

                // Fill ICMP message field
                if (attrs.RandomMsg)
                {
                    payload = Encoding.ASCII.GetBytes(Helper.RandomString());
                    Buffer.BlockCopy(payload, 0, packet.Message, 4, payload.Length);
                }

                // Update packet checksum
                packet.Checksum = 0;
                UInt16 chksm = packet.GetChecksum();
                packet.Checksum = chksm;

                try {
                    // Show request packet
                    if (Display.ShowRequests)
                    {
                        Display.RequestPacket(packet, Display.UseInputtedAddress | Display.UseResolvedAddress ? attrs.InputtedAddress : attrs.Address, index);
                    }

                    // If there were extra responses from a prior request, ignore them
                    while (sock.Available != 0)
                    {
                        bytesRead = sock.Receive(receiveBuffer);
                    }

                    // Send ping request
                    sock.SendTo(packet.GetBytes(), packetSize, SocketFlags.None, iep); // Packet size = message field + 4 header bytes
                    long requestTimestamp = Stopwatch.GetTimestamp();
                    try { results.Sent++; }
                    catch (OverflowException) { results.HasOverflowed = true; }

                    if (m_Debug)
                    {
                        // Induce random wait for debugging
                        Random rnd = new Random();
                        Thread.Sleep(scale);//rnd.Next(scale));//1500));
                        //Thread.Sleep(rnd.Next(100));
                        if (inverting)
                        {
                            scale -= 5;
                        }
                        else
                        {
                            scale += 5;
                        }
                        if (scale > 1100)
                        {
                            inverting = true;
                        }
                        else if (scale == 10)
                        {
                            inverting = false;
                        }
                        //if (rnd.Next(20) == 1) { throw new SocketException(); }
                    }

                    ICMP     response;
                    EndPoint responseEP = iep;
                    TimeSpan replyTime  = TimeSpan.Zero;
                    do
                    {
                        // Cancel if requested
                        m_CancellationToken.ThrowIfCancellationRequested();

                        // Set receive timeout, limited to 250ms so we don't block very long without checking for
                        // cancellation. If the requested ping timeout is longer, we will wait some more in subsequent
                        // loop iterations until the requested ping timeout is reached.
                        int remainingTimeout = (int)Math.Ceiling(attrs.Timeout - replyTime.TotalMilliseconds);
                        if (remainingTimeout <= 0)
                        {
                            throw new SocketException();
                        }
                        SetReceiveTimeout(Math.Min(remainingTimeout, 250));

                        // Wait for response
                        try {
                            bytesRead = sock.ReceiveFrom(receiveBuffer, ref responseEP);
                        } catch (SocketException) {
                            bytesRead = 0;
                        }
                        replyTime = new TimeSpan(Helper.StopwatchToTimeSpanTicks(Stopwatch.GetTimestamp() - requestTimestamp));

                        if (bytesRead == 0)
                        {
                            response = null;
                        }
                        else
                        {
                            // Store reply packet
                            response = new ICMP(receiveBuffer, bytesRead);

                            // If we sent an echo and receive a response with a different identifier or sequence
                            // number, ignore it (it could correspond to an older request that timed out)
                            if (packet.Type == 8 && response.Type == 0)
                            {
                                ushort responseSessionId   = BitConverter.ToUInt16(response.Message, 0);
                                ushort responseSequenceNum = BitConverter.ToUInt16(response.Message, 2);
                                if (responseSessionId != m_SessionId || responseSequenceNum != sequenceNum)
                                {
                                    response = null;
                                }
                            }
                        }
                    } while (response == null);

                    // Display reply packet
                    if (Display.ShowReplies)
                    {
                        Display.ReplyPacket(response, Display.UseInputtedAddress | Display.UseResolvedAddress ? attrs.InputtedAddress : responseEP.ToString(), index, replyTime, bytesRead);
                    }

                    // Store response info
                    try { results.Received++; }
                    catch (OverflowException) { results.HasOverflowed = true; }
                    results.CountPacketType(response.Type);
                    results.SaveResponseTime(replyTime.TotalMilliseconds);

                    if (attrs.BeepLevel == 2)
                    {
                        try { Console.Beep(); }
                        catch (Exception) { } // Silently continue if Console.Beep errors
                    }
                } catch (IOException) {
                    if (Display.ShowOutput)
                    {
                        Display.Error("General transmit error");
                    }
                    results.SaveResponseTime(-1);
                    try { results.Lost++; }
                    catch (OverflowException) { results.HasOverflowed = true; }
                } catch (SocketException) {
                    Display.Timeout(index);
                    if (attrs.BeepLevel == 1)
                    {
                        try { Console.Beep(); }
                        catch (Exception) { results.HasOverflowed = true; }
                    }
                    results.SaveResponseTime(-1);
                    try { results.Lost++; }
                    catch (OverflowException) { results.HasOverflowed = true; }
                } catch (OperationCanceledException) {
                    results.ScanWasCanceled = true;
                    break;
                } catch (Exception) {
                    if (Display.ShowOutput)
                    {
                        Display.Error("General error occured");
                    }
                    results.SaveResponseTime(-1);
                    try { results.Lost++; }
                    catch (OverflowException) { results.HasOverflowed = true; }
                }

                // Run callback (if provided) to notify of updated results
                resultsUpdateCallback?.Invoke(results);
            }

            // Clean up
            sock.Close();

            return(results);
        }