1 /*
2 * Copyright (c) 2022-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 "iptables_wrapper.h"
17
18 #include <unistd.h>
19
20 #include "datetime_ex.h"
21 #include "net_manager_constants.h"
22 #include "netmanager_base_common_utils.h"
23 #include "netnative_log_wrapper.h"
24
25 #ifdef UNITTEST_FORBID_FFRT
26 #undef UNITTEST_FORBID_FFRT
27 #endif
28 #define UNITTEST_FORBID_FFRT 1
29
30 namespace OHOS {
31 namespace nmd {
32 using namespace NetManagerStandard;
33 namespace {
34 constexpr const char *IPATBLES_CMD_PATH = "/system/bin/iptables";
35 constexpr const char *IP6TABLES_CMD_PATH = "/system/bin/ip6tables";
36 } // namespace
37
IptablesWrapper()38 IptablesWrapper::IptablesWrapper()
39 {
40 isRunningFlag_ = true;
41 isIptablesSystemAccess_ = access(IPATBLES_CMD_PATH, F_OK) == 0;
42 isIp6tablesSystemAccess_ = access(IP6TABLES_CMD_PATH, F_OK) == 0;
43
44 iptablesWrapperFfrtQueue_ = std::make_shared<ffrt::queue>("IptablesWrapper");
45 }
46
~IptablesWrapper()47 IptablesWrapper::~IptablesWrapper()
48 {
49 isRunningFlag_ = false;
50 iptablesWrapperFfrtQueue_.reset();
51 }
52
ExecuteCommand(const std::string & command)53 void IptablesWrapper::ExecuteCommand(const std::string &command)
54 {
55 std::string cmdWithWait = command + " -w 5 ";
56 NETNATIVE_LOGI("ExecuteCommand %{public}s", CommonUtils::AnonymousIpInStr(cmdWithWait).c_str());
57 if (CommonUtils::ForkExec(cmdWithWait) == NETMANAGER_ERROR) {
58 NETNATIVE_LOGE("run exec faild");
59 }
60 }
61
ExecuteCommandForRes(const std::string & command)62 void IptablesWrapper::ExecuteCommandForRes(const std::string &command)
63 {
64 std::string cmdWithWait = command + " -w 5 ";
65 NETNATIVE_LOGI("ExecuteCommandForRes %{public}s", CommonUtils::AnonymousIpInStr(cmdWithWait).c_str());
66 if (CommonUtils::ForkExec(cmdWithWait, &result_) == NETMANAGER_ERROR) {
67 NETNATIVE_LOGE("run exec faild");
68 }
69 }
70
RunCommand(const IpType & ipType,const std::string & command)71 int32_t IptablesWrapper::RunCommand(const IpType &ipType, const std::string &command)
72 {
73 NETNATIVE_LOG_D("IptablesWrapper::RunCommand, ipType:%{public}d", ipType);
74 if (!iptablesWrapperFfrtQueue_) {
75 NETNATIVE_LOGE("FFRT Init Fail");
76 return NETMANAGER_ERROR;
77 }
78
79 if (isIptablesSystemAccess_ && (ipType == IPTYPE_IPV4 || ipType == IPTYPE_IPV4V6)) {
80 std::string cmd = std::string(IPATBLES_CMD_PATH) + " " + command;
81 #if UNITTEST_FORBID_FFRT // Forbid FFRT for unittest, which will cause crash in destructor process
82 ExecuteCommand(cmd);
83 #else
84 std::function<void()> executeCommand = std::bind(&IptablesWrapper::ExecuteCommand, shared_from_this(), cmd);
85 iptablesWrapperFfrtQueue_->submit(executeCommand);
86 #endif // UNITTEST_FORBID_FFRT
87 }
88
89 if (isIp6tablesSystemAccess_ && (ipType == IPTYPE_IPV6 || ipType == IPTYPE_IPV4V6)) {
90 std::string cmd = std::string(IP6TABLES_CMD_PATH) + " " + command;
91 #if UNITTEST_FORBID_FFRT // Forbid FFRT for unittest, which will cause crash in destructor process
92 ExecuteCommand(cmd);
93 #else
94 std::function<void()> executeCommand = std::bind(&IptablesWrapper::ExecuteCommand, shared_from_this(), cmd);
95 iptablesWrapperFfrtQueue_->submit(executeCommand);
96 #endif // UNITTEST_FORBID_FFRT
97 }
98
99 return NetManagerStandard::NETMANAGER_SUCCESS;
100 }
101
RunCommandForRes(const IpType & ipType,const std::string & command)102 std::string IptablesWrapper::RunCommandForRes(const IpType &ipType, const std::string &command)
103 {
104 NETNATIVE_LOGI("IptablesWrapper::RunCommandForRes, ipType:%{public}d", ipType);
105 if (!iptablesWrapperFfrtQueue_) {
106 NETNATIVE_LOGE("FFRT Init Fail");
107 return result_;
108 }
109
110 if (ipType == IPTYPE_IPV4 || ipType == IPTYPE_IPV4V6) {
111 std::string cmd = std::string(IPATBLES_CMD_PATH) + " " + command;
112 std::function<void()> executeCommandForRes =
113 std::bind(&IptablesWrapper::ExecuteCommandForRes, shared_from_this(), cmd);
114
115 int64_t start = GetTickCount();
116 #if UNITTEST_FORBID_FFRT // Forbid FFRT for unittest, which will cause crash in destructor process
117 executeCommandForRes();
118 #else
119 ffrt::task_handle RunCommandForResTaskIpv4 = iptablesWrapperFfrtQueue_->submit_h(executeCommandForRes);
120 iptablesWrapperFfrtQueue_->wait(RunCommandForResTaskIpv4);
121 #endif // UNITTEST_FORBID_FFRT
122 NETNATIVE_LOGI("FFRT cost:%{public}lld ms", static_cast<long long>(GetTickCount() - start));
123 }
124
125 if (ipType == IPTYPE_IPV6 || ipType == IPTYPE_IPV4V6) {
126 std::string cmd = std::string(IP6TABLES_CMD_PATH) + " " + command;
127 std::function<void()> executeCommandForRes =
128 std::bind(&IptablesWrapper::ExecuteCommandForRes, shared_from_this(), cmd);
129
130 int64_t start = GetTickCount();
131 #if UNITTEST_FORBID_FFRT // Forbid FFRT for unittest, which will cause crash in destructor process
132 executeCommandForRes();
133 #else
134 ffrt::task_handle RunCommandForResTaskIpv6 = iptablesWrapperFfrtQueue_->submit_h(executeCommandForRes);
135 iptablesWrapperFfrtQueue_->wait(RunCommandForResTaskIpv6);
136 #endif // UNITTEST_FORBID_FFRT
137 NETNATIVE_LOGI("FFRT cost:%{public}lld ms", static_cast<long long>(GetTickCount() - start));
138 }
139
140 return result_;
141 }
142
RunMutipleCommands(const IpType & ipType,const std::vector<std::string> & commands)143 int32_t IptablesWrapper::RunMutipleCommands(const IpType &ipType, const std::vector<std::string> &commands)
144 {
145 NETNATIVE_LOG_D("IptablesWrapper::RunMutipleCommands, ipType:%{public}d", ipType);
146 if (!iptablesWrapperFfrtQueue_) {
147 NETNATIVE_LOGE("FFRT Init Fail");
148 return NETMANAGER_ERROR;
149 }
150
151 for (const std::string& command : commands) {
152 if (isIptablesSystemAccess_ && (ipType == IPTYPE_IPV4 || ipType == IPTYPE_IPV4V6)) {
153 std::string cmd = std::string(IPATBLES_CMD_PATH) + " " + command;
154 std::function<void()> executeCommand = std::bind(&IptablesWrapper::ExecuteCommand, shared_from_this(), cmd);
155 #if UNITTEST_FORBID_FFRT // Forbid FFRT for unittest, which will cause crash in destructor process
156 executeCommand();
157 #else
158 iptablesWrapperFfrtQueue_->submit(executeCommand);
159 #endif
160 }
161
162 if (isIp6tablesSystemAccess_ && (ipType == IPTYPE_IPV6 || ipType == IPTYPE_IPV4V6)) {
163 std::string cmd = std::string(IP6TABLES_CMD_PATH) + " " + command;
164 std::function<void()> executeCommand = std::bind(&IptablesWrapper::ExecuteCommand, shared_from_this(), cmd);
165 #if UNITTEST_FORBID_FFRT // Forbid FFRT for unittest, which will cause crash in destructor process
166 executeCommand();
167 #else
168 iptablesWrapperFfrtQueue_->submit(executeCommand);
169 #endif
170 }
171 }
172
173 return NetManagerStandard::NETMANAGER_SUCCESS;
174 }
175
176 } // namespace nmd
177 } // namespace OHOS
178