Line data Source code
1 : #include "source/common/network/socket_option_factory.h" 2 : 3 : #include "envoy/config/core/v3/base.pb.h" 4 : 5 : #include "source/common/common/fmt.h" 6 : #include "source/common/network/addr_family_aware_socket_option_impl.h" 7 : #include "source/common/network/socket_option_impl.h" 8 : #include "source/common/network/win32_redirect_records_option_impl.h" 9 : 10 : namespace Envoy { 11 : namespace Network { 12 : 13 : std::unique_ptr<Socket::Options> 14 0 : SocketOptionFactory::buildTcpKeepaliveOptions(Network::TcpKeepaliveConfig keepalive_config) { 15 0 : std::unique_ptr<Socket::Options> options = std::make_unique<Socket::Options>(); 16 0 : absl::optional<Network::Socket::Type> tcp_only = {Network::Socket::Type::Stream}; 17 0 : options->push_back(std::make_shared<Network::SocketOptionImpl>( 18 0 : envoy::config::core::v3::SocketOption::STATE_PREBIND, ENVOY_SOCKET_SO_KEEPALIVE, 1, 19 0 : tcp_only)); 20 : 21 0 : if (keepalive_config.keepalive_probes_.has_value()) { 22 0 : options->push_back(std::make_shared<Network::SocketOptionImpl>( 23 0 : envoy::config::core::v3::SocketOption::STATE_PREBIND, ENVOY_SOCKET_TCP_KEEPCNT, 24 0 : keepalive_config.keepalive_probes_.value(), tcp_only)); 25 0 : } 26 0 : if (keepalive_config.keepalive_interval_.has_value()) { 27 0 : options->push_back(std::make_shared<Network::SocketOptionImpl>( 28 0 : envoy::config::core::v3::SocketOption::STATE_PREBIND, ENVOY_SOCKET_TCP_KEEPINTVL, 29 0 : keepalive_config.keepalive_interval_.value(), tcp_only)); 30 0 : } 31 0 : if (keepalive_config.keepalive_time_.has_value()) { 32 0 : options->push_back(std::make_shared<Network::SocketOptionImpl>( 33 0 : envoy::config::core::v3::SocketOption::STATE_PREBIND, ENVOY_SOCKET_TCP_KEEPIDLE, 34 0 : keepalive_config.keepalive_time_.value(), tcp_only)); 35 0 : } 36 0 : return options; 37 0 : } 38 : 39 91 : std::unique_ptr<Socket::Options> SocketOptionFactory::buildIpFreebindOptions() { 40 91 : std::unique_ptr<Socket::Options> options = std::make_unique<Socket::Options>(); 41 91 : options->push_back(std::make_shared<Network::AddrFamilyAwareSocketOptionImpl>( 42 91 : envoy::config::core::v3::SocketOption::STATE_PREBIND, ENVOY_SOCKET_IP_FREEBIND, 43 91 : ENVOY_SOCKET_IPV6_FREEBIND, 1)); 44 91 : return options; 45 91 : } 46 : 47 64 : std::unique_ptr<Socket::Options> SocketOptionFactory::buildIpTransparentOptions() { 48 64 : std::unique_ptr<Socket::Options> options = std::make_unique<Socket::Options>(); 49 64 : options->push_back(std::make_shared<Network::AddrFamilyAwareSocketOptionImpl>( 50 64 : envoy::config::core::v3::SocketOption::STATE_PREBIND, ENVOY_SOCKET_IP_TRANSPARENT, 51 64 : ENVOY_SOCKET_IPV6_TRANSPARENT, 1)); 52 64 : options->push_back(std::make_shared<Network::AddrFamilyAwareSocketOptionImpl>( 53 64 : envoy::config::core::v3::SocketOption::STATE_BOUND, ENVOY_SOCKET_IP_TRANSPARENT, 54 64 : ENVOY_SOCKET_IPV6_TRANSPARENT, 1)); 55 64 : return options; 56 64 : } 57 : 58 : std::unique_ptr<Socket::Options> 59 0 : SocketOptionFactory::buildWFPRedirectRecordsOptions(const Win32RedirectRecords& redirect_records) { 60 0 : std::unique_ptr<Socket::Options> options = std::make_unique<Socket::Options>(); 61 0 : options->push_back(std::make_shared<Network::Win32RedirectRecordsOptionImpl>(redirect_records)); 62 0 : return options; 63 0 : } 64 : 65 25 : std::unique_ptr<Socket::Options> SocketOptionFactory::buildSocketMarkOptions(uint32_t mark) { 66 25 : std::unique_ptr<Socket::Options> options = std::make_unique<Socket::Options>(); 67 : // we need this to happen prior to binding or prior to connecting. In both cases, PREBIND will 68 : // fire. 69 25 : options->push_back(std::make_shared<Network::SocketOptionImpl>( 70 25 : envoy::config::core::v3::SocketOption::STATE_PREBIND, ENVOY_SOCKET_SO_MARK, mark)); 71 25 : return options; 72 25 : } 73 : 74 0 : std::unique_ptr<Socket::Options> SocketOptionFactory::buildSocketNoSigpipeOptions() { 75 : // Provide additional handling for `SIGPIPE` at the socket layer by converting it to `EPIPE`. 76 0 : std::unique_ptr<Socket::Options> options = std::make_unique<Socket::Options>(); 77 0 : options->push_back(std::make_shared<Network::SocketOptionImpl>( 78 0 : envoy::config::core::v3::SocketOption::STATE_PREBIND, ENVOY_SOCKET_SO_NOSIGPIPE, 1)); 79 0 : return options; 80 0 : } 81 : 82 : std::unique_ptr<Socket::Options> SocketOptionFactory::buildLiteralOptions( 83 0 : const Protobuf::RepeatedPtrField<envoy::config::core::v3::SocketOption>& socket_options) { 84 0 : auto options = std::make_unique<Socket::Options>(); 85 0 : for (const auto& socket_option : socket_options) { 86 0 : std::string buf; 87 0 : int int_value; 88 0 : switch (socket_option.value_case()) { 89 0 : case envoy::config::core::v3::SocketOption::ValueCase::kIntValue: 90 0 : int_value = socket_option.int_value(); 91 0 : buf.append(reinterpret_cast<char*>(&int_value), sizeof(int_value)); 92 0 : break; 93 0 : case envoy::config::core::v3::SocketOption::ValueCase::kBufValue: 94 0 : buf.append(socket_option.buf_value()); 95 0 : break; 96 0 : default: 97 0 : ENVOY_LOG(warn, "Socket option specified with no or unknown value: {}", 98 0 : socket_option.DebugString()); 99 0 : continue; 100 0 : } 101 0 : options->emplace_back(std::make_shared<Network::SocketOptionImpl>( 102 0 : socket_option.state(), 103 0 : Network::SocketOptionName( 104 0 : socket_option.level(), socket_option.name(), 105 0 : fmt::format("{}/{}", socket_option.level(), socket_option.name())), 106 0 : buf)); 107 0 : } 108 0 : return options; 109 0 : } 110 : 111 : std::unique_ptr<Socket::Options> 112 1 : SocketOptionFactory::buildTcpFastOpenOptions(uint32_t queue_length) { 113 1 : std::unique_ptr<Socket::Options> options = std::make_unique<Socket::Options>(); 114 1 : options->push_back(std::make_shared<Network::SocketOptionImpl>( 115 1 : envoy::config::core::v3::SocketOption::STATE_LISTENING, ENVOY_SOCKET_TCP_FASTOPEN, 116 1 : queue_length)); 117 1 : return options; 118 1 : } 119 : 120 606 : std::unique_ptr<Socket::Options> SocketOptionFactory::buildIpPacketInfoOptions() { 121 606 : std::unique_ptr<Socket::Options> options = std::make_unique<Socket::Options>(); 122 606 : options->push_back(std::make_shared<AddrFamilyAwareSocketOptionImpl>( 123 606 : envoy::config::core::v3::SocketOption::STATE_BOUND, ENVOY_SELF_IP_ADDR, ENVOY_SELF_IPV6_ADDR, 124 606 : 1)); 125 606 : return options; 126 606 : } 127 : 128 606 : std::unique_ptr<Socket::Options> SocketOptionFactory::buildRxQueueOverFlowOptions() { 129 606 : std::unique_ptr<Socket::Options> options = std::make_unique<Socket::Options>(); 130 606 : #ifdef SO_RXQ_OVFL 131 606 : options->push_back(std::make_shared<Network::SocketOptionImpl>( 132 606 : envoy::config::core::v3::SocketOption::STATE_BOUND, 133 606 : ENVOY_MAKE_SOCKET_OPTION_NAME(SOL_SOCKET, SO_RXQ_OVFL), 1)); 134 606 : #endif 135 606 : return options; 136 606 : } 137 : 138 134 : std::unique_ptr<Socket::Options> SocketOptionFactory::buildReusePortOptions() { 139 134 : std::unique_ptr<Socket::Options> options = std::make_unique<Socket::Options>(); 140 134 : options->push_back(std::make_shared<Network::SocketOptionImpl>( 141 134 : envoy::config::core::v3::SocketOption::STATE_PREBIND, ENVOY_SOCKET_SO_REUSEPORT, 1)); 142 134 : return options; 143 134 : } 144 : 145 0 : std::unique_ptr<Socket::Options> SocketOptionFactory::buildUdpGroOptions() { 146 0 : std::unique_ptr<Socket::Options> options = std::make_unique<Socket::Options>(); 147 0 : options->push_back(std::make_shared<SocketOptionImpl>( 148 0 : envoy::config::core::v3::SocketOption::STATE_BOUND, ENVOY_SOCKET_UDP_GRO, 1)); 149 0 : return options; 150 0 : } 151 : 152 54 : std::unique_ptr<Socket::Options> SocketOptionFactory::buildZeroSoLingerOptions() { 153 54 : std::unique_ptr<Socket::Options> options = std::make_unique<Socket::Options>(); 154 54 : struct linger linger; 155 54 : linger.l_onoff = 1; 156 54 : linger.l_linger = 0; 157 54 : absl::string_view linger_bstr{reinterpret_cast<const char*>(&linger), sizeof(struct linger)}; 158 54 : options->push_back(std::make_shared<SocketOptionImpl>( 159 54 : envoy::config::core::v3::SocketOption::STATE_LISTENING, 160 54 : ENVOY_MAKE_SOCKET_OPTION_NAME(SOL_SOCKET, SO_LINGER), linger_bstr)); 161 54 : return options; 162 54 : } 163 : 164 : } // namespace Network 165 : } // namespace Envoy