LCOV - code coverage report
Current view: top level - source/common/api/posix - os_sys_calls_impl.cc (source / functions) Hit Total Coverage
Test: coverage.dat Lines: 136 272 50.0 %
Date: 2024-01-05 06:35:25 Functions: 26 50 52.0 %

          Line data    Source code
       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        1317 : SysCallIntResult OsSysCallsImpl::bind(os_fd_t sockfd, const sockaddr* addr, socklen_t addrlen) {
      26        1317 :   const int rc = ::bind(sockfd, addr, addrlen);
      27        1317 :   return {rc, rc != -1 ? 0 : errno};
      28        1317 : }
      29             : 
      30           0 : SysCallIntResult OsSysCallsImpl::chmod(const std::string& path, mode_t mode) {
      31           0 :   const int rc = ::chmod(path.c_str(), mode);
      32           0 :   return {rc, rc != -1 ? 0 : errno};
      33           0 : }
      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        9959 : SysCallIntResult OsSysCallsImpl::close(os_fd_t fd) {
      42        9959 :   const int rc = ::close(fd);
      43        9959 :   return {rc, rc != -1 ? 0 : errno};
      44        9959 : }
      45             : 
      46         478 : SysCallSizeResult OsSysCallsImpl::writev(os_fd_t fd, const iovec* iov, int num_iov) {
      47         478 :   const ssize_t rc = ::writev(fd, iov, num_iov);
      48         478 :   return {rc, rc != -1 ? 0 : errno};
      49         478 : }
      50             : 
      51        4396 : SysCallSizeResult OsSysCallsImpl::readv(os_fd_t fd, const iovec* iov, int num_iov) {
      52        4396 :   const ssize_t rc = ::readv(fd, iov, num_iov);
      53        4396 :   return {rc, rc != -1 ? 0 : errno};
      54        4396 : }
      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        4383 : SysCallSizeResult OsSysCallsImpl::send(os_fd_t socket, void* buffer, size_t length, int flags) {
      69        4383 :   const ssize_t rc = ::send(socket, buffer, length, flags);
      70        4383 :   return {rc, rc != -1 ? 0 : errno};
      71        4383 : }
      72             : 
      73        2403 : SysCallSizeResult OsSysCallsImpl::recv(os_fd_t socket, void* buffer, size_t length, int flags) {
      74        2403 :   const ssize_t rc = ::recv(socket, buffer, length, flags);
      75        2403 :   return {rc, rc != -1 ? 0 : errno};
      76        2403 : }
      77             : 
      78         420 : SysCallSizeResult OsSysCallsImpl::recvmsg(os_fd_t sockfd, msghdr* msg, int flags) {
      79         420 :   const ssize_t rc = ::recvmsg(sockfd, msg, flags);
      80         420 :   return {rc, rc != -1 ? 0 : errno};
      81         420 : }
      82             : 
      83             : SysCallIntResult OsSysCallsImpl::recvmmsg(os_fd_t sockfd, struct mmsghdr* msgvec, unsigned int vlen,
      84          84 :                                           int flags, struct timespec* timeout) {
      85          84 : #if ENVOY_MMSG_MORE
      86          84 :   const int rc = ::recvmmsg(sockfd, msgvec, vlen, flags, timeout);
      87          84 :   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          84 : }
      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           0 : bool OsSysCallsImpl::supportsUdpGro() const {
     107             : #if !defined(__linux__)
     108             :   return false;
     109             : #else
     110           0 :   static const bool is_supported = [] {
     111           0 :     int fd = ::socket(AF_INET, SOCK_DGRAM | SOCK_NONBLOCK, IPPROTO_UDP);
     112           0 :     if (fd < 0) {
     113           0 :       return false;
     114           0 :     }
     115           0 :     int val = 1;
     116           0 :     bool result = (0 == ::setsockopt(fd, IPPROTO_UDP, UDP_GRO, &val, sizeof(val)));
     117           0 :     ::close(fd);
     118           0 :     return result;
     119           0 :   }();
     120           0 :   return is_supported;
     121           0 : #endif
     122           0 : }
     123             : 
     124           0 : bool OsSysCallsImpl::supportsUdpGso() const {
     125             : #if !defined(__linux__)
     126             :   return false;
     127             : #else
     128           0 :   static const bool is_supported = [] {
     129           0 :     int fd = ::socket(AF_INET, SOCK_DGRAM | SOCK_NONBLOCK, IPPROTO_UDP);
     130           0 :     if (fd < 0) {
     131           0 :       return false;
     132           0 :     }
     133           0 :     int optval;
     134           0 :     socklen_t optlen = sizeof(optval);
     135           0 :     bool result = (0 <= ::getsockopt(fd, IPPROTO_UDP, UDP_SEGMENT, &optval, &optlen));
     136           0 :     ::close(fd);
     137           0 :     return result;
     138           0 :   }();
     139           0 :   return is_supported;
     140           0 : #endif
     141           0 : }
     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           0 : bool OsSysCallsImpl::supportsMptcp() const {
     180             : #if !defined(__linux__)
     181             :   return false;
     182             : #else
     183           0 :   int fd = ::socket(AF_INET, SOCK_STREAM, IPPROTO_MPTCP);
     184           0 :   if (fd < 0) {
     185           0 :     return false;
     186           0 :   }
     187             : 
     188           0 :   ::close(fd);
     189           0 :   return true;
     190           0 : #endif
     191           0 : }
     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         111 : SysCallIntResult OsSysCallsImpl::stat(const char* pathname, struct stat* buf) {
     205         111 :   const int rc = ::stat(pathname, buf);
     206         111 :   return {rc, rc != -1 ? 0 : errno};
     207         111 : }
     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        3958 :                                             const void* optval, socklen_t optlen) {
     216        3958 :   const int rc = ::setsockopt(sockfd, level, optname, optval, optlen);
     217        3958 :   return {rc, rc != -1 ? 0 : errno};
     218        3958 : }
     219             : 
     220             : SysCallIntResult OsSysCallsImpl::getsockopt(os_fd_t sockfd, int level, int optname, void* optval,
     221        1178 :                                             socklen_t* optlen) {
     222        1178 :   const int rc = ::getsockopt(sockfd, level, optname, optval, optlen);
     223        1178 :   return {rc, rc != -1 ? 0 : errno};
     224        1178 : }
     225             : 
     226        5206 : SysCallSocketResult OsSysCallsImpl::socket(int domain, int type, int protocol) {
     227        5206 :   const os_fd_t rc = ::socket(domain, type, protocol);
     228        5206 :   return {rc, SOCKET_VALID(rc) ? 0 : errno};
     229        5206 : }
     230             : 
     231         668 : SysCallSizeResult OsSysCallsImpl::sendmsg(os_fd_t fd, const msghdr* message, int flags) {
     232         668 :   const int rc = ::sendmsg(fd, message, flags);
     233         668 :   return {rc, rc != -1 ? 0 : errno};
     234         668 : }
     235             : 
     236        2125 : SysCallIntResult OsSysCallsImpl::getsockname(os_fd_t sockfd, sockaddr* addr, socklen_t* addrlen) {
     237        2125 :   const int rc = ::getsockname(sockfd, addr, addrlen);
     238        2125 :   return {rc, rc != -1 ? 0 : errno};
     239        2125 : }
     240             : 
     241           0 : SysCallIntResult OsSysCallsImpl::gethostname(char* name, size_t length) {
     242           0 :   const int rc = ::gethostname(name, length);
     243           0 :   return {rc, rc != -1 ? 0 : errno};
     244           0 : }
     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          91 : SysCallIntResult OsSysCallsImpl::setsocketblocking(os_fd_t sockfd, bool blocking) {
     252          91 :   const int flags = ::fcntl(sockfd, F_GETFL, 0);
     253          91 :   int rc;
     254          91 :   if (flags == -1) {
     255           0 :     return {-1, errno};
     256           0 :   }
     257          91 :   if (blocking) {
     258          91 :     rc = ::fcntl(sockfd, F_SETFL, flags & ~O_NONBLOCK);
     259          91 :   } else {
     260           0 :     rc = ::fcntl(sockfd, F_SETFL, flags | O_NONBLOCK);
     261           0 :   }
     262          91 :   return {rc, rc != -1 ? 0 : errno};
     263          91 : }
     264             : 
     265        1328 : SysCallIntResult OsSysCallsImpl::connect(os_fd_t sockfd, const sockaddr* addr, socklen_t addrlen) {
     266        1328 :   const int rc = ::connect(sockfd, addr, addrlen);
     267        1328 :   return {rc, rc != -1 ? 0 : errno};
     268        1328 : }
     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           2 : bool OsSysCallsImpl::supportsAllPosixFileOperations() const { return true; }
     297             : 
     298         252 : SysCallIntResult OsSysCallsImpl::shutdown(os_fd_t sockfd, int how) {
     299         252 :   const int rc = ::shutdown(sockfd, how);
     300         252 :   return {rc, rc != -1 ? 0 : errno};
     301         252 : }
     302             : 
     303        3224 : SysCallIntResult OsSysCallsImpl::socketpair(int domain, int type, int protocol, os_fd_t sv[2]) {
     304        3224 :   const int rc = ::socketpair(domain, type, protocol, sv);
     305        3224 :   return {rc, rc != -1 ? 0 : errno};
     306        3224 : }
     307             : 
     308         607 : SysCallIntResult OsSysCallsImpl::listen(os_fd_t sockfd, int backlog) {
     309         607 :   const int rc = ::listen(sockfd, backlog);
     310         607 :   return {rc, rc != -1 ? 0 : errno};
     311         607 : }
     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          18 : SysCallSocketResult OsSysCallsImpl::duplicate(os_fd_t oldfd) {
     319          18 :   const int rc = ::dup(oldfd);
     320          18 :   return {rc, rc != -1 ? 0 : errno};
     321          18 : }
     322             : 
     323        2612 : SysCallSocketResult OsSysCallsImpl::accept(os_fd_t sockfd, sockaddr* addr, socklen_t* addrlen) {
     324        2612 :   os_fd_t rc;
     325             : 
     326        2612 : #if defined(__linux__)
     327        2612 :   rc = ::accept4(sockfd, addr, addrlen, SOCK_NONBLOCK);
     328             :   // If failed with EINVAL try without flags
     329        2612 :   if (rc >= 0 || errno != EINVAL) {
     330        2612 :     return {rc, rc != -1 ? 0 : errno};
     331        2612 :   }
     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        2612 : }
     341             : 
     342             : SysCallBoolResult OsSysCallsImpl::socketTcpInfo([[maybe_unused]] os_fd_t sockfd,
     343        1315 :                                                 [[maybe_unused]] EnvoyTcpInfo* tcp_info) {
     344        1315 : #ifdef TCP_INFO
     345        1315 :   struct tcp_info unix_tcp_info;
     346        1315 :   socklen_t len = sizeof(unix_tcp_info);
     347        1315 :   auto result = ::getsockopt(sockfd, IPPROTO_TCP, TCP_INFO, &unix_tcp_info, &len);
     348        1315 :   if (!SOCKET_FAILURE(result)) {
     349        1315 :     tcp_info->tcpi_rtt = std::chrono::microseconds(unix_tcp_info.tcpi_rtt);
     350             : 
     351        1315 :     const uint64_t mss = (unix_tcp_info.tcpi_snd_mss > 0) ? unix_tcp_info.tcpi_snd_mss : 1460;
     352             :     // Convert packets to bytes.
     353        1315 :     tcp_info->tcpi_snd_cwnd = unix_tcp_info.tcpi_snd_cwnd * mss;
     354        1315 :   }
     355        1315 :   return {!SOCKET_FAILURE(result), !SOCKET_FAILURE(result) ? 0 : errno};
     356           0 : #endif
     357             : 
     358           0 :   return {false, EOPNOTSUPP};
     359        1315 : }
     360             : 
     361          98 : bool OsSysCallsImpl::supportsGetifaddrs() const { return true; }
     362             : 
     363          98 : 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          98 :   struct ifaddrs* ifaddr;
     396          98 :   struct ifaddrs* ifa;
     397             : 
     398          98 :   const int rc = ::getifaddrs(&ifaddr);
     399          98 :   if (rc == -1) {
     400           0 :     return {rc, errno};
     401           0 :   }
     402             : 
     403         686 :   for (ifa = ifaddr; ifa != nullptr; ifa = ifa->ifa_next) {
     404         588 :     if (ifa->ifa_addr == nullptr) {
     405           0 :       continue;
     406           0 :     }
     407             : 
     408         588 :     if (ifa->ifa_addr->sa_family == AF_INET || ifa->ifa_addr->sa_family == AF_INET6) {
     409         392 :       const sockaddr_storage* ss = reinterpret_cast<sockaddr_storage*>(ifa->ifa_addr);
     410         392 :       size_t ss_len =
     411         392 :           ifa->ifa_addr->sa_family == AF_INET ? sizeof(sockaddr_in) : sizeof(sockaddr_in6);
     412         392 :       StatusOr<Network::Address::InstanceConstSharedPtr> address =
     413         392 :           Network::Address::addressFromSockAddr(*ss, ss_len, ifa->ifa_addr->sa_family == AF_INET6);
     414         392 :       if (address.ok()) {
     415         392 :         interfaces.emplace_back(ifa->ifa_name, ifa->ifa_flags, *address);
     416         392 :       }
     417         392 :     }
     418         588 :   }
     419             : 
     420          98 :   if (ifaddr) {
     421          98 :     ::freeifaddrs(ifaddr);
     422          98 :   }
     423             : 
     424          98 :   return {rc, 0};
     425          98 : #endif
     426          98 : }
     427             : 
     428             : SysCallIntResult OsSysCallsImpl::getaddrinfo(const char* node, const char* service,
     429        1029 :                                              const addrinfo* hints, addrinfo** res) {
     430        1029 :   const int rc = ::getaddrinfo(node, service, hints, res);
     431        1029 :   return {rc, errno};
     432        1029 : }
     433             : 
     434           0 : void OsSysCallsImpl::freeaddrinfo(addrinfo* res) { ::freeaddrinfo(res); }
     435             : 
     436             : } // namespace Api
     437             : } // namespace Envoy

Generated by: LCOV version 1.15