blob: 1e6a2e92a7725b82c9ec809327666c55c6e4f762 [file] [log] [blame]
// 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/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 255
0xFF,
// 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