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