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 <net/if.h> 23 #include <poll.h> 24 #include <sys/eventfd.h> 25 #include <sys/socket.h> 26 #include <sys/types.h> 27 #include <sys/uio.h> 28 #include <unistd.h> 29 30 #include "netdutils/Fd.h" 31 #include "netdutils/Slice.h" 32 #include "netdutils/Socket.h" 33 #include "netdutils/Status.h" 34 #include "netdutils/StatusOr.h" 35 #include "netdutils/UniqueFd.h" 36 #include "netdutils/UniqueFile.h" 37 38 namespace android { 39 namespace netdutils { 40 41 class Syscalls { 42 public: 43 virtual ~Syscalls() = default; 44 45 virtual StatusOr<UniqueFd> open(const std::string& pathname, int flags, 46 mode_t mode = 0) const = 0; 47 48 virtual StatusOr<UniqueFd> socket(int domain, int type, int protocol) const = 0; 49 50 virtual Status getsockname(Fd sock, sockaddr* addr, socklen_t* addrlen) const = 0; 51 52 virtual Status getsockopt(Fd sock, int level, int optname, void *optval, 53 socklen_t *optlen) const = 0; 54 55 virtual Status setsockopt(Fd sock, int level, int optname, const void* optval, 56 socklen_t optlen) const = 0; 57 58 virtual Status bind(Fd sock, const sockaddr* addr, socklen_t addrlen) const = 0; 59 60 virtual Status connect(Fd sock, const sockaddr* addr, socklen_t addrlen) const = 0; 61 62 virtual StatusOr<ifreq> ioctl(Fd sock, unsigned long request, ifreq* ifr) const = 0; 63 64 virtual StatusOr<UniqueFd> eventfd(unsigned int initval, int flags) const = 0; 65 66 virtual StatusOr<int> ppoll(pollfd* fds, nfds_t nfds, double timeout) const = 0; 67 68 virtual StatusOr<size_t> writev(Fd fd, const std::vector<iovec>& iov) const = 0; 69 70 virtual StatusOr<size_t> write(Fd fd, const Slice buf) const = 0; 71 72 virtual StatusOr<Slice> read(Fd fd, const Slice buf) const = 0; 73 74 virtual StatusOr<size_t> sendto(Fd sock, const Slice buf, int flags, const sockaddr* dst, 75 socklen_t dstlen) const = 0; 76 77 virtual StatusOr<Slice> recvfrom(Fd sock, const Slice dst, int flags, sockaddr* src, 78 socklen_t* srclen) const = 0; 79 80 virtual Status shutdown(Fd fd, int how) const = 0; 81 82 virtual Status close(Fd fd) const = 0; 83 84 virtual StatusOr<UniqueFile> fopen(const std::string& path, const std::string& mode) const = 0; 85 86 virtual StatusOr<int> vfprintf(FILE* file, const char* format, va_list ap) const = 0; 87 88 virtual StatusOr<int> vfscanf(FILE* file, const char* format, va_list ap) const = 0; 89 90 virtual Status fclose(FILE* file) const = 0; 91 92 virtual StatusOr<pid_t> fork() const = 0; 93 94 // va_args helpers 95 // va_start doesn't work when the preceding argument is a reference 96 // type so we're forced to use const char*. fprintf(FILE * file,const char * format,...)97 StatusOr<int> fprintf(FILE* file, const char* format, ...) const { 98 va_list ap; 99 va_start(ap, format); 100 auto result = vfprintf(file, format, ap); 101 va_end(ap); 102 return result; 103 } 104 105 // va_start doesn't work when the preceding argument is a reference 106 // type so we're forced to use const char*. fscanf(FILE * file,const char * format,...)107 StatusOr<int> fscanf(FILE* file, const char* format, ...) const { 108 va_list ap; 109 va_start(ap, format); 110 auto result = vfscanf(file, format, ap); 111 va_end(ap); 112 return result; 113 } 114 115 // Templated helpers that forward directly to methods declared above 116 template <typename SockaddrT> getsockname(Fd sock)117 StatusOr<SockaddrT> getsockname(Fd sock) const { 118 SockaddrT addr = {}; 119 socklen_t addrlen = sizeof(addr); 120 RETURN_IF_NOT_OK(getsockname(sock, asSockaddrPtr(&addr), &addrlen)); 121 return addr; 122 } 123 124 template <typename SockoptT> getsockopt(Fd sock,int level,int optname,void * optval,socklen_t * optlen)125 Status getsockopt(Fd sock, int level, int optname, void* optval, socklen_t* optlen) const { 126 return getsockopt(sock, level, optname, optval, optlen); 127 } 128 129 template <typename SockoptT> setsockopt(Fd sock,int level,int optname,const SockoptT & opt)130 Status setsockopt(Fd sock, int level, int optname, const SockoptT& opt) const { 131 return setsockopt(sock, level, optname, &opt, sizeof(opt)); 132 } 133 134 template <typename SockaddrT> bind(Fd sock,const SockaddrT & addr)135 Status bind(Fd sock, const SockaddrT& addr) const { 136 return bind(sock, asSockaddrPtr(&addr), sizeof(addr)); 137 } 138 139 template <typename SockaddrT> connect(Fd sock,const SockaddrT & addr)140 Status connect(Fd sock, const SockaddrT& addr) const { 141 return connect(sock, asSockaddrPtr(&addr), sizeof(addr)); 142 } 143 144 template <size_t size> ppoll(const std::array<Fd,size> & fds,uint16_t events,double timeout)145 StatusOr<std::array<uint16_t, size>> ppoll(const std::array<Fd, size>& fds, uint16_t events, 146 double timeout) const { 147 std::array<pollfd, size> tmp; 148 for (size_t i = 0; i < size; ++i) { 149 tmp[i].fd = fds[i].get(); 150 tmp[i].events = events; 151 tmp[i].revents = 0; 152 } 153 RETURN_IF_NOT_OK(ppoll(tmp.data(), tmp.size(), timeout).status()); 154 std::array<uint16_t, size> out; 155 for (size_t i = 0; i < size; ++i) { 156 out[i] = tmp[i].revents; 157 } 158 return out; 159 } 160 161 template <typename SockaddrT> sendto(Fd sock,const Slice buf,int flags,const SockaddrT & dst)162 StatusOr<size_t> sendto(Fd sock, const Slice buf, int flags, const SockaddrT& dst) const { 163 return sendto(sock, buf, flags, asSockaddrPtr(&dst), sizeof(dst)); 164 } 165 166 // Ignore src sockaddr recvfrom(Fd sock,const Slice dst,int flags)167 StatusOr<Slice> recvfrom(Fd sock, const Slice dst, int flags) const { 168 return recvfrom(sock, dst, flags, nullptr, nullptr); 169 } 170 171 template <typename SockaddrT> recvfrom(Fd sock,const Slice dst,int flags)172 StatusOr<std::pair<Slice, SockaddrT>> recvfrom(Fd sock, const Slice dst, int flags) const { 173 SockaddrT addr = {}; 174 socklen_t addrlen = sizeof(addr); 175 ASSIGN_OR_RETURN(auto used, recvfrom(sock, dst, flags, asSockaddrPtr(&addr), &addrlen)); 176 return std::make_pair(used, addr); 177 } 178 }; 179 180 // Specialized singleton that supports zero initialization and runtime 181 // override of contained pointer. 182 class SyscallsHolder { 183 public: 184 ~SyscallsHolder(); 185 186 // Return a pointer to an unowned instance of Syscalls. 187 Syscalls& get(); 188 189 // Testing only: set the value returned by getSyscalls. Return the old value. 190 // Callers are responsible for restoring the previous value returned 191 // by getSyscalls to avoid leaks. 192 Syscalls& swap(Syscalls& syscalls); 193 194 private: 195 std::atomic<Syscalls*> mSyscalls{nullptr}; 196 }; 197 198 // Syscalls instance used throughout netdutils 199 extern SyscallsHolder sSyscalls; 200 201 } // namespace netdutils 202 } // namespace android 203 204 #endif /* NETDUTILS_SYSCALLS_H */ 205