1 /*
2 * Copyright (C) 2021-2022 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15 #include <cstdint>
16 #include <sys/select.h>
17 #include <sys/socket.h>
18 #include <sys/time.h>
19 #include "system_func_mock.h"
20 #include "address_utils.h"
21 #include "dhcp_define.h"
22 #include "dhcp_logger.h"
23 #include "dhcp_message.h"
24 #include "dhcp_message_sim.h"
25 #include "dhcp_option.h"
26 #include "securec.h"
27
28 DEFINE_DHCPLOG_DHCP_LABEL("DhcpServerSystemFuncMock");
29
30 using namespace OHOS::DHCP;
31
32 #define MAGIC_COOKIE_LENGTH 4
33 #define OPT_HEADER_LENGTH 2
34 #define TIME_SEC_TO_USEC (1000 * 1000)
35
36 static bool g_mockTag = false;
37 static int TIME_MSEC_TO_USEC = 1000;
GetInstance()38 SystemFuncMock &SystemFuncMock::GetInstance()
39 {
40 static SystemFuncMock gSystemFuncMock;
41 return gSystemFuncMock;
42 };
43
SystemFuncMock()44 SystemFuncMock::SystemFuncMock() {}
45
~SystemFuncMock()46 SystemFuncMock::~SystemFuncMock() {}
47
SetMockFlag(bool flag)48 void SystemFuncMock::SetMockFlag(bool flag)
49 {
50 g_mockTag = flag;
51 }
52
GetMockFlag(void)53 bool SystemFuncMock::GetMockFlag(void)
54 {
55 return g_mockTag;
56 }
57
58 extern "C" {
59 int __real_open(const char *__file, int __oflag);
__wrap_open(const char * __file,int __oflag)60 int __wrap_open(const char *__file, int __oflag)
61 {
62 if (g_mockTag) {
63 return SystemFuncMock::GetInstance().open(__file, __oflag);
64 } else {
65 return __real_open(__file, __oflag);
66 }
67 }
68
69 ssize_t __real_write(int fd, const void *buf, size_t count);
__wrap_write(int fd,const void * buf,size_t count)70 ssize_t __wrap_write(int fd, const void *buf, size_t count)
71 {
72 if (g_mockTag) {
73 return SystemFuncMock::GetInstance().write(fd, buf, count);
74 } else {
75 return __real_write(fd, buf, count);
76 }
77 }
78
79 ssize_t __real_read(int fd, void *buf, size_t count);
__wrap_read(int fd,void * buf,size_t count)80 ssize_t __wrap_read(int fd, void *buf, size_t count)
81 {
82 if (g_mockTag) {
83 return SystemFuncMock::GetInstance().read(fd, buf, count);
84 } else {
85 return __real_read(fd, buf, count);
86 }
87 }
88
89 int __real_socket(int __domain, int __type, int __protocol);
__wrap_socket(int __domain,int __type,int __protocol)90 int __wrap_socket(int __domain, int __type, int __protocol)
91 {
92 DHCP_LOGD("==>socket.");
93 if (g_mockTag) {
94 DHCP_LOGD(" ==>mock enable.");
95 return SystemFuncMock::GetInstance().socket(__domain, __type, __protocol);
96 } else {
97 DHCP_LOGD(" ==>mock disable.");
98 }
99 return __real_socket(__domain, __type, __protocol);
100 }
101
102 int __real_setsockopt(int __fd, int __level, int __optname, const void *__optval, socklen_t __optlen);
__wrap_setsockopt(int __fd,int __level,int __optname,const void * __optval,socklen_t __optlen)103 int __wrap_setsockopt(int __fd, int __level, int __optname, const void *__optval, socklen_t __optlen)
104 {
105 DHCP_LOGD("==>setsockopt.");
106 if (g_mockTag) {
107 DHCP_LOGD(" ==>mock enable.");
108 return SystemFuncMock::GetInstance().setsockopt(__fd, __level, __optname, __optval, __optlen);
109 } else {
110 DHCP_LOGD(" ==>mock disable.");
111 }
112 return __real_setsockopt(__fd, __level, __optname, __optval, __optlen);
113 }
114
115 int __real_select(int __nfds, fd_set *__readfds, fd_set *__writefds, fd_set *__exceptfds, struct timeval *__timeout);
__wrap_select(int __nfds,fd_set * __readfds,fd_set * __writefds,fd_set * __exceptfds,struct timeval * __timeout)116 int __wrap_select(int __nfds, fd_set *__readfds, fd_set *__writefds, fd_set *__exceptfds, struct timeval *__timeout)
117 {
118 const unsigned int SLEEP_TIEM = 300000;
119 DHCP_LOGD("==>select.");
120 if (g_mockTag) {
121 DHCP_LOGD(" ==>mock enable.");
122 DHCP_LOGD("message queue total: %d.", DhcpMsgManager::GetInstance().SendTotal());
123 if (DhcpMsgManager::GetInstance().SendTotal() > 0) {
124 FD_CLR(__nfds, __readfds);
125 usleep(SLEEP_TIEM);
126 return 1;
127 }
128 int retval = SystemFuncMock::GetInstance().select(__nfds, __readfds, __writefds, __exceptfds, __timeout);
129 if (retval == 0) {
130 if (__timeout != nullptr) {
131 usleep(DHCP_SEL_WAIT_TIMEOUTS * TIME_MSEC_TO_USEC);
132 DHCP_LOGD("select time out.");
133 }
134 }
135 return retval;
136 } else {
137 DHCP_LOGD(" ==>mock disable.");
138 }
139 return __real_select(__nfds, __readfds, __writefds, __exceptfds, __timeout);
140 }
141
142 int __real_ioctl(int __fd, unsigned long __request, struct sockaddr *__ifreq);
__wrap_ioctl(int __fd,unsigned long __request,struct sockaddr * __ifreq)143 int __wrap_ioctl(int __fd, unsigned long __request, struct sockaddr *__ifreq)
144 {
145 if (g_mockTag) {
146 return SystemFuncMock::GetInstance().ioctl(__fd, __request, __ifreq);
147 } else {
148 return __real_ioctl(__fd, __request, __ifreq);
149 }
150 }
151
152 int __real_listen(int __fd, int __n);
__wrap_listen(int __fd,int __n)153 int __wrap_listen(int __fd, int __n)
154 {
155 if (g_mockTag) {
156 return SystemFuncMock::GetInstance().listen(__fd, __n);
157 } else {
158 return __real_listen(__fd, __n);
159 }
160 }
161
162 int __real_connect(int __fd, const struct sockaddr *__addr, socklen_t __len);
__wrap_connect(int __fd,const struct sockaddr * __addr,socklen_t __len)163 int __wrap_connect(int __fd, const struct sockaddr *__addr, socklen_t __len)
164 {
165 if (g_mockTag) {
166 return SystemFuncMock::GetInstance().connect(__fd, __addr, __len);
167 } else {
168 return __real_connect(__fd, __addr, __len);
169 }
170 }
171
172 pid_t __real_vfork();
__wrap_vfork()173 pid_t __wrap_vfork()
174 {
175 if (g_mockTag) {
176 return SystemFuncMock::GetInstance().vfork();
177 } else {
178 return __real_vfork();
179 }
180 }
181
182 int __real_execv(const char *__path, char *const *__argv);
__wrap_execv(const char * __path,char * const * __argv)183 int __wrap_execv(const char *__path, char *const *__argv)
184 {
185 if (g_mockTag) {
186 return SystemFuncMock::GetInstance().execv(__path, __argv);
187 } else {
188 return __real_execv(__path, __argv);
189 }
190 }
191
192 void __real__exit(int status);
__wrap__exit(int status)193 void __wrap__exit(int status)
194 {
195 if (g_mockTag) {
196 SystemFuncMock::GetInstance()._exit(status);
197 } else {
198 __real__exit(status);
199 }
200 return;
201 }
202
203 pid_t __real_waitpid(pid_t pid, int *status, int options);
__wrap_waitpid(pid_t pid,int * status,int options)204 pid_t __wrap_waitpid(pid_t pid, int *status, int options)
205 {
206 if (g_mockTag) {
207 return SystemFuncMock::GetInstance().waitpid(pid, status, options);
208 } else {
209 return __real_waitpid(pid, status, options);
210 }
211 }
212
213 int __real_kill(pid_t pid, int sig);
__wrap_kill(pid_t pid,int sig)214 int __wrap_kill(pid_t pid, int sig)
215 {
216 if (g_mockTag) {
217 return SystemFuncMock::GetInstance().kill(pid, sig);
218 } else {
219 return __real_kill(pid, sig);
220 }
221 }
222
223 int __real_bind(int __fd, struct sockaddr *__addr, socklen_t __len);
__wrap_bind(int __fd,struct sockaddr * __addr,socklen_t __len)224 int __wrap_bind(int __fd, struct sockaddr *__addr, socklen_t __len)
225 {
226 DHCP_LOGD("==>bind.");
227 if (g_mockTag) {
228 DHCP_LOGD(" ==>mock enable.");
229 return SystemFuncMock::GetInstance().bind(__fd, __addr, __len);
230 } else {
231 DHCP_LOGD(" ==>mock disable.");
232 }
233 return __real_bind(__fd, __addr, __len);
234 }
235
236 int __real_close(int _fileno);
__wrap_close(int _fileno)237 int __wrap_close(int _fileno)
238 {
239 DHCP_LOGD("==>close.");
240 if (g_mockTag) {
241 DHCP_LOGD(" ==>mock enable.");
242 return SystemFuncMock::GetInstance().close(_fileno);
243 } else {
244 DHCP_LOGD(" ==>mock disable.");
245 }
246 return __real_close(_fileno);
247 }
248
recvfrom(int __fd,void * __buf,size_t __n,int __flags,struct sockaddr * __addr,socklen_t * __addr_len)249 ssize_t recvfrom(int __fd, void *__buf, size_t __n, int __flags, struct sockaddr *__addr, socklen_t *__addr_len)
250 {
251 DHCP_LOGD("==>recvfrom.");
252 if (!g_mockTag) {
253 DHCP_LOGD(" ==>mock disable.");
254 return SystemFuncMock::GetInstance().recvfrom(__fd, __buf, __n, __flags, __addr, __addr_len);
255 }
256 DHCP_LOGD(" ==>mock enable.");
257 if (DhcpMsgManager::GetInstance().SendTotal() > 0 && __buf) {
258 DHCP_LOGD("== new message received.");
259 DhcpMessage msg = { 0 };
260 if (DhcpMsgManager::GetInstance().FrontSendMsg(&msg)) {
261 (void)memcpy_s(__buf, __n, &msg, sizeof(DhcpMessage));
262 DhcpMsgManager::GetInstance().PopSendMsg();
263 uint32_t srcIp = DhcpMsgManager::GetInstance().GetClientIp();
264 if (__addr != nullptr && srcIp != 0) {
265 struct sockaddr_in *sAddr = reinterpret_cast<sockaddr_in *>(__addr);
266 sAddr->sin_addr.s_addr = HostToNetwork(srcIp);
267 DhcpMsgManager::GetInstance().SetClientIp(0);
268 }
269 return sizeof(DhcpMessage);
270 }
271 }
272 return SystemFuncMock::GetInstance().recvfrom(__fd, __buf, __n, __flags, __addr, __addr_len);
273 }
274
ParseMockOptions(DhcpMessage * packet)275 int ParseMockOptions(DhcpMessage *packet)
276 {
277 if (packet == nullptr) {
278 DHCP_LOGD("dhcp message pointer is null.");
279 return RET_FAILED;
280 }
281 DhcpMsgInfo reply;
282 if (memset_s(&reply, sizeof(DhcpMsgInfo), 0, sizeof(DhcpMsgInfo)) != EOK) {
283 DHCP_LOGD("failed to reset dhcp message info.");
284 return RET_FAILED;
285 }
286 int retval = RET_FAILED;
287 if (memcpy_s(&reply.packet, sizeof(reply.packet), packet, sizeof(DhcpMessage)) != EOK) {
288 DHCP_LOGD("failed to fill dhcp message.");
289 return RET_FAILED;
290 }
291 reply.length = sizeof(DhcpMessage);
292 if (InitOptionList(&reply.options) != RET_SUCCESS) {
293 DHCP_LOGD("failed to init dhcp option list.");
294 return retval;
295 }
296 FreeOptionList(&reply.options);
297 return retval;
298 }
299
sendto(int __fd,const void * __buf,size_t __n,int __flags,const struct sockaddr * __addr,socklen_t __addr_len)300 ssize_t sendto(int __fd, const void *__buf,
301 size_t __n, int __flags, const struct sockaddr *__addr, socklen_t __addr_len)
302 {
303 DHCP_LOGD("==>sendto.");
304 if (g_mockTag) {
305 DHCP_LOGD(" ==>mock enable.");
306 if (__buf == nullptr) {
307 return SystemFuncMock::GetInstance().sendto(__fd, __buf, __n, __flags, __addr, __addr_len);
308 }
309 } else {
310 DHCP_LOGD(" ==>mock disable.");
311 }
312 return SystemFuncMock::GetInstance().sendto(__fd, __buf, __n, __flags, __addr, __addr_len);
313 }
314 }