• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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