/// <summary> /// Log a new IP packet. /// </summary> /// <param name="packet"> /// The packet to log. /// </param> public void LogPacket (IpV4Packet packet) { lock (m_logger.XmlWriter) { // <IpV4Header> m_logger.XmlWriter.WriteStartElement ("IpV4Header"); m_logger.XmlWriter.WriteElementString ("SourceAddress", packet.SourceAddress.ToString()); m_logger.XmlWriter.WriteElementString ("DestinationAddress",packet.DestinationAddress.ToString()); m_logger.XmlWriter.WriteElementString ("TransportProtocol", packet.TransportProtocol.ToString()); m_logger.XmlWriter.WriteElementString ("TimeToLive", packet.TimeToLive.ToString()); m_logger.XmlWriter.WriteElementString ("Identification", packet.Identification.ToString()); m_logger.XmlWriter.WriteElementString ("Checksum", packet.Checksum.ToString()); // <LengthFields> m_logger.XmlWriter.WriteStartElement ("IpLengthFields"); m_logger.XmlWriter.WriteElementString ("TotalLength", packet.TotalLength + " bytes"); m_logger.XmlWriter.WriteElementString ("HeaderLength", packet.HeaderLength + " bytes"); m_logger.XmlWriter.WriteElementString ("OptionsLength", (packet.TotalLength - (packet.Padding != null ? packet.Padding.Length : 0) - (packet.Data != null ? packet.Data.Length : 0) - 0x14) + " bytes"); m_logger.XmlWriter.WriteElementString ("PaddingLength", (packet.Padding != null ? packet.Padding.Length : 0) + " bytes"); m_logger.XmlWriter.WriteElementString ("DataLength", (packet.Data != null ? packet.Data.Length : 0) + " bytes"); m_logger.XmlWriter.WriteEndElement (); // </LengthFields> // <Fragmentation> m_logger.XmlWriter.WriteStartElement ("Fragmentation"); m_logger.XmlWriter.WriteElementString ("Fragments", packet.Fragments.ToString()); m_logger.XmlWriter.WriteElementString ("DontFragment", packet.ControlFlags.DontFragment.ToString()); m_logger.XmlWriter.WriteElementString ("MoreFragments", packet.ControlFlags.MoreFragments.ToString()); m_logger.XmlWriter.WriteElementString ("Offset", packet.ControlFlags.Offset.ToString()); m_logger.XmlWriter.WriteEndElement (); // </Fragmentation> // <TypeOfService> m_logger.XmlWriter.WriteStartElement ("TypeOfService"); m_logger.XmlWriter.WriteElementString ("Precedence", packet.TypeOfService.Precedence.ToString()); m_logger.XmlWriter.WriteElementString ("Delay", packet.TypeOfService.Delay.ToString()); m_logger.XmlWriter.WriteElementString ("Reliability", packet.TypeOfService.Reliability.ToString()); m_logger.XmlWriter.WriteElementString ("Throughput", packet.TypeOfService.Throughput.ToString()); m_logger.XmlWriter.WriteEndElement (); // </TypeOfService> if (packet.Options != null) { // <Options> m_logger.XmlWriter.WriteStartElement ("IpOptions"); foreach (IpV4Option option in packet.Options) { // <Option> m_logger.XmlWriter.WriteStartElement ("Option"); m_logger.XmlWriter.WriteElementString ("Class", option.Class.ToString()); m_logger.XmlWriter.WriteElementString ("Type", option.OptionType.ToString()); m_logger.XmlWriter.WriteElementString ("Length",option.Length + " bytes"); m_logger.XmlWriter.WriteElementString ("Copied",option.IsCopied.ToString()); #region Specific Options switch (option.OptionType) { case IpV4OptionNumber.EndOfOptions: break; case IpV4OptionNumber.InternetTimestamp: IpV4TimeStampOption option1 = new IpV4TimeStampOption (option); m_logger.XmlWriter.WriteElementString ("TimestampType", option1.OptionType.ToString()); m_logger.XmlWriter.WriteElementString ("Overflow", option1.Overflow.ToString()); m_logger.XmlWriter.WriteElementString ("Pointer", option1.Pointer.ToString()); break; case IpV4OptionNumber.LooseSourceRouting: IpV4RoutingOption option2 = new IpV4RoutingOption (option); m_logger.XmlWriter.WriteElementString ("Pointer", option2.Pointer.ToString()); break; case IpV4OptionNumber.NoOperation: break; case IpV4OptionNumber.RecordRoute: IpV4RoutingOption option3 = new IpV4RoutingOption (option); m_logger.XmlWriter.WriteElementString ("Pointer", option3.Pointer.ToString()); break; case IpV4OptionNumber.Security: IpV4SecurityOption option4 = new IpV4SecurityOption (option); m_logger.XmlWriter.WriteElementString ("SecurityLevel", option4.SecurityLevel.ToString()); m_logger.XmlWriter.WriteElementString ("Compartment", option4.Compartment.ToString()); m_logger.XmlWriter.WriteElementString ("HandlingRestrictions", option4.HandlingRestrictions.ToString()); m_logger.XmlWriter.WriteElementString ("TransmissionControlCode", option4.TransmissionControlCode.ToString()); break; case IpV4OptionNumber.StreamId: IpV4StreamIdentifierOption option5 = new IpV4StreamIdentifierOption (option); m_logger.XmlWriter.WriteElementString ("StreamIdentifier", option5.StreamIdentifier.ToString()); break; case IpV4OptionNumber.StrictSourceRouting: IpV4RoutingOption option6 = new IpV4RoutingOption (option); m_logger.XmlWriter.WriteElementString ("Pointer", option6.Pointer.ToString()); break; } #endregion m_logger.XmlWriter.WriteEndElement (); // </Option> } m_logger.XmlWriter.WriteEndElement (); // </Options> } m_logger.XmlWriter.WriteEndElement (); // </IpV4Header> } }
/// <summary> /// Create a new generic error ICMP packet. /// </summary> /// <param name="packet"> /// The ICMP packet to parse. /// </param> /// <exception cref="ArgumentNullException"> /// If the packet is null then an argument null exception occurs. /// </exception> public void Constructor(IcmpPacket packet) { if (packet == null) { throw new ArgumentNullException ("packet"); } // discard the unused field byte[] tempBuffer = new byte[packet.Data.Length - 4]; Array.Copy (packet.Data, 4, tempBuffer, 0, tempBuffer.Length); // parse out the packet data m_badPacket = new IpV4Packet (tempBuffer); }
/// <summary> /// Whenever a new IP packet arrives it should be passed to this method. /// If the packet is to be filtered out it will be ignored otherwise the /// IpV4PacketArrived will be raised with the packet /// </summary> /// <param name="packet"> /// The packet which has arrived. /// </param> public void HandleNewPacket(IpV4Packet packet) { bool match = true; // check the source address filter foreach (string filter in m_sourceAddressFilter) { if (!IpV4Filter.IsMatch (packet.SourceAddress.ToString(), filter)) { match = false; break; } } // if no match then exit if (!match) { return; } // check the destination address filter foreach (string filter in m_destAddressFilter) { if (!IpV4Filter.IsMatch (packet.DestinationAddress.ToString(), filter)) { match = false; break; } } // if no match then exit if (!match) { return; } // if we get here then the packet has passed through the filter and we // raise the event if (IpV4PacketArrived != null) { IpV4PacketArrived (packet); } }
/// <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> /// Whenever a new IP packet arrives it should be passed to this method. /// If the packet is fragmented it will be buffered until all of the other /// fragments have arrived, then it will be pieced back together into a whole /// packet. /// </summary> /// <param name="packet"> /// The packet which has arrived. /// </param> public void HandleNewPacket(IpV4Packet packet) { #region Check for Packets we don't need to parse // first thing we do is check if this packet is whole or not if (packet.ControlFlags.Offset == 0 && !packet.ControlFlags.MoreFragments) { // it's whole so our job is done already. Just forward it on. if (IpV4PacketArrived != null) IpV4PacketArrived (packet); return; } #endregion // at this point we know the packet is a fragment. Now what we want to do // is check through the array list to see if it belongs to any other fragments. // If so, we store the index in the array list of the other packets for further // processing. If not, we add it to a new item in the array list and store the new // index for further processing. #region Get Packet Index int index = -1; for (int i = 0; i < m_packets.Count; i++) { IpV4Packet p = (IpV4Packet)((IpFragmentsType)m_packets[i]).Fragments[0]; // we check if fragments belong by comparing their identification field, the // source and destination address, and the transport protocol if (p.Identification == packet.Identification && p.TransportProtocol == packet.TransportProtocol && p.SourceAddress == packet.SourceAddress && p.DestinationAddress == packet.DestinationAddress) { index = i; break; } } // if the index is still -1 then this is a new fragment if (index == -1) { // create and add a new fragments entry to the packets array IpFragmentsType newFragment = new IpFragmentsType(); index = m_packets.Add (newFragment); } #endregion // now we now need to add the new fragment to the packet array. #region Add Fragment IpFragmentsType currentPacket = (IpFragmentsType)m_packets[index]; currentPacket.Fragments.Add (packet); #endregion // now we check if this packet has the More Fragments bit not set. // This indicates that it is the last fragment. // HOWEVER, since ip packets may arrive out of order, this does not mean we have all // the fragments yet. But since it is the last packet, it does let us know how much // data we are waiting on so we can identify when we have all the fragments. // so calculate how much data we are waiting on and check if we have recieved it all. #region Calculate Total Packet Size and Check For Completion // calculate data currently recieved currentPacket.CurrentDataSize += packet.TotalLength - packet.HeaderLength; if (!packet.ControlFlags.MoreFragments) { // the total length of all the data is caculated by adding the offset on to the data // length of this packet, since it's the last one. currentPacket.TotalDataSize = packet.ControlFlags.Offset + packet.TotalLength - packet.HeaderLength; } // if we have recieved all the data then bingo, we have all the fragments // so reassemble them into a complete packet and remove these uneeded fragments if (currentPacket.CurrentDataSize == currentPacket.TotalDataSize) { IpV4Packet[] fragments = new IpV4Packet[currentPacket.Fragments.Count]; for (int i = 0; i < fragments.Length; i++) { fragments[i] = (IpV4Packet)currentPacket.Fragments[i]; } IpV4Packet WholePacket = new IpV4Packet (fragments); if (IpV4PacketArrived != null) IpV4PacketArrived (WholePacket); m_packets.RemoveAt (index); } #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; }
/// <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> /// 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> /// The fragment method will turn this IP packet into several using fragmentation. /// </summary> /// <param name="maximumTransmissionUnit"> /// The maximum size of the data in each fragment. The maximum transmission unit must /// be a multiple of 8. For example 8, 16, 24, 32 etc. /// </param> /// <returns> /// This method returns an array of fragmented IP packets which can be sent over the /// network. /// </returns> /// <exception cref="ArgumentException"> /// The MTU (maximum Transmission Unit) must be a multiple of 8 bytes /// </exception> public IpV4Packet[] Fragment (int maximumTransmissionUnit) { if (maximumTransmissionUnit % 8 != 0 && maximumTransmissionUnit > 0) { throw new ArgumentException ("The MTU (maximum Transmission Unit) must be a multiple of 8 bytes", "maximumTransmissionUnit"); } // calculate how many fragments of the maximum transmission unit size we need int fragmentCount = m_data.Length / maximumTransmissionUnit; // and if the data doesn't exactly divide up into the maximum transmission unit // size then add a new fragment for the bit on the end if (m_data.Length % maximumTransmissionUnit != 0) { fragmentCount++; } // allocate space for the fragments IpV4Packet[] fragments = new IpV4Packet[fragmentCount]; // build each fragment for (int i = 0; i < fragments.Length; i++) { fragments[i] = new IpV4Packet (); fragments[i].SourceAddress = m_sourceAddress; fragments[i].DestinationAddress = m_destAddress; fragments[i].Identification = m_id; fragments[i].HeaderLength = 0x14; fragments[i].TimeToLive = m_ttl; fragments[i].TransportProtocol = m_protocol; fragments[i].TypeOfService = m_tos; fragments[i].Version = 0x04; #region Add Options // if there are options... if (m_options != null) { int optionsLength = 0; // if this is the first fragment, simply copy in all the options. if (i == 0) { fragments[i].Options = new IpV4Option[m_options.Length]; m_options.CopyTo (fragments[i].Options, 0); // calculate the size in bytes of the options field for (int j = 0; j < m_options.Length; j++) { optionsLength += m_options[j].Length; } } // if not, copy in the ones which have the copy flag set else { for (int j = 0; j < m_options.Length; j++) { if (m_options[j].IsCopied) { if (fragments[i].Options == null) { fragments[i].Options = new IpV4Option[1]; } else { // add this new option to the array IpV4Option[] tempOptions = new IpV4Option[fragments[i].Options.Length]; Array.Copy (fragments[i].Options, 0, tempOptions, 0, fragments[i].Options.Length); fragments[i].Options = new IpV4Option[fragments[i].Options.Length + 1]; Array.Copy (tempOptions, 0, fragments[i].Options, 0, tempOptions.Length); } fragments[i].Options[fragments[i].Options.Length - 1] = m_options[j]; // calculate the new size of the options optionsLength += m_options[j].Length; } } } fragments[i].HeaderLength += (ushort)optionsLength; // if we need padding to end the header on a 32 bit boundary if (optionsLength % 4 != 0) { // then add padding! fragments[i].Padding = new byte[4 - (optionsLength % 4)]; fragments[i].HeaderLength += (ushort)(4 - (optionsLength % 4)); } } #endregion // calculate the offset fragments[i].ControlFlags.Offset = (ushort)(i * maximumTransmissionUnit); // set up the control flags fragments[i].ControlFlags.MoreFragments = (i < fragments.Length - 1); fragments[i].ControlFlags.DontFragment = false; // copy the data into the buffer at the correct offset if ((i < fragments.Length - 1) || m_data.Length % maximumTransmissionUnit == 0) { fragments[i].Data = new byte[maximumTransmissionUnit]; Array.Copy (m_data, fragments[i].ControlFlags.Offset, fragments[i].Data, 0, maximumTransmissionUnit); } else { fragments[i].Data = new byte[m_data.Length % maximumTransmissionUnit]; Array.Copy (m_data, fragments[i].ControlFlags.Offset, fragments[i].Data, 0, m_data.Length % maximumTransmissionUnit); } // and finally the total size fragments[i].TotalLength = (ushort)(fragments[i].HeaderLength + fragments[i].Data.Length); } return fragments; }
/// <summary> /// Create a new IPv4 packet. /// </summary> /// <param name="packetFragments"> /// The fragments from a fragmented packet which will be peiced together /// into a whole single packet. /// </param> public IpV4Packet (IpV4Packet[] packetFragments) { int index = 0; // get the index of the first packet fragment for (int i = 0; i < packetFragments.Length; i++) { if (packetFragments[i].ControlFlags.Offset == 0) { index = i; break; } } // copy fields over from the first packet m_version = 0x04; m_destAddress = packetFragments[index].DestinationAddress; m_headerLength = packetFragments[index].HeaderLength; m_id = packetFragments[index].Identification; m_protocol = packetFragments[index].TransportProtocol; m_sourceAddress = packetFragments[index].SourceAddress; m_ttl = packetFragments[index].TimeToLive; m_tos.Precedence = packetFragments[index].TypeOfService.Precedence; m_tos.Delay = packetFragments[index].TypeOfService.Delay; m_tos.Throughput = packetFragments[index].TypeOfService.Throughput; m_tos.Reliability = packetFragments[index].TypeOfService.Reliability; m_icf.DontFragment = false; m_icf.MoreFragments = false; m_icf.Offset = 0; m_fragments = (byte)packetFragments.Length; if (packetFragments[index].Options != null) { m_options = new IpV4Option [packetFragments[index].Options.Length]; packetFragments[index].Options.CopyTo (m_options, 0); } if (packetFragments[index].Padding != null) { m_padding = new byte [packetFragments[index].Padding.Length]; packetFragments[index].Padding.CopyTo (m_padding, 0); } // calculate the total size of the packet. We need to do this first so we have // enough space in the buffer for all the fragments because there is no guarantee // of the order, so we can't just resize it dynamically each time we process a // new fragment. It could go anywhere in the buffer. m_totalLength = m_headerLength; for (int i = 0; i < packetFragments.Length; i++) { m_totalLength += (ushort) packetFragments[i].Data.Length; } // ok now allocate enough space m_data = new byte[m_totalLength - m_headerLength]; // now loop through each fragment, and copy it's data into the buffer for (int i = 0; i < packetFragments.Length; i++) { Array.Copy (packetFragments[i].Data, 0, m_data, packetFragments[i].ControlFlags.Offset, packetFragments[i].Data.Length); } }
/// <summary> /// Send a SYN request to the next port to check it's state. /// </summary> private void SendRequest() { m_remoteEndPoint.Port = m_ports [m_portIndex]; // increment the local port. if (m_incPorts) { if (m_localEndPoint.Port == ushort.MaxValue) { m_localEndPoint.Port = 1024; } m_localEndPoint.Port++; } IpV4Packet ipHeader = new IpV4Packet (); // fill in the minimal IP fields ipHeader.DestinationAddress = m_remoteEndPoint.Address; ipHeader.SourceAddress = m_localEndPoint.Address; TcpPacket tcpHeader = new TcpPacket (); // fill in the minimal tcp fields tcpHeader.DestinationPort = (ushort)m_remoteEndPoint.Port; tcpHeader.SourcePort = (ushort)m_localEndPoint.Port; tcpHeader.SetFlag (TcpFlags.Synchronize, true); // send the request ipHeader.Data = tcpHeader.Serialize (m_localEndPoint.Address ,m_remoteEndPoint.Address); // send each fragment if (m_fragment) { IpV4Packet[] fragments = ipHeader.Fragment (8); 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)); } } // send the packet else { byte[] packet = ipHeader.Serialize (); m_socket.SendTo (packet, 0, packet.Length, SocketFlags.None, new IPEndPoint (ipHeader.DestinationAddress, 0)); } // start the time out timer m_timeoutTimer.Enabled = true; }
/// <summary> /// A new packet has arrived. /// </summary> /// <param name="data"> /// The packet. /// </param> private void NewPacket(byte[] data) { if (!m_working) { return; } IpV4Packet ipHeader = new IpV4Packet (data); // check to see if this packet doesn't belong to us if ((!ipHeader.SourceAddress.Equals(m_remoteEndPoint.Address)) || (!ipHeader.DestinationAddress.Equals(m_localEndPoint.Address))) { return; } TcpPacket tcpHeader = new TcpPacket (ipHeader.Data); // check to see if this packet doesn't belong to us if (tcpHeader.SourcePort != (ushort)m_remoteEndPoint.Port || tcpHeader.DestinationPort != (ushort)m_localEndPoint.Port) { return; } // disable the timeout timer m_timeoutTimer.Enabled = false; // if this is a reset packet if (tcpHeader.IsFlagSet (TcpFlags.Reset)) { // then the port is closed if (PortReply != null) { PortReply (m_remoteEndPoint, TcpPortState.Closed); } } // if it's a syn ack packet else if (tcpHeader.IsFlagSet (TcpFlags.Synchronize) && tcpHeader.IsFlagSet (TcpFlags.Acknowledgment)) { // then the port is opened if (PortReply != null) { PortReply (m_remoteEndPoint, TcpPortState.Opened); } // at this point the OS will send back a reset packet to close the connection } // increment the port m_portIndex++; // check to see if the port scan is complete if (m_portIndex == m_ports.Length) { if (ScanComplete != null) { ScanComplete (); } m_sendTimer = null; m_working = false; m_waitObject.Set (); return; } // check the next port if (m_sendTimer == null) { SendRequest (); } else { m_sendTimer.Enabled = true; } }