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