1 /*
2 * Copyright (C) 2024 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 "dhcp_result_store_manager.h"
17 #include "dhcp_common_utils.h"
18 #include "dhcp_errcode.h"
19 #include "dhcp_logger.h"
20 #include "securec.h"
21
22 namespace OHOS {
23 namespace DHCP {
24 DEFINE_DHCPLOG_DHCP_LABEL("DhcpResultStoreManager");
25 constexpr int MAC_ADDR_SIZE = 17;
DhcpResultStoreManager()26 DhcpResultStoreManager::DhcpResultStoreManager()
27 {
28 DHCP_LOGI("DhcpResultStoreManager()");
29 }
30
~DhcpResultStoreManager()31 DhcpResultStoreManager::~DhcpResultStoreManager()
32 {
33 DHCP_LOGI("~DhcpResultStoreManager()");
34 }
35
GetInstance()36 DhcpResultStoreManager &DhcpResultStoreManager::GetInstance()
37 {
38 static DhcpResultStoreManager g_ipInstance;
39 return g_ipInstance;
40 }
41
TrimString(std::string & str)42 static void TrimString(std::string &str)
43 {
44 int32_t i = 0;
45 int32_t j = static_cast<int32_t>(str.length()) - 1;
46 while (i < static_cast<int32_t>(str.length()) && (str[i] == ' ' || str[i] == '\n')) {
47 ++i;
48 }
49 while (j >= 0 && (str[j] == ' '|| str[j] == '\n')) {
50 --j;
51 }
52 str = ((i > j) ? "" : str.substr(i, j - i + 1));
53 }
54
SetClassKeyValue(IpInfoCached & item,const std::string & key,const std::string & value)55 static int32_t SetClassKeyValue(IpInfoCached &item, const std::string &key, const std::string &value)
56 {
57 int32_t errorKeyValue = 0;
58 std::string valueTmp = value;
59 if (key == "bssid") {
60 item.bssid = value;
61 } else if (key == "ssid") {
62 item.ssid = value;
63 } else if (key == "absoluteLeasetime") {
64 item.absoluteLeasetime = static_cast<int64_t>(CheckDataLegal(valueTmp));
65 } else if (key == "strYiaddr") {
66 if (strncpy_s(item.ipResult.strYiaddr, sizeof(item.ipResult.strYiaddr), value.c_str(), value.size()) != EOK) {
67 errorKeyValue++;
68 }
69 } else if (key == "strOptServerId") {
70 if (strncpy_s(
71 item.ipResult.strOptServerId, sizeof(item.ipResult.strOptServerId), value.c_str(), value.size()) != EOK) {
72 errorKeyValue++;
73 }
74 } else if (key == "strOptSubnet") {
75 if (strncpy_s(
76 item.ipResult.strOptSubnet, sizeof(item.ipResult.strOptSubnet), value.c_str(), value.size()) != EOK) {
77 errorKeyValue++;
78 }
79 } else if (key == "strOptDns1") {
80 if (strncpy_s(
81 item.ipResult.strOptDns1, sizeof(item.ipResult.strOptDns1), value.c_str(), value.size()) != EOK) {
82 errorKeyValue++;
83 }
84 } else if (key == "strOptDns2") {
85 if (strncpy_s(
86 item.ipResult.strOptDns2, sizeof(item.ipResult.strOptDns2), value.c_str(), value.size()) != EOK) {
87 errorKeyValue++;
88 }
89 } else if (key == "strOptRouter1") {
90 if (strncpy_s(
91 item.ipResult.strOptRouter1, sizeof(item.ipResult.strOptRouter1), value.c_str(), value.size()) != EOK) {
92 errorKeyValue++;
93 }
94 } else if (key == "strOptRouter2") {
95 if (strncpy_s(
96 item.ipResult.strOptRouter2, sizeof(item.ipResult.strOptRouter2), value.c_str(), value.size()) != EOK) {
97 errorKeyValue++;
98 }
99 } else if (key == "uOptLeasetime") {
100 item.ipResult.uOptLeasetime = static_cast<uint32_t>(CheckDataLegal(valueTmp));
101 } else {
102 errorKeyValue++;
103 }
104 return errorKeyValue;
105 }
106
OutClassString(IpInfoCached & item)107 static std::string OutClassString(IpInfoCached &item)
108 {
109 std::string buffer = "";
110 buffer += " <IpInfoCached>\n";
111 buffer += " bssid=" + std::string(item.bssid) + "\n";
112 buffer += " ssid=" + std::string(item.ssid) + "\n";
113 buffer += " absoluteLeasetime=" + std::to_string(item.absoluteLeasetime) + "\n";
114 buffer += " strYiaddr=" + std::string(item.ipResult.strYiaddr) + "\n";
115 buffer += " strOptServerId=" + std::string(item.ipResult.strOptServerId) + "\n";
116 buffer += " strOptSubnet=" + std::string(item.ipResult.strOptSubnet) + "\n";
117 buffer += " strOptDns1=" + std::string(item.ipResult.strOptDns1) + "\n";
118 buffer += " strOptDns2=" + std::string(item.ipResult.strOptDns2) + "\n";
119 buffer += " strOptRouter1=" + std::string(item.ipResult.strOptRouter1) + "\n";
120 buffer += " strOptRouter2=" + std::string(item.ipResult.strOptRouter2) + "\n";
121 buffer += " uOptLeasetime=" + std::to_string(item.ipResult.uOptLeasetime) + "\n";
122 buffer += " <IpInfoCached>\n";
123 return buffer;
124 }
125
ClearClass(IpInfoCached & item)126 static void ClearClass(IpInfoCached &item)
127 {
128 item.bssid.clear();
129 item.absoluteLeasetime = 0;
130 item.ipResult.uOptLeasetime = 0;
131 }
132
ReadNetworkSection(IpInfoCached & item,FILE * fp,char * line,size_t lineSize)133 static int32_t ReadNetworkSection(IpInfoCached &item, FILE *fp, char *line, size_t lineSize)
134 {
135 int32_t sectionError = 0;
136 while (fgets(line, lineSize, fp) != nullptr) {
137 std::string strLine = line;
138 TrimString(strLine);
139 if (strLine.empty()) {
140 continue;
141 }
142 if (strLine[0] == '<' && ((strLine.length() > 0) && (strLine[strLine.length() - 1] == '>'))) {
143 return sectionError;
144 }
145 std::string::size_type npos = strLine.find("=");
146 if (npos == std::string::npos) {
147 DHCP_LOGE("Invalid config line");
148 sectionError++;
149 continue;
150 }
151 std::string key = strLine.substr(0, npos);
152 std::string value = strLine.substr(npos + 1);
153 TrimString(key);
154 TrimString(value);
155 /* template function, needing specialization */
156 sectionError += SetClassKeyValue(item, key, value);
157 }
158 DHCP_LOGE("Section config not end correctly");
159 sectionError++;
160 return sectionError;
161 }
162
ReadNetwork(IpInfoCached & item,FILE * fp,char * line,size_t lineSize)163 static int32_t ReadNetwork(IpInfoCached &item, FILE *fp, char *line, size_t lineSize)
164 {
165 int32_t networkError = 0;
166 while (fgets(line, lineSize, fp) != nullptr) {
167 std::string strLine = line;
168 TrimString(strLine);
169 if (strLine.empty()) {
170 continue;
171 }
172 if (strLine[0] == '<' && ((strLine.length() > 0) && (strLine[strLine.length() - 1] == '>'))) {
173 networkError += ReadNetworkSection(item, fp, line, lineSize);
174 } else if (strLine.compare("}") == 0) {
175 return networkError;
176 } else {
177 DHCP_LOGE("Invalid config line");
178 networkError++;
179 }
180 }
181 DHCP_LOGE("Network config not end correctly");
182 networkError++;
183 return networkError;
184 }
185
186
SaveIpInfoInLocalFile(const IpInfoCached ipResult)187 int32_t DhcpResultStoreManager::SaveIpInfoInLocalFile(const IpInfoCached ipResult)
188 {
189 std::unique_lock<std::mutex> lock(m_ipResultMutex);
190 for (auto it = m_allIpCached.begin(); it != m_allIpCached.end(); it++) {
191 if (ipResult.bssid == it->bssid) {
192 m_allIpCached.erase(it);
193 break;
194 }
195 }
196 m_allIpCached.push_back(ipResult);
197 return SaveConfig();
198 }
199
RemoveCachedIp(const IpInfoCached & cacheInfo)200 int32_t DhcpResultStoreManager::RemoveCachedIp(const IpInfoCached &cacheInfo)
201 {
202 LoadAllIpCached(DHCP_CACHE_FILE);
203 DHCP_LOGE("RemoveCachedIp, m_allIpCached size is %{public}d", static_cast<int32_t>(m_allIpCached.size()));
204 if (cacheInfo.ssid.empty()) {
205 DHCP_LOGE("RemoveCachedIp, ssid is empty");
206 return DHCP_E_FAILED;
207 }
208 std::unique_lock<std::mutex> lock(m_ipResultMutex);
209 if (m_allIpCached.empty()) {
210 DHCP_LOGE("m_allIpCached is empty");
211 return DHCP_E_FAILED;
212 }
213 m_allIpCached.erase(std::remove_if(m_allIpCached.begin(), m_allIpCached.end(),
214 [cacheInfo](IpInfoCached x) { return x.ssid == cacheInfo.ssid; }), m_allIpCached.end());
215 return SaveConfig();
216 }
217
AddCachedIp(const IpInfoCached & cacheInfo)218 int32_t DhcpResultStoreManager::AddCachedIp(const IpInfoCached &cacheInfo)
219 {
220 LoadAllIpCached(DHCP_CACHE_FILE);
221 DHCP_LOGE("AddCachedIp, m_allIpCached size is %{public}d", static_cast<int32_t>(m_allIpCached.size()));
222 std::unique_lock<std::mutex> lock(m_ipResultMutex);
223 if (m_allIpCached.empty()) {
224 DHCP_LOGE("m_allIpCached is empty");
225 return DHCP_E_FAILED;
226 }
227 if (cacheInfo.ssid.empty() || (cacheInfo.bssid.size() != MAC_ADDR_SIZE)) {
228 DHCP_LOGE("ssid or bssid is invalid");
229 return DHCP_E_FAILED;
230 }
231 for (auto it = m_allIpCached.begin(); it != m_allIpCached.end(); it++) {
232 if (cacheInfo.bssid == it->bssid) {
233 it->ssid = cacheInfo.ssid;
234 break;
235 }
236 }
237 return SaveConfig();
238 }
239
GetCachedIp(const std::string targetBssid,IpInfoCached & outIpResult)240 int32_t DhcpResultStoreManager::GetCachedIp(const std::string targetBssid, IpInfoCached &outIpResult)
241 {
242 std::string fileName = DHCP_CACHE_FILE;
243 LoadAllIpCached(fileName);
244 std::unique_lock<std::mutex> lock(m_ipResultMutex);
245 for (auto it = m_allIpCached.begin(); it != m_allIpCached.end(); it++) {
246 if (targetBssid == it->bssid) {
247 outIpResult = static_cast<IpInfoCached>(*it);
248 return 0;
249 }
250 }
251 return -1;
252 }
253
SetConfigFilePath(const std::string & fileName)254 void DhcpResultStoreManager::SetConfigFilePath(const std::string &fileName)
255 {
256 m_fileName = fileName;
257 }
258
LoadAllIpCached(const std::string & fileName)259 int32_t DhcpResultStoreManager::LoadAllIpCached(const std::string &fileName)
260 {
261 std::unique_lock<std::mutex> lock(m_ipResultMutex);
262 SetConfigFilePath(fileName);
263 if (m_fileName.empty()) {
264 DHCP_LOGE("File name is empty.");
265 return -1;
266 }
267 char *realPaths = realpath(m_fileName.c_str(), nullptr);
268 if (realPaths == nullptr) {
269 DHCP_LOGE("realpath failed error");
270 return -1;
271 }
272 FILE *fp = fopen(realPaths, "r");
273 if (!fp) {
274 DHCP_LOGE("Loading config file: %{public}s, fopen() failed!", m_fileName.c_str());
275 free(realPaths);
276 return -1;
277 }
278 m_allIpCached.clear();
279 std::vector<IpInfoCached>().swap(m_allIpCached);
280 IpInfoCached item;
281 char line[1024];
282 int32_t configError;
283 while (fgets(line, sizeof(line), fp) != nullptr) {
284 std::string strLine = line;
285 TrimString(strLine);
286 if (strLine.empty()) {
287 continue;
288 }
289 if (strLine[0] == '[' && ((strLine.length() > 0) && (strLine[strLine.length() - 1] == '{'))) {
290 ClearClass(item); /* template function, needing specialization */
291 configError = ReadNetwork(item, fp, line, sizeof(line));
292 if (configError > 0) {
293 DHCP_LOGE("Parse network failed.");
294 continue;
295 }
296 m_allIpCached.push_back(item);
297 }
298 }
299
300 (void)fclose(fp);
301 free(realPaths);
302 return 0;
303 }
304
305
SaveConfig()306 int32_t DhcpResultStoreManager::SaveConfig()
307 {
308 if (!IsValidPath(m_fileName)) {
309 DHCP_LOGE("invalid path:%{public}s", m_fileName.c_str());
310 return -1;
311 }
312
313 FILE* fp = fopen(m_fileName.c_str(), "w");
314 if (!fp) {
315 DHCP_LOGE("Save config file: %{public}s, fopen() failed!", m_fileName.c_str());
316 return -1;
317 }
318 std::string content = "";
319 for (std::size_t i = 0; i < m_allIpCached.size(); ++i) {
320 IpInfoCached &item = m_allIpCached[i];
321 content += "[IpInfoCached_" + std::to_string(i + 1) + "] {\n";
322 content += OutClassString(item) + "\n";
323 content += "}\n";
324 }
325 uint32_t ret = fwrite(content.c_str(), 1, content.length(), fp);
326 if (ret != static_cast<uint32_t>(content.length())) {
327 DHCP_LOGE("Save config file: %{public}s, fwrite() failed!", m_fileName.c_str());
328 }
329 (void)fflush(fp);
330 (void)fsync(fileno(fp));
331 (void)fclose(fp);
332 m_allIpCached.clear(); /* clear values */
333 std::vector<IpInfoCached>().swap(m_allIpCached);
334 return 0;
335 }
336
337 } // namespace DHCP
338 } // namespace OHOS