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_logger.h"
19 #include "securec.h"
20 
21 namespace OHOS {
22 namespace DHCP {
23 DEFINE_DHCPLOG_DHCP_LABEL("DhcpResultStoreManager");
24 
DhcpResultStoreManager()25 DhcpResultStoreManager::DhcpResultStoreManager()
26 {
27     DHCP_LOGI("DhcpResultStoreManager()");
28 }
29 
~DhcpResultStoreManager()30 DhcpResultStoreManager::~DhcpResultStoreManager()
31 {
32     DHCP_LOGI("~DhcpResultStoreManager()");
33 }
34 
GetInstance()35 DhcpResultStoreManager &DhcpResultStoreManager::GetInstance()
36 {
37     static DhcpResultStoreManager g_ipInstance;
38     return g_ipInstance;
39 }
40 
SaveIpInfoInLocalFile(const IpInfoCached ipResult)41 int32_t DhcpResultStoreManager::SaveIpInfoInLocalFile(const IpInfoCached ipResult)
42 {
43     std::unique_lock<std::mutex> lock(m_ipResultMutex);
44     for (auto it = m_allIpCached.begin(); it != m_allIpCached.end(); it++) {
45         if (ipResult.bssid == it->bssid) {
46             m_allIpCached.erase(it);
47             break;
48         }
49     }
50     m_allIpCached.push_back(ipResult);
51     return SaveConfig();
52 }
53 
GetCachedIp(const std::string targetBssid,IpInfoCached & outIpResult)54 int32_t DhcpResultStoreManager::GetCachedIp(const std::string targetBssid, IpInfoCached &outIpResult)
55 {
56     std::string fileName = DHCP_CACHE_FILE;
57     LoadAllIpCached(fileName);
58     std::unique_lock<std::mutex> lock(m_ipResultMutex);
59     for (auto it = m_allIpCached.begin(); it != m_allIpCached.end(); it++) {
60         if (targetBssid == it->bssid) {
61             outIpResult = static_cast<IpInfoCached>(*it);
62             return 0;
63         }
64     }
65     return -1;
66 }
67 
SetConfigFilePath(const std::string & fileName)68 void DhcpResultStoreManager::SetConfigFilePath(const std::string &fileName)
69 {
70     m_fileName = fileName;
71 }
72 
LoadAllIpCached(const std::string & fileName)73 int32_t DhcpResultStoreManager::LoadAllIpCached(const std::string &fileName)
74 {
75     std::unique_lock<std::mutex> lock(m_ipResultMutex);
76     SetConfigFilePath(fileName);
77     if (m_fileName.empty()) {
78         DHCP_LOGE("File name is empty.");
79         return -1;
80     }
81     std::ifstream fs(m_fileName.c_str());
82     if (!fs.is_open()) {
83         DHCP_LOGE("Loading config file: %{public}s, fs.is_open() failed!", m_fileName.c_str());
84         return -1;
85     }
86     m_allIpCached.clear();
87     IpInfoCached item;
88     std::string line;
89     int32_t configError;
90     while (std::getline(fs, line)) {
91         TrimString(line);
92         if (line.empty()) {
93             continue;
94         }
95         if (line[0] == '[' && ((line.length() > 0) && (line[line.length() - 1] == '{'))) {
96             ClearClass(item); /* template function, needing specialization */
97             configError = ReadNetwork(item, fs, line);
98             if (configError > 0) {
99                 DHCP_LOGE("Parse network failed.");
100                 continue;
101             }
102             m_allIpCached.push_back(item);
103         }
104     }
105     fs.close();
106     return 0;
107 }
108 
ReadNetworkSection(IpInfoCached & item,std::ifstream & fs,std::string & line)109 int32_t DhcpResultStoreManager::ReadNetworkSection(IpInfoCached &item, std::ifstream &fs, std::string &line)
110 {
111     int32_t sectionError = 0;
112     while (std::getline(fs, line)) {
113         TrimString(line);
114         if (line.empty()) {
115             continue;
116         }
117         if (line[0] == '<' && ((line.length() > 0) && (line[line.length() - 1] == '>'))) {
118             return sectionError;
119         }
120         std::string::size_type npos = line.find("=");
121         if (npos == std::string::npos) {
122             DHCP_LOGE("Invalid config line");
123             sectionError++;
124             continue;
125         }
126         std::string key = line.substr(0, npos);
127         std::string value = line.substr(npos + 1);
128         TrimString(key);
129         TrimString(value);
130         /* template function, needing specialization */
131         sectionError += SetClassKeyValue(item, key, value);
132     }
133     DHCP_LOGE("Section config not end correctly");
134     sectionError++;
135     return sectionError;
136 }
137 
ReadNetwork(IpInfoCached & item,std::ifstream & fs,std::string & line)138 int32_t DhcpResultStoreManager::ReadNetwork(IpInfoCached &item, std::ifstream &fs, std::string &line)
139 {
140     int32_t networkError = 0;
141     while (std::getline(fs, line)) {
142         TrimString(line);
143         if (line.empty()) {
144             continue;
145         }
146         if (line[0] == '<' && ((line.length() > 0) && (line[line.length() - 1] == '>'))) {
147             networkError += ReadNetworkSection(item, fs, line);
148         } else if (line.compare("}") == 0) {
149             return networkError;
150         } else {
151             DHCP_LOGE("Invalid config line");
152             networkError++;
153         }
154     }
155     DHCP_LOGE("Network config not end correctly");
156     networkError++;
157     return networkError;
158 }
159 
SaveConfig()160 int32_t DhcpResultStoreManager::SaveConfig()
161 {
162     if (m_fileName.empty()) {
163         DHCP_LOGE("File name is empty.");
164         return -1;
165     }
166     FILE* fp = fopen(m_fileName.c_str(), "w");
167     if (!fp) {
168         DHCP_LOGE("Save config file: %{public}s, fopen() failed!", m_fileName.c_str());
169         return -1;
170     }
171     std::ostringstream ss;
172     for (std::size_t i = 0; i < m_allIpCached.size(); ++i) {
173         IpInfoCached &item = m_allIpCached[i];
174         ss << "[" << GetClassName() << "_" << (i + 1) << "] {" << std::endl;
175         ss << OutClassString(item) << std::endl;
176         ss << "}" << std::endl;
177     }
178     std::string content = ss.str();
179     uint32_t ret = fwrite(content.c_str(), 1, content.length(), fp);
180     if (ret != static_cast<uint32_t>(content.length())) {
181         DHCP_LOGE("Save config file: %{public}s, fwrite() failed!", m_fileName.c_str());
182     }
183     (void)fflush(fp);
184     (void)fsync(fileno(fp));
185     (void)fclose(fp);
186     m_allIpCached.clear(); /* clear values */
187     return 0;
188 }
189 
SetClassKeyValue(IpInfoCached & item,const std::string & key,const std::string & value)190 int32_t DhcpResultStoreManager::SetClassKeyValue(IpInfoCached &item, const std::string &key, const std::string &value)
191 {
192     int32_t errorKeyValue = 0;
193     std::string valueTmp = value;
194     if (key == "bssid") {
195         item.bssid = value;
196     } else if (key == "absoluteLeasetime") {
197         item.absoluteLeasetime = static_cast<int64_t>(CheckDataLegal(valueTmp));
198     } else if (key == "strYiaddr") {
199         if (strncpy_s(
200             item.ipResult.strYiaddr, sizeof(item.ipResult.strYiaddr), value.c_str(), value.size()) != EOK) {
201             errorKeyValue++;
202         }
203     } else if (key == "strOptServerId") {
204         if (strncpy_s(
205             item.ipResult.strOptServerId, sizeof(item.ipResult.strOptServerId), value.c_str(), value.size()) != EOK) {
206             errorKeyValue++;
207         }
208     } else if (key == "strOptSubnet") {
209         if (strncpy_s(
210             item.ipResult.strOptSubnet, sizeof(item.ipResult.strOptSubnet), value.c_str(), value.size()) != EOK) {
211             errorKeyValue++;
212         }
213     } else if (key == "strOptDns1") {
214         if (strncpy_s(
215             item.ipResult.strOptDns1, sizeof(item.ipResult.strOptDns1), value.c_str(), value.size()) != EOK) {
216             errorKeyValue++;
217         }
218     } else if (key == "strOptDns2") {
219         if (strncpy_s(
220             item.ipResult.strOptDns2, sizeof(item.ipResult.strOptDns2), value.c_str(), value.size()) != EOK) {
221             errorKeyValue++;
222         }
223     } else if (key == "strOptRouter1") {
224         if (strncpy_s(
225             item.ipResult.strOptRouter1, sizeof(item.ipResult.strOptRouter1), value.c_str(), value.size()) != EOK) {
226             errorKeyValue++;
227         }
228     } else if (key == "strOptRouter2") {
229         if (strncpy_s(
230             item.ipResult.strOptRouter2, sizeof(item.ipResult.strOptRouter2), value.c_str(), value.size()) != EOK) {
231             errorKeyValue++;
232         }
233     } else if (key == "uOptLeasetime") {
234         item.ipResult.uOptLeasetime = static_cast<uint32_t>(CheckDataLegal(valueTmp));
235     } else {
236         DHCP_LOGE("Invalid config key value");
237         errorKeyValue++;
238     }
239     return errorKeyValue;
240 }
241 
GetClassName()242 std::string DhcpResultStoreManager::GetClassName()
243 {
244     return "IpInfoCached";
245 }
246 
OutClassString(IpInfoCached & item)247 std::string DhcpResultStoreManager::OutClassString(IpInfoCached &item)
248 {
249     std::ostringstream ss;
250     ss << "    " <<"<IpInfoCached>" << std::endl;
251     ss << "    " <<"bssid=" << item.bssid << std::endl;
252     ss << "    " <<"absoluteLeasetime=" << item.absoluteLeasetime << std::endl;
253     ss << "    " <<"strYiaddr=" << item.ipResult.strYiaddr << std::endl;
254     ss << "    " <<"strOptServerId=" << item.ipResult.strOptServerId << std::endl;
255     ss << "    " <<"strOptSubnet=" << item.ipResult.strOptSubnet << std::endl;
256     ss << "    " <<"strOptDns1=" << item.ipResult.strOptDns1 << std::endl;
257     ss << "    " <<"strOptDns2=" << item.ipResult.strOptDns2 << std::endl;
258     ss << "    " <<"strOptRouter1=" << item.ipResult.strOptRouter1 << std::endl;
259     ss << "    " <<"strOptRouter2=" << item.ipResult.strOptRouter2 << std::endl;
260     ss << "    " <<"uOptLeasetime=" << item.ipResult.uOptLeasetime << std::endl;
261     ss << "    " <<"<IpInfoCached>" << std::endl;
262     return ss.str();
263 }
264 
ClearClass(IpInfoCached & item)265 void DhcpResultStoreManager::ClearClass(IpInfoCached &item)
266 {
267     item.bssid.clear();
268     item.absoluteLeasetime = 0;
269     item.ipResult.uOptLeasetime = 0;
270 }
271 }  // namespace Wifi
272 }  // namespace OHOS