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/time.h>
18 #include "system_func_mock.h"
19 #include "address_utils.h"
20 #include "dhcp_define.h"
21 #include "dhcp_server_ipv4.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 struct in_addr {
60 uint32_t s_addr;
61 };
62
63 struct sockaddr_in {
64 short int sin_family;
65 unsigned short int sin_port;
66 struct in_addr sin_addr;
67 unsigned char sin_zero[8];
68 };
69
70 int __real_open(const char *__file, int __oflag);
__wrap_open(const char * __file,int __oflag)71 int __wrap_open(const char *__file, int __oflag)
72 {
73 if (g_mockTag) {
74 return SystemFuncMock::GetInstance().open(__file, __oflag);
75 } else {
76 return __real_open(__file, __oflag);
77 }
78 }
79
80 ssize_t __real_write(int fd, const void *buf, size_t count);
__wrap_write(int fd,const void * buf,size_t count)81 ssize_t __wrap_write(int fd, const void *buf, size_t count)
82 {
83 if (g_mockTag) {
84 return SystemFuncMock::GetInstance().write(fd, buf, count);
85 } else {
86 return __real_write(fd, buf, count);
87 }
88 }
89
90 ssize_t __real_read(int fd, void *buf, size_t count);
__wrap_read(int fd,void * buf,size_t count)91 ssize_t __wrap_read(int fd, void *buf, size_t count)
92 {
93 if (g_mockTag) {
94 return SystemFuncMock::GetInstance().read(fd, buf, count);
95 } else {
96 return __real_read(fd, buf, count);
97 }
98 }
99
100 int __real_socket(int __domain, int __type, int __protocol);
__wrap_socket(int __domain,int __type,int __protocol)101 int __wrap_socket(int __domain, int __type, int __protocol)
102 {
103 DHCP_LOGD("==>socket.");
104 if (g_mockTag) {
105 DHCP_LOGD(" ==>mock enable.");
106 return SystemFuncMock::GetInstance().socket(__domain, __type, __protocol);
107 } else {
108 DHCP_LOGD(" ==>mock disable.");
109 }
110 return __real_socket(__domain, __type, __protocol);
111 }
112
113 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)114 int __wrap_setsockopt(int __fd, int __level, int __optname, const void *__optval, socklen_t __optlen)
115 {
116 DHCP_LOGD("==>setsockopt.");
117 if (g_mockTag) {
118 DHCP_LOGD(" ==>mock enable.");
119 return SystemFuncMock::GetInstance().setsockopt(__fd, __level, __optname, __optval, __optlen);
120 } else {
121 DHCP_LOGD(" ==>mock disable.");
122 }
123 return __real_setsockopt(__fd, __level, __optname, __optval, __optlen);
124 }
125
126 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)127 int __wrap_select(int __nfds, fd_set *__readfds, fd_set *__writefds, fd_set *__exceptfds, struct timeval *__timeout)
128 {
129 const unsigned int SLEEP_TIEM = 300000;
130 DHCP_LOGD("==>select.");
131 if (g_mockTag) {
132 DHCP_LOGD(" ==>mock enable.");
133 DHCP_LOGD("message queue total: %d.", DhcpMsgManager::GetInstance().SendTotal());
134 if (DhcpMsgManager::GetInstance().SendTotal() > 0) {
135 FD_CLR(__nfds, __readfds);
136 usleep(SLEEP_TIEM);
137 return 1;
138 }
139 int retval = SystemFuncMock::GetInstance().select(__nfds, __readfds, __writefds, __exceptfds, __timeout);
140 if (retval == 0) {
141 if (__timeout != nullptr) {
142 usleep(DHCP_SEL_WAIT_TIMEOUTS * TIME_MSEC_TO_USEC);
143 DHCP_LOGD("select time out.");
144 }
145 }
146 return retval;
147 } else {
148 DHCP_LOGD(" ==>mock disable.");
149 }
150 return __real_select(__nfds, __readfds, __writefds, __exceptfds, __timeout);
151 }
152
153 int __real_ioctl(int __fd, unsigned long __request, struct sockaddr *__ifreq);
__wrap_ioctl(int __fd,unsigned long __request,struct sockaddr * __ifreq)154 int __wrap_ioctl(int __fd, unsigned long __request, struct sockaddr *__ifreq)
155 {
156 if (g_mockTag) {
157 return SystemFuncMock::GetInstance().ioctl(__fd, __request, __ifreq);
158 } else {
159 return __real_ioctl(__fd, __request, __ifreq);
160 }
161 }
162
163 int __real_listen(int __fd, int __n);
__wrap_listen(int __fd,int __n)164 int __wrap_listen(int __fd, int __n)
165 {
166 if (g_mockTag) {
167 return SystemFuncMock::GetInstance().listen(__fd, __n);
168 } else {
169 return __real_listen(__fd, __n);
170 }
171 }
172
173 int __real_connect(int __fd, const struct sockaddr *__addr, socklen_t __len);
__wrap_connect(int __fd,const struct sockaddr * __addr,socklen_t __len)174 int __wrap_connect(int __fd, const struct sockaddr *__addr, socklen_t __len)
175 {
176 if (g_mockTag) {
177 return SystemFuncMock::GetInstance().connect(__fd, __addr, __len);
178 } else {
179 return __real_connect(__fd, __addr, __len);
180 }
181 }
182
183 pid_t __real_vfork();
__wrap_vfork()184 pid_t __wrap_vfork()
185 {
186 if (g_mockTag) {
187 return SystemFuncMock::GetInstance().vfork();
188 } else {
189 return __real_vfork();
190 }
191 }
192
193 int __real_execv(const char *__path, char *const *__argv);
__wrap_execv(const char * __path,char * const * __argv)194 int __wrap_execv(const char *__path, char *const *__argv)
195 {
196 if (g_mockTag) {
197 return SystemFuncMock::GetInstance().execv(__path, __argv);
198 } else {
199 return __real_execv(__path, __argv);
200 }
201 }
202
203 void __real__exit(int status);
__wrap__exit(int status)204 void __wrap__exit(int status)
205 {
206 if (g_mockTag) {
207 SystemFuncMock::GetInstance()._exit(status);
208 } else {
209 __real__exit(status);
210 }
211 return;
212 }
213
214 pid_t __real_waitpid(pid_t pid, int *status, int options);
__wrap_waitpid(pid_t pid,int * status,int options)215 pid_t __wrap_waitpid(pid_t pid, int *status, int options)
216 {
217 if (g_mockTag) {
218 return SystemFuncMock::GetInstance().waitpid(pid, status, options);
219 } else {
220 return __real_waitpid(pid, status, options);
221 }
222 }
223
224 int __real_kill(pid_t pid, int sig);
__wrap_kill(pid_t pid,int sig)225 int __wrap_kill(pid_t pid, int sig)
226 {
227 if (g_mockTag) {
228 return SystemFuncMock::GetInstance().kill(pid, sig);
229 } else {
230 return __real_kill(pid, sig);
231 }
232 }
233
234 int __real_bind(int __fd, struct sockaddr *__addr, socklen_t __len);
__wrap_bind(int __fd,struct sockaddr * __addr,socklen_t __len)235 int __wrap_bind(int __fd, struct sockaddr *__addr, socklen_t __len)
236 {
237 DHCP_LOGD("==>bind.");
238 if (g_mockTag) {
239 DHCP_LOGD(" ==>mock enable.");
240 return SystemFuncMock::GetInstance().bind(__fd, __addr, __len);
241 } else {
242 DHCP_LOGD(" ==>mock disable.");
243 }
244 return __real_bind(__fd, __addr, __len);
245 }
246
247 int __real_close(int _fileno);
__wrap_close(int _fileno)248 int __wrap_close(int _fileno)
249 {
250 DHCP_LOGD("==>close.");
251 if (g_mockTag) {
252 DHCP_LOGD(" ==>mock enable.");
253 return SystemFuncMock::GetInstance().close(_fileno);
254 } else {
255 DHCP_LOGD(" ==>mock disable.");
256 }
257 return __real_close(_fileno);
258 }
259
recvfrom(int __fd,void * __buf,size_t __n,int __flags,struct sockaddr * __addr,socklen_t * __addr_len)260 ssize_t recvfrom(int __fd, void *__buf, size_t __n, int __flags, struct sockaddr *__addr, socklen_t *__addr_len)
261 {
262 DHCP_LOGD("==>recvfrom.");
263 if (!g_mockTag) {
264 DHCP_LOGD(" ==>mock disable.");
265 return SystemFuncMock::GetInstance().recvfrom(__fd, __buf, __n, __flags, __addr, __addr_len);
266 }
267 DHCP_LOGD(" ==>mock enable.");
268 if (DhcpMsgManager::GetInstance().SendTotal() > 0 && __buf) {
269 DHCP_LOGD("== new message received.");
270 DhcpMessage msg = { 0 };
271 if (DhcpMsgManager::GetInstance().FrontSendMsg(&msg)) {
272 (void)memcpy_s(__buf, __n, &msg, sizeof(DhcpMessage));
273 DhcpMsgManager::GetInstance().PopSendMsg();
274 uint32_t srcIp = DhcpMsgManager::GetInstance().GetClientIp();
275 if (__addr != nullptr && srcIp != 0) {
276 struct sockaddr_in *sAddr = reinterpret_cast<sockaddr_in *>(__addr);
277 sAddr->sin_addr.s_addr = HostToNetwork(srcIp);
278 DhcpMsgManager::GetInstance().SetClientIp(0);
279 }
280 return sizeof(DhcpMessage);
281 }
282 }
283 return SystemFuncMock::GetInstance().recvfrom(__fd, __buf, __n, __flags, __addr, __addr_len);
284 }
285
ParseMockOptions(DhcpMessage * packet)286 int ParseMockOptions(DhcpMessage *packet)
287 {
288 if (packet == nullptr) {
289 DHCP_LOGD("dhcp message pointer is null.");
290 return RET_FAILED;
291 }
292 DhcpMsgInfo reply;
293 if (memset_s(&reply, sizeof(DhcpMsgInfo), 0, sizeof(DhcpMsgInfo)) != EOK) {
294 DHCP_LOGD("failed to reset dhcp message info.");
295 return RET_FAILED;
296 }
297 int retval = RET_FAILED;
298 if (memcpy_s(&reply.packet, sizeof(reply.packet), packet, sizeof(DhcpMessage)) != EOK) {
299 DHCP_LOGD("failed to fill dhcp message.");
300 return RET_FAILED;
301 }
302 reply.length = sizeof(DhcpMessage);
303 if (InitOptionList(&reply.options) != RET_SUCCESS) {
304 DHCP_LOGD("failed to init dhcp option list.");
305 return retval;
306 }
307 FreeOptionList(&reply.options);
308 return retval;
309 }
310
sendto(int __fd,const void * __buf,size_t __n,int __flags,struct sockaddr * __addr,socklen_t __addr_len)311 ssize_t sendto(int __fd, const void *__buf, size_t __n, int __flags, struct sockaddr *__addr, socklen_t __addr_len)
312 {
313 DHCP_LOGD("==>sendto.");
314 if (g_mockTag) {
315 DHCP_LOGD(" ==>mock enable.");
316 if (__buf == nullptr) {
317 return SystemFuncMock::GetInstance().sendto(__fd, __buf, __n, __flags, __addr, __addr_len);
318 }
319 } else {
320 DHCP_LOGD(" ==>mock disable.");
321 }
322 return SystemFuncMock::GetInstance().sendto(__fd, __buf, __n, __flags, __addr, __addr_len);
323 }
324 }
325