| // 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 "quic/qbone/platform/icmp_packet.h" |
| |
| #include <netinet/ip6.h> |
| |
| #include <cstdint> |
| |
| #include "absl/strings/string_view.h" |
| #include "quic/platform/api/quic_test.h" |
| #include "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; |
| |
| absl::string_view message_body = absl::string_view( |
| reinterpret_cast<const char*>(kReferenceICMPMessageBody), 56); |
| absl::string_view expected_packet = absl::string_view( |
| reinterpret_cast<const char*>(kReferenceICMPPacket), 104); |
| CreateIcmpPacket(src_addr, dst_addr, icmp_header, message_body, |
| [&expected_packet](absl::string_view 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; |
| |
| absl::string_view message_body = absl::string_view( |
| reinterpret_cast<const char*>(kReferenceICMPMessageBody), 56); |
| absl::string_view expected_packet = absl::string_view( |
| reinterpret_cast<const char*>(kReferenceICMPPacket), 104); |
| CreateIcmpPacket(src_addr, dst_addr, icmp_header, message_body, |
| [&expected_packet](absl::string_view packet) { |
| QUIC_LOG(INFO) << quiche::QuicheTextUtils::HexDump(packet); |
| ASSERT_EQ(packet, expected_packet); |
| }); |
| } |
| |
| } // namespace quic |