Line data Source code
1 : #pragma once
2 :
3 : #include <sys/types.h>
4 :
5 : #include <array>
6 : #include <cstdint>
7 : #include <string>
8 :
9 : #include "envoy/common/platform.h"
10 : #include "envoy/network/address.h"
11 : #include "envoy/network/socket.h"
12 :
13 : #include "source/common/common/assert.h"
14 : #include "source/common/common/statusor.h"
15 :
16 : namespace Envoy {
17 : namespace Network {
18 : namespace Address {
19 :
20 : /**
21 : * Check whether we are a) on Android or an Apple platform and b) configured via runtime to always
22 : * use v6 sockets.
23 : * This appears to be what Android OS does for all platform sockets.
24 : */
25 : bool forceV6();
26 :
27 : /**
28 : * Convert an address in the form of the socket address struct defined by Posix, Linux, etc. into
29 : * a Network::Address::Instance and return a pointer to it. Raises an EnvoyException on failure.
30 : * @param ss a valid address with family AF_INET, AF_INET6 or AF_UNIX.
31 : * @param len length of the address (e.g. from accept, getsockname or getpeername). If len > 0,
32 : * it is used to validate the structure contents; else if len == 0, it is ignored.
33 : * @param v6only disable IPv4-IPv6 mapping for IPv6 addresses?
34 : * @return InstanceConstSharedPtr the address.
35 : */
36 : StatusOr<InstanceConstSharedPtr> addressFromSockAddr(const sockaddr_storage& ss, socklen_t len,
37 : bool v6only = true);
38 : InstanceConstSharedPtr addressFromSockAddrOrThrow(const sockaddr_storage& ss, socklen_t len,
39 : bool v6only = true);
40 :
41 : /**
42 : * Convert an address in the form of the socket address struct defined by Posix, Linux, etc. into
43 : * a Network::Address::Instance and return a pointer to it. Die on failure.
44 : * @param ss a valid address with family AF_INET, AF_INET6 or AF_UNIX.
45 : * @param len length of the address (e.g. from accept, getsockname or getpeername). If len > 0,
46 : * it is used to validate the structure contents; else if len == 0, it is ignored.
47 : * @param fd the file descriptor for the created address instance.
48 : * @param v6only disable IPv4-IPv6 mapping for IPv6 addresses?
49 : * @return InstanceConstSharedPtr the address.
50 : */
51 : InstanceConstSharedPtr addressFromSockAddrOrDie(const sockaddr_storage& ss, socklen_t ss_len,
52 : os_fd_t fd, bool v6only = true);
53 :
54 : /**
55 : * Base class for all address types.
56 : */
57 : class InstanceBase : public Instance {
58 : public:
59 : // Network::Address::Instance
60 1404 : const std::string& asString() const override { return friendly_name_; }
61 607 : absl::string_view asStringView() const override { return friendly_name_; }
62 : // Default logical name is the human-readable name.
63 0 : const std::string& logicalName() const override { return asString(); }
64 22987 : Type type() const override { return type_; }
65 :
66 2645 : const SocketInterface& socketInterface() const override { return socket_interface_; }
67 :
68 : protected:
69 : InstanceBase(Type type, const SocketInterface* sock_interface)
70 200008 : : socket_interface_(*sock_interface), type_(type) {}
71 :
72 : std::string friendly_name_;
73 : const SocketInterface& socket_interface_;
74 :
75 : private:
76 : const Type type_;
77 : };
78 :
79 : // Create an address instance. Upon failure, return an error status without throwing.
80 : class InstanceFactory {
81 : public:
82 : template <typename InstanceType, typename... Args>
83 190951 : static StatusOr<InstanceConstSharedPtr> createInstancePtr(Args&&... args) {
84 190951 : absl::Status status;
85 : // Use new instead of make_shared here because the instance constructors are private and must be
86 : // called directly here.
87 190951 : std::shared_ptr<InstanceType> instance(new InstanceType(status, std::forward<Args>(args)...));
88 190951 : if (!status.ok()) {
89 0 : return status;
90 0 : }
91 190951 : return instance;
92 190951 : }
93 : };
94 :
95 : /**
96 : * Implementation of an IPv4 address.
97 : */
98 : class Ipv4Instance : public InstanceBase {
99 : public:
100 : /**
101 : * Construct from an existing unix IPv4 socket address (IP v4 address and port).
102 : */
103 : explicit Ipv4Instance(const sockaddr_in* address,
104 : const SocketInterface* sock_interface = nullptr);
105 :
106 : /**
107 : * Construct from a string IPv4 address such as "1.2.3.4". Port will be unset/0.
108 : */
109 : explicit Ipv4Instance(const std::string& address,
110 : const SocketInterface* sock_interface = nullptr);
111 :
112 : /**
113 : * Construct from a string IPv4 address such as "1.2.3.4" as well as a port.
114 : */
115 : Ipv4Instance(const std::string& address, uint32_t port,
116 : const SocketInterface* sock_interface = nullptr);
117 :
118 : /**
119 : * Construct from a port. The IPv4 address will be set to "any" and is suitable for binding
120 : * a port to any available address.
121 : */
122 : explicit Ipv4Instance(uint32_t port, const SocketInterface* sock_interface = nullptr);
123 :
124 : // Network::Address::Instance
125 : bool operator==(const Instance& rhs) const override;
126 22831 : const Ip* ip() const override { return &ip_; }
127 0 : const Pipe* pipe() const override { return nullptr; }
128 0 : const EnvoyInternalAddress* envoyInternalAddress() const override { return nullptr; }
129 2793 : const sockaddr* sockAddr() const override {
130 2793 : return reinterpret_cast<const sockaddr*>(&ip_.ipv4_.address_);
131 2793 : }
132 2793 : socklen_t sockAddrLen() const override { return sizeof(sockaddr_in); }
133 1328 : absl::string_view addressType() const override { return "default"; }
134 :
135 : /**
136 : * Convenience function to convert an IPv4 address to canonical string format.
137 : * @note This works similarly to inet_ntop() but is faster.
138 : * @param addr address to format.
139 : * @return the address in dotted-decimal string format.
140 : */
141 : static std::string sockaddrToString(const sockaddr_in& addr);
142 :
143 : // Validate that IPv4 is supported on this platform, raise an exception for the
144 : // given address if not.
145 : static absl::Status validateProtocolSupported();
146 :
147 : private:
148 : /**
149 : * Construct from an existing unix IPv4 socket address (IP v4 address and port).
150 : * Store the status code in passed in parameter instead of throwing.
151 : * It is called by the factory method and the partially constructed instance will be discarded
152 : * upon error.
153 : */
154 : explicit Ipv4Instance(absl::Status& error, const sockaddr_in* address,
155 : const SocketInterface* sock_interface = nullptr);
156 :
157 : struct Ipv4Helper : public Ipv4 {
158 3328 : uint32_t address() const override { return address_.sin_addr.s_addr; }
159 :
160 : sockaddr_in address_;
161 : };
162 :
163 : struct IpHelper : public Ip {
164 400 : const std::string& addressAsString() const override { return friendly_address_; }
165 698 : bool isAnyAddress() const override { return ipv4_.address_.sin_addr.s_addr == INADDR_ANY; }
166 0 : bool isUnicastAddress() const override {
167 0 : return !isAnyAddress() && (ipv4_.address_.sin_addr.s_addr != INADDR_BROADCAST) &&
168 : // inlined IN_MULTICAST() to avoid byte swapping
169 0 : !((ipv4_.address_.sin_addr.s_addr & htonl(0xf0000000)) == htonl(0xe0000000));
170 0 : }
171 3292 : const Ipv4* ipv4() const override { return &ipv4_; }
172 0 : const Ipv6* ipv6() const override { return nullptr; }
173 3997 : uint32_t port() const override { return ntohs(ipv4_.address_.sin_port); }
174 9545 : IpVersion version() const override { return IpVersion::v4; }
175 :
176 : Ipv4Helper ipv4_;
177 : std::string friendly_address_;
178 : };
179 :
180 : void initHelper(const sockaddr_in* address);
181 :
182 : IpHelper ip_;
183 : friend class InstanceFactory;
184 : };
185 :
186 : /**
187 : * Implementation of an IPv6 address.
188 : */
189 : class Ipv6Instance : public InstanceBase {
190 : public:
191 : /**
192 : * Construct from an existing unix IPv6 socket address (IP v6 address and port).
193 : */
194 : Ipv6Instance(const sockaddr_in6& address, bool v6only = true,
195 : const SocketInterface* sock_interface = nullptr);
196 :
197 : /**
198 : * Construct from a string IPv6 address such as "12:34::5". Port will be unset/0.
199 : */
200 : explicit Ipv6Instance(const std::string& address,
201 : const SocketInterface* sock_interface = nullptr);
202 :
203 : /**
204 : * Construct from a string IPv6 address such as "12:34::5" as well as a port.
205 : */
206 : Ipv6Instance(const std::string& address, uint32_t port,
207 : const SocketInterface* sock_interface = nullptr, bool v6only = true);
208 :
209 : /**
210 : * Construct from a port. The IPv6 address will be set to "any" and is suitable for binding
211 : * a port to any available address.
212 : */
213 : explicit Ipv6Instance(uint32_t port, const SocketInterface* sock_interface = nullptr);
214 :
215 : // Network::Address::Instance
216 : bool operator==(const Instance& rhs) const override;
217 4794 : const Ip* ip() const override { return &ip_; }
218 0 : const Pipe* pipe() const override { return nullptr; }
219 0 : const EnvoyInternalAddress* envoyInternalAddress() const override { return nullptr; }
220 517 : const sockaddr* sockAddr() const override {
221 517 : return reinterpret_cast<const sockaddr*>(&ip_.ipv6_.address_);
222 517 : }
223 517 : socklen_t sockAddrLen() const override { return sizeof(sockaddr_in6); }
224 0 : absl::string_view addressType() const override { return "default"; }
225 :
226 : // Validate that IPv6 is supported on this platform
227 : static absl::Status validateProtocolSupported();
228 :
229 : private:
230 : /**
231 : * Construct from an existing unix IPv6 socket address (IP v6 address and port).
232 : * Store the status code in passed in parameter instead of throwing.
233 : * It is called by the factory method and the partially constructed instance will be discarded
234 : * upon error.
235 : */
236 : Ipv6Instance(absl::Status& error, const sockaddr_in6& address, bool v6only = true,
237 : const SocketInterface* sock_interface = nullptr);
238 :
239 : struct Ipv6Helper : public Ipv6 {
240 1081 : Ipv6Helper() { memset(&address_, 0, sizeof(address_)); }
241 : absl::uint128 address() const override;
242 : bool v6only() const override;
243 : uint32_t scopeId() const override;
244 : uint32_t port() const;
245 : InstanceConstSharedPtr v4CompatibleAddress() const override;
246 : InstanceConstSharedPtr addressWithoutScopeId() const override;
247 :
248 : std::string makeFriendlyAddress() const;
249 :
250 : sockaddr_in6 address_;
251 : // Is IPv4 compatibility (https://tools.ietf.org/html/rfc3493#page-11) disabled?
252 : // Default initialized to true to preserve extant Envoy behavior where we don't explicitly set
253 : // this in the constructor.
254 : bool v6only_{true};
255 : };
256 :
257 : struct IpHelper : public Ip {
258 2 : const std::string& addressAsString() const override { return friendly_address_; }
259 0 : bool isAnyAddress() const override {
260 0 : return 0 == memcmp(&ipv6_.address_.sin6_addr, &in6addr_any, sizeof(struct in6_addr));
261 0 : }
262 0 : bool isUnicastAddress() const override {
263 0 : return !isAnyAddress() && !IN6_IS_ADDR_MULTICAST(&ipv6_.address_.sin6_addr);
264 0 : }
265 0 : const Ipv4* ipv4() const override { return nullptr; }
266 938 : const Ipv6* ipv6() const override { return &ipv6_; }
267 1596 : uint32_t port() const override { return ipv6_.port(); }
268 2824 : IpVersion version() const override { return IpVersion::v6; }
269 :
270 : Ipv6Helper ipv6_;
271 : std::string friendly_address_;
272 : };
273 :
274 : void initHelper(const sockaddr_in6& address, bool v6only);
275 :
276 : IpHelper ip_;
277 : friend class InstanceFactory;
278 : };
279 :
280 : /**
281 : * Implementation of a pipe address (unix domain socket on unix).
282 : */
283 : class PipeInstance : public InstanceBase {
284 : public:
285 : /**
286 : * Construct from an existing unix address.
287 : */
288 : explicit PipeInstance(const sockaddr_un* address, socklen_t ss_len, mode_t mode = 0,
289 : const SocketInterface* sock_interface = nullptr);
290 :
291 : /**
292 : * Construct from a string pipe path.
293 : */
294 : explicit PipeInstance(const std::string& pipe_path, mode_t mode = 0,
295 : const SocketInterface* sock_interface = nullptr);
296 :
297 0 : static absl::Status validateProtocolSupported() { return absl::OkStatus(); }
298 :
299 : // Network::Address::Instance
300 : bool operator==(const Instance& rhs) const override;
301 10 : const Ip* ip() const override { return nullptr; }
302 10 : const Pipe* pipe() const override { return &pipe_; }
303 0 : const EnvoyInternalAddress* envoyInternalAddress() const override { return nullptr; }
304 10 : const sockaddr* sockAddr() const override {
305 10 : return reinterpret_cast<const sockaddr*>(&pipe_.address_);
306 10 : }
307 0 : const sockaddr_un& getSockAddr() const { return pipe_.address_; }
308 5 : socklen_t sockAddrLen() const override {
309 5 : if (pipe_.abstract_namespace_) {
310 5 : return offsetof(struct sockaddr_un, sun_path) + pipe_.address_length_;
311 5 : }
312 0 : return sizeof(pipe_.address_);
313 5 : }
314 0 : absl::string_view addressType() const override { return "default"; }
315 :
316 : private:
317 : /**
318 : * Construct from an existing unix address.
319 : * Store the error status code in passed in parameter instead of throwing.
320 : * It is called by the factory method and the partially constructed instance will be discarded
321 : * upon error.
322 : */
323 : PipeInstance(absl::Status& error, const sockaddr_un* address, socklen_t ss_len, mode_t mode = 0,
324 : const SocketInterface* sock_interface = nullptr);
325 :
326 : struct PipeHelper : public Pipe {
327 :
328 5 : bool abstractNamespace() const override { return abstract_namespace_; }
329 5 : mode_t mode() const override { return mode_; }
330 :
331 : sockaddr_un address_;
332 : // For abstract namespaces.
333 : bool abstract_namespace_{false};
334 : uint32_t address_length_{0};
335 : mode_t mode_{0};
336 : };
337 :
338 : absl::Status initHelper(const sockaddr_un* address, mode_t mode);
339 :
340 : PipeHelper pipe_;
341 : friend class InstanceFactory;
342 : };
343 :
344 : class EnvoyInternalInstance : public InstanceBase {
345 : public:
346 : /**
347 : * Construct from a string name.
348 : */
349 : explicit EnvoyInternalInstance(const std::string& address_id, const std::string& endpoint_id = "",
350 : const SocketInterface* sock_interface = nullptr);
351 :
352 : // Network::Address::Instance
353 : bool operator==(const Instance& rhs) const override;
354 0 : const Ip* ip() const override { return nullptr; }
355 0 : const Pipe* pipe() const override { return nullptr; }
356 0 : const EnvoyInternalAddress* envoyInternalAddress() const override { return &internal_address_; }
357 : // TODO(lambdai): Verify all callers accepts nullptr.
358 0 : const sockaddr* sockAddr() const override { return nullptr; }
359 0 : socklen_t sockAddrLen() const override { return 0; }
360 0 : absl::string_view addressType() const override { return "envoy_internal"; }
361 :
362 : private:
363 : struct EnvoyInternalAddressImpl : public EnvoyInternalAddress {
364 : explicit EnvoyInternalAddressImpl(const std::string& address_id, const std::string& endpoint_id)
365 4 : : address_id_(address_id), endpoint_id_(endpoint_id) {}
366 4 : ~EnvoyInternalAddressImpl() override = default;
367 0 : const std::string& addressId() const override { return address_id_; }
368 0 : const std::string& endpointId() const override { return endpoint_id_; }
369 : const std::string address_id_;
370 : const std::string endpoint_id_;
371 : };
372 : EnvoyInternalAddressImpl internal_address_;
373 : };
374 :
375 : } // namespace Address
376 : } // namespace Network
377 : } // namespace Envoy
|