• 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 
16 #include <gtest/gtest.h>
17 #include <cstdint>
18 #include <cstdbool>
19 #include <cstdlib>
20 #include <cstdio>
21 #include <thread>
22 #include "dhcp_server.h"
23 #include "address_utils.h"
24 #include "dhcp_config.h"
25 #include "dhcp_option.h"
26 #include "dhcp_logger.h"
27 #include "system_func_mock.h"
28 #include "dhcp_message_sim.h"
29 #include "dhcp_ipv4.h"
30 #include "common_util.h"
31 #include "securec.h"
32 
33 using namespace testing::ext;
34 using namespace std;
35 using namespace OHOS::Wifi;
36 
37 #undef LOG_TAG
38 #define LOG_TAG "DhcpServerTest"
39 
40 struct ServerContext {
41     int broadCastFlagEnable;
42     DhcpAddressPool addressPool;
43     DhcpServerCallback callback;
44     DhcpConfig config;
45     int serverFd;
46     int looperState;
47     int initialized;
48 };
49 
50 namespace OHOS {
51 namespace Wifi {
52 constexpr int SERVER_RUNING_TIME = 10; // the value is in units of seconds.
53 
54 class DhcpServerTest : public testing::Test {
55 public:
SetUpTestCase()56     static void SetUpTestCase()
57     {}
TearDownTestCase()58     static void TearDownTestCase()
59     {}
SetUp()60     virtual void SetUp()
61     {}
TearDown()62     virtual void TearDown()
63     {
64         SystemFuncMock::GetInstance().SetMockFlag(false);
65     }
66 
67     int InitServerConfig(DhcpConfig *config);
68     int FreeServerConfig(DhcpConfig *config);
69     int TestDhcpRequest(uint32_t testIp, uint32_t srvId);
70     int TestDhcpRequestByMac(uint32_t testIp, uint32_t srvId, uint8_t *macAddr);
71     int TestDhcpRelease(uint32_t testIp, uint32_t srvId);
72     int InitDhcpRequests();
73     int InitDhcpErrorRequests();
74     bool InitBindingRecodersTest();
75     bool FixedOptionsTest();
76     int InitDhcpClient();
77     bool ServerRun(void);
78     bool StartServerTest();
79     void DelayStopServer();
80     int InitClientIp(void);
81 
82 private:
83     DhcpServerContext *m_pServerCtx = nullptr;
84     DhcpConfig m_serverConfg;
85     thread delayStopTh;
86 
87     DhcpClientContext *m_pMockClient = nullptr;
88     DhcpClientConfig m_clientConfg;
89 };
90 
InitServerConfig(DhcpConfig * config)91 int DhcpServerTest::InitServerConfig(DhcpConfig *config)
92 {
93     if (!config) {
94         return RET_FAILED;
95     }
96     const char* testIfaceName = "test_if0";
97     uint32_t serverId = ParseIpAddr("192.168.189.254");
98     uint32_t netmask = ParseIpAddr("255.255.255.0");
99     uint32_t beginIp = ParseIpAddr("192.168.189.100");
100     uint32_t endIp = ParseIpAddr("192.168.189.200");
101     if (serverId == 0 || netmask == 0 || beginIp == 0 || endIp == 0) {
102         printf("failed to parse address.\n");
103         return RET_FAILED;
104     }
105     if (memset_s(config, sizeof(DhcpConfig), 0, sizeof(DhcpConfig)) != EOK) {
106         return RET_FAILED;
107     }
108     if (memset_s(config->ifname, sizeof(config->ifname), '\0', sizeof(config->ifname)) != EOK) {
109         return RET_FAILED;
110     }
111     if (strncpy_s(config->ifname, sizeof(config->ifname), testIfaceName, strlen(testIfaceName)) != EOK) {
112         return RET_FAILED;
113     }
114     config->serverId = serverId;
115     config->netmask = netmask;
116     config->pool.beginAddress = beginIp;
117     config->pool.endAddress = endIp;
118     config->broadcast = 1;
119     if (InitOptionList(&config->options) != RET_SUCCESS) {
120         return RET_FAILED;
121     }
122     return RET_SUCCESS;
123 }
124 
125 extern "C" void InitBindingRecoders(DhcpAddressPool *pool);
InitBindingRecodersTest()126 bool DhcpServerTest::InitBindingRecodersTest()
127 {
128     if (!m_pServerCtx) {
129         return false;
130     }
131     ServerContext *srvIns = reinterpret_cast<ServerContext *>(m_pServerCtx->instance);
132 
133     AddressBinding bind = {0};
134     bind.bindingMode = BIND_MODE_DYNAMIC;
135     const uint8_t testMac1[DHCP_HWADDR_LENGTH] = {0x00, 0x0e, 0x3c, 0x65, 0x3a, 0x09, 0};
136     uint32_t testIp1 = ParseIpAddr("192.168.189.101");
137     bind.ipAddress = testIp1;
138     for (int i = 0; i < MAC_ADDR_LENGTH; ++i) {
139         bind.chaddr[i] = testMac1[i];
140     }
141     if (AddLease(&srvIns->addressPool, &bind) != RET_SUCCESS) {
142         LOGE("failed to add lease recoder.");
143         return false;
144     }
145 
146     const uint8_t testMac5[DHCP_HWADDR_LENGTH] =  {0x00, 0x0e, 0x3c, 0x65, 0x3a, 0x0e, 0};
147     uint32_t testIp5 = ParseIpAddr("192.168.189.130");
148     bind.ipAddress = testIp5;
149     bind.bindingMode = BIND_MODE_DYNAMIC;
150     for (int i = 0; i < MAC_ADDR_LENGTH; ++i) {
151         bind.chaddr[i] = testMac5[i];
152     }
153     bind.expireIn = Tmspsec();
154     bind.bindingTime = bind.expireIn  - DHCP_LEASE_TIME;
155     if (AddLease(&srvIns->addressPool, &bind) != RET_SUCCESS) {
156         return false;
157     }
158 
159     const uint8_t testMac6[DHCP_HWADDR_LENGTH] =  {0x00, 0xae, 0x3c, 0x65, 0x3a, 0x0e, 0};
160     uint32_t testIp6 = ParseIpAddr("192.168.189.118");
161     bind.ipAddress = testIp6;
162     bind.bindingMode = BIND_MODE_DYNAMIC;
163     for (int i = 0; i < MAC_ADDR_LENGTH; ++i) {
164         bind.chaddr[i] = testMac6[i];
165     }
166     bind.expireIn = Tmspsec();
167     bind.bindingTime = bind.expireIn  - DHCP_LEASE_TIME;
168     if (AddLease(&srvIns->addressPool, &bind) != RET_SUCCESS) {
169         return false;
170     }
171     srvIns->addressPool.leaseTime = DHCP_LEASE_TIME;
172     srvIns->addressPool.renewalTime = DHCP_RENEWAL_TIME;
173     InitBindingRecoders(nullptr);
174     DhcpAddressPool pool;
175     if (memset_s(&pool, sizeof(DhcpAddressPool), 0, sizeof(DhcpAddressPool)) != EOK) {
176         return false;
177     }
178     InitBindingRecoders(&pool);
179     InitBindingRecoders(&srvIns->addressPool);
180     return true;
181 }
182 
183 
FixedOptionsTest()184 bool DhcpServerTest::FixedOptionsTest()
185 {
186     const char *serverVendorId = "ohos-dhcp-server";
187     DhcpOption optVendorId = {VENDOR_CLASS_IDENTIFIER_OPTION, 0, {0}};
188     if (FillOption(&optVendorId, serverVendorId, strlen(serverVendorId)) != RET_SUCCESS) {
189         return false;
190     }
191     if (PushBackOption(&m_serverConfg.options, &optVendorId) != RET_SUCCESS) {
192         return false;
193     }
194     return true;
195 }
196 
TestServerCallback(int state,int code,const char * ifname)197 static int TestServerCallback(int state, int code, const char *ifname)
198 {
199     int ret = 0;
200     switch (state) {
201         case ST_STARTING: {
202             if (code == 0) {
203                 LOGD(" callback[%s] ==> server starting ...", ifname);
204             } else if (code == 1) {
205                 LOGD(" callback[%s] ==> server started.", ifname);
206             } else if (code == NUM_TWO) {
207                 LOGD(" callback[%s] ==> server start failed.", ifname);
208             }
209             break;
210         }
211         case ST_RELOADNG: {
212             LOGD(" callback[%s] ==> reloading ...", ifname);
213             break;
214         }
215         case ST_STOPED: {
216             LOGD(" callback[%s] ==> server stopped.", ifname);
217             break;
218         }
219         default:
220             break;
221     }
222     return ret;
223 }
224 
ServerRun(void)225 bool DhcpServerTest::ServerRun(void)
226 {
227     LOGD("begin test start dhcp server.");
228     int retval = true;
229     EXPECT_CALL(SystemFuncMock::GetInstance(), socket(_, _, _)).WillRepeatedly(Return(1));
230     EXPECT_CALL(SystemFuncMock::GetInstance(), setsockopt(_, _, _, _, _)).WillRepeatedly(Return(0));
231     EXPECT_CALL(SystemFuncMock::GetInstance(), select(_, _, _, _, _)).WillRepeatedly(Return(0));
232     EXPECT_CALL(SystemFuncMock::GetInstance(), bind(_, _, _)).WillRepeatedly(Return(0));
233     EXPECT_CALL(SystemFuncMock::GetInstance(), sendto(_, _, _, _, _, _)).WillRepeatedly(Return(sizeof(DhcpMessage)));
234     EXPECT_CALL(SystemFuncMock::GetInstance(), recvfrom(_, _, _, _, _, _)).WillRepeatedly(Return(0));
235     EXPECT_CALL(SystemFuncMock::GetInstance(), close(_)).WillRepeatedly(Return(0));
236 
237     m_pServerCtx = InitializeServer(&m_serverConfg);
238     if (!m_pServerCtx) {
239         LOGE("failed to initialized dhcp server context.");
240         retval = false;
241     }
242     if (!InitBindingRecodersTest()) {
243         LOGE("failed to initialize binding recoders.");
244         retval = false;
245     }
246     RegisterDhcpCallback(m_pServerCtx, TestServerCallback);
247     if (StartDhcpServer(nullptr) != RET_FAILED) {
248         LOGE("failed to start dhcp server. \n");
249         retval = false;
250     }
251     DhcpServerContext tempCtx;
252     memset_s(&tempCtx, sizeof(DhcpServerContext), 0, sizeof(DhcpServerContext));
253     memset_s(tempCtx.ifname, sizeof(tempCtx.ifname), '\0', sizeof(tempCtx.ifname));
254     if (StartDhcpServer(&tempCtx) != RET_FAILED) {
255         LOGE("failed to start dhcp server. \n");
256         retval = false;
257     }
258     strcpy_s(tempCtx.ifname, sizeof(tempCtx.ifname), "test_if1");
259     if (StartDhcpServer(&tempCtx) != RET_FAILED) {
260         LOGE("failed to start dhcp server. \n");
261         retval = false;
262     }
263     if (m_pServerCtx && StartDhcpServer(m_pServerCtx) != RET_SUCCESS) {
264         LOGE("failed to start dhcp server. \n");
265         retval = false;
266     }
267     if (SaveLease(m_pServerCtx) != RET_SUCCESS) {
268         retval = false;
269     }
270     if (m_pServerCtx) {
271         FreeServerContext(&m_pServerCtx);
272     }
273     return retval;
274 }
275 
StartServerTest()276 bool DhcpServerTest::StartServerTest()
277 {
278     bool retval = true;
279     LOGI("start dhcp server test...");
280     if (InitServerConfig(&m_serverConfg) != RET_SUCCESS) {
281         LOGE("failed to initialized dhcp server config.");
282         retval = false;
283     }
284     if (!FixedOptionsTest()) {
285         LOGE("failed to initialized fixed options.");
286         retval = false;
287     }
288     delayStopTh = std::thread(std::bind(&DhcpServerTest::DelayStopServer, this));
289     delayStopTh.detach();
290     if (InitDhcpClient() != RET_SUCCESS) {
291         retval = false;
292     }
293     LOGI("wait for test completed...");
294     retval = ServerRun();
295     return retval;
296 }
297 
DelayStopServer()298 void DhcpServerTest::DelayStopServer()
299 {
300     const int SLEEP_TIME = 3;
301     const int SLEEP_TIME1 = 1;
302     const int SLEEP_TIME2 = 1;
303     LOGI("wait for dhcp server stopped...");
304     LOGI("wait %d seconds...\n", SERVER_RUNING_TIME);
305     EXPECT_CALL(SystemFuncMock::GetInstance(), close(_)).WillRepeatedly(Return(0));
306     std::this_thread::sleep_for(std::chrono::seconds(SLEEP_TIME));
307     if (m_pServerCtx && m_pServerCtx->instance) {
308         ServerContext *srvIns = reinterpret_cast<ServerContext *>(m_pServerCtx->instance);
309         srvIns->looperState = SLEEP_TIME;
310     }
311     std::this_thread::sleep_for(std::chrono::seconds(SERVER_RUNING_TIME));
312     if (StopDhcpServer(m_pServerCtx) != RET_SUCCESS) {
313         LOGE("failed to stop dhcp server.");
314         return;
315     }
316     int waitSesc = 0;
317     while (waitSesc < SERVER_RUNING_TIME) {
318         if (GetServerStatus(m_pServerCtx) == ST_STOPED) {
319             LOGI("dhcp server stopped.");
320             break;
321         } else {
322             std::this_thread::sleep_for(std::chrono::seconds(SLEEP_TIME1));
323             waitSesc++;
324         }
325     }
326     std::this_thread::sleep_for(std::chrono::seconds(SLEEP_TIME2));
327 }
328 
TestDhcpRequest(uint32_t testIp,uint32_t srvId)329 int DhcpServerTest::TestDhcpRequest(uint32_t testIp, uint32_t srvId)
330 {
331     return TestDhcpRequestByMac(testIp, srvId, nullptr);
332 }
333 
TestDhcpRequestByMac(uint32_t testIp,uint32_t srvId,uint8_t * macAddr)334 int DhcpServerTest::TestDhcpRequestByMac(uint32_t testIp, uint32_t srvId, uint8_t *macAddr)
335 {
336     DhcpMsgInfo msgInfo = {{0}, 0, {0}};
337     InitOptionList(&msgInfo.options);
338     if (!InitMessage(m_pMockClient, &msgInfo, DHCPREQUEST)) {
339         LOGE("failed to init dhcp message.");
340         FreeOptionList(&msgInfo.options);
341         return RET_FAILED;
342     }
343     RemoveOption(&msgInfo.options, END_OPTION);
344     if (srvId != 0) {
345         DhcpOption optSrvId = {SERVER_IDENTIFIER_OPTION, 0, {0}};
346         AppendAddressOption(&optSrvId, srvId);
347         PushFrontOption(&msgInfo.options, &optSrvId);
348     }
349     DhcpOption optReqIp = {REQUESTED_IP_ADDRESS_OPTION, 0, {0}};
350     AppendAddressOption(&optReqIp, testIp);
351     PushBackOption(&msgInfo.options, &optReqIp);
352     DhcpOption endOpt = {END_OPTION, 0, {0}};
353     PushBackOption(&msgInfo.options, &endOpt);
354     msgInfo.packet.ciaddr = testIp;
355     if (macAddr != nullptr) {
356         if (!FillHwAddr(msgInfo.packet.chaddr, DHCP_HWADDR_LENGTH, macAddr, MAC_ADDR_LENGTH)) {
357             return DHCP_FALSE;
358         }
359     }
360     if (SendDhcpMessage(m_pMockClient, &msgInfo) != RET_SUCCESS) {
361         LOGE("failed to send dhcp message.");
362         FreeOptionList(&msgInfo.options);
363         return RET_FAILED;
364     }
365     FreeOptionList(&msgInfo.options);
366     return RET_SUCCESS;
367 }
368 
TestDhcpRelease(uint32_t testIp,uint32_t srvId)369 int DhcpServerTest::TestDhcpRelease(uint32_t testIp, uint32_t srvId)
370 {
371     DhcpMsgInfo msgInfo = {{0}, 0, {0}};
372     InitOptionList(&msgInfo.options);
373     if (!InitMessage(m_pMockClient, &msgInfo, DHCPRELEASE)) {
374         LOGE("failed to init dhcp message.");
375         FreeOptionList(&msgInfo.options);
376         return RET_FAILED;
377     }
378     RemoveOption(&msgInfo.options, END_OPTION);
379     if (srvId != 0) {
380         DhcpOption optSrvId = {SERVER_IDENTIFIER_OPTION, 0, {0}};
381         AppendAddressOption(&optSrvId, srvId);
382         PushBackOption(&msgInfo.options, &optSrvId);
383     }
384     DhcpOption optReqIp = {REQUESTED_IP_ADDRESS_OPTION, 0, {0}};
385     AppendAddressOption(&optReqIp, testIp);
386     PushBackOption(&msgInfo.options, &optReqIp);
387     msgInfo.packet.ciaddr = testIp;
388 
389     DhcpOption endOpt = {END_OPTION, 0, {0}};
390     PushBackOption(&msgInfo.options, &endOpt);
391     if (SendDhcpMessage(m_pMockClient, &msgInfo) != RET_SUCCESS) {
392         LOGE("failed to send dhcp message.");
393         FreeOptionList(&msgInfo.options);
394         return RET_FAILED;
395     }
396     FreeOptionList(&msgInfo.options);
397     return RET_SUCCESS;
398 }
399 
InitDhcpRequests()400 int DhcpServerTest::InitDhcpRequests()
401 {
402     uint32_t testIp = ParseIpAddr("192.168.189.101");
403     uint32_t srvId = ParseIpAddr("192.168.189.254");
404     DhcpMsgManager::GetInstance().SetClientIp(testIp);
405     if (DhcpRequest(m_pMockClient) != RET_SUCCESS) {
406         LOGE("[InitDhcpRequests] DhcpRequest failed");
407         return RET_FAILED;
408     }
409     DhcpMsgManager::GetInstance().SetClientIp(0);
410     if (TestDhcpRequest(testIp, srvId) != RET_SUCCESS) {
411         LOGE("[InitDhcpRequests] TestDhcpRequest1 failed");
412         return RET_FAILED;
413     }
414     testIp = ParseIpAddr("192.168.189.102");
415     if (TestDhcpRequest(testIp, 0) != RET_SUCCESS) {
416         return RET_FAILED;
417     }
418     testIp = ParseIpAddr("192.168.189.120");
419     uint8_t testMac1[DHCP_HWADDR_LENGTH] =  {0x00, 0x0e, 0x3c, 0x65, 0x3a, 0x0a, 0};
420     uint8_t testMac2[DHCP_HWADDR_LENGTH] =  {0x00, 0x0e, 0x3c, 0x65, 0x3a, 0x0b, 0};
421     uint8_t testMac3[DHCP_HWADDR_LENGTH] =  {0x00, 0x0e, 0x3c, 0x65, 0x3a, 0x0c, 0};
422     if (TestDhcpRequestByMac(testIp, srvId, testMac1) != RET_SUCCESS) {
423         return RET_FAILED;
424     }
425     DhcpMsgManager::GetInstance().SetClientIp(testIp);
426     if (TestDhcpRequest(testIp, srvId) != RET_SUCCESS) {
427         return RET_FAILED;
428     }
429     testIp = ParseIpAddr("192.168.189.101");
430     if (TestDhcpRequestByMac(testIp, srvId, testMac2) != RET_SUCCESS) {
431         return RET_FAILED;
432     }
433     testIp = ParseIpAddr("192.168.189.120");
434     DhcpMsgManager::GetInstance().SetClientIp(testIp);
435     if (TestDhcpRequestByMac(testIp, srvId, testMac3) != RET_SUCCESS) {
436         return RET_FAILED;
437     }
438     DhcpMsgManager::GetInstance().SetClientIp(0);
439     uint8_t testMac4[DHCP_HWADDR_LENGTH] =  {0x00, 0x0e, 0x3c, 0x65, 0x3a, 0x0d, 0};
440     testIp = ParseIpAddr("192.168.190.210");
441     if (TestDhcpRequestByMac(testIp, srvId, testMac4) != RET_SUCCESS) {
442         return RET_FAILED;
443     }
444     uint8_t testMac5[DHCP_HWADDR_LENGTH] =  {0x0a, 0x0e, 0x3c, 0x65, 0x3a, 0x0e, 0};
445     testIp = ParseIpAddr("192.168.189.130");
446     DhcpMsgManager::GetInstance().SetClientIp(testIp);
447     if (TestDhcpRequestByMac(testIp, srvId, testMac5) != RET_SUCCESS) {
448         return RET_FAILED;
449     }
450     DhcpMsgManager::GetInstance().SetClientIp(0);
451     return RET_SUCCESS;
452 }
453 
InitDhcpErrorRequests()454 int DhcpServerTest::InitDhcpErrorRequests()
455 {
456     uint32_t srvId = ParseIpAddr("192.168.100.254");
457     uint32_t testIp = ParseIpAddr("192.168.100.101");
458     DhcpMsgInfo msgInfo = {{0}, 0, {0}};
459     InitOptionList(&msgInfo.options);
460     if (!InitMessage(m_pMockClient, &msgInfo, DHCPREQUEST)) {
461         LOGE("failed to init dhcp message.");
462         FreeOptionList(&msgInfo.options);
463         return RET_FAILED;
464     }
465 
466     DhcpOption optReqIp = {REQUESTED_IP_ADDRESS_OPTION, 0, {0}};
467     AppendAddressOption(&optReqIp, testIp);
468     PushFrontOption(&msgInfo.options, &optReqIp);
469     DhcpOption optSrvId = {SERVER_IDENTIFIER_OPTION, 0, {0}};
470     AppendAddressOption(&optSrvId, srvId);
471     PushFrontOption(&msgInfo.options, &optSrvId);
472     if (SendDhcpMessage(m_pMockClient, &msgInfo) != RET_SUCCESS) {
473         LOGE("failed to send dhcp message.");
474         FreeOptionList(&msgInfo.options);
475         return RET_FAILED;
476     }
477 
478     RemoveOption(&msgInfo.options, DHCP_MESSAGE_TYPE_OPTION);
479     if (SendDhcpMessage(m_pMockClient, &msgInfo) != RET_SUCCESS) {
480         LOGE("failed to send dhcp message.");
481         FreeOptionList(&msgInfo.options);
482         return RET_FAILED;
483     }
484 
485     RemoveOption(&msgInfo.options, END_OPTION);
486     RemoveOption(&msgInfo.options, SERVER_IDENTIFIER_OPTION);
487     if (SendDhcpMessage(m_pMockClient, &msgInfo) != RET_SUCCESS) {
488         LOGE("failed to send dhcp message.");
489         FreeOptionList(&msgInfo.options);
490         return RET_FAILED;
491     }
492     return RET_SUCCESS;
493 }
494 
InitDhcpClient()495 int DhcpServerTest::InitDhcpClient()
496 {
497     uint8_t testMacAddr[DHCP_HWADDR_LENGTH] = {0x00, 0x0e, 0x3c, 0x65, 0x3a, 0x09, 0};
498 
499     LOGI("init mock dhcp client.");
500     const char* testIfname = "test_if0";
501 
502     if (memset_s(&m_clientConfg, sizeof(DhcpClientConfig), 0, sizeof(DhcpClientConfig)) != EOK) {
503         return RET_FAILED;
504     }
505     if (!FillHwAddr(m_clientConfg.chaddr, DHCP_HWADDR_LENGTH, testMacAddr, MAC_ADDR_LENGTH)) {
506         LOGE("FillHwAddr failed");
507         return RET_FAILED;
508     }
509     if (memset_s(m_clientConfg.ifname, IFACE_NAME_SIZE, '\0', IFACE_NAME_SIZE) != EOK) {
510         return RET_FAILED;
511     }
512     if (memcpy_s(m_clientConfg.ifname, IFACE_NAME_SIZE, testIfname, strlen(testIfname)) != EOK) {
513         return RET_FAILED;
514     }
515 
516     m_pMockClient = InitialDhcpClient(&m_clientConfg);
517     if (!m_pMockClient) {
518         LOGE("[InitDhcpClient] InitialDhcpClient failed");
519         return RET_FAILED;
520     }
521     if (DhcpDiscover(m_pMockClient) != RET_SUCCESS) {
522         LOGE("[InitDhcpClient] DhcpDiscover1 failed");
523         return RET_FAILED;
524     }
525     uint32_t testIp = ParseIpAddr("192.168.189.102");
526     uint32_t srvId = ParseIpAddr("192.168.189.254");
527     DhcpMsgManager::GetInstance().SetClientIp(testIp);
528     if (DhcpDiscover(m_pMockClient) != RET_SUCCESS) {
529         LOGE("[InitDhcpClient] DhcpDiscover2 failed");
530         return RET_FAILED;
531     }
532     InitDhcpRequests();
533     InitDhcpErrorRequests();
534     if (DhcpInform(m_pMockClient) != RET_SUCCESS) {
535         LOGE("[InitDhcpClient] DhcpInform1 failed");
536         return RET_FAILED;
537     }
538     if (InitClientIp() != RET_SUCCESS) {
539         return RET_FAILED;
540     }
541     testIp = ParseIpAddr("192.168.189.102");
542     if (TestDhcpRelease(testIp, srvId)) {
543         LOGE("[InitDhcpClient] TestDhcpRelease failed");
544         return RET_FAILED;
545     }
546     return RET_SUCCESS;
547 }
548 
InitClientIp(void)549 int DhcpServerTest::InitClientIp(void)
550 {
551     uint32_t testIp = ParseIpAddr("192.168.189.102");
552     DhcpMsgManager::GetInstance().SetClientIp(testIp);
553     if (DhcpInform(m_pMockClient) != RET_SUCCESS) {
554         LOGE("[InitDhcpClient] DhcpInform2 failed");
555         return RET_FAILED;
556     }
557     DhcpMsgManager::GetInstance().SetClientIp(0);
558     if (DhcpDecline(m_pMockClient) != RET_SUCCESS) {
559         LOGE("[InitDhcpClient] DhcpDecline1 failed");
560         return RET_FAILED;
561     }
562     testIp = ParseIpAddr("192.168.189.118");
563     DhcpMsgManager::GetInstance().SetClientIp(testIp);
564     if (DhcpDecline(m_pMockClient) != RET_SUCCESS) {
565         LOGE("[InitDhcpClient] DhcpDecline2 failed");
566         return RET_FAILED;
567     }
568     DhcpMsgManager::GetInstance().SetClientIp(0);
569     if (DhcpRelease(m_pMockClient) != RET_SUCCESS) {
570         LOGE("[InitDhcpClient] DhcpRelease failed");
571         return RET_FAILED;
572     }
573     return RET_SUCCESS;
574 }
575 
FreeServerConfig(DhcpConfig * config)576 int DhcpServerTest::FreeServerConfig(DhcpConfig *config)
577 {
578     if (!config) {
579         return RET_FAILED;
580     }
581     FreeOptionList(&config->options);
582     return RET_SUCCESS;
583 }
584 
585 HWTEST_F(DhcpServerTest, InitializeServerTest, TestSize.Level1)
586 {
587     SystemFuncMock::GetInstance().SetMockFlag(true);
588     EXPECT_CALL(SystemFuncMock::GetInstance(), socket(_, _, _)).WillRepeatedly(Return(1));
589     EXPECT_CALL(SystemFuncMock::GetInstance(), setsockopt(_, _, _, _, _)).WillRepeatedly(Return(0));
590     EXPECT_CALL(SystemFuncMock::GetInstance(), select(_, _, _, _, _)).WillRepeatedly(Return(0));
591     EXPECT_CALL(SystemFuncMock::GetInstance(), recvfrom(_, _, _, _, _, _)).WillRepeatedly(Return(0));
592     EXPECT_CALL(SystemFuncMock::GetInstance(), bind(_, _, _)).WillRepeatedly(Return(0));
593     EXPECT_CALL(SystemFuncMock::GetInstance(), close(_)).WillRepeatedly(Return(0));
594     DhcpConfig config;
595     PDhcpServerContext ctx = InitializeServer(nullptr);
596     EXPECT_TRUE(ctx == nullptr);
597     ASSERT_TRUE(memset_s(&config, sizeof(DhcpConfig), 0, sizeof(DhcpConfig)) == EOK);
598     ctx = InitializeServer(&config);
599     EXPECT_TRUE(ctx == nullptr);
600     EXPECT_TRUE(strcpy_s(config.ifname, sizeof(config.ifname), "test_if0") == EOK);
601     ctx = InitializeServer(&config);
602     EXPECT_TRUE(ctx == nullptr);
603 
604     EXPECT_EQ(RET_SUCCESS, InitServerConfig(&config));
605     ctx = InitializeServer(&config);
606     ASSERT_TRUE(ctx != nullptr);
607 
608     EXPECT_EQ(RET_SUCCESS, FreeServerConfig(&config));
609     EXPECT_EQ(RET_SUCCESS, FreeServerContext(&ctx));
610 }
611 
612 extern "C" int InitServer(const char *ifname);
613 
614 HWTEST_F(DhcpServerTest, InitServerByIfaceTest, TestSize.Level1)
615 {
616     const int SO_BROADCAST = 6;
617     const int SO_REUSEADDR = 2;
618     SystemFuncMock::GetInstance().SetMockFlag(true);
619     EXPECT_CALL(SystemFuncMock::GetInstance(), socket(_, _, _))
620         .WillOnce(Return(-1))
621         .WillRepeatedly(Return(1));
622     EXPECT_CALL(SystemFuncMock::GetInstance(), setsockopt(_, _, SO_REUSEADDR, _, _))
623         .WillOnce(Return(-1))
624         .WillRepeatedly(Return(0));
625     EXPECT_CALL(SystemFuncMock::GetInstance(), setsockopt(_, _, SO_BROADCAST, _, _))
626         .WillOnce(Return(-1))
627         .WillRepeatedly(Return(0));
628     EXPECT_CALL(SystemFuncMock::GetInstance(), select(_, _, _, _, _)).WillRepeatedly(Return(0));
629     EXPECT_CALL(SystemFuncMock::GetInstance(), recvfrom(_, _, _, _, _, _)).WillRepeatedly(Return(0));
630     EXPECT_CALL(SystemFuncMock::GetInstance(), bind(_, _, _))
631     .WillOnce(Return(-1))
632     .WillRepeatedly(Return(0));
633     EXPECT_CALL(SystemFuncMock::GetInstance(), close(_)).WillRepeatedly(Return(0));
634     const char* ifaceName = "test_if01";
635     EXPECT_EQ(-1, InitServer(ifaceName));
636     EXPECT_EQ(-1, InitServer(ifaceName));
637     EXPECT_EQ(-1, InitServer(ifaceName));
638     EXPECT_EQ(1, InitServer(ifaceName));
639 }
640 
641 HWTEST_F(DhcpServerTest, StartServerTest, TestSize.Level1)
642 {
643     SystemFuncMock::GetInstance().SetMockFlag(true);
644     EXPECT_TRUE(StartServerTest());
645 }
646 
647 HWTEST_F(DhcpServerTest, ReceiveDhcpMessageFailedTest, TestSize.Level1)
648 {
649     SystemFuncMock::GetInstance().SetMockFlag(true);
650     ON_CALL(SystemFuncMock::GetInstance(), select(_, _, _, _, _))
651         .WillByDefault(Return(0));
652     ON_CALL(SystemFuncMock::GetInstance(), recvfrom(_, _, _, _, _, _))
653         .WillByDefault(Return((int)sizeof(DhcpMsgInfo)));
654     DhcpMsgInfo msgInfo = {{0}, 0, {0}};
655     const uint8_t testMac1[DHCP_HWADDR_LENGTH] = {0x00, 0x0e, 0x3c, 0x65, 0x3a, 0x09, 0};
656 
657     int ret = ReceiveDhcpMessage(1, &msgInfo); // failed to select isset.
658     EXPECT_TRUE(ret == RET_SELECT_TIME_OUT || ret == RET_ERROR || ret == RET_FAILED);
659     ret = ReceiveDhcpMessage(1, &msgInfo); // message length error
660     EXPECT_TRUE(ret == RET_SELECT_TIME_OUT || ret == RET_ERROR || ret == RET_FAILED);
661     ret = ReceiveDhcpMessage(1, &msgInfo); // dhcp message type error
662     EXPECT_TRUE(ret == RET_SELECT_TIME_OUT || ret == RET_ERROR || ret == RET_FAILED);
663     msgInfo.packet.hlen = 128;
664     ret = ReceiveDhcpMessage(1, &msgInfo); // hlen error
665     EXPECT_TRUE(ret == RET_SELECT_TIME_OUT || ret == RET_ERROR || ret == RET_FAILED);
666     msgInfo.packet.hlen = 16;
667     msgInfo.packet.op = BOOTREPLY;
668     ret = ReceiveDhcpMessage(1, &msgInfo); // client op type error
669     EXPECT_TRUE(ret == RET_SELECT_TIME_OUT || ret == RET_ERROR || ret == RET_FAILED);
670     msgInfo.packet.op = BOOTREQUEST;
671     ret = ReceiveDhcpMessage(1, &msgInfo); // client hardware address error
672     EXPECT_TRUE(ret == RET_SELECT_TIME_OUT || ret == RET_ERROR || ret == RET_FAILED);
673     for (int i = 0; i < MAC_ADDR_LENGTH; ++i) {
674         msgInfo.packet.chaddr[i] = testMac1[i];
675     }
676     ret = ReceiveDhcpMessage(1, &msgInfo);
677     EXPECT_TRUE(ret == RET_SELECT_TIME_OUT || ret == RET_ERROR || ret == RET_FAILED);
678 }
679 
680 extern "C" int FillReply(PDhcpServerContext ctx, PDhcpMsgInfo received, PDhcpMsgInfo reply);
681 HWTEST_F(DhcpServerTest, FillReplyFailedTest, TestSize.Level1)
682 {
683     DhcpServerContext tempCtx;
684     ASSERT_TRUE(memset_s(&tempCtx, sizeof(DhcpServerContext), 0, sizeof(DhcpServerContext)) == EOK);
685     ASSERT_TRUE(memset_s(tempCtx.ifname, sizeof(tempCtx.ifname), '\0', sizeof(tempCtx.ifname)) == EOK);
686     DhcpMsgInfo recv, repl;
687     ASSERT_TRUE(memset_s(&recv, sizeof(DhcpMsgInfo), 0, sizeof(DhcpMsgInfo)) == EOK);
688     ASSERT_TRUE(memset_s(&repl, sizeof(DhcpMsgInfo), 0, sizeof(DhcpMsgInfo)) == EOK);
689     EXPECT_EQ(RET_ERROR, FillReply(&tempCtx, &recv, nullptr));
690     EXPECT_EQ(RET_FAILED, FillReply(&tempCtx, &recv, &repl));
691     recv.packet.flags = 1;
692     ServerContext srvInst;
693     ASSERT_TRUE(memset_s(&srvInst, sizeof(ServerContext), 0, sizeof(ServerContext)) == EOK);
694     tempCtx.instance = &srvInst;
695     recv.packet.siaddr = ParseIpAddr("192.168.189.252");
696     srvInst.addressPool.gateway = ParseIpAddr("192.168.189.254");
697     recv.packet.giaddr = ParseIpAddr("192.168.189.254");
698     EXPECT_EQ(RET_SUCCESS, FillReply(&tempCtx, &recv, &repl));
699     recv.packet.giaddr = 0;
700     EXPECT_EQ(RET_SUCCESS, FillReply(&tempCtx, &recv, &repl));
701 }
702 
703 extern "C" int BindNetInterface(int fd, const char *ifname);
704 HWTEST_F(DhcpServerTest, BindNetInterfaceFailedTest, TestSize.Level1)
705 {
706     SystemFuncMock::GetInstance().SetMockFlag(true);
707     EXPECT_CALL(SystemFuncMock::GetInstance(), setsockopt(_, _, _, _, _))
708         .WillOnce(Return(-1))
709         .WillOnce(Return(0));
710     const char* ifaceName = "test_if01";
711     EXPECT_EQ(RET_FAILED, BindNetInterface(1, nullptr));
712     EXPECT_EQ(RET_FAILED, BindNetInterface(1, ifaceName));
713     EXPECT_EQ(RET_SUCCESS, BindNetInterface(1, ifaceName));
714 }
715 
716 extern "C" int AddReplyServerIdOption(PDhcpOptionList options, uint32_t serverId);
717 HWTEST_F(DhcpServerTest, AddReplyServerIdOptionFailedTest, TestSize.Level1)
718 {
719     uint32_t srvId = ParseIpAddr("192.168.189.254");
720     ASSERT_TRUE(srvId != 0);
721     DhcpOptionList opts;
722     ASSERT_TRUE(memset_s(&opts, sizeof(DhcpOptionList), '\0', sizeof(DhcpOptionList)) == EOK);
723     EXPECT_EQ(RET_FAILED, AddReplyServerIdOption(nullptr, 0));
724     EXPECT_EQ(RET_FAILED, AddReplyServerIdOption(&opts, 0));
725 
726     EXPECT_EQ(RET_SUCCESS, AddReplyServerIdOption(&opts, srvId));
727     EXPECT_EQ(RET_SUCCESS, AddReplyServerIdOption(&opts, srvId));
728 }
729 
730 extern "C" int InitServerFixedOptions(DhcpConfig *config, DhcpServerContext *ctx);
731 HWTEST_F(DhcpServerTest, InitServerFixedOptionsFailedTest, TestSize.Level1)
732 {
733     DhcpServerContext tempCtx;
734     tempCtx.instance = nullptr;
735     ASSERT_TRUE(memset_s(&tempCtx, sizeof(DhcpServerContext), 0, sizeof(DhcpServerContext)) == EOK);
736     ASSERT_TRUE(memset_s(tempCtx.ifname, sizeof(tempCtx.ifname), '\0', sizeof(tempCtx.ifname)) == EOK);
737     DhcpConfig tempConfig;
738     ASSERT_TRUE(memset_s(&tempConfig, sizeof(DhcpConfig), 0, sizeof(DhcpConfig)) == EOK);
739     EXPECT_EQ(RET_FAILED, InitServerFixedOptions(nullptr, &tempCtx));
740     EXPECT_EQ(RET_FAILED, InitServerFixedOptions(&tempConfig, &tempCtx));
741 
742     ServerContext srvInst;
743     ASSERT_TRUE(memset_s(&srvInst, sizeof(ServerContext), 0, sizeof(ServerContext)) == EOK);
744     tempCtx.instance = &srvInst;
745     EXPECT_EQ(RET_FAILED, InitServerFixedOptions(&tempConfig, &tempCtx));
746 }
747 
748 extern "C" int AppendReplyTimeOptions(PDhcpServerContext ctx, PDhcpOptionList options);
749 HWTEST_F(DhcpServerTest, AppendReplyTimeOptionsFailedTest, TestSize.Level1)
750 {
751     DhcpServerContext tempCtx;
752     tempCtx.instance = nullptr;
753     ASSERT_TRUE(memset_s(&tempCtx, sizeof(DhcpServerContext), 0, sizeof(DhcpServerContext)) == EOK);
754     ASSERT_TRUE(memset_s(tempCtx.ifname, sizeof(tempCtx.ifname), '\0', sizeof(tempCtx.ifname)) == EOK);
755     EXPECT_EQ(RET_FAILED, AppendReplyTimeOptions(nullptr, nullptr));
756     EXPECT_EQ(RET_FAILED, AppendReplyTimeOptions(&tempCtx, nullptr));
757 }
758 
759 HWTEST_F(DhcpServerTest, FreeServerContextFailedTest, TestSize.Level1)
760 {
761     EXPECT_EQ(RET_FAILED, FreeServerContext(nullptr));
762 }
763 
764 extern "C" AddressBinding *GetBinding(DhcpAddressPool *pool, PDhcpMsgInfo received);
765 HWTEST_F(DhcpServerTest, GetBindingFailedTest, TestSize.Level1)
766 {
767     DhcpAddressPool tempPool;
768     DhcpMsgInfo msgInfo;
769     ASSERT_TRUE(memset_s(&tempPool, sizeof(DhcpAddressPool), 0, sizeof(DhcpAddressPool)) == EOK);
770     ASSERT_TRUE(memset_s(&msgInfo, sizeof(DhcpMsgInfo), 0, sizeof(DhcpMsgInfo)) == EOK);
771     EXPECT_TRUE(GetBinding(&tempPool, nullptr) == nullptr);
772     EXPECT_TRUE(GetBinding(nullptr, &msgInfo) == nullptr);
773     ASSERT_EQ(RET_SUCCESS, InitAddressPool(&tempPool, "test_if01", nullptr));
774     EXPECT_TRUE(GetBinding(&tempPool, &msgInfo) != nullptr);
775     FreeAddressPool(&tempPool);
776 }
777 
778 extern "C" int SendDhcpReply(PDhcpServerContext ctx, int replyType, PDhcpMsgInfo reply);
779 HWTEST_F(DhcpServerTest, SendDhcpReplyTest, TestSize.Level1)
780 {
781     DhcpServerContext tempCtx;
782     tempCtx.instance = nullptr;
783     ASSERT_TRUE(memset_s(&tempCtx, sizeof(DhcpServerContext), 0, sizeof(DhcpServerContext)) == EOK);
784     EXPECT_EQ(RET_FAILED, SendDhcpReply(&tempCtx, REPLY_NAK, nullptr));
785     EXPECT_EQ(RET_FAILED, SendDhcpReply(nullptr, REPLY_NAK, nullptr));
786 }
787 
788 HWTEST_F(DhcpServerTest, SaveLeaseFailedTest, TestSize.Level1)
789 {
790     DhcpServerContext tempCtx;
791     tempCtx.instance = nullptr;
792     ASSERT_TRUE(memset_s(&tempCtx, sizeof(DhcpServerContext), 0, sizeof(DhcpServerContext)) == EOK);
793     EXPECT_EQ(RET_FAILED, SaveLease(nullptr));
794     EXPECT_EQ(RET_FAILED, SaveLease(&tempCtx));
795 }
796 }
797 }
798