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 #include <cstdint>
17 #include <string>
18 #include <vector>
19 #include <cstring>
20
21 #include "securec.h"
22 #include "dhcp_logger.h"
23 #include "dhcp_dhcpd.h"
24 #include "dhcp_config.h"
25 #include "address_utils.h"
26 #include "dhcp_fuzz_common_func.h"
27 #include "dhcpdhcpd_fuzzer.h"
28
29 using namespace std;
30 namespace OHOS {
31 namespace DHCP {
32
33 constexpr size_t U32_AT_SIZE_ZERO = 4;
34 constexpr size_t MIN_STRING_SIZE = 8;
35 constexpr size_t MAX_IP_STRING_SIZE = 16;
36 constexpr int TWO = 2;
37
TestStopDhcpServerMain(const uint8_t * data,size_t size)38 void TestStopDhcpServerMain(const uint8_t* data, size_t size) {
39 }
40
TestRegisterDeviceConnectCallBack(const uint8_t * data,size_t size)41 void TestRegisterDeviceConnectCallBack(const uint8_t* data, size_t size)
42 {
43 DeviceConnectFun testCallback = [](const char* ifname) {
44 if (ifname) {
45 }
46 };
47
48 RegisterDeviceConnectCallBack(testCallback);
49
50 RegisterDeviceConnectCallBack(nullptr);
51 }
52
TestParseIpAddr(const uint8_t * data,size_t size)53 void TestParseIpAddr(const uint8_t* data, size_t size)
54 {
55 if (size < U32_AT_SIZE_ZERO) {
56 return;
57 }
58
59 size_t pos = 0;
60 uint32_t ipStringLen = U32_AT(data + pos) % MAX_IP_STRING_SIZE;
61 pos += sizeof(uint32_t);
62
63 if (pos + ipStringLen > size) {
64 return;
65 }
66
67 string ipString(reinterpret_cast<const char*>(data + pos), ipStringLen);
68 if (!ipString.empty()) {
69 ipString[ipString.length() - 1] = '\0';
70
71 ParseIpAddr(ipString.c_str());
72 }
73 }
74
TestDhcpConfigOperations(const uint8_t * data,size_t size)75 void TestDhcpConfigOperations(const uint8_t* data, size_t size)
76 {
77 if (size < sizeof(DhcpConfig)) {
78 return;
79 }
80
81 DhcpConfig config;
82 if (memset_s(&config, sizeof(DhcpConfig), 0, sizeof(DhcpConfig)) != EOK) {
83 return;
84 }
85
86 size_t pos = 0;
87 if (size >= pos + sizeof(uint32_t)) {
88 config.serverId = U32_AT(data + pos);
89 pos += sizeof(uint32_t);
90 }
91
92 if (size >= pos + sizeof(uint32_t)) {
93 config.netmask = U32_AT(data + pos);
94 pos += sizeof(uint32_t);
95 }
96
97 if (size >= pos + sizeof(uint32_t)) {
98 config.gateway = U32_AT(data + pos);
99 pos += sizeof(uint32_t);
100 }
101
102 if (size >= pos + sizeof(uint32_t)) {
103 config.pool.beginAddress = U32_AT(data + pos);
104 pos += sizeof(uint32_t);
105 }
106
107 if (size >= pos + sizeof(uint32_t)) {
108 config.pool.endAddress = U32_AT(data + pos);
109 pos += sizeof(uint32_t);
110 }
111
112 if (size >= pos + sizeof(uint32_t)) {
113 config.leaseTime = U32_AT(data + pos);
114 pos += sizeof(uint32_t);
115 }
116
117 if (size >= pos + sizeof(uint32_t)) {
118 config.renewalTime = U32_AT(data + pos);
119 pos += sizeof(uint32_t);
120 }
121
122 if (size >= pos + sizeof(uint32_t)) {
123 config.rebindingTime = U32_AT(data + pos);
124 pos += sizeof(uint32_t);
125 }
126
127 if (size >= pos + IFACE_NAME_SIZE) {
128 if (memcpy_s(config.ifname, IFACE_NAME_SIZE, data + pos, IFACE_NAME_SIZE) != EOK) {
129 return;
130 }
131 config.ifname[IFACE_NAME_SIZE - 1] = '\0';
132 }
133 }
134
TestArgumentOperations(const uint8_t * data,size_t size)135 void TestArgumentOperations(const uint8_t* data, size_t size)
136 {
137 if (size < U32_AT_SIZE_ZERO + MIN_STRING_SIZE * TWO) {
138 return;
139 }
140
141 size_t pos = 0;
142 uint32_t keyLen = U32_AT(data + pos) % 32;
143 pos += sizeof(uint32_t);
144
145 if (pos + keyLen > size) {
146 return;
147 }
148
149 string argKey(reinterpret_cast<const char*>(data + pos), keyLen);
150 pos += keyLen;
151
152 if (pos + sizeof(uint32_t) > size) {
153 return;
154 }
155
156 uint32_t valueLen = U32_AT(data + pos) % 64;
157 pos += sizeof(uint32_t);
158
159 if (pos + valueLen > size) {
160 return;
161 }
162
163 string argValue(reinterpret_cast<const char*>(data + pos), valueLen);
164
165 if (!argKey.empty()) {
166 argKey[argKey.length() - 1] = '\0';
167 }
168 if (!argValue.empty()) {
169 argValue[argValue.length() - 1] = '\0';
170 }
171 }
172
TestStringOperations(const uint8_t * data,size_t size)173 void TestStringOperations(const uint8_t* data, size_t size)
174 {
175 if (size < U32_AT_SIZE_ZERO) {
176 return;
177 }
178
179 size_t pos = 0;
180 uint32_t strLen = U32_AT(data + pos) % 256;
181 pos += sizeof(uint32_t);
182
183 if (pos + strLen > size) {
184 return;
185 }
186
187 vector<char> testString(strLen + 1, 0);
188 if (strLen > 0) {
189 if (memcpy_s(testString.data(), strLen, data + pos, strLen) != EOK) {
190 return;
191 }
192 }
193 testString[strLen] = '\0';
194
195 if (strLen > 0) {
196 ParseIpAddr(testString.data());
197 }
198 }
199
LLVMFuzzerTestOneInput(const uint8_t * data,size_t size)200 extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size)
201 {
202 if ((data == nullptr) || (size <= OHOS::DHCP::U32_AT_SIZE_ZERO)) {
203 return 0;
204 }
205
206 TestStartDhcpServerMain(data, size);
207 TestStopDhcpServerMain(data, size);
208 TestRegisterDeviceConnectCallBack(data, size);
209 TestParseIpAddr(data, size);
210 TestDhcpConfigOperations(data, size);
211 TestArgumentOperations(data, size);
212 TestStringOperations(data, size);
213
214 return 0;
215 }
216
217 } // namespace DHCP
218 } // namespace OHOS