• 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/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