Coverage Report

Created: 2023-11-12 09:30

/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