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