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