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 #include <cstdio>
16 #include <cstring>
17 #include <iostream>
18 #include <sstream>
19 #include <string>
20 #include "errorcode_convertor.h"
21 #include "iptables_wrapper.h"
22 #include "netmanager_base_common_utils.h"
23 #include "netnative_log_wrapper.h"
24 #include "net_manager_constants.h"
25 #include "wearable_distributed_net_manager.h"
26
27 namespace OHOS {
28 namespace nmd {
29 using namespace NetManagerStandard;
30 const int32_t MAX_CMD_LENGTH = 256;
31 const int32_t MAX_PORT_ID = 65535;
32
33 const std::string TCP_IPTABLES = "tcpiptables";
34 const std::string TCP_OUTPUT = "tcpoutput";
35 const std::string UDP_IPTABLES = "udpiptables";
36 const std::string UDP_OUTPUT = "udpoutput";
37 const std::string IPTABLES_DELETE_CMDS = "iptablesdeletecmds";
38
GetTcpIptables()39 std::vector<std::string> WearableDistributedNet::GetTcpIptables()
40 {
41 return tcpIptables_;
42 }
43
GetOutputAddTcp()44 std::string WearableDistributedNet::GetOutputAddTcp()
45 {
46 return tcpOutput_;
47 }
48
GetUdpIptables()49 std::vector<std::string> WearableDistributedNet::GetUdpIptables()
50 {
51 return udpIptables_;
52 }
53
GetUdpoutput()54 std::string WearableDistributedNet::GetUdpoutput()
55 {
56 return udpOutput_;
57 }
58
GetIptablesDeleteCmds()59 std::vector<std::string> WearableDistributedNet::GetIptablesDeleteCmds()
60 {
61 return iptablesDeleteCmds_;
62 }
63
ReadSystemIptablesConfiguration()64 bool WearableDistributedNet::ReadSystemIptablesConfiguration()
65 {
66 std::unique_lock<std::mutex> lock(iptablesParseMutex_);
67 if (iptablesHasBeenParse_) {
68 NETNATIVE_LOGI("iptables has been parsed");
69 return true;
70 }
71 const auto &jsonStr = ReadJsonFile();
72 if (jsonStr.length() == 0) {
73 NETNATIVE_LOGE("ReadConfigData config file is return empty");
74 return false;
75 }
76 cJSON *json = cJSON_Parse(jsonStr.c_str());
77 if (json == nullptr) {
78 NETNATIVE_LOGE("Json parse failed");
79 return false;
80 }
81 bool result = ReadIptablesInterfaces(*json);
82 if (result == false) {
83 NETNATIVE_LOGE("Failed to read iptables interfaces");
84 cJSON_Delete(json);
85 return false;
86 }
87 cJSON_Delete(json);
88 iptablesHasBeenParse_ = true;
89 return true;
90 }
91
ReadJsonFile()92 std::string WearableDistributedNet::ReadJsonFile()
93 {
94 std::ifstream infile;
95 std::string lineConfigInfo;
96 std::string allConfigInfo;
97 if (configPath_.empty()) {
98 NETNATIVE_LOGE("Config file path is empty");
99 return "";
100 }
101 infile.open(configPath_, std::ios::in);
102 if (!infile.is_open()) {
103 NETNATIVE_LOGE("ReadJsonFile filePath failed");
104 return allConfigInfo;
105 }
106 while (getline(infile, lineConfigInfo)) {
107 allConfigInfo.append(lineConfigInfo);
108 }
109 infile.close();
110 return allConfigInfo;
111 }
112
ParseTcpIptables(const cJSON & json)113 bool WearableDistributedNet::ParseTcpIptables(const cJSON &json)
114 {
115 cJSON *tcpIptablesObj = cJSON_GetObjectItemCaseSensitive(&json, TCP_IPTABLES.c_str());
116 for (int32_t i = 0; i < cJSON_GetArraySize(tcpIptablesObj); i++) {
117 cJSON *tcpIptablesItem = cJSON_GetArrayItem(tcpIptablesObj, i);
118 if (tcpIptablesItem == nullptr || tcpIptablesItem->valuestring == nullptr) {
119 NETNATIVE_LOGE("Invalid item in TCP iptables array");
120 return false;
121 }
122 const auto tcpIptablesValue = tcpIptablesItem->valuestring;
123 tcpIptables_.push_back(std::string(tcpIptablesValue));
124 }
125 return true;
126 }
127
ParseTcpOutputRule(const cJSON & json)128 bool WearableDistributedNet::ParseTcpOutputRule(const cJSON &json)
129 {
130 cJSON *tcpOutputJsonItem = cJSON_GetObjectItemCaseSensitive(&json, TCP_OUTPUT.c_str());
131 if (tcpOutputJsonItem == nullptr) {
132 NETNATIVE_LOGE("Failed to find tcpOutputJsonItem information");
133 return false;
134 }
135 tcpOutput_ = cJSON_GetStringValue(tcpOutputJsonItem);
136 return true;
137 }
138
ParseUdpIptables(const cJSON & json)139 bool WearableDistributedNet::ParseUdpIptables(const cJSON &json)
140 {
141 cJSON *udpIptablesObj = cJSON_GetObjectItemCaseSensitive(&json, UDP_IPTABLES.c_str());
142 for (int32_t i = 0; i < cJSON_GetArraySize(udpIptablesObj); i++) {
143 cJSON *udpIptablesItem = cJSON_GetArrayItem(udpIptablesObj, i);
144 if (udpIptablesItem == nullptr || udpIptablesItem->valuestring == nullptr) {
145 NETNATIVE_LOGE("Invalid item in UDP iptables array");
146 return false;
147 }
148 const auto udpIptablesValue = udpIptablesItem->valuestring;
149 udpIptables_.push_back(std::string(udpIptablesValue));
150 }
151 return true;
152 }
153
ParseUdpOutputRule(const cJSON & json)154 bool WearableDistributedNet::ParseUdpOutputRule(const cJSON &json)
155 {
156 cJSON *udpOutputItem = cJSON_GetObjectItemCaseSensitive(&json, UDP_OUTPUT.c_str());
157 if (udpOutputItem == nullptr) {
158 NETNATIVE_LOGE("Failed to find udpOutputItem information");
159 return false;
160 }
161 udpOutput_ = cJSON_GetStringValue(udpOutputItem);
162 return true;
163 }
164
ParseIptablesDeleteCmds(const cJSON & json)165 bool WearableDistributedNet::ParseIptablesDeleteCmds(const cJSON &json)
166 {
167 cJSON *iptablesDeleteCmdsObj = cJSON_GetObjectItemCaseSensitive(&json, IPTABLES_DELETE_CMDS.c_str());
168 for (int32_t i = 0; i < cJSON_GetArraySize(iptablesDeleteCmdsObj); i++) {
169 cJSON *iptablesDeleteCmdsItem = cJSON_GetArrayItem(iptablesDeleteCmdsObj, i);
170 if (iptablesDeleteCmdsItem == nullptr || iptablesDeleteCmdsItem->valuestring == nullptr) {
171 NETNATIVE_LOGE("Invalid item in iptables delete commands array");
172 return false;
173 }
174 const auto iptablesDeleteCmdsValue = iptablesDeleteCmdsItem->valuestring;
175 iptablesDeleteCmds_.push_back(std::string(iptablesDeleteCmdsValue));
176 }
177 return true;
178 }
179
ReadIptablesInterfaces(const cJSON & json)180 bool WearableDistributedNet::ReadIptablesInterfaces(const cJSON &json)
181 {
182 if (!ParseTcpIptables(json)) {
183 NETNATIVE_LOGE("ParseTcpIptables failed");
184 return false;
185 }
186 if (!ParseTcpOutputRule(json)) {
187 NETNATIVE_LOGE("ParseTcpOutputRule failed");
188 return false;
189 }
190 if (!ParseUdpIptables(json)) {
191 NETNATIVE_LOGE("ParseUdpIptables failed");
192 return false;
193 }
194 if (!ParseUdpOutputRule(json)) {
195 NETNATIVE_LOGE("ParseUdpOutputRule failed");
196 return false;
197 }
198 if (!ParseIptablesDeleteCmds(json)) {
199 NETNATIVE_LOGE("ParseIptablesDeleteCmds failed");
200 return false;
201 }
202 return true;
203 }
204
SetTcpPort(const int32_t tcpPortId)205 void WearableDistributedNet::SetTcpPort(const int32_t tcpPortId)
206 {
207 tcpPort_ = tcpPortId;
208 }
209
GetTcpPort()210 int32_t WearableDistributedNet::GetTcpPort()
211 {
212 return tcpPort_;
213 }
214
RunCommandResult(const std::string & cmd)215 int32_t RunCommandResult(const std::string &cmd)
216 {
217 std::string response =
218 IptablesWrapper::GetInstance()->RunCommandForRes(OHOS::nmd::IpType::IPTYPE_IPV4, cmd);
219 return response.empty() ? NETMANAGER_SUCCESS : NETMANAGER_ERROR;
220 }
221
ExecuteIptablesCommands(const std::vector<std::string> & commands)222 int32_t WearableDistributedNet::ExecuteIptablesCommands(const std::vector<std::string> &commands)
223 {
224 for (const auto &command : commands) {
225 if (command.length() > MAX_CMD_LENGTH) {
226 NETNATIVE_LOGE("Invalid command found at index");
227 return NETMANAGER_ERROR;
228 }
229 if (RunCommandResult(command) != NETMANAGER_SUCCESS) {
230 return NETMANAGER_ERROR;
231 }
232 }
233 return NETMANAGER_SUCCESS;
234 }
235
EnableWearableDistributedNetForward(const int32_t tcpPortId,const int32_t udpPortId)236 int32_t WearableDistributedNet::EnableWearableDistributedNetForward(const int32_t tcpPortId, const int32_t udpPortId)
237 {
238 if (!ReadSystemIptablesConfiguration()) {
239 NETNATIVE_LOGE("Failed to read system iptables configuration");
240 return NETMANAGER_ERR_READ_DATA_FAIL;
241 }
242 if (tcpPortId <= 0 || tcpPortId > MAX_PORT_ID) {
243 NETNATIVE_LOGE("Invalid TCP port ID");
244 return NETMANAGER_WEARABLE_DISTRIBUTED_NET_ERR_INVALID_TCP_PORT_ID;
245 }
246 if (udpPortId <= 0 || udpPortId > MAX_PORT_ID) {
247 NETNATIVE_LOGE("Invalid UDP port ID");
248 return NETMANAGER_WEARABLE_DISTRIBUTED_NET_ERR_INVALID_UDP_PORT_ID;
249 }
250 SetTcpPort(tcpPortId);
251 int32_t ret = EstablishTcpIpRules();
252 if (ret != NETMANAGER_SUCCESS) {
253 NETNATIVE_LOGE("Failed to establish TCP IP rules for network distribution");
254 return ret;
255 }
256 ret = EstablishUdpIpRules(udpPortId);
257 if (ret != NETMANAGER_SUCCESS) {
258 NETNATIVE_LOGE("Failed to establish UDP IP rules for network distribution");
259 return ret;
260 }
261
262 return NETMANAGER_SUCCESS;
263 }
264
GenerateRule(const std::string & inputRules,const int32_t portId)265 std::string WearableDistributedNet::GenerateRule(const std::string &inputRules, const int32_t portId)
266 {
267 if (inputRules.empty()) {
268 NETNATIVE_LOGE("Input rules are null");
269 return "";
270 }
271 if (inputRules.length() > MAX_CMD_LENGTH) {
272 NETNATIVE_LOGE("Input rules are invalid");
273 return "";
274 }
275 char res[MAX_CMD_LENGTH] = {0};
276 if (sprintf_s(res, MAX_CMD_LENGTH, inputRules.c_str(), portId) == -1) {
277 return "";
278 }
279 return std::string(res);
280 }
281
ApplyRule(const RULES_TYPE type,const int32_t portId)282 int32_t WearableDistributedNet::ApplyRule(const RULES_TYPE type, const int32_t portId)
283 {
284 if (portId <= 0 || portId > MAX_PORT_ID) {
285 return NETMANAGER_WEARABLE_DISTRIBUTED_NET_ERR_INVALID_PORT_ID;
286 }
287 std::string resultRules;
288 switch (type) {
289 case TCP_ADD_RULE:
290 resultRules = GenerateRule(TCP_ADD16, portId);
291 break;
292 case UDP_ADD_RULE:
293 resultRules = GenerateRule(UDP_ADD16, portId);
294 break;
295 case INPUT_ADD_RULE:
296 resultRules = GenerateRule(INPUT_ADD, portId);
297 break;
298 case INPUT_DEL_RULE:
299 resultRules = GenerateRule(INPUT_DEL, portId);
300 break;
301 default:
302 NETNATIVE_LOGE("Invalid rule type");
303 break;
304 }
305 if (resultRules.empty()) {
306 NETNATIVE_LOGE("Failed to generate rule");
307 return NETMANAGER_ERR_INVALID_PARAMETER;
308 }
309 return RunCommandResult(resultRules);
310 }
311
EstablishTcpIpRules()312 int32_t WearableDistributedNet::EstablishTcpIpRules()
313 {
314 NETNATIVE_LOGI("Establishing TCP IP rules for network distribution");
315 if (ExecuteIptablesCommands(GetTcpIptables()) != NETMANAGER_SUCCESS) {
316 NETNATIVE_LOGE("Failed to execute TCP iptables commands");
317 return NETMANAGER_ERROR;
318 }
319 if (ApplyRule(TCP_ADD_RULE, GetTcpPort()) != NETMANAGER_SUCCESS) {
320 NETNATIVE_LOGE("Failed to apply TCP add rule");
321 return NETMANAGER_ERROR;
322 }
323 return RunCommandResult(GetOutputAddTcp());
324 }
325
EstablishUdpIpRules(const int32_t udpPortId)326 int32_t WearableDistributedNet::EstablishUdpIpRules(const int32_t udpPortId)
327 {
328 NETNATIVE_LOGI("Establishing UDP IP rules for network distribution");
329 if (ExecuteIptablesCommands(GetUdpIptables()) != NETMANAGER_SUCCESS) {
330 NETNATIVE_LOGE("Failed to execute UDP iptables commands");
331 return NETMANAGER_ERROR;
332 }
333 if (ApplyRule(UDP_ADD_RULE, udpPortId) != NETMANAGER_SUCCESS) {
334 NETNATIVE_LOGE("Failed to apply UDP add rule");
335 return NETMANAGER_ERROR;
336 }
337 return RunCommandResult(GetUdpoutput());
338 }
339
DisableWearableDistributedNetForward()340 int32_t WearableDistributedNet::DisableWearableDistributedNetForward()
341 {
342 NETNATIVE_LOGI("Disabling wearable distributed net forward");
343 if (ExecuteIptablesCommands(GetIptablesDeleteCmds()) != NETMANAGER_SUCCESS) {
344 NETNATIVE_LOGE("Failed to execute iptables delete commands");
345 return NETMANAGER_ERROR;
346 }
347 if (ApplyRule(INPUT_DEL_RULE, GetTcpPort()) != NETMANAGER_SUCCESS) {
348 NETNATIVE_LOGE("Failed to apply input delete rule");
349 return NETMANAGER_ERROR;
350 }
351 return NETMANAGER_SUCCESS;
352 }
353 } // namespace nmd
354 } // namespace OHOS