Commit b2ce6613 authored by Brickner_cp's avatar Brickner_cp

ICMP

parent 66338447
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using PcapDotNet.Base;
using PcapDotNet.Packets.Ethernet;
using PcapDotNet.Packets.Icmp;
using PcapDotNet.Packets.Igmp;
using PcapDotNet.Packets.IpV4;
using PcapDotNet.Packets.TestUtils;
using PcapDotNet.TestUtils;
namespace PcapDotNet.Packets.Test
{
/// <summary>
/// Summary description for IcmpTests
/// </summary>
[TestClass]
public class IcmpTests
{
public IcmpTests()
{
//
// TODO: Add constructor logic here
//
}
private TestContext testContextInstance;
/// <summary>
/// Gets or sets the test context which provides
/// information about and functionality for the current test run.
/// </summary>
public TestContext TestContext
{
get
{
return testContextInstance;
}
set
{
testContextInstance = value;
}
}
#region Additional test attributes
//
// You can use the following additional attributes as you write your tests:
//
// Use ClassInitialize to run code before running the first test in the class
// [ClassInitialize()]
// public static void MyClassInitialize(TestContext testContext) { }
//
// Use ClassCleanup to run code after all tests in a class have run
// [ClassCleanup()]
// public static void MyClassCleanup() { }
//
// Use TestInitialize to run code before running each test
// [TestInitialize()]
// public void MyTestInitialize() { }
//
// Use TestCleanup to run code after each test has run
// [TestCleanup()]
// public void MyTestCleanup() { }
//
#endregion
[TestMethod]
public void RandomIcmpTest()
{
MacAddress ethernetSource = new MacAddress("00:01:02:03:04:05");
MacAddress ethernetDestination = new MacAddress("A0:A1:A2:A3:A4:A5");
Random random = new Random();
byte ipV4TypeOfService = random.NextByte();
ushort ipV4Identification = random.NextUShort();
byte ipV4Ttl = random.NextByte();
IpV4Fragmentation ipV4Fragmentation = random.NextIpV4Fragmentation();
IpV4Address ipV4Source = new IpV4Address(random.NextUInt());
IpV4Address ipV4Destination = new IpV4Address(random.NextUInt());
IpV4Options ipV4Options = random.NextIpV4Options();
for (int i = 0; i != 1000; ++i)
{
IcmpMessageType icmpMessageType = random.NextEnum<IcmpMessageType>();
Packet packet;
switch (icmpMessageType)
{
case IcmpMessageType.DestinationUnreachable:
IcmpCodeDestinationUnrechable code = random.NextEnum<IcmpCodeDestinationUnrechable>();
byte icmpIpV4TypeOfService = random.NextByte();
ushort icmpIpV4Identification = random.NextUShort();
byte icmpIpV4Ttl = random.NextByte();
IpV4Fragmentation icmpIpV4Fragmentation = random.NextIpV4Fragmentation();
IpV4Protocol icmpIpV4Protocol = random.NextEnum<IpV4Protocol>();
IpV4Address icmpIpV4Source = new IpV4Address(random.NextUInt());
IpV4Address icmpIpV4Destination = new IpV4Address(random.NextUInt());
IpV4Options icmpIpV4Options = random.NextIpV4Options();
Datagram icmpIpV4Payload = random.NextDatagram(random.Next(200));
packet = PacketBuilder.EthernetIpV4IcmpDestinationUnreachable(DateTime.Now,
ethernetSource, ethernetDestination,
ipV4TypeOfService, ipV4Identification, ipV4Fragmentation,
ipV4Ttl,
ipV4Source, ipV4Destination, ipV4Options,
code,
icmpIpV4TypeOfService, icmpIpV4Identification,
icmpIpV4Fragmentation,
icmpIpV4Ttl, icmpIpV4Protocol, icmpIpV4Source,
icmpIpV4Destination,
icmpIpV4Options, icmpIpV4Payload);
break;
default:
throw new InvalidOperationException("Invalid icmpMessageType " + icmpMessageType);
}
Assert.IsTrue(packet.IsValid, "IsValid");
}
}
}
}
\ No newline at end of file
......@@ -13,7 +13,7 @@ using PcapDotNet.TestUtils;
namespace PcapDotNet.Packets.Test
{
/// <summary>
/// Summary description for UdpTests
/// Summary description for IgmpTests
/// </summary>
[TestClass]
public class IgmpTests
......
......@@ -49,6 +49,7 @@
<Compile Include="DataLinkTests.cs" />
<Compile Include="EndianitiyTests.cs" />
<Compile Include="EthernetTests.cs" />
<Compile Include="IcmpTests.cs" />
<Compile Include="IgmpTests.cs" />
<Compile Include="IpV4Tests.cs" />
<Compile Include="MacAddressTests.cs" />
......
......@@ -34,9 +34,9 @@ namespace PcapDotNet.Packets.Icmp
/// <summary>
/// The value of this field determines the format of the remaining data.
/// </summary>
public IcmpType Type
public IcmpMessageType MessageType
{
get { return (IcmpType)this[Offset.Type]; }
get { return (IcmpMessageType)this[Offset.Type]; }
}
public byte Code
......@@ -44,9 +44,9 @@ namespace PcapDotNet.Packets.Icmp
get { return this[Offset.Code]; }
}
public IcmpTypeAndCode TypeAndCode
public IcmpMessageTypeAndCode MessageTypeAndCode
{
get { return (IcmpTypeAndCode)ReadUShort(Offset.Type, Endianity.Big); }
get { return (IcmpMessageTypeAndCode)ReadUShort(Offset.Type, Endianity.Big); }
}
/// <summary>
......@@ -223,12 +223,26 @@ namespace PcapDotNet.Packets.Icmp
{
}
internal static void WriteHeader(byte[] buffer, int offset,
IcmpMessageType messageType, byte code, uint valueAccordingToType)
{
buffer.Write(offset + Offset.Type, (byte)messageType);
buffer.Write(offset + Offset.Code, code);
buffer.Write(offset + Offset.Variable, valueAccordingToType, Endianity.Big);
}
internal static void WriteChecksum(byte[] buffer, int offset, int length)
{
ushort checksum = CalculateChecksum(buffer, offset, length);
buffer.Write(offset + Offset.Checksum, checksum, Endianity.Big);
}
protected override bool CalculateIsValid()
{
if (Length < HeaderLength || !IsChecksumCorrect)
return false;
switch (Type)
switch (MessageType)
{
default:
return false;
......@@ -237,8 +251,13 @@ namespace PcapDotNet.Packets.Icmp
private ushort CalculateChecksum()
{
uint sum = Sum16Bits(Buffer, StartOffset, Math.Min(Offset.Checksum, Length)) +
Sum16Bits(Buffer, StartOffset + Offset.Checksum + sizeof(ushort), Length - Offset.Checksum - sizeof(ushort));
return CalculateChecksum(Buffer, StartOffset, Length);
}
private static ushort CalculateChecksum(byte[] buffer, int offset, int length)
{
uint sum = Sum16Bits(buffer, offset, Math.Min(Offset.Checksum, length)) +
Sum16Bits(buffer, offset + Offset.Checksum + sizeof(ushort), length - Offset.Checksum - sizeof(ushort));
return Sum16BitsToChecksum(sum);
}
......
namespace PcapDotNet.Packets.Icmp
{
public enum IcmpType : byte
public enum IcmpMessageType : byte
{
/// <summary>
/// RFC 792
......
namespace PcapDotNet.Packets.Icmp
{
public enum IcmpTypeAndCode : ushort
/// <summary>
/// RFC 792.
/// </summary>
public enum IcmpCodeDestinationUnrechable : byte
{
/// <summary>
/// If, according to the information in the gateway's routing tables,
/// the network specified in the internet destination field of a datagram is unreachable,
/// e.g., the distance to the network is infinity,
/// the gateway may send a destination unreachable message to the internet source host of the datagram.
/// </summary>
DestinationUnreachableNetUnreachable = 0x00,
/// <summary>
/// RFC 792.
/// In some networks, the gateway may be able to determine if the internet destination host is unreachable.
/// Gateways in these networks may send destination unreachable messages to the source host when the destination host is unreachable.
/// </summary>
DestinationUnreachableHostUnreachable = 0x01,
/// <summary>
/// RFC 792.
/// If, in the destination host, the IP module cannot deliver the datagram because the indicated protocol module is not active,
/// the destination host may send a destination unreachable message to the source host.
/// </summary>
DestinationUnreachableProtocolUnreachable = 0x02,
/// <summary>
/// RFC 792.
/// If, in the destination host, the IP module cannot deliver the datagram because the indicated process port is not active,
/// the destination host may send a destination unreachable message to the source host.
/// </summary>
DestinationUnreachablePortUnreachable = 0x03,
/// <summary>
/// RFC 792.
/// A datagram must be fragmented to be forwarded by a gateway yet the Don't Fragment flag is on.
/// In this case the gateway must discard the datagram and may return a destination unreachable message.
/// </summary>
DestinationUnreachableFragmentationNeededAndDontFragmentSet = 0x04,
/// <summary>
/// RFC 792.
/// </summary>
DestinationUnreachableSourceRouteFailed = 0x05,
}
public enum IcmpMessageTypeAndCode : ushort
{
/// <summary>
/// RFC 792.
......
......@@ -2,6 +2,7 @@
using System.Collections;
using System.Linq;
using System.Text;
using PcapDotNet.Packets.Icmp;
using PcapDotNet.Packets.Igmp;
using PcapDotNet.Packets.Transport;
......@@ -213,6 +214,17 @@ namespace PcapDotNet.Packets.IpV4
get { return Tcp; }
}
public IcmpDatagram Icmp
{
get
{
if (_icmp == null && Length >= HeaderLength)
_icmp = new IcmpDatagram(Buffer, StartOffset + HeaderLength, Length - HeaderLength);
return _icmp;
}
}
/// <summary>
/// The payload of the datagram as an IGMP datagram.
/// </summary>
......@@ -369,6 +381,7 @@ namespace PcapDotNet.Packets.IpV4
private bool? _isHeaderChecksumCorrect;
private bool? _isTransportChecksumCorrect;
private IpV4Options _options;
private IcmpDatagram _icmp;
private IgmpDatagram _igmp;
private TcpDatagram _tcp;
private UdpDatagram _udp;
......
......@@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Linq;
using PcapDotNet.Packets.Arp;
using PcapDotNet.Packets.Ethernet;
using PcapDotNet.Packets.Icmp;
using PcapDotNet.Packets.Igmp;
using PcapDotNet.Packets.IpV4;
using PcapDotNet.Packets.Transport;
......@@ -109,6 +110,60 @@ namespace PcapDotNet.Packets
return new Packet(buffer, timestamp, DataLinkKind.Ethernet);
}
/// <summary>
/// Builds an ICMP over IPv4 over Ethernet packet.
/// </summary>
/// <param name="timestamp">The packet timestamp.</param>
/// <param name="ethernetSource">The ethernet source mac address.</param>
/// <param name="ethernetDestination">The ethernet destination mac address.</param>
/// <param name="ipV4TypeOfService">The IPv4 Type of Service.</param>
/// <param name="ipV4Identification">The IPv4 Identification.</param>
/// <param name="ipV4Fragmentation">The IPv4 Fragmentation.</param>
/// <param name="ipV4Ttl">The IPv4 TTL.</param>
/// <param name="ipV4SourceAddress">The IPv4 source address.</param>
/// <param name="ipV4DestinationAddress">The IPv4 destination address.</param>
/// <param name="ipV4Options">The IPv4 options.</param>
/// <returns>A packet with an IPv4 over Ethernet datagram.</returns>
public static Packet EthernetIpV4IcmpDestinationUnreachable(DateTime timestamp,
MacAddress ethernetSource, MacAddress ethernetDestination,
byte ipV4TypeOfService, ushort ipV4Identification,
IpV4Fragmentation ipV4Fragmentation,
byte ipV4Ttl,
IpV4Address ipV4SourceAddress, IpV4Address ipV4DestinationAddress,
IpV4Options ipV4Options,
IcmpCodeDestinationUnrechable icmpCode,
byte icmpIpV4TypeOfService, ushort icmpIpV4Identification,
IpV4Fragmentation icmpIpV4Fragmentation,
byte icmpIpV4Ttl, IpV4Protocol icmpIpV4Protocol,
IpV4Address icmpIpV4SourceAddress, IpV4Address icmpIpV4DestinationAddress,
IpV4Options icmpIpV4Options,
Datagram icmpIpV4Payload)
{
int ipHeaderLength = IpV4Datagram.HeaderMinimumLength + ipV4Options.BytesLength;
int icmpIpHeaderLength = IpV4Datagram.HeaderMinimumLength + icmpIpV4Options.BytesLength;
int ipPayloadLength = IcmpDatagram.HeaderLength + icmpIpHeaderLength + icmpIpV4Payload.Length;
int icmpOffset = EthernetDatagram.HeaderLength + ipHeaderLength;
byte[] buffer = new byte[icmpOffset + ipPayloadLength];
EthernetDatagram.WriteHeader(buffer, 0, ethernetSource, ethernetDestination, EthernetType.IpV4);
IpV4Datagram.WriteHeader(buffer, EthernetDatagram.HeaderLength,
ipV4TypeOfService, ipV4Identification, ipV4Fragmentation,
ipV4Ttl, IpV4Protocol.InternetControlMessageProtocol,
ipV4SourceAddress, ipV4DestinationAddress,
ipV4Options, ipPayloadLength);
IcmpDatagram.WriteHeader(buffer, icmpOffset, IcmpMessageType.DestinationUnreachable, (byte)icmpCode, 0);
IpV4Datagram.WriteHeader(buffer, icmpOffset + IcmpDatagram.HeaderLength,
icmpIpV4TypeOfService, icmpIpV4Identification,
icmpIpV4Fragmentation,
icmpIpV4Ttl, icmpIpV4Protocol,
icmpIpV4SourceAddress, icmpIpV4DestinationAddress,
icmpIpV4Options, icmpIpV4Payload.Length);
icmpIpV4Payload.Write(buffer, icmpOffset + IcmpDatagram.HeaderLength + icmpIpHeaderLength);
IcmpDatagram.WriteChecksum(buffer, icmpOffset, ipPayloadLength);
return new Packet(buffer, timestamp, DataLinkKind.Ethernet);
}
/// <summary>
/// Builds an IGMP query version 1 over IPv4 over Ethernet packet.
/// </summary>
......
......@@ -83,8 +83,8 @@
<Compile Include="Icmp\IcmpSecurityFailuresDatagram.cs" />
<Compile Include="Icmp\IcmpTimestampDatagram.cs" />
<Compile Include="Icmp\IcmpTracerouteDatagram.cs" />
<Compile Include="Icmp\IcmpType.cs" />
<Compile Include="Icmp\IcmpTypeAndCode.cs" />
<Compile Include="Icmp\IcmpMessageType.cs" />
<Compile Include="Icmp\IcmpMessageTypeAndCode.cs" />
<Compile Include="Icmp\IcmpTypedDatagram.cs" />
<Compile Include="IDataLink.cs" />
<Compile Include="Igmp\IgmpDatagram.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