blob: 36fcd853289cab13d07f86860be143e51f3aeee8 [file] [log] [blame]
Ken Chend27d6c92021-10-21 22:18:59 +08001/*
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
38namespace android {
39namespace netdutils {
40
41class 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*.
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*.
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>
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>
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>
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>
135 Status bind(Fd sock, const SockaddrT& addr) const {
136 return bind(sock, asSockaddrPtr(&addr), sizeof(addr));
137 }
138
139 template <typename SockaddrT>
140 Status connect(Fd sock, const SockaddrT& addr) const {
141 return connect(sock, asSockaddrPtr(&addr), sizeof(addr));
142 }
143
144 template <size_t size>
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>
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
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>
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.
182class 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
199extern SyscallsHolder sSyscalls;
200
201} // namespace netdutils
202} // namespace android
203
204#endif /* NETDUTILS_SYSCALLS_H */