public static async Task <IEnumerable <IPAddress> > GetFullRoute(string adr) { var ret = new List <IPAddress>(); using (var pong = new Ping()) { var po = new PingOptions(1, true); PingReply?r = null; var buffer = new byte[buffer_size]; for (var i = 0; i < buffer.Length; i++) { buffer[i] = 0; } for (var i = 1; i < max_hops; i++) { if (r != null && r.Status != IPStatus.TimedOut) { po.Ttl = i; } r = await pong.SendPingAsync(adr, ping_timeout, buffer, po).ConfigureAwait(false); if (r.Status == IPStatus.TtlExpired) { ret.Add(r.Address); } else { break; } } } ret.Add(IPAddress.Parse(adr)); return(ret); }
private bool TryGetPingReply( SocketConfig socketConfig, byte[] receiveBuffer, int bytesReceived, Stopwatch sw, ref int ipHeaderLength, [NotNullWhen(true)] out PingReply?reply) { byte type, code; reply = null; if (socketConfig.IsIpv4) { // Determine actual size of IP header byte ihl = (byte)(receiveBuffer[0] & 0x0f); // Internet Header Length ipHeaderLength = 4 * ihl; if (bytesReceived - ipHeaderLength < IcmpHeaderLengthInBytes) { return(false); // Not enough bytes to reconstruct actual IP header + ICMP header. } } int icmpHeaderOffset = ipHeaderLength; // Skip IP header. IcmpHeader receivedHeader = MemoryMarshal.Read <IcmpHeader>(receiveBuffer.AsSpan(icmpHeaderOffset)); type = receivedHeader.Type; code = receivedHeader.Code; if (socketConfig.Identifier != receivedHeader.Identifier || type == (byte)IcmpV4MessageType.EchoRequest || type == (byte)IcmpV6MessageType.EchoRequest) // Echo Request, ignore { return(false); } sw.Stop(); long roundTripTime = sw.ElapsedMilliseconds; int dataOffset = ipHeaderLength + IcmpHeaderLengthInBytes; // We want to return a buffer with the actual data we sent out, not including the header data. byte[] dataBuffer = new byte[bytesReceived - dataOffset]; Buffer.BlockCopy(receiveBuffer, dataOffset, dataBuffer, 0, dataBuffer.Length); IPStatus status = socketConfig.IsIpv4 ? IcmpV4MessageConstants.MapV4TypeToIPStatus(type, code) : IcmpV6MessageConstants.MapV6TypeToIPStatus(type, code); IPAddress address = ((IPEndPoint)socketConfig.EndPoint).Address; reply = new PingReply(address, socketConfig.Options, status, roundTripTime, dataBuffer); return(true); }
private async Task <(PCStatus, string)> GetStatusAsync() { PingReply?pingReply = null; try { if (!Uri.TryCreate(BaseAddress, UriKind.Absolute, out var baseAddressUri)) { return(PCStatus.Offline, $"Invalid URI : '{BaseAddress}'"); } if (IPAddress.TryParse(baseAddressUri.Host, out var baseIpAddress)) { try { pingReply = pinger.Send(baseIpAddress); } catch (PingException ex) { pingReply = null; } } if (pingReply != null && pingReply.Status != IPStatus.Success) { return(PCStatus.Offline, null); } var res = await ValidatePin(); if (res) { return(PCStatus.ValidPIN, null); } else { return(PCStatus.ServerOnline, null); } } catch (Exception ex) { var message = ex is OperationCanceledException?null: $"{ex.GetType().Name}{Environment.NewLine}{ex.Message}{Environment.NewLine}{ex.StackTrace}"; if (pingReply == null) { return(PCStatus.Offline, message); } else { return(PCStatus.DeviceOnline, message); } } }
private static bool TryParseTtlExceeded(string stdout, out PingReply?reply) { reply = null; if (!stdout.Contains("Time to live exceeded", StringComparison.Ordinal)) { return(false); } // look for address in "From 172.21.64.1 icmp_seq=1 Time to live exceeded" int addressStart = stdout.IndexOf("From ", StringComparison.Ordinal) + 5; int addressLength = stdout.IndexOf(' ', Math.Max(addressStart, 0)) - addressStart; IPAddress?address; if (addressStart < 5 || addressLength <= 0 || !IPAddress.TryParse(stdout.AsSpan(addressStart, addressLength), out address)) { // failed to parse source address (which in case of TTL is different than the original // destination address), fallback to all 0 address = new IPAddress(0); } reply = CreatePingReply(IPStatus.TimeExceeded, address); return(true); }
internal PingCompletedEventArgs(PingReply?reply, Exception?error, bool cancelled, object?userToken) : base(error, cancelled, userToken) { Reply = reply; }
private void ProcessMTUSize(string targetNameOrAddress) { PingReply?reply, replyResult = null; if (!TryResolveNameOrAddress(targetNameOrAddress, out string resolvedTargetName, out IPAddress? targetAddress)) { if (Quiet.IsPresent) { WriteObject(-1); } return; } // Caution! Algorithm is sensitive to changing boundary values. int HighMTUSize = 10000; int CurrentMTUSize = 1473; int LowMTUSize = targetAddress.AddressFamily == AddressFamily.InterNetworkV6 ? 1280 : 68; int timeout = TimeoutSeconds * 1000; try { PingOptions pingOptions = new PingOptions(MaxHops, true); int retry = 1; while (LowMTUSize < (HighMTUSize - 1)) { byte[] buffer = GetSendBuffer(CurrentMTUSize); WriteDebug(StringUtil.Format( "LowMTUSize: {0}, CurrentMTUSize: {1}, HighMTUSize: {2}", LowMTUSize, CurrentMTUSize, HighMTUSize)); reply = SendCancellablePing(targetAddress, timeout, buffer, pingOptions); if (reply.Status == IPStatus.PacketTooBig || reply.Status == IPStatus.TimedOut) { HighMTUSize = CurrentMTUSize; retry = 1; } else if (reply.Status == IPStatus.Success) { LowMTUSize = CurrentMTUSize; replyResult = reply; retry = 1; } else { // If the host didn't reply, try again up to the 'Count' value. if (retry >= Count) { string message = StringUtil.Format( TestConnectionResources.NoPingResult, targetAddress, reply.Status.ToString()); Exception pingException = new PingException(message); ErrorRecord errorRecord = new ErrorRecord( pingException, TestConnectionExceptionId, ErrorCategory.ResourceUnavailable, targetAddress); WriteError(errorRecord); return; } else { retry++; continue; } } CurrentMTUSize = (LowMTUSize + HighMTUSize) / 2; // Prevent DoS attack. Thread.Sleep(100); } } catch (PingException ex) { string message = StringUtil.Format(TestConnectionResources.NoPingResult, targetAddress, ex.Message); Exception pingException = new PingException(message, ex.InnerException); ErrorRecord errorRecord = new ErrorRecord( pingException, TestConnectionExceptionId, ErrorCategory.ResourceUnavailable, targetAddress); WriteError(errorRecord); return; } if (Quiet.IsPresent) { WriteObject(CurrentMTUSize); } else { WriteObject(new PingMtuStatus( Source, resolvedTargetName, replyResult ?? throw new ArgumentNullException(nameof(replyResult)), CurrentMTUSize)); } }
private bool TryGetPingReply( SocketConfig socketConfig, byte[] receiveBuffer, int bytesReceived, Stopwatch sw, ref int ipHeaderLength, [NotNullWhen(true)] out PingReply?reply) { byte type, code; reply = null; if (socketConfig.IsIpv4) { // Determine actual size of IP header byte ihl = (byte)(receiveBuffer[0] & 0x0f); // Internet Header Length ipHeaderLength = 4 * ihl; if (bytesReceived - ipHeaderLength < IcmpHeaderLengthInBytes) { return(false); // Not enough bytes to reconstruct actual IP header + ICMP header. } } int icmpHeaderOffset = ipHeaderLength; int dataOffset = ipHeaderLength + IcmpHeaderLengthInBytes; // Skip IP header. IcmpHeader receivedHeader = MemoryMarshal.Read <IcmpHeader>(receiveBuffer.AsSpan(icmpHeaderOffset)); ushort identifier = 0; type = receivedHeader.Type; code = receivedHeader.Code; // Validate the ICMP header and get the identifier if (socketConfig.IsIpv4) { if (type == (byte)IcmpV4MessageType.EchoReply) { // Reply packet has the identifier in the ICMP header. identifier = receivedHeader.Identifier; } else if (type == (byte)IcmpV4MessageType.DestinationUnreachable || type == (byte)IcmpV4MessageType.TimeExceeded || type == (byte)IcmpV4MessageType.ParameterProblemBadIPHeader || type == (byte)IcmpV4MessageType.SourceQuench || type == (byte)IcmpV4MessageType.RedirectMessage) { // Original IP+ICMP request is in the payload. Read the ICMP header from // the payload to get identifier. if (dataOffset + MinIpHeaderLengthInBytes + IcmpHeaderLengthInBytes > bytesReceived) { return(false); } byte ihl = (byte)(receiveBuffer[dataOffset] & 0x0f); // Internet Header Length int payloadIpHeaderLength = 4 * ihl; if (bytesReceived - dataOffset - payloadIpHeaderLength < IcmpHeaderLengthInBytes) { return(false); // Not enough bytes to reconstruct actual IP header + ICMP header. } IcmpHeader originalRequestHeader = MemoryMarshal.Read <IcmpHeader>(receiveBuffer.AsSpan(dataOffset + payloadIpHeaderLength)); identifier = originalRequestHeader.Identifier; // Update the date offset to point past the payload IP+ICMP headers. While the specification // doesn't indicate there should be any additional data the reality is that we often get the // original packet data back. dataOffset += payloadIpHeaderLength + IcmpHeaderLengthInBytes; } else { return(false); } } else { if (type == (byte)IcmpV6MessageType.EchoReply) { // Reply packet has the identifier in the ICMP header. identifier = receivedHeader.Identifier; } else if (type == (byte)IcmpV6MessageType.DestinationUnreachable || type == (byte)IcmpV6MessageType.TimeExceeded || type == (byte)IcmpV6MessageType.ParameterProblem || type == (byte)IcmpV6MessageType.PacketTooBig) { // Original IP+ICMP request is in the payload. Read the ICMP header from // the payload to get identifier. if (bytesReceived - dataOffset < IpV6HeaderLengthInBytes + IcmpHeaderLengthInBytes) { return(false); // Not enough bytes to reconstruct actual IP header + ICMP header. } IcmpHeader originalRequestHeader = MemoryMarshal.Read <IcmpHeader>(receiveBuffer.AsSpan(dataOffset + IpV6HeaderLengthInBytes)); identifier = originalRequestHeader.Identifier; // Update the date offset to point past the payload IP+ICMP headers. While the specification // doesn't indicate there should be any additional data the reality is that we often get the // original packet data back. dataOffset += IpV6HeaderLengthInBytes + IcmpHeaderLengthInBytes; } else { return(false); } } if (socketConfig.Identifier != identifier) { return(false); } sw.Stop(); long roundTripTime = sw.ElapsedMilliseconds; // We want to return a buffer with the actual data we sent out, not including the header data. byte[] dataBuffer = new byte[bytesReceived - dataOffset]; Buffer.BlockCopy(receiveBuffer, dataOffset, dataBuffer, 0, dataBuffer.Length); IPStatus status = socketConfig.IsIpv4 ? IcmpV4MessageConstants.MapV4TypeToIPStatus(type, code) : IcmpV6MessageConstants.MapV6TypeToIPStatus(type, code); IPAddress address = ((IPEndPoint)socketConfig.EndPoint).Address; reply = new PingReply(address, socketConfig.Options, status, roundTripTime, dataBuffer); return(true); }