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/cleanup.h"
15
#include "source/common/common/statusor.h"
16

            
17
namespace Envoy {
18
namespace Network {
19
namespace Address {
20

            
21
/**
22
 * Check whether we are a) on Android or an Apple platform and b) configured via runtime to always
23
 * use v6 sockets.
24
 * This appears to be what Android OS does for all platform sockets.
25
 */
26
bool forceV6();
27

            
28
/**
29
 * Convert an address in the form of the socket address struct defined by Posix, Linux, etc. into
30
 * a Network::Address::Instance and return a pointer to it. Raises an EnvoyException on failure.
31
 * @param ss a valid address with family AF_INET, AF_INET6 or AF_UNIX.
32
 * @param len length of the address (e.g. from accept, getsockname or getpeername). If len > 0,
33
 *        it is used to validate the structure contents; else if len == 0, it is ignored.
34
 * @param v6only disable IPv4-IPv6 mapping for IPv6 addresses?
35
 * @return InstanceConstSharedPtr the address.
36
 */
37
StatusOr<InstanceConstSharedPtr> addressFromSockAddr(const sockaddr_storage& ss, socklen_t len,
38
                                                     bool v6only = true);
39

            
40
/**
41
 * Convert an address in the form of the socket address struct defined by Posix, Linux, etc. into
42
 * a Network::Address::Instance and return a pointer to it. Die on failure.
43
 * @param ss a valid address with family AF_INET, AF_INET6 or AF_UNIX.
44
 * @param len length of the address (e.g. from accept, getsockname or getpeername). If len > 0,
45
 *        it is used to validate the structure contents; else if len == 0, it is ignored.
46
 * @param fd the file descriptor for the created address instance.
47
 * @param v6only disable IPv4-IPv6 mapping for IPv6 addresses?
48
 * @return InstanceConstSharedPtr the address.
49
 */
50
InstanceConstSharedPtr addressFromSockAddrOrDie(const sockaddr_storage& ss, socklen_t ss_len,
51
                                                os_fd_t fd, bool v6only = true);
52

            
53
/**
54
 * Base class for all address types.
55
 */
56
class InstanceBase : public Instance {
57
public:
58
  // Network::Address::Instance
59
126990
  const std::string& asString() const override { return friendly_name_; }
60
39528
  absl::string_view asStringView() const override { return friendly_name_; }
61
  // Default logical name is the human-readable name.
62
4
  const std::string& logicalName() const override { return asString(); }
63
1684680
  Type type() const override { return type_; }
64

            
65
109608
  const SocketInterface& socketInterface() const override { return socket_interface_; }
66

            
67
protected:
68
  InstanceBase(Type type, const SocketInterface* sock_interface)
69
3669069
      : socket_interface_(*sock_interface), type_(type) {}
70

            
71
  std::string friendly_name_;
72
  const SocketInterface& socket_interface_;
73

            
74
private:
75
  const Type type_;
76
};
77

            
78
// Create an address instance. Upon failure, return an error status without throwing.
79
class InstanceFactory {
80
public:
81
  template <typename InstanceType, typename... Args>
82
3414613
  static StatusOr<InstanceConstSharedPtr> createInstancePtr(Args&&... args) {
83
3414613
    absl::Status status = absl::OkStatus();
84
    // Use new instead of make_shared here because the instance constructors are private and must
85
    // be called directly here.
86
3414613
    std::shared_ptr<InstanceType> instance(new InstanceType(status, std::forward<Args>(args)...));
87
3414613
    if (!status.ok()) {
88
8
      return status;
89
8
    }
90
3414605
    return instance;
91
3414613
  }
92
};
93

            
94
/**
95
 * Implementation of an IPv4 address.
96
 */
97
class Ipv4Instance : public InstanceBase {
98
public:
99
  /**
100
   * Construct from an existing unix IPv4 socket address (IP v4 address and port).
101
   */
102
  explicit Ipv4Instance(const sockaddr_in* address, const SocketInterface* sock_interface = nullptr,
103
                        absl::optional<std::string> network_namespace = absl::nullopt);
104

            
105
  /**
106
   * Construct from a string IPv4 address such as "1.2.3.4". Port will be unset/0.
107
   */
108
  explicit Ipv4Instance(const std::string& address, const SocketInterface* sock_interface = nullptr,
109
                        absl::optional<std::string> network_namespace = absl::nullopt);
110

            
111
  /**
112
   * Construct from a string IPv4 address such as "1.2.3.4" as well as a port.
113
   */
114
  Ipv4Instance(const std::string& address, uint32_t port,
115
               const SocketInterface* sock_interface = nullptr,
116
               absl::optional<std::string> network_namespace = absl::nullopt);
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
                        absl::optional<std::string> network_namespace = absl::nullopt);
124

            
125
  /**
126
   * Copy and override the network namespace.
127
   */
128
  explicit Ipv4Instance(const Ipv4Instance& that,
129
                        const absl::optional<std::string>& network_namespace);
130

            
131
  // Network::Address::Instance
132
  bool operator==(const Instance& rhs) const override;
133
4559448
  const Ip* ip() const override { return &ip_; }
134
1
  const Pipe* pipe() const override { return nullptr; }
135
1
  const EnvoyInternalAddress* envoyInternalAddress() const override { return nullptr; }
136
457031
  const sockaddr* sockAddr() const override {
137
457031
    return reinterpret_cast<const sockaddr*>(&ip_.ipv4_.address_);
138
457031
  }
139
455538
  socklen_t sockAddrLen() const override { return sizeof(sockaddr_in); }
140
53329
  absl::string_view addressType() const override { return "default"; }
141
128871
  absl::optional<std::string> networkNamespace() const override { return network_namespace_; }
142
10
  InstanceConstSharedPtr withNetworkNamespace(absl::string_view network_namespace) const override {
143
10
    absl::optional<std::string> namespace_override;
144
10
    if (!network_namespace.empty()) {
145
8
      namespace_override = network_namespace;
146
8
    }
147
10
    return std::make_shared<const Ipv4Instance>(*this, namespace_override);
148
10
  }
149

            
150
  /**
151
   * Convenience function to convert an IPv4 address to canonical string format.
152
   * @note This works similarly to inet_ntop() but is faster.
153
   * @param addr address to format.
154
   * @return the address in dotted-decimal string format.
155
   */
156
  static std::string sockaddrToString(const sockaddr_in& addr);
157

            
158
  // Validate that IPv4 is supported on this platform, raise an exception for the
159
  // given address if not.
160
  static absl::Status validateProtocolSupported();
161

            
162
  /**
163
   * For use in tests only.
164
   * Force validateProtocolSupported() to return false for IPv4.
165
   */
166
  static Envoy::Cleanup forceProtocolUnsupportedForTest(bool new_val);
167

            
168
private:
169
  /**
170
   * Construct from an existing unix IPv4 socket address (IP v4 address and port).
171
   * Store the status code in passed in parameter instead of throwing.
172
   * It is called by the factory method and the partially constructed instance will be discarded
173
   * upon error.
174
   */
175
  explicit Ipv4Instance(absl::Status& error, const sockaddr_in* address,
176
                        const SocketInterface* sock_interface = nullptr,
177
                        absl::optional<std::string> network_namespace = absl::nullopt);
178

            
179
  struct Ipv4Helper : public Ipv4 {
180
1929374
    uint32_t address() const override { return address_.sin_addr.s_addr; }
181

            
182
    sockaddr_in address_;
183
  };
184

            
185
  struct IpHelper : public Ip {
186
7803
    const std::string& addressAsString() const override { return friendly_address_; }
187
39589
    bool isAnyAddress() const override { return ipv4_.address_.sin_addr.s_addr == INADDR_ANY; }
188
105
    bool isUnicastAddress() const override {
189
105
      return !isAnyAddress() && (ipv4_.address_.sin_addr.s_addr != INADDR_BROADCAST) &&
190
             // inlined IN_MULTICAST() to avoid byte swapping
191
105
             !((ipv4_.address_.sin_addr.s_addr & htonl(0xf0000000)) == htonl(0xe0000000));
192
105
    }
193
6
    bool isLinkLocalAddress() const override {
194
      // Check if the address is in the link-local range: 169.254.0.0/16.
195
6
      return (ipv4_.address_.sin_addr.s_addr & htonl(0xffff0000)) == htonl(0xa9fe0000);
196
6
    }
197
2
    bool isUniqueLocalAddress() const override {
198
      // Unique Local Addresses (ULA) are not applicable to IPv4.
199
2
      return false;
200
2
    }
201
2
    bool isSiteLocalAddress() const override {
202
      // Site-Local Addresses are not applicable to IPv4.
203
2
      return false;
204
2
    }
205
2
    bool isTeredoAddress() const override {
206
      // Teredo addresses are not applicable to IPv4.
207
2
      return false;
208
2
    }
209
1927404
    const Ipv4* ipv4() const override { return &ipv4_; }
210
2295
    const Ipv6* ipv6() const override { return nullptr; }
211
2401009
    uint32_t port() const override { return ntohs(ipv4_.address_.sin_port); }
212
2667452
    IpVersion version() const override { return IpVersion::v4; }
213

            
214
    Ipv4Helper ipv4_;
215
    std::string friendly_address_;
216
  };
217

            
218
  void initHelper(const sockaddr_in* address);
219

            
220
  IpHelper ip_;
221
  const absl::optional<std::string> network_namespace_;
222
  friend class InstanceFactory;
223
};
224

            
225
/**
226
 * Implementation of an IPv6 address.
227
 */
228
class Ipv6Instance : public InstanceBase {
229
public:
230
  /**
231
   * Construct from an existing unix IPv6 socket address (IP v6 address and port).
232
   */
233
  Ipv6Instance(const sockaddr_in6& address, bool v6only = true,
234
               const SocketInterface* sock_interface = nullptr,
235
               absl::optional<std::string> network_namespace = absl::nullopt);
236

            
237
  /**
238
   * Construct from a string IPv6 address such as "12:34::5". Port will be unset/0.
239
   */
240
  explicit Ipv6Instance(const std::string& address, const SocketInterface* sock_interface = nullptr,
241
                        absl::optional<std::string> network_namespace = absl::nullopt);
242

            
243
  /**
244
   * Construct from a string IPv6 address such as "12:34::5" as well as a port.
245
   */
246
  Ipv6Instance(const std::string& address, uint32_t port,
247
               const SocketInterface* sock_interface = nullptr, bool v6only = true,
248
               absl::optional<std::string> network_namespace = absl::nullopt);
249

            
250
  /**
251
   * Construct from a port. The IPv6 address will be set to "any" and is suitable for binding
252
   * a port to any available address.
253
   */
254
  explicit Ipv6Instance(uint32_t port, const SocketInterface* sock_interface = nullptr,
255
                        absl::optional<std::string> network_namespace = absl::nullopt);
256

            
257
  /**
258
   * Copy and override the network namespace.
259
   */
260
  explicit Ipv6Instance(const Ipv6Instance& that,
261
                        const absl::optional<std::string>& network_namespace);
262

            
263
  // Network::Address::Instance
264
  bool operator==(const Instance& rhs) const override;
265
156492
  const Ip* ip() const override { return &ip_; }
266
1
  const Pipe* pipe() const override { return nullptr; }
267
1
  const EnvoyInternalAddress* envoyInternalAddress() const override { return nullptr; }
268
858
  const sockaddr* sockAddr() const override {
269
858
    return reinterpret_cast<const sockaddr*>(&ip_.ipv6_.address_);
270
858
  }
271
510
  socklen_t sockAddrLen() const override { return sizeof(sockaddr_in6); }
272
168
  absl::string_view addressType() const override { return "default"; }
273
610
  absl::optional<std::string> networkNamespace() const override { return network_namespace_; }
274
7
  InstanceConstSharedPtr withNetworkNamespace(absl::string_view network_namespace) const override {
275
7
    absl::optional<std::string> namespace_override;
276
7
    if (!network_namespace.empty()) {
277
5
      namespace_override = network_namespace;
278
5
    }
279
7
    return std::make_shared<const Ipv6Instance>(*this, namespace_override);
280
7
  }
281

            
282
  /**
283
   * Convenience function to convert an IPv6 address to canonical string format.
284
   * @param addr address to format.
285
   * @return the address in dotted-decimal string format.
286
   */
287
  static std::string sockaddrToString(const sockaddr_in6& addr);
288

            
289
  // Validate that IPv6 is supported on this platform
290
  static absl::Status validateProtocolSupported();
291

            
292
  /**
293
   * For use in tests only.
294
   * Force validateProtocolSupported() to return false for IPv6.
295
   */
296
  static Envoy::Cleanup forceProtocolUnsupportedForTest(bool new_val);
297

            
298
private:
299
  /**
300
   * Construct from an existing unix IPv6 socket address (IP v6 address and port).
301
   * Store the status code in passed in parameter instead of throwing.
302
   * It is called by the factory method and the partially constructed instance will be discarded
303
   * upon error.
304
   */
305
  Ipv6Instance(absl::Status& error, const sockaddr_in6& address, bool v6only = true,
306
               const SocketInterface* sock_interface = nullptr,
307
               absl::optional<std::string> network_namespace = absl::nullopt);
308

            
309
  struct Ipv6Helper : public Ipv6 {
310
114288
    Ipv6Helper() { memset(&address_, 0, sizeof(address_)); }
311
    absl::uint128 address() const override;
312
    bool v6only() const override;
313
    uint32_t scopeId() const override;
314
    uint32_t port() const;
315
    InstanceConstSharedPtr v4CompatibleAddress() const override;
316
    InstanceConstSharedPtr addressWithoutScopeId() const override;
317

            
318
    std::string makeFriendlyAddress() const;
319
    static std::string makeFriendlyAddress(const sockaddr_in6& address);
320

            
321
    sockaddr_in6 address_;
322
    // Is IPv4 compatibility (https://tools.ietf.org/html/rfc3493#page-11) disabled?
323
    // Default initialized to true to preserve extant Envoy behavior where we don't explicitly set
324
    // this in the constructor.
325
    bool v6only_{true};
326
  };
327

            
328
  struct IpHelper : public Ip {
329
225
    const std::string& addressAsString() const override { return friendly_address_; }
330
295
    bool isAnyAddress() const override {
331
295
      return 0 == memcmp(&ipv6_.address_.sin6_addr, &in6addr_any, sizeof(struct in6_addr));
332
295
    }
333
16
    bool isUnicastAddress() const override {
334
16
      return !isAnyAddress() && !IN6_IS_ADDR_MULTICAST(&ipv6_.address_.sin6_addr);
335
16
    }
336
23
    bool isLinkLocalAddress() const override {
337
      // Check if the address is in the link-local range: fe80::/10 or in the v4 mapped link-local
338
      // range: [::ffff:169.254.0.0].
339
23
      return IN6_IS_ADDR_LINKLOCAL(&ipv6_.address_.sin6_addr) ||
340
23
             (IN6_IS_ADDR_V4MAPPED(&ipv6_.address_.sin6_addr) &&
341
14
              (ipv6_.address_.sin6_addr.s6_addr[12] == 0xa9 &&
342
8
               ipv6_.address_.sin6_addr.s6_addr[13] == 0xfe));
343
23
    }
344
9
    bool isUniqueLocalAddress() const override {
345
      // Unique Local Addresses (ULA) are in the range fc00::/7.
346
9
      return (ipv6_.address_.sin6_addr.s6_addr[0] & 0xfe) == 0xfc;
347
9
    }
348
9
    bool isSiteLocalAddress() const override {
349
      // Site-Local Addresses are in the range fec0::/10.
350
9
      return IN6_IS_ADDR_SITELOCAL(&ipv6_.address_.sin6_addr);
351
9
    }
352
7
    bool isTeredoAddress() const override {
353
      // Teredo addresses have the prefix 2001:0000::/32.
354
7
      return ipv6_.address_.sin6_addr.s6_addr[0] == 0x20 &&
355
7
             ipv6_.address_.sin6_addr.s6_addr[1] == 0x01 &&
356
7
             ipv6_.address_.sin6_addr.s6_addr[2] == 0x00 &&
357
7
             ipv6_.address_.sin6_addr.s6_addr[3] == 0x00;
358
7
    }
359
16
    const Ipv4* ipv4() const override { return nullptr; }
360
36931
    const Ipv6* ipv6() const override { return &ipv6_; }
361
115408
    uint32_t port() const override { return ipv6_.port(); }
362
116998
    IpVersion version() const override { return IpVersion::v6; }
363

            
364
    Ipv6Helper ipv6_;
365
    std::string friendly_address_;
366
  };
367

            
368
  void initHelper(const sockaddr_in6& address, bool v6only);
369

            
370
  IpHelper ip_;
371
  const absl::optional<std::string> network_namespace_;
372
  friend class InstanceFactory;
373
};
374

            
375
/**
376
 * Implementation of a pipe address (unix domain socket on unix).
377
 */
378
class PipeInstance : public InstanceBase {
379
public:
380
  /**
381
   * Construct from an existing unix address.
382
   */
383
  static absl::StatusOr<std::unique_ptr<PipeInstance>>
384
  create(const sockaddr_un* address, socklen_t ss_len, mode_t mode = 0,
385
         const SocketInterface* sock_interface = nullptr);
386

            
387
  /**
388
   * Construct from a string pipe path.
389
   */
390
  static absl::StatusOr<std::unique_ptr<PipeInstance>>
391
  create(const std::string& pipe_path, mode_t mode = 0,
392
         const SocketInterface* sock_interface = nullptr);
393

            
394
  static absl::Status validateProtocolSupported() { return absl::OkStatus(); }
395

            
396
  // Network::Address::Instance
397
  bool operator==(const Instance& rhs) const override;
398
266
  const Ip* ip() const override { return nullptr; }
399
106
  const Pipe* pipe() const override { return &pipe_; }
400
1
  const EnvoyInternalAddress* envoyInternalAddress() const override { return nullptr; }
401
136
  const sockaddr* sockAddr() const override {
402
136
    return reinterpret_cast<const sockaddr*>(&pipe_.address_);
403
136
  }
404
318
  const sockaddr_un& getSockAddr() const { return pipe_.address_; }
405
83
  socklen_t sockAddrLen() const override {
406
83
    if (pipe_.abstract_namespace_) {
407
27
      return offsetof(struct sockaddr_un, sun_path) + pipe_.address_length_;
408
27
    }
409
56
    return sizeof(pipe_.address_);
410
83
  }
411
30
  absl::string_view addressType() const override { return "default"; }
412
69
  absl::optional<std::string> networkNamespace() const override { return {}; }
413
1
  InstanceConstSharedPtr withNetworkNamespace(absl::string_view) const override { return nullptr; }
414

            
415
private:
416
  explicit PipeInstance(const std::string& pipe_path, mode_t mode,
417
                        const SocketInterface* sock_interface, absl::Status& creation_status);
418
  /**
419
   * Construct from an existing unix address.
420
   * Store the error status code in passed in parameter instead of throwing.
421
   * It is called by the factory method and the partially constructed instance will be discarded
422
   * upon error.
423
   */
424
  PipeInstance(absl::Status& error, const sockaddr_un* address, socklen_t ss_len, mode_t mode = 0,
425
               const SocketInterface* sock_interface = nullptr);
426

            
427
  struct PipeHelper : public Pipe {
428

            
429
53
    bool abstractNamespace() const override { return abstract_namespace_; }
430
62
    mode_t mode() const override { return mode_; }
431

            
432
    sockaddr_un address_;
433
    // For abstract namespaces.
434
    bool abstract_namespace_{false};
435
    uint32_t address_length_{0};
436
    mode_t mode_{0};
437
  };
438

            
439
  absl::Status initHelper(const sockaddr_un* address, mode_t mode);
440

            
441
  PipeHelper pipe_;
442
  friend class InstanceFactory;
443
};
444

            
445
class EnvoyInternalInstance : public InstanceBase {
446
public:
447
  /**
448
   * Construct from a string name.
449
   */
450
  explicit EnvoyInternalInstance(const std::string& address_id, const std::string& endpoint_id = "",
451
                                 const SocketInterface* sock_interface = nullptr);
452

            
453
  // Network::Address::Instance
454
  bool operator==(const Instance& rhs) const override;
455
119
  const Ip* ip() const override { return nullptr; }
456
3
  const Pipe* pipe() const override { return nullptr; }
457
65
  const EnvoyInternalAddress* envoyInternalAddress() const override { return &internal_address_; }
458
  // TODO(lambdai): Verify all callers accepts nullptr.
459
4
  const sockaddr* sockAddr() const override { return nullptr; }
460
3
  socklen_t sockAddrLen() const override { return 0; }
461
22
  absl::string_view addressType() const override { return "envoy_internal"; }
462
94
  absl::optional<std::string> networkNamespace() const override { return {}; }
463
1
  InstanceConstSharedPtr withNetworkNamespace(absl::string_view) const override { return nullptr; }
464

            
465
private:
466
  struct EnvoyInternalAddressImpl : public EnvoyInternalAddress {
467
    explicit EnvoyInternalAddressImpl(const std::string& address_id, const std::string& endpoint_id)
468
187
        : address_id_(address_id), endpoint_id_(endpoint_id) {}
469
189
    ~EnvoyInternalAddressImpl() override = default;
470
49
    const std::string& addressId() const override { return address_id_; }
471
13
    const std::string& endpointId() const override { return endpoint_id_; }
472
    const std::string address_id_;
473
    const std::string endpoint_id_;
474
  };
475
  EnvoyInternalAddressImpl internal_address_;
476
};
477

            
478
} // namespace Address
479
} // namespace Network
480
} // namespace Envoy