/// <summary> /// /// </summary> /// <param name="data"> /// /// </param> private void NewPacket(byte[] data) { // store the time the packet arrived m_stop = Environment.TickCount; // parse out the ip header IpV4Packet ipPacket = new IpV4Packet(data); // double check to make sure this is an icmp packet if (ipPacket.TransportProtocol != ProtocolType.Icmp) { return; } // parse out the icmp packet IcmpPacket icmpPacket = new IcmpPacket(ipPacket.Data); // if this is an echo reply if (icmpPacket.MessageType == IcmpMessageType.EchoReply) { // deserialize the packet IcmpEcho echo = new IcmpEcho(icmpPacket); // if this packet matches our identifier, and destination address if (echo.Identifier == m_id && ipPacket.SourceAddress.Equals(m_remoteAddress)) { // disable the timeout timer m_timer.Enabled = false; // raise the event if (PingReply != null) { PingReply(ipPacket, icmpPacket, (int)((uint)m_stop - (uint)m_start)); } // reset the id back to 0 so we can resume sending packets. m_id = 0; // signal the wait event m_waitObject.Set(); } } }
/// <summary> /// Log a new ICMP packet. /// </summary> /// <param name="packet"> /// The packet to log. /// </param> public void LogPacket(IcmpPacket packet) { lock (m_logger.XmlWriter) { // <IcmpHeader> m_logger.XmlWriter.WriteStartElement ("IcmpHeader"); m_logger.XmlWriter.WriteElementString ("Type", packet.MessageType.ToString()); m_logger.XmlWriter.WriteElementString ("Checksum", packet.Checksum.ToString()); #region Specific ICMP Types switch (packet.MessageType) { case IcmpMessageType.DestinationUnreachable: IcmpDestinationUnreachable option1 = new IcmpDestinationUnreachable (packet); m_logger.XmlWriter.WriteElementString ("Code", option1.Code.ToString()); break; case IcmpMessageType.Echo: IcmpEcho option2 = new IcmpEcho (packet); m_logger.XmlWriter.WriteElementString ("Identifier", option2.Identifier.ToString()); m_logger.XmlWriter.WriteElementString ("SequenceNumber", option2.SequenceNumber.ToString()); m_logger.XmlWriter.WriteElementString ("DataLength", (option2.Data != null ? option2.Data.Length : 0) + " bytes"); m_logger.XmlWriter.WriteElementString ("Data", (option2.Data != null ? System.Text.ASCIIEncoding.ASCII.GetString (option2.Data) : string.Empty)); break; case IcmpMessageType.EchoReply: IcmpEcho option3 = new IcmpEcho (packet); m_logger.XmlWriter.WriteElementString ("Identifier", option3.Identifier.ToString()); m_logger.XmlWriter.WriteElementString ("SequenceNumber", option3.SequenceNumber.ToString()); m_logger.XmlWriter.WriteElementString ("DataLength", (option3.Data != null ? option3.Data.Length : 0) + " bytes"); m_logger.XmlWriter.WriteElementString ("Data", (option3.Data != null ? System.Text.ASCIIEncoding.ASCII.GetString (option3.Data) : string.Empty)); break; case IcmpMessageType.ParameterProblem: IcmpParameterProblem option4 = new IcmpParameterProblem (packet); m_logger.XmlWriter.WriteElementString ("Pointer", option4.ErrorPointer.ToString()); break; case IcmpMessageType.Redirect: IcmpRedirect option5 = new IcmpRedirect (packet); m_logger.XmlWriter.WriteElementString ("Gateway", option5.GatewayAddress.ToString()); break; case IcmpMessageType.SourceQuench: break; case IcmpMessageType.TimeExceeded: break; case IcmpMessageType.TimeStamp: break; case IcmpMessageType.TimestampReply: break; } #endregion m_logger.XmlWriter.WriteEndElement (); // </IcmpHeader> } }
/// <summary> /// Send a new ping packet. /// </summary> /// <param name="destination"> /// The address to send the packet to. /// </param> /// <param name="payload"> /// The data to send in the ping. /// </param> /// <param name="async"> /// If this is true, SendPing will return immediately otherwise it will wait /// </param> /// <param name="timeOutTime"> /// The number of milliseconds before the reply times out. /// </param> /// <exception cref="ObjectDisposedException"> /// If the class has been disposed then an ObjectDisposedException will be thrown. /// </exception> /// <exception cref="Exception"> /// If the class is already waiting for a ping reply then an exception will be thrown. /// Use the CancelPing method first. /// </exception> public void SendPing(IPAddress destination, byte[] payload, bool async, double timeOutTime) { if (m_disposed) { throw new ObjectDisposedException(this.ToString(), "This object has already been disposed"); } // check if a ping is already in process if (m_id != 0) { throw new Exception("A ping request is already in process. Either wait for the reply, or cancel the request first"); } Random random = new Random(); IcmpEcho echo = new IcmpEcho(); // generate random identifier and sequence number echo.Identifier = (ushort)random.Next(ushort.MaxValue); echo.SequenceNumber = (ushort)random.Next(ushort.MaxValue); m_id = echo.Identifier; m_remoteAddress = destination; m_timer.Interval = timeOutTime; // store the payload echo.Data = payload; // build the icmp header IcmpPacket icmpHeader = echo.Serialize(false); // build the ip header IpV4Packet ipHeader = new IpV4Packet(); ipHeader.TransportProtocol = ProtocolType.Icmp; ipHeader.SourceAddress = m_networkInterface; ipHeader.DestinationAddress = destination; ipHeader.Data = icmpHeader.Serialize(); if (m_fragment) { IpV4Packet[] fragments = ipHeader.Fragment(8); // send each fragment for (int i = 0; i < fragments.Length; i++) { byte[] packet = fragments[i].Serialize(); m_socket.SendTo(packet, 0, packet.Length, SocketFlags.None, new IPEndPoint(fragments[i].DestinationAddress, 0)); } } else { // send the packet byte[] packet = ipHeader.Serialize(); m_socket.SendTo(packet, 0, packet.Length, SocketFlags.None, new IPEndPoint(ipHeader.DestinationAddress, 0)); } // save the time and start the timeout timer m_start = Environment.TickCount; m_timer.Enabled = true; // wait for the reply m_waitObject.Reset(); if (!async) { m_waitObject.WaitOne(); } }
/// <summary> /// /// </summary> /// <param name="data"> /// /// </param> private void NewPacket(byte[] data) { // store the time the packet arrived m_stop = Environment.TickCount; // parse out the ip header IpV4Packet ipPacket = new IpV4Packet (data); // double check to make sure this is an icmp packet if (ipPacket.TransportProtocol != ProtocolType.Icmp) { return; } // parse out the icmp packet IcmpPacket icmpPacket = new IcmpPacket (ipPacket.Data); // if this is an echo reply if (icmpPacket.MessageType == IcmpMessageType.EchoReply) { // deserialize the packet IcmpEcho echo = new IcmpEcho (icmpPacket); // if this packet matches our identifier, and destination address if (echo.Identifier == m_id && ipPacket.SourceAddress.Equals (m_remoteAddress)) { // disable the timeout timer m_timer.Enabled = false; // raise the event if (PingReply != null) { PingReply (ipPacket, icmpPacket, (int)((uint)m_stop - (uint)m_start)); } // reset the id back to 0 so we can resume sending packets. m_id = 0; // signal the wait event m_waitObject.Set (); } } }
/// <summary> /// Send a new ping packet. /// </summary> /// <param name="destination"> /// The address to send the packet to. /// </param> /// <param name="payload"> /// The data to send in the ping. /// </param> /// <param name="async"> /// If this is true, SendPing will return immediately otherwise it will wait /// </param> /// <param name="timeOutTime"> /// The number of milliseconds before the reply times out. /// </param> /// <exception cref="ObjectDisposedException"> /// If the class has been disposed then an ObjectDisposedException will be thrown. /// </exception> /// <exception cref="Exception"> /// If the class is already waiting for a ping reply then an exception will be thrown. /// Use the CancelPing method first. /// </exception> public void SendPing(IPAddress destination, byte[] payload, bool async, double timeOutTime) { if (m_disposed) { throw new ObjectDisposedException (this.ToString(), "This object has already been disposed"); } // check if a ping is already in process if (m_id != 0) { throw new Exception ("A ping request is already in process. Either wait for the reply, or cancel the request first"); } Random random = new Random (); IcmpEcho echo = new IcmpEcho (); // generate random identifier and sequence number echo.Identifier = (ushort)random.Next (ushort.MaxValue); echo.SequenceNumber = (ushort)random.Next (ushort.MaxValue); m_id = echo.Identifier; m_remoteAddress = destination; m_timer.Interval = timeOutTime; // store the payload echo.Data = payload; // build the icmp header IcmpPacket icmpHeader = echo.Serialize (false); // build the ip header IpV4Packet ipHeader = new IpV4Packet (); ipHeader.TransportProtocol = ProtocolType.Icmp; ipHeader.SourceAddress = m_networkInterface; ipHeader.DestinationAddress = destination; ipHeader.Data = icmpHeader.Serialize (); if (m_fragment) { IpV4Packet[] fragments = ipHeader.Fragment (8); // send each fragment for (int i = 0; i < fragments.Length; i++) { byte[] packet = fragments[i].Serialize (); m_socket.SendTo (packet, 0, packet.Length, SocketFlags.None, new IPEndPoint (fragments[i].DestinationAddress, 0)); } } else { // send the packet byte[] packet = ipHeader.Serialize (); m_socket.SendTo (packet, 0, packet.Length, SocketFlags.None, new IPEndPoint (ipHeader.DestinationAddress, 0)); } // save the time and start the timeout timer m_start = Environment.TickCount; m_timer.Enabled = true; // wait for the reply m_waitObject.Reset (); if (!async) { m_waitObject.WaitOne (); } }
/// <summary> /// Send the next request in order to find the next hop. /// </summary> private void SendRequest() { // generate a 32 byte payload string data = new string ('x', 32); byte[] payload = System.Text.ASCIIEncoding.ASCII.GetBytes (data); // fill in ip header fields IpV4Packet ipPacket = new IpV4Packet (); ipPacket.DestinationAddress = m_remoteAddress; ipPacket.SourceAddress = m_localAddress; ipPacket.TransportProtocol = ProtocolType.Icmp; ipPacket.TimeToLive = m_ttl; // save the identification m_ipId = ipPacket.Identification; // add routing options if any if (m_route != null) { ipPacket.Options = new IpV4Option[2]; ipPacket.Options[0] = m_route.Serialize (m_strictRouting ? IpV4OptionNumber.StrictSourceRouting : IpV4OptionNumber.LooseSourceRouting); ipPacket.Options[1] = new IpV4Option (); ipPacket.Options[1].OptionType = IpV4OptionNumber.EndOfOptions; ipPacket.Options[1].IsCopied = false; ipPacket.Options[1].Length = 1; ipPacket.Options[1].Class = IpV4OptionClass.Control; ipPacket.Options[1].Data = null; } // create a new echo packet IcmpEcho echo = new IcmpEcho (); echo.Identifier = m_id; echo.Data = payload; // serialize the icmp packet IcmpPacket icmpPacket = echo.Serialize (false); ipPacket.Data = icmpPacket.Serialize (); if (m_fragment) { IpV4Packet[] fragments = ipPacket.Fragment (8); // send each fragment for (int i = 0; i < fragments.Length; i++) { byte[] packet = fragments[i].Serialize (); m_socket.SendTo (packet, 0, packet.Length, SocketFlags.None, new IPEndPoint (fragments[i].DestinationAddress, 0)); } } else { // send the ip packet byte[] packet = ipPacket.Serialize (); m_socket.SendTo (packet, 0, packet.Length, SocketFlags.None, new IPEndPoint (ipPacket.DestinationAddress, 0)); } // grab the current time m_start = Environment.TickCount; // start the timeout timer m_timer.Enabled = true; }
/// <summary> /// This event occurs whenever a new packet arrives. /// </summary> /// <param name="data"> /// The data in the packet. /// </param> private void NewPacket(byte[] data) { if (!m_working) { return; } // store the time the packet arrived m_stop = Environment.TickCount; // parse out the ip header IpV4Packet ipPacket = new IpV4Packet (data); // double check to make sure this is an icmp packet if (ipPacket.TransportProtocol != ProtocolType.Icmp) { return; } // parse out the icmp packet IcmpPacket icmpPacket = new IcmpPacket (ipPacket.Data); // if this is an echo reply if (icmpPacket.MessageType == IcmpMessageType.EchoReply) { #region Reply From Destination // deserialize the packet IcmpEcho echo = new IcmpEcho (icmpPacket); // if this packet matches our identifier, and destination address if (echo.Identifier == m_id) { // disable the timeout timer m_timer.Enabled = false; // raise the event if (RouteUpdate != null) { RouteUpdate (ipPacket.SourceAddress, (int)((uint)m_stop - (uint)m_start), m_ttl); } // raise the event if (TraceFinished != null) { TraceFinished (); } // signal the wait event m_waitObject.Set (); // allow new trace routes m_working = false; } #endregion } // if the time to live exceeded then we have a new hop else if (icmpPacket.MessageType == IcmpMessageType.TimeExceeded) { #region Reply From Router IcmpTimeExceeded icmpTimeExceeded = new IcmpTimeExceeded (icmpPacket); // make sure this packet is for us if (m_ipId != icmpTimeExceeded.BadPacket.Identification) { return; } // disable the timeout timer m_timer.Enabled = false; // raise the event if (RouteUpdate != null && m_working) { RouteUpdate (ipPacket.SourceAddress, (int)((uint)m_stop - (uint)m_start), m_ttl); } // increment the time to live. m_ttl++; // if the max hop count is exceeded if (m_ttl > m_maxHops) { // disable the timeout timer m_timer.Enabled = false; // allow new trace routes m_working = false; // raise the event if (MaxHopsExceeded != null) { MaxHopsExceeded (); } // signal the wait event m_waitObject.Set (); } else { // send the next request SendRequest (); } #endregion } }
/// <summary> /// This event occurs whenever a new packet arrives. /// </summary> /// <param name="data"> /// The data in the packet. /// </param> private void NewPacket(byte[] data) { if (!m_working) { return; } // store the time the packet arrived m_stop = Environment.TickCount; // parse out the ip header IpV4Packet ipPacket = new IpV4Packet(data); // double check to make sure this is an icmp packet if (ipPacket.TransportProtocol != ProtocolType.Icmp) { return; } // parse out the icmp packet IcmpPacket icmpPacket = new IcmpPacket(ipPacket.Data); // if this is an echo reply if (icmpPacket.MessageType == IcmpMessageType.EchoReply) { #region Reply From Destination // deserialize the packet IcmpEcho echo = new IcmpEcho(icmpPacket); // if this packet matches our identifier, and destination address if (echo.Identifier == m_id) { // disable the timeout timer m_timer.Enabled = false; // raise the event if (RouteUpdate != null) { RouteUpdate(ipPacket.SourceAddress, (int)((uint)m_stop - (uint)m_start), m_ttl); } // raise the event if (TraceFinished != null) { TraceFinished(); } // signal the wait event m_waitObject.Set(); // allow new trace routes m_working = false; } #endregion } // if the time to live exceeded then we have a new hop else if (icmpPacket.MessageType == IcmpMessageType.TimeExceeded) { #region Reply From Router IcmpTimeExceeded icmpTimeExceeded = new IcmpTimeExceeded(icmpPacket); // make sure this packet is for us if (m_ipId != icmpTimeExceeded.BadPacket.Identification) { return; } // disable the timeout timer m_timer.Enabled = false; // raise the event if (RouteUpdate != null && m_working) { RouteUpdate(ipPacket.SourceAddress, (int)((uint)m_stop - (uint)m_start), m_ttl); } // increment the time to live. m_ttl++; // if the max hop count is exceeded if (m_ttl > m_maxHops) { // disable the timeout timer m_timer.Enabled = false; // allow new trace routes m_working = false; // raise the event if (MaxHopsExceeded != null) { MaxHopsExceeded(); } // signal the wait event m_waitObject.Set(); } else { // send the next request SendRequest(); } #endregion } }
/// <summary> /// Send the next request in order to find the next hop. /// </summary> private void SendRequest() { // generate a 32 byte payload string data = new string ('x', 32); byte[] payload = System.Text.ASCIIEncoding.ASCII.GetBytes(data); // fill in ip header fields IpV4Packet ipPacket = new IpV4Packet(); ipPacket.DestinationAddress = m_remoteAddress; ipPacket.SourceAddress = m_localAddress; ipPacket.TransportProtocol = ProtocolType.Icmp; ipPacket.TimeToLive = m_ttl; // save the identification m_ipId = ipPacket.Identification; // add routing options if any if (m_route != null) { ipPacket.Options = new IpV4Option[2]; ipPacket.Options[0] = m_route.Serialize(m_strictRouting ? IpV4OptionNumber.StrictSourceRouting : IpV4OptionNumber.LooseSourceRouting); ipPacket.Options[1] = new IpV4Option(); ipPacket.Options[1].OptionType = IpV4OptionNumber.EndOfOptions; ipPacket.Options[1].IsCopied = false; ipPacket.Options[1].Length = 1; ipPacket.Options[1].Class = IpV4OptionClass.Control; ipPacket.Options[1].Data = null; } // create a new echo packet IcmpEcho echo = new IcmpEcho(); echo.Identifier = m_id; echo.Data = payload; // serialize the icmp packet IcmpPacket icmpPacket = echo.Serialize(false); ipPacket.Data = icmpPacket.Serialize(); if (m_fragment) { IpV4Packet[] fragments = ipPacket.Fragment(8); // send each fragment for (int i = 0; i < fragments.Length; i++) { byte[] packet = fragments[i].Serialize(); m_socket.SendTo(packet, 0, packet.Length, SocketFlags.None, new IPEndPoint(fragments[i].DestinationAddress, 0)); } } else { // send the ip packet byte[] packet = ipPacket.Serialize(); m_socket.SendTo(packet, 0, packet.Length, SocketFlags.None, new IPEndPoint(ipPacket.DestinationAddress, 0)); } // grab the current time m_start = Environment.TickCount; // start the timeout timer m_timer.Enabled = true; }