public void Process_PacketBatch_TwoPacket() { var randomIPNonTcpPacket = IPPacket.RandomPacket(IPVersion.IPv4); var randomIPPacket = IPPacket.RandomPacket(IPVersion.IPv4); var randomTCPPacket = TcpPacket.RandomPacket(); randomIPPacket.PayloadPacket = randomTCPPacket; //Arrange var posixTimeval = new PosixTimeval(); var rawTCPCapture = new RawCapture(LinkLayers.Raw, posixTimeval, randomIPPacket.Bytes); var rawNonTCPCapture = new RawCapture(LinkLayers.Raw, posixTimeval, randomIPNonTcpPacket.Bytes); var rawPacketBatchRequest = new RawPacketBatchRequest( new[] { new RawPacket(rawTCPCapture), new RawPacket(rawNonTCPCapture), new RawPacket(rawTCPCapture) }, 1); //Act this._rawPacketBatchParserActorRefSUT.Tell(rawPacketBatchRequest); //Assert this._captureActorTestProbe.ExpectMsg <Frame>(frame => frame.TimestampTicks == posixTimeval.Date.Ticks); this._captureActorTestProbe.ExpectMsg <Frame>(frame => frame.TimestampTicks == posixTimeval.Date.Ticks); this._captureActorTestProbe.ExpectNoMsg(); }
/// <summary> /// Constructor for a statistics mode event /// </summary> internal StatisticsEventArgs(StatisticsDevice device, PosixTimeval timeval, long packets, long bytes) { Device = device; Timeval = timeval; ReceivedPackets = packets; ReceivedBytes = bytes; }
/// <summary> /// constructor /// </summary> /// <param name="deviceToCaptureInfo"></param> /// <param name="filter"></param> /// <param name="deviceMode"></param> /// <param name="reportMethods"></param> /// <param name="heartBeatDelay"></param> public BaseSensor(CaptureDeviceDescription deviceToCaptureInfo, string filter, DeviceMode deviceMode, List <ISensorReport> reportMethods, int heartBeatDelay, Enumerations.SensorMode sensorMode) { _sensorId = Guid.NewGuid(); _lastTimeval = new PosixTimeval(0, 0); _reportMethods = reportMethods; _currentCaptureDevice = GetDeviceToCapture(deviceToCaptureInfo); _currentCaptureDevice.Open(deviceMode); if (!string.IsNullOrEmpty(filter)) { _currentCaptureDevice.Filter = filter; } //attach listeners switch (sensorMode) { case Enumerations.SensorMode.PacketCapture: //_currentCaptureDevice.OnPacketArrival += new PacketArrivalEventHandler(_currentCaptureDevice_OnPacketArrival); _currentCaptureDevice.OnPacketArrival += new PacketArrivalEventHandler(device_OnPacketArrival); break; case Enumerations.SensorMode.Statistics: var device = _currentCaptureDevice as WinPcapDevice; device.Mode = CaptureMode.Statistics; device.OnPcapStatistics += device_OnPcapStatistics; break; } //start heartbeat timer StartHeartbeat(heartBeatDelay, reportMethods); }
public void DateTimeConversion() { var now = DateTime.Now; var pX = new PosixTimeval(now); Assert.AreEqual(pX.Date.Ticks, now.ToUniversalTime().Ticks, TimeSpan.TicksPerMillisecond * 1.0); }
private void OnPacketReceive(Packet packet, PosixTimeval timeVal) { if (packet.Is <IPPacket>(out var ipPacket)) { HandleIpPacket(ipPacket, timeVal); } }
/// <summary> /// A wrapper class for libpcap's pcap_pkthdr structure /// </summary> private unsafe PcapHeader(IntPtr pcap_pkthdr, TimestampResolution resolution) { ulong tv_sec; ulong tv_usec; if (is32BitTs) { var ts = *(timeval_windows *)pcap_pkthdr; tv_sec = (ulong)ts.tv_sec; tv_usec = (ulong)ts.tv_usec; } else if (isMacOSX) { var ts = *(timeval_macosx *)pcap_pkthdr; tv_sec = (ulong)ts.tv_sec; tv_usec = (ulong)ts.tv_usec; } else { var ts = *(timeval_unix *)pcap_pkthdr; tv_sec = (ulong)ts.tv_sec; tv_usec = (ulong)ts.tv_usec; } Timeval = new PosixTimeval(tv_sec, tv_usec, resolution); CaptureLength = (uint)Marshal.ReadInt32(pcap_pkthdr + CaptureLengthOffset); PacketLength = (uint)Marshal.ReadInt32(pcap_pkthdr + PacketLengthOffset); }
/// <summary> /// Pass a packet to an existing connection if one is present /// or /// Create a new connection, notify the OnConnectionFound delegate and /// pass the packet to this new connection /// </summary> /// <param name="timeval"> /// A <see cref="PosixTimeval"/> /// </param> /// <param name="tcp"> /// A <see cref="TcpPacket"/> /// </param> public void ProcessPacket(PosixTimeval timeval, TcpPacket tcp) { TcpFlow foundFlow = null; TcpConnection foundConnection = null; // attempt to find the connection and flow that // this packet belongs to foreach (var c in Connections) { foundFlow = c.IsMatch(tcp); if (foundFlow != null) { foundConnection = c; break; } } TcpConnection connectionToUse; TcpFlow flowToUse; if (foundConnection == null) { log.Debug("foundConnection == null"); if (tcp.Reset) { log.Debug("creating new connection, RST flag is set"); } else { log.Debug("creating new connection, RST flag is not set"); } // create a new connection connectionToUse = new TcpConnection(tcp); connectionToUse.OnConnectionClosed += HandleConnectionToUseOnConnectionClosed; connectionToUse.Timeout = ConnectionTimeout; // figure out which flow matches this tcp packet flowToUse = connectionToUse.FindFlow(tcp); // send notification that a new connection was found OnConnectionFound(connectionToUse); Connections.Add(connectionToUse); } else { // use the flows that we found connectionToUse = foundConnection; flowToUse = foundFlow; } // pass the packet to the appropriate connection connectionToUse.HandlePacket(timeval, tcp, flowToUse); // pass the packet to the appropriate flow flowToUse.HandlePacket(timeval, tcp, connectionToUse); }
/// <summary> /// Handle closing connections by removing them from the list /// </summary> /// <param name="timeval"> /// A <see cref="PosixTimeval"/> /// </param> /// <param name="connection"> /// A <see cref="TcpConnection"/> /// </param> /// <param name="tcp"> /// A <see cref="TcpPacket"/> /// </param> /// <param name="closeType"> /// A <see cref="TcpConnection.CloseType"/> /// </param> void HandleConnectionToUseOnConnectionClosed(PosixTimeval timeval, TcpConnection connection, TcpPacket tcp, TcpConnection.CloseType closeType) { // remove the connection from the list Connections.Remove(connection); }
private void Write(BinaryWriter binaryWriter, PosixTimeval posix, byte[] data) { binaryWriter.Write(Convert.ToUInt32(posix.Seconds)); binaryWriter.Write(Convert.ToUInt32(posix.MicroSeconds)); binaryWriter.Write(Convert.ToUInt32(data.Length)); binaryWriter.Write(Convert.ToUInt32(data.Length)); binaryWriter.Write(data); }
// Offset is the offset into the stream where this packet starts public PacketInfo(TimedPacket timedPacket, long offset) { Ack = timedPacket.Packet.AcknowledgmentNumber; Seq = timedPacket.Packet.SequenceNumber; Length = timedPacket.Packet.PayloadData.Length; Offset = offset; Time = timedPacket.Time; }
void device_OnPcapStatistics(object sender, StatisticsModeEventArgs e) { foreach (ISensorReport reportMethod in _reportMethods) { reportMethod.ReportStatistics(e.Statistics, _lastTimeval, _sensorId.ToString()); } _lastTimeval = e.Statistics.Timeval; }
internal void HandlePacket(PosixTimeval timeval, TcpPacket tcp, TcpConnection connection) { OnPacketReceived?.Invoke(timeval, tcp, connection, this); // look for disconnection if (tcp.Finished == true) { IsOpen = false; OnFlowClosed?.Invoke(timeval, tcp, connection, this); } }
public PacketRecord(WinDivertAddress addr, ReadOnlyMemory <byte> data) { var timestamp = new PosixTimeval(BootTime + TimeSpan.FromTicks(addr.Timestamp)); Header = new WinDivertHeader(timestamp) { InterfaceIndex = addr.IfIdx, SubInterfaceIndex = addr.SubIfIdx, Flags = addr.Flags }; ; Data = data; }
static void HandleOnPacketReceived(PosixTimeval timeval, PacketDotNet.TcpPacket tcp, TcpConnection connection, TcpFlow flow) { lock (DictionaryLock) { if (!TcpPackets.ContainsKey(flow)) { TcpPackets[flow] = new List <Entry>(); } var entry = new Entry(timeval, tcp); TcpPackets[flow].Add(entry); } }
private void HandleIpPacket(IPPacket ipPacket, PosixTimeval timeVal) { if (ipPacket.Is <TcpPacket>(out var tcpPacket)) { HandleTcpPacket(tcpPacket, ipPacket, timeVal); } // TODO: UDP is not yet supported if (ipPacket.Is <UdpPacket>(out var udpPacket)) { // HandleUdpPacket(udpPacket, ipPacket, timeVal); } }
public void ReassemblePacket(long srcIP, long dstIP, TcpPacket tcpPacket, PosixTimeval timeVal) { try { ushort sourcePort = 0; ushort destinationPort = 0; //if (proto == IPProtocolType.TCP) { PacketWritten = false; sourcePort = tcpPacket.SourcePort; destinationPort = tcpPacket.DestinationPort; // If the payload length is zero bail out ulong length = (ulong)(tcpPacket.PayloadData.Length); if (length == 0) { //Console.WriteLine("Invalid length (TCP): " + ip.Source.ToString() + "#" + ip.Destination.ToString()); //return; } if (tcpPacket.Fin == true) { this.HasFin = true; } ReassembleTcp((ulong)tcpPacket.SequenceNumber, tcpPacket.AcknowledgmentNumber, length, tcpPacket.PayloadData, (ulong)tcpPacket.PayloadData.Length, tcpPacket.Syn, srcIP, dstIP, (uint)tcpPacket.SourcePort, (uint)tcpPacket.DestinationPort, timeVal); //} if (TimestampFirstPacket == null) { TimestampFirstPacket = timeVal; } TimestampLastPacket = timeVal; } catch (Exception ex) { //this.Log().Error(ex.ToString()); } }
/// <summary> /// Write the text representation of <see cref="DnsPacket"/>. It uses Flix assert format, e.g., Frame(DnsPacket(0.1, 1234, Query)). /// </summary> /// <param name="packet"></param> public void WriteRecord(PosixTimeval timestamp, FlowKey flowKey, DnsPacket packet) { string answerString(DnsPacket.Answer answer) { switch (answer.Rdata) { case DnsPacket.ARecord a: return($"A(\"{answer.Name.DomainNameString}\",\"{new IPAddress(a.Address)}\")"); case DnsPacket.AaaaRecord aaaa: return($"AAAA(\"{answer.Name.DomainNameString}\",\"{new IPAddress(aaaa.Address)}\")"); case DnsPacket.CnameRecord cname: return($"CNAME(\"{answer.Name.DomainNameString}\",\"{cname.Hostname.DomainNameString}\")"); case DnsPacket.NsRecord ns: return($"NS(\"{answer.Name.DomainNameString}\",\"{ns.Hostname.DomainNameString}\")"); case DnsPacket.MxRecord mx: return($"NS(\"{answer.Name.DomainNameString}\",{mx.Priority},\"{mx.Hostname.DomainNameString}\")"); default: return("NULL"); } } var ts = ((double)timestamp.Seconds + ((double)timestamp.MicroSeconds) / 1000000).ToString("0.000"); var id = packet.TransactionId; var rcode = packet.Flags.Rcode == 0 ? "NoError" : "NameDoesNotExist"; var queries = String.Join("::", packet.Queries.Select(x => $"{x.Type.ToString().ToUpperInvariant()}(\"{x.Name.DomainNameString}\",\"\")").Append("Nil")); var answers = String.Join("::", packet.Answers.Select(answerString).Append("Nil")); var qr = packet.Flags.Qr == 0 ? $"Query({id},{queries})" : $"Response({id},{rcode},{queries},{answers})"; var dns = $"DNS({qr})"; var proto = CultureInfo.InvariantCulture.TextInfo.ToTitleCase(flowKey.Protocol.ToString()); var ipSrc = flowKey.SourceEndpoint.Address.ToString(); var ipDst = flowKey.DestinationEndpoint.Address.ToString(); var portSrc = flowKey.SourceEndpoint.Port; var portDst = flowKey.DestinationEndpoint.Port; var flow = $"{proto}(\"{ipSrc}\",\"{ipDst}\",{portSrc},{portDst})"; // Frame(1520329507.498, Udp("192.168.111.100", "147.229.9.43", 1234, 53), DnsPacket(Query(15595,A("api.github.com.", "")::Nil))). var str = $"Frame({ts}, {flow}, {dns})."; m_writer.WriteLine(str); m_writer.Flush(); }
public void Process_PacketBatch_NonTransportPacket() { var randomIPPacket = IPPacket.RandomPacket(IPVersion.IPv4); //Arrange var posixTimeval = new PosixTimeval(); var rawCapture = new RawCapture(LinkLayers.Raw, posixTimeval, randomIPPacket.Bytes); var rawPacketBatchRequest = new RawPacketBatchRequest(new[] { new RawPacket(rawCapture) }, 1); //Act this._rawPacketBatchParserActorRefSUT.Tell(rawPacketBatchRequest); //Assert this._captureActorTestProbe.ExpectNoMsg(); }
internal void HandlePacket(PosixTimeval timeval, TcpPacket tcp, TcpFlow flow) { log.DebugFormat("timeval {0}, tcp {1}, flow {2}", timeval, tcp, flow); LastPacketReceived = DateTime.Now; // reset the timer closeTimer.Interval = Timeout.TotalMilliseconds; switch (ConnectionState) { case ConnectionStates.Open: if (tcp.Finished && tcp.Acknowledgment) { ConnectionState = ConnectionStates.WaitingForSecondFinAck; } break; case ConnectionStates.WaitingForSecondFinAck: if (tcp.Finished && tcp.Acknowledgment) { ConnectionState = ConnectionStates.WaitingForFinalAck; } break; case ConnectionStates.WaitingForFinalAck: if (tcp.Acknowledgment) { ConnectionState = ConnectionStates.Closed; // report connection closure if (OnConnectionClosed != null) { OnConnectionClosed(timeval, this, tcp, CloseType.FlowsClosed); } } break; } if (OnPacketReceived != null) { OnPacketReceived(timeval, this, flow, tcp); } }
private void ReadPacketFileHandler(byte[] e, bool isEnd) { if (isEnd) { PcapFileEOF = true; return; } PosixTimeval time = new PosixTimeval(); RawCapture rawCapture = new RawCapture(LinkLayers.Ethernet, time, e); lock (PacketQueueLock) { // push the packet to the queue . PacketQueue.Enqueue(rawCapture); } }
public RawCapture NextPacket() { PosixTimeval timestamp = null; DeviceWrapper wrapper = null; List <string> devNeedClose = null; foreach (var device in _devices.Values) { var currentPkt = device.CurrentPacket; if (currentPkt == null) { if (devNeedClose == null) { devNeedClose = new List <string>(); } devNeedClose.Add(device.Name); } else if (timestamp == null || currentPkt.Timeval < timestamp) { timestamp = currentPkt.Timeval; wrapper = device; } } if (devNeedClose != null) { foreach (var name in devNeedClose) { var d = _devices[name]; _devices.Remove(name); d.Device.Close(); } } if (wrapper == null) { return(null); } var pkt = wrapper.CurrentPacket; wrapper.NextPacket(); return(pkt); }
/// <summary> /// Packet data is only valid until the next call /// </summary> /// <param name="e"></param> /// <returns>Status of the operation</returns> public GetPacketStatus GetNextPacket(out PacketCapture e) { ThrowIfNotOpen(); while (true) { bool ret; WinDivertAddress addr; uint readLen; unsafe { fixed(byte *p = buffer) { ret = WinDivertNative.WinDivertRecv(Handle, new IntPtr(p), (uint)buffer.Length, out readLen, out addr); } } if (!ret) { var err = Marshal.GetLastWin32Error(); if (err == ERROR_INSUFFICIENT_BUFFER) { // Increase buffer size buffer = new byte[buffer.Length * 2]; continue; } if (err == ERROR_NO_DATA) { e = default; return((GetPacketStatus)(-err)); } ThrowWin32Error("Recv failed", err); } var timestamp = new PosixTimeval(BootTime + TimeSpan.FromTicks(addr.Timestamp)); var data = new ReadOnlySpan <byte>(buffer, 0, (int)readLen); var header = new WinDivertHeader(timestamp) { InterfaceIndex = addr.IfIdx, SubInterfaceIndex = addr.SubIfIdx, Flags = addr.Flags }; e = new PacketCapture(this, header, data); return(GetPacketStatus.PacketRead); } }
private void OnConnectionClosed(PosixTimeval timeval, TcpConnection con, TcpPacket tcp, TcpConnection.CloseType closeType) { if (OnTCPConnectClosed != null) { TCPConnectionInfo ti = new TCPConnectionInfo(); ti.SrcIP = con.Flows[0].address; ti.SrcPort = con.Flows[0].port; ti.DestIP = con.Flows[1].address; ti.DestPort = con.Flows[1].port; ti.DeviceId = DeviceId.ToString(); TCPConnectionArg arg = new TCPConnectionArg(); arg.ConnectionInfo = ti; OnTCPConnectClosed(arg); } }
public RawCapture GetNextPacket() { ThrowIfNotOpen(); Span <byte> buffer = stackalloc byte[4096]; while (true) { bool ret; WinDivertAddress addr; uint readLen; unsafe { fixed(byte *p = buffer) { ret = WinDivertNative.WinDivertRecv(Handle, new IntPtr(p), (uint)buffer.Length, out readLen, out addr); } } if (!ret) { var err = Marshal.GetLastWin32Error(); if (err == ERROR_INSUFFICIENT_BUFFER) { // Increase buffer size buffer = stackalloc byte[buffer.Length * 2]; continue; } if (err == ERROR_NO_DATA) { return(null); } ThrowWin32Error("Recv failed", err); } var timestamp = new PosixTimeval(BootTime + TimeSpan.FromTicks(addr.Timestamp)); var data = buffer.Slice(0, (int)readLen).ToArray(); var raw = new WinDivertCapture(timestamp, data) { InterfaceIndex = addr.IfIdx, SubInterfaceIndex = addr.SubIfIdx, Flags = addr.Flags, }; return(raw); } }
/// <summary> /// Writes the payload data to the database /// </summary> /// <param name="net_src"></param> /// <param name="net_dst"></param> /// <param name="srcport"></param> /// <param name="dstport"></param> /// <param name="index"></param> /// <param name="data"></param> /// <param name="timestamp"></param> private void SavePacketData(long net_src, long net_dst, uint srcport, uint dstport, int index, byte[] data, PosixTimeval timestamp) { try { // Ignore empty packets if (data.Length == 0) { return; } if (data.Length == 1) { if (data[0] == 0) { return; } } PacketWritten = true; PreviousPacketEndOffset = CurrentOffset; CurrentOffset += data.Length; DataSize += data.Length; _storage.Write(data, 0, data.Length); bool isOutBound = false; if (index == 0) { isOutBound = true; } } catch (Exception ex) { //this.Log().Error(ex.ToString()); } }
/// <summary> /// /// </summary> /// <param name="timeval"> /// A <see cref="PosixTimeval"/> /// </param> /// <param name="connection"> /// A <see cref="TcpConnection"/> /// </param> /// <param name="flow"> /// A <see cref="TcpFlow"/> /// </param> /// <param name="tcp"> /// A <see cref="TcpPacket"/> /// </param> protected void HandleCOnPacketReceived(PosixTimeval timeval, TcpConnection connection, TcpFlow flow, TcpPacket tcp) { // look up the ConnectionStatistics var connectionStatistics = connectionDictionary[connection]; if (tcp.Synchronize && !tcp.Acknowledgment) { if (connectionStatistics.clientFlow != null) { OnMeasurementEvent(this, connection, EventTypes.DuplicateSynFound); return; } connectionStatistics.clientFlow = flow; connectionStatistics.synTime = timeval; } else if (tcp.Synchronize && tcp.Acknowledgment) { if (connectionStatistics.serverFlow != null) { OnMeasurementEvent(this, connection, EventTypes.DuplicateSynAckFound); return; } connectionStatistics.serverFlow = flow; connectionStatistics.synAckTime = timeval; } // if we have both a syn and a syn-ack time then report that // we have a valid measurement if ((connectionStatistics.synTime != null) && (connectionStatistics.synAckTime != null)) { OnMeasurementFound(this, connection, connectionStatistics); // unregister the handler since we found our syn-syn/ack time connection.OnPacketReceived -= HandleCOnPacketReceived; } }
public void OperatorTest () { var p1 = new PosixTimeval(100, 50); var p2 = new PosixTimeval(100, 100); var p3 = new PosixTimeval(200, 20); var p4 = new PosixTimeval(100, 50); Assert.IsTrue(p1 < p2, "p1 < p2"); Assert.IsTrue(p2 < p3, "p2 < p3"); Assert.IsTrue(p1 < p3, "p1 < p3"); Assert.IsTrue(p2 > p1, "p2 > p1"); Assert.IsTrue(p3 > p2, "p3 > p2"); Assert.IsTrue(p3 > p1, "p3 > p1"); Assert.IsTrue(p1 != p2, "p1 != p2"); Assert.IsTrue(p1 == p4, "p1 == p4"); Assert.IsTrue(p1 <= p2, "p1 <= p2"); Assert.IsTrue(p2 >= p1, "p2 >= p1"); }
public void OperatorTest() { var p1 = new PosixTimeval(100, 50); var p2 = new PosixTimeval(100, 100); var p3 = new PosixTimeval(200, 20); var p4 = new PosixTimeval(100, 50); Assert.IsTrue(p1 < p2, "p1 < p2"); Assert.IsTrue(p2 < p3, "p2 < p3"); Assert.IsTrue(p1 < p3, "p1 < p3"); Assert.IsTrue(p2 > p1, "p2 > p1"); Assert.IsTrue(p3 > p2, "p3 > p2"); Assert.IsTrue(p3 > p1, "p3 > p1"); Assert.IsTrue(p1 != p2, "p1 != p2"); Assert.IsTrue(p1 == p4, "p1 == p4"); Assert.IsTrue(p1 <= p2, "p1 <= p2"); Assert.IsTrue(p2 >= p1, "p2 >= p1"); }
internal StatisticsModePacket(RawCapture p) { this.Timeval = p.Timeval; this.m_pktData = p.Data; }
private void HandleTcpPacket(TcpPacket tcpPacket, IPPacket ipPacket, PosixTimeval timeVal) { var srcIp = ipPacket.SourceAddress; var dstIp = ipPacket.DestinationAddress; var localIp = ""; var serverIp = ""; var srcIsLocal = false; var dstIsLocal = false; var type = typeof(TcpPacket); var protocolName = "TCP"; var sender = SenderEnum.Unknown; IPEndPoint localEndPoint = null, remoteEndPoint = null; if (srcIp.IsLocal()) { localIp = srcIp.ToString(); srcIsLocal = true; localEndPoint = new IPEndPoint(srcIp, tcpPacket.SourcePort); remoteEndPoint = new IPEndPoint(dstIp, tcpPacket.DestinationPort); sender = SenderEnum.Client; } else { serverIp = srcIp.ToString(); } if (dstIp.IsLocal()) { localIp = dstIp.ToString(); dstIsLocal = true; localEndPoint = new IPEndPoint(dstIp, tcpPacket.DestinationPort); remoteEndPoint = new IPEndPoint(srcIp, tcpPacket.SourcePort); sender = SenderEnum.Server; } else { serverIp = dstIp.ToString(); } if (srcIsLocal && dstIsLocal) { // TODO: throw error since we can't determine who is client and who is server without user intervention } switch (remoteEndPoint.Port) { case 80: protocolName = "HTTP"; break; case 443: protocolName = "HTTPS"; break; } if (localEndPoint != null) { var connectionInfo = _connections.FirstOrDefault(ci => ci.EqualsTo(protocolName, localEndPoint, remoteEndPoint)); if (connectionInfo == null) { connectionInfo = new ConnectionInfo("Unassigned", protocolName, localEndPoint, remoteEndPoint); _connections.Add(connectionInfo); RefreshConnectionsTable(); } connectionInfo.AddPacket(new TimedPacket(tcpPacket, timeVal, sender)); } }
public void ToStringTest() { var p1 = new PosixTimeval(123, 12345); Assert.AreEqual("123.012345s", p1.ToString()); }