blob: c85280fe18fe743c885bc93182af861e23a72c9a [file] [log] [blame]
wubf975eac2019-08-19 19:41:01 -07001// 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#ifndef QUICHE_QUIC_QBONE_QBONE_PACKET_PROCESSOR_H_
6#define QUICHE_QUIC_QBONE_QBONE_PACKET_PROCESSOR_H_
7
8#include <netinet/icmp6.h>
9#include <netinet/ip6.h>
10
vasilvv1436e342020-10-09 12:31:16 -070011#include "absl/strings/string_view.h"
QUICHE team5be974e2020-12-29 18:35:24 -050012#include "quic/core/quic_types.h"
13#include "quic/platform/api/quic_ip_address.h"
wubf975eac2019-08-19 19:41:01 -070014
15namespace quic {
16
17enum : size_t {
18 kIPv6HeaderSize = 40,
19 kICMPv6HeaderSize = sizeof(icmp6_hdr),
20 kTotalICMPv6HeaderSize = kIPv6HeaderSize + kICMPv6HeaderSize,
21};
22
23// QBONE packet processor accepts packets destined in either direction
24// (client-to-network or network-to-client). It inspects them and makes
25// decisions on whether they should be forwarded or dropped, replying with ICMP
26// messages as appropriate.
27class QbonePacketProcessor {
28 public:
29 enum class Direction {
30 // Packet is going from the QBONE client into the network behind the QBONE.
QUICHE team234c8772019-12-06 14:14:12 -080031 FROM_OFF_NETWORK = 0,
wubf975eac2019-08-19 19:41:01 -070032 // Packet is going from the network begin QBONE to the client.
33 FROM_NETWORK = 1
34 };
35
36 enum class ProcessingResult {
37 OK = 0,
38 SILENT_DROP = 1,
39 ICMP = 2,
40 // Equivalent to |SILENT_DROP| at the moment, but indicates that the
41 // downstream filter has buffered the packet and deferred its processing.
42 // The packet may be emitted at a later time.
43 DEFER = 3,
44 // In addition to sending an ICMP message, also send a TCP RST. This option
45 // requires the incoming packet to have been a valid TCP packet, as a TCP
46 // RST requires information from the current connection state to be
47 // well-formed.
48 ICMP_AND_TCP_RESET = 4,
49 };
50
51 class OutputInterface {
52 public:
53 virtual ~OutputInterface();
54
vasilvv1436e342020-10-09 12:31:16 -070055 virtual void SendPacketToClient(absl::string_view packet) = 0;
56 virtual void SendPacketToNetwork(absl::string_view packet) = 0;
wubf975eac2019-08-19 19:41:01 -070057 };
58
59 class StatsInterface {
60 public:
61 virtual ~StatsInterface();
62
63 virtual void OnPacketForwarded(Direction direction) = 0;
64 virtual void OnPacketDroppedSilently(Direction direction) = 0;
65 virtual void OnPacketDroppedWithIcmp(Direction direction) = 0;
66 virtual void OnPacketDroppedWithTcpReset(Direction direction) = 0;
67 virtual void OnPacketDeferred(Direction direction) = 0;
68 };
69
70 // Allows to implement a custom packet filter on top of the filtering done by
71 // the packet processor itself.
72 class Filter {
73 public:
74 virtual ~Filter();
75 // The main interface function. The following arguments are supplied:
76 // - |direction|, to indicate direction of the packet.
77 // - |full_packet|, which includes the IPv6 header and possibly the IPv6
78 // options that were understood by the processor.
79 // - |payload|, the contents of the IPv6 packet, i.e. a TCP, a UDP or an
80 // ICMP packet.
81 // - |icmp_header|, an output argument which allows the filter to specify
82 // the ICMP message with which the packet is to be rejected.
83 // The method is called only on packets which were already verified as valid
84 // IPv6 packets.
85 //
86 // The implementer of this method has four options to return:
87 // - OK will cause the filter to pass the packet through
88 // - SILENT_DROP will cause the filter to drop the packet silently
89 // - ICMP will cause the filter to drop the packet and send an ICMP
90 // response.
91 // - DEFER will cause the packet to be not forwarded; the filter is
92 // responsible for sending (or not sending) it later using |output|.
93 //
94 // Note that |output| should not be used except in the DEFER case, as the
95 // processor will perform the necessary writes itself.
96 virtual ProcessingResult FilterPacket(Direction direction,
vasilvv1436e342020-10-09 12:31:16 -070097 absl::string_view full_packet,
98 absl::string_view payload,
wubf975eac2019-08-19 19:41:01 -070099 icmp6_hdr* icmp_header,
100 OutputInterface* output);
101
102 protected:
103 // Helper methods that allow to easily extract information that is required
104 // for filtering from the |ipv6_header| argument. All of those assume that
105 // the header is of valid size, which is true for everything passed into
106 // FilterPacket().
vasilvv1436e342020-10-09 12:31:16 -0700107 inline uint8_t TransportProtocolFromHeader(absl::string_view ipv6_header) {
wubf975eac2019-08-19 19:41:01 -0700108 return ipv6_header[6];
109 }
vasilvv1436e342020-10-09 12:31:16 -0700110 inline QuicIpAddress SourceIpFromHeader(absl::string_view ipv6_header) {
wubf975eac2019-08-19 19:41:01 -0700111 QuicIpAddress address;
112 address.FromPackedString(&ipv6_header[8],
113 QuicIpAddress::kIPv6AddressSize);
114 return address;
115 }
dmcardled70b99e2019-12-12 09:52:39 -0800116 inline QuicIpAddress DestinationIpFromHeader(
vasilvv1436e342020-10-09 12:31:16 -0700117 absl::string_view ipv6_header) {
wubf975eac2019-08-19 19:41:01 -0700118 QuicIpAddress address;
119 address.FromPackedString(&ipv6_header[24],
120 QuicIpAddress::kIPv6AddressSize);
121 return address;
122 }
123 };
124
125 // |self_ip| is the IP address from which the processor will originate ICMP
126 // messages. |client_ip| is the expected IP address of the client, used for
127 // packet validation.
128 //
129 // |output| and |stats| are the visitor interfaces used by the processor.
130 // |output| gets notified whenever the processor decides to send a packet, and
131 // |stats| gets notified about any decisions that processor makes, without a
132 // reference to which packet that decision was made about.
133 QbonePacketProcessor(QuicIpAddress self_ip,
134 QuicIpAddress client_ip,
135 size_t client_ip_subnet_length,
136 OutputInterface* output,
137 StatsInterface* stats);
138 QbonePacketProcessor(const QbonePacketProcessor&) = delete;
139 QbonePacketProcessor& operator=(const QbonePacketProcessor&) = delete;
140
141 // Accepts an IPv6 packet and handles it accordingly by either forwarding it,
142 // replying with an ICMP packet or silently dropping it. |packet| will be
143 // modified in the process, by having the TTL field decreased.
QUICHE teamb80d7c32020-02-23 23:44:20 -0800144 void ProcessPacket(std::string* packet, Direction direction);
wubf975eac2019-08-19 19:41:01 -0700145
146 void set_filter(std::unique_ptr<Filter> filter) {
147 filter_ = std::move(filter);
148 }
149
150 void set_client_ip(QuicIpAddress client_ip) { client_ip_ = client_ip; }
151 void set_client_ip_subnet_length(size_t client_ip_subnet_length) {
152 client_ip_subnet_length_ = client_ip_subnet_length;
153 }
154
155 static const QuicIpAddress kInvalidIpAddress;
156
157 protected:
158 // Processes the header and returns what should be done with the packet.
159 // After that, calls an external packet filter if registered. TTL of the
160 // packet may be decreased in the process.
QUICHE teamb80d7c32020-02-23 23:44:20 -0800161 ProcessingResult ProcessIPv6HeaderAndFilter(std::string* packet,
wubf975eac2019-08-19 19:41:01 -0700162 Direction direction,
163 uint8_t* transport_protocol,
164 char** transport_data,
165 icmp6_hdr* icmp_header);
166
167 void SendIcmpResponse(icmp6_hdr* icmp_header,
vasilvv1436e342020-10-09 12:31:16 -0700168 absl::string_view original_packet,
wubf975eac2019-08-19 19:41:01 -0700169 Direction original_direction);
170
vasilvv1436e342020-10-09 12:31:16 -0700171 void SendTcpReset(absl::string_view original_packet,
wubf975eac2019-08-19 19:41:01 -0700172 Direction original_direction);
173
174 inline bool IsValid() const { return client_ip_ != kInvalidIpAddress; }
175
176 // IP address of the server. Used to send ICMP messages.
177 in6_addr self_ip_;
178 // IP address range of the VPN client.
179 QuicIpAddress client_ip_;
180 size_t client_ip_subnet_length_;
181
182 OutputInterface* output_;
183 StatsInterface* stats_;
184 std::unique_ptr<Filter> filter_;
185
186 private:
187 // Performs basic sanity and permission checks on the packet, and decreases
188 // the TTL.
QUICHE teamb80d7c32020-02-23 23:44:20 -0800189 ProcessingResult ProcessIPv6Header(std::string* packet,
wubf975eac2019-08-19 19:41:01 -0700190 Direction direction,
191 uint8_t* transport_protocol,
192 char** transport_data,
193 icmp6_hdr* icmp_header);
194
vasilvv1436e342020-10-09 12:31:16 -0700195 void SendResponse(Direction original_direction, absl::string_view packet);
wubf975eac2019-08-19 19:41:01 -0700196};
197
198} // namespace quic
199#endif // QUICHE_QUIC_QBONE_QBONE_PACKET_PROCESSOR_H_