Coverage Report

Created: 2023-11-12 09:30

/proc/self/cwd/source/common/api/posix/os_sys_calls_impl.cc
Line
Count
Source (jump to first uncovered line)
1
#include <fcntl.h>
2
#include <sys/stat.h>
3
#include <unistd.h>
4
5
#include <cerrno>
6
#include <string>
7
8
#include "envoy/network/socket.h"
9
10
#include "source/common/api/os_sys_calls_impl.h"
11
#include "source/common/network/address_impl.h"
12
13
#if defined(__ANDROID_API__) && __ANDROID_API__ < 24
14
#pragma clang diagnostic push
15
#pragma clang diagnostic ignored "-Wold-style-cast"
16
namespace android {
17
#include "third_party/android/ifaddrs-android.h"
18
} // namespace android
19
#pragma clang diagnostic pop
20
#endif
21
22
namespace Envoy {
23
namespace Api {
24
25
26.4k
SysCallIntResult OsSysCallsImpl::bind(os_fd_t sockfd, const sockaddr* addr, socklen_t addrlen) {
26
26.4k
  const int rc = ::bind(sockfd, addr, addrlen);
27
26.4k
  return {rc, rc != -1 ? 0 : errno};
28
26.4k
}
29
30
13
SysCallIntResult OsSysCallsImpl::chmod(const std::string& path, mode_t mode) {
31
13
  const int rc = ::chmod(path.c_str(), mode);
32
13
  return {rc, rc != -1 ? 0 : errno};
33
13
}
34
35
SysCallIntResult OsSysCallsImpl::ioctl(os_fd_t sockfd, unsigned long request, void* argp,
36
0
                                       unsigned long, void*, unsigned long, unsigned long*) {
37
0
  const int rc = ::ioctl(sockfd, request, argp);
38
0
  return {rc, rc != -1 ? 0 : errno};
39
0
}
40
41
283k
SysCallIntResult OsSysCallsImpl::close(os_fd_t fd) {
42
283k
  const int rc = ::close(fd);
43
283k
  return {rc, rc != -1 ? 0 : errno};
44
283k
}
45
46
5.14k
SysCallSizeResult OsSysCallsImpl::writev(os_fd_t fd, const iovec* iov, int num_iov) {
47
5.14k
  const ssize_t rc = ::writev(fd, iov, num_iov);
48
5.14k
  return {rc, rc != -1 ? 0 : errno};
49
5.14k
}
50
51
48.1k
SysCallSizeResult OsSysCallsImpl::readv(os_fd_t fd, const iovec* iov, int num_iov) {
52
48.1k
  const ssize_t rc = ::readv(fd, iov, num_iov);
53
48.1k
  return {rc, rc != -1 ? 0 : errno};
54
48.1k
}
55
56
SysCallSizeResult OsSysCallsImpl::pwrite(os_fd_t fd, const void* buffer, size_t length,
57
0
                                         off_t offset) const {
58
0
  const ssize_t rc = ::pwrite(fd, buffer, length, offset);
59
0
  return {rc, rc != -1 ? 0 : errno};
60
0
}
61
62
SysCallSizeResult OsSysCallsImpl::pread(os_fd_t fd, void* buffer, size_t length,
63
0
                                        off_t offset) const {
64
0
  const ssize_t rc = ::pread(fd, buffer, length, offset);
65
0
  return {rc, rc != -1 ? 0 : errno};
66
0
}
67
68
24.1k
SysCallSizeResult OsSysCallsImpl::send(os_fd_t socket, void* buffer, size_t length, int flags) {
69
24.1k
  const ssize_t rc = ::send(socket, buffer, length, flags);
70
24.1k
  return {rc, rc != -1 ? 0 : errno};
71
24.1k
}
72
73
9.70k
SysCallSizeResult OsSysCallsImpl::recv(os_fd_t socket, void* buffer, size_t length, int flags) {
74
9.70k
  const ssize_t rc = ::recv(socket, buffer, length, flags);
75
9.70k
  return {rc, rc != -1 ? 0 : errno};
76
9.70k
}
77
78
0
SysCallSizeResult OsSysCallsImpl::recvmsg(os_fd_t sockfd, msghdr* msg, int flags) {
79
0
  const ssize_t rc = ::recvmsg(sockfd, msg, flags);
80
0
  return {rc, rc != -1 ? 0 : errno};
81
0
}
82
83
SysCallIntResult OsSysCallsImpl::recvmmsg(os_fd_t sockfd, struct mmsghdr* msgvec, unsigned int vlen,
84
0
                                          int flags, struct timespec* timeout) {
85
0
#if ENVOY_MMSG_MORE
86
0
  const int rc = ::recvmmsg(sockfd, msgvec, vlen, flags, timeout);
87
0
  return {rc, errno};
88
#else
89
  UNREFERENCED_PARAMETER(sockfd);
90
  UNREFERENCED_PARAMETER(msgvec);
91
  UNREFERENCED_PARAMETER(vlen);
92
  UNREFERENCED_PARAMETER(flags);
93
  UNREFERENCED_PARAMETER(timeout);
94
  return {false, EOPNOTSUPP};
95
#endif
96
0
}
97
98
0
bool OsSysCallsImpl::supportsMmsg() const {
99
0
#if ENVOY_MMSG_MORE
100
0
  return true;
101
#else
102
  return false;
103
#endif
104
0
}
105
106
58
bool OsSysCallsImpl::supportsUdpGro() const {
107
#if !defined(__linux__)
108
  return false;
109
#else
110
58
  static const bool is_supported = [] {
111
1
    int fd = ::socket(AF_INET, SOCK_DGRAM | SOCK_NONBLOCK, IPPROTO_UDP);
112
1
    if (fd < 0) {
113
0
      return false;
114
0
    }
115
1
    int val = 1;
116
1
    bool result = (0 == ::setsockopt(fd, IPPROTO_UDP, UDP_GRO, &val, sizeof(val)));
117
1
    ::close(fd);
118
1
    return result;
119
1
  }();
120
58
  return is_supported;
121
58
#endif
122
58
}
123
124
3
bool OsSysCallsImpl::supportsUdpGso() const {
125
#if !defined(__linux__)
126
  return false;
127
#else
128
3
  static const bool is_supported = [] {
129
1
    int fd = ::socket(AF_INET, SOCK_DGRAM | SOCK_NONBLOCK, IPPROTO_UDP);
130
1
    if (fd < 0) {
131
0
      return false;
132
0
    }
133
1
    int optval;
134
1
    socklen_t optlen = sizeof(optval);
135
1
    bool result = (0 <= ::getsockopt(fd, IPPROTO_UDP, UDP_SEGMENT, &optval, &optlen));
136
1
    ::close(fd);
137
1
    return result;
138
1
  }();
139
3
  return is_supported;
140
3
#endif
141
3
}
142
143
0
bool OsSysCallsImpl::supportsIpTransparent(Network::Address::IpVersion ip_version) const {
144
#if !defined(__linux__)
145
  UNREFERENCED_PARAMETER(ip_version);
146
  return false;
147
#else
148
  // The linux kernel supports IP_TRANSPARENT by following patch(starting from v2.6.28) :
149
  // https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/net/ipv4/ip_sockglue.c?id=f5715aea4564f233767ea1d944b2637a5fd7cd2e
150
  //
151
  // The linux kernel supports IPV6_TRANSPARENT by following patch(starting from v2.6.37) :
152
  // https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/net/ipv6/ipv6_sockglue.c?id=6c46862280c5f55eda7750391bc65cd7e08c7535
153
  //
154
  // So, almost recent linux kernel supports both IP_TRANSPARENT and IPV6_TRANSPARENT options.
155
  // But there are also has ipv4 only or ipv6 only scenarios.
156
  //
157
  // And these socket options need CAP_NET_ADMIN capability to be applied.
158
  // The CAP_NET_ADMIN capability should be applied by root user before call this function.
159
160
0
  static constexpr auto transparent_supported = [](int family) {
161
0
    auto opt_tp = family == AF_INET ? ENVOY_SOCKET_IP_TRANSPARENT : ENVOY_SOCKET_IPV6_TRANSPARENT;
162
0
    int fd = ::socket(family, SOCK_DGRAM | SOCK_NONBLOCK, IPPROTO_UDP);
163
0
    if (fd < 0) {
164
0
      return false;
165
0
    }
166
0
    int val = 1;
167
0
    bool result = (0 == ::setsockopt(fd, opt_tp.level(), opt_tp.option(), &val, sizeof(val)));
168
0
    ::close(fd);
169
0
    return result;
170
0
  };
171
  // Check ipv4 case
172
0
  static const bool ipv4_is_supported = transparent_supported(AF_INET);
173
  // Check ipv6 case
174
0
  static const bool ipv6_is_supported = transparent_supported(AF_INET6);
175
0
  return ip_version == Network::Address::IpVersion::v4 ? ipv4_is_supported : ipv6_is_supported;
176
0
#endif
177
0
}
178
179
5
bool OsSysCallsImpl::supportsMptcp() const {
180
#if !defined(__linux__)
181
  return false;
182
#else
183
5
  int fd = ::socket(AF_INET, SOCK_STREAM, IPPROTO_MPTCP);
184
5
  if (fd < 0) {
185
5
    return false;
186
5
  }
187
188
0
  ::close(fd);
189
0
  return true;
190
5
#endif
191
5
}
192
193
0
SysCallIntResult OsSysCallsImpl::ftruncate(int fd, off_t length) {
194
0
  const int rc = ::ftruncate(fd, length);
195
0
  return {rc, rc != -1 ? 0 : errno};
196
0
}
197
198
SysCallPtrResult OsSysCallsImpl::mmap(void* addr, size_t length, int prot, int flags, int fd,
199
0
                                      off_t offset) {
200
0
  void* rc = ::mmap(addr, length, prot, flags, fd, offset);
201
0
  return {rc, rc != MAP_FAILED ? 0 : errno};
202
0
}
203
204
12.8k
SysCallIntResult OsSysCallsImpl::stat(const char* pathname, struct stat* buf) {
205
12.8k
  const int rc = ::stat(pathname, buf);
206
12.8k
  return {rc, rc != -1 ? 0 : errno};
207
12.8k
}
208
209
0
SysCallIntResult OsSysCallsImpl::fstat(os_fd_t fd, struct stat* buf) {
210
0
  const int rc = ::fstat(fd, buf);
211
0
  return {rc, rc != -1 ? 0 : errno};
212
0
}
213
214
SysCallIntResult OsSysCallsImpl::setsockopt(os_fd_t sockfd, int level, int optname,
215
72.4k
                                            const void* optval, socklen_t optlen) {
216
72.4k
  const int rc = ::setsockopt(sockfd, level, optname, optval, optlen);
217
72.4k
  return {rc, rc != -1 ? 0 : errno};
218
72.4k
}
219
220
SysCallIntResult OsSysCallsImpl::getsockopt(os_fd_t sockfd, int level, int optname, void* optval,
221
5.79k
                                            socklen_t* optlen) {
222
5.79k
  const int rc = ::getsockopt(sockfd, level, optname, optval, optlen);
223
5.79k
  return {rc, rc != -1 ? 0 : errno};
224
5.79k
}
225
226
263k
SysCallSocketResult OsSysCallsImpl::socket(int domain, int type, int protocol) {
227
263k
  const os_fd_t rc = ::socket(domain, type, protocol);
228
263k
  return {rc, SOCKET_VALID(rc) ? 0 : errno};
229
263k
}
230
231
0
SysCallSizeResult OsSysCallsImpl::sendmsg(os_fd_t fd, const msghdr* message, int flags) {
232
0
  const int rc = ::sendmsg(fd, message, flags);
233
0
  return {rc, rc != -1 ? 0 : errno};
234
0
}
235
236
15.6k
SysCallIntResult OsSysCallsImpl::getsockname(os_fd_t sockfd, sockaddr* addr, socklen_t* addrlen) {
237
15.6k
  const int rc = ::getsockname(sockfd, addr, addrlen);
238
15.6k
  return {rc, rc != -1 ? 0 : errno};
239
15.6k
}
240
241
10.6k
SysCallIntResult OsSysCallsImpl::gethostname(char* name, size_t length) {
242
10.6k
  const int rc = ::gethostname(name, length);
243
10.6k
  return {rc, rc != -1 ? 0 : errno};
244
10.6k
}
245
246
0
SysCallIntResult OsSysCallsImpl::getpeername(os_fd_t sockfd, sockaddr* name, socklen_t* namelen) {
247
0
  const int rc = ::getpeername(sockfd, name, namelen);
248
0
  return {rc, rc != -1 ? 0 : errno};
249
0
}
250
251
0
SysCallIntResult OsSysCallsImpl::setsocketblocking(os_fd_t sockfd, bool blocking) {
252
0
  const int flags = ::fcntl(sockfd, F_GETFL, 0);
253
0
  int rc;
254
0
  if (flags == -1) {
255
0
    return {-1, errno};
256
0
  }
257
0
  if (blocking) {
258
0
    rc = ::fcntl(sockfd, F_SETFL, flags & ~O_NONBLOCK);
259
0
  } else {
260
0
    rc = ::fcntl(sockfd, F_SETFL, flags | O_NONBLOCK);
261
0
  }
262
0
  return {rc, rc != -1 ? 0 : errno};
263
0
}
264
265
7.60k
SysCallIntResult OsSysCallsImpl::connect(os_fd_t sockfd, const sockaddr* addr, socklen_t addrlen) {
266
7.60k
  const int rc = ::connect(sockfd, addr, addrlen);
267
7.60k
  return {rc, rc != -1 ? 0 : errno};
268
7.60k
}
269
270
0
SysCallIntResult OsSysCallsImpl::open(const char* pathname, int flags) const {
271
0
  const int rc = ::open(pathname, flags);
272
0
  return {rc, rc != -1 ? 0 : errno};
273
0
}
274
275
0
SysCallIntResult OsSysCallsImpl::open(const char* pathname, int flags, mode_t mode) const {
276
0
  const int rc = ::open(pathname, flags, mode);
277
0
  return {rc, rc != -1 ? 0 : errno};
278
0
}
279
280
0
SysCallIntResult OsSysCallsImpl::unlink(const char* pathname) const {
281
0
  const int rc = ::unlink(pathname);
282
0
  return {rc, rc != -1 ? 0 : errno};
283
0
}
284
285
SysCallIntResult OsSysCallsImpl::linkat(os_fd_t olddirfd, const char* oldpath, os_fd_t newdirfd,
286
0
                                        const char* newpath, int flags) const {
287
0
  const int rc = ::linkat(olddirfd, oldpath, newdirfd, newpath, flags);
288
0
  return {rc, rc != -1 ? 0 : errno};
289
0
}
290
291
0
SysCallIntResult OsSysCallsImpl::mkstemp(char* tmplate) const {
292
0
  const int rc = ::mkstemp(tmplate);
293
0
  return {rc, rc != -1 ? 0 : errno};
294
0
}
295
296
146
bool OsSysCallsImpl::supportsAllPosixFileOperations() const { return true; }
297
298
46
SysCallIntResult OsSysCallsImpl::shutdown(os_fd_t sockfd, int how) {
299
46
  const int rc = ::shutdown(sockfd, how);
300
46
  return {rc, rc != -1 ? 0 : errno};
301
46
}
302
303
11.2k
SysCallIntResult OsSysCallsImpl::socketpair(int domain, int type, int protocol, os_fd_t sv[2]) {
304
11.2k
  const int rc = ::socketpair(domain, type, protocol, sv);
305
11.2k
  return {rc, rc != -1 ? 0 : errno};
306
11.2k
}
307
308
7.97k
SysCallIntResult OsSysCallsImpl::listen(os_fd_t sockfd, int backlog) {
309
7.97k
  const int rc = ::listen(sockfd, backlog);
310
7.97k
  return {rc, rc != -1 ? 0 : errno};
311
7.97k
}
312
313
0
SysCallSizeResult OsSysCallsImpl::write(os_fd_t sockfd, const void* buffer, size_t length) {
314
0
  const ssize_t rc = ::write(sockfd, buffer, length);
315
0
  return {rc, rc != -1 ? 0 : errno};
316
0
}
317
318
38
SysCallSocketResult OsSysCallsImpl::duplicate(os_fd_t oldfd) {
319
38
  const int rc = ::dup(oldfd);
320
38
  return {rc, rc != -1 ? 0 : errno};
321
38
}
322
323
13.9k
SysCallSocketResult OsSysCallsImpl::accept(os_fd_t sockfd, sockaddr* addr, socklen_t* addrlen) {
324
13.9k
  os_fd_t rc;
325
326
13.9k
#if defined(__linux__)
327
13.9k
  rc = ::accept4(sockfd, addr, addrlen, SOCK_NONBLOCK);
328
  // If failed with EINVAL try without flags
329
13.9k
  if (rc >= 0 || errno != EINVAL) {
330
13.9k
    return {rc, rc != -1 ? 0 : errno};
331
13.9k
  }
332
0
#endif
333
334
0
  rc = ::accept(sockfd, addr, addrlen);
335
0
  if (rc >= 0) {
336
0
    setsocketblocking(rc, false);
337
0
  }
338
339
0
  return {rc, rc != -1 ? 0 : errno};
340
13.9k
}
341
342
SysCallBoolResult OsSysCallsImpl::socketTcpInfo([[maybe_unused]] os_fd_t sockfd,
343
6.99k
                                                [[maybe_unused]] EnvoyTcpInfo* tcp_info) {
344
6.99k
#ifdef TCP_INFO
345
6.99k
  struct tcp_info unix_tcp_info;
346
6.99k
  socklen_t len = sizeof(unix_tcp_info);
347
6.99k
  auto result = ::getsockopt(sockfd, IPPROTO_TCP, TCP_INFO, &unix_tcp_info, &len);
348
6.99k
  if (!SOCKET_FAILURE(result)) {
349
6.99k
    tcp_info->tcpi_rtt = std::chrono::microseconds(unix_tcp_info.tcpi_rtt);
350
351
6.99k
    const uint64_t mss = (unix_tcp_info.tcpi_snd_mss > 0) ? unix_tcp_info.tcpi_snd_mss : 1460;
352
    // Convert packets to bytes.
353
6.99k
    tcp_info->tcpi_snd_cwnd = unix_tcp_info.tcpi_snd_cwnd * mss;
354
6.99k
  }
355
6.99k
  return {!SOCKET_FAILURE(result), !SOCKET_FAILURE(result) ? 0 : errno};
356
0
#endif
357
358
0
  return {false, EOPNOTSUPP};
359
6.99k
}
360
361
2.64k
bool OsSysCallsImpl::supportsGetifaddrs() const { return true; }
362
363
2.64k
SysCallIntResult OsSysCallsImpl::getifaddrs([[maybe_unused]] InterfaceAddressVector& interfaces) {
364
#if defined(__ANDROID_API__) && __ANDROID_API__ < 24
365
  struct android::ifaddrs* ifaddr;
366
  struct android::ifaddrs* ifa;
367
368
  const int rc = android::getifaddrs(&ifaddr);
369
  if (rc == -1) {
370
    return {rc, errno};
371
  }
372
373
  for (ifa = ifaddr; ifa != nullptr; ifa = ifa->ifa_next) {
374
    if (ifa->ifa_addr == nullptr) {
375
      continue;
376
    }
377
378
    if (ifa->ifa_addr->sa_family == AF_INET || ifa->ifa_addr->sa_family == AF_INET6) {
379
      const sockaddr_storage* ss = reinterpret_cast<sockaddr_storage*>(ifa->ifa_addr);
380
      size_t ss_len =
381
          ifa->ifa_addr->sa_family == AF_INET ? sizeof(sockaddr_in) : sizeof(sockaddr_in6);
382
      StatusOr<Network::Address::InstanceConstSharedPtr> address =
383
          Network::Address::addressFromSockAddr(*ss, ss_len, ifa->ifa_addr->sa_family == AF_INET6);
384
      if (address.ok()) {
385
        interfaces.emplace_back(ifa->ifa_name, ifa->ifa_flags, *address);
386
      }
387
    }
388
  }
389
390
  if (ifaddr) {
391
    android::freeifaddrs(ifaddr);
392
  }
393
  return {rc, 0};
394
#else
395
2.64k
  struct ifaddrs* ifaddr;
396
2.64k
  struct ifaddrs* ifa;
397
398
2.64k
  const int rc = ::getifaddrs(&ifaddr);
399
2.64k
  if (rc == -1) {
400
0
    return {rc, errno};
401
0
  }
402
403
13.2k
  for (ifa = ifaddr; ifa != nullptr; ifa = ifa->ifa_next) {
404
10.5k
    if (ifa->ifa_addr == nullptr) {
405
0
      continue;
406
0
    }
407
408
10.5k
    if (ifa->ifa_addr->sa_family == AF_INET || ifa->ifa_addr->sa_family == AF_INET6) {
409
5.29k
      const sockaddr_storage* ss = reinterpret_cast<sockaddr_storage*>(ifa->ifa_addr);
410
5.29k
      size_t ss_len =
411
5.29k
          ifa->ifa_addr->sa_family == AF_INET ? sizeof(sockaddr_in) : sizeof(sockaddr_in6);
412
5.29k
      StatusOr<Network::Address::InstanceConstSharedPtr> address =
413
5.29k
          Network::Address::addressFromSockAddr(*ss, ss_len, ifa->ifa_addr->sa_family == AF_INET6);
414
5.29k
      if (address.ok()) {
415
5.29k
        interfaces.emplace_back(ifa->ifa_name, ifa->ifa_flags, *address);
416
5.29k
      }
417
5.29k
    }
418
10.5k
  }
419
420
2.64k
  if (ifaddr) {
421
2.64k
    ::freeifaddrs(ifaddr);
422
2.64k
  }
423
424
2.64k
  return {rc, 0};
425
2.64k
#endif
426
2.64k
}
427
428
SysCallIntResult OsSysCallsImpl::getaddrinfo(const char* node, const char* service,
429
132k
                                             const addrinfo* hints, addrinfo** res) {
430
132k
  const int rc = ::getaddrinfo(node, service, hints, res);
431
132k
  return {rc, errno};
432
132k
}
433
434
0
void OsSysCallsImpl::freeaddrinfo(addrinfo* res) { ::freeaddrinfo(res); }
435
436
} // namespace Api
437
} // namespace Envoy