Commit 4cf6f1a4 authored by Brickner_cp's avatar Brickner_cp

Use actual Transport length for Transport checksum calculation and not...

Use actual Transport length for Transport checksum calculation and not according to IP total length.
parent 61c481e2
......@@ -4,6 +4,7 @@ using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Text;
using System.Xml.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using PcapDotNet.Packets;
......@@ -161,9 +162,39 @@ namespace PcapDotNet.Core.Test
// dns.response_to.
Packet.FromHexadecimalString(
"45000107400100003a110e4adc9fd4c801487eeb0035c8db00f3ead1fb96818000010001000500050436746f340469707636096d6963726f736f667403636f6d0000010001c00c0001000100000dbb00",
DateTime.Now, DataLinkKind.IpV4),
// TCP Checksum is bad because of too big IP total length.
Packet.FromHexadecimalString(
"450000a8392040003706944a4a7dab3501487eeb0050cb50800f365664e4726250180089df90000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
DateTime.Now, DataLinkKind.IpV4),
// TCP Checksum is zero.
Packet.FromHexadecimalString(
"450005dc54224000370674144a7dab3501487eeb0050cb5080a8136c64e4726250100089000000002db2707095328b271a9acf128e85be789f0e5ea6cb9d6f13f32481f6baf855420b60fe5c4053407e",
DateTime.Now, DataLinkKind.IpV4));
}
[TestMethod]
public void CompareTcpZeroChecksumToWiresharkTest()
{
ComparePacketsToWireshark(
PacketBuilder.Build(DateTime.Now,
new EthernetLayer(),
new IpV4Layer
{
Ttl = 128
},
new TcpLayer
{
Checksum = 0,
Window = 100,
},
new PayloadLayer
{
Data = new Datagram(new byte[10])
}));
}
private static Packet CreateRandomPacket(Random random)
{
Packet packet;
......@@ -411,6 +442,9 @@ namespace PcapDotNet.Core.Test
{
IEnumerator<Packet> packetEnumerator = packets.GetEnumerator();
List<Packet> failedPackets = new List<Packet>();
StringBuilder failureMessage = new StringBuilder();
// Parse XML
int i = 1;
foreach (var documentPacket in document.Element("pdml").Elements("packet"))
......@@ -424,10 +458,17 @@ namespace PcapDotNet.Core.Test
}
catch (Exception e)
{
throw new AssertFailedException("Failed comparing packet " + i + ". " + e.Message, e);
failedPackets.Add(packet);
failureMessage.Append(new AssertFailedException("Failed comparing packet " + i + ". " + e.Message, e) + Environment.NewLine);
}
++i;
}
if (failedPackets.Any())
{
PacketDumpFile.Dump(Path.GetTempPath() + "temp." + 1000 + ".pcap", failedPackets.First().DataLink.Kind, 65536, failedPackets);
throw new AssertFailedException("Failed comparing " + failedPackets.Count + " packets:" + Environment.NewLine + failureMessage);
}
}
private static void ComparePacket(Packet packet, XElement documentPacket)
......
......@@ -87,10 +87,15 @@ namespace PcapDotNet.Core.Test
break;
}
httpFieldName = fieldShow.Substring(0, colonIndex);
string fieldValue = fieldShow.Substring(colonIndex + 1).SkipWhile(c => c == ' ').TakeWhile(c => c != '\\').SequenceToString();
string expectedFieldValue = httpDatagram.Header[httpFieldName].ValueString;
Assert.IsTrue(expectedFieldValue.Contains(fieldValue),
string.Format("{0} <{1}> doesn't contain <{2}>", field.Name(), expectedFieldValue, fieldValue));
if (!field.Value().EndsWith("0d0a"))
Assert.IsNull(httpDatagram.Header[httpFieldName]);
else
{
string fieldValue = fieldShow.Substring(colonIndex + 1).SkipWhile(c => c == ' ').TakeWhile(c => c != '\\').SequenceToString();
string expectedFieldValue = httpDatagram.Header[httpFieldName].ValueString;
Assert.IsTrue(expectedFieldValue.Contains(fieldValue),
string.Format("{0} <{1}> doesn't contain <{2}>", field.Name(), expectedFieldValue, fieldValue));
}
}
break;
......@@ -130,7 +135,12 @@ namespace PcapDotNet.Core.Test
case "http.content_length_header":
_data.Append(field.Value());
if (!IsBadHttp(httpDatagram))
field.AssertShowDecimal(httpDatagram.Header.ContentLength.ContentLength.Value);
{
if (!field.Value().EndsWith("0d0a"))
Assert.IsNull(httpDatagram.Header.ContentLength);
else
field.AssertShowDecimal(httpDatagram.Header.ContentLength.ContentLength.Value);
}
break;
case "http.content_type":
......@@ -138,17 +148,22 @@ namespace PcapDotNet.Core.Test
string[] mediaType = fieldShow.Split(new[] {';', ' ', '/'}, StringSplitOptions.RemoveEmptyEntries);
if (!IsBadHttp(httpDatagram))
{
Assert.AreEqual(httpDatagram.Header.ContentType.MediaType, mediaType[0]);
Assert.AreEqual(httpDatagram.Header.ContentType.MediaSubtype, mediaType[1]);
int fieldShowParametersStart = fieldShow.IndexOf(';');
if (fieldShowParametersStart == -1)
Assert.IsFalse(httpDatagram.Header.ContentType.Parameters.Any());
if (!field.Value().EndsWith("0d0a"))
Assert.IsNull(httpDatagram.Header.ContentType);
else
{
string expected =
httpDatagram.Header.ContentType.Parameters.Select(pair => pair.Key + '=' + pair.Value.ToWiresharkLiteral()).
SequenceToString(';');
Assert.AreEqual(expected, fieldShow.Substring(fieldShowParametersStart + 1));
Assert.AreEqual(httpDatagram.Header.ContentType.MediaType, mediaType[0]);
Assert.AreEqual(httpDatagram.Header.ContentType.MediaSubtype, mediaType[1]);
int fieldShowParametersStart = fieldShow.IndexOf(';');
if (fieldShowParametersStart == -1)
Assert.IsFalse(httpDatagram.Header.ContentType.Parameters.Any());
else
{
string expected =
httpDatagram.Header.ContentType.Parameters.Select(pair => pair.Key + '=' + pair.Value.ToWiresharkLiteral()).
SequenceToString(';');
Assert.AreEqual(expected, fieldShow.Substring(fieldShowParametersStart + 1));
}
}
}
break;
......@@ -194,7 +209,7 @@ namespace PcapDotNet.Core.Test
if (httpDatagram.Version == null)
{
if (field.Show() != string.Empty)
Assert.IsTrue(field.Show().Contains(" "));
Assert.IsTrue(field.Show().Contains(" ") || field.Show().Length < 8);
}
else
field.AssertShow(httpDatagram.Version.ToString());
......
......@@ -130,14 +130,15 @@ namespace PcapDotNet.Core.Test
{
foreach (var checksumField in field.Fields())
{
// When TCP checksum is zero Wireshark assumes it's Checksum Offloading and puts false in both checksum_good and checksum_bad.
switch (checksumField.Name())
{
case "tcp.checksum_good":
checksumField.AssertShowDecimal(ipV4Datagram.IsTransportChecksumCorrect);
checksumField.AssertShowDecimal(tcpDatagram.Checksum != 0 && ipV4Datagram.IsTransportChecksumCorrect);
break;
case "tcp.checksum_bad":
checksumField.AssertShowDecimal(!ipV4Datagram.IsTransportChecksumCorrect);
checksumField.AssertShowDecimal(tcpDatagram.Checksum != 0 && !ipV4Datagram.IsTransportChecksumCorrect);
break;
default:
......
......@@ -68,7 +68,7 @@ namespace PcapDotNet.Packets.Test
Packet packet = packetBuilder.Build(DateTime.Now);
if (greLayer.Checksum == null &&
!new[] { EthernetType.IpV4, EthernetType.Arp }.Contains(packet.Ethernet.IpV4.Gre.ProtocolType))
!new[] { EthernetType.IpV4, EthernetType.Arp, EthernetType.VLanTaggedFrame }.Contains(packet.Ethernet.IpV4.Gre.ProtocolType))
{
Assert.IsTrue(packet.IsValid, "IsValid, ProtocolType=" + packet.Ethernet.IpV4.Gre.ProtocolType);
}
......
......@@ -433,30 +433,9 @@ namespace PcapDotNet.Packets.IpV4
buffer.Write(offset + headerLength + transportChecksumOffset, checksumValue, Endianity.Big);
}
private ushort CalculateTransportChecksum()
{
return CalculateTransportChecksum(Buffer, StartOffset, HeaderLength, (ushort)(TotalLength - HeaderLength), Transport.ChecksumOffset, Transport.IsChecksumOptional, Destination);
}
private static ushort CalculateTransportChecksum(byte[] buffer, int offset, int headerLength, ushort transportLength, int transportChecksumOffset, bool isChecksumOptional, IpV4Address destination)
{
int offsetAfterChecksum = offset + headerLength + transportChecksumOffset + 2;
uint sum = Sum16Bits(buffer, offset + Offset.Source, IpV4Address.SizeOf) +
Sum16Bits(destination) +
buffer[offset + Offset.Protocol] + transportLength +
Sum16Bits(buffer, offset + headerLength, transportChecksumOffset) +
Sum16Bits(buffer, offsetAfterChecksum, Math.Min(transportLength - transportChecksumOffset - 2, buffer.Length - offsetAfterChecksum));
ushort checksumResult = Sum16BitsToChecksum(sum);
if (checksumResult == 0 && isChecksumOptional)
return 0xFFFF;
return checksumResult;
}
/// <summary>
/// An IPv4 datagram is valid if its length is big enough for the header, the header checksum is correct and the payload is valid.
/// </summary>
/// <returns></returns>
protected override bool CalculateIsValid()
{
if (Length < HeaderMinimumLength || Length < HeaderLength)
......@@ -495,6 +474,26 @@ namespace PcapDotNet.Packets.IpV4
return Sum16BitsToChecksum(sum);
}
private ushort CalculateTransportChecksum()
{
return CalculateTransportChecksum(Buffer, StartOffset, HeaderLength, (ushort)Transport.Length, Transport.ChecksumOffset, Transport.IsChecksumOptional, Destination);
}
private static ushort CalculateTransportChecksum(byte[] buffer, int offset, int headerLength, ushort transportLength, int transportChecksumOffset, bool isChecksumOptional, IpV4Address destination)
{
int offsetAfterChecksum = offset + headerLength + transportChecksumOffset + 2;
uint sum = Sum16Bits(buffer, offset + Offset.Source, IpV4Address.SizeOf) +
Sum16Bits(destination) +
buffer[offset + Offset.Protocol] + transportLength +
Sum16Bits(buffer, offset + headerLength, transportChecksumOffset) +
Sum16Bits(buffer, offsetAfterChecksum, transportLength - transportChecksumOffset - 2);
ushort checksumResult = Sum16BitsToChecksum(sum);
if (checksumResult == 0 && isChecksumOptional)
return 0xFFFF;
return checksumResult;
}
private IpV4Address? _destination;
private bool? _isHeaderChecksumCorrect;
private bool? _isTransportChecksumCorrect;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment