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(); }
/// <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(); }
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(); }
private void Cleanup() { // On deconstruction m_Socket.Close(); m_Packet = null; m_PingAttributes = null; m_PingResults = null; OnPingResultsUpdateCallback = null; }
/// <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(); }
/// <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(); }
/// <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); }
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); }
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(); }
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); }
/// <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(); }
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 }
/// <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); }
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); } }
/// <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(); }
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); }