1 // Copyright 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/masque/masque_encapsulated_client.h"
6
7 #include <algorithm>
8 #include <cstddef>
9 #include <cstdint>
10 #include <memory>
11 #include <optional>
12 #include <string>
13 #include <utility>
14
15 #include "absl/strings/string_view.h"
16 #include "quiche/quic/core/crypto/proof_verifier.h"
17 #include "quiche/quic/core/io/quic_event_loop.h"
18 #include "quiche/quic/core/quic_connection.h"
19 #include "quiche/quic/core/quic_packet_writer.h"
20 #include "quiche/quic/core/quic_server_id.h"
21 #include "quiche/quic/core/quic_session.h"
22 #include "quiche/quic/core/quic_types.h"
23 #include "quiche/quic/core/quic_versions.h"
24 #include "quiche/quic/masque/masque_client.h"
25 #include "quiche/quic/masque/masque_client_session.h"
26 #include "quiche/quic/masque/masque_encapsulated_client_session.h"
27 #include "quiche/quic/masque/masque_utils.h"
28 #include "quiche/quic/platform/api/quic_ip_address.h"
29 #include "quiche/quic/platform/api/quic_logging.h"
30 #include "quiche/quic/platform/api/quic_socket_address.h"
31 #include "quiche/quic/tools/quic_client_default_network_helper.h"
32 #include "quiche/quic/tools/quic_default_client.h"
33 #include "quiche/common/platform/api/quiche_logging.h"
34 #include "quiche/common/quiche_data_reader.h"
35 #include "quiche/common/quiche_data_writer.h"
36
37 namespace quic {
38
39 namespace {
40
41 class ChecksumWriter {
42 public:
ChecksumWriter(quiche::QuicheDataWriter & writer)43 explicit ChecksumWriter(quiche::QuicheDataWriter& writer) : writer_(writer) {}
IngestUInt16(uint16_t val)44 void IngestUInt16(uint16_t val) { accumulator_ += val; }
IngestUInt8(uint8_t val)45 void IngestUInt8(uint8_t val) {
46 uint16_t val16 = odd_ ? val : (val << 8);
47 accumulator_ += val16;
48 odd_ = !odd_;
49 }
IngestData(size_t offset,size_t length)50 bool IngestData(size_t offset, size_t length) {
51 quiche::QuicheDataReader reader(
52 writer_.data(), std::min<size_t>(offset + length, writer_.capacity()));
53 if (!reader.Seek(offset) || reader.BytesRemaining() < length) {
54 return false;
55 }
56 // Handle any potentially off first byte.
57 uint8_t first_byte;
58 if (odd_ && reader.ReadUInt8(&first_byte)) {
59 IngestUInt8(first_byte);
60 }
61 // Handle each 16-bit word at a time.
62 while (reader.BytesRemaining() >= sizeof(uint16_t)) {
63 uint16_t word;
64 if (!reader.ReadUInt16(&word)) {
65 return false;
66 }
67 IngestUInt16(word);
68 }
69 // Handle any leftover odd byte.
70 uint8_t last_byte;
71 if (reader.ReadUInt8(&last_byte)) {
72 IngestUInt8(last_byte);
73 }
74 return true;
75 }
WriteChecksumAtOffset(size_t offset)76 bool WriteChecksumAtOffset(size_t offset) {
77 while (accumulator_ >> 16 > 0) {
78 accumulator_ = (accumulator_ & 0xffff) + (accumulator_ >> 16);
79 }
80 accumulator_ = 0xffff & ~accumulator_;
81 quiche::QuicheDataWriter writer2(writer_.capacity(), writer_.data());
82 return writer2.Seek(offset) && writer2.WriteUInt16(accumulator_);
83 }
84
85 private:
86 quiche::QuicheDataWriter& writer_;
87 uint32_t accumulator_ = 0xffff;
88 bool odd_ = false;
89 };
90
91 // Custom packet writer that allows getting all of a connection's outgoing
92 // packets.
93 class MasquePacketWriter : public QuicPacketWriter {
94 public:
MasquePacketWriter(MasqueEncapsulatedClient * client)95 explicit MasquePacketWriter(MasqueEncapsulatedClient* client)
96 : client_(client) {}
WritePacket(const char * buffer,size_t buf_len,const QuicIpAddress &,const QuicSocketAddress & peer_address,PerPacketOptions *,const QuicPacketWriterParams &)97 WriteResult WritePacket(const char* buffer, size_t buf_len,
98 const QuicIpAddress& /*self_address*/,
99 const QuicSocketAddress& peer_address,
100 PerPacketOptions* /*options*/,
101 const QuicPacketWriterParams& /*params*/) override {
102 QUICHE_DCHECK(peer_address.IsInitialized());
103 QUIC_DVLOG(1) << "MasquePacketWriter trying to write " << buf_len
104 << " bytes to " << peer_address;
105 if (client_->masque_client()->masque_mode() == MasqueMode::kConnectIp) {
106 constexpr size_t kIPv4HeaderSize = 20;
107 constexpr size_t kIPv4ChecksumOffset = 10;
108 constexpr size_t kIPv6HeaderSize = 40;
109 constexpr size_t kUdpHeaderSize = 8;
110 const size_t udp_length = kUdpHeaderSize + buf_len;
111 std::string packet;
112 packet.resize(
113 (peer_address.host().IsIPv6() ? kIPv6HeaderSize : kIPv4HeaderSize) +
114 udp_length);
115 quiche::QuicheDataWriter writer(packet.size(), packet.data());
116 if (peer_address.host().IsIPv6()) {
117 // Write IPv6 header.
118 QUICHE_CHECK(writer.WriteUInt8(0x60)); // Version = 6 and DSCP.
119 QUICHE_CHECK(writer.WriteUInt8(0)); // DSCP/ECN and flow label.
120 QUICHE_CHECK(writer.WriteUInt16(0)); // Flow label.
121 QUICHE_CHECK(writer.WriteUInt16(udp_length)); // Payload Length.
122 QUICHE_CHECK(writer.WriteUInt8(17)); // Next header = UDP.
123 QUICHE_CHECK(writer.WriteUInt8(64)); // Hop limit = 64.
124 in6_addr source_address = {};
125 if (client_->masque_encapsulated_client_session()
126 ->local_v6_address()
127 .IsIPv6()) {
128 source_address = client_->masque_encapsulated_client_session()
129 ->local_v6_address()
130 .GetIPv6();
131 }
132 QUICHE_CHECK(
133 writer.WriteBytes(&source_address, sizeof(source_address)));
134 in6_addr destination_address = peer_address.host().GetIPv6();
135 QUICHE_CHECK(writer.WriteBytes(&destination_address,
136 sizeof(destination_address)));
137 } else {
138 // Write IPv4 header.
139 QUICHE_CHECK(writer.WriteUInt8(0x45)); // Version = 4, IHL = 5.
140 QUICHE_CHECK(writer.WriteUInt8(0)); // DSCP/ECN.
141 QUICHE_CHECK(writer.WriteUInt16(packet.size())); // Total Length.
142 QUICHE_CHECK(writer.WriteUInt32(0)); // No fragmentation.
143 QUICHE_CHECK(writer.WriteUInt8(64)); // TTL = 64.
144 QUICHE_CHECK(writer.WriteUInt8(17)); // IP Protocol = UDP.
145 QUICHE_CHECK(writer.WriteUInt16(0)); // Checksum = 0 initially.
146 in_addr source_address = {};
147 if (client_->masque_encapsulated_client_session()
148 ->local_v4_address()
149 .IsIPv4()) {
150 source_address = client_->masque_encapsulated_client_session()
151 ->local_v4_address()
152 .GetIPv4();
153 }
154 QUICHE_CHECK(
155 writer.WriteBytes(&source_address, sizeof(source_address)));
156 in_addr destination_address = peer_address.host().GetIPv4();
157 QUICHE_CHECK(writer.WriteBytes(&destination_address,
158 sizeof(destination_address)));
159 ChecksumWriter ip_checksum_writer(writer);
160 QUICHE_CHECK(ip_checksum_writer.IngestData(0, kIPv4HeaderSize));
161 QUICHE_CHECK(
162 ip_checksum_writer.WriteChecksumAtOffset(kIPv4ChecksumOffset));
163 }
164 // Write UDP header.
165 QUICHE_CHECK(writer.WriteUInt16(0x1234)); // Source port.
166 QUICHE_CHECK(
167 writer.WriteUInt16(peer_address.port())); // Destination port.
168 QUICHE_CHECK(writer.WriteUInt16(udp_length)); // UDP length.
169 QUICHE_CHECK(writer.WriteUInt16(0)); // Checksum = 0 initially.
170 // Write UDP payload.
171 QUICHE_CHECK(writer.WriteBytes(buffer, buf_len));
172 ChecksumWriter udp_checksum_writer(writer);
173 if (peer_address.host().IsIPv6()) {
174 QUICHE_CHECK(udp_checksum_writer.IngestData(8, 32)); // IP addresses.
175 udp_checksum_writer.IngestUInt16(0); // High bits of UDP length.
176 udp_checksum_writer.IngestUInt16(
177 udp_length); // Low bits of UDP length.
178 udp_checksum_writer.IngestUInt16(0); // Zeroes.
179 udp_checksum_writer.IngestUInt8(0); // Zeroes.
180 udp_checksum_writer.IngestUInt8(17); // Next header = UDP.
181 QUICHE_CHECK(udp_checksum_writer.IngestData(
182 kIPv6HeaderSize, udp_length)); // UDP header and data.
183 QUICHE_CHECK(
184 udp_checksum_writer.WriteChecksumAtOffset(kIPv6HeaderSize + 6));
185 } else {
186 QUICHE_CHECK(udp_checksum_writer.IngestData(12, 8)); // IP addresses.
187 udp_checksum_writer.IngestUInt8(0); // Zeroes.
188 udp_checksum_writer.IngestUInt8(17); // IP Protocol = UDP.
189 udp_checksum_writer.IngestUInt16(udp_length); // UDP length.
190 QUICHE_CHECK(udp_checksum_writer.IngestData(
191 kIPv4HeaderSize, udp_length)); // UDP header and data.
192 QUICHE_CHECK(
193 udp_checksum_writer.WriteChecksumAtOffset(kIPv4HeaderSize + 6));
194 }
195 client_->masque_client()->masque_client_session()->SendIpPacket(
196 packet, client_->masque_encapsulated_client_session());
197 } else {
198 absl::string_view packet(buffer, buf_len);
199 client_->masque_client()->masque_client_session()->SendPacket(
200 packet, peer_address, client_->masque_encapsulated_client_session());
201 }
202 return WriteResult(WRITE_STATUS_OK, buf_len);
203 }
204
IsWriteBlocked() const205 bool IsWriteBlocked() const override { return false; }
206
SetWritable()207 void SetWritable() override {}
208
MessageTooBigErrorCode() const209 std::optional<int> MessageTooBigErrorCode() const override {
210 return std::nullopt;
211 }
212
GetMaxPacketSize(const QuicSocketAddress &) const213 QuicByteCount GetMaxPacketSize(
214 const QuicSocketAddress& /*peer_address*/) const override {
215 return kMasqueMaxEncapsulatedPacketSize;
216 }
217
SupportsReleaseTime() const218 bool SupportsReleaseTime() const override { return false; }
219
IsBatchMode() const220 bool IsBatchMode() const override { return false; }
221
SupportsEcn() const222 bool SupportsEcn() const override { return false; }
GetNextWriteLocation(const QuicIpAddress &,const QuicSocketAddress &)223 QuicPacketBuffer GetNextWriteLocation(
224 const QuicIpAddress& /*self_address*/,
225 const QuicSocketAddress& /*peer_address*/) override {
226 return {nullptr, nullptr};
227 }
228
Flush()229 WriteResult Flush() override { return WriteResult(WRITE_STATUS_OK, 0); }
230
231 private:
232 MasqueEncapsulatedClient* client_; // Unowned.
233 };
234
235 // Custom network helper that allows injecting a custom packet writer in order
236 // to get all of a connection's outgoing packets.
237 class MasqueClientDefaultNetworkHelper : public QuicClientDefaultNetworkHelper {
238 public:
MasqueClientDefaultNetworkHelper(QuicEventLoop * event_loop,MasqueEncapsulatedClient * client)239 MasqueClientDefaultNetworkHelper(QuicEventLoop* event_loop,
240 MasqueEncapsulatedClient* client)
241 : QuicClientDefaultNetworkHelper(event_loop, client), client_(client) {}
CreateQuicPacketWriter()242 QuicPacketWriter* CreateQuicPacketWriter() override {
243 return new MasquePacketWriter(client_);
244 }
245
246 private:
247 MasqueEncapsulatedClient* client_; // Unowned.
248 };
249
250 } // namespace
251
MasqueEncapsulatedClient(QuicSocketAddress server_address,const QuicServerId & server_id,QuicEventLoop * event_loop,std::unique_ptr<ProofVerifier> proof_verifier,MasqueClient * masque_client)252 MasqueEncapsulatedClient::MasqueEncapsulatedClient(
253 QuicSocketAddress server_address, const QuicServerId& server_id,
254 QuicEventLoop* event_loop, std::unique_ptr<ProofVerifier> proof_verifier,
255 MasqueClient* masque_client)
256 : QuicDefaultClient(
257 server_address, server_id, MasqueSupportedVersions(),
258 MasqueEncapsulatedConfig(), event_loop,
259 std::make_unique<MasqueClientDefaultNetworkHelper>(event_loop, this),
260 std::move(proof_verifier)),
261 masque_client_(masque_client) {}
262
~MasqueEncapsulatedClient()263 MasqueEncapsulatedClient::~MasqueEncapsulatedClient() {
264 masque_client_->masque_client_session()->CloseConnectUdpStream(
265 masque_encapsulated_client_session());
266 }
267
CreateQuicClientSession(const ParsedQuicVersionVector & supported_versions,QuicConnection * connection)268 std::unique_ptr<QuicSession> MasqueEncapsulatedClient::CreateQuicClientSession(
269 const ParsedQuicVersionVector& supported_versions,
270 QuicConnection* connection) {
271 QUIC_DLOG(INFO) << "Creating MASQUE encapsulated session for "
272 << connection->connection_id();
273 return std::make_unique<MasqueEncapsulatedClientSession>(
274 *config(), supported_versions, connection, server_id(), crypto_config(),
275 masque_client_->masque_client_session());
276 }
277
278 MasqueEncapsulatedClientSession*
masque_encapsulated_client_session()279 MasqueEncapsulatedClient::masque_encapsulated_client_session() {
280 return static_cast<MasqueEncapsulatedClientSession*>(
281 QuicDefaultClient::session());
282 }
283
284 } // namespace quic
285