1
#include "source/common/api/os_sys_calls_impl.h"
2

            
3
#include <fcntl.h>
4
#include <sys/stat.h>
5
#include <unistd.h>
6

            
7
#include <cerrno>
8
#include <string>
9

            
10
#include "envoy/network/socket.h"
11

            
12
#include "source/common/network/address_impl.h"
13

            
14
#if defined(__ANDROID_API__) && __ANDROID_API__ < 24
15
#pragma clang diagnostic push
16
#pragma clang diagnostic ignored "-Wold-style-cast"
17
namespace android {
18
#include "third_party/android/ifaddrs-android.h"
19
} // namespace android
20
#pragma clang diagnostic pop
21
#endif
22

            
23
namespace Envoy {
24
namespace Api {
25

            
26
42566
SysCallIntResult OsSysCallsImpl::bind(os_fd_t sockfd, const sockaddr* addr, socklen_t addrlen) {
27
42566
  const int rc = ::bind(sockfd, addr, addrlen);
28
42566
  return {rc, rc != -1 ? 0 : errno};
29
42566
}
30

            
31
8
SysCallIntResult OsSysCallsImpl::chmod(const std::string& path, mode_t mode) {
32
8
  const int rc = ::chmod(path.c_str(), mode);
33
8
  return {rc, rc != -1 ? 0 : errno};
34
8
}
35

            
36
SysCallIntResult OsSysCallsImpl::ioctl(os_fd_t sockfd, unsigned long request, void* argp,
37
1
                                       unsigned long, void*, unsigned long, unsigned long*) {
38
1
  const int rc = ::ioctl(sockfd, request, argp);
39
1
  return {rc, rc != -1 ? 0 : errno};
40
1
}
41

            
42
243190
SysCallIntResult OsSysCallsImpl::close(os_fd_t fd) {
43
243190
  const int rc = ::close(fd);
44
243206
  return {rc, rc != -1 ? 0 : errno};
45
243190
}
46

            
47
174630
SysCallSizeResult OsSysCallsImpl::writev(os_fd_t fd, const iovec* iov, int num_iov) {
48
174630
  const ssize_t rc = ::writev(fd, iov, num_iov);
49
174630
  return {rc, rc != -1 ? 0 : errno};
50
174630
}
51

            
52
1053611
SysCallSizeResult OsSysCallsImpl::readv(os_fd_t fd, const iovec* iov, int num_iov) {
53
1053611
  const ssize_t rc = ::readv(fd, iov, num_iov);
54
1053611
  return {rc, rc != -1 ? 0 : errno};
55
1053611
}
56

            
57
SysCallSizeResult OsSysCallsImpl::pwrite(os_fd_t fd, const void* buffer, size_t length,
58
1983
                                         off_t offset) const {
59
1983
  const ssize_t rc = ::pwrite(fd, buffer, length, offset);
60
1983
  return {rc, rc != -1 ? 0 : errno};
61
1983
}
62

            
63
SysCallSizeResult OsSysCallsImpl::pread(os_fd_t fd, void* buffer, size_t length,
64
1798
                                        off_t offset) const {
65
1798
  const ssize_t rc = ::pread(fd, buffer, length, offset);
66
1798
  return {rc, rc != -1 ? 0 : errno};
67
1798
}
68

            
69
661242
SysCallSizeResult OsSysCallsImpl::send(os_fd_t socket, void* buffer, size_t length, int flags) {
70
661242
  const ssize_t rc = ::send(socket, buffer, length, flags);
71
661242
  return {rc, rc != -1 ? 0 : errno};
72
661242
}
73

            
74
135496
SysCallSizeResult OsSysCallsImpl::recv(os_fd_t socket, void* buffer, size_t length, int flags) {
75
135496
  const ssize_t rc = ::recv(socket, buffer, length, flags);
76
135496
  return {rc, rc != -1 ? 0 : errno};
77
135496
}
78

            
79
436201
SysCallSizeResult OsSysCallsImpl::recvmsg(os_fd_t sockfd, msghdr* msg, int flags) {
80
436201
  const ssize_t rc = ::recvmsg(sockfd, msg, flags);
81
436201
  return {rc, rc != -1 ? 0 : errno};
82
436201
}
83

            
84
SysCallIntResult OsSysCallsImpl::recvmmsg(os_fd_t sockfd, struct mmsghdr* msgvec, unsigned int vlen,
85
125018
                                          int flags, struct timespec* timeout) {
86
125018
#if ENVOY_MMSG_MORE
87
125018
  const int rc = ::recvmmsg(sockfd, msgvec, vlen, flags, timeout);
88
125018
  return {rc, errno};
89
#else
90
  UNREFERENCED_PARAMETER(sockfd);
91
  UNREFERENCED_PARAMETER(msgvec);
92
  UNREFERENCED_PARAMETER(vlen);
93
  UNREFERENCED_PARAMETER(flags);
94
  UNREFERENCED_PARAMETER(timeout);
95
  return {false, EOPNOTSUPP};
96
#endif
97
125018
}
98

            
99
56272
bool OsSysCallsImpl::supportsMmsg() const {
100
56272
#if ENVOY_MMSG_MORE
101
56272
  return true;
102
#else
103
  return false;
104
#endif
105
56272
}
106

            
107
51151
bool OsSysCallsImpl::supportsUdpGro() const {
108
#if !defined(__linux__)
109
  return false;
110
#else
111
51151
  static const bool is_supported = [] {
112
130
    int fd = ::socket(AF_INET, SOCK_DGRAM | SOCK_NONBLOCK, IPPROTO_UDP);
113
130
    int val = 1;
114
130
    bool result = (0 == ::setsockopt(fd, IPPROTO_UDP, UDP_GRO, &val, sizeof(val)));
115
130
    ::close(fd);
116
130
    return result;
117
130
  }();
118
51151
  return is_supported;
119
51151
#endif
120
51151
}
121

            
122
1062
bool OsSysCallsImpl::supportsUdpGso() const {
123
#if !defined(__linux__)
124
  return false;
125
#else
126
1062
  static const bool is_supported = [] {
127
108
    int fd = ::socket(AF_INET, SOCK_DGRAM | SOCK_NONBLOCK, IPPROTO_UDP);
128
108
    int optval;
129
108
    socklen_t optlen = sizeof(optval);
130
108
    bool result = (0 <= ::getsockopt(fd, IPPROTO_UDP, UDP_SEGMENT, &optval, &optlen));
131
108
    ::close(fd);
132
108
    return result;
133
108
  }();
134
1062
  return is_supported;
135
1062
#endif
136
1062
}
137

            
138
1
bool OsSysCallsImpl::supportsIpTransparent(Network::Address::IpVersion ip_version) const {
139
#if !defined(__linux__)
140
  UNREFERENCED_PARAMETER(ip_version);
141
  return false;
142
#else
143
  // The linux kernel supports IP_TRANSPARENT by following patch(starting from v2.6.28) :
144
  // https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/net/ipv4/ip_sockglue.c?id=f5715aea4564f233767ea1d944b2637a5fd7cd2e
145
  //
146
  // The linux kernel supports IPV6_TRANSPARENT by following patch(starting from v2.6.37) :
147
  // https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/net/ipv6/ipv6_sockglue.c?id=6c46862280c5f55eda7750391bc65cd7e08c7535
148
  //
149
  // So, almost recent linux kernel supports both IP_TRANSPARENT and IPV6_TRANSPARENT options.
150
  // But there are also has ipv4 only or ipv6 only scenarios.
151
  //
152
  // And these socket options need CAP_NET_ADMIN capability to be applied.
153
  // The CAP_NET_ADMIN capability should be applied by root user before call this function.
154

            
155
2
  static constexpr auto transparent_supported = [](int family) {
156
2
    auto opt_tp = family == AF_INET ? ENVOY_SOCKET_IP_TRANSPARENT : ENVOY_SOCKET_IPV6_TRANSPARENT;
157
2
    int fd = ::socket(family, SOCK_DGRAM | SOCK_NONBLOCK, IPPROTO_UDP);
158
2
    int val = 1;
159
2
    bool result = (0 == ::setsockopt(fd, opt_tp.level(), opt_tp.option(), &val, sizeof(val)));
160
2
    ::close(fd);
161
2
    return result;
162
2
  };
163
  // Check ipv4 case
164
1
  static const bool ipv4_is_supported = transparent_supported(AF_INET);
165
  // Check ipv6 case
166
1
  static const bool ipv6_is_supported = transparent_supported(AF_INET6);
167
1
  return ip_version == Network::Address::IpVersion::v4 ? ipv4_is_supported : ipv6_is_supported;
168
1
#endif
169
1
}
170

            
171
1
bool OsSysCallsImpl::supportsMptcp() const {
172
#if !defined(__linux__)
173
  return false;
174
#else
175
1
  int fd = ::socket(AF_INET, SOCK_STREAM, IPPROTO_MPTCP);
176
1
  if (fd < 0) {
177
    return false;
178
  }
179

            
180
1
  ::close(fd);
181
1
  return true;
182
1
#endif
183
1
}
184

            
185
12
SysCallIntResult OsSysCallsImpl::ftruncate(int fd, off_t length) {
186
12
  const int rc = ::ftruncate(fd, length);
187
12
  return {rc, rc != -1 ? 0 : errno};
188
12
}
189

            
190
SysCallPtrResult OsSysCallsImpl::mmap(void* addr, size_t length, int prot, int flags, int fd,
191
10
                                      off_t offset) {
192
10
  void* rc = ::mmap(addr, length, prot, flags, fd, offset);
193
10
  return {rc, rc != MAP_FAILED ? 0 : errno};
194
10
}
195

            
196
2585
SysCallIntResult OsSysCallsImpl::stat(const char* pathname, struct stat* buf) {
197
2585
  const int rc = ::stat(pathname, buf);
198
2585
  return {rc, rc != -1 ? 0 : errno};
199
2585
}
200

            
201
10
SysCallIntResult OsSysCallsImpl::fstat(os_fd_t fd, struct stat* buf) {
202
10
  const int rc = ::fstat(fd, buf);
203
10
  return {rc, rc != -1 ? 0 : errno};
204
10
}
205

            
206
SysCallIntResult OsSysCallsImpl::setsockopt(os_fd_t sockfd, int level, int optname,
207
178606
                                            const void* optval, socklen_t optlen) {
208
178606
  const int rc = ::setsockopt(sockfd, level, optname, optval, optlen);
209
178606
  return {rc, rc != -1 ? 0 : errno};
210
178606
}
211

            
212
SysCallIntResult OsSysCallsImpl::getsockopt(os_fd_t sockfd, int level, int optname, void* optval,
213
55277
                                            socklen_t* optlen) {
214
55277
  const int rc = ::getsockopt(sockfd, level, optname, optval, optlen);
215
55277
  return {rc, rc != -1 ? 0 : errno};
216
55277
}
217

            
218
187882
SysCallSocketResult OsSysCallsImpl::socket(int domain, int type, int protocol) {
219
187882
  const os_fd_t rc = ::socket(domain, type, protocol);
220
187882
  return {rc, SOCKET_VALID(rc) ? 0 : errno};
221
187882
}
222

            
223
356658
SysCallSizeResult OsSysCallsImpl::sendmsg(os_fd_t fd, const msghdr* message, int flags) {
224
356658
  const int rc = ::sendmsg(fd, message, flags);
225
356658
  return {rc, rc != -1 ? 0 : errno};
226
356658
}
227

            
228
105380
SysCallIntResult OsSysCallsImpl::getsockname(os_fd_t sockfd, sockaddr* addr, socklen_t* addrlen) {
229
105380
  const int rc = ::getsockname(sockfd, addr, addrlen);
230
105380
  return {rc, rc != -1 ? 0 : errno};
231
105380
}
232

            
233
1
SysCallIntResult OsSysCallsImpl::gethostname(char* name, size_t length) {
234
1
  const int rc = ::gethostname(name, length);
235
1
  return {rc, rc != -1 ? 0 : errno};
236
1
}
237

            
238
584
SysCallIntResult OsSysCallsImpl::getpeername(os_fd_t sockfd, sockaddr* name, socklen_t* namelen) {
239
584
  const int rc = ::getpeername(sockfd, name, namelen);
240
584
  return {rc, rc != -1 ? 0 : errno};
241
584
}
242

            
243
178
SysCallIntResult OsSysCallsImpl::setsocketblocking(os_fd_t sockfd, bool blocking) {
244
178
  const int flags = ::fcntl(sockfd, F_GETFL, 0);
245
178
  int rc;
246
178
  if (flags == -1) {
247
8
    return {-1, errno};
248
8
  }
249
170
  if (blocking) {
250
158
    rc = ::fcntl(sockfd, F_SETFL, flags & ~O_NONBLOCK);
251
169
  } else {
252
12
    rc = ::fcntl(sockfd, F_SETFL, flags | O_NONBLOCK);
253
12
  }
254
170
  return {rc, rc != -1 ? 0 : errno};
255
178
}
256

            
257
56849
SysCallIntResult OsSysCallsImpl::connect(os_fd_t sockfd, const sockaddr* addr, socklen_t addrlen) {
258
56849
  const int rc = ::connect(sockfd, addr, addrlen);
259
56849
  return {rc, rc != -1 ? 0 : errno};
260
56849
}
261

            
262
108
SysCallIntResult OsSysCallsImpl::open(const char* pathname, int flags) const {
263
108
  const int rc = ::open(pathname, flags);
264
108
  return {rc, rc != -1 ? 0 : errno};
265
108
}
266

            
267
59
SysCallIntResult OsSysCallsImpl::open(const char* pathname, int flags, mode_t mode) const {
268
59
  const int rc = ::open(pathname, flags, mode);
269
59
  return {rc, rc != -1 ? 0 : errno};
270
59
}
271

            
272
44
SysCallIntResult OsSysCallsImpl::unlink(const char* pathname) const {
273
44
  const int rc = ::unlink(pathname);
274
44
  return {rc, rc != -1 ? 0 : errno};
275
44
}
276

            
277
SysCallIntResult OsSysCallsImpl::linkat(os_fd_t olddirfd, const char* oldpath, os_fd_t newdirfd,
278
40
                                        const char* newpath, int flags) const {
279
40
  const int rc = ::linkat(olddirfd, oldpath, newdirfd, newpath, flags);
280
40
  return {rc, rc != -1 ? 0 : errno};
281
40
}
282

            
283
7
SysCallIntResult OsSysCallsImpl::mkstemp(char* tmplate) const {
284
7
  const int rc = ::mkstemp(tmplate);
285
7
  return {rc, rc != -1 ? 0 : errno};
286
7
}
287

            
288
150
bool OsSysCallsImpl::supportsAllPosixFileOperations() const { return true; }
289

            
290
3059
SysCallIntResult OsSysCallsImpl::shutdown(os_fd_t sockfd, int how) {
291
3059
  const int rc = ::shutdown(sockfd, how);
292
3059
  return {rc, rc != -1 ? 0 : errno};
293
3059
}
294

            
295
9
SysCallIntResult OsSysCallsImpl::socketpair(int domain, int type, int protocol, os_fd_t sv[2]) {
296
9
  const int rc = ::socketpair(domain, type, protocol, sv);
297
9
  return {rc, rc != -1 ? 0 : errno};
298
9
}
299

            
300
37432
SysCallIntResult OsSysCallsImpl::listen(os_fd_t sockfd, int backlog) {
301
37432
  const int rc = ::listen(sockfd, backlog);
302
37432
  return {rc, rc != -1 ? 0 : errno};
303
37432
}
304

            
305
19
SysCallSizeResult OsSysCallsImpl::write(os_fd_t sockfd, const void* buffer, size_t length) {
306
19
  const ssize_t rc = ::write(sockfd, buffer, length);
307
19
  return {rc, rc != -1 ? 0 : errno};
308
19
}
309

            
310
234
SysCallSocketResult OsSysCallsImpl::duplicate(os_fd_t oldfd) {
311
234
  const int rc = ::dup(oldfd);
312
234
  return {rc, rc != -1 ? 0 : errno};
313
234
}
314

            
315
108919
SysCallSocketResult OsSysCallsImpl::accept(os_fd_t sockfd, sockaddr* addr, socklen_t* addrlen) {
316
108919
  os_fd_t rc;
317

            
318
108919
#if defined(__linux__)
319
108919
  rc = ::accept4(sockfd, addr, addrlen, SOCK_NONBLOCK);
320
#else
321
  rc = ::accept(sockfd, addr, addrlen);
322
  if (rc >= 0) {
323
    setsocketblocking(rc, false);
324
  }
325
#endif
326
108919
  return {rc, rc != -1 ? 0 : errno};
327
108919
}
328

            
329
SysCallBoolResult OsSysCallsImpl::socketTcpInfo([[maybe_unused]] os_fd_t sockfd,
330
54108
                                                [[maybe_unused]] EnvoyTcpInfo* tcp_info) {
331
54108
#ifdef TCP_INFO
332
54108
  struct tcp_info unix_tcp_info;
333
54108
  socklen_t len = sizeof(unix_tcp_info);
334
54108
  auto result = ::getsockopt(sockfd, IPPROTO_TCP, TCP_INFO, &unix_tcp_info, &len);
335
54108
  if (!SOCKET_FAILURE(result)) {
336
54080
    tcp_info->tcpi_rtt = std::chrono::microseconds(unix_tcp_info.tcpi_rtt);
337

            
338
54080
    const uint64_t mss = (unix_tcp_info.tcpi_snd_mss > 0) ? unix_tcp_info.tcpi_snd_mss : 1460;
339
    // Convert packets to bytes.
340
54080
    tcp_info->tcpi_snd_cwnd = unix_tcp_info.tcpi_snd_cwnd * mss;
341
54080
  }
342
54108
  return {!SOCKET_FAILURE(result), !SOCKET_FAILURE(result) ? 0 : errno};
343
#else
344
  return {false, EOPNOTSUPP};
345
#endif
346
54108
}
347

            
348
10860
bool OsSysCallsImpl::supportsGetifaddrs() const { return true; }
349

            
350
10674
SysCallIntResult OsSysCallsImpl::getifaddrs([[maybe_unused]] InterfaceAddressVector& interfaces) {
351
#if defined(__ANDROID_API__) && __ANDROID_API__ < 24
352
  struct android::ifaddrs* ifaddr;
353
  struct android::ifaddrs* ifa;
354

            
355
  const int rc = android::getifaddrs(&ifaddr);
356
  if (rc == -1) {
357
    return {rc, errno};
358
  }
359

            
360
  for (ifa = ifaddr; ifa != nullptr; ifa = ifa->ifa_next) {
361
    if (ifa->ifa_addr == nullptr) {
362
      continue;
363
    }
364

            
365
    if (ifa->ifa_addr->sa_family == AF_INET || ifa->ifa_addr->sa_family == AF_INET6) {
366
      const sockaddr_storage* ss = reinterpret_cast<sockaddr_storage*>(ifa->ifa_addr);
367
      size_t ss_len =
368
          ifa->ifa_addr->sa_family == AF_INET ? sizeof(sockaddr_in) : sizeof(sockaddr_in6);
369
      StatusOr<Network::Address::InstanceConstSharedPtr> address =
370
          Network::Address::addressFromSockAddr(*ss, ss_len, ifa->ifa_addr->sa_family == AF_INET6);
371
      if (address.ok()) {
372
        interfaces.emplace_back(ifa->ifa_name, ifa->ifa_flags, *address);
373
      }
374
    }
375
  }
376

            
377
  if (ifaddr) {
378
    android::freeifaddrs(ifaddr);
379
  }
380
  return {rc, 0};
381
#else
382
10674
  struct ifaddrs* ifaddr;
383
10674
  struct ifaddrs* ifa;
384

            
385
10674
  const int rc = ::getifaddrs(&ifaddr);
386
10674
  if (rc == -1) {
387
    return {rc, errno};
388
  }
389

            
390
85392
  for (ifa = ifaddr; ifa != nullptr; ifa = ifa->ifa_next) {
391
74718
    if (ifa->ifa_addr == nullptr) {
392
      continue;
393
    }
394

            
395
74718
    if (ifa->ifa_addr->sa_family == AF_INET || ifa->ifa_addr->sa_family == AF_INET6) {
396
53370
      const sockaddr_storage* ss = reinterpret_cast<sockaddr_storage*>(ifa->ifa_addr);
397
53370
      size_t ss_len =
398
53370
          ifa->ifa_addr->sa_family == AF_INET ? sizeof(sockaddr_in) : sizeof(sockaddr_in6);
399
53370
      StatusOr<Network::Address::InstanceConstSharedPtr> address =
400
53370
          Network::Address::addressFromSockAddr(*ss, ss_len, ifa->ifa_addr->sa_family == AF_INET6);
401
53370
      if (address.ok()) {
402
53370
        interfaces.emplace_back(ifa->ifa_name, ifa->ifa_flags, *address);
403
53370
      }
404
53370
    }
405
74718
  }
406

            
407
10674
  if (ifaddr) {
408
10674
    ::freeifaddrs(ifaddr);
409
10674
  }
410

            
411
10674
  return {rc, 0};
412
10674
#endif
413
10674
}
414

            
415
SysCallIntResult OsSysCallsImpl::getaddrinfo(const char* node, const char* service,
416
48533
                                             const addrinfo* hints, addrinfo** res) {
417
48533
  const int rc = ::getaddrinfo(node, service, hints, res);
418
48533
  return {rc, errno};
419
48533
}
420

            
421
45794
void OsSysCallsImpl::freeaddrinfo(addrinfo* res) { ::freeaddrinfo(res); }
422

            
423
10668
SysCallIntResult OsSysCallsImpl::getrlimit(int resource, struct rlimit* rlim) {
424
10668
  const int rc = ::getrlimit(resource, rlim);
425
10668
  return {rc, errno};
426
10668
}
427

            
428
SysCallIntResult OsSysCallsImpl::setrlimit(int resource, const struct rlimit* rlim) {
429
  const int rc = ::setrlimit(resource, rlim);
430
  return {rc, errno};
431
}
432

            
433
} // namespace Api
434
} // namespace Envoy