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