private static void CreateRandomIpV4Payload(Random random, IpV4Layer ipV4Layer, List<ILayer> layers) { if (random.NextBool(20)) { // Finish with payload. PayloadLayer payloadLayer = random.NextPayloadLayer(random.Next(100)); layers.Add(payloadLayer); return; } ipV4Layer.Protocol = null; if (random.NextBool()) ipV4Layer.Fragmentation = IpV4Fragmentation.None; switch (random.Next(0, 9)) { case 0: // IpV4. case 1: IpV4Layer innerIpV4Layer = random.NextIpV4Layer(); layers.Add(innerIpV4Layer); CreateRandomIpV4Payload(random, innerIpV4Layer, layers); return; case 2: // Igmp. layers.Add(random.NextIgmpLayer()); return; case 3: // Icmp. IcmpLayer icmpLayer = random.NextIcmpLayer(); layers.Add(icmpLayer); layers.AddRange(random.NextIcmpPayloadLayers(icmpLayer)); return; case 4: // Gre. GreLayer greLayer = random.NextGreLayer(); layers.Add(greLayer); CreateRandomEthernetPayload(random, greLayer, layers); return; case 5: // Udp. case 6: UdpLayer udpLayer = random.NextUdpLayer(); layers.Add(udpLayer); CreateRandomUdpPayload(random, udpLayer, layers); return; case 7: // Tcp. case 8: TcpLayer tcpLayer = random.NextTcpLayer(); layers.Add(tcpLayer); CreateRandomTcpPayload(random, tcpLayer, layers); return; default: throw new InvalidOperationException("Invalid value."); } }
private static void CreateRandomIpPayload(Random random, Layer ipLayer, List<ILayer> layers) { IpV6Layer ipV6Layer = ipLayer as IpV6Layer; if (ipV6Layer != null) { var headers = ipV6Layer.ExtensionHeaders.Headers; if (headers.Any() && headers.Last().Protocol == IpV4Protocol.EncapsulatingSecurityPayload) return; } if (ipV6Layer != null ? ipV6Layer.LastNextHeader != null : random.NextBool(20)) { // Finish with payload. PayloadLayer payloadLayer = random.NextPayloadLayer(random.Next(100)); layers.Add(payloadLayer); return; } IpV4Layer ipV4Layer = ipLayer as IpV4Layer; if (ipV4Layer != null) { ipV4Layer.Protocol = null; if (random.NextBool()) ipV4Layer.Fragmentation = IpV4Fragmentation.None; } switch (random.Next(0, 11)) { case 0: // IpV4. case 1: IpV4Layer innerIpV4Layer = random.NextIpV4Layer(); layers.Add(innerIpV4Layer); CreateRandomIpPayload(random, innerIpV4Layer, layers); return; case 2: // IpV6. case 3: IpV6Layer innerIpV6Layer = random.NextIpV6Layer(random.NextBool(20)); layers.Add(innerIpV6Layer); CreateRandomIpPayload(random, innerIpV6Layer, layers); return; case 4: // Igmp. layers.Add(random.NextIgmpLayer()); return; case 5: // Icmp. IcmpLayer icmpLayer = random.NextIcmpLayer(); layers.Add(icmpLayer); layers.AddRange(random.NextIcmpPayloadLayers(icmpLayer)); return; case 6: // Gre. GreLayer greLayer = random.NextGreLayer(); layers.Add(greLayer); CreateRandomEthernetPayload(random, greLayer, layers); return; case 7: // Udp. case 8: UdpLayer udpLayer = random.NextUdpLayer(); layers.Add(udpLayer); CreateRandomUdpPayload(random, udpLayer, layers); return; case 9: // Tcp. case 10: TcpLayer tcpLayer = random.NextTcpLayer(); layers.Add(tcpLayer); CreateRandomTcpPayload(random, tcpLayer, layers); return; default: throw new InvalidOperationException("Invalid value."); } }
public void RandomIcmpTest() { EthernetLayer ethernetLayer = new EthernetLayer { Source = new MacAddress("00:01:02:03:04:05"), Destination = new MacAddress("A0:A1:A2:A3:A4:A5") }; int seed = new Random().Next(); Console.WriteLine("Seed: " + seed); Random random = new Random(seed); for (int i = 0; i != 2000; ++i) { IpV4Layer ipV4Layer = random.NextIpV4Layer(null); ipV4Layer.HeaderChecksum = null; Layer ipLayer = random.NextBool() ? (Layer)ipV4Layer : random.NextIpV6Layer(IpV4Protocol.InternetControlMessageProtocol, false); IcmpLayer icmpLayer = random.NextIcmpLayer(); icmpLayer.Checksum = null; if (icmpLayer.MessageType == IcmpMessageType.DestinationUnreachable && icmpLayer.MessageTypeAndCode != IcmpMessageTypeAndCode.DestinationUnreachableFragmentationNeededAndDoNotFragmentSet) { ((IcmpDestinationUnreachableLayer)icmpLayer).NextHopMaximumTransmissionUnit = 0; } IEnumerable<ILayer> icmpPayloadLayers = random.NextIcmpPayloadLayers(icmpLayer); int icmpPayloadLength = icmpPayloadLayers.Select(layer => layer.Length).Sum(); switch (icmpLayer.MessageType) { case IcmpMessageType.ParameterProblem: if (icmpPayloadLength % 4 != 0) icmpPayloadLayers = icmpPayloadLayers.Concat(new[] {new PayloadLayer {Data = random.NextDatagram(4 - icmpPayloadLength % 4)}}); icmpPayloadLength = icmpPayloadLayers.Select(layer => layer.Length).Sum(); IcmpParameterProblemLayer icmpParameterProblemLayer = (IcmpParameterProblemLayer)icmpLayer; icmpParameterProblemLayer.Pointer = (byte)(icmpParameterProblemLayer.Pointer % icmpPayloadLength); icmpParameterProblemLayer.OriginalDatagramLength = icmpPayloadLength - icmpPayloadLayers.First().Length; break; case IcmpMessageType.SecurityFailures: ((IcmpSecurityFailuresLayer)icmpLayer).Pointer %= (ushort)icmpPayloadLength; break; } PacketBuilder packetBuilder = new PacketBuilder(new ILayer[] { ethernetLayer, ipLayer, icmpLayer }.Concat(icmpPayloadLayers)); Packet packet = packetBuilder.Build(DateTime.Now); Assert.IsTrue(packet.IsValid, "IsValid"); byte[] buffer = (byte[])packet.Buffer.Clone(); buffer.Write(ethernetLayer.Length + ipLayer.Length, random.NextDatagram(icmpLayer.Length)); Packet illegalPacket = new Packet(buffer, DateTime.Now, packet.DataLink); Assert.IsFalse(illegalPacket.IsValid, "IsInvalid"); if (illegalPacket.Ethernet.Ip.Icmp is IcmpUnknownDatagram) { byte[] icmpBuffer = new byte[illegalPacket.Ethernet.Ip.Icmp.ExtractLayer().Length]; ILayer layer = illegalPacket.Ethernet.Ip.Icmp.ExtractLayer(); layer.Write(icmpBuffer,0,icmpBuffer.Length, null,null); layer.Finalize(icmpBuffer,0,icmpBuffer.Length,null); MoreAssert.AreSequenceEqual(illegalPacket.Ethernet.Ip.Icmp.ToArray(), icmpBuffer); Assert.AreEqual(illegalPacket, PacketBuilder.Build(DateTime.Now, ethernetLayer, ipLayer, illegalPacket.Ethernet.Ip.Icmp.ExtractLayer())); } // Ethernet ethernetLayer.EtherType = ipLayer == ipV4Layer ? EthernetType.IpV4 : EthernetType.IpV6; Assert.AreEqual(ethernetLayer, packet.Ethernet.ExtractLayer(), "Ethernet Layer"); ethernetLayer.EtherType = EthernetType.None; // IP. if (ipLayer == ipV4Layer) { // IPv4. ipV4Layer.Protocol = IpV4Protocol.InternetControlMessageProtocol; ipV4Layer.HeaderChecksum = ((IpV4Layer)packet.Ethernet.IpV4.ExtractLayer()).HeaderChecksum; Assert.AreEqual(ipV4Layer, packet.Ethernet.IpV4.ExtractLayer()); ipV4Layer.HeaderChecksum = null; Assert.AreEqual(ipV4Layer.Length, packet.Ethernet.IpV4.HeaderLength); Assert.IsTrue(packet.Ethernet.IpV4.IsHeaderChecksumCorrect); Assert.AreEqual(ipV4Layer.Length + icmpLayer.Length + icmpPayloadLength, packet.Ethernet.IpV4.TotalLength); Assert.AreEqual(IpV4Datagram.DefaultVersion, packet.Ethernet.IpV4.Version); } else { // IPv6. Assert.AreEqual(ipLayer, packet.Ethernet.IpV6.ExtractLayer()); } // ICMP IcmpDatagram actualIcmp = packet.Ethernet.Ip.Icmp; IcmpLayer actualIcmpLayer = (IcmpLayer)actualIcmp.ExtractLayer(); icmpLayer.Checksum = actualIcmpLayer.Checksum; Assert.AreEqual(icmpLayer, actualIcmpLayer); Assert.AreEqual(icmpLayer.GetHashCode(), actualIcmpLayer.GetHashCode()); if (actualIcmpLayer.MessageType != IcmpMessageType.RouterSolicitation) { Assert.AreNotEqual(random.NextIcmpLayer(), actualIcmpLayer); IcmpLayer otherIcmpLayer = random.NextIcmpLayer(); Assert.AreNotEqual(otherIcmpLayer.GetHashCode(), actualIcmpLayer.GetHashCode()); } Assert.IsTrue(actualIcmp.IsChecksumCorrect); Assert.AreEqual(icmpLayer.MessageType, actualIcmp.MessageType); Assert.AreEqual(icmpLayer.CodeValue, actualIcmp.Code); Assert.AreEqual(icmpLayer.MessageTypeAndCode, actualIcmp.MessageTypeAndCode); Assert.AreEqual(packet.Length - ethernetLayer.Length - ipLayer.Length - IcmpDatagram.HeaderLength, actualIcmp.Payload.Length); Assert.IsNotNull(icmpLayer.ToString()); switch (packet.Ethernet.Ip.Icmp.MessageType) { case IcmpMessageType.RouterSolicitation: case IcmpMessageType.SourceQuench: case IcmpMessageType.TimeExceeded: Assert.AreEqual<uint>(0, actualIcmp.Variable); break; case IcmpMessageType.DestinationUnreachable: case IcmpMessageType.ParameterProblem: case IcmpMessageType.Redirect: case IcmpMessageType.ConversionFailed: case IcmpMessageType.Echo: case IcmpMessageType.EchoReply: case IcmpMessageType.Timestamp: case IcmpMessageType.TimestampReply: case IcmpMessageType.InformationRequest: case IcmpMessageType.InformationReply: case IcmpMessageType.RouterAdvertisement: case IcmpMessageType.AddressMaskRequest: case IcmpMessageType.AddressMaskReply: break; case IcmpMessageType.TraceRoute: Assert.AreEqual(((IcmpTraceRouteLayer)icmpLayer).OutboundHopCount == 0xFFFF, ((IcmpTraceRouteDatagram)actualIcmp).IsOutbound); break; case IcmpMessageType.DomainNameRequest: case IcmpMessageType.SecurityFailures: break; case IcmpMessageType.DomainNameReply: default: throw new InvalidOperationException("Invalid icmpMessageType " + packet.Ethernet.Ip.Icmp.MessageType); } } }