Line data Source code
1 : #pragma once
2 :
3 : #include <memory>
4 : #include <string>
5 : #include <vector>
6 :
7 : #include "envoy/common/optref.h"
8 : #include "envoy/common/platform.h"
9 : #include "envoy/common/pure.h"
10 : #include "envoy/config/core/v3/base.pb.h"
11 : #include "envoy/network/address.h"
12 : #include "envoy/network/io_handle.h"
13 : #include "envoy/ssl/connection.h"
14 :
15 : #include "absl/strings/string_view.h"
16 : #include "absl/types/optional.h"
17 :
18 : namespace Envoy {
19 : namespace Network {
20 :
21 : // SocketOptionName is an optional value that captures the setsockopt(2)
22 : // arguments. The idea here is that if a socket option is not supported
23 : // on a platform, we can make this the empty value, which allows us to
24 : // avoid #ifdef proliferation.
25 : struct SocketOptionName {
26 507 : SocketOptionName() = default;
27 : SocketOptionName(int level, int option, const std::string& name)
28 2684 : : value_(std::make_tuple(level, option, name)) {}
29 :
30 1582 : int level() const { return std::get<0>(value_.value()); }
31 1582 : int option() const { return std::get<1>(value_.value()); }
32 0 : const std::string& name() const { return std::get<2>(value_.value()); }
33 :
34 4273 : bool hasValue() const { return value_.has_value(); }
35 0 : bool operator==(const SocketOptionName& rhs) const { return value_ == rhs.value_; }
36 :
37 : private:
38 : absl::optional<std::tuple<int, int, std::string>> value_;
39 : };
40 :
41 : // ENVOY_MAKE_SOCKET_OPTION_NAME is a helper macro to generate a
42 : // SocketOptionName with a descriptive string name.
43 : #define ENVOY_MAKE_SOCKET_OPTION_NAME(level, option) \
44 2684 : ::Envoy::Network::SocketOptionName(level, option, #level "/" #option)
45 :
46 : // Moved from source/common/network/socket_option_impl.h to avoid dependency loops.
47 : #ifdef IP_TRANSPARENT
48 227 : #define ENVOY_SOCKET_IP_TRANSPARENT ENVOY_MAKE_SOCKET_OPTION_NAME(IPPROTO_IP, IP_TRANSPARENT)
49 : #else
50 : #define ENVOY_SOCKET_IP_TRANSPARENT Network::SocketOptionName()
51 : #endif
52 :
53 : #ifdef IPV6_TRANSPARENT
54 136 : #define ENVOY_SOCKET_IPV6_TRANSPARENT ENVOY_MAKE_SOCKET_OPTION_NAME(IPPROTO_IPV6, IPV6_TRANSPARENT)
55 : #else
56 : #define ENVOY_SOCKET_IPV6_TRANSPARENT Network::SocketOptionName()
57 : #endif
58 :
59 : #ifdef IP_FREEBIND
60 91 : #define ENVOY_SOCKET_IP_FREEBIND ENVOY_MAKE_SOCKET_OPTION_NAME(IPPROTO_IP, IP_FREEBIND)
61 : #else
62 : #define ENVOY_SOCKET_IP_FREEBIND Network::SocketOptionName()
63 : #endif
64 :
65 : #ifdef IPV6_FREEBIND
66 91 : #define ENVOY_SOCKET_IPV6_FREEBIND ENVOY_MAKE_SOCKET_OPTION_NAME(IPPROTO_IPV6, IPV6_FREEBIND)
67 : #else
68 : #define ENVOY_SOCKET_IPV6_FREEBIND Network::SocketOptionName()
69 : #endif
70 :
71 : #ifdef SO_KEEPALIVE
72 0 : #define ENVOY_SOCKET_SO_KEEPALIVE ENVOY_MAKE_SOCKET_OPTION_NAME(SOL_SOCKET, SO_KEEPALIVE)
73 : #else
74 : #define ENVOY_SOCKET_SO_KEEPALIVE Network::SocketOptionName()
75 : #endif
76 :
77 : #ifdef SO_MARK
78 25 : #define ENVOY_SOCKET_SO_MARK ENVOY_MAKE_SOCKET_OPTION_NAME(SOL_SOCKET, SO_MARK)
79 : #else
80 : #define ENVOY_SOCKET_SO_MARK Network::SocketOptionName()
81 : #endif
82 :
83 : #ifdef SO_NOSIGPIPE
84 : #define ENVOY_SOCKET_SO_NOSIGPIPE ENVOY_MAKE_SOCKET_OPTION_NAME(SOL_SOCKET, SO_NOSIGPIPE)
85 : #else
86 293 : #define ENVOY_SOCKET_SO_NOSIGPIPE Network::SocketOptionName()
87 : #endif
88 :
89 : #ifdef SO_REUSEPORT
90 134 : #define ENVOY_SOCKET_SO_REUSEPORT ENVOY_MAKE_SOCKET_OPTION_NAME(SOL_SOCKET, SO_REUSEPORT)
91 : #else
92 : #define ENVOY_SOCKET_SO_REUSEPORT Network::SocketOptionName()
93 : #endif
94 :
95 : #ifdef SO_ORIGINAL_DST
96 99 : #define ENVOY_SOCKET_SO_ORIGINAL_DST ENVOY_MAKE_SOCKET_OPTION_NAME(SOL_IP, SO_ORIGINAL_DST)
97 : #else
98 : #define ENVOY_SOCKET_SO_ORIGINAL_DST Network::SocketOptionName()
99 : #endif
100 :
101 : #ifdef IP6T_SO_ORIGINAL_DST
102 : #define ENVOY_SOCKET_IP6T_SO_ORIGINAL_DST \
103 8 : ENVOY_MAKE_SOCKET_OPTION_NAME(SOL_IPV6, IP6T_SO_ORIGINAL_DST)
104 : #else
105 : #define ENVOY_SOCKET_IP6T_SO_ORIGINAL_DST Network::SocketOptionName()
106 : #endif
107 :
108 : #ifdef UDP_GRO
109 0 : #define ENVOY_SOCKET_UDP_GRO ENVOY_MAKE_SOCKET_OPTION_NAME(SOL_UDP, UDP_GRO)
110 : #else
111 : #define ENVOY_SOCKET_UDP_GRO Network::SocketOptionName()
112 : #endif
113 :
114 : #ifdef TCP_KEEPCNT
115 0 : #define ENVOY_SOCKET_TCP_KEEPCNT ENVOY_MAKE_SOCKET_OPTION_NAME(IPPROTO_TCP, TCP_KEEPCNT)
116 : #else
117 : #define ENVOY_SOCKET_TCP_KEEPCNT Network::SocketOptionName()
118 : #endif
119 :
120 : #ifdef TCP_KEEPIDLE
121 0 : #define ENVOY_SOCKET_TCP_KEEPIDLE ENVOY_MAKE_SOCKET_OPTION_NAME(IPPROTO_TCP, TCP_KEEPIDLE)
122 : #elif TCP_KEEPALIVE // macOS uses a different name from Linux for just this option.
123 : #define ENVOY_SOCKET_TCP_KEEPIDLE ENVOY_MAKE_SOCKET_OPTION_NAME(IPPROTO_TCP, TCP_KEEPALIVE)
124 : #else
125 : #define ENVOY_SOCKET_TCP_KEEPIDLE Network::SocketOptionName()
126 : #endif
127 :
128 : #ifdef TCP_KEEPINTVL
129 0 : #define ENVOY_SOCKET_TCP_KEEPINTVL ENVOY_MAKE_SOCKET_OPTION_NAME(IPPROTO_TCP, TCP_KEEPINTVL)
130 : #else
131 : #define ENVOY_SOCKET_TCP_KEEPINTVL Network::SocketOptionName()
132 : #endif
133 :
134 : #ifdef TCP_FASTOPEN
135 1 : #define ENVOY_SOCKET_TCP_FASTOPEN ENVOY_MAKE_SOCKET_OPTION_NAME(IPPROTO_TCP, TCP_FASTOPEN)
136 : #else
137 : #define ENVOY_SOCKET_TCP_FASTOPEN Network::SocketOptionName()
138 : #endif
139 :
140 : // Linux uses IP_PKTINFO for both sending source address and receiving destination
141 : // address.
142 : // FreeBSD uses IP_RECVDSTADDR for receiving destination address and IP_SENDSRCADDR for sending
143 : // source address. And these two have same value for convenience purpose.
144 : #ifdef IP_RECVDSTADDR
145 : #ifdef IP_SENDSRCADDR
146 : static_assert(IP_RECVDSTADDR == IP_SENDSRCADDR);
147 : #endif
148 : #define ENVOY_IP_PKTINFO IP_RECVDSTADDR
149 : #elif IP_PKTINFO
150 : #define ENVOY_IP_PKTINFO IP_PKTINFO
151 : #endif
152 :
153 606 : #define ENVOY_SELF_IP_ADDR ENVOY_MAKE_SOCKET_OPTION_NAME(IPPROTO_IP, ENVOY_IP_PKTINFO)
154 :
155 : // Both Linux and FreeBSD use IPV6_RECVPKTINFO for both sending source address and
156 : // receiving destination address.
157 606 : #define ENVOY_SELF_IPV6_ADDR ENVOY_MAKE_SOCKET_OPTION_NAME(IPPROTO_IPV6, IPV6_RECVPKTINFO)
158 :
159 : #ifdef SO_ATTACH_REUSEPORT_CBPF
160 : #define ENVOY_ATTACH_REUSEPORT_CBPF \
161 0 : ENVOY_MAKE_SOCKET_OPTION_NAME(SOL_SOCKET, SO_ATTACH_REUSEPORT_CBPF)
162 : #else
163 : #define ENVOY_ATTACH_REUSEPORT_CBPF Network::SocketOptionName()
164 : #endif
165 :
166 : /**
167 : * Interface representing a single filter chain info.
168 : */
169 : class FilterChainInfo {
170 : public:
171 1042 : virtual ~FilterChainInfo() = default;
172 :
173 : /**
174 : * @return the name of this filter chain.
175 : */
176 : virtual absl::string_view name() const PURE;
177 : };
178 :
179 : class ListenerInfo;
180 :
181 : using FilterChainInfoConstSharedPtr = std::shared_ptr<const FilterChainInfo>;
182 :
183 : /**
184 : * Interfaces for providing a socket's various addresses. This is split into a getters interface
185 : * and a getters + setters interface. This is so that only the getters portion can be overridden
186 : * in certain cases.
187 : */
188 : class ConnectionInfoProvider {
189 : public:
190 6485 : virtual ~ConnectionInfoProvider() = default;
191 :
192 : /**
193 : * @return the local address of the socket.
194 : */
195 : virtual const Address::InstanceConstSharedPtr& localAddress() const PURE;
196 :
197 : /**
198 : * @return true if the local address has been restored to a value that is different from the
199 : * address the socket was initially accepted at.
200 : */
201 : virtual bool localAddressRestored() const PURE;
202 :
203 : /**
204 : * @return the remote address of the socket.
205 : */
206 : virtual const Address::InstanceConstSharedPtr& remoteAddress() const PURE;
207 :
208 : /**
209 : * @return the direct remote address of the socket. This is the address of the directly
210 : * connected peer, and cannot be modified by listener filters.
211 : */
212 : virtual const Address::InstanceConstSharedPtr& directRemoteAddress() const PURE;
213 :
214 : /**
215 : * @return SNI value for downstream host.
216 : */
217 : virtual absl::string_view requestedServerName() const PURE;
218 :
219 : /**
220 : * @return Connection ID of the downstream connection, or unset if not available.
221 : **/
222 : virtual absl::optional<uint64_t> connectionID() const PURE;
223 :
224 : /**
225 : * @return the name of the network interface used by local end of the connection, or unset if not
226 : *available.
227 : **/
228 : virtual absl::optional<absl::string_view> interfaceName() const PURE;
229 :
230 : /**
231 : * Dumps the state of the ConnectionInfoProvider to the given ostream.
232 : *
233 : * @param os the std::ostream to dump to.
234 : * @param indent_level the level of indentation.
235 : */
236 : virtual void dumpState(std::ostream& os, int indent_level) const PURE;
237 :
238 : /**
239 : * @return the downstream SSL connection. This will be nullptr if the downstream
240 : * connection does not use SSL.
241 : */
242 : virtual Ssl::ConnectionInfoConstSharedPtr sslConnection() const PURE;
243 :
244 : /**
245 : * @return ja3 fingerprint hash of the downstream connection, if any.
246 : */
247 : virtual absl::string_view ja3Hash() const PURE;
248 :
249 : /**
250 : * @return roundTripTime of the connection
251 : */
252 : virtual const absl::optional<std::chrono::milliseconds>& roundTripTime() const PURE;
253 :
254 : /**
255 : * @return the filter chain info provider backing this socket.
256 : */
257 : virtual OptRef<const FilterChainInfo> filterChainInfo() const PURE;
258 :
259 : /**
260 : * @return the listener info backing this socket.
261 : */
262 : virtual OptRef<const ListenerInfo> listenerInfo() const PURE;
263 : };
264 :
265 : class ConnectionInfoSetter : public ConnectionInfoProvider {
266 : public:
267 : /**
268 : * Set the local address of the socket. On accepted sockets the local address defaults to the
269 : * one at which the connection was received at, which is the same as the listener's address, if
270 : * the listener is bound to a specific address.
271 : *
272 : * @param local_address the new local address.
273 : */
274 : virtual void setLocalAddress(const Address::InstanceConstSharedPtr& local_address) PURE;
275 :
276 : /**
277 : * Restores the local address of the socket. On accepted sockets the local address defaults to the
278 : * one at which the connection was received at, which is the same as the listener's address, if
279 : * the listener is bound to a specific address. Call this to restore the address to a value
280 : * different from the one the socket was initially accepted at. This should only be called when
281 : * restoring the original destination address of a connection redirected by iptables REDIRECT. The
282 : * caller is responsible for making sure the new address is actually different.
283 : *
284 : * @param local_address the new local address.
285 : */
286 : virtual void restoreLocalAddress(const Address::InstanceConstSharedPtr& local_address) PURE;
287 :
288 : /**
289 : * Set the remote address of the socket.
290 : */
291 : virtual void setRemoteAddress(const Address::InstanceConstSharedPtr& remote_address) PURE;
292 :
293 : /**
294 : * @param SNI value requested.
295 : */
296 : virtual void setRequestedServerName(const absl::string_view requested_server_name) PURE;
297 :
298 : /**
299 : * @param id Connection ID of the downstream connection.
300 : **/
301 : virtual void setConnectionID(uint64_t id) PURE;
302 :
303 : /**
304 : * @param enable whether to enable or disable setting interface name. While having an interface
305 : * name might be helpful for debugging, it might come at a performance cost.
306 : */
307 : virtual void enableSettingInterfaceName(const bool enable) PURE;
308 :
309 : /**
310 : * @param interface_name the name of the network interface used by the local end of the
311 : *connection.
312 : **/
313 : virtual void maybeSetInterfaceName(IoHandle& io_handle) PURE;
314 :
315 : /**
316 : * @param connection_info sets the downstream ssl connection.
317 : */
318 : virtual void setSslConnection(const Ssl::ConnectionInfoConstSharedPtr& ssl_connection_info) PURE;
319 :
320 : /**
321 : * @param JA3 fingerprint.
322 : */
323 : virtual void setJA3Hash(const absl::string_view ja3_hash) PURE;
324 :
325 : /**
326 : * @param milliseconds of round trip time of previous connection
327 : */
328 : virtual void setRoundTripTime(std::chrono::milliseconds round_trip_time) PURE;
329 :
330 : /**
331 : * @param filter_chain_info the filter chain info provider backing this socket.
332 : */
333 : virtual void setFilterChainInfo(FilterChainInfoConstSharedPtr filter_chain_info) PURE;
334 :
335 : /**
336 : * @param listener_info the listener info provider backing this socket.
337 : */
338 : virtual void setListenerInfo(std::shared_ptr<const ListenerInfo> listener_info) PURE;
339 : };
340 :
341 : using ConnectionInfoSetterSharedPtr = std::shared_ptr<ConnectionInfoSetter>;
342 : using ConnectionInfoProviderSharedPtr = std::shared_ptr<const ConnectionInfoProvider>;
343 :
344 : /**
345 : * Base class for Sockets
346 : */
347 : class Socket {
348 : public:
349 4435 : virtual ~Socket() = default;
350 :
351 : /**
352 : * Type of sockets supported. See man 2 socket for more details
353 : */
354 : enum class Type { Stream, Datagram };
355 :
356 : /**
357 : * @return the connection info provider backing this socket.
358 : */
359 : virtual ConnectionInfoSetter& connectionInfoProvider() PURE;
360 : virtual const ConnectionInfoProvider& connectionInfoProvider() const PURE;
361 : virtual ConnectionInfoProviderSharedPtr connectionInfoProviderSharedPtr() const PURE;
362 :
363 : /**
364 : * @return IoHandle for the underlying connection
365 : */
366 : virtual IoHandle& ioHandle() PURE;
367 :
368 : /**
369 : * @return const IoHandle for the underlying connection
370 : */
371 : virtual const IoHandle& ioHandle() const PURE;
372 :
373 : /**
374 : * Used to duplicate the underlying file descriptor of the socket.
375 : * @return a pointer to the new Socket.
376 : */
377 : virtual std::unique_ptr<Socket> duplicate() PURE;
378 :
379 : /**
380 : * @return the type (stream or datagram) of the socket.
381 : */
382 : virtual Socket::Type socketType() const PURE;
383 :
384 : /**
385 : * @return the type (IP or pipe) of addresses used by the socket (subset of socket domain)
386 : */
387 : virtual Address::Type addressType() const PURE;
388 :
389 : /**
390 : * @return the IP version used by the socket if address type is IP, absl::nullopt otherwise
391 : */
392 : virtual absl::optional<Address::IpVersion> ipVersion() const PURE;
393 :
394 : /**
395 : * Close the underlying socket.
396 : */
397 : virtual void close() PURE;
398 :
399 : /**
400 : * Return true if close() hasn't been called.
401 : */
402 : virtual bool isOpen() const PURE;
403 :
404 : /**
405 : * Bind a socket to this address. The socket should have been created with a call to socket()
406 : * @param address address to bind the socket to.
407 : * @return a Api::SysCallIntResult with rc_ = 0 for success and rc_ = -1 for failure. If the call
408 : * is successful, errno_ shouldn't be used.
409 : */
410 : virtual Api::SysCallIntResult bind(const Address::InstanceConstSharedPtr address) PURE;
411 :
412 : /**
413 : * Listen on bound socket.
414 : * @param backlog maximum number of pending connections for listener
415 : * @return a Api::SysCallIntResult with rc_ = 0 for success and rc_ = -1 for failure. If the call
416 : * is successful, errno_ shouldn't be used.
417 : */
418 : virtual Api::SysCallIntResult listen(int backlog) PURE;
419 :
420 : /**
421 : * Connect a socket to this address. The socket should have been created with a call to socket()
422 : * on this object.
423 : * @param address remote address to connect to.
424 : * @return a Api::SysCallIntResult with rc_ = 0 for success and rc_ = -1 for failure. If the call
425 : * is successful, errno_ shouldn't be used.
426 : */
427 : virtual Api::SysCallIntResult connect(const Address::InstanceConstSharedPtr address) PURE;
428 :
429 : /**
430 : * @see MSDN WSAIoctl. Controls the mode of a socket.
431 : */
432 : virtual Api::SysCallIntResult ioctl(unsigned long control_code, void* in_buffer,
433 : unsigned long in_buffer_len, void* out_buffer,
434 : unsigned long out_buffer_len,
435 : unsigned long* bytes_returned) PURE;
436 :
437 : /**
438 : * Propagates option to underlying socket (@see man 2 setsockopt)
439 : */
440 : virtual Api::SysCallIntResult setSocketOption(int level, int optname, const void* optval,
441 : socklen_t optlen) PURE;
442 :
443 : /**
444 : * Retrieves option from underlying socket (@see man 2 getsockopt)
445 : */
446 : virtual Api::SysCallIntResult getSocketOption(int level, int optname, void* optval,
447 : socklen_t* optlen) const PURE;
448 :
449 : /**
450 : * Toggle socket blocking state
451 : */
452 : virtual Api::SysCallIntResult setBlockingForTest(bool blocking) PURE;
453 :
454 : /**
455 : * Visitor class for setting socket options.
456 : */
457 : class Option {
458 : public:
459 3359 : virtual ~Option() = default;
460 :
461 : /**
462 : * @param socket the socket on which to apply options.
463 : * @param state the current state of the socket. Significant for options that can only be
464 : * set for some particular state of the socket.
465 : * @return true if succeeded, false otherwise.
466 : */
467 : virtual bool setOption(Socket& socket,
468 : envoy::config::core::v3::SocketOption::SocketState state) const PURE;
469 :
470 : /**
471 : * @param vector of bytes to which the option should append hash key data that will be used
472 : * to separate connections based on the option. Any data already in the key vector must
473 : * not be modified.
474 : */
475 : virtual void hashKey(std::vector<uint8_t>& key) const PURE;
476 :
477 : /**
478 : * Contains details about what this option applies to a socket.
479 : */
480 : struct Details {
481 : SocketOptionName name_;
482 : std::string value_; ///< Binary string representation of an option's value.
483 :
484 0 : bool operator==(const Details& other) const {
485 0 : return name_ == other.name_ && value_ == other.value_;
486 0 : }
487 : };
488 :
489 : /**
490 : * @param socket The socket for which we want to know the options that would be applied.
491 : * @param state The state at which we would apply the options.
492 : * @return What we would apply to the socket at the provided state. Empty if we'd apply nothing.
493 : */
494 : virtual absl::optional<Details>
495 : getOptionDetails(const Socket& socket,
496 : envoy::config::core::v3::SocketOption::SocketState state) const PURE;
497 :
498 : /**
499 : * Whether the socket implementation is supported. Real implementations should typically return
500 : * true. Placeholder implementations may indicate such by returning false. Note this does NOT
501 : * inherently prevent an option from being applied if it's passed to socket/connection
502 : * interfaces.
503 : * @return Whether this is a supported socket option.
504 : */
505 : virtual bool isSupported() const PURE;
506 : };
507 :
508 : using OptionConstPtr = std::unique_ptr<const Option>;
509 : using OptionConstSharedPtr = std::shared_ptr<const Option>;
510 : using Options = std::vector<OptionConstSharedPtr>;
511 : using OptionsSharedPtr = std::shared_ptr<Options>;
512 :
513 2317 : static OptionsSharedPtr& appendOptions(OptionsSharedPtr& to, const OptionsSharedPtr& from) {
514 2317 : to->insert(to->end(), from->begin(), from->end());
515 2317 : return to;
516 2317 : }
517 :
518 : static bool applyOptions(const OptionsSharedPtr& options, Socket& socket,
519 3574 : envoy::config::core::v3::SocketOption::SocketState state) {
520 3574 : if (options == nullptr) {
521 1688 : return true;
522 1688 : }
523 3008 : for (const auto& option : *options) {
524 2737 : if (!option->setOption(socket, state)) {
525 0 : return false;
526 0 : }
527 2737 : }
528 1886 : return true;
529 1886 : }
530 :
531 : /**
532 : * Add a socket option visitor for later retrieval with options().
533 : */
534 : virtual void addOption(const OptionConstSharedPtr&) PURE;
535 :
536 : /**
537 : * Add socket option visitors for later retrieval with options().
538 : */
539 : virtual void addOptions(const OptionsSharedPtr&) PURE;
540 :
541 : /**
542 : * @return the socket options stored earlier with addOption() and addOptions() calls, if any.
543 : */
544 : virtual const OptionsSharedPtr& options() const PURE;
545 : };
546 :
547 : using SocketPtr = std::unique_ptr<Socket>;
548 : using SocketSharedPtr = std::shared_ptr<Socket>;
549 : using SocketOptRef = absl::optional<std::reference_wrapper<Socket>>;
550 :
551 : } // namespace Network
552 : } // namespace Envoy
|