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; ...@@ -4,6 +4,7 @@ using System.Diagnostics;
using System.Globalization; using System.Globalization;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Text;
using System.Xml.Linq; using System.Xml.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting; using Microsoft.VisualStudio.TestTools.UnitTesting;
using PcapDotNet.Packets; using PcapDotNet.Packets;
...@@ -161,9 +162,39 @@ namespace PcapDotNet.Core.Test ...@@ -161,9 +162,39 @@ namespace PcapDotNet.Core.Test
// dns.response_to. // dns.response_to.
Packet.FromHexadecimalString( Packet.FromHexadecimalString(
"45000107400100003a110e4adc9fd4c801487eeb0035c8db00f3ead1fb96818000010001000500050436746f340469707636096d6963726f736f667403636f6d0000010001c00c0001000100000dbb00", "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)); 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) private static Packet CreateRandomPacket(Random random)
{ {
Packet packet; Packet packet;
...@@ -411,6 +442,9 @@ namespace PcapDotNet.Core.Test ...@@ -411,6 +442,9 @@ namespace PcapDotNet.Core.Test
{ {
IEnumerator<Packet> packetEnumerator = packets.GetEnumerator(); IEnumerator<Packet> packetEnumerator = packets.GetEnumerator();
List<Packet> failedPackets = new List<Packet>();
StringBuilder failureMessage = new StringBuilder();
// Parse XML // Parse XML
int i = 1; int i = 1;
foreach (var documentPacket in document.Element("pdml").Elements("packet")) foreach (var documentPacket in document.Element("pdml").Elements("packet"))
...@@ -424,10 +458,17 @@ namespace PcapDotNet.Core.Test ...@@ -424,10 +458,17 @@ namespace PcapDotNet.Core.Test
} }
catch (Exception e) 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; ++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) private static void ComparePacket(Packet packet, XElement documentPacket)
......
...@@ -87,10 +87,15 @@ namespace PcapDotNet.Core.Test ...@@ -87,10 +87,15 @@ namespace PcapDotNet.Core.Test
break; break;
} }
httpFieldName = fieldShow.Substring(0, colonIndex); httpFieldName = fieldShow.Substring(0, colonIndex);
string fieldValue = fieldShow.Substring(colonIndex + 1).SkipWhile(c => c == ' ').TakeWhile(c => c != '\\').SequenceToString(); if (!field.Value().EndsWith("0d0a"))
string expectedFieldValue = httpDatagram.Header[httpFieldName].ValueString; Assert.IsNull(httpDatagram.Header[httpFieldName]);
Assert.IsTrue(expectedFieldValue.Contains(fieldValue), else
string.Format("{0} <{1}> doesn't contain <{2}>", field.Name(), expectedFieldValue, fieldValue)); {
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; break;
...@@ -130,7 +135,12 @@ namespace PcapDotNet.Core.Test ...@@ -130,7 +135,12 @@ namespace PcapDotNet.Core.Test
case "http.content_length_header": case "http.content_length_header":
_data.Append(field.Value()); _data.Append(field.Value());
if (!IsBadHttp(httpDatagram)) 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; break;
case "http.content_type": case "http.content_type":
...@@ -138,17 +148,22 @@ namespace PcapDotNet.Core.Test ...@@ -138,17 +148,22 @@ namespace PcapDotNet.Core.Test
string[] mediaType = fieldShow.Split(new[] {';', ' ', '/'}, StringSplitOptions.RemoveEmptyEntries); string[] mediaType = fieldShow.Split(new[] {';', ' ', '/'}, StringSplitOptions.RemoveEmptyEntries);
if (!IsBadHttp(httpDatagram)) if (!IsBadHttp(httpDatagram))
{ {
Assert.AreEqual(httpDatagram.Header.ContentType.MediaType, mediaType[0]); if (!field.Value().EndsWith("0d0a"))
Assert.AreEqual(httpDatagram.Header.ContentType.MediaSubtype, mediaType[1]); Assert.IsNull(httpDatagram.Header.ContentType);
int fieldShowParametersStart = fieldShow.IndexOf(';');
if (fieldShowParametersStart == -1)
Assert.IsFalse(httpDatagram.Header.ContentType.Parameters.Any());
else else
{ {
string expected = Assert.AreEqual(httpDatagram.Header.ContentType.MediaType, mediaType[0]);
httpDatagram.Header.ContentType.Parameters.Select(pair => pair.Key + '=' + pair.Value.ToWiresharkLiteral()). Assert.AreEqual(httpDatagram.Header.ContentType.MediaSubtype, mediaType[1]);
SequenceToString(';'); int fieldShowParametersStart = fieldShow.IndexOf(';');
Assert.AreEqual(expected, fieldShow.Substring(fieldShowParametersStart + 1)); 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; break;
...@@ -194,7 +209,7 @@ namespace PcapDotNet.Core.Test ...@@ -194,7 +209,7 @@ namespace PcapDotNet.Core.Test
if (httpDatagram.Version == null) if (httpDatagram.Version == null)
{ {
if (field.Show() != string.Empty) if (field.Show() != string.Empty)
Assert.IsTrue(field.Show().Contains(" ")); Assert.IsTrue(field.Show().Contains(" ") || field.Show().Length < 8);
} }
else else
field.AssertShow(httpDatagram.Version.ToString()); field.AssertShow(httpDatagram.Version.ToString());
......
...@@ -130,14 +130,15 @@ namespace PcapDotNet.Core.Test ...@@ -130,14 +130,15 @@ namespace PcapDotNet.Core.Test
{ {
foreach (var checksumField in field.Fields()) 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()) switch (checksumField.Name())
{ {
case "tcp.checksum_good": case "tcp.checksum_good":
checksumField.AssertShowDecimal(ipV4Datagram.IsTransportChecksumCorrect); checksumField.AssertShowDecimal(tcpDatagram.Checksum != 0 && ipV4Datagram.IsTransportChecksumCorrect);
break; break;
case "tcp.checksum_bad": case "tcp.checksum_bad":
checksumField.AssertShowDecimal(!ipV4Datagram.IsTransportChecksumCorrect); checksumField.AssertShowDecimal(tcpDatagram.Checksum != 0 && !ipV4Datagram.IsTransportChecksumCorrect);
break; break;
default: default:
......
...@@ -68,7 +68,7 @@ namespace PcapDotNet.Packets.Test ...@@ -68,7 +68,7 @@ namespace PcapDotNet.Packets.Test
Packet packet = packetBuilder.Build(DateTime.Now); Packet packet = packetBuilder.Build(DateTime.Now);
if (greLayer.Checksum == null && 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); Assert.IsTrue(packet.IsValid, "IsValid, ProtocolType=" + packet.Ethernet.IpV4.Gre.ProtocolType);
} }
......
...@@ -433,30 +433,9 @@ namespace PcapDotNet.Packets.IpV4 ...@@ -433,30 +433,9 @@ namespace PcapDotNet.Packets.IpV4
buffer.Write(offset + headerLength + transportChecksumOffset, checksumValue, Endianity.Big); 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> /// <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. /// 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> /// </summary>
/// <returns></returns>
protected override bool CalculateIsValid() protected override bool CalculateIsValid()
{ {
if (Length < HeaderMinimumLength || Length < HeaderLength) if (Length < HeaderMinimumLength || Length < HeaderLength)
...@@ -495,6 +474,26 @@ namespace PcapDotNet.Packets.IpV4 ...@@ -495,6 +474,26 @@ namespace PcapDotNet.Packets.IpV4
return Sum16BitsToChecksum(sum); 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 IpV4Address? _destination;
private bool? _isHeaderChecksumCorrect; private bool? _isHeaderChecksumCorrect;
private bool? _isTransportChecksumCorrect; 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