Line data Source code
1 : #include "source/common/network/addr_family_aware_socket_option_impl.h" 2 : 3 : #include "envoy/common/exception.h" 4 : #include "envoy/common/optref.h" 5 : #include "envoy/config/core/v3/base.pb.h" 6 : 7 : #include "source/common/api/os_sys_calls_impl.h" 8 : #include "source/common/common/assert.h" 9 : #include "source/common/network/address_impl.h" 10 : #include "source/common/network/socket_option_impl.h" 11 : 12 : namespace Envoy { 13 : namespace Network { 14 : 15 : namespace { 16 : 17 : OptRef<const Socket::Option> getOptionForSocket(const Socket& socket, 18 : const Socket::Option& ipv4_option, 19 1212 : const Socket::Option& ipv6_option) { 20 1212 : auto version = socket.ipVersion(); 21 1212 : if (!version.has_value()) { 22 0 : return {}; 23 0 : } 24 : 25 : // If the FD is v4, we can only try the IPv4 variant. 26 1212 : if (*version == Network::Address::IpVersion::v4) { 27 182 : return {ipv4_option}; 28 182 : } 29 : // If the FD is v6, we first try the IPv6 variant if the platform supports it and fallback to the 30 : // IPv4 variant otherwise. 31 1030 : ASSERT(*version == Network::Address::IpVersion::v6); 32 1030 : if (ipv6_option.isSupported()) { 33 1030 : return {ipv6_option}; 34 1030 : } 35 0 : return {ipv4_option}; 36 1030 : } 37 : 38 : } // namespace 39 : 40 : bool AddrFamilyAwareSocketOptionImpl::setOption( 41 1212 : Socket& socket, envoy::config::core::v3::SocketOption::SocketState state) const { 42 1212 : return setIpSocketOption(socket, state, *ipv4_option_, *ipv6_option_); 43 1212 : } 44 : 45 : absl::optional<Socket::Option::Details> AddrFamilyAwareSocketOptionImpl::getOptionDetails( 46 0 : const Socket& socket, envoy::config::core::v3::SocketOption::SocketState state) const { 47 0 : auto option = getOptionForSocket(socket, *ipv4_option_, *ipv6_option_); 48 : 49 0 : if (!option.has_value()) { 50 0 : return absl::nullopt; 51 0 : } 52 : 53 0 : return option.value().get().getOptionDetails(socket, state); 54 0 : } 55 : 56 : bool AddrFamilyAwareSocketOptionImpl::setIpSocketOption( 57 : Socket& socket, envoy::config::core::v3::SocketOption::SocketState state, 58 1212 : const Socket::Option& ipv4_option, const Socket::Option& ipv6_option) { 59 1212 : auto option = getOptionForSocket(socket, ipv4_option, ipv6_option); 60 : 61 1212 : if (!option.has_value()) { 62 0 : ENVOY_LOG(warn, "Failed to set IP socket option on non-IP socket"); 63 0 : return false; 64 0 : } 65 : 66 1212 : return option.value().get().setOption(socket, state); 67 1212 : } 68 : 69 : } // namespace Network 70 : } // namespace Envoy