/// <summary> /// Creates UDP datagram based on the specified IP packet. /// </summary> /// <param name="ipPacket">A source IpPacket Object that contains a UDP datagram.</param> /// <param name="reuseOriginalBuffer">A flag that determines if the original packet's buffer needs to be reused.</param> /// <returns>A new UdpDatagram instance.</returns> /// <exception cref="System.ArgumentNullException">ipPacket is null</exception> /// <exception cref="System.NotSupportedException">Only UDP packets are supported.</exception> /// <exception cref="System.ArgumentOutOfRangeException">ipPacket.PacketData is empty.</exception> public static UdpDatagram ToUdpDatagram(this IIpPacket ipPacket, bool reuseOriginalBuffer = true) { if (ipPacket == null) { throw new ArgumentNullException("ipPacket"); } if (ipPacket.ProtocolType != ProtocolType.Udp) { throw new NotSupportedException("Only UDP packets are supported."); } if (ipPacket.PacketData.Count <= 0) { throw new ArgumentOutOfRangeException(); } var packetData = ipPacket.PacketData.AsByteArraySegment(); UdpDatagramHeader udpDatagramHeader = null; if (ipPacket.PacketData.Count > 8) { udpDatagramHeader = new UdpDatagramHeader( packetData.Array.ReadNetOrderUShort(packetData.Offset), packetData.Array.ReadNetOrderUShort(2 + packetData.Offset), packetData.Array.ReadNetOrderUShort(4 + packetData.Offset), packetData.Array.ReadNetOrderUShort(6 + packetData.Offset)); } ArraySegment <byte> udpData; if (reuseOriginalBuffer) { udpData = new ArraySegment <byte>( packetData.Array, packetData.Offset + 8, packetData.Count - 8); } else { var ipOptionsDataArray = new byte[packetData.Count - 8]; Array.Copy(packetData.Array, packetData.Offset + 8, ipOptionsDataArray, 0, packetData.Count - 8); udpData = new ArraySegment <byte>(ipOptionsDataArray); } var udpDatagram = new UdpDatagram { PacketHeader = ipPacket.PacketHeader, UdpDatagramHeader = udpDatagramHeader, UdpData = udpData, ReceivedTime = ipPacket.ReceivedTime }; return(udpDatagram); }
/// <summary> /// Creates UDP datagram based on the specified IP packet. /// </summary> /// <param name="ipPacket">A source IpPacket Object that contains a UDP datagram.</param> /// <param name="reuseOriginalBuffer">A flag that determines if the original packet's buffer needs to be reused.</param> /// <returns>A new UdpDatagram instance.</returns> /// <exception cref="System.ArgumentNullException">ipPacket is null</exception> /// <exception cref="System.NotSupportedException">Only UDP packets are supported.</exception> /// <exception cref="System.ArgumentOutOfRangeException">ipPacket.PacketData is empty.</exception> public static UdpDatagram ToUdpDatagram(this IIpPacket ipPacket, bool reuseOriginalBuffer = true) { if (ipPacket == null) { throw new ArgumentNullException("ipPacket"); } if (ipPacket.ProtocolType != ProtocolType.Udp) { throw new NotSupportedException("Only UDP packets are supported."); } if (ipPacket.PacketData.Count <= 0) { throw new ArgumentOutOfRangeException(); } var packetData = ipPacket.PacketData.AsByteArraySegment(); UdpDatagramHeader udpDatagramHeader = null; if (ipPacket.PacketData.Count > 8) { udpDatagramHeader = new UdpDatagramHeader( packetData.Array.ReadNetOrderUShort(packetData.Offset), packetData.Array.ReadNetOrderUShort(2 + packetData.Offset), packetData.Array.ReadNetOrderUShort(4 + packetData.Offset), packetData.Array.ReadNetOrderUShort(6 + packetData.Offset)); } ArraySegment<byte> udpData; if (reuseOriginalBuffer) { udpData = new ArraySegment<byte>( packetData.Array, packetData.Offset + 8, packetData.Count - 8); } else { var ipOptionsDataArray = new byte[packetData.Count - 8]; Array.Copy(packetData.Array, packetData.Offset + 8, ipOptionsDataArray, 0, packetData.Count - 8); udpData = new ArraySegment<byte>(ipOptionsDataArray); } var udpDatagram = new UdpDatagram { PacketHeader = ipPacket.PacketHeader, UdpDatagramHeader = udpDatagramHeader, UdpData = udpData, ReceivedTime = ipPacket.ReceivedTime }; return udpDatagram; }
private bool IsDestinationListenEndpoint(byte[] Buffer, out IpPacket packet) { var upacket = new UdpDatagram(Buffer); packet = upacket; if (packet.Protocol != ProtocolType.Udp) { return(false); } return(upacket.DestinationIpAddress.Equals(ListenEndPoint.Address) && upacket.DestinationPort == ListenEndPoint.Port); }
/// <summary> /// Takes a UDP Datagram object and encodes the UDP header for transmission on the network. Assumes UDP checksum is computed. /// </summary> /// <param name="Input">Datagram object to encode.</param> /// <returns>UDP header encoded in network order.</returns> public static byte[] UdpHeaderToWireBytes(this UdpDatagram Input) { //udp header is 8 bytes using (var outPacket = new MemoryStream()) { outPacket.Write(BitConverter.GetBytes(NetworkOrderUshort(Input.SourcePort)), 0, 2); outPacket.Write(BitConverter.GetBytes(NetworkOrderUshort(Input.DestinationPort)), 0, 2); outPacket.Write(BitConverter.GetBytes(NetworkOrderUshort(Input.UdpLength)), 0, 2); outPacket.Write(BitConverter.GetBytes(NetworkOrderUshort(Input.UdpCheckSum)), 0, 2); //should be zero if we haven't calculated it yet. return(outPacket.ToArray()); } }
/// <summary> /// Creates an instance of a Log object. /// </summary> /// <param name="ReceivedPacket">An UdpDatagram object generated on data received on a Raw socket. </param> /// <param name="Parser">A regular expression that will be used to parse the internal message of the Log.</param> public Syslog(UdpDatagram ReceivedPacket, Regex Parser) : base(ReceivedPacket) { if (Protocol != ProtocolType.Udp) { throw new NotSupportedException("Datagrams other than UDP not supported to generate Syslogs."); } string LogMessage = Encoding.ASCII.GetString(UdpData); if (string.IsNullOrWhiteSpace(LogMessage)) { throw new ArgumentOutOfRangeException("Incoming UDP datagram contained no Syslog data."); } Match defMatch = DefaultParser.Match(LogMessage); var privalMatch = defMatch.Groups["PRIVAL"].Value.Trim(); if (!string.IsNullOrWhiteSpace(privalMatch)) { var prival = int.Parse(privalMatch); LogSeverity = (Severity)Enum.ToObject(typeof(Severity), prival & 0x7); LogFacility = (Facility)Enum.ToObject(typeof(Facility), prival >> 3); Message = defMatch.Groups["MESSAGE"].Value.Trim(); } else { throw new ArgumentOutOfRangeException( "Datagram does not contain the correct string indicating the PRIVAL of the Syslog"); } if (SetRegex(Parser)) { NamedCollectedMatches = new Dictionary <string, Group>(StringComparer.OrdinalIgnoreCase); //support needed for other encoding per IETF RFC. Match matchMe = this.Parser.Match(LogMessage); if (matchMe.Groups.Count < 1) { throw new Exception("Only no parsable fields in the incoming Syslog"); } foreach (var groupName in Parser.GetGroupNames()) { if (string.IsNullOrEmpty(matchMe.Groups[groupName].Value)) { continue; } NamedCollectedMatches.Add(groupName, matchMe.Groups[groupName]); } } }
/// <summary> /// Takes an UDPDatagram object and encodes it for transmission on the network in a byte array. Includes computing checksums. /// </summary> /// <param name="Input">UdpDatagram object for encoding.</param> /// <returns>Network order byte array with IP and UDP checksums included ready to send on a raw socket.</returns> public static byte[] ToWirebytes(this UdpDatagram Input) { using (var builderStream = new MemoryStream()) { var ipHeader = PacketHeaderToWireBytes(Input); builderStream.Write(ipHeader, 0, ipHeader.Length); var udpCk = GetUdpCheckSum(Input); Input.UdpCheckSum = NetworkOrderUshort(udpCk); builderStream.Write(UdpHeaderToWireBytes(Input), 0, 8); //bytes now in network order here builderStream.Write(Input.UdpData, 0, Input.UdpData.Length); return(builderStream.ToArray()); } }
/// <summary> /// From a UDP datagram object, creates the UDP pseudoheader that is used to compute the UDP checksum per RFC 768 /// </summary> /// <param name="Input">The datagram object to use in encoding</param> /// <returns>Byte array of the pseudo header in Network Order</returns> public static byte[] UdpPseudoHeader(this UdpDatagram Input) { byte Zeroes = 0; byte Protocol = Input.ProtocolNumber; ushort UDPLength = Input.UdpLength; using (MemoryStream builder = new MemoryStream()) { builder.Write(Input.SourceIpAddress.GetAddressBytes(), 0, 4); builder.Write(Input.DestinationIpAddress.GetAddressBytes(), 0, 4); builder.WriteByte(Zeroes); builder.WriteByte(Input.ProtocolNumber); builder.Write(BitConverter.GetBytes(NetworkOrderUshort(Input.UdpLength)), 0, 2); return(builder.ToArray()); } }
/// <summary> /// Uses the UDP Pseudoheader, UDP Header, and UDP payload to compute the checksum used in UDP transmission, per RFC 768 /// </summary> /// <param name="Input">The UdpDatagram object to check</param> /// <returns>16bit integer sum in network order.</returns> public static ushort GetUdpCheckSum(this UdpDatagram Input) { using (var udpCk = new MemoryStream()) { var udpPh = UdpPseudoHeader(Input); udpCk.Write(udpPh, 0, udpPh.Length); udpCk.Write(BitConverter.GetBytes(NetworkOrderUshort(Input.SourcePort)), 0, 2); udpCk.Write(BitConverter.GetBytes(NetworkOrderUshort(Input.DestinationPort)), 0, 2); udpCk.Write(BitConverter.GetBytes(NetworkOrderUshort(Input.UdpLength)), 0, 2); udpCk.WriteByte(0); udpCk.WriteByte(0); udpCk.Write(Input.UdpData, 0, Input.UdpData.Length); return(GetInternetChecksum(udpCk.ToArray())); } }
static void UdpPackets() { Console.WriteLine("\n======================= {0} =======================\n", MethodInfo.GetCurrentMethod().Name); var packets = PcapNg.ReadForward(fileName) .Where(b => b.Type == BlockType.EnhancedPacketBlock) .Cast<EnhancedPacketBlock>() .Take(5); foreach (var packet in packets) { int ipLen = packet.PacketData.Length - 14; // 14 is the size of the Ethernet header byte[] datagram = new byte[ipLen]; Array.Copy(packet.PacketData, 14, datagram, 0, ipLen); UdpDatagram udp = new UdpDatagram(datagram); Console.WriteLine(udp.PacketData.ToHexDump()); Console.WriteLine(); } }
/// <summary> /// Creates an instance of a Log object. /// </summary> /// <param name="ReceivedPacket">An UdpDatagram object generated on data received on a Raw socket. </param> /// <param name="Parser">A regular expression that will be used to parse the internal message of the Log.</param> public Syslog(UdpDatagram ReceivedPacket, Regex Parser) : base(ReceivedPacket) { if (Protocol != ProtocolType.Udp) { throw new NotSupportedException("Datagrams other than UDP not supported to generate Syslogs."); } string LogMessage = Encoding.ASCII.GetString(UdpData); if (string.IsNullOrWhiteSpace(LogMessage)) { throw new ArgumentOutOfRangeException("Incoming UDP datagram contained no Syslog data."); } Match defMatch = DefaultParser.Match(LogMessage); var privalMatch = defMatch.Groups["PRIVAL"].Value.Trim(); if (!string.IsNullOrWhiteSpace(privalMatch)) { var prival = int.Parse(privalMatch); LogSeverity = (Severity)Enum.ToObject(typeof(Severity), prival & 0x7); LogFacility = (Facility)Enum.ToObject(typeof(Facility), prival >> 3); Message = defMatch.Groups["MESSAGE"].Value.Trim(); } else { throw new ArgumentOutOfRangeException("Datagram does not contain the correct string indicating the PRIVAL of the Syslog"); } if (SetRegex(Parser)) { NamedCollectedMatches = new Dictionary<string, Group>(StringComparer.OrdinalIgnoreCase); //support needed for other encoding per IETF RFC. Match matchMe = this.Parser.Match(LogMessage); if (matchMe.Groups.Count < 1) throw new Exception("Only no parsable fields in the incoming Syslog"); foreach (var groupName in Parser.GetGroupNames()) { if (string.IsNullOrEmpty(matchMe.Groups[groupName].Value)) continue; NamedCollectedMatches.Add(groupName, matchMe.Groups[groupName]); } } }