xref: /aosp_15_r20/external/cronet/net/third_party/quiche/src/quiche/quic/masque/masque_encapsulated_client.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
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