Commit 762de5ab authored by Brickner_cp's avatar Brickner_cp

Add support for DNS Option Client Subnet.

Fix ICMP Parameter Problem.
Add CommercialSecurity to the list of IPv4 option types (without supporting it).
Wireshark 1.12.3
parent 3695a2fb
...@@ -195,6 +195,15 @@ namespace PcapDotNet.Core.Test ...@@ -195,6 +195,15 @@ namespace PcapDotNet.Core.Test
DateTime.Now, new DataLink(DataLinkKind.LinuxSll))); DateTime.Now, new DataLink(DataLinkKind.LinuxSll)));
} }
[TestMethod]
public void CompareMdnsQueryToWiresharkTest()
{
ComparePacketsToWireshark(
Packet.FromHexadecimalString(
"9221e942a2a35fe13e477f6d080047ef03095fa200003f117cef97257914f7ef2dc08804d67189037c0014e914eb02edce8b92b103b0000300050002000208797773697971696701660176046c78736d01780867716973656a6f6e07726b6b6563747703766e67026e7600003900ff086a776d7871626f690561656f6374046c7573720372616b066f717072756f0000fa0003076577656c74636e0469687178016c000003000306656a6c766a7904766e786406666a6f706869096f7467716479706d64066b71736d726e086b6963747171786b01790774766b636f656b0977726976736c68666300000900013406fb7a00070575746578670001690279790872676669626e62740663626c6a686a047563737502796302646900000b0004612e5287000d4c0cbd4134281019613edfe69d06646c76766d72046466657200003900fe15ed69250038fe22370c90f301b65c0ea97d6a0b441061ea7586f14b7deb653febba13d87cf9e9f3f09777b40c8599edb6ab467e60914419632ebaa03325036e7978036e766a00002800043c425d7600283f8aaddeefed0494d1a5e6de5975fa744e3e48c0cb6dfbe6ba7d5249311a95e9e976977fb550cab307646c736567687300001e00043be655710031087364646379746462096a70717865636e676f096a636a6d66696c6873016405627369617902706500b64f3e9ec623719b066277726b6a62096a6a68736a7178746e046b777576057770646367066a6c666b736b00000c00015006760d000100026471047071696a08716173747666697408667975676177636806666f656d6e740000fe00fe4b61a27e00467ec11db77e8d0ef41eda501b46a903087e497a411870b17e6e1a0e07661b65d9f67bbc48ebfa9f2001a96ece1e347dd0b0a1d4e72c3c4d0e109f49647f078e02747625caedbb036e76680772676364697770096a7178696864686f7602716c0000ff0000713ccfa7000cb2e3f484503cd3fcde0b2d3f097572696e6a797365650270770468667570086474616d6273696305676d61656400000c000072b2e660001a09646f6d646f78706e680674746c797164077869707066676b00",
DateTime.Now, new DataLink(DataLinkKind.Ethernet)));
}
[TestMethod] [TestMethod]
public void CompareTcpZeroChecksumToWiresharkTest() public void CompareTcpZeroChecksumToWiresharkTest()
{ {
......
...@@ -157,10 +157,11 @@ namespace PcapDotNet.Core.Test ...@@ -157,10 +157,11 @@ namespace PcapDotNet.Core.Test
} }
else if (resourceRecordFieldsArray.Length < resourceRecordsArray.Length) else if (resourceRecordFieldsArray.Length < resourceRecordsArray.Length)
{ {
// TODO: This case should never happen when https://bugs.wireshark.org/bugzilla/show_bug.cgi?id=10615 is fixed. // TODO: This case should never happen when https://bugs.wireshark.org/bugzilla/show_bug.cgi?id=10615 and https://bugs.wireshark.org/bugzilla/show_bug.cgi?id=10988 are fixed.
XElement lastDnsType = resourceRecordFieldsArray.Last().Fields().Skip(1).First(); XElement lastDnsTypeField = resourceRecordFieldsArray.Last().Fields().Skip(1).First();
lastDnsType.AssertName("dns.resp.type"); lastDnsTypeField.AssertName("dns.resp.type");
lastDnsType.AssertShowDecimal((ushort)DnsType.NextDomain); DnsType lastDnsType = (DnsType)ushort.Parse(lastDnsTypeField.Show());
Assert.IsTrue(new[] {DnsType.NextDomain, DnsType.Opt}.Contains(lastDnsType));
} }
for (int i = 0; i != resourceRecordsArray.Length; ++i) for (int i = 0; i != resourceRecordsArray.Length; ++i)
{ {
...@@ -208,7 +209,7 @@ namespace PcapDotNet.Core.Test ...@@ -208,7 +209,7 @@ namespace PcapDotNet.Core.Test
resourceRecordAttributeField.AssertNoFields(); resourceRecordAttributeField.AssertNoFields();
break; break;
case "dns.resp.cache_flush": // TODO: Find out what does this field symbolize. case "dns.resp.cache_flush": // TODO: Support MDNS.
resourceRecordAttributeField.AssertShowDecimal((ushort)resourceRecord.DnsClass >> 15); resourceRecordAttributeField.AssertShowDecimal((ushort)resourceRecord.DnsClass >> 15);
resourceRecordAttributeField.AssertNoFields(); resourceRecordAttributeField.AssertNoFields();
break; break;
...@@ -232,6 +233,12 @@ namespace PcapDotNet.Core.Test ...@@ -232,6 +233,12 @@ namespace PcapDotNet.Core.Test
resourceRecordAttributeField.AssertNoFields(); resourceRecordAttributeField.AssertNoFields();
break; break;
case "dns.qry.qu":
// TODO: Support MDNS.
resourceRecordAttributeField.AssertShowDecimal(((ushort)resourceRecord.DnsClass >> 15) == 1);
resourceRecordAttributeField.AssertNoFields();
break;
default: default:
if (!CompareResourceRecordData(resourceRecordAttributeField, resourceRecord)) if (!CompareResourceRecordData(resourceRecordAttributeField, resourceRecord))
return; return;
...@@ -825,19 +832,19 @@ namespace PcapDotNet.Core.Test ...@@ -825,19 +832,19 @@ namespace PcapDotNet.Core.Test
case "dns.loc.size": case "dns.loc.size":
Assert.AreEqual(0, locData.Version); Assert.AreEqual(0, locData.Version);
string sizeValue = dataField.Showname().Split(new[] {'(', ')'})[1]; string sizeValue = dataField.Showname().Split(new[] {'(', ')'})[1];
Assert.AreEqual((locData.Size / 100) + " m", sizeValue); Assert.AreEqual(GetPrecisionValueString(locData.Size) + " m", sizeValue);
break; break;
case "dns.loc.horizontal_precision": case "dns.loc.horizontal_precision":
Assert.AreEqual(0, locData.Version); Assert.AreEqual(0, locData.Version);
string horizontalPrecisionValue = dataField.Showname().Split(new[] {'(', ')'})[1]; string horizontalPrecisionValue = dataField.Showname().Split(new[] {'(', ')'})[1];
Assert.AreEqual((locData.HorizontalPrecision / 100).ToString(), horizontalPrecisionValue); Assert.AreEqual(GetPrecisionValueString(locData.HorizontalPrecision), horizontalPrecisionValue);
break; break;
case "dns.loc.vertial_precision": case "dns.loc.vertial_precision":
Assert.AreEqual(0, locData.Version); Assert.AreEqual(0, locData.Version);
string verticalPrecisionValue = dataField.Showname().Split(new[] {'(', ')'})[1]; string verticalPrecisionValue = dataField.Showname().Split(new[] {'(', ')'})[1];
Assert.AreEqual((locData.VerticalPrecision / 100).ToString(), verticalPrecisionValue); Assert.AreEqual(GetPrecisionValueString(locData.VerticalPrecision), verticalPrecisionValue);
break; break;
case "dns.loc.latitude": case "dns.loc.latitude":
...@@ -1077,19 +1084,26 @@ namespace PcapDotNet.Core.Test ...@@ -1077,19 +1084,26 @@ namespace PcapDotNet.Core.Test
case "dns.opt": case "dns.opt":
foreach (XElement subfield in dataField.Fields()) foreach (XElement subfield in dataField.Fields())
{ {
subfield.AssertNoFields();
DnsOption dnsOption = optData.Options.Options[_optOptionIndex]; DnsOption dnsOption = optData.Options.Options[_optOptionIndex];
var clientSubnet = dnsOption as DnsOptionClientSubnet;
switch (subfield.Name()) switch (subfield.Name())
{ {
case "dns.opt.code": case "dns.opt.code":
subfield.AssertNoFields();
subfield.AssertShowDecimal((ushort)dnsOption.Code); subfield.AssertShowDecimal((ushort)dnsOption.Code);
break; break;
case "dns.opt.len": case "dns.opt.len":
subfield.AssertShowDecimal(dnsOption.DataLength); subfield.AssertShowDecimal(dnsOption.DataLength);
if (subfield.Fields().Any())
{
Assert.AreEqual(1, subfield.Fields().Count());
subfield.Fields().First().AssertName("_ws.expert");
}
break; break;
case "dns.opt.data": case "dns.opt.data":
subfield.AssertNoFields();
switch (dnsOption.Code) switch (dnsOption.Code)
{ {
case DnsOptionCode.UpdateLease: case DnsOptionCode.UpdateLease:
...@@ -1097,22 +1111,64 @@ namespace PcapDotNet.Core.Test ...@@ -1097,22 +1111,64 @@ namespace PcapDotNet.Core.Test
break; break;
case DnsOptionCode.LongLivedQuery: case DnsOptionCode.LongLivedQuery:
byte[] expectedLongLivedQueryValue = byte[] expectedLongLivedQueryValue = new byte[dnsOption.DataLength];
new byte[sizeof(ushort) + sizeof(ushort) + sizeof(ushort) + sizeof(ulong) + sizeof(uint)];
var longLivedQuery = (DnsOptionLongLivedQuery)dnsOption; var longLivedQuery = (DnsOptionLongLivedQuery)dnsOption;
int offset = 0; int longLivedQueryOffset = 0;
expectedLongLivedQueryValue.Write(ref offset, longLivedQuery.Version, Endianity.Big); expectedLongLivedQueryValue.Write(ref longLivedQueryOffset, longLivedQuery.Version, Endianity.Big);
expectedLongLivedQueryValue.Write(ref offset, (ushort)longLivedQuery.OpCode, Endianity.Big); expectedLongLivedQueryValue.Write(ref longLivedQueryOffset, (ushort)longLivedQuery.OpCode, Endianity.Big);
expectedLongLivedQueryValue.Write(ref offset, (ushort)longLivedQuery.ErrorCode, Endianity.Big); expectedLongLivedQueryValue.Write(ref longLivedQueryOffset, (ushort)longLivedQuery.ErrorCode, Endianity.Big);
expectedLongLivedQueryValue.Write(ref offset, longLivedQuery.Id, Endianity.Big); expectedLongLivedQueryValue.Write(ref longLivedQueryOffset, longLivedQuery.Id, Endianity.Big);
expectedLongLivedQueryValue.Write(ref offset, longLivedQuery.LeaseLife, Endianity.Big); expectedLongLivedQueryValue.Write(ref longLivedQueryOffset, longLivedQuery.LeaseLife, Endianity.Big);
subfield.AssertValue(expectedLongLivedQueryValue); subfield.AssertValue(expectedLongLivedQueryValue);
break; break;
case DnsOptionCode.ClientSubnet:
byte[] expectedClientSubnetValue = new byte[dnsOption.DataLength];
int clientSubnetOffset = 0;
expectedClientSubnetValue.Write(ref clientSubnetOffset, (ushort)clientSubnet.Family, Endianity.Big);
expectedClientSubnetValue.Write(ref clientSubnetOffset, clientSubnet.SourceNetmask);
expectedClientSubnetValue.Write(ref clientSubnetOffset, clientSubnet.ScopeNetmask);
expectedClientSubnetValue.Write(ref clientSubnetOffset, clientSubnet.Address);
subfield.AssertValue(expectedClientSubnetValue);
break;
default: default:
subfield.AssertValue(((DnsOptionAnything)dnsOption).Data); subfield.AssertValue(((DnsOptionAnything)dnsOption).Data);
break; break;
} }
if (dnsOption.Code != DnsOptionCode.ClientSubnet)
++_optOptionIndex;
break;
case "dns.opt.client.family":
subfield.AssertNoFields();
subfield.AssertShowDecimal((ushort)clientSubnet.Family);
break;
case "dns.opt.client.netmask":
subfield.AssertNoFields();
subfield.AssertShowDecimal(clientSubnet.SourceNetmask);
break;
case "dns.opt.client.scope":
subfield.AssertNoFields();
subfield.AssertShowDecimal(clientSubnet.ScopeNetmask);
break;
case "dns.opt.client.addr":
case "dns.opt.client.addr4":
case "dns.opt.client.addr6":
subfield.AssertNoFields();
if (clientSubnet.Address.Length <= 16)
{
subfield.AssertValue(clientSubnet.Address);
}
else
{
subfield.AssertValue(clientSubnet.Address.Take(16));
// TODO: Remove this return when https://bugs.wireshark.org/bugzilla/show_bug.cgi?id=10988 is fixed.
return false;
}
++_optOptionIndex; ++_optOptionIndex;
break; break;
...@@ -1773,16 +1829,13 @@ namespace PcapDotNet.Core.Test ...@@ -1773,16 +1829,13 @@ namespace PcapDotNet.Core.Test
private static string GetPrecisionValueString(ulong value) private static string GetPrecisionValueString(ulong value)
{ {
double resultValue = value / 100.0; double resultValue = value / 100.0;
string valueDescription = " m";
if (resultValue >= 1000000) if (resultValue < 1000000)
{ return resultValue.ToString();
int log = (int)Math.Log10(resultValue);
resultValue /= Math.Pow(10, log);
valueDescription = "e+00" + log + valueDescription;
}
return resultValue + valueDescription; int log = (int)Math.Log10(resultValue);
resultValue /= Math.Pow(10, log);
return resultValue + "e+00" + log;
} }
private int _hipRendezvousServersIndex; private int _hipRendezvousServersIndex;
......
...@@ -37,7 +37,9 @@ namespace PcapDotNet.Core.Test ...@@ -37,7 +37,9 @@ namespace PcapDotNet.Core.Test
break; break;
case "eth.fcs": case "eth.fcs":
field.AssertValue(ethernetDatagram.FrameCheckSequence); // TODO: Support RARP.
if (ethernetDatagram.EtherType != EthernetType.ReverseArp)
field.AssertValue(ethernetDatagram.FrameCheckSequence);
break; break;
case "eth.padding": case "eth.padding":
......
using System; using System;
using System.Text; using System.Text;
using System.Xml.Linq; using System.Xml.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using PcapDotNet.Base; using PcapDotNet.Base;
using PcapDotNet.Packets; using PcapDotNet.Packets;
using PcapDotNet.Packets.Icmp; using PcapDotNet.Packets.Icmp;
using PcapDotNet.Packets.IpV4; using PcapDotNet.Packets.IpV4;
using System.Linq;
namespace PcapDotNet.Core.Test namespace PcapDotNet.Core.Test
{ {
...@@ -42,11 +42,28 @@ namespace PcapDotNet.Core.Test ...@@ -42,11 +42,28 @@ namespace PcapDotNet.Core.Test
break; break;
case "data": case "data":
var casted1 = icmpDatagram as IcmpIpV4PayloadDatagram; var icmpIpV4PayloadDatagram = icmpDatagram as IcmpIpV4PayloadDatagram;
if (casted1 != null) if (icmpIpV4PayloadDatagram != null)
{ {
if (casted1.IpV4.Protocol != IpV4Protocol.IpComp) // TODO: Support IpComp. if (!new[]
field.AssertDataField(casted1.IpV4.Payload); {
IpV4Protocol.IpComp, // TODO: Support IpComp.
IpV4Protocol.Ax25, // TODO: Support Ax25.
IpV4Protocol.FibreChannel, // TODO: Support FibreChannel.
}.Contains(icmpIpV4PayloadDatagram.IpV4.Protocol))
{
if (icmpIpV4PayloadDatagram.IpV4.Protocol == IpV4Protocol.Udp)
{
// Uncomment this when https://bugs.wireshark.org/bugzilla/show_bug.cgi?id=10990 is fixed.
// field.AssertDataField(casted1.IpV4.Udp.Payload);
}
else
{
// TODO: Remove this condition when https://bugs.wireshark.org/bugzilla/show_bug.cgi?id=10991 and https://bugs.wireshark.org/bugzilla/show_bug.cgi?id=10992 are fixed.
if (!(icmpIpV4PayloadDatagram is IcmpParameterProblemDatagram || icmpIpV4PayloadDatagram is IcmpRedirectDatagram))
field.AssertDataField(icmpIpV4PayloadDatagram.IpV4.Payload);
}
}
} }
else else
{ {
......
...@@ -58,11 +58,13 @@ namespace PcapDotNet.Core.Test ...@@ -58,11 +58,13 @@ namespace PcapDotNet.Core.Test
break; break;
case "ip.flags.df": case "ip.flags.df":
subfield.AssertShowDecimal((ipV4Datagram.Fragmentation.Options & IpV4FragmentationOptions.DoNotFragment) == IpV4FragmentationOptions.DoNotFragment); subfield.AssertShowDecimal((ipV4Datagram.Fragmentation.Options & IpV4FragmentationOptions.DoNotFragment) ==
IpV4FragmentationOptions.DoNotFragment);
break; break;
case "ip.flags.mf": case "ip.flags.mf":
subfield.AssertShowDecimal((ipV4Datagram.Fragmentation.Options & IpV4FragmentationOptions.MoreFragments) == IpV4FragmentationOptions.MoreFragments); subfield.AssertShowDecimal((ipV4Datagram.Fragmentation.Options & IpV4FragmentationOptions.MoreFragments) ==
IpV4FragmentationOptions.MoreFragments);
break; break;
default: default:
...@@ -137,16 +139,20 @@ namespace PcapDotNet.Core.Test ...@@ -137,16 +139,20 @@ namespace PcapDotNet.Core.Test
case "ip.dst": case "ip.dst":
case "ip.dst_host": case "ip.dst_host":
// TODO: Remove this condition when https://bugs.wireshark.org/bugzilla/show_bug.cgi?id=10959 is fixed or (worst case) when MTU Reply option is supported. // TODO: Remove this condition when https://bugs.wireshark.org/bugzilla/show_bug.cgi?id=10959 is fixed or (worst case) when MTU Reply and CommercialSecurity options are supported.
if (ipV4Datagram.Options == null || !ipV4Datagram.Options.Any(option => option.OptionType == IpV4OptionType.MaximumTransmissionUnitReply)) if (ipV4Datagram.Options == null || !ipV4Datagram.Options.Any(option => option.OptionType == IpV4OptionType.MaximumTransmissionUnitReply ||
option.OptionType == IpV4OptionType.CommercialSecurity))
{
field.AssertShow(ipV4Datagram.Destination.ToString()); field.AssertShow(ipV4Datagram.Destination.ToString());
}
field.AssertNoFields(); field.AssertNoFields();
break; break;
case "ip.addr": case "ip.addr":
case "ip.host": case "ip.host":
// TODO: Remove this condition when https://bugs.wireshark.org/bugzilla/show_bug.cgi?id=10959 is fixed or (worst case) when MTU Reply option is supported. // TODO: Remove this condition when https://bugs.wireshark.org/bugzilla/show_bug.cgi?id=10959 is fixed or (worst case) when MTU Reply and CommercialSecurity options are supported.
if (ipV4Datagram.Options == null || !ipV4Datagram.Options.Any(option => option.OptionType == IpV4OptionType.MaximumTransmissionUnitReply)) if (ipV4Datagram.Options == null || !ipV4Datagram.Options.Any(option => option.OptionType == IpV4OptionType.MaximumTransmissionUnitReply ||
option.OptionType == IpV4OptionType.CommercialSecurity))
{ {
Assert.IsTrue(field.Show() == ipV4Datagram.Source.ToString() || Assert.IsTrue(field.Show() == ipV4Datagram.Source.ToString() ||
field.Show() == ipV4Datagram.Destination.ToString()); field.Show() == ipV4Datagram.Destination.ToString());
...@@ -184,7 +190,7 @@ namespace PcapDotNet.Core.Test ...@@ -184,7 +190,7 @@ namespace PcapDotNet.Core.Test
field.Show().StartsWith("Unknown") || field.Show().StartsWith("Unknown") ||
field.Show().StartsWith("Security") || field.Show().StartsWith("Security") ||
field.Show().StartsWith("Router Alert (with option length = ") || field.Show().StartsWith("Router Alert (with option length = ") ||
field.Show().StartsWith("Stream identifier (with option length = ") || field.Show().StartsWith("Stream ID (with option length = ") ||
field.Show().Contains("with too") || field.Show().Contains("with too") ||
field.Show().Contains(" bytes says option goes past end of options") || field.Show().Contains(" bytes says option goes past end of options") ||
field.Show().Contains("(length byte past end of options)") || field.Show().Contains("(length byte past end of options)") ||
......
...@@ -103,14 +103,12 @@ namespace PcapDotNet.Core.Test ...@@ -103,14 +103,12 @@ namespace PcapDotNet.Core.Test
{ {
Assert.IsFalse(ipV6Datagram.ExtensionHeaders.IsValid); Assert.IsFalse(ipV6Datagram.ExtensionHeaders.IsValid);
int maxLength = ipV6Datagram.Length - IpV6Datagram.HeaderLength - ipV6Datagram.ExtensionHeaders.BytesLength; int maxLength = ipV6Datagram.Length - IpV6Datagram.HeaderLength - ipV6Datagram.ExtensionHeaders.BytesLength;
if (field.Fields().Any(subfield => subfield.Name() == "")) if (field.Fields().Any(subfield => subfield.Name() == "ipv6.opt.length"))
{ {
int length = int.Parse( int length = int.Parse(field.Fields().First(subfield => subfield.Name() == "ipv6.opt.length").Show());
field.Fields().Where(subfield => subfield.Name() == "" && subfield.Show().StartsWith("Length:")).Select(
subfield => subfield.Show().Split(new[] {':', '(', ' '}, StringSplitOptions.RemoveEmptyEntries)[2]).First());
MoreAssert.IsBigger(maxLength, length); MoreAssert.IsBigger(maxLength, length);
} else }
else
{ {
Assert.AreEqual(6, maxLength); Assert.AreEqual(6, maxLength);
} }
......
...@@ -265,6 +265,7 @@ namespace PcapDotNet.Core.Test ...@@ -265,6 +265,7 @@ namespace PcapDotNet.Core.Test
field.Show().StartsWith("Unknown (0x09) ") || // Unknown in Wireshark but known (and invalid) in Pcap.Net. field.Show().StartsWith("Unknown (0x09) ") || // Unknown in Wireshark but known (and invalid) in Pcap.Net.
field.Show().StartsWith("Unknown (0x0a) ") || // Unknown in Wireshark but known (and invalid) in Pcap.Net. field.Show().StartsWith("Unknown (0x0a) ") || // Unknown in Wireshark but known (and invalid) in Pcap.Net.
field.Show().StartsWith("Unknown (0x19) ") || // Unknown in Wireshark but known (and invalid) in Pcap.Net. field.Show().StartsWith("Unknown (0x19) ") || // Unknown in Wireshark but known (and invalid) in Pcap.Net.
field.Show().StartsWith("Unknown (0x2d) ") || // Unknown in Wireshark and unknown and invalid in Pcap.Net.
field.Show().StartsWith("Echo reply (with option length = ") || field.Show().StartsWith("Echo reply (with option length = ") ||
field.Show().Contains("bytes says option goes past end of options") || field.Show().Contains("bytes says option goes past end of options") ||
field.Show().Contains(") (with too-short option length = ") || field.Show().Contains(") (with too-short option length = ") ||
......
...@@ -48,15 +48,32 @@ namespace PcapDotNet.Core.Test ...@@ -48,15 +48,32 @@ namespace PcapDotNet.Core.Test
field.AssertNoFields(); field.AssertNoFields();
if (!new[] if (!new[]
{ {
(EthernetType)1, (EthernetType)5, (EthernetType)17, (EthernetType)29, (EthernetType)30, (EthernetType)43, (EthernetType)50, EthernetType.ReverseArp, (EthernetType)1,
(EthernetType)5,
(EthernetType)17,
(EthernetType)29,
(EthernetType)30,
(EthernetType)43,
(EthernetType)50,
EthernetType.ReverseArp, // TODO: Support RARP
EthernetType.ExtensibleAuthenticationProtocolOverLan, // TODO: Support this protocol.
}.Contains( }.Contains(
vLanTaggedFrameDatagram.EtherType)) vLanTaggedFrameDatagram.EtherType))
{
field.AssertValue(vLanTaggedFrameDatagram.ExtraData); field.AssertValue(vLanTaggedFrameDatagram.ExtraData);
}
break; break;
case "eth.padding": case "eth.padding":
field.AssertNoFields(); field.AssertNoFields();
field.AssertValue(vLanTaggedFrameDatagram.Trailer); if (!new[]
{
EthernetType.ExtensibleAuthenticationProtocolOverLan, // TODO: Support this protocol.
}.Contains(
vLanTaggedFrameDatagram.EtherType))
{
field.AssertValue(vLanTaggedFrameDatagram.Trailer);
}
break; break;
default: default:
......
...@@ -94,6 +94,9 @@ namespace PcapDotNet.Packets.TestUtils ...@@ -94,6 +94,9 @@ namespace PcapDotNet.Packets.TestUtils
case DnsOptionCode.NameServerIdentifier: case DnsOptionCode.NameServerIdentifier:
return new DnsOptionAnything(DnsOptionCode.NameServerIdentifier, random.NextDataSegment(random.NextInt(0, 100))); return new DnsOptionAnything(DnsOptionCode.NameServerIdentifier, random.NextDataSegment(random.NextInt(0, 100)));
case DnsOptionCode.ClientSubnet:
return new DnsOptionClientSubnet(random.NextEnum<AddressFamily>(), random.NextByte(), random.NextByte(), random.NextDataSegment(random.NextInt(0, 50)));
default: default:
throw new InvalidOperationException("Invalid value"); throw new InvalidOperationException("Invalid value");
} }
......
...@@ -75,11 +75,12 @@ namespace PcapDotNet.Packets.TestUtils ...@@ -75,11 +75,12 @@ namespace PcapDotNet.Packets.TestUtils
if (maximumOptionLength >= IpV4OptionUnknown.OptionMinimumLength && random.Next(100) > 90) if (maximumOptionLength >= IpV4OptionUnknown.OptionMinimumLength && random.Next(100) > 90)
return random.NextIpV4OptionUnknown(maximumOptionLength); return random.NextIpV4OptionUnknown(maximumOptionLength);
// TODO: Support MTU Probe and MTU Reply. // TODO: Support MTU Probe, MTU Reply and CommercialSecurity.
List<IpV4OptionType> impossibleOptionTypes = new List<IpV4OptionType> List<IpV4OptionType> impossibleOptionTypes = new List<IpV4OptionType>
{ {
IpV4OptionType.MaximumTransmissionUnitProbe, IpV4OptionType.MaximumTransmissionUnitProbe,
IpV4OptionType.MaximumTransmissionUnitReply IpV4OptionType.MaximumTransmissionUnitReply,
IpV4OptionType.CommercialSecurity,
}; };
if (maximumOptionLength < IpV4OptionBasicSecurity.OptionMinimumLength) if (maximumOptionLength < IpV4OptionBasicSecurity.OptionMinimumLength)
impossibleOptionTypes.Add(IpV4OptionType.BasicSecurity); impossibleOptionTypes.Add(IpV4OptionType.BasicSecurity);
......
...@@ -83,6 +83,9 @@ namespace PcapDotNet.Packets.Dns ...@@ -83,6 +83,9 @@ namespace PcapDotNet.Packets.Dns
case DnsOptionCode.UpdateLease: case DnsOptionCode.UpdateLease:
return DnsOptionUpdateLease.Read(data); return DnsOptionUpdateLease.Read(data);
case DnsOptionCode.ClientSubnet:
return DnsOptionClientSubnet.Read(data);
case DnsOptionCode.NameServerIdentifier: case DnsOptionCode.NameServerIdentifier:
default: default:
return new DnsOptionAnything(code, data); return new DnsOptionAnything(code, data);
......
using PcapDotNet.Base;
namespace PcapDotNet.Packets.Dns
{
/// <summary>
/// https://tools.ietf.org/html/draft-ietf-dnsop-edns-client-subnet
/// <pre>
/// +-----+----------------+---------------+
/// | bit | 0-7 | 8-15 |
/// +-----+----------------+---------------+
/// | 0 | FAMILY |
/// +-----+----------------+---------------+
/// | 16 | SOURCE NETMASK | SCOPE NETMASK |
/// +-----+----------------+---------------+
/// | 32 | ADDRESS |
/// | ... | |
/// +-----+--------------------------------+
/// </pre>
/// </summary>
public sealed class DnsOptionClientSubnet : DnsOption
{
private static class Offset
{
public const int Family = 0;
public const int SourceNetmask = Family + sizeof(ushort);
public const int ScopeNetmask = SourceNetmask + sizeof(byte);
public const int Address = ScopeNetmask + sizeof(byte);
}
/// <summary>
/// The minimum number of bytes this option data can take.
/// </summary>
public const int MininmumDataLength = Offset.Address;
public DnsOptionClientSubnet(AddressFamily family, byte sourceMask, byte scopeNetmask, DataSegment address)
: base(DnsOptionCode.ClientSubnet)
{
Family = family;
SourceNetmask = sourceMask;
ScopeNetmask = scopeNetmask;
Address = address;
}
/// <summary>
/// Indicates the family of the address contained in the option.
/// </summary>
public AddressFamily Family { get; private set; }
/// <summary>
/// Representing the length of the netmask pertaining to the query.
/// In replies, it mirrors the same value as in the requests.
/// It can be set to 0 to disable client-based lookups, in which case the Address field must be absent.
/// </summary>
public byte SourceNetmask { get; private set; }
/// <summary>
/// Representing the length of the netmask pertaining to the reply.
/// In requests, it should be set to the longest cacheable length supported by the Intermediate Nameserver.
/// In requests it may be set to 0 to have the Authoritative Nameserver treat the longest cacheable length as the SourceNetmask length.
/// In responses, this field is set by the Authoritative Nameserver to indicate the coverage of the response.
/// It might or might not match SourceNetmask; it could be shorter or longer.
/// </summary>
public byte ScopeNetmask { get; private set; }
/// <summary>
/// Contains either an IPv4 or IPv6 address, depending on Family, truncated in the request to the number of bits indicated by the Source Netmask field,
/// with bits set to 0 to pad up to the end of the last octet used. (This need not be as many octets as a complete address would take.)
/// In the reply, if the ScopeNetmask of the request was 0 then Address must contain the same octets as in the request.
/// Otherwise, the bits for Address will be significant through the maximum of the SouceNetmask or ScopeNetmask, and 0 filled to the end of an octet.
/// </summary>
public DataSegment Address { get; private set; }
/// <summary>
/// The number of bytes the option data takes.
/// </summary>
public override int DataLength
{
get { return MininmumDataLength + Address.Length; }
}
internal override bool EqualsData(DnsOption other)
{
return EqualsData(other as DnsOptionClientSubnet);
}
internal override int DataGetHashCode()
{
return Sequence.GetHashCode(BitSequence.Merge((ushort)Family, SourceNetmask, ScopeNetmask), Address);
}
internal override void WriteData(byte[] buffer, ref int offset)
{
buffer.Write(ref offset, (ushort)Family, Endianity.Big);
buffer.Write(ref offset, SourceNetmask);
buffer.Write(ref offset, ScopeNetmask);
buffer.Write(ref offset, Address);
}
internal static DnsOptionClientSubnet Read(DataSegment data)
{
if (data.Length < MininmumDataLength)
return null;
AddressFamily family = (AddressFamily)data.ReadUShort(Offset.Family, Endianity.Big);
byte sourceNetmask = data[Offset.SourceNetmask];
byte scopeNetmask = data[Offset.ScopeNetmask];
DataSegment address = data.Subsegment(Offset.Address, data.Length - Offset.Address);
return new DnsOptionClientSubnet(family, sourceNetmask, scopeNetmask, address);
}
private bool EqualsData(DnsOptionClientSubnet other)
{
return other != null &&
Family.Equals(other.Family) &&
SourceNetmask.Equals(other.SourceNetmask) &&
ScopeNetmask.Equals(other.ScopeNetmask) &&
Address.Equals(other.Address);
}
}
}
\ No newline at end of file
...@@ -28,5 +28,10 @@ ...@@ -28,5 +28,10 @@
/// NSID. /// NSID.
/// </summary> /// </summary>
NameServerIdentifier = 3, NameServerIdentifier = 3,
/// <summary>
/// https://tools.ietf.org/html/draft-ietf-dnsop-edns-client-subnet
/// </summary>
ClientSubnet = 8,
} }
} }
\ No newline at end of file
...@@ -18,9 +18,18 @@ ...@@ -18,9 +18,18 @@
public const int ConstDataLength = sizeof(int); public const int ConstDataLength = sizeof(int);
/// <summary> /// <summary>
/// Builds /// Builds an instance from a least value.
/// </summary> /// </summary>
/// <param name="lease"></param> /// <param name="lease">
/// Indicating the lease life, in seconds, desired by the client.
/// In Update Responses, this field contains the actual lease granted by the server.
/// Note that the lease granted by the server may be less than, greater than, or equal to the value requested by the client.
/// To reduce network and server load, a minimum lease of 30 minutes (1800 seconds) is recommended.
/// Note that leases are expected to be sufficiently long as to make timer discrepancies (due to transmission latency, etc.)
/// between a client and server negligible.
/// Clients that expect the updated records to be relatively static may request appropriately longer leases.
/// Servers may grant relatively longer or shorter leases to reduce network traffic due to refreshes, or reduce stale data, respectively.
/// </param>
public DnsOptionUpdateLease(int lease) public DnsOptionUpdateLease(int lease)
: base(DnsOptionCode.UpdateLease) : base(DnsOptionCode.UpdateLease)
{ {
......
...@@ -30,7 +30,11 @@ namespace PcapDotNet.Packets.Icmp ...@@ -30,7 +30,11 @@ namespace PcapDotNet.Packets.Icmp
get get
{ {
if (_ipV4 == null && Length >= HeaderLength) if (_ipV4 == null && Length >= HeaderLength)
_ipV4 = new IpV4Datagram(Buffer, StartOffset + HeaderLength, IpV4Length); {
_ipV4 = new IpV4Datagram(Buffer, StartOffset + HeaderLength, Length - HeaderLength);
// TODO: Do this processing without recreating the datagram again.
ProcessIpV4Payload(ref _ipV4);
}
return _ipV4; return _ipV4;
} }
} }
...@@ -48,7 +52,9 @@ namespace PcapDotNet.Packets.Icmp ...@@ -48,7 +52,9 @@ namespace PcapDotNet.Packets.Icmp
return (ip.Length >= IpV4Datagram.HeaderMinimumLength && ip.Length >= ip.HeaderLength); return (ip.Length >= IpV4Datagram.HeaderMinimumLength && ip.Length >= ip.HeaderLength);
} }
internal virtual int IpV4Length { get { return Length - HeaderLength; } } internal virtual void ProcessIpV4Payload(ref IpV4Datagram ipV4)
{
}
private IpV4Datagram _ipV4; private IpV4Datagram _ipV4;
} }
......
using System; using System;
using PcapDotNet.Packets.IpV4;
namespace PcapDotNet.Packets.Icmp namespace PcapDotNet.Packets.Icmp
{ {
...@@ -65,7 +66,7 @@ namespace PcapDotNet.Packets.Icmp ...@@ -65,7 +66,7 @@ namespace PcapDotNet.Packets.Icmp
/// </summary> /// </summary>
protected override bool CalculateIsValid() protected override bool CalculateIsValid()
{ {
return base.CalculateIsValid() && Pointer < IpV4.Length && OriginalDatagramLength == IpV4.Length; return base.CalculateIsValid() && Pointer < IpV4.Length && OriginalDatagramLength == IpV4.Payload.Length;
} }
internal override IcmpDatagram CreateInstance(byte[] buffer, int offset, int length) internal override IcmpDatagram CreateInstance(byte[] buffer, int offset, int length)
...@@ -73,9 +74,10 @@ namespace PcapDotNet.Packets.Icmp ...@@ -73,9 +74,10 @@ namespace PcapDotNet.Packets.Icmp
return new IcmpParameterProblemDatagram(buffer, offset, length); return new IcmpParameterProblemDatagram(buffer, offset, length);
} }
internal override int IpV4Length internal override void ProcessIpV4Payload(ref IpV4Datagram ipV4)
{ {
get { return Math.Min(Length - HeaderLength, OriginalDatagramLength); } if (ipV4.Payload.Length > OriginalDatagramLength)
ipV4 = new IpV4Datagram(ipV4.Buffer, ipV4.StartOffset, ipV4.HeaderLength + OriginalDatagramLength);
} }
private IcmpParameterProblemDatagram(byte[] buffer, int offset, int length) private IcmpParameterProblemDatagram(byte[] buffer, int offset, int length)
......
...@@ -104,6 +104,12 @@ namespace PcapDotNet.Packets.IpV4 ...@@ -104,6 +104,12 @@ namespace PcapDotNet.Packets.IpV4
/// </summary> /// </summary>
LooseSourceRouting = 131, LooseSourceRouting = 131,
/// <summary>
/// http://tools.ietf.org/html/draft-ietf-cipso-ipsecurity
/// CIPSO - Commercial Security.
/// </summary>
CommercialSecurity = 134,
/// <summary> /// <summary>
/// Strict Source Routing. /// Strict Source Routing.
/// Used to route the internet datagram based on information supplied by the source. /// Used to route the internet datagram based on information supplied by the source.
......
...@@ -128,6 +128,7 @@ ...@@ -128,6 +128,7 @@
<Compile Include="Dns\ResourceData\DnsLongLivedQueryErrorCode.cs" /> <Compile Include="Dns\ResourceData\DnsLongLivedQueryErrorCode.cs" />
<Compile Include="Dns\ResourceData\DnsLongLivedQueryOpcode.cs" /> <Compile Include="Dns\ResourceData\DnsLongLivedQueryOpcode.cs" />
<Compile Include="Dns\ResourceData\DnsOption.cs" /> <Compile Include="Dns\ResourceData\DnsOption.cs" />
<Compile Include="Dns\ResourceData\DnsOptionClientSubnet.cs" />
<Compile Include="Dns\ResourceData\DnsOptionCode.cs" /> <Compile Include="Dns\ResourceData\DnsOptionCode.cs" />
<Compile Include="Dns\ResourceData\DnsOptionLongLivedQuery.cs" /> <Compile Include="Dns\ResourceData\DnsOptionLongLivedQuery.cs" />
<Compile Include="Dns\ResourceData\DnsOptions.cs" /> <Compile Include="Dns\ResourceData\DnsOptions.cs" />
......
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