| // Copyright (c) 2019 The Chromium Authors. All rights reserved. | |
| // Use of this source code is governed by a BSD-style license that can be | |
| // found in the LICENSE file. | |
| #include "net/third_party/quiche/src/quic/qbone/platform/icmp_packet.h" | |
| #include <netinet/ip6.h> | |
| #include <cstdint> | |
| #include "net/third_party/quiche/src/quic/platform/api/quic_test.h" | |
| #include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h" | |
| #include "net/third_party/quiche/src/common/platform/api/quiche_text_utils.h" | |
| namespace quic { | |
| namespace { | |
| constexpr char kReferenceSourceAddress[] = "fe80:1:2:3:4::1"; | |
| constexpr char kReferenceDestinationAddress[] = "fe80:4:3:2:1::1"; | |
| // clang-format off | |
| constexpr uint8_t kReferenceICMPMessageBody[] { | |
| 0xd2, 0x61, 0x29, 0x5b, 0x00, 0x00, 0x00, 0x00, | |
| 0x0d, 0x59, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, | |
| 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, | |
| 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, | |
| 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, | |
| 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, | |
| 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37 | |
| }; | |
| constexpr uint8_t kReferenceICMPPacket[] = { | |
| // START IPv6 Header | |
| // IPv6 with zero TOS and flow label. | |
| 0x60, 0x00, 0x00, 0x00, | |
| // Payload is 64 bytes | |
| 0x00, 0x40, | |
| // Next header is 58 | |
| 0x3a, | |
| // Hop limit is 64 | |
| 0x40, | |
| // Source address of fe80:1:2:3:4::1 | |
| 0xfe, 0x80, 0x00, 0x01, 0x00, 0x02, 0x00, 0x03, | |
| 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, | |
| // Destination address of fe80:4:3:2:1::1 | |
| 0xfe, 0x80, 0x00, 0x04, 0x00, 0x03, 0x00, 0x02, | |
| 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, | |
| // END IPv6 Header | |
| // START ICMPv6 Header | |
| // Echo Request, zero code | |
| 0x80, 0x00, | |
| // Checksum | |
| 0xec, 0x00, | |
| // Identifier | |
| 0xcb, 0x82, | |
| // Sequence Number | |
| 0x00, 0x01, | |
| // END ICMPv6 Header | |
| // Message body | |
| 0xd2, 0x61, 0x29, 0x5b, 0x00, 0x00, 0x00, 0x00, | |
| 0x0d, 0x59, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, | |
| 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, | |
| 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, | |
| 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, | |
| 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, | |
| 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37 | |
| }; | |
| // clang-format on | |
| } // namespace | |
| TEST(IcmpPacketTest, CreatedPacketMatchesReference) { | |
| QuicIpAddress src; | |
| ASSERT_TRUE(src.FromString(kReferenceSourceAddress)); | |
| in6_addr src_addr; | |
| memcpy(src_addr.s6_addr, src.ToPackedString().data(), sizeof(in6_addr)); | |
| QuicIpAddress dst; | |
| ASSERT_TRUE(dst.FromString(kReferenceDestinationAddress)); | |
| in6_addr dst_addr; | |
| memcpy(dst_addr.s6_addr, dst.ToPackedString().data(), sizeof(in6_addr)); | |
| icmp6_hdr icmp_header{}; | |
| icmp_header.icmp6_type = ICMP6_ECHO_REQUEST; | |
| icmp_header.icmp6_id = 0x82cb; | |
| icmp_header.icmp6_seq = 0x0100; | |
| quiche::QuicheStringPiece message_body = quiche::QuicheStringPiece( | |
| reinterpret_cast<const char*>(kReferenceICMPMessageBody), 56); | |
| quiche::QuicheStringPiece expected_packet = quiche::QuicheStringPiece( | |
| reinterpret_cast<const char*>(kReferenceICMPPacket), 104); | |
| CreateIcmpPacket(src_addr, dst_addr, icmp_header, message_body, | |
| [&expected_packet](quiche::QuicheStringPiece packet) { | |
| QUIC_LOG(INFO) << quiche::QuicheTextUtils::HexDump(packet); | |
| ASSERT_EQ(packet, expected_packet); | |
| }); | |
| } | |
| TEST(IcmpPacketTest, NonZeroChecksumIsIgnored) { | |
| QuicIpAddress src; | |
| ASSERT_TRUE(src.FromString(kReferenceSourceAddress)); | |
| in6_addr src_addr; | |
| memcpy(src_addr.s6_addr, src.ToPackedString().data(), sizeof(in6_addr)); | |
| QuicIpAddress dst; | |
| ASSERT_TRUE(dst.FromString(kReferenceDestinationAddress)); | |
| in6_addr dst_addr; | |
| memcpy(dst_addr.s6_addr, dst.ToPackedString().data(), sizeof(in6_addr)); | |
| icmp6_hdr icmp_header{}; | |
| icmp_header.icmp6_type = ICMP6_ECHO_REQUEST; | |
| icmp_header.icmp6_id = 0x82cb; | |
| icmp_header.icmp6_seq = 0x0100; | |
| // Set the checksum to a bogus value | |
| icmp_header.icmp6_cksum = 0x1234; | |
| quiche::QuicheStringPiece message_body = quiche::QuicheStringPiece( | |
| reinterpret_cast<const char*>(kReferenceICMPMessageBody), 56); | |
| quiche::QuicheStringPiece expected_packet = quiche::QuicheStringPiece( | |
| reinterpret_cast<const char*>(kReferenceICMPPacket), 104); | |
| CreateIcmpPacket(src_addr, dst_addr, icmp_header, message_body, | |
| [&expected_packet](quiche::QuicheStringPiece packet) { | |
| QUIC_LOG(INFO) << quiche::QuicheTextUtils::HexDump(packet); | |
| ASSERT_EQ(packet, expected_packet); | |
| }); | |
| } | |
| } // namespace quic |