Пример #1
0
        public static void PacketType(ICMP packet)
        {
            // Apply colour rules
            if (!NoColor)
            {
                Console.BackgroundColor = packet.Type > typeColors.Length ? ConsoleColor.White : typeColors[packet.Type];
                Console.ForegroundColor = ConsoleColor.Black;
            }

            // Print packet type
            switch (packet.Type)
            {
            case 3:
                Console.Write(packet.Code > destUnreachableCodeValues.Length ? packetTypes[packet.Type] : destUnreachableCodeValues[packet.Code]);
                break;

            case 5:
                Console.Write(packet.Code > redirectCodeValues.Length ? packetTypes[packet.Type] : redirectCodeValues[packet.Code]);
                break;

            case 11:
                Console.Write(packet.Code > timeExceedCodeValues.Length ? packetTypes[packet.Type] : timeExceedCodeValues[packet.Code]);
                break;

            case 12:
                Console.Write(packet.Code > badParameterCodeValues.Length ? packetTypes[packet.Type] : badParameterCodeValues[packet.Code]);
                break;

            default:
                Console.Write(packet.Type > packetTypes.Length ? "[" + packet.Type + "] UNASSIGNED " : packetTypes[packet.Type]);
                break;
            }

            ResetColor();
        }
Пример #2
0
        /// <summary>
        /// Display ICMP packet that have been sent
        /// </summary>
        public static void RequestPacket(ICMP packet, String address, int index)
        {
            if (!Display.ShowOutput)
            {
                return;
            }

            // Show shortened info
            if (Short)
            {
                Console.Write(REQUEST_MSG_SHORT, address);
            }
            else
            {
                Console.Write(REQUEST_MSG, address, index, packet.GetBytes().Length);
            }

            // Print coloured type
            PacketType(packet);
            Console.Write(REQUEST_CODE_TXT, packet.code);

            // Display timestamp
            if (ShowTimeStamp)
            {
                Console.Write(TIMESTAMP_LAYOUT, DateTime.Now.ToString("HH:mm:ss"));
            }

            // End line
            Console.WriteLine();
        }
Пример #3
0
        public static void PacketType(ICMP packet)
        {
            // Apply colour rules
            if (!Configuration.NoColor)
            {
                Console.BackgroundColor = packet.Type > _typeColors.Length ? ConsoleColor.White : _typeColors[packet.Type];
                Console.ForegroundColor = ConsoleColor.Black;
            }

            // Print packet type
            switch (packet.Type)
            {
            case 3:
                Console.Write(packet.Code > ICMPStrings.DestinationUnreachableCodeValues.Length ? ICMPStrings.PacketTypes[packet.Type] : ICMPStrings.DestinationUnreachableCodeValues[packet.Code]);
                break;

            case 5:
                Console.Write(packet.Code > ICMPStrings.RedirectCodeValues.Length ? ICMPStrings.PacketTypes[packet.Type] : ICMPStrings.RedirectCodeValues[packet.Code]);
                break;

            case 11:
                Console.Write(packet.Code > ICMPStrings.TimeExceedCodeValues.Length ? ICMPStrings.PacketTypes[packet.Type] : ICMPStrings.TimeExceedCodeValues[packet.Code]);
                break;

            case 12:
                Console.Write(packet.Code > ICMPStrings.BadParameterCodeValues.Length ? ICMPStrings.PacketTypes[packet.Type] : ICMPStrings.BadParameterCodeValues[packet.Code]);
                break;

            default:
                Console.Write(packet.Type > ICMPStrings.PacketTypes.Length ? "[" + packet.Type + "] UNASSIGNED " : ICMPStrings.PacketTypes[packet.Type]);
                break;
            }

            ResetColor();
        }
Пример #4
0
 private void Cleanup()
 {
     // On deconstruction
     m_Socket.Close();
     m_Packet                    = null;
     m_PingAttributes            = null;
     m_PingResults               = null;
     OnPingResultsUpdateCallback = null;
 }
Пример #5
0
        /// <summary>
        /// Display information about a captured packet
        /// </summary>
        public static void CapturedPacket(string localAddress, ICMP packet, string remoteAddress, string timeReceived, int bytesRead)
        {
            // Display captured packet
            Console.BackgroundColor = packet.Type > typeColors.Length ? ConsoleColor.Black : typeColors[packet.Type];
            Console.ForegroundColor = ConsoleColor.Black;
            Console.WriteLine(CAPTURED_PACKET_MSG, timeReceived, bytesRead, remoteAddress, packet.Type, packet.Code, localAddress);

            // Reset console colours
            ResetColor();
        }
Пример #6
0
        /// <summary>
        /// Display information about a captured packet
        /// </summary>
        public static void CapturedPacket(ICMP packet, String address, String timeReceived, int bytesRead)
        {
            // Display captured packet
            Console.BackgroundColor = packet.type > typeColors.Length ? ConsoleColor.Black : typeColors[packet.type];
            Console.ForegroundColor = ConsoleColor.Black;
            Console.WriteLine(CAPTURED_PACKET_MSG, timeReceived, bytesRead, address, packet.type, packet.code);

            // Reset console colours
            ResetColor();
        }
Пример #7
0
        /// <summary>
        /// Listens for all ICMPv4 activity on localhost.
        ///
        /// Does this by setting a raw socket to SV_IO_ALL which
        /// will recieve all packets and filters to just show
        /// ICMP packets. Runs until ctrl-c or exit
        /// </summary>
        /// <source>https://stackoverflow.com/a/9174392</source>
        public void Listen()
        {
            IPAddress   localAddress    = null;
            Socket      listeningSocket = null;
            PingResults results         = new PingResults();

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

            IsRunning = true;
            try {
                // Create listener socket
                listeningSocket = CreateRawSocket(AddressFamily.InterNetwork);
                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

                PowerPing.Display.ListenIntroMsg();

                // Listening loop
                while (true)
                {
                    byte[] buffer = new byte[4096]; // TODO: could cause overflow?

                    // 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
                    PowerPing.Display.CapturedPacket(response, remoteEndPoint.ToString(), DateTime.Now.ToString("h:mm:ss.ff tt"), bytesRead);

                    // Store results
                    results.CountPacketType(response.type);
                    results.Received++;

                    if (cancelEvent.WaitOne(0))
                    {
                        break;
                    }
                }
            } catch (SocketException) {
                PowerPing.Display.Error("Could not read packet from socket");
                results.Lost++;
            } catch (Exception) {
                PowerPing.Display.Error("General exception occured", true);
            }

            // Clean up
            IsRunning = false;
            listeningSocket.Close();

            Display.ListenResults(results);
        }
Пример #8
0
        private void ReceivePacket(ref ICMP response, ref EndPoint responseEndPoint, ref TimeSpan replyTime, ref int bytesRead, long requestTimestamp)
        {
            byte[] receiveBuffer = new byte[m_PingAttributes.ReceiveBufferSize];

            // Wait for request
            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(m_PingAttributes.Timeout - replyTime.TotalMilliseconds);
                if (remainingTimeout <= 0)
                {
                    throw new SocketException();
                }
                SetSocketReceiveTimeout(Math.Min(remainingTimeout, 250));

                // Wait for response
                try {
                    bytesRead = m_Socket.ReceiveFrom(receiveBuffer, ref responseEndPoint);
                }
                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 (m_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 != m_CurrentSequenceNumber)
                        {
                            response = null;
                        }
                    }
                }
            } while (response == null);
        }
Пример #9
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)
            {
                ConsoleDisplay.Error($"Exception occured while trying to create listening socket for {address.ToString()} ({e.GetType().ToString().Split('.').Last()})");
                return;
            }

            ConsoleDisplay.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
                    ConsoleDisplay.CapturedPacket(address.ToString(), response, remoteEndPoint.ToString(), DateTime.Now.ToString("h:mm:ss.ff tt"), bytesRead);

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

            listeningSocket.Close();
        }
Пример #10
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);
        }
Пример #11
0
        /// <summary>
        /// Display ICMP packet that have been sent
        /// </summary>
        public static void RequestPacket(ICMP packet, string address, int index)
        {
            if (!Configuration.ShowOutput || !Configuration.ShowRequests)
            {
                return;
            }

            // Show shortened info
            if (Configuration.Short)
            {
                Console.Write(ProgramStrings.REQUEST_MSG_SHORT, address);
            }
            else
            {
                Console.Write(ProgramStrings.REQUEST_MSG, address, index, packet.GetBytes().Length);
            }

            // Print coloured type
            PacketType(packet);
            Console.Write(ProgramStrings.REQUEST_CODE_TXT, packet.Code);

            // Display timestamp
            if (Configuration.ShowFullTimeStamp)
            {
                Console.Write(ProgramStrings.TIMESTAMP_LAYOUT, DateTime.Now.ToString(CultureInfo.CurrentCulture));
            }
            else if (Configuration.ShowFullTimeStampUTC)
            {
                Console.Write(ProgramStrings.TIMESTAMP_LAYOUT, DateTime.UtcNow.ToString(CultureInfo.CurrentCulture));
            }
            else if (Configuration.ShowTimeStamp)
            {
                Console.Write(ProgramStrings.TIMESTAMP_LAYOUT, DateTime.Now.ToString("HH:mm:ss"));
            }
            else if (Configuration.ShowtimeStampUTC)
            {
                Console.Write(ProgramStrings.TIMESTAMP_LAYOUT, DateTime.UtcNow.ToString("HH:mm:ss"));
            }

            // End line
            Console.WriteLine();
        }
Пример #12
0
        private void ConstructPacket()
        {
            m_Packet      = new ICMP();
            m_Packet.Type = m_PingAttributes.Type;
            m_Packet.Code = m_PingAttributes.Code;

            // Work out what our intial payload will be and add to packet
            byte[] payload;
            if (m_PingAttributes.ArtificalMessageSize != -1)
            {
                payload = Helper.GenerateByteArray(m_PingAttributes.ArtificalMessageSize);
            }
            else
            {
                payload = Encoding.ASCII.GetBytes(m_PingAttributes.Message);
            }
            UpdatePacketMessage(payload);

            Buffer.BlockCopy(BitConverter.GetBytes(m_SessionId), 0, m_Packet.Message, 0, 2); // Add identifier to ICMP message
        }
Пример #13
0
        /// <summary>
        /// Core ICMP sending method (used by all other functions)
        /// Takes a set of attributes, performs operation and returns a set of results.
        ///
        /// Works specifically by creating a raw socket, creating a ICMP object and
        /// other socket properties (timeouts, interval etc) using the
        /// inputted properties (attrs), then performs ICMP operation
        /// before cleaning up and returning results.
        ///
        /// NOTE: There is a weird hack here, The set of PingAttributes used are
        /// those provided in the parameter as opposed to the ones stored
        /// in this class (Ping.Attributes) (similar case with PingResults).
        /// This is due to some functions (flood, scan) requiring to be run on seperate threads
        /// and needing us to pass specific attributes directly to the object
        /// trust me it works (I think..)
        /// </summary>
        /// <param name="attrs">Properties of pings to be sent</param>
        /// <returns>Set of ping results</returns>
        private PingResults SendICMP(PingAttributes attrs)
        {
            IPEndPoint iep    = null;
            EndPoint   ep     = null;
            IPAddress  ipAddr = null;
            ICMP       packet = new ICMP();
            Socket     sock   = null;

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

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

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

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

            // Set socket options
            sock.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReceiveTimeout, attrs.Timeout); // Socket timeout
            sock.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.IpTimeToLive, attrs.Ttl);
            sock.DontFragment = attrs.DontFragment;

            // 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(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
            while (attrs.Continous ? true : index <= attrs.Count)
            {
                // Exit loop if cancel event is set
                if (cancelEvent.WaitOne(0))
                {
                    break;
                }
                else
                {
                    IsRunning = true;
                }

                // 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.Host : attrs.Address, index);
                    }

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

                    // 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 (debug)
                    {
                        // Induce random wait for debugging
                        Random rnd = new Random();
                        Thread.Sleep(rnd.Next(700));
                        if (rnd.Next(20) == 1)
                        {
                            throw new SocketException();
                        }
                    }

                    ICMP     response;
                    TimeSpan replyTime;
                    do
                    {
                        // Wait for response
                        bytesRead = sock.ReceiveFrom(receiveBuffer, ref ep);
                        replyTime = new TimeSpan(Helper.StopwatchToTimeSpanTicks(Stopwatch.GetTimestamp() - requestTimestamp));

                        // Store reply packet
                        response = new ICMP(receiveBuffer, bytesRead);

                        // Ignore unexpected echo responses
                        if (packet.type == 8 && response.type == 0)
                        {
                            ushort responseSessionId   = BitConverter.ToUInt16(response.message, 0);
                            ushort responseSequenceNum = BitConverter.ToUInt16(response.message, 2);
                            if (responseSessionId != sessionId || responseSequenceNum != sequenceNum)
                            {
                                if (replyTime.TotalMilliseconds >= attrs.Timeout)
                                {
                                    throw new SocketException();
                                }
                                response = null;
                            }
                        }
                    } while (response == null);

                    // Display reply packet
                    if (Display.ShowReplies)
                    {
                        PowerPing.Display.ReplyPacket(response, Display.UseInputtedAddress | Display.UseResolvedAddress ? attrs.Host : ep.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)
                    {
                        PowerPing.Display.Error("General transmit error");
                    }
                    Results.SaveResponseTime(-1);
                    try { Results.Lost++; }
                    catch (OverflowException) { Results.HasOverflowed = true; }
                } catch (SocketException) {
                    PowerPing.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 (Exception) {
                    if (Display.ShowOutput)
                    {
                        PowerPing.Display.Error("General error occured");
                    }
                    Results.SaveResponseTime(-1);
                    try { Results.Lost++; }
                    catch (OverflowException) { Results.HasOverflowed = true; }
                } finally {
                    // Increment seq and wait for interval
                    index++;

                    // Wait for set interval before sending again
                    cancelEvent.WaitOne(attrs.Interval);

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

                // Stop sending if flag is set
                if (!IsRunning)
                {
                    break;
                }
            }

            // Clean up
            IsRunning = false;
            sock.Close();

            return(Results);
        }
Пример #14
0
        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);
            }
        }
Пример #15
0
        /// <summary>
        /// Display information about reply ping packet
        /// </summary>
        /// <param name="packet">Reply packet</param>
        /// <param name="address">Reply address</param>
        /// <param name="index">Sequence number</param>
        /// <param name="replyTime">Time taken before reply received in milliseconds</param>
        public static void ReplyPacket(ICMP packet, string address, int index, TimeSpan replyTime, int bytesRead)
        {
            if (!Display.ShowOutput)
            {
                return;
            }

            // If drawing symbols
            if (UseSymbols)
            {
                if (packet.Type == 0x00)
                {
                    if (replyTime <= TimeSpan.FromMilliseconds(100))
                    {
                        Console.ForegroundColor = ConsoleColor.Green;
                        Console.Write(ReplySymbols.LessThan100);
                    }
                    else if (replyTime <= TimeSpan.FromMilliseconds(250))
                    {
                        Console.ForegroundColor = ConsoleColor.Yellow;
                        Console.Write(ReplySymbols.LessThan250);
                    }
                    else if (replyTime <= TimeSpan.FromMilliseconds(500))
                    {
                        Console.ForegroundColor = ConsoleColor.Red;
                        Console.Write(ReplySymbols.LessThan500);
                    }
                    else
                    {
                        Console.ForegroundColor = ConsoleColor.Magenta;
                        Console.Write(ReplySymbols.GreaterThan500);
                    }
                    ResetColor();
                }
                else
                {
                    Timeout(0);
                }
                return;
            }

            // Show shortened info
            if (Short)
            {
                Console.Write(REPLY_MSG_SHORT, address);
            }
            else
            {
                Console.Write(REPLY_MSG, address, index, bytesRead);
            }

            // Print icmp packet type
            PacketType(packet);

            // Display ICMP message (if specified)
            if (ShowMessages)
            {
                string messageWithoutHeader = Encoding.ASCII.GetString(packet.Message, 4, packet.Message.Length - 4);
                Console.Write(REPLY_MSG_TXT, new string(messageWithoutHeader.Where(c => !char.IsControl(c)).ToArray()));
            }

            // Print coloured time segment
            Console.Write(REPLY_TIME_TXT);
            if (!NoColor)
            {
                if (replyTime <= TimeSpan.FromMilliseconds(100))
                {
                    Console.ForegroundColor = ConsoleColor.Green;
                }
                else if (replyTime <= TimeSpan.FromMilliseconds(500))
                {
                    Console.ForegroundColor = ConsoleColor.Yellow;
                }
                else
                {
                    Console.ForegroundColor = ConsoleColor.Red;
                }
            }
            Console.Write("{0:0." + new string('0', DecimalPlaces) + "}ms", replyTime.TotalMilliseconds);
            ResetColor();

            // Display checksum
            if (ShowChecksum)
            {
                Console.Write(REPLY_CHKSM_TXT, packet.Checksum);
            }

            // Display timestamp
            if (ShowFullTimeStamp)
            {
                Console.Write(TIMESTAMP_LAYOUT, DateTime.Now.ToString(CultureInfo.CurrentCulture));
            }
            else if (ShowFullTimeStampUTC)
            {
                Console.Write(TIMESTAMP_LAYOUT, DateTime.UtcNow.ToString(CultureInfo.CurrentCulture));
            }
            else if (ShowTimeStamp)
            {
                Console.Write(TIMESTAMP_LAYOUT, DateTime.Now.ToString("HH:mm:ss"));
            }
            else if (ShowtimeStampUTC)
            {
                Console.Write(TIMESTAMP_LAYOUT, DateTime.UtcNow.ToString("HH:mm:ss"));
            }

            // End line
            Console.WriteLine();
        }
Пример #16
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);
        }