/// <summary> /// Processes a received packet for a UDP request using the identification field. /// </summary> /// <param name="ip">The IP packet.</param> /// <param name="length">The data length.</param> /// <param name="result">The result.</param> private void ProcessPacketUdpIdentification(ProtoPacketIp ip, int length, MultipathTracerouteResult result) { ProtoPacketIcmp icmp; // If the packet payload is ICMP. if ((icmp = ip.Payload as ProtoPacketIcmp) != null) { if (icmp.Type == (byte)ProtoPacketIcmp.IcmpType.TimeExceeded) { // If the packet type is ICMP time exceeded. ProtoPacketIcmpTimeExceeded icmpTimeExceeded = icmp as ProtoPacketIcmpTimeExceeded; // Use the last bytes of the UDP ports to find the flow. ushort flowId = (ushort)((icmpTimeExceeded.IpPayload[1] << 8) | icmpTimeExceeded.IpPayload[3]); byte flow; if (result.TryGetUdpFlow(flowId, out flow)) { // Get the time-to-live. byte ttl = (byte)(icmpTimeExceeded.IpHeader.Identification >> 8); // Get the attempt. byte attempt = (byte)(icmpTimeExceeded.IpHeader.Identification & 0xF); // Add the result. result.UdpDataResponseReceived(flow, ttl, attempt, MultipathTracerouteData.ResponseType.TimeExceeded, DateTime.Now, ip); // Remove the corresponding request. result.RemoveRequest(MultipathTracerouteResult.RequestType.Udp, flow, ttl, attempt); } } else if (icmp.Type == (byte)ProtoPacketIcmp.IcmpType.DestinationUnreachable) { // If the packet type is ICMP destination unreachable. ProtoPacketIcmpDestinationUnreachable icmpDestinationUnreachable = icmp as ProtoPacketIcmpDestinationUnreachable; // Check the message is a port unreachable. if (icmpDestinationUnreachable.Code == (byte)ProtoPacketIcmpDestinationUnreachable.DestinationUnreachableCode.PortUnreachable) { // Use the last bytes of the UDP ports to find the flow. ushort flowId = (ushort)((icmpDestinationUnreachable.IpPayload[1] << 8) | icmpDestinationUnreachable.IpPayload[3]); byte flow; if (result.TryGetUdpFlow(flowId, out flow)) { // Get the time-to-live. byte ttl = (byte)(icmpDestinationUnreachable.IpHeader.Identification >> 8); // Get the attempt. byte attempt = (byte)(icmpDestinationUnreachable.IpHeader.Identification & 0xF); // Add the result. result.UdpDataResponseReceived(flow, ttl, attempt, MultipathTracerouteData.ResponseType.DestinationUnreachable, DateTime.Now, ip); // Remove the corresponding request. result.RemoveRequest(MultipathTracerouteResult.RequestType.Udp, flow, ttl, attempt); } } } } }
///// <summary> ///// Processes a received packet. ///// </summary> ///// <param name="buffer">The data buffer.</param> ///// <param name="length">The data length.</param> ///// <param name="result">The result.</param> //private void ProcessPacket(byte[] buffer, int length, MultipathTracerouteResult result) //{ // // Set the buffer index. // int index = 0; // // The packets. // ProtoPacketIp ip; // // Try and parse the packet using the specified filter. // if (ProtoPacketIp.ParseFilter(buffer, ref index, length, result.PacketFilters, out ip)) // { // // Call the callback methods. // result.Callback(MultipathTracerouteState.StateType.PacketCapture, ip); // // Process the packet for the current protocol. // lock (this.syncProcess) // { // if (null != this.processPacket) this.processPacket(ip, length, result); // } // } //} /// <summary> /// Processes a received packet for an ICMP request. /// </summary> /// <param name="ip">The IP packet.</param> /// <param name="length">The data length.</param> /// <param name="result">The result.</param> private void ProcessPacketIcmp(ProtoPacketIp ip, int length, MultipathTracerouteResult result) { ProtoPacketIcmp icmp; // If the packet payload is ICMP. if ((icmp = ip.Payload as ProtoPacketIcmp) != null) { if (icmp.Type == (byte)ProtoPacketIcmp.IcmpType.EchoReply) { // If the packet type is ICMP echo reply. ProtoPacketIcmpEchoReply icmpEchoReply = icmp as ProtoPacketIcmpEchoReply; // Use the reply identifier to find the flow. byte flow; if (result.TryGetIcmpFlow(icmpEchoReply.Identifier, out flow)) { // Get the time-to-live. byte ttl = (byte)(icmpEchoReply.Sequence >> 8); // Get the attempt. byte attempt = (byte)(icmpEchoReply.Sequence & 0xFF); // Add the result. result.IcmpDataResponseReceived(flow, ttl, attempt, MultipathTracerouteData.ResponseType.EchoReply, DateTime.Now, ip); // Remove the corresponding request. result.RemoveRequest(MultipathTracerouteResult.RequestType.Icmp, flow, ttl, attempt); } } else if (icmp.Type == (byte)ProtoPacketIcmp.IcmpType.TimeExceeded) { // If the packet type is ICMP time exceeded. ProtoPacketIcmpTimeExceeded icmpTimeExceeded = icmp as ProtoPacketIcmpTimeExceeded; // Use the ICMP request identifier to find the flow. ushort flowId = (ushort)((icmpTimeExceeded.IpPayload[4] << 8) | icmpTimeExceeded.IpPayload[5]); byte flow; if (result.TryGetIcmpFlow(flowId, out flow)) { // Get the time-to-live. byte ttl = icmpTimeExceeded.IpPayload[6]; // Get the attempt. byte attempt = icmpTimeExceeded.IpPayload[7]; // Add the result. result.IcmpDataResponseReceived(flow, ttl, attempt, MultipathTracerouteData.ResponseType.TimeExceeded, DateTime.Now, ip); // Remove the corresponding request. result.RemoveRequest(MultipathTracerouteResult.RequestType.Icmp, flow, ttl, attempt); } } } }