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_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 using namespace OHOS::Wifi;
29
30 #define MAGIC_COOKIE_LENGTH 4
31 #define OPT_HEADER_LENGTH 2
32 #define TIME_SEC_TO_USEC (1000 * 1000)
33
34 #undef LOG_TAG
35 #define LOG_TAG "DhcpServerSystemFuncMock"
36
37 static bool g_mockTag = false;
38 static int TIME_MSEC_TO_USEC = 1000;
GetInstance()39 SystemFuncMock &SystemFuncMock::GetInstance()
40 {
41 static SystemFuncMock gSystemFuncMock;
42 return gSystemFuncMock;
43 };
44
SystemFuncMock()45 SystemFuncMock::SystemFuncMock() {}
46
~SystemFuncMock()47 SystemFuncMock::~SystemFuncMock() {}
48
SetMockFlag(bool flag)49 void SystemFuncMock::SetMockFlag(bool flag)
50 {
51 g_mockTag = flag;
52 }
53
GetMockFlag(void)54 bool SystemFuncMock::GetMockFlag(void)
55 {
56 return g_mockTag;
57 }
58
59 extern "C" {
60 struct in_addr {
61 uint32_t s_addr;
62 };
63
64 struct sockaddr_in {
65 short int sin_family;
66 unsigned short int sin_port;
67 struct in_addr sin_addr;
68 unsigned char sin_zero[8];
69 };
70
71 int __real_socket(int __domain, int __type, int __protocol);
__wrap_socket(int __domain,int __type,int __protocol)72 int __wrap_socket(int __domain, int __type, int __protocol)
73 {
74 LOGD("==>socket.");
75 if (g_mockTag) {
76 LOGD(" ==>mock enable.");
77 return SystemFuncMock::GetInstance().socket(__domain, __type, __protocol);
78 } else {
79 LOGD(" ==>mock disable.");
80 }
81 return __real_socket(__domain, __type, __protocol);
82 }
83
84 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)85 int __wrap_setsockopt(int __fd, int __level, int __optname, const void *__optval, socklen_t __optlen)
86 {
87 LOGD("==>setsockopt.");
88 if (g_mockTag) {
89 LOGD(" ==>mock enable.");
90 return SystemFuncMock::GetInstance().setsockopt(__fd, __level, __optname, __optval, __optlen);
91 } else {
92 LOGD(" ==>mock disable.");
93 }
94 return __real_setsockopt(__fd, __level, __optname, __optval, __optlen);
95 }
96
97 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)98 int __wrap_select(int __nfds, fd_set *__readfds, fd_set *__writefds, fd_set *__exceptfds, struct timeval *__timeout)
99 {
100 const unsigned int SLEEP_TIEM = 300000;
101 LOGD("==>select.");
102 if (g_mockTag) {
103 LOGD(" ==>mock enable.");
104 LOGD("message queue total: %d.", DhcpMsgManager::GetInstance().SendTotal());
105 if (DhcpMsgManager::GetInstance().SendTotal() > 0) {
106 FD_CLR(__nfds, __readfds);
107 usleep(SLEEP_TIEM);
108 return 1;
109 }
110 int retval = SystemFuncMock::GetInstance().select(__nfds, __readfds, __writefds, __exceptfds, __timeout);
111 if (retval == 0) {
112 if (__timeout != nullptr) {
113 usleep(DHCP_SEL_WAIT_TIMEOUTS * TIME_MSEC_TO_USEC);
114 LOGD("select time out.");
115 }
116 }
117 return retval;
118 } else {
119 LOGD(" ==>mock disable.");
120 }
121 return __real_select(__nfds, __readfds, __writefds, __exceptfds, __timeout);
122 }
123
124 int __real_bind(int __fd, struct sockaddr *__addr, socklen_t __len);
__wrap_bind(int __fd,struct sockaddr * __addr,socklen_t __len)125 int __wrap_bind(int __fd, struct sockaddr *__addr, socklen_t __len)
126 {
127 LOGD("==>bind.");
128 if (g_mockTag) {
129 LOGD(" ==>mock enable.");
130 return SystemFuncMock::GetInstance().bind(__fd, __addr, __len);
131 } else {
132 LOGD(" ==>mock disable.");
133 }
134 return __real_bind(__fd, __addr, __len);
135 }
136
137 int __real_close(int _fileno);
__wrap_close(int _fileno)138 int __wrap_close(int _fileno)
139 {
140 LOGD("==>close.");
141 if (g_mockTag) {
142 LOGD(" ==>mock enable.");
143 return SystemFuncMock::GetInstance().close(_fileno);
144 } else {
145 LOGD(" ==>mock disable.");
146 }
147 return __real_close(_fileno);
148 }
149
recvfrom(int __fd,void * __buf,size_t __n,int __flags,struct sockaddr * __addr,socklen_t * __addr_len)150 ssize_t recvfrom(int __fd, void *__buf, size_t __n, int __flags, struct sockaddr *__addr, socklen_t *__addr_len)
151 {
152 LOGD("==>recvfrom.");
153 if (!g_mockTag) {
154 LOGD(" ==>mock disable.");
155 return SystemFuncMock::GetInstance().recvfrom(__fd, __buf, __n, __flags, __addr, __addr_len);
156 }
157 LOGD(" ==>mock enable.");
158 if (DhcpMsgManager::GetInstance().SendTotal() > 0 && __buf) {
159 LOGD("== new message received.");
160 DhcpMessage msg = { 0 };
161 if (DhcpMsgManager::GetInstance().FrontSendMsg(&msg)) {
162 (void)memcpy_s(__buf, __n, &msg, sizeof(DhcpMessage));
163 DhcpMsgManager::GetInstance().PopSendMsg();
164 uint32_t srcIp = DhcpMsgManager::GetInstance().GetClientIp();
165 if (__addr != nullptr && srcIp != 0) {
166 struct sockaddr_in *sAddr = reinterpret_cast<sockaddr_in *>(__addr);
167 sAddr->sin_addr.s_addr = HostToNetwork(srcIp);
168 DhcpMsgManager::GetInstance().SetClientIp(0);
169 }
170 return sizeof(DhcpMessage);
171 }
172 }
173 return SystemFuncMock::GetInstance().recvfrom(__fd, __buf, __n, __flags, __addr, __addr_len);
174 }
175
ParseMockOptions(DhcpMessage * packet)176 int ParseMockOptions(DhcpMessage *packet)
177 {
178 if (packet == nullptr) {
179 LOGD("dhcp message pointer is null.");
180 return RET_FAILED;
181 }
182 DhcpMsgInfo reply;
183 if (memset_s(&reply, sizeof(DhcpMsgInfo), 0, sizeof(DhcpMsgInfo)) != EOK) {
184 LOGD("failed to reset dhcp message info.");
185 return RET_FAILED;
186 }
187 int retval = RET_FAILED;
188 if (memcpy_s(&reply.packet, sizeof(reply.packet), packet, sizeof(DhcpMessage)) != EOK) {
189 LOGD("failed to fill dhcp message.");
190 return RET_FAILED;
191 }
192 reply.length = sizeof(DhcpMessage);
193 if (InitOptionList(&reply.options) != RET_SUCCESS) {
194 LOGD("failed to init dhcp option list.");
195 return retval;
196 }
197 FreeOptionList(&reply.options);
198 return retval;
199 }
200
sendto(int __fd,const void * __buf,size_t __n,int __flags,struct sockaddr * __addr,socklen_t __addr_len)201 ssize_t sendto(int __fd, const void *__buf, size_t __n, int __flags, struct sockaddr *__addr, socklen_t __addr_len)
202 {
203 LOGD("==>sendto.");
204 if (g_mockTag) {
205 LOGD(" ==>mock enable.");
206 if (__buf == nullptr) {
207 return SystemFuncMock::GetInstance().sendto(__fd, __buf, __n, __flags, __addr, __addr_len);
208 }
209 } else {
210 LOGD(" ==>mock disable.");
211 }
212 return SystemFuncMock::GetInstance().sendto(__fd, __buf, __n, __flags, __addr, __addr_len);
213 }
214 }
215