/// <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); }
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); }
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(); }
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()); }
/// <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); }
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> /// 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); }
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); }