Line data Source code
1 : #include "source/common/network/socket_interface_impl.h" 2 : 3 : #include "envoy/common/exception.h" 4 : #include "envoy/extensions/network/socket_interface/v3/default_socket_interface.pb.h" 5 : 6 : #include "source/common/api/os_sys_calls_impl.h" 7 : #include "source/common/common/assert.h" 8 : #include "source/common/common/utility.h" 9 : #include "source/common/network/address_impl.h" 10 : #include "source/common/network/io_socket_handle_impl.h" 11 : #include "source/common/network/win32_socket_handle_impl.h" 12 : 13 : namespace Envoy { 14 : namespace Network { 15 : 16 : IoHandlePtr SocketInterfaceImpl::makePlatformSpecificSocket(int socket_fd, bool socket_v6only, 17 3978 : absl::optional<int> domain) { 18 3978 : if constexpr (Event::PlatformDefaultTriggerType == Event::FileTriggerType::EmulatedEdge) { 19 0 : return std::make_unique<Win32SocketHandleImpl>(socket_fd, socket_v6only, domain); 20 0 : } 21 3978 : return std::make_unique<IoSocketHandleImpl>(socket_fd, socket_v6only, domain); 22 3978 : } 23 : 24 : IoHandlePtr SocketInterfaceImpl::makeSocket(int socket_fd, bool socket_v6only, 25 2645 : absl::optional<int> domain) const { 26 2645 : return makePlatformSpecificSocket(socket_fd, socket_v6only, domain); 27 2645 : } 28 : 29 : IoHandlePtr SocketInterfaceImpl::socket(Socket::Type socket_type, Address::Type addr_type, 30 : Address::IpVersion version, bool socket_v6only, 31 2645 : const SocketCreationOptions& options) const { 32 2645 : int protocol = 0; 33 : #if defined(__APPLE__) || defined(WIN32) 34 : ASSERT(!options.mptcp_enabled_, "MPTCP is only supported on Linux"); 35 : int flags = 0; 36 : #else 37 2645 : int flags = SOCK_NONBLOCK; 38 : 39 2645 : if (options.mptcp_enabled_) { 40 0 : ASSERT(socket_type == Socket::Type::Stream); 41 0 : ASSERT(addr_type == Address::Type::Ip); 42 0 : protocol = IPPROTO_MPTCP; 43 0 : } 44 2645 : #endif 45 : 46 2645 : if (socket_type == Socket::Type::Stream) { 47 1948 : flags |= SOCK_STREAM; 48 2645 : } else { 49 697 : flags |= SOCK_DGRAM; 50 697 : } 51 : 52 2645 : int domain; 53 2645 : if (addr_type == Address::Type::Ip) { 54 2640 : if (version == Address::IpVersion::v6 || Address::forceV6()) { 55 515 : domain = AF_INET6; 56 2640 : } else { 57 2125 : ASSERT(version == Address::IpVersion::v4); 58 2125 : domain = AF_INET; 59 2125 : } 60 2645 : } else if (addr_type == Address::Type::Pipe) { 61 5 : domain = AF_UNIX; 62 5 : } else { 63 0 : ASSERT(addr_type == Address::Type::EnvoyInternal); 64 0 : PANIC("not implemented"); 65 : // TODO(lambdai): Add InternalIoSocketHandleImpl to support internal address. 66 0 : return nullptr; 67 0 : } 68 : 69 2645 : const Api::SysCallSocketResult result = 70 2645 : Api::OsSysCallsSingleton::get().socket(domain, flags, protocol); 71 2645 : RELEASE_ASSERT(SOCKET_VALID(result.return_value_), 72 2645 : fmt::format("socket(2) failed, got error: {}", errorDetails(result.errno_))); 73 2645 : IoHandlePtr io_handle = makeSocket(result.return_value_, socket_v6only, domain); 74 : 75 : #if defined(__APPLE__) || defined(WIN32) 76 : // Cannot set SOCK_NONBLOCK as a ::socket flag. 77 : const int rc = io_handle->setBlocking(false).return_value_; 78 : RELEASE_ASSERT(!SOCKET_FAILURE(rc), 79 : fmt::format("Unable to set socket non-blocking: got error: {}", rc)); 80 : #endif 81 : 82 2645 : return io_handle; 83 2645 : } 84 : 85 : IoHandlePtr SocketInterfaceImpl::socket(Socket::Type socket_type, 86 : const Address::InstanceConstSharedPtr addr, 87 2645 : const SocketCreationOptions& options) const { 88 2645 : Address::IpVersion ip_version = addr->ip() ? addr->ip()->version() : Address::IpVersion::v4; 89 2645 : int v6only = 0; 90 2645 : if (addr->type() == Address::Type::Ip && ip_version == Address::IpVersion::v6) { 91 515 : v6only = addr->ip()->ipv6()->v6only(); 92 515 : } 93 : 94 2645 : IoHandlePtr io_handle = 95 2645 : SocketInterfaceImpl::socket(socket_type, addr->type(), ip_version, v6only, options); 96 2645 : if (addr->type() == Address::Type::Ip && ip_version == Address::IpVersion::v6 && 97 2645 : !Address::forceV6()) { 98 : // Setting IPV6_V6ONLY restricts the IPv6 socket to IPv6 connections only. 99 515 : const Api::SysCallIntResult result = io_handle->setOption( 100 515 : IPPROTO_IPV6, IPV6_V6ONLY, reinterpret_cast<const char*>(&v6only), sizeof(v6only)); 101 515 : ENVOY_BUG(!SOCKET_FAILURE(result.return_value_), 102 515 : fmt::format("Unable to set socket v6-only: got error: {}", result.return_value_)); 103 515 : } 104 2645 : return io_handle; 105 2645 : } 106 : 107 2562 : bool SocketInterfaceImpl::ipFamilySupported(int domain) { 108 2562 : Api::OsSysCalls& os_sys_calls = Api::OsSysCallsSingleton::get(); 109 2562 : const Api::SysCallSocketResult result = os_sys_calls.socket(domain, SOCK_STREAM, 0); 110 2562 : if (SOCKET_VALID(result.return_value_)) { 111 2562 : RELEASE_ASSERT( 112 2562 : os_sys_calls.close(result.return_value_).return_value_ == 0, 113 2562 : fmt::format("Fail to close fd: response code {}", errorDetails(result.return_value_))); 114 2562 : } 115 2562 : return SOCKET_VALID(result.return_value_); 116 2562 : } 117 : 118 : Server::BootstrapExtensionPtr 119 : SocketInterfaceImpl::createBootstrapExtension(const Protobuf::Message&, 120 0 : Server::Configuration::ServerFactoryContext&) { 121 0 : return std::make_unique<SocketInterfaceExtension>(*this); 122 0 : } 123 : 124 12 : ProtobufTypes::MessagePtr SocketInterfaceImpl::createEmptyConfigProto() { 125 12 : return std::make_unique< 126 12 : envoy::extensions::network::socket_interface::v3::DefaultSocketInterface>(); 127 12 : } 128 : 129 : REGISTER_FACTORY(SocketInterfaceImpl, Server::Configuration::BootstrapExtensionFactory); 130 : 131 : static SocketInterfaceLoader* socket_interface_ = 132 : new SocketInterfaceLoader(std::make_unique<SocketInterfaceImpl>()); 133 : 134 : } // namespace Network 135 : } // namespace Envoy