Commit 61c481e2 authored by Brickner_cp's avatar Brickner_cp

Add support for IPv4 datalink (raw IP packets). Thanks brianestey17!

Better handling of malformed transport layer (UDP or TCP) when calculating transport checksum.
parent 9b05bae8
......@@ -128,7 +128,7 @@ namespace PcapDotNet.Core.Test
TimeSpan actualDiff = packet.Timestamp - lastTimestamp;
MoreAssert.IsInRange(
expectedDiff.Subtract(TimeSpan.FromSeconds(0.06)),
expectedDiff.Add(TimeSpan.FromSeconds(0.06)),
expectedDiff.Add(TimeSpan.FromSeconds(0.1)),
actualDiff, "actualDiff");
}
lastTimestamp = packet.Timestamp;
......
......@@ -152,6 +152,18 @@ namespace PcapDotNet.Core.Test
ComparePacketsToWireshark(packet);
}
[TestMethod]
public void CompareIpV4DataLinkToWiresharkTest()
{
ComparePacketsToWireshark(
// Normal.
Packet.FromHexadecimalString("46000028000000000102c48601487eebe0000016940400002200f9010000000104000000e00000fc", DateTime.Now, DataLinkKind.IpV4),
// dns.response_to.
Packet.FromHexadecimalString(
"45000107400100003a110e4adc9fd4c801487eeb0035c8db00f3ead1fb96818000010001000500050436746f340469707636096d6963726f736f667403636f6d0000010001c00c0001000100000dbb00",
DateTime.Now, DataLinkKind.IpV4));
}
private static Packet CreateRandomPacket(Random random)
{
Packet packet;
......@@ -334,7 +346,7 @@ namespace PcapDotNet.Core.Test
// ReSharper disable HeuristicUnreachableCode
if (!IsRetry)
{
PacketDumpFile.Dump(pcapFilename, new PcapDataLink(DataLinkKind.Ethernet), PacketDevice.DefaultSnapshotLength, packets);
PacketDumpFile.Dump(pcapFilename, new PcapDataLink(packets.First().DataLink.Kind), PacketDevice.DefaultSnapshotLength, packets);
}
else
{
......@@ -431,6 +443,7 @@ namespace PcapDotNet.Core.Test
switch (layer.Name())
{
case "geninfo":
case "raw":
break;
case "frame":
......
......@@ -30,7 +30,7 @@ namespace PcapDotNet.Core.Test
case "dns.id":
field.AssertShowHex(dnsDatagram.Id);
break;
case "dns.flags":
field.AssertShowHex(dnsDatagram.Subsegment(2, 2).ToArray().ReadUShort(0, Endianity.Big));
foreach (var flagField in field.Fields())
......@@ -132,6 +132,10 @@ namespace PcapDotNet.Core.Test
}
break;
case "dns.response_to":
case "dns.time":
break;
default:
throw new InvalidOperationException("Invalid DNS field " + field.Name());
}
......@@ -146,8 +150,10 @@ namespace PcapDotNet.Core.Test
if (resourceRecordFieldsArray.Length != resourceRecordsArray.Length)
{
var queryNameField = resourceRecordFieldsArray[resourceRecordsArray.Length].Fields().First();
Assert.AreEqual("dns.qry.name", queryNameField.Name());
Assert.AreEqual("<Unknown extended label>", queryNameField.Show());
if (queryNameField.Name() == "dns.qry.name")
Assert.AreEqual("<Unknown extended label>", queryNameField.Show());
else
Assert.AreEqual("dns.resp.name", queryNameField.Name());
}
for (int i = 0; i != resourceRecordsArray.Length; ++i)
{
......
......@@ -33,36 +33,44 @@ namespace PcapDotNet.Core.Test
}
else
field.AssertShowDecimal(tcpDatagram.Payload.Length);
field.AssertNoFields();
break;
case "tcp.srcport":
field.AssertShowDecimal(tcpDatagram.SourcePort);
field.AssertNoFields();
break;
case "tcp.dstport":
field.AssertShowDecimal(tcpDatagram.DestinationPort);
field.AssertNoFields();
break;
case "tcp.port":
Assert.IsTrue(ushort.Parse(field.Show()) == tcpDatagram.SourcePort ||
ushort.Parse(field.Show()) == tcpDatagram.DestinationPort);
field.AssertNoFields();
break;
case "tcp.seq":
field.AssertShowDecimal(tcpDatagram.SequenceNumber);
field.AssertNoFields();
break;
case "tcp.nxtseq":
field.AssertShowDecimal(tcpDatagram.NextSequenceNumber);
field.AssertNoFields();
break;
case "tcp.ack":
field.AssertShowDecimal(tcpDatagram.AcknowledgmentNumber);
field.AssertNoFields();
break;
case "tcp.hdr_len":
field.AssertShowDecimal(tcpDatagram.HeaderLength);
field.AssertNoFields();
break;
case "tcp.flags":
......@@ -107,11 +115,13 @@ namespace PcapDotNet.Core.Test
flagField.AssertShowDecimal(tcpDatagram.IsFin);
break;
}
flagField.AssertNoFields();
}
break;
case "tcp.window_size":
case "tcp.window_size_value":
field.AssertShowDecimal(tcpDatagram.Window);
field.AssertNoFields();
break;
case "tcp.checksum":
......@@ -140,6 +150,7 @@ namespace PcapDotNet.Core.Test
case "tcp.urgent_pointer":
field.AssertShowDecimal(tcpDatagram.UrgentPointer);
field.AssertNoFields();
break;
case "tcp.options":
......@@ -148,9 +159,10 @@ namespace PcapDotNet.Core.Test
case "tcp.stream":
case "tcp.pdu.size":
case "tcp.window_size_value":
case "tcp.window_size":
case "tcp.window_size_scalefactor":
case "":
field.AssertNoFields();
break;
default:
......
......@@ -37,7 +37,10 @@ DataLinkKind PcapDataLink::Kind::get()
case 1:
return DataLinkKind::Ethernet;
case 143:
case 12:
return DataLinkKind::IpV4;
case 143:
return DataLinkKind::Docsis;
default:
......@@ -114,6 +117,9 @@ int PcapDataLink::KindToValue(DataLinkKind kind)
case DataLinkKind::Ethernet:
return 1;
case DataLinkKind::IpV4:
return 12;
case DataLinkKind::Docsis:
return 143;
......
......@@ -16,6 +16,14 @@ namespace PcapDotNet.Packets
get { return _ethernet; }
}
/// <summary>
/// IPv4 DataLink.
/// </summary>
public static DataLink IpV4
{
get { return _ipV4; }
}
/// <summary>
/// Create the DataLink from a kind.
/// </summary>
......@@ -82,6 +90,7 @@ namespace PcapDotNet.Packets
}
private static readonly DataLink _ethernet = new DataLink(DataLinkKind.Ethernet);
private static readonly DataLink _ipV4 = new DataLink(DataLinkKind.IpV4);
private readonly DataLinkKind _kind;
}
}
\ No newline at end of file
......@@ -10,6 +10,11 @@ namespace PcapDotNet.Packets
/// </summary>
Ethernet,
/// <summary>
/// IPv4 data link kind.
/// </summary>
IpV4,
/// <summary>
/// Data Over Cable Service Interface Specification.
/// </summary>
......
......@@ -440,11 +440,12 @@ namespace PcapDotNet.Packets.IpV4
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, offset + headerLength + transportChecksumOffset + 2, transportLength - transportChecksumOffset - 2);
Sum16Bits(buffer, offsetAfterChecksum, Math.Min(transportLength - transportChecksumOffset - 2, buffer.Length - offsetAfterChecksum));
ushort checksumResult = Sum16BitsToChecksum(sum);
if (checksumResult == 0 && isChecksumOptional)
......
......@@ -165,6 +165,15 @@ namespace PcapDotNet.Packets.IpV4
nextTransportLayer.Checksum, Destination);
}
/// <summary>
/// The kind of the data link of the layer.
/// Can be null if this is not the first layer in the packet.
/// </summary>
public override DataLinkKind? DataLink
{
get { return DataLinkKind.IpV4; }
}
/// <summary>
/// True iff the two IPv4 layers have the same TypeOfService, Identification, Fragmentation, Ttl, Protocol, HeaderChecksum, Source, Destination and Options.
/// </summary>
......
......@@ -4,6 +4,7 @@ using System.Collections.Generic;
using System.Linq;
using PcapDotNet.Base;
using PcapDotNet.Packets.Ethernet;
using PcapDotNet.Packets.IpV4;
namespace PcapDotNet.Packets
{
......@@ -249,18 +250,32 @@ namespace PcapDotNet.Packets
/// <summary>
/// Takes the entire packet as an Ethernet datagram.
/// Please note that if the DataLink is not Ethernet, this should make no sense.
/// </summary>
public EthernetDatagram Ethernet
{
get { return _ethernet ?? (_ethernet = new EthernetDatagram(Buffer, 0, Length)); }
}
/// <summary>
/// Takes the entire packet as an IPv4 datagram.
/// Please note that if the DataLink is not IPv4, this should make no sense.
/// </summary>
public IpV4Datagram IpV4
{
get { return _ipV4 ?? (_ipV4 = new IpV4Datagram(Buffer, 0, Length)); }
}
private bool CalculateIsValid()
{
switch (DataLink.Kind)
{
case DataLinkKind.Ethernet:
return Ethernet.IsValid;
case DataLinkKind.IpV4:
return IpV4.IsValid;
default:
return false;
}
......@@ -272,5 +287,6 @@ namespace PcapDotNet.Packets
private bool? _isValid;
private EthernetDatagram _ethernet;
private IpV4Datagram _ipV4;
}
}
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