• 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 #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