• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2025 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 
17 #include "dhcp_arp_checker_fuzzer.h"
18 #include "dhcp_arp_checker.h"
19 #include "dhcp_fuzz_common_func.h"
20 #include <cstdint>
21 #include <string>
22 #include <vector>
23 #include <chrono>
24 #include <cstring>
25 #include <sys/socket.h>
26 #include <netinet/in.h>
27 #include <arpa/inet.h>
28 #include <linux/if_packet.h>
29 #include <poll.h>
30 #include <fcntl.h>
31 #include <unistd.h>
32 #include <algorithm>
33 #include "securec.h"
34 #include "dhcp_arp_checker.h"
35 
36 using namespace std;
37 namespace OHOS {
38 namespace DHCP {
39 
40 constexpr size_t MIN_U32_SIZE = sizeof(uint32_t);
41 constexpr size_t MIN_U16_SIZE = sizeof(uint16_t);
42 constexpr int32_t DEFAULT_TIMEOUT_MILLIS = 1000;
43 constexpr size_t MIN_ETH_ALEN = ETH_ALEN;
44 
45 std::shared_ptr<DhcpArpChecker> pDhcpArpChecker = std::make_shared<DhcpArpChecker>();
46 
TestStart(const uint8_t * data,size_t size)47 void TestStart(const uint8_t* data, size_t size)
48 {
49     if (size < MIN_U32_SIZE) {
50         return;
51     }
52     size_t pos = 0;
53     uint32_t ifnameLen = U32_AT(data);
54     pos += MIN_U32_SIZE;
55     if (pos + ifnameLen > size) {
56         return;
57     }
58     string ifname(reinterpret_cast<const char*>(data + pos), ifnameLen);
59     pos += ifnameLen;
60 
61     if (pos + MIN_U32_SIZE > size) {
62         return;
63     }
64     uint32_t hwAddrLen = U32_AT(data + pos);
65     pos += MIN_U32_SIZE;
66     if (pos + hwAddrLen > size) {
67         return;
68     }
69     string hwAddr(reinterpret_cast<const char*>(data + pos), hwAddrLen);
70     pos += hwAddrLen;
71 
72     if (pos + MIN_U32_SIZE > size) {
73         return;
74     }
75     uint32_t senderIpLen = U32_AT(data + pos);
76     pos += MIN_U32_SIZE;
77     if (pos + senderIpLen > size) {
78         return;
79     }
80     string senderIp(reinterpret_cast<const char*>(data + pos), senderIpLen);
81     pos += senderIpLen;
82 
83     if (pos + MIN_U32_SIZE > size) {
84         return;
85     }
86     uint32_t targetIpLen = U32_AT(data + pos);
87     pos += MIN_U32_SIZE;
88     if (pos + targetIpLen > size) {
89         return;
90     }
91     string targetIp(reinterpret_cast<const char*>(data + pos), targetIpLen);
92 
93     pDhcpArpChecker->Start(ifname, hwAddr, senderIp, targetIp);
94 }
95 
TestStop(const uint8_t * data,size_t size)96 void TestStop(const uint8_t* data, size_t size)
97 {
98     (void)data;
99     (void)size;
100     pDhcpArpChecker->Stop();
101 }
102 
TestSetArpPacket(const uint8_t * data,size_t size)103 void TestSetArpPacket(const uint8_t* data, size_t size)
104 {
105     ArpPacket arpPacket;
106     bool isFillSenderIp = (size >= 1) ? (data[0] != 0) : false;
107     pDhcpArpChecker->SetArpPacket(arpPacket, isFillSenderIp);
108 }
109 
TestDoArpCheck(const uint8_t * data,size_t size)110 void TestDoArpCheck(const uint8_t* data, size_t size)
111 {
112     int32_t timeoutMillis = (size >= MIN_U32_SIZE) ? static_cast<int32_t>(U32_AT(data)) : DEFAULT_TIMEOUT_MILLIS;
113     bool isFillSenderIp = (size >= MIN_U32_SIZE + 1) ? (data[MIN_U32_SIZE] != 0) : false;
114     uint64_t timeCost = 0;
115     pDhcpArpChecker->DoArpCheck(timeoutMillis, isFillSenderIp, timeCost);
116 }
117 
TestGetGwMacAddrList(const uint8_t * data,size_t size)118 void TestGetGwMacAddrList(const uint8_t* data, size_t size)
119 {
120     int32_t timeoutMillis = (size >= MIN_U32_SIZE) ? static_cast<int32_t>(U32_AT(data)) : DEFAULT_TIMEOUT_MILLIS;
121     bool isFillSenderIp = (size >= MIN_U32_SIZE + 1) ? (data[MIN_U32_SIZE] != 0) : false;
122     vector<string> gwMacLists;
123     pDhcpArpChecker->GetGwMacAddrList(timeoutMillis, isFillSenderIp, gwMacLists);
124 }
125 
TestSaveGwMacAddr(const uint8_t * data,size_t size)126 void TestSaveGwMacAddr(const uint8_t* data, size_t size)
127 {
128     if (size < MIN_U32_SIZE) {
129         return;
130     }
131     size_t pos = 0;
132     uint32_t gwMacAddrLen = U32_AT(data);
133     pos += MIN_U32_SIZE;
134     if (pos + gwMacAddrLen > size) {
135         return;
136     }
137     string gwMacAddr(reinterpret_cast<const char*>(data + pos), gwMacAddrLen);
138     vector<string> gwMacLists;
139     pDhcpArpChecker->SaveGwMacAddr(gwMacAddr, gwMacLists);
140 }
141 
TestCreateSocket(const uint8_t * data,size_t size)142 void TestCreateSocket(const uint8_t* data, size_t size)
143 {
144     if (size < MIN_U32_SIZE) {
145         return;
146     }
147     size_t pos = 0;
148     uint32_t ifaceLen = U32_AT(data);
149     pos += MIN_U32_SIZE;
150     if (pos + ifaceLen > size) {
151         return;
152     }
153     string iface(reinterpret_cast<const char*>(data + pos), ifaceLen);
154     uint16_t protocol = (size >= pos + MIN_U16_SIZE) ? static_cast<uint16_t>(U16_AT(data + pos)) : ETH_P_ARP;
155     pDhcpArpChecker->CreateSocket(iface.c_str(), protocol);
156 }
157 
TestSendData(const uint8_t * data,size_t size)158 void TestSendData(const uint8_t* data, size_t size)
159 {
160     if (size < MIN_U32_SIZE) {
161         return;
162     }
163     size_t pos = 0;
164     uint32_t count = U32_AT(data);
165     pos += MIN_U32_SIZE;
166     if (pos + count > size) {
167         return;
168     }
169     uint8_t* buff = const_cast<uint8_t*>(data + pos);
170     pos += count;
171     uint8_t destHwaddr[MIN_ETH_ALEN] = {0};
172     if (pos + MIN_ETH_ALEN <= size) {
173         if (memcpy_s(destHwaddr, MIN_ETH_ALEN, data + pos, MIN_ETH_ALEN) != 0) {
174             return;
175         }
176     }
177     pDhcpArpChecker->SendData(buff, count, destHwaddr);
178 }
179 
TestRecvData(const uint8_t * data,size_t size)180 void TestRecvData(const uint8_t* data, size_t size)
181 {
182     if (size < MIN_U32_SIZE) {
183         return;
184     }
185     size_t pos = 0;
186     uint32_t count = U32_AT(data);
187     pos += MIN_U32_SIZE;
188     if (pos + count > size) {
189         return;
190     }
191     uint8_t* buff = const_cast<uint8_t*>(data + pos);
192     pos += count;
193     int32_t timeoutMillis = (size >= pos + MIN_U32_SIZE) ?
194         static_cast<int32_t>(U32_AT(data + pos)) : DEFAULT_TIMEOUT_MILLIS;
195     pDhcpArpChecker->RecvData(buff, count, timeoutMillis);
196 }
197 
TestCloseSocket(const uint8_t * data,size_t size)198 void TestCloseSocket(const uint8_t* data, size_t size)
199 {
200     (void)data;
201     (void)size;
202     pDhcpArpChecker->CloseSocket();
203 }
204 
TestSetNonBlock(const uint8_t * data,size_t size)205 void TestSetNonBlock(const uint8_t* data, size_t size)
206 {
207     int32_t fd = (size >= MIN_U32_SIZE) ? static_cast<int32_t>(U32_AT(data)) : 0;
208     pDhcpArpChecker->SetNonBlock(fd);
209 }
210 
211 /* Fuzzer entry point */
LLVMFuzzerTestOneInput(const uint8_t * data,size_t size)212 extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size)
213 {
214     if ((data == nullptr) || (size <= MIN_U32_SIZE)) {
215         return 0;
216     }
217 
218     TestStart(data, size);
219     TestStop(data, size);
220     TestSetArpPacket(data, size);
221     TestDoArpCheck(data, size);
222     TestGetGwMacAddrList(data, size);
223     TestSaveGwMacAddr(data, size);
224     TestCreateSocket(data, size);
225     TestSendData(data, size);
226     TestRecvData(data, size);
227     TestCloseSocket(data, size);
228     TestSetNonBlock(data, size);
229 
230     return 0;
231 }
232 }  // namespace DHCP
233 }  // namespace OHOS