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