/proc/self/cwd/source/common/network/address_impl.h
Line | Count | Source (jump to first uncovered line) |
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 | 43.3k | const std::string& asString() const override { return friendly_name_; } |
61 | 8.28k | 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 | 1.38M | Type type() const override { return type_; } |
65 | | |
66 | 34.0k | const SocketInterface& socketInterface() const override { return socket_interface_; } |
67 | | |
68 | | protected: |
69 | | InstanceBase(Type type, const SocketInterface* sock_interface) |
70 | 2.35M | : 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 | 963k | static StatusOr<InstanceConstSharedPtr> createInstancePtr(Args&&... args) { |
84 | 963k | 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 | 963k | std::shared_ptr<InstanceType> instance(new InstanceType(status, std::forward<Args>(args)...)); |
88 | 963k | if (!status.ok()) { |
89 | 0 | return status; |
90 | 0 | } |
91 | 963k | return instance; |
92 | 963k | } absl::StatusOr<std::__1::shared_ptr<Envoy::Network::Address::Instance const> > Envoy::Network::Address::InstanceFactory::createInstancePtr<Envoy::Network::Address::Ipv4Instance, sockaddr_in*>(sockaddr_in*&&) Line | Count | Source | 83 | 808k | static StatusOr<InstanceConstSharedPtr> createInstancePtr(Args&&... args) { | 84 | 808k | 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 | 808k | std::shared_ptr<InstanceType> instance(new InstanceType(status, std::forward<Args>(args)...)); | 88 | 808k | if (!status.ok()) { | 89 | 0 | return status; | 90 | 0 | } | 91 | 808k | return instance; | 92 | 808k | } |
absl::StatusOr<std::__1::shared_ptr<Envoy::Network::Address::Instance const> > Envoy::Network::Address::InstanceFactory::createInstancePtr<Envoy::Network::Address::Ipv6Instance, sockaddr_in6&, bool&>(sockaddr_in6&, bool&) Line | Count | Source | 83 | 127k | static StatusOr<InstanceConstSharedPtr> createInstancePtr(Args&&... args) { | 84 | 127k | 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 | 127k | std::shared_ptr<InstanceType> instance(new InstanceType(status, std::forward<Args>(args)...)); | 88 | 127k | if (!status.ok()) { | 89 | 0 | return status; | 90 | 0 | } | 91 | 127k | return instance; | 92 | 127k | } |
absl::StatusOr<std::__1::shared_ptr<Envoy::Network::Address::Instance const> > Envoy::Network::Address::InstanceFactory::createInstancePtr<Envoy::Network::Address::Ipv4Instance, sockaddr_in const*&>(sockaddr_in const*&) Line | Count | Source | 83 | 28.5k | static StatusOr<InstanceConstSharedPtr> createInstancePtr(Args&&... args) { | 84 | 28.5k | 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 | 28.5k | std::shared_ptr<InstanceType> instance(new InstanceType(status, std::forward<Args>(args)...)); | 88 | 28.5k | if (!status.ok()) { | 89 | 0 | return status; | 90 | 0 | } | 91 | 28.5k | return instance; | 92 | 28.5k | } |
absl::StatusOr<std::__1::shared_ptr<Envoy::Network::Address::Instance const> > Envoy::Network::Address::InstanceFactory::createInstancePtr<Envoy::Network::Address::Ipv6Instance, sockaddr_in6 const&, bool&>(sockaddr_in6 const&, bool&) Line | Count | Source | 83 | 109 | static StatusOr<InstanceConstSharedPtr> createInstancePtr(Args&&... args) { | 84 | 109 | 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 | 109 | std::shared_ptr<InstanceType> instance(new InstanceType(status, std::forward<Args>(args)...)); | 88 | 109 | if (!status.ok()) { | 89 | 0 | return status; | 90 | 0 | } | 91 | 109 | return instance; | 92 | 109 | } |
Unexecuted instantiation: absl::StatusOr<std::__1::shared_ptr<Envoy::Network::Address::Instance const> > Envoy::Network::Address::InstanceFactory::createInstancePtr<Envoy::Network::Address::PipeInstance, sockaddr_un const*&, unsigned int&>(sockaddr_un const*&, unsigned int&) Unexecuted instantiation: absl::StatusOr<std::__1::shared_ptr<Envoy::Network::Address::Instance const> > Envoy::Network::Address::InstanceFactory::createInstancePtr<Envoy::Network::Address::Ipv6Instance, sockaddr_in6&, bool const&>(sockaddr_in6&, bool const&) |
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 | 1.47M | 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 | 15.6k | const sockaddr* sockAddr() const override { |
130 | 15.6k | return reinterpret_cast<const sockaddr*>(&ip_.ipv4_.address_); |
131 | 15.6k | } |
132 | 15.6k | socklen_t sockAddrLen() const override { return sizeof(sockaddr_in); } |
133 | 7.60k | 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 | 328k | uint32_t address() const override { return address_.sin_addr.s_addr; } |
159 | | |
160 | | sockaddr_in address_; |
161 | | }; |
162 | | |
163 | | struct IpHelper : public Ip { |
164 | 136k | const std::string& addressAsString() const override { return friendly_address_; } |
165 | 7.97k | 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 | 328k | const Ipv4* ipv4() const override { return &ipv4_; } |
172 | 0 | const Ipv6* ipv6() const override { return nullptr; } |
173 | 107k | uint32_t port() const override { return ntohs(ipv4_.address_.sin_port); } |
174 | 848k | 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 | 608k | 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 | 16.4k | const sockaddr* sockAddr() const override { |
221 | 16.4k | return reinterpret_cast<const sockaddr*>(&ip_.ipv6_.address_); |
222 | 16.4k | } |
223 | 16.4k | 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 | 252k | 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 | 995 | const std::string& addressAsString() const override { return friendly_address_; } |
259 | 24 | bool isAnyAddress() const override { |
260 | 24 | return 0 == memcmp(&ipv6_.address_.sin6_addr, &in6addr_any, sizeof(struct in6_addr)); |
261 | 24 | } |
262 | 0 | bool isUnicastAddress() const override { |
263 | 0 | return !isAnyAddress() && !IN6_IS_ADDR_MULTICAST(&ipv6_.address_.sin6_addr); |
264 | 0 | } |
265 | 2 | const Ipv4* ipv4() const override { return nullptr; } |
266 | 150k | const Ipv6* ipv6() const override { return &ipv6_; } |
267 | 253k | uint32_t port() const override { return ipv6_.port(); } |
268 | 422k | 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 | 15.2k | const Ip* ip() const override { return nullptr; } |
302 | 3.93k | const Pipe* pipe() const override { return &pipe_; } |
303 | 0 | const EnvoyInternalAddress* envoyInternalAddress() const override { return nullptr; } |
304 | 3.93k | const sockaddr* sockAddr() const override { |
305 | 3.93k | return reinterpret_cast<const sockaddr*>(&pipe_.address_); |
306 | 3.93k | } |
307 | 0 | const sockaddr_un& getSockAddr() const { return pipe_.address_; } |
308 | 1.96k | socklen_t sockAddrLen() const override { |
309 | 1.96k | if (pipe_.abstract_namespace_) { |
310 | 1.85k | return offsetof(struct sockaddr_un, sun_path) + pipe_.address_length_; |
311 | 1.85k | } |
312 | 115 | return sizeof(pipe_.address_); |
313 | 1.96k | } |
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 | 1.96k | bool abstractNamespace() const override { return abstract_namespace_; } |
329 | 1.97k | 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 | 104 | 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 | 316 | : address_id_(address_id), endpoint_id_(endpoint_id) {} |
366 | 316 | ~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 |