/// <summary> /// Correct fields such as checksums. Recursive. /// </summary> public void CorrectFields() { this.Checksum = 0; var thisAsBytes = this.ToArray(); this.Checksum = IPv4.ComputeChecksum(thisAsBytes, 0, thisAsBytes.Length); }
/// <summary> /// Attempts to parse raw data into a structured packet /// </summary> /// <param name="buffer">Raw data to parse</param> /// <param name="packet">Parsed packet</param> /// <param name="count">The length of the packet in bytes</param> /// <param name="index">The index into the buffer at which the packet begins</param> /// <returns>True if parsing was successful, false if it is not.</returns> internal static bool TryParse(byte[] buffer, int index, int count, out SNAP packet) { try { if (count < MinimumParseableBytes) { packet = null; return(false); } using (var ms = new MemoryStream(buffer, index, count, false)) { using (var br = new BinaryReader(ms)) { var organizationCode = br.ReadBytes(3); var etherType = ByteOrder.NetworkToHostOrder(br.ReadUInt16()); packet = null; if (organizationCode[0] == 0 && organizationCode[1] == 0 && organizationCode[2] == 0) { switch (etherType) { case (ushort)EtherTypes.IPv4: { IPv4 payload; if (IPv4.TryParse( buffer, index + (int)br.BaseStream.Position, (int)(count - br.BaseStream.Position), out payload)) { packet = new SNAP <IPv4> { Payload = payload }; } } break; case (ushort)EtherTypes.ARP: { ARP payload; if (ARP.TryParse( buffer, index + (int)br.BaseStream.Position, (int)(count - br.BaseStream.Position), out payload)) { packet = new SNAP <ARP> { Payload = payload }; } } break; case (ushort)EtherTypes.EAPoLAN: { IEEE802_1x payload; if (IEEE802_1x.TryParse( buffer, index + (int)br.BaseStream.Position, (int)(count - br.BaseStream.Position), out payload)) { packet = new SNAP <IEEE802_1x> { Payload = payload }; } } break; } } if (packet == null) { Generic payload; Generic.TryParse( buffer, index + (int)br.BaseStream.Position, (int)(count - br.BaseStream.Position), out payload); // This can never fail, so I'm not checking the output packet = new SNAP <Generic> { Payload = payload }; } packet.OrganizationCode = organizationCode; packet.ProtocolID = etherType; return(true); } } } catch (Exception) { packet = null; return(false); } }
/// <summary> /// Attempts to parse raw data into a structured packet /// </summary> /// <param name="buffer">Raw data to parse</param> /// <param name="packet">Parsed packet</param> /// <param name="count">The length of the packet in bytes</param> /// <param name="index">The index into the buffer at which the packet begins</param> /// <returns>True if parsing was successful, false if it is not.</returns> internal static bool TryParse(byte[] buffer, int index, int count, out IPv4 packet) { try { if (count < MinimumParseableBytes) { packet = null; return(false); } using (var ms = new MemoryStream(buffer, index, count, false)) { using (var br = new BinaryReader(ms)) { var versionAndHeaderLen = br.ReadByte(); var version = versionAndHeaderLen >> 4; var headerLength = versionAndHeaderLen & 0x0F; var differentiatedServices = br.ReadByte(); var totalLength = ByteOrder.NetworkToHostOrder(br.ReadUInt16()); var id = ByteOrder.NetworkToHostOrder(br.ReadUInt16()); var flagsAndFragOff = new BitVector32(ByteOrder.NetworkToHostOrder(br.ReadUInt16())); var ttl = br.ReadByte(); var protocol = br.ReadByte(); var headerChecksum = ByteOrder.NetworkToHostOrder(br.ReadUInt16()); var sourceAddress = new IPv4Address(br.ReadBytes(4)); var destAddress = new IPv4Address(br.ReadBytes(4)); if (headerLength == 0 || (headerLength * 32 / 8 > count)) { // Specified header length is larger than available bytes packet = null; return(false); } byte[] optionsAndPadding; if (headerLength * 32 / 8 < br.BaseStream.Position) { optionsAndPadding = br.ReadBytes(headerLength * 32 / 8 - (int)br.BaseStream.Position); } else { optionsAndPadding = Array.Empty <byte>(); } br.BaseStream.Seek(headerLength * 32 / 8, SeekOrigin.Begin); // TODO: Accept option for IgnoreLength int payloadLength; if (true /*IgnoreLength*/) { payloadLength = count - (int)br.BaseStream.Position; } /*else * { * payloadLength = (totalLength - (headerLength * 32 / 8) * }*/ packet = null; switch (protocol) { case (byte)Protocols.UDP: { UDP payload; if (UDP.TryParse( buffer, index + (int)br.BaseStream.Position, payloadLength, out payload)) { packet = new IPv4 <UDP> { Payload = payload }; } } break; case (byte)Protocols.ICMP: { ICMP payload; if (ICMP.TryParse( buffer, index + (int)br.BaseStream.Position, payloadLength, out payload)) { packet = new IPv4 <ICMP> { Payload = payload }; } } break; case (byte)Protocols.TCP: { TCP payload; if (TCP.TryParse( buffer, index + (int)br.BaseStream.Position, payloadLength, out payload)) { packet = new IPv4 <TCP> { Payload = payload }; } } break; } if (packet == null) { Generic payload; Generic.TryParse(buffer, index + (int)br.BaseStream.Position, payloadLength, out payload); // This can never fail, so I'm not checking the output packet = new IPv4 <Generic> { Payload = payload }; } packet.Version = version; packet.HeaderLength = headerLength; packet.DifferentiatedServices = differentiatedServices; packet.TotalLength = totalLength; packet.ID = id; packet.FlagsAndFragOff = flagsAndFragOff; packet.TTL = ttl; packet.Protocol = protocol; packet.HeaderChecksum = headerChecksum; packet.SourceAddress = sourceAddress; packet.DestAddress = destAddress; packet.OptionsAndPadding = optionsAndPadding; return(true); } } } catch (Exception) { packet = null; return(false); } }
/// <summary> /// Attempts to parse raw data into a structured packet /// </summary> /// <param name="buffer">Raw data to parse</param> /// <param name="packet">Parsed packet</param> /// <param name="count">The length of the packet in bytes</param> /// <param name="index">The index into the buffer at which the packet begins</param> /// <returns>True if parsing was successful, false if it is not.</returns> internal static bool TryParse(byte[] buffer, int index, int count, out IPv4 packet) { try { if (count < MinimumParseableBytes) { packet = null; return false; } using (var ms = new MemoryStream(buffer, index, count, false)) { using (var br = new BinaryReader(ms)) { var versionAndHeaderLen = br.ReadByte(); var version = versionAndHeaderLen >> 4; var headerLength = versionAndHeaderLen & 0x0F; var differentiatedServices = br.ReadByte(); var totalLength = ByteOrder.NetworkToHostOrder(br.ReadUInt16()); var id = ByteOrder.NetworkToHostOrder(br.ReadUInt16()); var flagsAndFragOff = new BitVector32(ByteOrder.NetworkToHostOrder(br.ReadUInt16())); var ttl = br.ReadByte(); var protocol = br.ReadByte(); var headerChecksum = ByteOrder.NetworkToHostOrder(br.ReadUInt16()); var sourceAddress = new IPv4Address(br.ReadBytes(4)); var destAddress = new IPv4Address(br.ReadBytes(4)); if (headerLength == 0 || (headerLength * 32 / 8 > count)) { // Specified header length is larger than available bytes packet = null; return false; } byte[] optionsAndPadding; if (headerLength * 32 / 8 < br.BaseStream.Position) { optionsAndPadding = br.ReadBytes(headerLength * 32 / 8 - (int)br.BaseStream.Position); } else { optionsAndPadding = Array.Empty<byte>(); } br.BaseStream.Seek(headerLength * 32 / 8, SeekOrigin.Begin); // TODO: Accept option for IgnoreLength int payloadLength; if (true /*IgnoreLength*/) { payloadLength = count - (int)br.BaseStream.Position; } /*else { payloadLength = (totalLength - (headerLength * 32 / 8) }*/ packet = null; switch (protocol) { case (byte)Protocols.UDP: { UDP payload; if (UDP.TryParse( buffer, index + (int)br.BaseStream.Position, payloadLength, out payload)) { packet = new IPv4<UDP> { Payload = payload }; } } break; case (byte)Protocols.ICMP: { ICMP payload; if (ICMP.TryParse( buffer, index + (int)br.BaseStream.Position, payloadLength, out payload)) { packet = new IPv4<ICMP> { Payload = payload }; } } break; // TODO: Add TCP when ported over } if (packet == null) { Generic payload; Generic.TryParse(buffer, index + (int)br.BaseStream.Position, payloadLength, out payload); // This can never fail, so I'm not checking the output packet = new IPv4<Generic> { Payload = payload }; } packet.Version = version; packet.HeaderLength = headerLength; packet.DifferentiatedServices = differentiatedServices; packet.TotalLength = totalLength; packet.ID = id; packet.FlagsAndFragOff = flagsAndFragOff; packet.TTL = ttl; packet.Protocol = protocol; packet.HeaderChecksum = headerChecksum; packet.SourceAddress = sourceAddress; packet.DestAddress = destAddress; packet.OptionsAndPadding = optionsAndPadding; return true; } } } catch (Exception) { packet = null; return false; } }
/// <summary> /// Attempts to parse raw data into a structured packet /// </summary> /// <param name="buffer">Raw data to parse</param> /// <param name="packet">Parsed packet</param> /// <param name="count">The length of the packet in bytes</param> /// <param name="index">The index into the buffer at which the packet begins</param> /// <returns>True if parsing was successful, false if it is not.</returns> internal static bool TryParse(byte[] buffer, int index, int count, out EthernetII packet) { try { if (count < MinimumParseableBytes) { packet = null; return(false); } using (var ms = new MemoryStream(buffer, index, count, false)) { using (var br = new BinaryReader(ms)) { var dstMac = br.ReadBytes(6); var srcMac = br.ReadBytes(6); var etherType = ByteOrder.NetworkToHostOrder(br.ReadUInt16()); packet = null; switch (etherType) { case (ushort)EtherTypes.IPv4: { IPv4 payload; if (IPv4.TryParse( buffer, index + (int)br.BaseStream.Position, (int)(count - br.BaseStream.Position), out payload)) { packet = new EthernetII <IPv4> { Payload = payload }; } } break; case (ushort)EtherTypes.ARP: { ARP payload; if (ARP.TryParse( buffer, index + (int)br.BaseStream.Position, (int)(count - br.BaseStream.Position), out payload)) { packet = new EthernetII <ARP> { Payload = payload }; } } break; } if (packet == null) { Generic payload; Generic.TryParse( buffer, index + (int)br.BaseStream.Position, (int)(count - br.BaseStream.Position), out payload); // This can never fail, so I'm not checking the output packet = new EthernetII <Generic> { Payload = payload }; } packet.DstMac = dstMac; packet.EtherType = etherType; packet.SrcMac = srcMac; return(true); } } } catch (Exception) { packet = null; return(false); } }