• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 }