1 /* 2 * Copyright (C) 2017 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #ifndef NETDUTILS_SYSCALLS_H 18 #define NETDUTILS_SYSCALLS_H 19 20 #include <memory> 21 22 #include <poll.h> 23 #include <unistd.h> 24 #include <sys/eventfd.h> 25 #include <sys/socket.h> 26 #include <sys/types.h> 27 #include <sys/uio.h> 28 29 #include "netdutils/Slice.h" 30 #include "netdutils/Socket.h" 31 #include "netdutils/Status.h" 32 #include "netdutils/StatusOr.h" 33 #include "netdutils/UniqueFd.h" 34 #include "netdutils/UniqueFile.h" 35 36 namespace android { 37 namespace netdutils { 38 39 class Syscalls { 40 public: 41 virtual ~Syscalls() = default; 42 43 virtual StatusOr<UniqueFd> open(const std::string& pathname, int flags, 44 mode_t mode = 0) const = 0; 45 46 virtual StatusOr<UniqueFd> socket(int domain, int type, int protocol) const = 0; 47 48 virtual Status getsockname(Fd sock, sockaddr* addr, socklen_t* addrlen) const = 0; 49 50 virtual Status getsockopt(Fd sock, int level, int optname, void *optval, 51 socklen_t *optlen) const = 0; 52 53 virtual Status setsockopt(Fd sock, int level, int optname, const void* optval, 54 socklen_t optlen) const = 0; 55 56 virtual Status bind(Fd sock, const sockaddr* addr, socklen_t addrlen) const = 0; 57 58 virtual Status connect(Fd sock, const sockaddr* addr, socklen_t addrlen) const = 0; 59 60 virtual StatusOr<UniqueFd> eventfd(unsigned int initval, int flags) const = 0; 61 62 virtual StatusOr<int> ppoll(pollfd* fds, nfds_t nfds, double timeout) const = 0; 63 64 virtual StatusOr<size_t> writev(Fd fd, const std::vector<iovec>& iov) const = 0; 65 66 virtual StatusOr<size_t> write(Fd fd, const Slice buf) const = 0; 67 68 virtual StatusOr<Slice> read(Fd fd, const Slice buf) const = 0; 69 70 virtual StatusOr<size_t> sendto(Fd sock, const Slice buf, int flags, const sockaddr* dst, 71 socklen_t dstlen) const = 0; 72 73 virtual StatusOr<Slice> recvfrom(Fd sock, const Slice dst, int flags, sockaddr* src, 74 socklen_t* srclen) const = 0; 75 76 virtual Status shutdown(Fd fd, int how) const = 0; 77 78 virtual Status close(Fd fd) const = 0; 79 80 virtual StatusOr<UniqueFile> fopen(const std::string& path, const std::string& mode) const = 0; 81 82 virtual StatusOr<int> vfprintf(FILE* file, const char* format, va_list ap) const = 0; 83 84 virtual StatusOr<int> vfscanf(FILE* file, const char* format, va_list ap) const = 0; 85 86 virtual Status fclose(FILE* file) const = 0; 87 88 virtual StatusOr<pid_t> fork() const = 0; 89 90 // va_args helpers 91 // va_start doesn't work when the preceding argument is a reference 92 // type so we're forced to use const char*. fprintf(FILE * file,const char * format,...)93 StatusOr<int> fprintf(FILE* file, const char* format, ...) const { 94 va_list ap; 95 va_start(ap, format); 96 auto result = vfprintf(file, format, ap); 97 va_end(ap); 98 return result; 99 } 100 101 // va_start doesn't work when the preceding argument is a reference 102 // type so we're forced to use const char*. fscanf(FILE * file,const char * format,...)103 StatusOr<int> fscanf(FILE* file, const char* format, ...) const { 104 va_list ap; 105 va_start(ap, format); 106 auto result = vfscanf(file, format, ap); 107 va_end(ap); 108 return result; 109 } 110 111 // Templated helpers that forward directly to methods declared above 112 template <typename SockaddrT> getsockname(Fd sock)113 StatusOr<SockaddrT> getsockname(Fd sock) const { 114 SockaddrT addr = {}; 115 socklen_t addrlen = sizeof(addr); 116 RETURN_IF_NOT_OK(getsockname(sock, asSockaddrPtr(&addr), &addrlen)); 117 return addr; 118 } 119 120 template <typename SockoptT> getsockopt(Fd sock,int level,int optname,void * optval,socklen_t * optlen)121 Status getsockopt(Fd sock, int level, int optname, void* optval, socklen_t* optlen) const { 122 return getsockopt(sock, level, optname, optval, optlen); 123 } 124 125 template <typename SockoptT> setsockopt(Fd sock,int level,int optname,const SockoptT & opt)126 Status setsockopt(Fd sock, int level, int optname, const SockoptT& opt) const { 127 return setsockopt(sock, level, optname, &opt, sizeof(opt)); 128 } 129 130 template <typename SockaddrT> bind(Fd sock,const SockaddrT & addr)131 Status bind(Fd sock, const SockaddrT& addr) const { 132 return bind(sock, asSockaddrPtr(&addr), sizeof(addr)); 133 } 134 135 template <typename SockaddrT> connect(Fd sock,const SockaddrT & addr)136 Status connect(Fd sock, const SockaddrT& addr) const { 137 return connect(sock, asSockaddrPtr(&addr), sizeof(addr)); 138 } 139 140 template <size_t size> ppoll(const std::array<Fd,size> & fds,uint16_t events,double timeout)141 StatusOr<std::array<uint16_t, size>> ppoll(const std::array<Fd, size>& fds, uint16_t events, 142 double timeout) const { 143 std::array<pollfd, size> tmp; 144 for (size_t i = 0; i < size; ++i) { 145 tmp[i].fd = fds[i].get(); 146 tmp[i].events = events; 147 tmp[i].revents = 0; 148 } 149 RETURN_IF_NOT_OK(ppoll(tmp.data(), tmp.size(), timeout).status()); 150 std::array<uint16_t, size> out; 151 for (size_t i = 0; i < size; ++i) { 152 out[i] = tmp[i].revents; 153 } 154 return out; 155 } 156 157 template <typename SockaddrT> sendto(Fd sock,const Slice buf,int flags,const SockaddrT & dst)158 StatusOr<size_t> sendto(Fd sock, const Slice buf, int flags, const SockaddrT& dst) const { 159 return sendto(sock, buf, flags, asSockaddrPtr(&dst), sizeof(dst)); 160 } 161 162 // Ignore src sockaddr recvfrom(Fd sock,const Slice dst,int flags)163 StatusOr<Slice> recvfrom(Fd sock, const Slice dst, int flags) const { 164 return recvfrom(sock, dst, flags, nullptr, nullptr); 165 } 166 167 template <typename SockaddrT> recvfrom(Fd sock,const Slice dst,int flags)168 StatusOr<std::pair<Slice, SockaddrT>> recvfrom(Fd sock, const Slice dst, int flags) const { 169 SockaddrT addr = {}; 170 socklen_t addrlen = sizeof(addr); 171 ASSIGN_OR_RETURN(auto used, recvfrom(sock, dst, flags, asSockaddrPtr(&addr), &addrlen)); 172 return std::make_pair(used, addr); 173 } 174 }; 175 176 // Specialized singleton that supports zero initialization and runtime 177 // override of contained pointer. 178 class SyscallsHolder { 179 public: 180 ~SyscallsHolder(); 181 182 // Return a pointer to an unowned instance of Syscalls. 183 Syscalls& get(); 184 185 // Testing only: set the value returned by getSyscalls. Return the old value. 186 // Callers are responsible for restoring the previous value returned 187 // by getSyscalls to avoid leaks. 188 Syscalls& swap(Syscalls& syscalls); 189 190 private: 191 std::atomic<Syscalls*> mSyscalls{nullptr}; 192 }; 193 194 // Syscalls instance used throughout netdutils 195 extern SyscallsHolder sSyscalls; 196 197 } // namespace netdutils 198 } // namespace android 199 200 #endif /* NETDUTILS_SYSCALLS_H */ 201