1 // Copyright (c) 2019 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "quiche/quic/qbone/platform/icmp_packet.h"
6
7 #include <netinet/ip6.h>
8
9 #include <cstdint>
10
11 #include "absl/strings/string_view.h"
12 #include "quiche/quic/platform/api/quic_test.h"
13 #include "quiche/common/quiche_text_utils.h"
14
15 namespace quic {
16 namespace {
17
18 constexpr char kReferenceSourceAddress[] = "fe80:1:2:3:4::1";
19 constexpr char kReferenceDestinationAddress[] = "fe80:4:3:2:1::1";
20
21 // clang-format off
22 constexpr uint8_t kReferenceICMPMessageBody[] {
23 0xd2, 0x61, 0x29, 0x5b, 0x00, 0x00, 0x00, 0x00,
24 0x0d, 0x59, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
25 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
26 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
27 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
28 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
29 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37
30 };
31
32 constexpr uint8_t kReferenceICMPPacket[] = {
33 // START IPv6 Header
34 // IPv6 with zero TOS and flow label.
35 0x60, 0x00, 0x00, 0x00,
36 // Payload is 64 bytes
37 0x00, 0x40,
38 // Next header is 58
39 0x3a,
40 // Hop limit is 255
41 0xFF,
42 // Source address of fe80:1:2:3:4::1
43 0xfe, 0x80, 0x00, 0x01, 0x00, 0x02, 0x00, 0x03,
44 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
45 // Destination address of fe80:4:3:2:1::1
46 0xfe, 0x80, 0x00, 0x04, 0x00, 0x03, 0x00, 0x02,
47 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
48 // END IPv6 Header
49 // START ICMPv6 Header
50 // Echo Request, zero code
51 0x80, 0x00,
52 // Checksum
53 0xec, 0x00,
54 // Identifier
55 0xcb, 0x82,
56 // Sequence Number
57 0x00, 0x01,
58 // END ICMPv6 Header
59 // Message body
60 0xd2, 0x61, 0x29, 0x5b, 0x00, 0x00, 0x00, 0x00,
61 0x0d, 0x59, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
62 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
63 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
64 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
65 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
66 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37
67 };
68 // clang-format on
69
70 } // namespace
71
TEST(IcmpPacketTest,CreatedPacketMatchesReference)72 TEST(IcmpPacketTest, CreatedPacketMatchesReference) {
73 QuicIpAddress src;
74 ASSERT_TRUE(src.FromString(kReferenceSourceAddress));
75 in6_addr src_addr;
76 memcpy(src_addr.s6_addr, src.ToPackedString().data(), sizeof(in6_addr));
77
78 QuicIpAddress dst;
79 ASSERT_TRUE(dst.FromString(kReferenceDestinationAddress));
80 in6_addr dst_addr;
81 memcpy(dst_addr.s6_addr, dst.ToPackedString().data(), sizeof(in6_addr));
82
83 icmp6_hdr icmp_header{};
84 icmp_header.icmp6_type = ICMP6_ECHO_REQUEST;
85 icmp_header.icmp6_id = 0x82cb;
86 icmp_header.icmp6_seq = 0x0100;
87
88 absl::string_view message_body = absl::string_view(
89 reinterpret_cast<const char*>(kReferenceICMPMessageBody), 56);
90 absl::string_view expected_packet = absl::string_view(
91 reinterpret_cast<const char*>(kReferenceICMPPacket), 104);
92 CreateIcmpPacket(src_addr, dst_addr, icmp_header, message_body,
93 [&expected_packet](absl::string_view packet) {
94 QUIC_LOG(INFO) << quiche::QuicheTextUtils::HexDump(packet);
95 ASSERT_EQ(packet, expected_packet);
96 });
97 }
98
TEST(IcmpPacketTest,NonZeroChecksumIsIgnored)99 TEST(IcmpPacketTest, NonZeroChecksumIsIgnored) {
100 QuicIpAddress src;
101 ASSERT_TRUE(src.FromString(kReferenceSourceAddress));
102 in6_addr src_addr;
103 memcpy(src_addr.s6_addr, src.ToPackedString().data(), sizeof(in6_addr));
104
105 QuicIpAddress dst;
106 ASSERT_TRUE(dst.FromString(kReferenceDestinationAddress));
107 in6_addr dst_addr;
108 memcpy(dst_addr.s6_addr, dst.ToPackedString().data(), sizeof(in6_addr));
109
110 icmp6_hdr icmp_header{};
111 icmp_header.icmp6_type = ICMP6_ECHO_REQUEST;
112 icmp_header.icmp6_id = 0x82cb;
113 icmp_header.icmp6_seq = 0x0100;
114 // Set the checksum to a bogus value
115 icmp_header.icmp6_cksum = 0x1234;
116
117 absl::string_view message_body = absl::string_view(
118 reinterpret_cast<const char*>(kReferenceICMPMessageBody), 56);
119 absl::string_view expected_packet = absl::string_view(
120 reinterpret_cast<const char*>(kReferenceICMPPacket), 104);
121 CreateIcmpPacket(src_addr, dst_addr, icmp_header, message_body,
122 [&expected_packet](absl::string_view packet) {
123 QUIC_LOG(INFO) << quiche::QuicheTextUtils::HexDump(packet);
124 ASSERT_EQ(packet, expected_packet);
125 });
126 }
127
128 } // namespace quic
129