1
#include "source/common/network/io_socket_handle_base_impl.h"
2

            
3
#include "envoy/buffer/buffer.h"
4
#include "envoy/common/exception.h"
5
#include "envoy/event/dispatcher.h"
6

            
7
#include "source/common/api/os_sys_calls_impl.h"
8
#include "source/common/common/assert.h"
9
#include "source/common/common/utility.h"
10
#include "source/common/network/address_impl.h"
11
#include "source/common/network/io_socket_error_impl.h"
12
#include "source/common/network/io_socket_handle_impl.h"
13
#include "source/common/network/socket_interface_impl.h"
14

            
15
namespace Envoy {
16
namespace Network {
17

            
18
IoSocketHandleBaseImpl::IoSocketHandleBaseImpl(os_fd_t fd, bool socket_v6only,
19
                                               absl::optional<int> domain)
20
155494
    : fd_(fd), socket_v6only_(socket_v6only), domain_(domain) {}
21

            
22
155493
IoSocketHandleBaseImpl::~IoSocketHandleBaseImpl() {
23
155493
  if (SOCKET_VALID(fd_)) {
24
    // The TLS slot has been shut down by this moment with IoUring wiped out, thus
25
    // better use this posix system call instead of IoSocketHandleBaseImpl::close().
26
5
    ::close(fd_);
27
5
  }
28
155493
}
29

            
30
7735526
bool IoSocketHandleBaseImpl::isOpen() const { return SOCKET_VALID(fd_); }
31

            
32
597439
bool IoSocketHandleBaseImpl::wasConnected() const { return was_connected_; }
33

            
34
56145
bool IoSocketHandleBaseImpl::supportsMmsg() const {
35
56145
  return Api::OsSysCallsSingleton::get().supportsMmsg();
36
56145
}
37

            
38
46690
bool IoSocketHandleBaseImpl::supportsUdpGro() const {
39
46690
  return Api::OsSysCallsSingleton::get().supportsUdpGro();
40
46690
}
41

            
42
Api::SysCallIntResult IoSocketHandleBaseImpl::setOption(int level, int optname, const void* optval,
43
178619
                                                        socklen_t optlen) {
44
178619
  return Api::OsSysCallsSingleton::get().setsockopt(fd_, level, optname, optval, optlen);
45
178619
}
46

            
47
Api::SysCallIntResult IoSocketHandleBaseImpl::getOption(int level, int optname, void* optval,
48
55279
                                                        socklen_t* optlen) {
49
55279
  return Api::OsSysCallsSingleton::get().getsockopt(fd_, level, optname, optval, optlen);
50
55279
}
51

            
52
Api::SysCallIntResult IoSocketHandleBaseImpl::ioctl(unsigned long control_code, void* in_buffer,
53
                                                    unsigned long in_buffer_len, void* out_buffer,
54
                                                    unsigned long out_buffer_len,
55
                                                    unsigned long* bytes_returned) {
56
  return Api::OsSysCallsSingleton::get().ioctl(fd_, control_code, in_buffer, in_buffer_len,
57
                                               out_buffer, out_buffer_len, bytes_returned);
58
}
59

            
60
170
Api::SysCallIntResult IoSocketHandleBaseImpl::setBlocking(bool blocking) {
61
170
  return Api::OsSysCallsSingleton::get().setsocketblocking(fd_, blocking);
62
170
}
63

            
64
50
absl::optional<int> IoSocketHandleBaseImpl::domain() { return domain_; }
65

            
66
105357
absl::StatusOr<Address::InstanceConstSharedPtr> IoSocketHandleBaseImpl::localAddress() {
67
105357
  sockaddr_storage ss;
68
105357
  socklen_t ss_len = sizeof(ss);
69
105357
  memset(&ss, 0, ss_len);
70
105357
  auto& os_sys_calls = Api::OsSysCallsSingleton::get();
71
105357
  Api::SysCallIntResult result =
72
105357
      os_sys_calls.getsockname(fd_, reinterpret_cast<sockaddr*>(&ss), &ss_len);
73
105357
  if (result.return_value_ != 0) {
74
    return absl::InvalidArgumentError(fmt::format("getsockname failed for '{}': ({}) {}", fd_,
75
                                                  result.errno_, errorDetails(result.errno_)));
76
  }
77
105357
  return Address::addressFromSockAddr(ss, ss_len, socket_v6only_);
78
105357
}
79

            
80
585
absl::StatusOr<Address::InstanceConstSharedPtr> IoSocketHandleBaseImpl::peerAddress() {
81
585
  sockaddr_storage ss;
82
585
  socklen_t ss_len = sizeof(ss);
83
585
  memset(&ss, 0, ss_len);
84
585
  auto& os_sys_calls = Api::OsSysCallsSingleton::get();
85
585
  Api::SysCallIntResult result =
86
585
      os_sys_calls.getpeername(fd_, reinterpret_cast<sockaddr*>(&ss), &ss_len);
87
585
  if (result.return_value_ != 0) {
88
    return absl::InvalidArgumentError(
89
        fmt::format("getpeername failed for '{}': {}", fd_, errorDetails(result.errno_)));
90
  }
91

            
92
585
  if (static_cast<unsigned int>(ss_len) >=
93
585
          (offsetof(sockaddr_storage, ss_family) + sizeof(ss.ss_family)) &&
94
585
      ss.ss_family == AF_UNIX) {
95
    // For Unix domain sockets, can't find out the peer name, but it should match our own
96
    // name for the socket (i.e. the path should match, barring any namespace or other
97
    // mechanisms to hide things, of which there are many).
98
27
    ss_len = sizeof(ss);
99
27
    result = os_sys_calls.getsockname(fd_, reinterpret_cast<sockaddr*>(&ss), &ss_len);
100
27
    if (result.return_value_ != 0) {
101
      throwEnvoyExceptionOrPanic(
102
          fmt::format("getsockname failed for '{}': {}", fd_, errorDetails(result.errno_)));
103
    }
104
27
  }
105
585
  return Address::addressFromSockAddr(ss, ss_len, socket_v6only_);
106
585
}
107

            
108
54108
absl::optional<std::chrono::milliseconds> IoSocketHandleBaseImpl::lastRoundTripTime() {
109
54108
  Api::EnvoyTcpInfo info;
110
54108
  auto result = Api::OsSysCallsSingleton::get().socketTcpInfo(fd_, &info);
111
54108
  if (!result.return_value_) {
112
29
    return {};
113
29
  }
114
54079
  return std::chrono::duration_cast<std::chrono::milliseconds>(info.tcpi_rtt);
115
54108
}
116

            
117
2
absl::optional<uint64_t> IoSocketHandleBaseImpl::congestionWindowInBytes() const {
118
2
  Api::EnvoyTcpInfo info;
119
2
  auto result = Api::OsSysCallsSingleton::get().socketTcpInfo(fd_, &info);
120
2
  if (!result.return_value_) {
121
    return {};
122
  }
123
2
  return info.tcpi_snd_cwnd;
124
2
}
125

            
126
14
absl::optional<std::string> IoSocketHandleBaseImpl::interfaceName() {
127
14
  auto& os_syscalls_singleton = Api::OsSysCallsSingleton::get();
128
14
  if (!os_syscalls_singleton.supportsGetifaddrs()) {
129
1
    return absl::nullopt;
130
1
  }
131

            
132
13
  auto address_or_error = localAddress();
133
13
  if (!address_or_error.status().ok()) {
134
    return absl::nullopt;
135
  }
136
13
  Address::InstanceConstSharedPtr& socket_address = *address_or_error;
137
13
  if (!socket_address || socket_address->type() != Address::Type::Ip) {
138
1
    return absl::nullopt;
139
1
  }
140

            
141
12
  Api::InterfaceAddressVector interface_addresses{};
142
12
  const Api::SysCallIntResult rc = os_syscalls_singleton.getifaddrs(interface_addresses);
143
12
  if (rc.return_value_ != 0) {
144
1
    ENVOY_LOG_EVERY_POW_2(warn, "getifaddrs error: {}", rc.errno_);
145
1
    return absl::nullopt;
146
1
  }
147

            
148
11
  absl::optional<std::string> selected_interface_name{};
149
11
  for (const auto& interface_address : interface_addresses) {
150
10
    if (!interface_address.interface_addr_) {
151
      continue;
152
    }
153

            
154
10
    if (socket_address->ip()->version() == interface_address.interface_addr_->ip()->version()) {
155
      // Compare address _without port_.
156
      // TODO: create common addressAsStringWithoutPort method to simplify code here.
157
10
      absl::uint128 socket_address_value;
158
10
      absl::uint128 interface_address_value;
159
10
      switch (socket_address->ip()->version()) {
160
10
      case Address::IpVersion::v4:
161
10
        socket_address_value = socket_address->ip()->ipv4()->address();
162
10
        interface_address_value = interface_address.interface_addr_->ip()->ipv4()->address();
163
10
        break;
164
      case Address::IpVersion::v6:
165
        socket_address_value = socket_address->ip()->ipv6()->address();
166
        interface_address_value = interface_address.interface_addr_->ip()->ipv6()->address();
167
        break;
168
      default:
169
        ENVOY_BUG(false, fmt::format("unexpected IP family {}",
170
10
                                     static_cast<int>(socket_address->ip()->version())));
171
10
      }
172

            
173
10
      if (socket_address_value == interface_address_value) {
174
10
        selected_interface_name = interface_address.interface_name_;
175
10
        break;
176
10
      }
177
10
    }
178
10
  }
179

            
180
11
  return selected_interface_name;
181
11
}
182

            
183
} // namespace Network
184
} // namespace Envoy