LCOV - code coverage report
Current view: top level - source/common/network - address_impl.h (source / functions) Hit Total Coverage
Test: coverage.dat Lines: 47 80 58.8 %
Date: 2024-01-05 06:35:25 Functions: 35 60 58.3 %

          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

Generated by: LCOV version 1.15